isaacscript-common 7.0.0 → 7.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 (254) hide show
  1. package/dist/callbacks/postPlayerChangeHealth.lua +8 -1
  2. package/dist/callbacks/postPlayerChangeStat.d.ts +3 -0
  3. package/dist/callbacks/postPlayerChangeStat.d.ts.map +1 -0
  4. package/dist/callbacks/postPlayerChangeStat.lua +88 -0
  5. package/dist/callbacks/subscriptions/postPlayerChangeHealth.d.ts +2 -2
  6. package/dist/callbacks/subscriptions/postPlayerChangeHealth.d.ts.map +1 -1
  7. package/dist/callbacks/subscriptions/postPlayerChangeHealth.lua +9 -2
  8. package/dist/callbacks/subscriptions/postPlayerChangeStat.d.ts +12 -0
  9. package/dist/callbacks/subscriptions/postPlayerChangeStat.d.ts.map +1 -0
  10. package/dist/callbacks/subscriptions/postPlayerChangeStat.lua +35 -0
  11. package/dist/classes/DefaultMap.d.ts +5 -5
  12. package/dist/classes/DefaultMap.d.ts.map +1 -1
  13. package/dist/core/constants.d.ts +1 -1
  14. package/dist/core/constants.d.ts.map +1 -1
  15. package/dist/core/constants.lua +1 -1
  16. package/dist/enums/AmbushType.d.ts +1 -0
  17. package/dist/enums/AmbushType.d.ts.map +1 -1
  18. package/dist/enums/AmbushType.lua +1 -0
  19. package/dist/enums/CornerType.d.ts +1 -0
  20. package/dist/enums/CornerType.d.ts.map +1 -1
  21. package/dist/enums/CornerType.lua +1 -0
  22. package/dist/enums/ModCallbackCustom.d.ts +70 -39
  23. package/dist/enums/ModCallbackCustom.d.ts.map +1 -1
  24. package/dist/enums/ModCallbackCustom.lua +37 -35
  25. package/dist/enums/PocketItemType.d.ts +1 -0
  26. package/dist/enums/PocketItemType.d.ts.map +1 -1
  27. package/dist/enums/PocketItemType.lua +1 -0
  28. package/dist/enums/RockAltType.d.ts +1 -0
  29. package/dist/enums/RockAltType.d.ts.map +1 -1
  30. package/dist/enums/RockAltType.lua +1 -0
  31. package/dist/enums/SerializationType.d.ts +1 -0
  32. package/dist/enums/SerializationType.d.ts.map +1 -1
  33. package/dist/enums/SerializationType.lua +1 -0
  34. package/dist/enums/SlotDestructionType.d.ts +1 -0
  35. package/dist/enums/SlotDestructionType.d.ts.map +1 -1
  36. package/dist/enums/SlotDestructionType.lua +1 -0
  37. package/dist/enums/StatType.d.ts +28 -0
  38. package/dist/enums/StatType.d.ts.map +1 -0
  39. package/dist/enums/StatType.lua +28 -0
  40. package/dist/enums/index.d.ts +1 -0
  41. package/dist/enums/index.d.ts.map +1 -1
  42. package/dist/enums/index.lua +8 -0
  43. package/dist/enums/private/CopyableIsaacAPIClassType.d.ts +5 -1
  44. package/dist/enums/private/CopyableIsaacAPIClassType.d.ts.map +1 -1
  45. package/dist/enums/private/CopyableIsaacAPIClassType.lua +3 -1
  46. package/dist/enums/private/SerializationBrand.d.ts +1 -0
  47. package/dist/enums/private/SerializationBrand.d.ts.map +1 -1
  48. package/dist/enums/private/SerializationBrand.lua +1 -0
  49. package/dist/features/customStage/backdrop.d.ts +1 -1
  50. package/dist/features/customStage/backdrop.d.ts.map +1 -1
  51. package/dist/features/customStage/backdrop.lua +1 -1
  52. package/dist/features/customStage/init.lua +2 -2
  53. package/dist/features/customStage/versusScreen.lua +2 -2
  54. package/dist/features/saveDataManager/merge.d.ts +1 -0
  55. package/dist/features/saveDataManager/merge.d.ts.map +1 -1
  56. package/dist/features/saveDataManager/merge.lua +1 -0
  57. package/dist/functions/bitSet128.d.ts +25 -0
  58. package/dist/functions/bitSet128.d.ts.map +1 -0
  59. package/dist/functions/bitSet128.lua +71 -0
  60. package/dist/functions/cacheFlag.d.ts +23 -1
  61. package/dist/functions/cacheFlag.d.ts.map +1 -1
  62. package/dist/functions/cacheFlag.lua +78 -0
  63. package/dist/functions/collectibles.d.ts +2 -2
  64. package/dist/functions/collectibles.lua +2 -2
  65. package/dist/functions/color.d.ts +1 -1
  66. package/dist/functions/color.d.ts.map +1 -1
  67. package/dist/functions/color.lua +2 -2
  68. package/dist/functions/deepCopy.d.ts +1 -0
  69. package/dist/functions/deepCopy.d.ts.map +1 -1
  70. package/dist/functions/deepCopy.lua +1 -0
  71. package/dist/functions/familiars.d.ts +4 -4
  72. package/dist/functions/familiars.lua +4 -4
  73. package/dist/functions/flag.d.ts +1 -1
  74. package/dist/functions/flag.lua +1 -1
  75. package/dist/functions/flying.lua +2 -2
  76. package/dist/functions/index.d.ts +2 -1
  77. package/dist/functions/index.d.ts.map +1 -1
  78. package/dist/functions/index.lua +16 -8
  79. package/dist/functions/input.d.ts +4 -1
  80. package/dist/functions/input.d.ts.map +1 -1
  81. package/dist/functions/input.lua +10 -2
  82. package/dist/functions/jsonRoom.lua +4 -4
  83. package/dist/functions/kColor.d.ts +1 -1
  84. package/dist/functions/kColor.d.ts.map +1 -1
  85. package/dist/functions/kColor.lua +2 -2
  86. package/dist/functions/log.lua +1 -1
  87. package/dist/functions/npcs.d.ts +2 -2
  88. package/dist/functions/npcs.lua +2 -2
  89. package/dist/functions/playerIndex.d.ts +1 -1
  90. package/dist/functions/playerIndex.lua +1 -1
  91. package/dist/functions/playerStats.d.ts +6 -0
  92. package/dist/functions/playerStats.d.ts.map +1 -0
  93. package/dist/functions/playerStats.lua +21 -0
  94. package/dist/functions/players.d.ts +1 -1
  95. package/dist/functions/players.lua +1 -1
  96. package/dist/functions/rng.d.ts +1 -1
  97. package/dist/functions/rng.d.ts.map +1 -1
  98. package/dist/functions/rng.lua +2 -2
  99. package/dist/functions/rockAlt.d.ts.map +1 -1
  100. package/dist/functions/rockAlt.lua +11 -20
  101. package/dist/functions/roomTransition.d.ts +1 -1
  102. package/dist/functions/roomTransition.lua +1 -1
  103. package/dist/functions/rooms.d.ts +1 -1
  104. package/dist/functions/rooms.d.ts.map +1 -1
  105. package/dist/functions/rooms.lua +2 -1
  106. package/dist/functions/sprites.d.ts +3 -3
  107. package/dist/functions/sprites.lua +3 -3
  108. package/dist/functions/tears.d.ts +5 -4
  109. package/dist/functions/tears.d.ts.map +1 -1
  110. package/dist/functions/tears.lua +5 -4
  111. package/dist/functions/utils.d.ts +4 -1
  112. package/dist/functions/utils.d.ts.map +1 -1
  113. package/dist/functions/utils.lua +4 -1
  114. package/dist/functions/vector.d.ts +1 -1
  115. package/dist/functions/vector.d.ts.map +1 -1
  116. package/dist/functions/vector.lua +2 -2
  117. package/dist/initCustomCallbacks.d.ts.map +1 -1
  118. package/dist/initCustomCallbacks.lua +3 -0
  119. package/dist/interfaces/ChargeBarSprites.d.ts +1 -1
  120. package/dist/interfaces/Corner.d.ts +5 -0
  121. package/dist/interfaces/Corner.d.ts.map +1 -1
  122. package/dist/interfaces/CustomStageLua.d.ts +57 -0
  123. package/dist/interfaces/CustomStageLua.d.ts.map +1 -1
  124. package/dist/interfaces/GridEntityCustomData.d.ts +6 -0
  125. package/dist/interfaces/GridEntityCustomData.d.ts.map +1 -1
  126. package/dist/interfaces/JSONRoomsFile.d.ts +7 -3
  127. package/dist/interfaces/JSONRoomsFile.d.ts.map +1 -1
  128. package/dist/interfaces/PlayerHealth.d.ts +1 -1
  129. package/dist/interfaces/PlayerHealth.d.ts.map +1 -1
  130. package/dist/interfaces/PocketItemDescription.d.ts +1 -1
  131. package/dist/interfaces/PocketItemDescription.d.ts.map +1 -1
  132. package/dist/interfaces/RoomDescription.d.ts +1 -1
  133. package/dist/interfaces/RoomDescription.d.ts.map +1 -1
  134. package/dist/interfaces/SaveData.d.ts +2 -5
  135. package/dist/interfaces/SaveData.d.ts.map +1 -1
  136. package/dist/interfaces/StatTypeType.d.ts +21 -0
  137. package/dist/interfaces/StatTypeType.d.ts.map +1 -0
  138. package/dist/interfaces/StatTypeType.lua +4 -0
  139. package/dist/interfaces/TrinketSituation.d.ts +1 -1
  140. package/dist/interfaces/TrinketSituation.d.ts.map +1 -1
  141. package/dist/interfaces/index.d.ts +1 -0
  142. package/dist/interfaces/index.d.ts.map +1 -1
  143. package/dist/interfaces/private/AddCallbackParameterCustom.d.ts +2 -0
  144. package/dist/interfaces/private/AddCallbackParameterCustom.d.ts.map +1 -1
  145. package/dist/maps/keyboardToString.d.ts +4 -0
  146. package/dist/maps/keyboardToString.d.ts.map +1 -0
  147. package/dist/maps/keyboardToString.lua +73 -0
  148. package/dist/objects/callbackRegisterFunctions.d.ts.map +1 -1
  149. package/dist/objects/callbackRegisterFunctions.lua +3 -0
  150. package/dist/objects/isaacAPIClassTypeToBrand.d.ts.map +1 -1
  151. package/dist/objects/isaacAPIClassTypeToBrand.lua +7 -1
  152. package/dist/objects/isaacAPIClassTypeToFunctions.d.ts.map +1 -1
  153. package/dist/objects/isaacAPIClassTypeToFunctions.lua +12 -1
  154. package/dist/types/AnyEntity.d.ts +5 -0
  155. package/dist/types/AnyEntity.d.ts.map +1 -1
  156. package/dist/types/AnyGridEntity.d.ts +5 -0
  157. package/dist/types/AnyGridEntity.d.ts.map +1 -1
  158. package/dist/types/CollectibleIndex.d.ts +4 -3
  159. package/dist/types/CollectibleIndex.d.ts.map +1 -1
  160. package/dist/types/Immutable.d.ts +3 -1
  161. package/dist/types/Immutable.d.ts.map +1 -1
  162. package/dist/types/PickupIndex.d.ts +4 -2
  163. package/dist/types/PickupIndex.d.ts.map +1 -1
  164. package/dist/types/PlayerIndex.d.ts +3 -2
  165. package/dist/types/PlayerIndex.d.ts.map +1 -1
  166. package/dist/types/SerializedIsaacAPIClass.d.ts +6 -0
  167. package/dist/types/SerializedIsaacAPIClass.d.ts.map +1 -1
  168. package/dist/types/TSTLClass.d.ts +5 -0
  169. package/dist/types/TSTLClass.d.ts.map +1 -1
  170. package/dist/types/TrapdoorDestination.d.ts +3 -0
  171. package/dist/types/TrapdoorDestination.d.ts.map +1 -1
  172. package/package.json +2 -2
  173. package/src/callbacks/postPlayerChangeHealth.ts +7 -1
  174. package/src/callbacks/postPlayerChangeStat.ts +110 -0
  175. package/src/callbacks/subscriptions/postPlayerChangeHealth.ts +5 -1
  176. package/src/callbacks/subscriptions/postPlayerChangeStat.ts +55 -0
  177. package/src/classes/DefaultMap.ts +7 -7
  178. package/src/core/constants.ts +1 -1
  179. package/src/enums/AmbushType.ts +1 -0
  180. package/src/enums/CornerType.ts +1 -0
  181. package/src/enums/ModCallbackCustom.ts +36 -4
  182. package/src/enums/PocketItemType.ts +1 -0
  183. package/src/enums/RockAltType.ts +1 -0
  184. package/src/enums/SerializationType.ts +1 -0
  185. package/src/enums/SlotDestructionType.ts +1 -0
  186. package/src/enums/StatType.ts +47 -0
  187. package/src/enums/index.ts +1 -0
  188. package/src/enums/indexTypeDoc.ts +1 -0
  189. package/src/enums/private/CopyableIsaacAPIClassType.ts +5 -1
  190. package/src/enums/private/SerializationBrand.ts +1 -0
  191. package/src/features/customStage/backdrop.ts +1 -1
  192. package/src/features/customStage/init.ts +2 -2
  193. package/src/features/customStage/versusScreen.ts +2 -2
  194. package/src/features/fastReset.ts +1 -1
  195. package/src/features/indexTypeDoc.ts +2 -1
  196. package/src/features/saveDataManager/merge.ts +1 -0
  197. package/src/functions/bitSet128.ts +96 -0
  198. package/src/functions/cacheFlag.ts +90 -1
  199. package/src/functions/collectibles.ts +2 -2
  200. package/src/functions/color.ts +3 -2
  201. package/src/functions/deepCopy.ts +1 -0
  202. package/src/functions/familiars.ts +4 -4
  203. package/src/functions/flag.ts +1 -1
  204. package/src/functions/flying.ts +1 -1
  205. package/src/functions/index.ts +2 -1
  206. package/src/functions/indexTypeDoc.ts +2 -1
  207. package/src/functions/input.ts +15 -2
  208. package/src/functions/jsonRoom.ts +4 -4
  209. package/src/functions/kColor.ts +2 -2
  210. package/src/functions/log.ts +1 -1
  211. package/src/functions/npcs.ts +2 -2
  212. package/src/functions/playerIndex.ts +1 -1
  213. package/src/functions/playerStats.ts +25 -0
  214. package/src/functions/players.ts +1 -1
  215. package/src/functions/rng.ts +2 -2
  216. package/src/functions/rockAlt.ts +28 -13
  217. package/src/functions/roomTransition.ts +1 -1
  218. package/src/functions/rooms.ts +2 -1
  219. package/src/functions/sprites.ts +3 -3
  220. package/src/functions/tears.ts +5 -4
  221. package/src/functions/utils.ts +5 -1
  222. package/src/functions/vector.ts +2 -2
  223. package/src/initCustomCallbacks.ts +2 -0
  224. package/src/interfaces/ChargeBarSprites.ts +1 -1
  225. package/src/interfaces/Corner.ts +5 -0
  226. package/src/interfaces/CustomStageLua.ts +66 -0
  227. package/src/interfaces/GridEntityCustomData.ts +6 -0
  228. package/src/interfaces/JSONRoomsFile.ts +7 -3
  229. package/src/interfaces/PlayerHealth.ts +1 -1
  230. package/src/interfaces/PocketItemDescription.ts +1 -1
  231. package/src/interfaces/RoomDescription.ts +1 -1
  232. package/src/interfaces/SaveData.ts +1 -5
  233. package/src/interfaces/StatTypeType.ts +21 -0
  234. package/src/interfaces/TrinketSituation.ts +1 -1
  235. package/src/interfaces/index.ts +1 -0
  236. package/src/interfaces/indexTypeDoc.ts +1 -0
  237. package/src/interfaces/private/AddCallbackParameterCustom.ts +2 -0
  238. package/src/maps/keyboardToString.ts +77 -0
  239. package/src/objects/callbackRegisterFunctions.ts +2 -0
  240. package/src/objects/isaacAPIClassTypeToBrand.ts +1 -0
  241. package/src/objects/isaacAPIClassTypeToFunctions.ts +12 -0
  242. package/src/types/AnyEntity.ts +5 -0
  243. package/src/types/AnyGridEntity.ts +5 -0
  244. package/src/types/CollectibleIndex.ts +4 -3
  245. package/src/types/Immutable.ts +3 -1
  246. package/src/types/PickupIndex.ts +4 -2
  247. package/src/types/PlayerIndex.ts +3 -2
  248. package/src/types/SerializedIsaacAPIClass.ts +6 -0
  249. package/src/types/TSTLClass.ts +5 -0
  250. package/src/types/TrapdoorDestination.ts +3 -0
  251. package/dist/functions/collectibleCacheFlag.d.ts +0 -24
  252. package/dist/functions/collectibleCacheFlag.d.ts.map +0 -1
  253. package/dist/functions/collectibleCacheFlag.lua +0 -80
  254. package/src/functions/collectibleCacheFlag.ts +0 -90
