isaacscript-common 11.0.1 → 11.2.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 (37) hide show
  1. package/dist/index.d.ts +15 -1
  2. package/dist/isaacscript-common.lua +337 -193
  3. package/dist/package.lua +2 -2
  4. package/dist/src/features/extraConsoleCommands/init.d.ts.map +1 -1
  5. package/dist/src/features/extraConsoleCommands/init.lua +14 -21
  6. package/dist/src/features/extraConsoleCommands/listCommands.d.ts +26 -7
  7. package/dist/src/features/extraConsoleCommands/listCommands.d.ts.map +1 -1
  8. package/dist/src/features/extraConsoleCommands/listCommands.lua +114 -23
  9. package/dist/src/features/extraConsoleCommands/v.d.ts +7 -6
  10. package/dist/src/features/extraConsoleCommands/v.d.ts.map +1 -1
  11. package/dist/src/features/extraConsoleCommands/v.lua +9 -7
  12. package/dist/src/features/saveDataManager/main.d.ts.map +1 -1
  13. package/dist/src/features/saveDataManager/main.lua +6 -1
  14. package/dist/src/functions/collectibles.d.ts +4 -0
  15. package/dist/src/functions/collectibles.d.ts.map +1 -1
  16. package/dist/src/functions/collectibles.lua +4 -0
  17. package/dist/src/functions/map.d.ts +1 -1
  18. package/dist/src/functions/map.lua +1 -1
  19. package/dist/src/functions/tears.d.ts +6 -0
  20. package/dist/src/functions/tears.d.ts.map +1 -1
  21. package/dist/src/functions/tears.lua +6 -0
  22. package/dist/src/functions/trinkets.d.ts +4 -0
  23. package/dist/src/functions/trinkets.d.ts.map +1 -1
  24. package/dist/src/functions/trinkets.lua +4 -0
  25. package/dist/src/maps/transformationNameToPlayerForm.d.ts +4 -0
  26. package/dist/src/maps/transformationNameToPlayerForm.d.ts.map +1 -0
  27. package/dist/src/maps/transformationNameToPlayerForm.lua +37 -0
  28. package/package.json +2 -2
  29. package/src/features/extraConsoleCommands/init.ts +20 -26
  30. package/src/features/extraConsoleCommands/listCommands.ts +128 -24
  31. package/src/features/extraConsoleCommands/v.ts +11 -7
  32. package/src/features/saveDataManager/main.ts +12 -1
  33. package/src/functions/collectibles.ts +4 -0
  34. package/src/functions/map.ts +1 -1
  35. package/src/functions/tears.ts +6 -0
  36. package/src/functions/trinkets.ts +4 -0
  37. package/src/maps/transformationNameToPlayerForm.ts +35 -0
@@ -33,6 +33,9 @@ end
33
33
  -- only use this function in the `POST_TEAR_INIT_VERY_LATE` callback or on frame 1+.
34
34
  --
35
35
  -- If this function is called on frame 0, it will throw a run-time error.
36
+ --
37
+ -- Note that this function does not work properly when the tear is from a Lead Pencil barrage. In
38
+ -- this case, it will always appear as if the tear is coming from a player.
36
39
  function ____exports.isTearFromFamiliar(self, tear)
37
40
  if tear.FrameCount == 0 then
38
41
  error("Failed to check if the given tear was from a player since the tear's frame count was equal to 0. (The \"isTearFromFamiliar\" function must only be used in the \"POST_TEAR_INIT_VERY_LATE\" callback or on frame 1 and onwards.)")
@@ -52,6 +55,9 @@ end
52
55
  -- only use this function in the `POST_TEAR_INIT_VERY_LATE` callback or on frame 1+.
53
56
  --
54
57
  -- If this function is called on frame 0, it will throw a run-time error.
58
+ --
59
+ -- Note that this function does not work properly when the tear is from a Lead Pencil barrage. In
60
+ -- this case, it will always appear as if the tear is coming from a player.
55
61
  function ____exports.isTearFromPlayer(self, tear)
56
62
  if tear.FrameCount == 0 then
57
63
  error("Failed to check if the given tear was from a player since the tear's frame count was equal to 0. (The \"isTearFromPlayer\" function must only be used in the \"POST_TEAR_INIT_VERY_LATE\" callback or on frame 1 and onwards.)")
@@ -24,6 +24,8 @@ export declare function getOpenTrinketSlot(player: EntityPlayer): int | undefine
24
24
  /**
25
25
  * Helper function to get the in-game description for a trinket. Returns "Unknown" if the provided
26
26
  * trinket type was not valid.
27
+ *
28
+ * This function works for both vanilla and modded trinkets.
27
29
  */
