isaacscript-common 6.14.0 → 6.16.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.
- package/dist/callbacks/postGridEntityCustomCollision.d.ts +2 -0
- package/dist/callbacks/postGridEntityCustomCollision.d.ts.map +1 -0
- package/dist/callbacks/postGridEntityCustomCollision.lua +71 -0
- package/dist/callbacks/postGridEntityCustomRender.lua +0 -7
- package/dist/callbacks/postGridEntityCustomUpdate.lua +0 -7
- package/dist/callbacks/subscriptions/postGridEntityCustomBroken.d.ts +6 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomBroken.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomBroken.lua +24 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomCollision.d.ts +6 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomCollision.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomCollision.lua +29 -0
- package/dist/enums/ModCallbackCustom.d.ts +96 -62
- package/dist/enums/ModCallbackCustom.d.ts.map +1 -1
- package/dist/enums/ModCallbackCustom.lua +64 -60
- package/dist/features/customGridEntity.d.ts +5 -1
- package/dist/features/customGridEntity.d.ts.map +1 -1
- package/dist/features/customGridEntity.lua +65 -5
- package/dist/functions/collectibles.d.ts +6 -2
- package/dist/functions/collectibles.d.ts.map +1 -1
- package/dist/functions/collectibles.lua +4 -2
- package/dist/functions/color.d.ts +11 -15
- package/dist/functions/color.d.ts.map +1 -1
- package/dist/functions/color.lua +55 -74
- package/dist/functions/deepCopy.d.ts.map +1 -1
- package/dist/functions/deepCopy.lua +22 -1
- package/dist/functions/gridEntities.d.ts +0 -16
- package/dist/functions/gridEntities.d.ts.map +1 -1
- package/dist/functions/gridEntities.lua +0 -19
- package/dist/functions/isaacAPIClass.d.ts +1 -1
- package/dist/functions/isaacAPIClass.d.ts.map +1 -1
- package/dist/functions/itemPool.d.ts +10 -0
- package/dist/functions/itemPool.d.ts.map +1 -0
- package/dist/functions/itemPool.lua +116 -0
- package/dist/functions/kColor.d.ts +11 -15
- package/dist/functions/kColor.d.ts.map +1 -1
- package/dist/functions/kColor.lua +42 -61
- package/dist/functions/mergeTests.lua +2 -2
- package/dist/functions/npcs.d.ts +1 -29
- package/dist/functions/npcs.d.ts.map +1 -1
- package/dist/functions/npcs.lua +0 -45
- package/dist/functions/projectiles.d.ts +32 -0
- package/dist/functions/projectiles.d.ts.map +1 -0
- package/dist/functions/projectiles.lua +73 -0
- package/dist/functions/rng.d.ts +11 -15
- package/dist/functions/rng.d.ts.map +1 -1
- package/dist/functions/rng.lua +32 -52
- package/dist/functions/rockAlt.d.ts +26 -6
- package/dist/functions/rockAlt.d.ts.map +1 -1
- package/dist/functions/rockAlt.lua +303 -78
- package/dist/functions/saveFile.d.ts +8 -7
- package/dist/functions/saveFile.d.ts.map +1 -1
- package/dist/functions/saveFile.lua +10 -96
- package/dist/functions/serialization.d.ts +26 -7
- package/dist/functions/serialization.d.ts.map +1 -1
- package/dist/functions/serialization.lua +51 -19
- package/dist/functions/table.d.ts +2 -2
- package/dist/functions/table.lua +2 -2
- package/dist/functions/trinketGive.d.ts +13 -0
- package/dist/functions/trinketGive.d.ts.map +1 -1
- package/dist/functions/trinketGive.lua +16 -0
- package/dist/functions/tstlClass.d.ts +1 -1
- package/dist/functions/tstlClass.d.ts.map +1 -1
- package/dist/functions/vector.d.ts +11 -15
- package/dist/functions/vector.d.ts.map +1 -1
- package/dist/functions/vector.lua +36 -55
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.lua +16 -0
- package/dist/initCustomCallbacks.d.ts.map +1 -1
- package/dist/initCustomCallbacks.lua +3 -0
- package/dist/interfaces/AddCallbackParameterCustom.d.ts +4 -0
- package/dist/interfaces/AddCallbackParameterCustom.d.ts.map +1 -1
- package/dist/objects/callbackRegisterFunctions.d.ts.map +1 -1
- package/dist/objects/callbackRegisterFunctions.lua +6 -0
- package/dist/objects/isaacAPIClassTypeToFunctions.d.ts +12 -0
- package/dist/objects/isaacAPIClassTypeToFunctions.d.ts.map +1 -0
- package/dist/objects/isaacAPIClassTypeToFunctions.lua +25 -0
- package/dist/types/{private/IsaacAPIClass.d.ts → IsaacAPIClass.d.ts} +0 -0
- package/dist/types/IsaacAPIClass.d.ts.map +1 -0
- package/dist/types/{private/IsaacAPIClass.lua → IsaacAPIClass.lua} +0 -0
- package/dist/types/{private/SerializedIsaacAPIClass.d.ts → SerializedIsaacAPIClass.d.ts} +0 -0
- package/dist/types/SerializedIsaacAPIClass.d.ts.map +1 -0
- package/dist/types/{private/SerializedIsaacAPIClass.lua → SerializedIsaacAPIClass.lua} +0 -0
- package/dist/types/{private/TSTLClass.d.ts → TSTLClass.d.ts} +0 -0
- package/dist/types/TSTLClass.d.ts.map +1 -0
- package/dist/types/{private/TSTLClass.lua → TSTLClass.lua} +0 -0
- package/package.json +2 -2
- package/src/callbacks/postGridEntityCustomCollision.ts +74 -0
- package/src/callbacks/postGridEntityCustomRender.ts +1 -17
- package/src/callbacks/postGridEntityCustomUpdate.ts +1 -17
- package/src/callbacks/subscriptions/postGridEntityCustomBroken.ts +36 -0
- package/src/callbacks/subscriptions/postGridEntityCustomCollision.ts +43 -0
- package/src/enums/ModCallbackCustom.ts +38 -2
- package/src/features/customGridEntity.ts +76 -0
- package/src/functions/collectibles.ts +6 -2
- package/src/functions/color.ts +67 -87
- package/src/functions/deepCopy.ts +15 -2
- package/src/functions/gridEntities.ts +0 -23
- package/src/functions/isaacAPIClass.ts +1 -1
- package/src/functions/itemPool.ts +153 -0
- package/src/functions/kColor.ts +65 -84
- package/src/functions/mergeTests.ts +2 -2
- package/src/functions/npcs.ts +1 -58
- package/src/functions/projectiles.ts +78 -0
- package/src/functions/rng.ts +45 -65
- package/src/functions/rockAlt.ts +339 -60
- package/src/functions/saveFile.ts +13 -119
- package/src/functions/serialization.ts +81 -25
- package/src/functions/table.ts +2 -2
- package/src/functions/trinketGive.ts +21 -0
- package/src/functions/tstlClass.ts +1 -1
- package/src/functions/vector.ts +55 -74
- package/src/index.ts +2 -0
- package/src/initCustomCallbacks.ts +2 -0
- package/src/interfaces/AddCallbackParameterCustom.ts +4 -0
- package/src/objects/callbackRegisterFunctions.ts +6 -0
- package/src/objects/isaacAPIClassTypeToFunctions.ts +63 -0
- package/src/types/{private/IsaacAPIClass.ts → IsaacAPIClass.ts} +0 -0
- package/src/types/{private/SerializedIsaacAPIClass.ts → SerializedIsaacAPIClass.ts} +0 -0
- package/src/types/{private/TSTLClass.ts → TSTLClass.ts} +0 -0
- package/dist/objects/isaacAPIClassTypeToCopyFunction.d.ts +0 -6
- package/dist/objects/isaacAPIClassTypeToCopyFunction.d.ts.map +0 -1
- package/dist/objects/isaacAPIClassTypeToCopyFunction.lua +0 -13
- package/dist/objects/serializedIsaacAPIClassTypeToIdentityFunction.d.ts +0 -5
- package/dist/objects/serializedIsaacAPIClassTypeToIdentityFunction.d.ts.map +0 -1
- package/dist/objects/serializedIsaacAPIClassTypeToIdentityFunction.lua +0 -13
- package/dist/types/private/IsaacAPIClass.d.ts.map +0 -1
- package/dist/types/private/SerializedIsaacAPIClass.d.ts.map +0 -1
- package/dist/types/private/TSTLClass.d.ts.map +0 -1
- package/src/objects/isaacAPIClassTypeToCopyFunction.ts +0 -18
- package/src/objects/serializedIsaacAPIClassTypeToIdentityFunction.ts +0 -14
|
@@ -9,14 +9,12 @@ import {
|
|
|
9
9
|
} from "isaac-typescript-definitions";
|
|
10
10
|
import { game } from "../cachedClasses";
|
|
11
11
|
import { DISTANCE_OF_GRID_TILE } from "../constants";
|
|
12
|
-
import { RockAltType } from "../enums/RockAltType";
|
|
13
12
|
import { GRID_ENTITY_TYPE_TO_BROKEN_STATE_MAP } from "../maps/gridEntityTypeToBrokenStateMap";
|
|
14
13
|
import { GRID_ENTITY_XML_MAP } from "../maps/gridEntityXMLMap";
|
|
15
14
|
import {
|
|
16
15
|
DEFAULT_TOP_LEFT_WALL_GRID_INDEX,
|
|
17
16
|
ROOM_SHAPE_TO_TOP_LEFT_WALL_GRID_INDEX_MAP,
|
|
18
17
|
} from "../maps/roomShapeToTopLeftWallGridIndexMap";
|
|
19
|
-
import { BACKDROP_TYPE_TO_ROCK_ALT_TYPE } from "../objects/backdropTypeToRockAltType";
|
|
20
18
|
import { AnyGridEntity } from "../types/AnyGridEntity";
|
|
21
19
|
import { isCircleIntersectingRectangle } from "./math";
|
|
22
20
|
import { roomUpdateSafe } from "./rooms";
|
|
@@ -276,27 +274,6 @@ export function getMatchingGridEntities(
|
|
|
276
274
|
);
|
|
277
275
|
}
|
|
278
276
|
|
|
279
|
-
/**
|
|
280
|
-
* Helper function to get the alternate rock type (i.e. urn, mushroom, etc.) that the current room
|
|
281
|
-
* will have.
|
|
282
|
-
*
|
|
283
|
-
* The rock type is based on the backdrop of the room.
|
|
284
|
-
*
|
|
285
|
-
* For example, if you change the backdrop of the starting room of the run to `BackdropType.CAVES`,
|
|
286
|
-
* and then spawn `GridEntityType.ROCK_ALT`, it will be a mushroom instead of an urn. Additionally,
|
|
287
|
-
* if it is destroyed, it will generate mushroom-appropriate rewards.
|
|
288
|
-
*
|
|
289
|
-
* On the other hand, if an urn is spawned first before the backdrop is changed to
|
|
290
|
-
* `BackdropType.CAVES`, the graphic of the urn will not switch to a mushroom. However, when
|
|
291
|
-
* destroyed, the urn will still generate mushroom-appropriate rewards.
|
|
292
|
-
*/
|
|
293
|
-
export function getRockAltType(): RockAltType {
|
|
294
|
-
const room = game.GetRoom();
|
|
295
|
-
const backdropType = room.GetBackdropType();
|
|
296
|
-
|
|
297
|
-
return BACKDROP_TYPE_TO_ROCK_ALT_TYPE[backdropType];
|
|
298
|
-
}
|
|
299
|
-
|
|
300
277
|
export function getSurroundingGridEntities(
|
|
301
278
|
gridEntity: GridEntity,
|
|
302
279
|
): GridEntity[] {
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CollectibleType,
|
|
3
|
+
ItemConfigTag,
|
|
4
|
+
ItemPoolType,
|
|
5
|
+
PlayerType,
|
|
6
|
+
TrinketType,
|
|
7
|
+
} from "isaac-typescript-definitions";
|
|
8
|
+
import { game } from "../cachedClasses";
|
|
9
|
+
import { PlayerIndex } from "../types/PlayerIndex";
|
|
10
|
+
import { getCollectibleSet } from "./collectibleSet";
|
|
11
|
+
import { collectibleHasTag } from "./collectibleTag";
|
|
12
|
+
import { mapGetPlayer, mapSetPlayer } from "./playerDataStructures";
|
|
13
|
+
import { getPlayers } from "./playerIndex";
|
|
14
|
+
import { getPlayersOfType } from "./players";
|
|
15
|
+
import { repeat } from "./utils";
|
|
16
|
+
|
|
17
|
+
const COLLECTIBLES_THAT_AFFECT_ITEM_POOLS: readonly CollectibleType[] = [
|
|
18
|
+
CollectibleType.CHAOS, // 402
|
|
19
|
+
CollectibleType.SACRED_ORB, // 691
|
|
20
|
+
CollectibleType.TMTRAINER, // 721
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const TRINKETS_THAT_AFFECT_ITEM_POOLS: readonly TrinketType[] = [
|
|
24
|
+
TrinketType.NO,
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Helper function to see if the given collectible is still present in the given item pool.
|
|
29
|
+
*
|
|
30
|
+
* If the collectible is non-offensive, any Tainted Losts will be temporarily changed to Isaac and
|
|
31
|
+
* then changed back. (This is because Tainted Lost is not able to retrieve non-offensive
|
|
32
|
+
* collectibles from item pools).
|
|
33
|
+
*/
|
|
34
|
+
export function isCollectibleInItemPool(
|
|
35
|
+
collectibleType: CollectibleType,
|
|
36
|
+
itemPoolType: ItemPoolType,
|
|
37
|
+
): boolean {
|
|
38
|
+
// On Tainted Lost, it is impossible to retrieve non-offensive collectibles from pools, so we
|
|
39
|
+
// temporarily change the character to Isaac.
|
|
40
|
+
const taintedLosts = getPlayersOfType(PlayerType.THE_LOST_B);
|
|
41
|
+
const isOffensive = collectibleHasTag(
|
|
42
|
+
collectibleType,
|
|
43
|
+
ItemConfigTag.OFFENSIVE,
|
|
44
|
+
);
|
|
45
|
+
let changedPlayerTypes = false;
|
|
46
|
+
if (!isOffensive) {
|
|
47
|
+
changedPlayerTypes = true;
|
|
48
|
+
for (const player of taintedLosts) {
|
|
49
|
+
player.ChangePlayerType(PlayerType.ISAAC);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const [removedItemsMap, removedTrinketsMap] =
|
|
54
|
+
removeItemsAndTrinketsThatAffectItemPools();
|
|
55
|
+
|
|
56
|
+
// Blacklist every collectible in the game except for the provided collectible.
|
|
57
|
+
const itemPool = game.GetItemPool();
|
|
58
|
+
const collectibleSet = getCollectibleSet();
|
|
59
|
+
for (const collectibleTypeInSet of collectibleSet.values()) {
|
|
60
|
+
if (collectibleTypeInSet !== collectibleType) {
|
|
61
|
+
itemPool.AddRoomBlacklist(collectibleTypeInSet);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Get a collectible from the pool and see if it is the intended collectible. (We can use any
|
|
66
|
+
// arbitrary value as the seed since it should not influence the result.)
|
|
67
|
+
const retrievedCollectibleType = itemPool.GetCollectible(
|
|
68
|
+
itemPoolType,
|
|
69
|
+
false,
|
|
70
|
+
1 as Seed,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const collectibleUnlocked = retrievedCollectibleType === collectibleType;
|
|
74
|
+
|
|
75
|
+
// Reset the blacklist
|
|
76
|
+
itemPool.ResetRoomBlacklist();
|
|
77
|
+
|
|
78
|
+
restoreItemsAndTrinketsThatAffectItemPools(
|
|
79
|
+
removedItemsMap,
|
|
80
|
+
removedTrinketsMap,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// Change any players back to Tainted Lost, if necessary.
|
|
84
|
+
if (changedPlayerTypes) {
|
|
85
|
+
for (const player of taintedLosts) {
|
|
86
|
+
player.ChangePlayerType(PlayerType.THE_LOST_B);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return collectibleUnlocked;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Before checking the item pools, remove any collectibles or trinkets that would affect the
|
|
95
|
+
* retrieved collectible types.
|
|
96
|
+
*/
|
|
97
|
+
function removeItemsAndTrinketsThatAffectItemPools(): [
|
|
98
|
+
removedItemsMap: Map<PlayerIndex, CollectibleType[]>,
|
|
99
|
+
removedTrinketsMap: Map<PlayerIndex, TrinketType[]>,
|
|
100
|
+
] {
|
|
101
|
+
const removedItemsMap = new Map<PlayerIndex, CollectibleType[]>();
|
|
102
|
+
const removedTrinketsMap = new Map<PlayerIndex, TrinketType[]>();
|
|
103
|
+
for (const player of getPlayers()) {
|
|
104
|
+
const removedItems: CollectibleType[] = [];
|
|
105
|
+
for (const itemToRemove of COLLECTIBLES_THAT_AFFECT_ITEM_POOLS) {
|
|
106
|
+
if (player.HasCollectible(itemToRemove)) {
|
|
107
|
+
const numCollectibles = player.GetCollectibleNum(itemToRemove);
|
|
108
|
+
repeat(numCollectibles, () => {
|
|
109
|
+
player.RemoveCollectible(itemToRemove);
|
|
110
|
+
removedItems.push(itemToRemove);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
mapSetPlayer(removedItemsMap, player, removedItems);
|
|
116
|
+
|
|
117
|
+
const removedTrinkets: TrinketType[] = [];
|
|
118
|
+
for (const trinketToRemove of TRINKETS_THAT_AFFECT_ITEM_POOLS) {
|
|
119
|
+
if (player.HasTrinket(trinketToRemove)) {
|
|
120
|
+
const numTrinkets = player.GetTrinketMultiplier(trinketToRemove);
|
|
121
|
+
repeat(numTrinkets, () => {
|
|
122
|
+
player.TryRemoveTrinket(trinketToRemove);
|
|
123
|
+
removedTrinkets.push(trinketToRemove);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
mapSetPlayer(removedTrinketsMap, player, removedTrinkets);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return [removedItemsMap, removedTrinketsMap];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function restoreItemsAndTrinketsThatAffectItemPools(
|
|
135
|
+
removedItemsMap: Map<PlayerIndex, CollectibleType[]>,
|
|
136
|
+
removedTrinketsMap: Map<PlayerIndex, TrinketType[]>,
|
|
137
|
+
) {
|
|
138
|
+
for (const player of getPlayers()) {
|
|
139
|
+
const removedItems = mapGetPlayer(removedItemsMap, player);
|
|
140
|
+
if (removedItems !== undefined) {
|
|
141
|
+
for (const collectibleType of removedItems) {
|
|
142
|
+
player.AddCollectible(collectibleType, 0, false); // Prevent Chaos from spawning pickups
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const removedTrinkets = mapGetPlayer(removedTrinketsMap, player);
|
|
147
|
+
if (removedTrinkets !== undefined) {
|
|
148
|
+
for (const trinketType of removedTrinkets) {
|
|
149
|
+
player.AddTrinket(trinketType, false);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
package/src/functions/kColor.ts
CHANGED
|
@@ -1,103 +1,67 @@
|
|
|
1
1
|
import { SerializationBrand } from "../enums/private/SerializationBrand";
|
|
2
|
-
import { SerializationType } from "../enums/SerializationType";
|
|
3
2
|
import { isaacAPIClassEquals, isIsaacAPIClassOfType } from "./isaacAPIClass";
|
|
4
3
|
import { getRandom } from "./random";
|
|
5
4
|
import { getRandomSeed, isRNG, newRNG } from "./rng";
|
|
6
5
|
import { copyValuesToTable, getNumbersFromTable, tableHasKeys } from "./table";
|
|
7
6
|
import { isTable } from "./types";
|
|
8
7
|
|
|
9
|
-
type SerializedKColor = LuaMap<string, unknown> & {
|
|
8
|
+
export type SerializedKColor = LuaMap<string, unknown> & {
|
|
10
9
|
readonly __serializedKColorBrand: symbol;
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
interface CopyKColorReturn {
|
|
14
|
-
[SerializationType.NONE]: KColor;
|
|
15
|
-
[SerializationType.SERIALIZE]: SerializedKColor;
|
|
16
|
-
[SerializationType.DESERIALIZE]: KColor;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
12
|
const KEYS = ["Red", "Green", "Blue", "Alpha"];
|
|
20
13
|
const OBJECT_NAME = "KColor";
|
|
21
14
|
|
|
15
|
+
/** Helper function to copy a `KColor` Isaac API class. */
|
|
16
|
+
export function copyKColor(kColor: KColor): KColor {
|
|
17
|
+
if (!isKColor(kColor)) {
|
|
18
|
+
error(
|
|
19
|
+
`Failed to copy a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return KColor(kColor.Red, kColor.Green, kColor.Blue, kColor.Alpha);
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
/**
|
|
23
|
-
* Helper function to
|
|
24
|
-
*
|
|
25
|
-
* @param kColor The KColor object to copy. In the case of deserialization, this will actually be a
|
|
26
|
-
* Lua table instead of an instantiated KColor class.
|
|
27
|
-
* @param serializationType Default is `SerializationType.NONE`.
|
|
27
|
+
* Helper function to convert a `SerializedKColor` object to a normal `KColor` object. (This is used
|
|
28
|
+
* by the save data manager when reading data from the "save#.dat" file.)
|
|
28
29
|
*/
|
|
29
|
-
export function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return KColor(kColor.Red, kColor.Green, kColor.Blue, kColor.Alpha);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
case SerializationType.SERIALIZE: {
|
|
52
|
-
if (!isKColor(kColor)) {
|
|
53
|
-
error(
|
|
54
|
-
`Failed to serialize a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const kColorTable = new LuaMap<string, unknown>();
|
|
59
|
-
copyValuesToTable(kColor, KEYS, kColorTable);
|
|
60
|
-
kColorTable.set(SerializationBrand.K_COLOR, "");
|
|
61
|
-
return kColorTable as SerializedKColor;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
case SerializationType.DESERIALIZE: {
|
|
65
|
-
if (!isTable(kColor)) {
|
|
66
|
-
error(
|
|
67
|
-
`Failed to deserialize a ${OBJECT_NAME} object since the provided object was not a Lua table.`,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const [r, g, b, a] = getNumbersFromTable(
|
|
72
|
-
kColor as LuaMap<string, unknown>,
|
|
73
|
-
OBJECT_NAME,
|
|
74
|
-
...KEYS,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
if (r === undefined) {
|
|
78
|
-
error(
|
|
79
|
-
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: r`,
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
if (g === undefined) {
|
|
83
|
-
error(
|
|
84
|
-
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: g`,
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
if (b === undefined) {
|
|
88
|
-
error(
|
|
89
|
-
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: b`,
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
if (a === undefined) {
|
|
93
|
-
error(
|
|
94
|
-
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: a`,
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return KColor(r, g, b, a);
|
|
99
|
-
}
|
|
30
|
+
export function deserializeKColor(kColor: SerializedKColor): KColor {
|
|
31
|
+
if (!isTable(kColor)) {
|
|
32
|
+
error(
|
|
33
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object was not a Lua table.`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const [r, g, b, a] = getNumbersFromTable(
|
|
38
|
+
kColor as LuaMap<string, unknown>,
|
|
39
|
+
OBJECT_NAME,
|
|
40
|
+
...KEYS,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (r === undefined) {
|
|
44
|
+
error(
|
|
45
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: Red`,
|
|
46
|
+
);
|
|
100
47
|
}
|
|
48
|
+
if (g === undefined) {
|
|
49
|
+
error(
|
|
50
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: Green`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (b === undefined) {
|
|
54
|
+
error(
|
|
55
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: Blue`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (a === undefined) {
|
|
59
|
+
error(
|
|
60
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: Alpha`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return KColor(r, g, b, a);
|
|
101
65
|
}
|
|
102
66
|
|
|
103
67
|
/**
|
|
@@ -144,3 +108,20 @@ export function isSerializedKColor(
|
|
|
144
108
|
export function kColorEquals(kColor1: KColor, kColor2: KColor): boolean {
|
|
145
109
|
return isaacAPIClassEquals(kColor1, kColor2, KEYS);
|
|
146
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Helper function to convert a `KColor` object to a `SerializedKColor` object. (This is used by the
|
|
114
|
+
* save data manager when writing data from the "save#.dat" file.)
|
|
115
|
+
*/
|
|
116
|
+
export function serializeKColor(kColor: KColor): SerializedKColor {
|
|
117
|
+
if (!isKColor(kColor)) {
|
|
118
|
+
error(
|
|
119
|
+
`Failed to serialize a ${OBJECT_NAME} object since the provided object was not a userdata ${OBJECT_NAME} class.`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const kColorTable = new LuaMap<string, unknown>();
|
|
124
|
+
copyValuesToTable(kColor, KEYS, kColorTable);
|
|
125
|
+
kColorTable.set(SerializationBrand.K_COLOR, "");
|
|
126
|
+
return kColorTable as SerializedKColor;
|
|
127
|
+
}
|
|
@@ -5,7 +5,7 @@ import { deepCopy } from "./deepCopy";
|
|
|
5
5
|
import { log } from "./log";
|
|
6
6
|
import { isRNG, newRNG } from "./rng";
|
|
7
7
|
import { isSerializedIsaacAPIClass } from "./serialization";
|
|
8
|
-
import {
|
|
8
|
+
import { isVector, serializeVector } from "./vector";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Run the suite of tests that prove that the "merge" function works properly. (This function is not
|
|
@@ -92,7 +92,7 @@ function oldTableHasSerializedIsaacAPIClass() {
|
|
|
92
92
|
const y = 60;
|
|
93
93
|
const vector = Vector(x, y);
|
|
94
94
|
|
|
95
|
-
const vectorSerialized =
|
|
95
|
+
const vectorSerialized = serializeVector(vector);
|
|
96
96
|
if (!isSerializedIsaacAPIClass(vectorSerialized)) {
|
|
97
97
|
error(
|
|
98
98
|
'The "isSerializedIsaacAPIClass" function says that a serialized vector is not serialized.',
|
package/src/functions/npcs.ts
CHANGED
|
@@ -11,13 +11,11 @@ import {
|
|
|
11
11
|
MotherVariant,
|
|
12
12
|
NpcState,
|
|
13
13
|
PeepVariant,
|
|
14
|
-
ProjectilesMode,
|
|
15
14
|
RaglingVariant,
|
|
16
15
|
VisVariant,
|
|
17
16
|
} from "isaac-typescript-definitions";
|
|
18
17
|
import { EGGY_STATE_FRAME_OF_FINAL_SPIDER } from "../constants";
|
|
19
|
-
import {
|
|
20
|
-
import { getNPCs, getProjectiles } from "./entitiesSpecific";
|
|
18
|
+
import { getNPCs } from "./entitiesSpecific";
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Used to filter out certain NPCs when determining of an NPC is "alive" and/or should keep the
|
|
@@ -46,33 +44,6 @@ const NON_ALIVE_NPCS_TYPE_VARIANT_SUBTYPE: ReadonlySet<string> = new Set([
|
|
|
46
44
|
`${EntityType.MOTHER}.${MotherVariant.MOTHER_1}.${MotherSubType.PHASE_2}`, // 912
|
|
47
45
|
]);
|
|
48
46
|
|
|
49
|
-
/**
|
|
50
|
-
* Helper function to make an NPC fire a projectile. Returns the fired projectile. Use this function
|
|
51
|
-
* instead of the `EntityNPC.FireProjectiles` method, since that returns void.
|
|
52
|
-
*
|
|
53
|
-
* @param npc The NPC to fire the projectile from.
|
|
54
|
-
* @param position The staring position of the projectile.
|
|
55
|
-
* @param velocity The starting velocity of the projectile.
|
|
56
|
-
* @param projectilesMode The mode of the projectile. Optional. Default is
|
|
57
|
-
* `ProjectilesMode.ONE_PROJECTILE`.
|
|
58
|
-
* @param projectileParams The parameters of the projectile. Optional. Default is
|
|
59
|
-
* `ProjectileParams()`.
|
|
60
|
-
* @returns The fired projectile.
|
|
61
|
-
*/
|
|
62
|
-
export function fireProjectiles(
|
|
63
|
-
npc: EntityNPC,
|
|
64
|
-
position: Vector,
|
|
65
|
-
velocity: Vector,
|
|
66
|
-
projectilesMode: ProjectilesMode = ProjectilesMode.ONE_PROJECTILE,
|
|
67
|
-
projectileParams: ProjectileParams = ProjectileParams(),
|
|
68
|
-
): EntityProjectile[] {
|
|
69
|
-
const oldProjectiles = getProjectiles(projectileParams.Variant);
|
|
70
|
-
npc.FireProjectiles(position, velocity, projectilesMode, projectileParams);
|
|
71
|
-
const newProjectiles = getProjectiles(projectileParams.Variant);
|
|
72
|
-
|
|
73
|
-
return getFilteredNewEntities(oldProjectiles, newProjectiles);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
47
|
/**
|
|
77
48
|
* Helper function to get all of the non-dead NPCs in the room.
|
|
78
49
|
*
|
|
@@ -149,31 +120,3 @@ export function isRaglingDeathPatch(npc: EntityNPC): boolean {
|
|
|
149
120
|
npc.State === NpcState.SPECIAL
|
|
150
121
|
);
|
|
151
122
|
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* The base game `EntityNPC.FireProjectiles` method does not return anything, which is a problem in
|
|
155
|
-
* situations where you need to work with the fired projectiles. This function runs that method, and
|
|
156
|
-
* then returns the projectiles that were spawned.
|
|
157
|
-
*
|
|
158
|
-
* @param npc The EntityNPC firing projectiles.
|
|
159
|
-
* @param position The starting position of the projectiles.
|
|
160
|
-
* @param velocity The starting velocity of the projectiles.
|
|
161
|
-
* @param projectilesMode A ProjectilesMode enum value defining how to fire the projectiles.
|
|
162
|
-
* @param projectileParams A ProjectileParams object containing various parameters for the
|
|
163
|
-
* projectiles.
|
|
164
|
-
* @returns An array of EntityProjectiles containing all fired projectiles.
|
|
165
|
-
*/
|
|
166
|
-
export function npcFireProjectiles(
|
|
167
|
-
npc: EntityNPC,
|
|
168
|
-
position: Vector,
|
|
169
|
-
velocity: Vector,
|
|
170
|
-
projectilesMode: ProjectilesMode,
|
|
171
|
-
projectileParams: ProjectileParams,
|
|
172
|
-
): EntityProjectile[] {
|
|
173
|
-
const oldEntities = getProjectiles();
|
|
174
|
-
npc.FireProjectiles(position, velocity, projectilesMode, projectileParams);
|
|
175
|
-
const newEntities = getProjectiles();
|
|
176
|
-
const filteredNewEntities = getFilteredNewEntities(oldEntities, newEntities);
|
|
177
|
-
|
|
178
|
-
return filteredNewEntities;
|
|
179
|
-
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EntityFlag,
|
|
3
|
+
EntityType,
|
|
4
|
+
ProjectilesMode,
|
|
5
|
+
} from "isaac-typescript-definitions";
|
|
6
|
+
import { getFilteredNewEntities } from "./entities";
|
|
7
|
+
import { getProjectiles, spawnNPC } from "./entitiesSpecific";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helper function to make an NPC fire one or more projectiles. Returns the fired projectile(s).
|
|
11
|
+
*
|
|
12
|
+
* Use this function instead of the `EntityNPC.FireProjectiles` method if you need to modify or
|
|
13
|
+
* access the `EntityProjectile` objects after they are fired, since this function returns the
|
|
14
|
+
* objects in an array.
|
|
15
|
+
*
|
|
16
|
+
* @param npc The NPC to fire the projectile(s) from. You can also pass undefined if you do not want
|
|
17
|
+
* the projectile(s) to come from anything in particular.
|
|
18
|
+
* @param position The staring position of the projectile(s).
|
|
19
|
+
* @param velocity The starting velocity of the projectile(s).
|
|
20
|
+
* @param projectilesMode Optional. The mode of the projectile(s). Default is
|
|
21
|
+
* `ProjectilesMode.ONE_PROJECTILE`.
|
|
22
|
+
* @param projectileParams Optional. The parameters of the projectile(s). Default is
|
|
23
|
+
* `ProjectileParams()`.
|
|
24
|
+
* @returns The fired projectile(s).
|
|
25
|
+
*/
|
|
26
|
+
export function fireProjectiles(
|
|
27
|
+
npc: EntityNPC | undefined,
|
|
28
|
+
position: Vector,
|
|
29
|
+
velocity: Vector,
|
|
30
|
+
projectilesMode: ProjectilesMode = ProjectilesMode.ONE_PROJECTILE,
|
|
31
|
+
projectileParams: ProjectileParams = ProjectileParams(),
|
|
32
|
+
): EntityProjectile[] {
|
|
33
|
+
const oldProjectiles = getProjectiles(projectileParams.Variant);
|
|
34
|
+
|
|
35
|
+
let spawnedFly = false;
|
|
36
|
+
if (npc === undefined) {
|
|
37
|
+
// Since the `EntityNPC.FireProjectiles` method is not static, we arbitrarily spawn a fly.
|
|
38
|
+
spawnedFly = true;
|
|
39
|
+
npc = spawnNPC(EntityType.FLY, 0, 0, position);
|
|
40
|
+
npc.Visible = false;
|
|
41
|
+
npc.ClearEntityFlags(EntityFlag.APPEAR);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
npc.FireProjectiles(position, velocity, projectilesMode, projectileParams);
|
|
45
|
+
const newProjectiles = getProjectiles(projectileParams.Variant);
|
|
46
|
+
|
|
47
|
+
if (spawnedFly) {
|
|
48
|
+
npc.Remove();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return getFilteredNewEntities(oldProjectiles, newProjectiles);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Helper function to spawn projectiles in a circle around a position. Under the hood, this
|
|
56
|
+
* leverages `ProjectileMode.N_PROJECTILES_IN_CIRCLE`.
|
|
57
|
+
*
|
|
58
|
+
* @param npc The NPC to fire the projectile(s) from. You can also pass undefined if you do not want
|
|
59
|
+
* the projectile(s) to come from anything in particular.
|
|
60
|
+
* @param position The staring position of the projectile(s).
|
|
61
|
+
* @param speed The speed of the projectile(s).
|
|
62
|
+
* @param numProjectiles The amount of projectiles to spawn.
|
|
63
|
+
* @returns The fired projectile(s).
|
|
64
|
+
*/
|
|
65
|
+
export function fireProjectilesInCircle(
|
|
66
|
+
npc: EntityNPC | undefined,
|
|
67
|
+
position: Vector,
|
|
68
|
+
speed: float,
|
|
69
|
+
numProjectiles: int,
|
|
70
|
+
): EntityProjectile[] {
|
|
71
|
+
const velocity = Vector(speed, numProjectiles);
|
|
72
|
+
return fireProjectiles(
|
|
73
|
+
npc,
|
|
74
|
+
position,
|
|
75
|
+
velocity,
|
|
76
|
+
ProjectilesMode.N_PROJECTILES_IN_CIRCLE,
|
|
77
|
+
);
|
|
78
|
+
}
|