@@ -0,0 +1,96 @@
1
+ import { SerializationBrand } from "../enums/private/SerializationBrand";
2
+ import { isIsaacAPIClassOfType } from "./isaacAPIClass";
3
+ import { copyValuesToTable, getNumbersFromTable, tableHasKeys } from "./table";
4
+ import { isTable } from "./types";
5
+
6
+ export type SerializedBitSet128 = LuaMap<string, unknown> & {
7
+ readonly __serializedBitSet128Brand: symbol;
8
+ };
9
+
10
+ const OBJECT_NAME = "BitSet128";
11
+ const KEYS = ["l", "h"];
12
+
13
+ /** Helper function to copy a `BitSet128` Isaac API class. */
14
+ export function copyBitSet128(bitSet128: BitSet128): BitSet128 {
15
+ if (!isBitSet128(bitSet128)) {
16
+ error(
17
+ `Failed to copy a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
18
+ );
19
+ }
20
+
21
+ const lowBits = bitSet128.l;
22
+ const highBits = bitSet128.h;
23
+
24
+ return BitSet128(lowBits, highBits);
25
+ }
26
+
27
+ /**
28
+ * Helper function to convert a `SerializedBitSet128` object to a normal `BitSet128` object. (This
29
+ * is used by the save data manager when reading data from the "save#.dat" file.)
30
+ */
31
+ export function deserializeBitSet128(
32
+ bitSet128: SerializedBitSet128,
33
+ ): BitSet128 {
34
+ if (!isTable(bitSet128)) {
35
+ error(
36
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object was not a Lua table.`,
37
+ );
38
+ }
39
+
40
+ const [l, h] = getNumbersFromTable(
41
+ bitSet128 as LuaMap<string, unknown>,
42
+ OBJECT_NAME,
43
+ ...KEYS,
44
+ );
45
+
46
+ if (l === undefined) {
47
+ error(
48
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: l`,
49
+ );
50
+ }
51
+ if (h === undefined) {
52
+ error(
53
+ `Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: h`,
54
+ );
55
+ }
56
+
57
+ return BitSet128(l, h);
58
+ }
59
+
60
+ /** Helper function to check if something is an instantiated `BitSet128` object. */
61
+ export function isBitSet128(object: unknown): object is BitSet128 {
62
+ return isIsaacAPIClassOfType(object, OBJECT_NAME);
63
+ }
64
+
65
+ /**
66
+ * Used to determine is the given table is a serialized `BitSet128` object created by the save data
67
+ * manager and/or the `deepCopy` function.
68
+ */
69
+ export function isSerializedBitSet128(
70
+ object: unknown,
71
+ ): object is SerializedBitSet128 {
72
+ if (!isTable(object)) {
73
+ return false;
74
+ }
75
+
76
+ return (
77
+ tableHasKeys(object, ...KEYS) && object.has(SerializationBrand.BIT_SET_128)
78
+ );
79
+ }
80
+
81
+ /**
82
+ * Helper function to convert a `BitSet128` object to a `SerializedBitSet128` object. (This is used
83
+ * by the save data manager when writing data from the "save#.dat" file.)
84
+ */
85
+ export function serializeBitSet128(bitSet128: BitSet128): SerializedBitSet128 {
86
+ if (!isBitSet128(bitSet128)) {
87
+ error(
88
+ `Failed to serialize a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
89
+ );
90
+ }
91
+
92
+ const bitSet128Table = new LuaMap<string, unknown>();
93
+ copyValuesToTable(bitSet128, KEYS, bitSet128Table);
94
+ bitSet128Table.set(SerializationBrand.BIT_SET_128, "");
95
+ return bitSet128Table as SerializedBitSet128;
96
+ }
@@ -1,5 +1,62 @@
1
- import { CacheFlag } from "isaac-typescript-definitions";
1
+ import { CacheFlag, CollectibleType } from "isaac-typescript-definitions";
2
+ import { itemConfig } from "../core/cachedClasses";
2
3
  import { DEFAULT_PLAYER_STAT_MAP } from "../maps/defaultPlayerStatMap";