28
30
  export declare function getTrinketDescription(trinketType: TrinketType): string;
29
31
  /**
@@ -40,6 +42,8 @@ export declare function getTrinketGfxFilename(trinketType: TrinketType): string;
40
42
  * not valid.
41
43
  *
42
44
  * For example, `getTrinketName(TrinketType.SWALLOWED_PENNY)` would return "Swallowed Penny".
45
+ *
46
+ * This function works for both vanilla and modded trinkets.
43
47
  */
44
48
  export declare function getTrinketName(trinketType: TrinketType): string;
45
49
  /** Helper function to get an array that represents every vanilla trinket type. */
@@ -1 +1 @@
1
- {"version":3,"file":"trinkets.d.ts","sourceRoot":"","sources":["../../../src/functions/trinkets.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EACZ,MAAM,8BAA8B,CAAC;AAkCtC;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,CAE1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,GAAG,GAAG,SAAS,CAkBxE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CActE;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAOtE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAc/D;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,IAAI,WAAW,EAAE,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAOhE;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAErE;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAErE;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAEtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CASjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,IAAI,CAeN"}
1
+ {"version":3,"file":"trinkets.d.ts","sourceRoot":"","sources":["../../../src/functions/trinkets.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EACZ,MAAM,8BAA8B,CAAC;AAkCtC;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,CAE1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,GAAG,GAAG,SAAS,CAkBxE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CActE;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAOtE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAc/D;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,IAAI,WAAW,EAAE,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAOhE;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAErE;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAErE;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAEtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CASjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,IAAI,CAeN"}
@@ -75,6 +75,8 @@ function ____exports.getOpenTrinketSlot(self, player)
75
75
  end
76
76
  --- Helper function to get the in-game description for a trinket. Returns "Unknown" if the provided
77
77
  -- trinket type was not valid.
78
+ --
79
+ -- This function works for both vanilla and modded trinkets.
78
80
  function ____exports.getTrinketDescription(self, trinketType)
79
81
  local trinketDescription = TRINKET_DESCRIPTION_MAP:get(trinketType)
80
82
  if trinketDescription ~= nil then
@@ -103,6 +105,8 @@ end
103
105
  -- not valid.
104
106
  --
105
107
  -- For example, `getTrinketName(TrinketType.SWALLOWED_PENNY)` would return "Swallowed Penny".
108
+ --
109
+ -- This function works for both vanilla and modded trinkets.
106
110
  function ____exports.getTrinketName(self, trinketType)
107
111
  local trinketName = TRINKET_TYPE_TO_NAME_MAP:get(trinketType)
108
112
  if trinketName ~= nil then
@@ -0,0 +1,4 @@
1
+ import { PlayerForm } from "isaac-typescript-definitions";
2
+ /** Maps transformation names to the values of the `PlayerForm` enum. */
3
+ export declare const TRANSFORMATION_NAME_TO_PLAYER_FORM_MAP: ReadonlyMap<string, PlayerForm>;
4
+ //# sourceMappingURL=transformationNameToPlayerForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformationNameToPlayerForm.d.ts","sourceRoot":"","sources":["../../../src/maps/transformationNameToPlayerForm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,wEAAwE;AACxE,eAAO,MAAM,sCAAsC,EAAE,WAAW,CAC9D,MAAM,EACN,UAAU,CA6BV,CAAC"}
@@ -0,0 +1,37 @@
1
+ local ____lualib = require("lualib_bundle")
2
+ local Map = ____lualib.Map
3
+ local __TS__New = ____lualib.__TS__New
4
+ local ____exports = {}
5
+ local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
6
+ local PlayerForm = ____isaac_2Dtypescript_2Ddefinitions.PlayerForm
7
+ --- Maps transformation names to the values of the `PlayerForm` enum.
8
+ ____exports.TRANSFORMATION_NAME_TO_PLAYER_FORM_MAP = __TS__New(Map, {
9
+ {"guppy", PlayerForm.GUPPY},
10
+ {"cat", PlayerForm.GUPPY},
11
+ {"beelzebub", PlayerForm.BEELZEBUB},
12
+ {"fly", PlayerForm.BEELZEBUB},
13
+ {"funGuy", PlayerForm.FUN_GUY},
14
+ {"mushroom", PlayerForm.FUN_GUY},
15
+ {"seraphim", PlayerForm.SERAPHIM},
16
+ {"angel", PlayerForm.SERAPHIM},
17
+ {"bob", PlayerForm.BOB},
18
+ {"poison", PlayerForm.BOB},
19
+ {"spun", PlayerForm.SPUN},
20
+ {"drugs", PlayerForm.SPUN},
21
+ {"needles", PlayerForm.SPUN},
22
+ {"yesMother", PlayerForm.YES_MOTHER},
23
+ {"mother", PlayerForm.YES_MOTHER},
24
+ {"mom", PlayerForm.YES_MOTHER},
25
+ {"conjoined", PlayerForm.CONJOINED},
26
+ {"triple", PlayerForm.CONJOINED},
27
+ {"leviathan", PlayerForm.LEVIATHAN},
28
+ {"devil", PlayerForm.LEVIATHAN},
29
+ {"ohCrap", PlayerForm.OH_CRAP},
30
+ {"crap", PlayerForm.OH_CRAP},
31
+ {"poop", PlayerForm.OH_CRAP},
32
+ {"bookWorm", PlayerForm.BOOKWORM},
33
+ {"adult", PlayerForm.ADULT},
34
+ {"spiderBaby", PlayerForm.SPIDER_BABY},
35
+ {"stompy", PlayerForm.STOMPY}
36
+ })
37
+ return ____exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "11.0.1",
3
+ "version": "11.2.0",
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/src/index.d.ts",
24
24
  "dependencies": {
25
- "isaac-typescript-definitions": "^7.2.1"
25
+ "isaac-typescript-definitions": "^7.2.3"
26
26
  }
27
27
  }
@@ -5,10 +5,8 @@ import {
5
5
  EntityType,
6
6
  LevelCurse,
7
7
  ModCallback,
8
- TearVariant,
9
8
  } from "isaac-typescript-definitions";
10
9
  import { ModUpgraded } from "../../classes/ModUpgraded";
11
- import { MAX_SPEED_STAT } from "../../core/constants";
12
10
  import { addFlag, bitFlags } from "../../functions/flag";
13
11
  import { getMapPartialMatch } from "../../functions/map";
14
12
  import { printConsole } from "../../functions/utils";
@@ -37,6 +35,11 @@ function initCommandMap() {
37
35
 
38
36
  function initCallbacks(mod: ModUpgraded) {
39
37
  mod.AddCallback(ModCallback.POST_UPDATE, postUpdate); // 1
38
+ mod.AddCallback(
39
+ ModCallback.EVALUATE_CACHE,
40
+ evaluateCacheDamage,
41
+ CacheFlag.DAMAGE, // 1 << 0
42
+ ); // 8
40
43
  mod.AddCallback(
41
44
  ModCallback.EVALUATE_CACHE,
42
45
  evaluateCacheFireDelay,
@@ -59,37 +62,44 @@ function initCallbacks(mod: ModUpgraded) {
59
62
  ); // 11
60
63
  mod.AddCallback(ModCallback.POST_CURSE_EVAL, postCurseEval); // 12
61
64
  mod.AddCallback(ModCallback.EXECUTE_CMD, executeCmd); // 22
62
- mod.AddCallback(ModCallback.POST_FIRE_TEAR, postFireTear); // 61
63
65
  }
64
66
 
65
67
  // ModCallback.POST_UPDATE (1)
66
68
  function postUpdate() {
67
- if (v.run.spamBloodRights) {
69
+ if (v.persistent.spamBloodRights) {
68
70
  const player = Isaac.GetPlayer();
69
71
  player.UseActiveItem(CollectibleType.BLOOD_RIGHTS);
70
72
  }
71
73
  }
72
74
 
75
+ // ModCallback.EVALUATE_CACHE (8)
76
+ // CacheFlag.DAMAGE (1 << 0)
77
+ function evaluateCacheDamage(player: EntityPlayer) {
78
+ if (v.persistent.damage) {
79
+ player.Damage = v.persistent.damageAmount;
80
+ }
81
+ }
82
+
73
83
  // ModCallback.EVALUATE_CACHE (8)
74
84
  // CacheFlag.FIRE_DELAY (1 << 1)
75
85
  function evaluateCacheFireDelay(player: EntityPlayer) {
76
- if (v.run.maxTears) {
77
- player.FireDelay = 1; // Equivalent to Soy Milk
86
+ if (v.persistent.tears) {
87
+ player.FireDelay = v.persistent.tearsAmount; // Equivalent to Soy Milk
78
88
  }
79
89
  }
80
90
 
81
91
  // ModCallback.EVALUATE_CACHE (8)
82
92
  // CacheFlag.SPEED (1 << 4)
83
93
  function evaluateCacheSpeed(player: EntityPlayer) {
84
- if (v.run.maxSpeed) {
85
- player.MoveSpeed = MAX_SPEED_STAT;
94
+ if (v.persistent.speed) {
95
+ player.MoveSpeed = v.persistent.speedAmount;
86
96
  }
87
97
  }
88
98
 
89
99
  // ModCallback.EVALUATE_CACHE (8)
90
100
  // CacheFlag.FLYING (1 << 7)
91
101
  function evaluateCacheFlying(player: EntityPlayer) {
92
- if (v.run.flight) {
102
+ if (v.persistent.flight) {
93
103
  player.CanFly = true;
94
104
  }
95
105
  }
@@ -103,7 +113,7 @@ function entityTakeDmgPlayer(
103
113
  _damageSource: EntityRef,
104
114
  _damageCountdownFrames: int,
105
115
  ) {
106
- if (v.run.spamBloodRights) {
116
+ if (v.persistent.spamBloodRights) {
107
117
  return false;
108
118
  }
109
119
 
@@ -178,19 +188,3 @@ function executeCmd(command: string, params: string) {
178
188
  printConsole(`Command: ${commandName}`);
179
189
  commandFunction(params);
180
190
  }
181
-
182
- // ModCallback.POST_FIRE_TEAR (61)
183
- function postFireTear(tear: EntityTear) {
184
- if (v.run.chaosCardTears) {
185
- tear.ChangeVariant(TearVariant.CHAOS_CARD);
186
- }
187
-
188
- if (v.run.maxDamage) {
189
- // If we increase the damage stat too high, then the tears will become bigger than the screen.
190
- // Instead, increase the collision damage of the tear.
191
- tear.CollisionDamage *= 1000;
192
-
193
- // Change the visual of the tear so that it is more clear that we have debug-damage turned on.
194
- tear.ChangeVariant(TearVariant.TOOTH);
195
- }
196
- }
@@ -45,6 +45,7 @@ import {
45
45
  LevelStage,
46
46
  PillColor,
47
47
  PillEffect,
48
+ PlayerForm,
48
49
  PlayerType,
49
50
  RoomType,
50
51
  SoundEffect,
@@ -70,7 +71,7 @@ import { addCharge } from "../../functions/charge";
70
71
  import { isValidCollectibleType } from "../../functions/collectibles";
71
72
  import { runDeepCopyTests } from "../../functions/deepCopyTests";
72
73
  import { getNPCs } from "../../functions/entitiesSpecific";
73
- import { getEnumValues } from "../../functions/enums";
74
+ import { getEnumValues, getLastEnumValue } from "../../functions/enums";
74
75
  import { addFlag } from "../../functions/flag";
75
76
  import { spawnGridEntity } from "../../functions/gridEntities";
76
77
  import { getRoomGridIndexesForType } from "../../functions/levelGrid";
@@ -99,8 +100,13 @@ import { gridCoordinatesToWorldPosition } from "../../functions/roomGrid";
99
100
  import { changeRoom } from "../../functions/rooms";
100
101
  import { reloadRoom as reloadRoomFunction } from "../../functions/roomTransition";
101
102
  import { onSetSeed, restart, setUnseeded } from "../../functions/run";
103
+ import { getSortedSetValues } from "../../functions/set";
102
104
  import { spawnCollectible as spawnCollectibleFunction } from "../../functions/spawnCollectible";
103
105
  import { setStage } from "../../functions/stage";
106
+ import {
107
+ getCollectibleTypesForTransformation,
108
+ getTransformationName,
109
+ } from "../../functions/transformations";
104
110
  import { getGoldenTrinketType } from "../../functions/trinkets";
105
111
  import {
106
112
  asCardType,
@@ -113,6 +119,7 @@ import { CHARACTER_NAME_TO_TYPE_MAP } from "../../maps/characterNameToTypeMap";
113
119
  import { COLLECTIBLE_NAME_TO_TYPE_MAP } from "../../maps/collectibleNameToTypeMap";
114
120
  import { PILL_NAME_TO_EFFECT_MAP } from "../../maps/pillNameToEffectMap";
115
121
  import { ROOM_NAME_TO_TYPE_MAP } from "../../maps/roomNameToTypeMap";
122
+ import { TRANSFORMATION_NAME_TO_PLAYER_FORM_MAP } from "../../maps/transformationNameToPlayerForm";
116
123
  import { TRINKET_NAME_TO_TYPE_MAP } from "../../maps/trinketNameToTypeMap";
117
124
  import { getLastCardType, getLastPillEffect } from "../firstLast";
118
125
  import {
@@ -400,8 +407,8 @@ export function cc(): void {
400
407
  * "debug 10".
401
408
  */
402
409
  export function chaosCardTears(): void {
403
- v.run.chaosCardTears = !v.run.chaosCardTears;
404
- printEnabled(v.run.chaosCardTears, "Chaos Card tears");
410
+ v.persistent.chaosCardTears = !v.persistent.chaosCardTears;
411
+ printEnabled(v.persistent.chaosCardTears, "Chaos Card tears");
405
412
  }
406
413
 
407
414
  /**
@@ -522,10 +529,23 @@ export function dadsNote(): void {
522
529
  bossRoom();
523
530
  }
524
531
 
525
- /** Toggles extremely high-damage tears for the player. */
526
- export function damage(): void {
527
- v.run.maxDamage = !v.run.maxDamage;
528
- printEnabled(v.run.maxDamage, "debug damage");
532
+ /**
533
+ * Toggles a set damage stat for the player. You can provide an optional argument to this command in
534
+ * order to set the damage to a specific amount. Default is 500.
535
+ */
536
+ export function damage(params: string): void {
537
+ if (params !== "") {
538
+ const num = tonumber(params);
539
+ if (num === undefined) {
540
+ printConsole(`The provided damage amount is invalid: ${params}`);
541
+ return;
542
+ }
543
+
544
+ v.persistent.damageAmount = num;
545
+ }
546
+
547
+ v.persistent.damage = !v.persistent.damage;
548
+ printEnabled(v.persistent.damage, "debug damage");
529
549
  }
530
550
 
531
551
  /** Toggles permanent Curse of Darkness. */
@@ -592,26 +612,26 @@ export function eternalHearts(params: string): void {
592
612
  export function flight(params: string): void {
593
613
  const player = Isaac.GetPlayer();
594
614
 
595
- v.run.flight = !v.run.flight;
615
+ v.persistent.flight = !v.persistent.flight;
596
616
 
597
617
  // Optionally, allow the toggle to be overridden by a parameter.
598
618
  if (params === "true") {
599
- v.run.flight = true;
619
+ v.persistent.flight = true;
600
620
  } else if (params === "false") {
601
- v.run.flight = false;
621
+ v.persistent.flight = false;
602
622
  }
603
623
 
604
624
  player.AddCacheFlags(CacheFlag.FLYING);
605
625
  player.EvaluateItems();
606
626
 
607
627
  const collectibleUsedToShowFlight = CollectibleType.FATE;
608
- if (v.run.flight) {
628
+ if (v.persistent.flight) {
609
629
  addCollectibleCostume(player, collectibleUsedToShowFlight);
610
630
  } else {
611
631
  removeCollectibleCostume(player, collectibleUsedToShowFlight);
612
632
  }
613
633
 
614
- printEnabled(v.run.maxSpeed, "max speed");
634
+ printEnabled(v.persistent.speed, "max speed");
615
635
  }
616
636
 
617
637
  /** Alias for the "startingRoom" command. */
@@ -1000,6 +1020,11 @@ export function playSound(params: string): void {
1000
1020
  sound(params);
1001
1021
  }
1002
1022
 
1023
+ /** Alias for the "transformation" command. */
1024
+ export function playerForm(params: string): void {
1025
+ transformation(params);
1026
+ }
1027
+
1003
1028
  /** Sets the player's pocket item to the specified collectible type. */
1004
1029
  export function pocket(params: string): void {
1005
1030
  if (params === "") {
@@ -1318,8 +1343,8 @@ export function sounds(): void {
1318
1343
  * "debug 10".
1319
1344
  */
1320
1345
  export function spam(): void {
1321
- v.run.spamBloodRights = !v.run.spamBloodRights;
1322
- printEnabled(v.run.spamBloodRights, "spamming Blood Rights");
1346
+ v.persistent.spamBloodRights = !v.persistent.spamBloodRights;
1347
+ printEnabled(v.persistent.spamBloodRights, "spamming Blood Rights");
1323
1348
  }
1324
1349
 
1325
1350
  export function spawnCollectible(params: string): void {
@@ -1405,19 +1430,33 @@ export function spawnTrinket(params: string): void {
1405
1430
  spawnTrinketFunction(trinketType, centerPos);
1406
1431
  }
1407
1432
 
1408
- /** Toggles maximum movement speed and flight for the player. */
1409
- export function speed(): void {
1433
+ /**
1434
+ * Toggles a set movement speed and flight for the player. You can provide an optional argument to
1435
+ * this command in order to set the speed to a specific amount. Default is 2.0 (which is the maximum
1436
+ * that the stat can be set to).
1437
+ */
1438
+ export function speed(params: string): void {
1410
1439
  const player = Isaac.GetPlayer();
1411
1440
 
1412
- v.run.maxSpeed = !v.run.maxSpeed;
1441
+ if (params !== "") {
1442
+ const num = tonumber(params);
1443
+ if (num === undefined) {
1444
+ printConsole(`The provided speed amount is invalid: ${params}`);
1445
+ return;
1446
+ }
1447
+
1448
+ v.persistent.damageAmount = num;
1449
+ }
1450
+
1451
+ v.persistent.speed = !v.persistent.speed;
1413
1452
 
1414
1453
  player.AddCacheFlags(CacheFlag.SPEED);
1415
1454
  player.EvaluateItems();
1416
1455
 
1417
- const value = tostring(v.run.maxSpeed);
1456
+ const value = tostring(v.persistent.speed);
1418
1457
  flight(value);
1419
1458
 
1420
- printEnabled(v.run.maxSpeed, "max speed and flight");
1459
+ printEnabled(v.persistent.speed, "max speed and flight");
1421
1460
  }
1422
1461
 
1423
1462
  /** Alias for the "startingRoom" command. */
@@ -1438,17 +1477,28 @@ export function superSecretRoom(): void {
1438
1477
  }
1439
1478
 
1440
1479
  /**
1441
- * Toggles an extremely high tears stat (e.g. fire rate) for the player, equivalent of that to soy
1442
- * milk.
1480
+ * Toggles a set tear delay (e.g. fire rate) for the player. You can provide an optional argument to
1481
+ * this command in order to set the tear delay to a specific amount. Default is 1 (which is
1482
+ * equivalent to the Soy Milk tear rate).
1443
1483
  */
1444
- export function tears(): void {
1445
- v.run.maxTears = !v.run.maxTears;
1484
+ export function tears(params: string): void {
1485
+ if (params !== "") {
1486
+ const num = tonumber(params);
1487
+ if (num === undefined) {
1488
+ printConsole(`The provided tear delay amount is invalid: ${params}`);
1489
+ return;
1490
+ }
1491
+
1492
+ v.persistent.tearsAmount = num;
1493
+ }
1494
+
1495
+ v.persistent.tears = !v.persistent.tears;
1446
1496
 
1447
1497
  const player = Isaac.GetPlayer();
1448
1498
  player.AddCacheFlags(CacheFlag.FIRE_DELAY);
1449
1499
  player.EvaluateItems();
1450
1500
 
1451
- printEnabled(v.run.maxDamage, "debug tear-rate");
1501
+ printEnabled(v.persistent.damage, "debug tear-rate");
1452
1502
  }
1453
1503
 
1454
1504
  /** Alias for the "runTests" command. */
@@ -1456,6 +1506,60 @@ export function tests(): void {
1456
1506
  runTests();
1457
1507
  }
1458
1508
 
1509
+ /**
1510
+ * Gives the specified transformation. Accepts either the transformation number or the partial name
1511
+ * of the transformation.
1512
+ *
1513
+ * For example:
1514
+ * - transformation 1 - Gives the Beelzebub transformation.
1515
+ * - transformation gup - Gives the Guppy transformation.
1516
+ */
1517
+ export function transformation(params: string): void {
1518
+ if (params === "") {
1519
+ printConsole("You must specify a transformation name or number.");
1520
+ return;
1521
+ }
1522
+
1523
+ let targetPlayerForm: PlayerForm;
1524
+ const num = tonumber(params) as PlayerForm | undefined;
1525
+ if (num === undefined) {
1526
+ const match = getMapPartialMatch(
1527
+ params,
1528
+ TRANSFORMATION_NAME_TO_PLAYER_FORM_MAP,
1529
+ );
1530
+ if (match === undefined) {
1531
+ printConsole(`Unknown transformation: ${params}`);
1532
+ return;
1533
+ }
1534
+
1535
+ targetPlayerForm = match[1];
1536
+ } else {
1537
+ const lastPlayerForm = getLastEnumValue(PlayerForm);
1538
+ if (num < PlayerForm.GUPPY || num > lastPlayerForm) {
1539
+ printConsole(`Invalid transformation number: ${num}`);
1540
+ return;
1541
+ }
1542
+
1543
+ targetPlayerForm = num;
1544
+ }
1545
+
1546
+ const transformationName = getTransformationName(targetPlayerForm);
1547
+ const player = Isaac.GetPlayer();
1548
+ const collectibleTypesSet =
1549
+ getCollectibleTypesForTransformation(targetPlayerForm);
1550
+ const collectiblesTypes = getSortedSetValues(collectibleTypesSet);
1551
+ for (let i = 0; i < 3; i++) {
1552
+ const collectibleType = collectiblesTypes[i];
1553
+ if (collectibleType !== undefined) {
1554
+ player.AddCollectible(collectibleType);
1555
+ }
1556
+ }
1557
+
1558
+ printConsole(
1559
+ `Gave transformation: ${transformationName} (${targetPlayerForm})`,
1560
+ );
1561
+ }
1562
+
1459
1563
  /** Creates a trapdoor next to the player. */
1460
1564
  export function trapdoor(): void {
1461
1565
  spawnTrapdoorOrCrawlSpace(true);
@@ -1,5 +1,6 @@
1
1
  const v = {
2
2
  persistent: {
3
+ // Curses
3
4
  darkness: false, // 1
4
5
  labyrinth: false, // 2
5
6
  lost: false, // 3
@@ -8,17 +9,20 @@ const v = {
8
9
  maze: false, // 6
9
10
  blind: false, // 7
10
11
  giant: false, // 8
11
-
12
12
  disableCurses: false,
13
- },
14
13
 
15
- run: {
14
+ // Stats
15
+ damage: false,
16
+ damageAmount: 500,
17
+ speed: false,
18
+ speedAmount: 2.0,
19
+ tears: false,
20
+ tearsAmount: 1, // In tear delay, not tears stat
21
+ flight: false,
22
+
23
+ // Other
16
24
  chaosCardTears: false,
17
25
  spamBloodRights: false,
18
- maxDamage: false,
19
- maxSpeed: false,
20
- maxTears: false,
21
- flight: false,
22
26
  },
23
27
  };
24
28
  export default v;
@@ -1,4 +1,4 @@
1
- import { ModCallback } from "isaac-typescript-definitions";
1
+ import { CollectibleType, ModCallback } from "isaac-typescript-definitions";
2
2
  import { ModUpgraded } from "../../classes/ModUpgraded";
3
3
  import { game } from "../../core/cachedClasses";
4
4
  import { ModCallbackCustom } from "../../enums/ModCallbackCustom";
@@ -33,6 +33,11 @@ let loadedDataOnThisRun = false;
33
33
  export function saveDataManagerInit(incomingMod: ModUpgraded): void {
34
34
  mod = incomingMod;
35
35
 
36
+ mod.AddCallback(
37
+ ModCallback.POST_USE_ITEM,
38
+ postUseItemGlowingHourGlass,
39
+ CollectibleType.GLOWING_HOUR_GLASS,
40
+ ); // 3
36
41
  mod.AddCallback(ModCallback.POST_PLAYER_INIT, postPlayerInit); // 9
37
42
  mod.AddCallback(ModCallback.PRE_GAME_EXIT, preGameExit); // 17
38
43
  mod.AddCallback(ModCallback.POST_NEW_LEVEL, postNewLevel); // 18
@@ -42,6 +47,12 @@ export function saveDataManagerInit(incomingMod: ModUpgraded): void {
42
47
  ); // 19
43
48
  }
44
49
 
50
+ // ModCallback.POST_USE_ITEM (3)
51
+ // CollectibleType.GLOWING_HOUR_GLASS (422)
52
+ function postUseItemGlowingHourGlass() {
53
+ return undefined;
54
+ }
55
+
45
56
  // ModCallback.POST_PLAYER_INIT (9)
46
57
  function postPlayerInit() {
47
58
  if (mod === null) {
@@ -100,6 +100,8 @@ export function getCollectibleChargeType(
100
100
  /**
101
101
  * Helper function to get the in-game description for a collectible. Returns "Unknown" if the
102
102
  * provided collectible type was not valid.
103
+ *
104
+ * This function works for both vanilla and modded collectibles.
103
105
  */
104
106
  export function getCollectibleDescription(
105
107
  collectibleType: CollectibleType,
@@ -319,6 +321,8 @@ export function getCollectibleMaxCharges(
319
321
  * type is not valid.
320
322
  *
321
323
  * For example, `getCollectibleName(CollectibleType.SAD_ONION)` would return "Sad Onion".
324
+ *
325
+ * This function works for both vanilla and modded collectibles.
322
326
  */
323
327
  export function getCollectibleName(collectibleType: CollectibleType): string {
324
328
  // "ItemConfigItem.Name" is bugged with vanilla items on patch v1.7.6, so we use a hard-coded map
@@ -24,7 +24,7 @@ export function copyMap<K, V>(oldMap: Map<K, V>): Map<K, V> {
24
24
  * ["bar", 456],
25
25
  * ]);
26
26
  * const searchText = "f";
27
- * const match = getMapPartialMatch(map, searchText); // match is now equal to 123
27
+ * const match = getMapPartialMatch(map, searchText); // match is now equal to ["foo", 123]
28
28
  *
29
29
  * @returns If a match was found, returns a tuple of the map key and value. If a match was not
30
30
  * found, returns undefined.
@@ -42,6 +42,9 @@ export function getTearsStat(fireDelay: float): float {
42
42
  * only use this function in the `POST_TEAR_INIT_VERY_LATE` callback or on frame 1+.
43
43
  *
44
44
  * If this function is called on frame 0, it will throw a run-time error.
45
+ *
46
+ * Note that this function does not work properly when the tear is from a Lead Pencil barrage. In
47
+ * this case, it will always appear as if the tear is coming from a player.
45
48
  */
46
49
  export function isTearFromFamiliar(tear: EntityTear): boolean {
47
50
  if (tear.FrameCount === 0) {
@@ -71,6 +74,9 @@ export function isTearFromFamiliar(tear: EntityTear): boolean {
71
74
  * only use this function in the `POST_TEAR_INIT_VERY_LATE` callback or on frame 1+.
72
75
  *
73
76
  * If this function is called on frame 0, it will throw a run-time error.
77
+ *
78
+ * Note that this function does not work properly when the tear is from a Lead Pencil barrage. In
79
+ * this case, it will always appear as if the tear is coming from a player.
74
80
  */
75
81
  export function isTearFromPlayer(tear: EntityTear): boolean {
76
82
  if (tear.FrameCount === 0) {
@@ -83,6 +83,8 @@ export function getOpenTrinketSlot(player: EntityPlayer): int | undefined {
83
83
  /**
84
84
  * Helper function to get the in-game description for a trinket. Returns "Unknown" if the provided
85
85
  * trinket type was not valid.
86
+ *
87
+ * This function works for both vanilla and modded trinkets.
86
88
  */
87
89
  export function getTrinketDescription(trinketType: TrinketType): string {
88
90
  // "ItemConfigItem.Description" is bugged with vanilla items on patch v1.7.6, so we use a
@@ -122,6 +124,8 @@ export function getTrinketGfxFilename(trinketType: TrinketType): string {
122
124
  * not valid.
123
125
  *
124
126
  * For example, `getTrinketName(TrinketType.SWALLOWED_PENNY)` would return "Swallowed Penny".
127
+ *
128
+ * This function works for both vanilla and modded trinkets.
125
129
  */
126
130
  export function getTrinketName(trinketType: TrinketType): string {
127
131
  // "ItemConfigItem.Name" is bugged with vanilla items on patch v1.7.6, so we use a hard-coded map
@@ -0,0 +1,35 @@
1
+ import { PlayerForm } from "isaac-typescript-definitions";
2
+
3
+ /** Maps transformation names to the values of the `PlayerForm` enum. */
4
+ export const TRANSFORMATION_NAME_TO_PLAYER_FORM_MAP: ReadonlyMap<
5
+ string,
6
+ PlayerForm
7
+ > = new Map([
8
+ ["guppy", PlayerForm.GUPPY], // 0
9
+ ["cat", PlayerForm.GUPPY], // 0
10
+ ["beelzebub", PlayerForm.BEELZEBUB], // 1
11
+ ["fly", PlayerForm.BEELZEBUB], // 1
12
+ ["funGuy", PlayerForm.FUN_GUY], // 2
13
+ ["mushroom", PlayerForm.FUN_GUY], // 2
14
+ ["seraphim", PlayerForm.SERAPHIM], // 3
15
+ ["angel", PlayerForm.SERAPHIM], // 3
16
+ ["bob", PlayerForm.BOB], // 4
17
+ ["poison", PlayerForm.BOB], // 4
18
+ ["spun", PlayerForm.SPUN], // 5
19
+ ["drugs", PlayerForm.SPUN], // 5
20
+ ["needles", PlayerForm.SPUN], // 5
21
+ ["yesMother", PlayerForm.YES_MOTHER], // 6
22
+ ["mother", PlayerForm.YES_MOTHER], // 6
23
+ ["mom", PlayerForm.YES_MOTHER], // 6
24
+ ["conjoined", PlayerForm.CONJOINED], // 7
25
+ ["triple", PlayerForm.CONJOINED], // 7
26
+ ["leviathan", PlayerForm.LEVIATHAN], // 8
27
+ ["devil", PlayerForm.LEVIATHAN], // 8
28
+ ["ohCrap", PlayerForm.OH_CRAP], // 9
29
+ ["crap", PlayerForm.OH_CRAP], // 9
30
+ ["poop", PlayerForm.OH_CRAP], // 9
31
+ ["bookWorm", PlayerForm.BOOKWORM], // 10
32
+ ["adult", PlayerForm.ADULT], // 11
33
+ ["spiderBaby", PlayerForm.SPIDER_BABY], // 12
34
+ ["stompy", PlayerForm.STOMPY], // 13
35
+ ]);