isaacscript-common 20.13.1 → 20.14.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 (32) hide show
  1. package/dist/index.d.ts +32 -4
  2. package/dist/isaacscript-common.lua +182 -113
  3. package/dist/lualib_bundle.lua +6 -30
  4. package/dist/src/classes/features/other/CustomStages.d.ts.map +1 -1
  5. package/dist/src/classes/features/other/CustomStages.lua +7 -0
  6. package/dist/src/classes/features/other/customStages/gridEntities.lua +22 -55
  7. package/dist/src/classes/features/other/customStages/versusScreen.lua +4 -10
  8. package/dist/src/classes/features/other/extraConsoleCommands/commands.d.ts +2 -0
  9. package/dist/src/classes/features/other/extraConsoleCommands/commands.d.ts.map +1 -1
  10. package/dist/src/classes/features/other/extraConsoleCommands/commands.lua +6 -0
  11. package/dist/src/functions/logMisc.d.ts +1 -0
  12. package/dist/src/functions/logMisc.d.ts.map +1 -1
  13. package/dist/src/functions/logMisc.lua +6 -0
  14. package/dist/src/functions/sound.d.ts +18 -1
  15. package/dist/src/functions/sound.d.ts.map +1 -1
  16. package/dist/src/functions/sound.lua +31 -1
  17. package/dist/src/functions/ui.d.ts +4 -3
  18. package/dist/src/functions/ui.d.ts.map +1 -1
  19. package/dist/src/functions/ui.lua +4 -3
  20. package/dist/src/interfaces/CustomStageTSConfig.d.ts +7 -0
  21. package/dist/src/interfaces/CustomStageTSConfig.d.ts.map +1 -1
  22. package/dist/src/objects/stageToMusic.d.ts +108 -0
  23. package/dist/src/objects/stageToMusic.d.ts.map +1 -0
  24. package/dist/src/objects/stageToMusic.lua +93 -0
  25. package/package.json +1 -1
  26. package/src/classes/features/other/CustomStages.ts +19 -7
  27. package/src/classes/features/other/extraConsoleCommands/commands.ts +7 -0
  28. package/src/functions/logMisc.ts +9 -1
  29. package/src/functions/sound.ts +48 -3
  30. package/src/functions/ui.ts +4 -3
  31. package/src/interfaces/CustomStageTSConfig.ts +8 -0
  32. package/src/objects/stageToMusic.ts +99 -0
@@ -9,7 +9,7 @@ import {
9
9
  RoomType,
10
10
  StageType,
11
11
  } from "isaac-typescript-definitions";
12
- import { game } from "../../../core/cachedClasses";
12
+ import { game, musicManager } from "../../../core/cachedClasses";
13
13
  import * as metadataJSON from "../../../customStageMetadata.json"; // This will correspond to "customStageMetadata.lua" at run-time.
14
14
  import { Exported } from "../../../decorators";
15
15
  import { ISCFeature } from "../../../enums/ISCFeature";
@@ -28,6 +28,7 @@ import {
28
28
  getRoomDataForTypeVariant,
29
29
  getRoomsInsideGrid,
30
30
  } from "../../../functions/rooms";
31
+ import { getMusicForStage } from "../../../functions/sound";
31
32
  import { setStage } from "../../../functions/stage";
32
33
  import { asNumber } from "../../../functions/types";
33
34
  import {
@@ -457,22 +458,23 @@ export class CustomStages extends Feature {
457
458
  level.SetStage(LevelStage.BASEMENT_1, StageType.ORIGINAL);
458
459
  }
459
460
 
460
- let baseStage =
461
+ let baseStage: LevelStage =
461
462
  customStage.baseStage === undefined
462
463
  ? DEFAULT_BASE_STAGE
463
- : customStage.baseStage;
464
+ : (customStage.baseStage as LevelStage);
464
465
  if (!firstFloor) {
465
- baseStage++;
466
+ baseStage++; // eslint-disable-line isaacscript/strict-enums
466
467
  }
467
468
 
468
- const baseStageType =
469
+ const baseStageType: StageType =
469
470
  customStage.baseStageType === undefined
470
471
  ? DEFAULT_BASE_STAGE_TYPE
471
- : customStage.baseStageType;
472
+ : (customStage.baseStageType as StageType);
472
473
 
474
+ // eslint-disable-next-line isaacscript/strict-enums
473
475
  const reseed = asNumber(stage) >= baseStage;
474
476
 
475
- setStage(baseStage as LevelStage, baseStageType as StageType, reseed);
477
+ setStage(baseStage, baseStageType, reseed);
476
478
 
477
479
  this.setStageRoomsData(customStage, rng, verbose);
478
480
 
@@ -495,6 +497,16 @@ export class CustomStages extends Feature {
495
497
  });