4
+ import { getCollectibleArray } from "./collectibleSet";
5
+ import { getEnumValues } from "./enums";
6
+ import { hasFlag } from "./flag";
7
+ import { copySet, getSortedSetValues } from "./set";
8
+ import { repeat } from "./utils";
9
+
10
+ const CACHE_FLAG_TO_COLLECTIBLES_MAP = new Map<
11
+ CacheFlag,
12
+ Set<CollectibleType>
13
+ >();
14
+
15
+ function initCacheFlagMap() {
16
+ for (const cacheFlag of getEnumValues(CacheFlag)) {
17
+ const collectiblesSet = new Set<CollectibleType>();
18
+
19
+ for (const collectibleType of getCollectibleArray()) {
20
+ if (collectibleHasCacheFlag(collectibleType, cacheFlag)) {
21
+ collectiblesSet.add(collectibleType);
22
+ }
23
+ }
24
+
25
+ CACHE_FLAG_TO_COLLECTIBLES_MAP.set(cacheFlag, collectiblesSet);
26
+ }
27
+ }
28
+
29
+ export function collectibleHasCacheFlag(
30
+ collectibleType: CollectibleType,
31
+ cacheFlag: CacheFlag,
32
+ ): boolean {
33
+ const itemConfigItem = itemConfig.GetCollectible(collectibleType);
34
+ if (itemConfigItem === undefined) {
35
+ return false;
36
+ }
37
+
38
+ return hasFlag(itemConfigItem.CacheFlags, cacheFlag);
39
+ }
40
+
41
+ /**
42
+ * Returns a set containing every collectible type with the given cache flag, including modded
43
+ * collectibles.
44
+ */
45
+ export function getCollectiblesForCacheFlag(
46
+ cacheFlag: CacheFlag,
47
+ ): Set<CollectibleType> {
48
+ // Lazy initialize the map.
49
+ if (CACHE_FLAG_TO_COLLECTIBLES_MAP.size === 0) {
50
+ initCacheFlagMap();
51
+ }
52
+
53
+ const collectiblesSet = CACHE_FLAG_TO_COLLECTIBLES_MAP.get(cacheFlag);
54
+ if (collectiblesSet === undefined) {
55
+ return new Set();
56
+ }
57
+
58
+ return copySet(collectiblesSet);
59
+ }
3
60
 