496
498
  }
497
499
 
500
+ // The bugged stage will not have any music associated with it, so we must manually start to
501
+ // play a track.
502
+ const music =
503
+ customStage.music === undefined
504
+ ? getMusicForStage(baseStage, baseStageType)
505
+ : Isaac.GetMusicIdByName(customStage.music);
506
+ this.runInNFrames.runNextGameFrame(() => {
507
+ musicManager.Play(music);
508
+ });
509
+
498
510
  // We must reload the current room in order for the `Level.SetStage` method to take effect.
499
511
  // Furthermore, we need to cancel the queued warp to the `GridRoom.DEBUG` room. We can
500
512
  // accomplish both of these things by initiating a room transition to an arbitrary room.
@@ -79,6 +79,7 @@ import { addFlag } from "../../../../functions/flag";
79
79
  import { spawnGridEntity } from "../../../../functions/gridEntities";
80
80
  import { getRoomGridIndexesForType } from "../../../../functions/levelGrid";
81
81
  import {
82
+ logMusic,
82
83
  logPlayerEffects,
83
84
  logRoom,
84
85
  logSeedEffects,
@@ -961,6 +962,12 @@ export function miniboss(): void {
961
962
  warpToRoomType(RoomType.MINI_BOSS);
962
963
  }
963
964
 
965
+ /** Logs the currently playing music track to the "log.txt" file. */
966
+ export function music(): void {
967
+ logMusic();
968
+ print('Logged the currently playing music track to the "log.txt" file.');
969
+ }
970
+
964
971
  /** Alias for the "disableCurses" command. */
965
972
  export function noCurses(): void {
966
973
  disableCurses();
@@ -6,13 +6,14 @@ import {
6
6
  GridRoom,
7
7
  HeartSubType,
8
8
  LevelStateFlag,
9
+ Music,
9
10
  ProjectileFlag,
10
11
  SeedEffect,
11
12
  SoundEffect,
12
13
  TearFlag,
13
14
  UseFlag,
14
15
  } from "isaac-typescript-definitions";
15
- import { game, sfxManager } from "../core/cachedClasses";
16
+ import { game, musicManager, sfxManager } from "../core/cachedClasses";
16
17
  import { arrayToString, isArray } from "./array";
17
18
  import { getCollectibleName } from "./collectibles";
18
19
  import { getEntityID } from "./entities";
@@ -194,6 +195,13 @@ export function logMap(this: void, map: Map<AnyNotNil, unknown>): void {
194
195
  log(` The size of the map was: ${map.size}`);
195
196
  }
196
197
 
198
+ export function logMusic(this: void): void {
199
+ const currentMusic = musicManager.GetCurrentMusicID();
200
+ log(
201
+ `Currently playing music track: ${Music[currentMusic]} (${currentMusic})`,
202
+ );
203
+ }
204
+
197
205
  export function logPlayerEffects(this: void, player: EntityPlayer): void {
198
206
  const effects = getEffectsList(player);
199
207
 
@@ -1,9 +1,54 @@
1
- import { SoundEffect } from "isaac-typescript-definitions";
2
- import { sfxManager } from "../core/cachedClasses";
1
+ import {
2
+ LevelStage,
3
+ Music,
4
+ SoundEffect,
5
+ StageType,
6
+ } from "isaac-typescript-definitions";
7
+ import { game, sfxManager } from "../core/cachedClasses";
8
+ import { STAGE_TO_MUSIC } from "../objects/stageToMusic";
3
9
  import { getEnumValues } from "./enums";
4
10
 
5
- export function stopAllSoundEffects(): void {
11
+ /**
12
+ * Helper function to get the corresponding music value for a stage and stage type combination.
13
+ *
14
+ * @param stage Optional. The stage to get the music for. If not specified, the current stage will
15
+ * be used.
16
+ * @param stageType Optional. The stage type to get the music for. If not specified, the current
17
+ * stage type will be used.
18
+ */
19
+ export function getMusicForStage(
20
+ stage?: LevelStage,
21
+ stageType?: StageType,
22
+ ): Music {
23
+ const level = game.GetLevel();
24
+
25
+ if (stage === undefined) {
26
+ stage = level.GetStage();
27
+ }
28
+
29
+ if (stageType === undefined) {
30
+ stageType = level.GetStageType();
31
+ }
32
+
33
+ const stageTypeToMusic = STAGE_TO_MUSIC[stage];
34
+ return stageTypeToMusic[stageType];
35
+ }
36
+
37
+ /**
38
+ * Helper function to manually stop every vanilla sound effect. If you also want to stop custom
39
+ * sound effects in addition to vanilla ones, then pass the `SoundEffectCustom` enum for your mod.
40
+ *
41
+ * @param soundEffectCustom Optional. The enum that represents all of the custom sound effects for
42
+ * your mod.
43
+ */
44
+ export function stopAllSoundEffects(soundEffectCustom?: unknown): void {
6
45
  for (const soundEffect of getEnumValues(SoundEffect)) {
7
46
  sfxManager.Stop(soundEffect);
8
47
  }
48
+
49
+ if (soundEffectCustom !== undefined) {
50
+ for (const soundEffect of getEnumValues(soundEffectCustom)) {
51
+ sfxManager.Stop(soundEffect as SoundEffect);
52
+ }
53
+ }
9
54
  }
@@ -4,9 +4,10 @@ import { UI_HEART_WIDTH, VectorZero } from "../core/constants";
4
4
  import { copyVector } from "./vector";
5
5
 
6
6
  /**
7
- * In the options menu, players have the ability to set a HUD offset. This uses the current HUD
8
- * offset to generate a vector that should be added to the corresponding position that you want to
9
- * draw a UI element.
7
+ * In the options menu, players have the ability to set a HUD offset (which gets written to the
8
+ * `HudOffset` attribute in the "options.ini" file). This function uses the current HUD offset to
9
+ * generate a vector that should be added to the corresponding position that you want to draw a UI
10
+ * element at.
10
11
  *
11
12
  * For example:
12
13
  * - If the user does not have a HUD offset configured, this function will return `Vector(0, 0)`.
@@ -70,6 +70,14 @@ export interface CustomStageTSConfig {
70
70
  */
71
71
  baseStageType?: number;
72
72
 
73
+ /**
74
+ * Optional. A string that represents the name of the music track from the "content/music.xml"
75
+ * file that corresponds to this custom stage. It will be manually played upon entering the stage.
76
+ *
77
+ * If not specified, the same music track as the base stage will be used.
78
+ */
79
+ music?: string;
80
+
73
81
  /**
74
82
  * Optional. An object containing the paths to the backdrop graphics for the stage. (A backdrop is
75
83
  * the graphics for the walls and floor.) If not specified, the graphics for Basement will be
@@ -0,0 +1,99 @@
1
+ import { LevelStage, Music, StageType } from "isaac-typescript-definitions";
2
+ import { HasAllEnumKeys } from "../types/HasAllEnumKeys";
3
+
4
+ const BASEMENT_TO_MUSIC = {
5
+ [StageType.ORIGINAL]: Music.BASEMENT,
6
+ [StageType.WRATH_OF_THE_LAMB]: Music.CELLAR,
7
+ [StageType.AFTERBIRTH]: Music.BURNING_BASEMENT,
8
+ [StageType.GREED_MODE]: Music.BASEMENT,
9
+ [StageType.REPENTANCE]: Music.DOWNPOUR,
10
+ [StageType.REPENTANCE_B]: Music.DROSS,
11
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
12
+
13
+ const CAVES_TO_MUSIC = {
14
+ [StageType.ORIGINAL]: Music.CAVES,
15
+ [StageType.WRATH_OF_THE_LAMB]: Music.CATACOMBS,
16
+ [StageType.AFTERBIRTH]: Music.FLOODED_CAVES,
17
+ [StageType.GREED_MODE]: Music.CAVES,
18
+ [StageType.REPENTANCE]: Music.MINES,
19
+ [StageType.REPENTANCE_B]: Music.ASHPIT,
20
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
21
+
22
+ const DEPTHS_TO_MUSIC = {
23
+ [StageType.ORIGINAL]: Music.DEPTHS,
24
+ [StageType.WRATH_OF_THE_LAMB]: Music.NECROPOLIS,
25
+ [StageType.AFTERBIRTH]: Music.DANK_DEPTHS,
26
+ [StageType.GREED_MODE]: Music.DEPTHS,
27
+ [StageType.REPENTANCE]: Music.MAUSOLEUM,
28
+ [StageType.REPENTANCE_B]: Music.GEHENNA,
29
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
30
+
31
+ const WOMB_TO_MUSIC = {
32
+ [StageType.ORIGINAL]: Music.WOMB,
33
+ [StageType.WRATH_OF_THE_LAMB]: Music.UTERO,
34
+ [StageType.AFTERBIRTH]: Music.SCARRED_WOMB,
35
+ [StageType.GREED_MODE]: Music.WOMB,
36
+ [StageType.REPENTANCE]: Music.CORPSE,
37
+ [StageType.REPENTANCE_B]: Music.MORTIS,
38
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
39
+
40
+ const BLUE_WOMB_TO_MUSIC = {
41
+ [StageType.ORIGINAL]: Music.BLUE_WOMB,
42
+ [StageType.WRATH_OF_THE_LAMB]: Music.BLUE_WOMB,
43
+ [StageType.AFTERBIRTH]: Music.BLUE_WOMB,
44
+ [StageType.GREED_MODE]: Music.BLUE_WOMB,
45
+ [StageType.REPENTANCE]: Music.BLUE_WOMB,
46
+ [StageType.REPENTANCE_B]: Music.BLUE_WOMB,
47
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
48
+
49
+ const SHEOL_CATHEDRAL_TO_MUSIC = {
50
+ [StageType.ORIGINAL]: Music.SHEOL,
51
+ [StageType.WRATH_OF_THE_LAMB]: Music.CATHEDRAL,
52
+ [StageType.AFTERBIRTH]: Music.SHEOL,
53
+ [StageType.GREED_MODE]: Music.SHEOL,
54
+ [StageType.REPENTANCE]: Music.SHEOL,
55
+ [StageType.REPENTANCE_B]: Music.SHEOL,
56
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
57
+
58
+ const DARK_ROOM_CHEST_TO_MUSIC = {
59
+ [StageType.ORIGINAL]: Music.DARK_ROOM,
60
+ [StageType.WRATH_OF_THE_LAMB]: Music.CHEST,
61
+ [StageType.AFTERBIRTH]: Music.DARK_ROOM,
62
+ [StageType.GREED_MODE]: Music.DARK_ROOM,
63
+ [StageType.REPENTANCE]: Music.DARK_ROOM,
64
+ [StageType.REPENTANCE_B]: Music.DARK_ROOM,
65
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
66
+
67
+ const THE_VOID_TO_MUSIC = {
68
+ [StageType.ORIGINAL]: Music.VOID,
69
+ [StageType.WRATH_OF_THE_LAMB]: Music.VOID,
70
+ [StageType.AFTERBIRTH]: Music.VOID,
71
+ [StageType.GREED_MODE]: Music.VOID,
72
+ [StageType.REPENTANCE]: Music.VOID,
73
+ [StageType.REPENTANCE_B]: Music.VOID,
74
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
75
+
76
+ const HOME_TO_MUSIC = {
77
+ [StageType.ORIGINAL]: Music.ISAACS_HOUSE,
78
+ [StageType.WRATH_OF_THE_LAMB]: Music.ISAACS_HOUSE,
79
+ [StageType.AFTERBIRTH]: Music.ISAACS_HOUSE,
80
+ [StageType.GREED_MODE]: Music.ISAACS_HOUSE,
81
+ [StageType.REPENTANCE]: Music.ISAACS_HOUSE,
82
+ [StageType.REPENTANCE_B]: Music.ISAACS_HOUSE,
83
+ } as const satisfies HasAllEnumKeys<StageType, Music>;
84
+
85
+ export const STAGE_TO_MUSIC = {
86
+ [LevelStage.BASEMENT_1]: BASEMENT_TO_MUSIC,
87
+ [LevelStage.BASEMENT_2]: BASEMENT_TO_MUSIC,
88
+ [LevelStage.CAVES_1]: CAVES_TO_MUSIC,
89
+ [LevelStage.CAVES_2]: CAVES_TO_MUSIC,
90
+ [LevelStage.DEPTHS_1]: DEPTHS_TO_MUSIC,
91
+ [LevelStage.DEPTHS_2]: DEPTHS_TO_MUSIC,
92
+ [LevelStage.WOMB_1]: WOMB_TO_MUSIC,
93
+ [LevelStage.WOMB_2]: WOMB_TO_MUSIC,
94
+ [LevelStage.BLUE_WOMB]: BLUE_WOMB_TO_MUSIC,
95
+ [LevelStage.SHEOL_CATHEDRAL]: SHEOL_CATHEDRAL_TO_MUSIC,
96
+ [LevelStage.DARK_ROOM_CHEST]: DARK_ROOM_CHEST_TO_MUSIC,
97
+ [LevelStage.THE_VOID]: THE_VOID_TO_MUSIC,
98
+ [LevelStage.HOME]: HOME_TO_MUSIC,
99
+ } as const satisfies HasAllEnumKeys<LevelStage, Record<StageType, Music>>;