4
61
  /**
5
62
  * Returns the starting stat that Isaac (the default character) starts with. For example, if you
@@ -10,3 +67,35 @@ import { DEFAULT_PLAYER_STAT_MAP } from "../maps/defaultPlayerStatMap";
10
67
  export function getDefaultPlayerStat(cacheFlag: CacheFlag): number | undefined {
11
68
  return DEFAULT_PLAYER_STAT_MAP.get(cacheFlag);
12
69
  }
70
+
71
+ /**
72
+ * Returns an array containing every collectible type that the player has that matches the provided
73
+ * CacheFlag.
74
+ *
75
+ * For example, if the cache flag is `CacheFlag.FLYING`, and the player has one Lord of the Pit and
76
+ * two Dead Doves, then this function would return:
77
+ *
78
+ * ```ts
79
+ * [
80
+ * CollectibleType.LORD_OF_THE_PIT,
81
+ * CollectibleType.DEAD_DOVE,
82
+ * CollectibleType.DEAD_DOVE,
83
+ * ]
84
+ * ```
85
+ */
86
+ export function getPlayerCollectiblesForCacheFlag(
87
+ player: EntityPlayer,
88
+ cacheFlag: CacheFlag,
89
+ ): CollectibleType[] {
90
+ const collectiblesForCacheFlag = getCollectiblesForCacheFlag(cacheFlag);
91
+
92
+ const playerCollectibles: CollectibleType[] = [];
93
+ for (const collectibleType of getSortedSetValues(collectiblesForCacheFlag)) {
94
+ const numCollectibles = player.GetCollectibleNum(collectibleType);
95
+ repeat(numCollectibles, () => {
96
+ playerCollectibles.push(collectibleType);
97
+ });
98
+ }
99
+
100
+ return playerCollectibles;
101
+ }
@@ -614,8 +614,8 @@ export function setCollectibleSprite(
614
614
  }
615
615
 
616
616
  /**
617
- * Helper function to change the collectible on a pedestal. Simply updating the `SubType` property
618
- * is not sufficient because the sprite will not change.
617
+ * Helper function to change the collectible on a pedestal. Simply updating the `SubType` field is
618
+ * not sufficient because the sprite will not change.
619
619
  */
620
620
  export function setCollectibleSubType(
621
621
  collectible: EntityPickup,
@@ -9,8 +9,8 @@ export type SerializedColor = LuaMap<string, unknown> & {
9
9
  readonly __serializedColorBrand: symbol;
10
10
  };
11
11
 
12
- const KEYS = ["R", "G", "B", "A", "RO", "GO", "BO"];
13
12
  const OBJECT_NAME = "Color";
13
+ const KEYS = ["R", "G", "B", "A", "RO", "GO", "BO"];
14
14
 
15
15
  export function colorEquals(color1: Color, color2: Color): boolean {
16
16
  return isaacAPIClassEquals(color1, color2, KEYS);
@@ -91,7 +91,7 @@ export function getRandomColor(
91
91
  return Color(r, g, b, alpha);
92
92
  }
93
93
 
94
- /** Helper function to check if something is an instantiated Color object. */
94
+ /** Helper function to check if something is an instantiated `Color` object. */
95
95
  export function isColor(object: unknown): object is Color {
96
96
  return isIsaacAPIClassOfType(object, OBJECT_NAME);
97
97
  }
@@ -107,6 +107,7 @@ export function isSerializedColor(object: unknown): object is SerializedColor {
107
107
 
108
108
  return tableHasKeys(object, ...KEYS) && object.has(SerializationBrand.COLOR);
109
109
  }
110
+
110
111
  /**
111
112
  * Helper function to convert a `Color` object to a `SerializedColor` object. (This is used by the
112
113
  * save data manager when writing data from the "save#.dat" file.)
@@ -42,6 +42,7 @@ const COPYABLE_ISAAC_API_CLASS_TYPES_SET = new Set<string>(
42
42
  * - TSTL `Set`
43
43
  * - TSTL classes
44
44
  * - `DefaultMap`
45
+ * - Isaac `BitSet128` objects
45
46
  * - Isaac `Color` objects
46
47
  * - Isaac `KColor` objects
47
48
  * - Isaac `RNG` objects
@@ -11,8 +11,8 @@ import { getFamiliars } from "./entitiesSpecific";
11
11
  * specify an incorrect RNG object. (The vanilla method is bugged in that it does not increment the
12
12
  * RNG object; see the documentation of the method for more details.)
13
13
  *
14
- * This function is meant to be called in the EvaluateCache callback (when the cache flag is equal
15
- * to `CacheFlag.FAMILIARS`).
14
+ * This function is meant to be called in the `EVALUATE_CACHE` callback (when the cache flag is
15
+ * equal to `CacheFlag.FAMILIARS`).
16
16
  *
17
17
  * Note that this function is only meant to be used in special circumstances where the familiar
18
18
  * count is completely custom and does not correspond to the amount of collectibles. For the general
@@ -56,8 +56,8 @@ export function checkFamiliar(
56
56
  * Use this helper function instead of invoking the `EntityPlayer.CheckFamiliar` method directly so
57
57
  * that the target count is handled automatically.
58
58
  *
59
- * This function is meant to be called in the EvaluateCache callback (when the cache flag is equal
60
- * to `CacheFlag.FAMILIARS`).
59
+ * This function is meant to be called in the `EVALUATE_CACHE` callback (when the cache flag is
60
+ * equal to `CacheFlag.FAMILIARS`).
61
61
  *
62
62
  * Use this function when the amount of familiars should be equal to the amount of associated
63
63
  * collectibles that the player has (plus any extras from having used Box of Friends or Monster
@@ -42,7 +42,7 @@ export function addFlag<T extends BitFlag | BitFlag128>(
42
42
  * Helper function for casting a flag enum value to a `BitFlags` object.
43
43
  *
44
44
  * This is useful because the compiler will prevent you from assigning a specific flag to a
45
- * `BitFlags` property. (It does this to ensure type safety, since `BitFlags` can represent a zero
45
+ * `BitFlags` field. (It does this to ensure type safety, since `BitFlags` can represent a zero
46
46
  * value or a composition of N flags.)
47
47
  *
48
48
  * For example:
@@ -5,7 +5,7 @@ import {
5
5
  PlayerType,
6
6
  TrinketType,
7
7
  } from "isaac-typescript-definitions";
8
- import { getCollectiblesForCacheFlag } from "./collectibleCacheFlag";
8
+ import { getCollectiblesForCacheFlag } from "./cacheFlag";
9
9
  import { copySet, deleteSetsFromSet } from "./set";
10
10
 
11
11
  const FLYING_CHARACTERS: ReadonlySet<PlayerType> = new Set([
@@ -3,6 +3,7 @@
3
3
  export * from "./ambush";
4
4
  export * from "./array";
5
5
  export * from "./benchmark";
6
+ export * from "./bitSet128";
6
7
  export * from "./bitwise";
7
8
  export * from "./bombs";
8
9
  export * from "./bosses";
@@ -12,7 +13,6 @@ export * from "./challenges";
12
13
  export * from "./characters";
13
14
  export * from "./charge";
14
15
  export * from "./chargeBar";
15
- export * from "./collectibleCacheFlag";
16
16
  export * from "./collectibles";
17
17
  export * from "./collectibleSet";
18
18
  export * from "./collectibleTag";
@@ -63,6 +63,7 @@ export * from "./playerDataStructures";
63
63
  export * from "./playerHealth";
64
64
  export * from "./playerIndex";
65
65
  export * from "./players";
66
+ export * from "./playerStats";
66
67
  export * from "./pocketItems";
67
68
  export * from "./positionVelocity";
68
69
  export * from "./pressurePlate";
@@ -3,6 +3,7 @@
3
3
  export * as Ambush from "./ambush";
4
4
  export * as Array from "./array";
5
5
  export * as Benchmark from "./benchmark";
6
+ export * as BitSet128 from "./bitSet128";
6
7
  export * as Bitwise from "./bitwise";
7
8
  export * as Bombs from "./bombs";
8
9
  export * as Bosses from "./bosses";
@@ -12,7 +13,6 @@ export * as Challenges from "./challenges";
12
13
  export * as Characters from "./characters";
13
14
  export * as Charge from "./charge";
14
15
  export * as ChargeBar from "./chargeBar";
15
- export * as CollectibleCacheFlag from "./collectibleCacheFlag";
16
16
  export * as Collectibles from "./collectibles";
17
17
  export * as CollectibleSet from "./collectibleSet";
18
18
  export * as CollectibleTag from "./collectibleTag";
@@ -63,6 +63,7 @@ export * as PlayerDataStructures from "./playerDataStructures";
63
63
  export * as PlayerHealth from "./playerHealth";
64
64
  export * as PlayerIndex from "./playerIndex";
65
65
  export * as Players from "./players";
66
+ export * as PlayerStats from "./playerStats";
66
67
  export * as PocketItems from "./pocketItems";
67
68
  export * as PositionVelocity from "./positionVelocity";
68
69
  export * as PressurePlate from "./pressurePlate";
@@ -4,6 +4,7 @@ import {
4
4
  ControllerIndex,
5
5
  Keyboard,
6
6
  } from "isaac-typescript-definitions";
7
+ import { KEYBOARD_TO_STRING } from "../maps/keyboardToString";
7
8
  import { getEnumValues } from "./enums";
8
9
  import { copySet } from "./set";
9
10
  import { trimPrefix } from "./string";
@@ -133,6 +134,18 @@ export function isShootActionTriggeredOnAnyInput(): boolean {
133
134
  );
134
135
  }
135
136
 
136
- export function keyboardToString(keyboard: Keyboard): string {
137
- return Keyboard[keyboard] ?? "unknown";
137
+ /**
138
+ * Helper function to get the string that would be typed if someone pressed the corresponding key.
139
+ */
140
+ export function keyboardToString(
141
+ keyboard: Keyboard,
142
+ uppercase: boolean,
143
+ ): string | undefined {
144
+ const tuple = KEYBOARD_TO_STRING.get(keyboard);
145
+ if (tuple === undefined) {
146
+ return undefined;
147
+ }
148
+
149
+ const [lowercaseCharacter, uppercaseCharacter] = tuple;
150
+ return uppercase ? uppercaseCharacter : lowercaseCharacter;
138
151
  }
@@ -22,7 +22,7 @@ export function getJSONRoomDoorSlotFlags(
22
22
  const roomShapeNumber = tonumber(roomShapeString);
23
23
  if (roomShapeNumber === undefined) {
24
24
  error(
25
- `Failed to parse the "shape" property of a JSON room: ${roomShapeString}`,
25
+ `Failed to parse the "shape" field of a JSON room: ${roomShapeString}`,
26
26
  );
27
27
  }
28
28
  const roomShape = roomShapeNumber as RoomShape;
@@ -33,7 +33,7 @@ export function getJSONRoomDoorSlotFlags(
33
33
  const existsString = door.$.exists;
34
34
  if (existsString !== "True" && existsString !== "False") {
35
35
  error(
36
- `Failed to parse the "exists" property of a JSON room door: ${existsString}`,
36
+ `Failed to parse the "exists" field of a JSON room door: ${existsString}`,
37
37
  );
38
38
  }
39
39
 
@@ -44,13 +44,13 @@ export function getJSONRoomDoorSlotFlags(
44
44
  const xString = door.$.x;
45
45
  const x = tonumber(xString);
46
46
  if (x === undefined) {
47
- error(`Failed to parse the "x" property of a JSON room door: ${xString}`);
47
+ error(`Failed to parse the "x" field of a JSON room door: ${xString}`);
48
48
  }
49
49
 
50
50
  const yString = door.$.y;
51
51
  const y = tonumber(yString);
52
52
  if (y === undefined) {
53
- error(`Failed to parse the "y" property of a JSON room door: ${yString}`);
53
+ error(`Failed to parse the "y" field of a JSON room door: ${yString}`);
54
54
  }
55
55
 
56
56
  const doorSlot = getRoomShapeDoorSlot(roomShape, x, y);
@@ -9,8 +9,8 @@ export type SerializedKColor = LuaMap<string, unknown> & {
9
9
  readonly __serializedKColorBrand: symbol;
10
10
  };
11
11
 
12
- const KEYS = ["Red", "Green", "Blue", "Alpha"];
13
12
  const OBJECT_NAME = "KColor";
13
+ const KEYS = ["Red", "Green", "Blue", "Alpha"];
14
14
 
15
15
  /** Helper function to copy a `KColor` Isaac API class. */
16
16
  export function copyKColor(kColor: KColor): KColor {
@@ -84,7 +84,7 @@ export function getRandomKColor(
84
84
  return KColor(r, g, b, alpha);
85
85
  }
86
86
 
87
- /** Helper function to check if something is an instantiated KColor object. */
87
+ /** Helper function to check if something is an instantiated `KColor` object. */
88
88
  export function isKColor(object: unknown): object is KColor {
89
89
  return isIsaacAPIClassOfType(object, OBJECT_NAME);
90
90
  }
@@ -455,7 +455,7 @@ export function logUseFlags(
455
455
  * the Isaac API).
456
456
  */
457
457
  export function logUserdata(this: void, userdata: unknown): void {
458
- if (isUserdata(userdata)) {
458
+ if (!isUserdata(userdata)) {
459
459
  log("Userdata: [not userdata]");
460
460
  return;
461
461
  }
@@ -108,8 +108,8 @@ export function isAliveExceptionNPC(npc: EntityNPC): boolean {
108
108
  * that is spawned when the boss does the multi-stomp attack.
109
109
  *
110
110
  * When this attack occurs, four extra copies of Daddy Long Legs will be spawned with the same
111
- * entity type, variant, and sub-type. The `Entity.Parent` property will be undefined in this case,
112
- * so the way to tell them apart is to check for a non-undefined `Entity.SpawnerEntity` property.
111
+ * entity type, variant, and sub-type. The `Entity.Parent` field will be undefined in this case, so
112
+ * the way to tell them apart is to check for a non-undefined `Entity.SpawnerEntity` field.
113
113
  */
114
114
  export function isDaddyLongLegsChildStompEntity(npc: EntityNPC): boolean {
115
115
  return (
@@ -198,7 +198,7 @@ export function getSubPlayerParent(
198
198
 
199
199
  /**
200
200
  * Helper function to detect if a particular player is a "child" player, meaning that they have a
201
- * non-undefined `EntityPlayer.Parent` property. (For example, the Strawman Keeper.)
201
+ * non-undefined `EntityPlayer.Parent` field. (For example, the Strawman Keeper.)
202
202
  */
203
203
  export function isChildPlayer(player: EntityPlayer): boolean {
204
204
  return player.Parent !== undefined;
@@ -0,0 +1,25 @@
1
+ import { StatType } from "../enums/StatType";
2
+ import { StatTypeType } from "../interfaces/StatTypeType";
3
+
4
+ /** Helper function to get the stat for a player corresponding to the `StatType`. */
5
+ export function getPlayerStat<T extends StatType>(
6
+ player: EntityPlayer,
7
+ statType: T,
8
+ ): StatTypeType[T] {
9
+ // We can't use a switch statement here because control-flow based type analysis does not apply to
10
+ // generic type parameters.
11
+ return {
12
+ [StatType.DAMAGE]: player.Damage, // 1 << 0
13
+ [StatType.FIRE_DELAY]: player.MaxFireDelay, // 1 << 1
14
+ [StatType.SHOT_SPEED]: player.ShotSpeed, // 1 << 2
15
+ [StatType.TEAR_HEIGHT]: player.TearHeight, // 1 << 3
16
+ [StatType.TEAR_RANGE]: player.TearRange, // 1 << 3
17
+ [StatType.TEAR_FALLING_ACCELERATION]: player.TearFallingAcceleration, // 1 << 3
18
+ [StatType.TEAR_FALLING_SPEED]: player.TearFallingSpeed, // 1 << 3
19
+ [StatType.MOVE_SPEED]: player.MoveSpeed, // 1 << 4
20
+ [StatType.TEAR_FLAG]: player.TearFlags, // 1 << 5
21
+ [StatType.TEAR_COLOR]: player.TearColor, // 1 << 6
22
+ [StatType.FLYING]: player.CanFly, // 1 << 7
23
+ [StatType.LUCK]: player.Luck, // 1 << 10
24
+ }[statType];
25
+ }
@@ -48,7 +48,7 @@ export function addCollectibleCostume(
48
48
 
49
49
  /**
50
50
  * Helper function to add a stat to a player based on the `CacheFlag` provided. Call this function
51
- * from the EvaluateCache callback.
51
+ * from the `EVALUATE_CACHE` callback.
52
52
  *
53
53
  * Note that for `CacheFlag.FIRE_DELAY`, the "amount" argument will be interpreted as the tear stat
54
54
  * to add (and not the amount to mutate `EntityPlayer.MaxFireDelay` by).
@@ -15,8 +15,8 @@ export type SerializedRNG = LuaMap<string, unknown> & {
15
15
  */
16
16
  const RECOMMENDED_SHIFT_IDX = 35;
17
17
 
18
- const KEYS = ["seed"];
19
18
  const OBJECT_NAME = "RNG";
19
+ const KEYS = ["seed"];
20
20
 
21
21
  /** Helper function to copy an `RNG` Isaac API class. */
22
22
  export function copyRNG(rng: RNG): RNG {
@@ -60,7 +60,7 @@ export function getRandomSeed(): Seed {
60
60
  return safeRandomNumber as Seed;
61
61
  }
62
62
 
63
- /** Helper function to check if something is an instantiated RNG object. */
63
+ /** Helper function to check if something is an instantiated `RNG` object. */
64
64
  export function isRNG(object: unknown): object is RNG {
65
65
  return isIsaacAPIClassOfType(object, OBJECT_NAME);
66
66
  }
@@ -41,6 +41,13 @@ const ROCK_ALT_CHANCES = {
41
41
  } as const;
42
42
 
43
43
  const COIN_VELOCITY_MULTIPLIER = 2;
44
+
45
+ /** Matches the vanilla value, according to Fly's decompilation. */
46
+ const FIND_FREE_INITIAL_STEP = 70;
47
+
48
+ /** Matches the vanilla value, according to Fly's decompilation. */
49
+ const FART_RADIUS = DISTANCE_OF_GRID_TILE * 3;
50
+
44
51
  const POLYP_PROJECTILE_SPEED = 10;
45
52
  const POLYP_NUM_PROJECTILES = 6;
46
53
 
@@ -128,6 +135,8 @@ export function spawnRockAltReward(
128
135
  }
129
136
 
130
137
  function spawnRockAltRewardUrn(position: Vector, rng: RNG): boolean {
138
+ const room = game.GetRoom();
139
+
131
140
  const chance = getRandom(rng);
132
141
  let totalChance = 0;
133
142
 
@@ -171,11 +180,11 @@ function spawnRockAltRewardUrn(position: Vector, rng: RNG): boolean {
171
180
  // Since the detrimental effect is the final option, we don't need to check the chance.
172
181
  const numEnemiesChance = getRandom(rng);
173
182
  const numEnemies = numEnemiesChance < 0.5 ? 1 : 2;
174
- const length = DISTANCE_OF_GRID_TILE * 3;
175
183
  repeat(numEnemies, () => {
176
- const randomVector = getRandomVector(rng);
177
- const offset = randomVector.mul(length);
178
- const targetPos = position.add(offset);
184
+ const targetPos = room.FindFreePickupSpawnPosition(
185
+ position,
186
+ FIND_FREE_INITIAL_STEP,
187
+ );
179
188
  EntityNPC.ThrowSpider(position, undefined, targetPos, false, 0);
180
189
  });
181
190
  return true;
@@ -253,7 +262,8 @@ function spawnRockAltRewardMushroom(position: Vector, rng: RNG): boolean {
253
262
  }
254
263
 
255
264
  // Since the detrimental effect is the final option, we don't need to check the chance.
256
- spawnEffectWithSeed(EffectVariant.FART, 0, position, rng);
265
+ game.Fart(position);
266
+ game.ButterBeanFart(position, FART_RADIUS, undefined);
257
267
  return true;
258
268
  }
259
269
 
@@ -383,6 +393,8 @@ function spawnRockAltRewardPolyp(position: Vector, rng: RNG): boolean {
383
393
  }
384
394
 
385
395
  function spawnRockAltRewardBucketDownpour(position: Vector, rng: RNG): boolean {
396
+ const room = game.GetRoom();
397
+
386
398
  const chance = getRandom(rng);
387
399
  let totalChance = 0;
388
400
 
@@ -430,11 +442,12 @@ function spawnRockAltRewardBucketDownpour(position: Vector, rng: RNG): boolean {
430
442
 
431
443
  const numEnemiesChance = getRandom(rng);
432
444
  const numEnemies = numEnemiesChance < 0.5 ? 1 : 2;
433
- const jumpDistance = DISTANCE_OF_GRID_TILE * 3;
434
445
  repeat(numEnemies, () => {
435
- const randomVector = getRandomVector(rng);
436
- const offset = randomVector.mul(jumpDistance);
437
- const targetPos = position.add(offset);
446
+ const targetPos = room.FindFreePickupSpawnPosition(
447
+ position,
448
+ FIND_FREE_INITIAL_STEP,
449
+ );
450
+
438
451
  // If the room has water, Spiders will automatically be replaced with Striders.
439
452
  const spider = EntityNPC.ThrowSpider(
440
453
  position,
@@ -455,6 +468,8 @@ function spawnRockAltRewardBucketDownpour(position: Vector, rng: RNG): boolean {
455
468
  }
456
469
 
457
470
  function spawnRockAltRewardBucketDross(position: Vector, rng: RNG): boolean {
471
+ const room = game.GetRoom();
472
+
458
473
  const chance = getRandom(rng);
459
474
  let totalChance = 0;
460
475
 
@@ -502,11 +517,11 @@ function spawnRockAltRewardBucketDross(position: Vector, rng: RNG): boolean {
502
517
 
503
518
  const numEnemiesChance = getRandom(rng);
504
519
  const numEnemies = numEnemiesChance < 0.5 ? 1 : 2;
505
- const jumpDistance = DISTANCE_OF_GRID_TILE * 3;
506
520
  repeat(numEnemies, () => {
507
- const randomVector = getRandomVector(rng);
508
- const offset = randomVector.mul(jumpDistance);
509
- const targetPos = position.add(offset);
521
+ const targetPos = room.FindFreePickupSpawnPosition(
522
+ position,
523
+ FIND_FREE_INITIAL_STEP,
524
+ );
510
525
  const spider = EntityNPC.ThrowSpider(
511
526
  position,
512
527
  undefined,
@@ -31,7 +31,7 @@ export function reloadRoom(): void {
31
31
  * arguments.
32
32
  *
33
33
  * Use this function instead of invoking the `Game.StartRoomTransition` method directly so that:
34
- * - you do not forget to set `Level.LeaveDoor` property
34
+ * - you do not forget to set the `Level.LeaveDoor` field
35
35
  * - to prevent crashing on invalid room grid indexes
36
36
  * - to automatically handle Curse of the Maze
37
37
  *
@@ -50,7 +50,7 @@ import { erange, irange } from "./utils";
50
50
  /**
51
51
  * Helper function for quickly switching to a new room without playing a particular animation. Use
52
52
  * this helper function over invoking the `Game.ChangeRoom` method directly to ensure that you do
53
- * not forget to set the `LeaveDoor` property and to prevent crashing on invalid room grid indexes.
53
+ * not forget to set the `LeaveDoor` field and to prevent crashing on invalid room grid indexes.
54
54
  */
55
55
  export function changeRoom(roomGridIndex: int): void {
56
56
  const level = game.GetLevel();
@@ -498,6 +498,7 @@ export function roomUpdateSafe(): void {
498
498
  /** Helper function to set the backdrop of the current room. */
499
499
  export function setBackdrop(backdropType: BackdropType): void {
500
500
  game.ShowHallucination(0, backdropType);
501
+ sfxManager.Stop(SoundEffect.DEATH_CARD);
501
502
  }
502
503
 
503
504
  /**
@@ -34,9 +34,9 @@ export function clearSprite(sprite: Sprite, ...layerIDs: int[]): void {
34
34
  *
35
35
  * Note that this function is bugged with the Stop Watch or the Broken Watch, since using the
36
36
  * `Sprite.SetFrame` method will reset the internal accumulator used to slow down the playback speed
37
- * of the animation. (The `PlaybackSpeed` property of the sprite is not used.) Thus, it is only safe
38
- * to use this function on animations that are not slowed down by Stop Watch or Broken Watch, such
39
- * as player animations.
37
+ * of the animation. (The `PlaybackSpeed` field of the sprite is not used.) Thus, it is only safe to
38
+ * use this function on animations that are not slowed down by Stop Watch or Broken Watch, such as
39
+ * player animations.
40
40
  */
41
41
  export function getLastFrameOfAnimation(
42
42
  sprite: Sprite,