isaacscript-common 44.0.0 → 44.1.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.
- package/dist/index.rollup.d.ts +12 -4
- package/dist/isaacscript-common.lua +5334 -5211
- package/dist/src/classes/features/other/ItemPoolDetection.d.ts.map +1 -1
- package/dist/src/classes/features/other/ItemPoolDetection.lua +2 -1
- package/dist/src/classes/features/other/Pause.lua +2 -2
- package/dist/src/classes/features/other/extraConsoleCommands/commands.lua +4 -3
- package/dist/src/functions/characters.d.ts +9 -2
- package/dist/src/functions/characters.d.ts.map +1 -1
- package/dist/src/functions/characters.lua +13 -4
- package/dist/src/functions/charge.lua +2 -2
- package/dist/src/functions/playerCollectibles.d.ts +127 -0
- package/dist/src/functions/playerCollectibles.d.ts.map +1 -0
- package/dist/src/functions/playerCollectibles.lua +308 -0
- package/dist/src/functions/playerHealth.d.ts.map +1 -1
- package/dist/src/functions/playerHealth.lua +3 -2
- package/dist/src/functions/playerTrinkets.d.ts +69 -0
- package/dist/src/functions/playerTrinkets.d.ts.map +1 -0
- package/dist/src/functions/playerTrinkets.lua +160 -0
- package/dist/src/functions/players.d.ts +5 -166
- package/dist/src/functions/players.d.ts.map +1 -1
- package/dist/src/functions/players.lua +20 -389
- package/dist/src/functions/trinketGive.lua +2 -2
- package/dist/src/functions/trinkets.d.ts +0 -30
- package/dist/src/functions/trinkets.d.ts.map +1 -1
- package/dist/src/functions/trinkets.lua +0 -71
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.lua +16 -0
- package/dist/src/objects/{characterStartingCollectibles.d.ts → characterStartingCollectibleTypes.d.ts} +2 -2
- package/dist/src/objects/characterStartingCollectibleTypes.d.ts.map +1 -0
- package/dist/src/objects/{characterStartingCollectibles.lua → characterStartingCollectibleTypes.lua} +1 -1
- package/dist/src/objects/characterStartingTrinketTypes.d.ts +46 -0
- package/dist/src/objects/characterStartingTrinketTypes.d.ts.map +1 -0
- package/dist/src/objects/characterStartingTrinketTypes.lua +49 -0
- package/package.json +1 -1
- package/src/classes/features/other/ItemPoolDetection.ts +2 -4
- package/src/classes/features/other/Pause.ts +1 -1
- package/src/classes/features/other/extraConsoleCommands/commands.ts +3 -3
- package/src/functions/characters.ts +20 -4
- package/src/functions/charge.ts +1 -1
- package/src/functions/playerCollectibles.ts +372 -0
- package/src/functions/playerHealth.ts +2 -6
- package/src/functions/playerTrinkets.ts +184 -0
- package/src/functions/players.ts +16 -481
- package/src/functions/trinketGive.ts +1 -1
- package/src/functions/trinkets.ts +1 -84
- package/src/index.ts +2 -0
- package/src/objects/{characterStartingCollectibles.ts → characterStartingCollectibleTypes.ts} +1 -1
- package/src/objects/characterStartingTrinketTypes.ts +129 -0
- package/dist/src/objects/characterStartingCollectibles.d.ts.map +0 -1
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActiveSlot,
|
|
3
|
+
CollectibleType,
|
|
4
|
+
PlayerType,
|
|
5
|
+
} from "isaac-typescript-definitions";
|
|
6
|
+
import { ACTIVE_SLOT_VALUES } from "../arrays/cachedEnumValues";
|
|
7
|
+
import { game, itemConfig } from "../core/cachedClasses";
|
|
8
|
+
import { ReadonlySet } from "../types/ReadonlySet";
|
|
9
|
+
import { sumArray } from "./array";
|
|
10
|
+
import { getCollectibleMaxCharges } from "./collectibles";
|
|
11
|
+
import { getAllPlayers, getPlayers } from "./playerIndex";
|
|
12
|
+
import { isCharacter } from "./players";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Helper function to add one or more collectibles to a player.
|
|
16
|
+
*
|
|
17
|
+
* This function is variadic, meaning that you can supply as many collectible types as you want to
|
|
18
|
+
* add.
|
|
19
|
+
*/
|
|
20
|
+
export function addCollectible(
|
|
21
|
+
player: EntityPlayer,
|
|
22
|
+
...collectibleTypes: CollectibleType[]
|
|
23
|
+
): void {
|
|
24
|
+
for (const collectibleType of collectibleTypes) {
|
|
25
|
+
player.AddCollectible(collectibleType);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function addCollectibleCostume(
|
|
30
|
+
player: EntityPlayer,
|
|
31
|
+
collectibleType: CollectibleType,
|
|
32
|
+
): void {
|
|
33
|
+
const itemConfigItem = itemConfig.GetCollectible(collectibleType);
|
|
34
|
+
if (itemConfigItem === undefined) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
player.AddCostume(itemConfigItem, false);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Helper function to check to see if any player has a particular collectible.
|
|
43
|
+
*
|
|
44
|
+
* @param collectibleType The collectible type to check for.
|
|
45
|
+
* @param ignoreModifiers If set to true, only counts collectibles the player actually owns and
|
|
46
|
+
* ignores effects granted by items like Zodiac, 3 Dollar Bill and Lemegeton.
|
|
47
|
+
* Default is false.
|
|
48
|
+
*/
|
|
49
|
+
export function anyPlayerHasCollectible(
|
|
50
|
+
collectibleType: CollectibleType,
|
|
51
|
+
ignoreModifiers?: boolean,
|
|
52
|
+
): boolean {
|
|
53
|
+
const players = getAllPlayers();
|
|
54
|
+
|
|
55
|
+
return players.some((player) =>
|
|
56
|
+
player.HasCollectible(collectibleType, ignoreModifiers),
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Helper function to find the active slots that the player has the corresponding collectible type
|
|
62
|
+
* in. Returns an empty array if the player does not have the collectible in any active slot.
|
|
63
|
+
*/
|
|
64
|
+
export function getActiveItemSlots(
|
|
65
|
+
player: EntityPlayer,
|
|
66
|
+
collectibleType: CollectibleType,
|
|
67
|
+
): ActiveSlot[] {
|
|
68
|
+
return ACTIVE_SLOT_VALUES.filter((activeSlot) => {
|
|
69
|
+
const activeItem = player.GetActiveItem(activeSlot);
|
|
70
|
+
return activeItem === collectibleType;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Helper function to return the total amount of collectibles that a player has that match the
|
|
76
|
+
* collectible type(s) provided.
|
|
77
|
+
*
|
|
78
|
+
* This function is variadic, meaning that you can specify N collectible types.
|
|
79
|
+
*
|
|
80
|
+
* Note that this will filter out non-real collectibles like Lilith's Incubus.
|
|
81
|
+
*/
|
|
82
|
+
export function getPlayerCollectibleCount(
|
|
83
|
+
player: EntityPlayer,
|
|
84
|
+
...collectibleTypes: CollectibleType[]
|
|
85
|
+
): int {
|
|
86
|
+
let numCollectibles = 0;
|
|
87
|
+
for (const collectibleType of collectibleTypes) {
|
|
88
|
+
// We specify "true" as the second argument to filter out things like Lilith's Incubus.
|
|
89
|
+
numCollectibles += player.GetCollectibleNum(collectibleType, true);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return numCollectibles;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Helper function to get only the players that have a certain collectible.
|
|
97
|
+
*
|
|
98
|
+
* This function is variadic, meaning that you can supply as many collectible types as you want to
|
|
99
|
+
* check for. It only returns the players that have all of the collectibles.
|
|
100
|
+
*/
|
|
101
|
+
export function getPlayersWithCollectible(
|
|
102
|
+
...collectibleTypes: CollectibleType[]
|
|
103
|
+
): EntityPlayer[] {
|
|
104
|
+
const players = getPlayers();
|
|
105
|
+
|
|
106
|
+
return players.filter((player) =>
|
|
107
|
+
collectibleTypes.every((collectibleType) =>
|
|
108
|
+
player.HasCollectible(collectibleType),
|
|
109
|
+
),
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Returns the total number of collectibles amongst all players. For example, if player 1 has 1 Sad
|
|
115
|
+
* Onion and player 2 has 2 Sad Onions, then this function would return 3.
|
|
116
|
+
*
|
|
117
|
+
* Note that this will filter out non-real collectibles like Lilith's Incubus.
|
|
118
|
+
*/
|
|
119
|
+
export function getTotalPlayerCollectibles(
|
|
120
|
+
collectibleType: CollectibleType,
|
|
121
|
+
): int {
|
|
122
|
+
const players = getPlayers();
|
|
123
|
+
const numCollectiblesArray = players.map((player) =>
|
|
124
|
+
// We specify "true" as the second argument to filter out things like Lilith's Incubus.
|
|
125
|
+
player.GetCollectibleNum(collectibleType, true),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return sumArray(numCollectiblesArray);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Helper function to check to see if a player has one or more collectibles.
|
|
133
|
+
*
|
|
134
|
+
* This function is variadic, meaning that you can supply as many collectible types as you want to
|
|
135
|
+
* check for. Returns true if the player has any of the supplied collectible types.
|
|
136
|
+
*
|
|
137
|
+
* This function always passes `false` to the `ignoreModifiers` argument.
|
|
138
|
+
*/
|
|
139
|
+
export function hasCollectible(
|
|
140
|
+
player: EntityPlayer,
|
|
141
|
+
...collectibleTypes: CollectibleType[]
|
|
142
|
+
): boolean {
|
|
143
|
+
return collectibleTypes.some((collectibleType) =>
|
|
144
|
+
player.HasCollectible(collectibleType),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Helper function to check to see if a player has a specific collectible in one or more active
|
|
150
|
+
* slots.
|
|
151
|
+
*
|
|
152
|
+
* This function is variadic, meaning that you can specify as many active slots as you want to check
|
|
153
|
+
* for. This function will return true if the collectible type is located in any of the active slots
|
|
154
|
+
* provided.
|
|
155
|
+
*/
|
|
156
|
+
export function hasCollectibleInActiveSlot(
|
|
157
|
+
player: EntityPlayer,
|
|
158
|
+
collectibleType: CollectibleType,
|
|
159
|
+
...activeSlots: ActiveSlot[]
|
|
160
|
+
): boolean {
|
|
161
|
+
const matchingActiveSlotsSet = new ReadonlySet(activeSlots);
|
|
162
|
+
const activeItemSlots = getActiveItemSlots(player, collectibleType);
|
|
163
|
+
|
|
164
|
+
return activeItemSlots.some((activeSlot) =>
|
|
165
|
+
matchingActiveSlotsSet.has(activeSlot),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Returns whether the player can hold an additional active item, beyond what they are currently
|
|
171
|
+
* carrying. This takes the Schoolbag into account.
|
|
172
|
+
*
|
|
173
|
+
* If the player is the Tainted Soul, this always returns false, since that character cannot pick up
|
|
174
|
+
* items. (Only Tainted Forgotten can pick up items.)
|
|
175
|
+
*/
|
|
176
|
+
export function hasOpenActiveItemSlot(player: EntityPlayer): boolean {
|
|
177
|
+
if (isCharacter(player, PlayerType.SOUL_B)) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const activeItemPrimary = player.GetActiveItem(ActiveSlot.PRIMARY);
|
|
182
|
+
const activeItemSecondary = player.GetActiveItem(ActiveSlot.SECONDARY);
|
|
183
|
+
const hasSchoolbag = player.HasCollectible(CollectibleType.SCHOOLBAG);
|
|
184
|
+
|
|
185
|
+
if (hasSchoolbag) {
|
|
186
|
+
return (
|
|
187
|
+
activeItemPrimary === CollectibleType.NULL ||
|
|
188
|
+
activeItemSecondary === CollectibleType.NULL
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return activeItemPrimary === CollectibleType.NULL;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Helper function to check if the active slot of a particular player is empty.
|
|
197
|
+
*
|
|
198
|
+
* @param player The player to check.
|
|
199
|
+
* @param activeSlot Optional. The active slot to check. Default is `ActiveSlot.PRIMARY`.
|
|
200
|
+
*/
|
|
201
|
+
export function isActiveSlotEmpty(
|
|
202
|
+
player: EntityPlayer,
|
|
203
|
+
activeSlot = ActiveSlot.PRIMARY,
|
|
204
|
+
): boolean {
|
|
205
|
+
const activeCollectibleType = player.GetActiveItem(activeSlot);
|
|
206
|
+
return activeCollectibleType === CollectibleType.NULL;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Helper function to remove all of the active items from a player. This includes the Schoolbag item
|
|
211
|
+
* and any pocket actives.
|
|
212
|
+
*/
|
|
213
|
+
export function removeAllActiveItems(player: EntityPlayer): void {
|
|
214
|
+
for (const activeSlot of ACTIVE_SLOT_VALUES) {
|
|
215
|
+
const collectibleType = player.GetActiveItem(activeSlot);
|
|
216
|
+
if (collectibleType === CollectibleType.NULL) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let stillHasCollectible: boolean;
|
|
221
|
+
do {
|
|
222
|
+
player.RemoveCollectible(collectibleType);
|
|
223
|
+
stillHasCollectible = player.HasCollectible(collectibleType);
|
|
224
|
+
} while (stillHasCollectible);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Helper function to remove one or more collectibles to a player.
|
|
230
|
+
*
|
|
231
|
+
* This function is variadic, meaning that you can supply as many collectible types as you want to
|
|
232
|
+
* remove.
|
|
233
|
+
*/
|
|
234
|
+
export function removeCollectible(
|
|
235
|
+
player: EntityPlayer,
|
|
236
|
+
...collectibleTypes: CollectibleType[]
|
|
237
|
+
): void {
|
|
238
|
+
for (const collectibleType of collectibleTypes) {
|
|
239
|
+
player.RemoveCollectible(collectibleType);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Helper function to remove a collectible costume from a player. Use this helper function to avoid
|
|
245
|
+
* having to request the collectible from the item config.
|
|
246
|
+
*/
|
|
247
|
+
export function removeCollectibleCostume(
|
|
248
|
+
player: EntityPlayer,
|
|
249
|
+
collectibleType: CollectibleType,
|
|
250
|
+
): void {
|
|
251
|
+
const itemConfigItem = itemConfig.GetCollectible(collectibleType);
|
|
252
|
+
if (itemConfigItem === undefined) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
player.RemoveCostume(itemConfigItem);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Helper function to remove one or more collectibles from all players. If any player has more than
|
|
261
|
+
* one copy of the item, then all copies of it will be removed.
|
|
262
|
+
*
|
|
263
|
+
* This function is variadic, meaning that you can specify as many collectibles as you want to
|
|
264
|
+
* remove.
|
|
265
|
+
*/
|
|
266
|
+
export function removeCollectibleFromAllPlayers(
|
|
267
|
+
...collectibleTypes: CollectibleType[]
|
|
268
|
+
): void {
|
|
269
|
+
for (const player of getAllPlayers()) {
|
|
270
|
+
for (const collectibleType of collectibleTypes) {
|
|
271
|
+
while (player.HasCollectible(collectibleType, true)) {
|
|
272
|
+
player.RemoveCollectible(collectibleType);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Helper function to set an active collectible to a particular slot. This has different behavior
|
|
280
|
+
* than calling the `player.AddCollectible` method with the `activeSlot` argument, because this
|
|
281
|
+
* function will not shift existing items into the Schoolbag and it handles
|
|
282
|
+
* `ActiveSlot.SLOT_POCKET2`.
|
|
283
|
+
*
|
|
284
|
+
* Note that if an item is set to `ActiveSlot.SLOT_POCKET2`, it will disappear after being used and
|
|
285
|
+
* will be automatically removed upon entering a new room.
|
|
286
|
+
*
|
|
287
|
+
* @param player The player to give the item to.
|
|
288
|
+
* @param collectibleType The collectible type of the item to give.
|
|
289
|
+
* @param activeSlot Optional. The slot to set. Default is `ActiveSlot.PRIMARY`.
|
|
290
|
+
* @param charge Optional. The argument of charges to set. If not specified, the item will be set
|
|
291
|
+
* with maximum charges.
|
|
292
|
+
* @param keepInPools Optional. Whether to remove the item from pools. Default is false.
|
|
293
|
+
*/
|
|
294
|
+
export function setActiveItem(
|
|
295
|
+
player: EntityPlayer,
|
|
296
|
+
collectibleType: CollectibleType,
|
|
297
|
+
activeSlot = ActiveSlot.PRIMARY,
|
|
298
|
+
charge?: int,
|
|
299
|
+
keepInPools = false,
|
|
300
|
+
): void {
|
|
301
|
+
const itemPool = game.GetItemPool();
|
|
302
|
+
const primaryCollectibleType = player.GetActiveItem(ActiveSlot.PRIMARY);
|
|
303
|
+
const primaryCharge = player.GetActiveCharge(ActiveSlot.PRIMARY);
|
|
304
|
+
const secondaryCollectibleType = player.GetActiveItem(ActiveSlot.SECONDARY);
|
|
305
|
+
|
|
306
|
+
if (charge === undefined) {
|
|
307
|
+
charge = getCollectibleMaxCharges(collectibleType);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (!keepInPools) {
|
|
311
|
+
itemPool.RemoveCollectible(collectibleType);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
switch (activeSlot) {
|
|
315
|
+
case ActiveSlot.PRIMARY: {
|
|
316
|
+
// If there is a Schoolbag item, removing the primary item will shift the Schoolbag item to
|
|
317
|
+
// the primary slot.
|
|
318
|
+
if (primaryCollectibleType !== CollectibleType.NULL) {
|
|
319
|
+
player.RemoveCollectible(primaryCollectibleType);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// If there was a Schoolbag item, adding a new primary item will shift it back into the
|
|
323
|
+
// secondary slot.
|
|
324
|
+
player.AddCollectible(collectibleType, charge, false);
|
|
325
|
+
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
case ActiveSlot.SECONDARY: {
|
|
330
|
+
if (primaryCollectibleType !== CollectibleType.NULL) {
|
|
331
|
+
player.RemoveCollectible(primaryCollectibleType);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (secondaryCollectibleType !== CollectibleType.NULL) {
|
|
335
|
+
player.RemoveCollectible(secondaryCollectibleType);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Add the new item, which will go to the primary slot.
|
|
339
|
+
player.AddCollectible(secondaryCollectibleType, charge, false);
|
|
340
|
+
|
|
341
|
+
// Add back the original primary item, if any.
|
|
342
|
+
if (primaryCollectibleType !== CollectibleType.NULL) {
|
|
343
|
+
player.AddCollectible(primaryCollectibleType, primaryCharge, false);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
case ActiveSlot.POCKET: {
|
|
350
|
+
player.SetPocketActiveItem(collectibleType, activeSlot, keepInPools);
|
|
351
|
+
player.SetActiveCharge(charge, activeSlot);
|
|
352
|
+
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
case ActiveSlot.POCKET_SINGLE_USE: {
|
|
357
|
+
player.SetPocketActiveItem(collectibleType, activeSlot, keepInPools);
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Helper function to use an active item without showing an animation, keeping the item, or adding
|
|
365
|
+
* any costumes.
|
|
366
|
+
*/
|
|
367
|
+
export function useActiveItemTemp(
|
|
368
|
+
player: EntityPlayer,
|
|
369
|
+
collectibleType: CollectibleType,
|
|
370
|
+
): void {
|
|
371
|
+
player.UseActiveItem(collectibleType, false, false, true, false, -1);
|
|
372
|
+
}
|
|
@@ -11,12 +11,8 @@ import type { PlayerHealth, SoulHeartType } from "../interfaces/PlayerHealth";
|
|
|
11
11
|
import { countSetBits, getKBitOfN, getNumBitsOfN } from "./bitwise";
|
|
12
12
|
import { getCharacterMaxHeartContainers } from "./characters";
|
|
13
13
|
import { getTotalCharge } from "./charge";
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
isCharacter,
|
|
17
|
-
isKeeper,
|
|
18
|
-
setActiveItem,
|
|
19
|
-
} from "./players";
|
|
14
|
+
import { getActiveItemSlots, setActiveItem } from "./playerCollectibles";
|
|
15
|
+
import { isCharacter, isKeeper } from "./players";
|
|
20
16
|
import { repeat } from "./utils";
|
|
21
17
|
|
|
22
18
|
export function addPlayerHealthType(
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PlayerType,
|
|
3
|
+
TrinketSlot,
|
|
4
|
+
TrinketType,
|
|
5
|
+
} from "isaac-typescript-definitions";
|
|
6
|
+
import { TRINKET_SLOT_VALUES } from "../arrays/cachedEnumValues";
|
|
7
|
+
import { itemConfig } from "../core/cachedClasses";
|
|
8
|
+
import { getAllPlayers, getPlayers } from "./playerIndex";
|
|
9
|
+
import { isCharacter } from "./players";
|
|
10
|
+
|
|
11
|
+
export function addTrinketCostume(
|
|
12
|
+
player: EntityPlayer,
|
|
13
|
+
trinketType: TrinketType,
|
|
14
|
+
): void {
|
|
15
|
+
const itemConfigTrinket = itemConfig.GetTrinket(trinketType);
|
|
16
|
+
if (itemConfigTrinket === undefined) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
player.AddCostume(itemConfigTrinket, false);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Helper function to check to see if any player has a particular trinket.
|
|
25
|
+
*
|
|
26
|
+
* @param trinketType The trinket type to check for.
|
|
27
|
+
* @param ignoreModifiers If set to true, only counts trinkets the player actually holds and ignores
|
|
28
|
+
* effects granted by other items. Default is false.
|
|
29
|
+
*/
|
|
30
|
+
export function anyPlayerHasTrinket(
|
|
31
|
+
trinketType: TrinketType,
|
|
32
|
+
ignoreModifiers?: boolean,
|
|
33
|
+
): boolean {
|
|
34
|
+
const players = getAllPlayers();
|
|
35
|
+
|
|
36
|
+
return players.some((player) =>
|
|
37
|
+
player.HasTrinket(trinketType, ignoreModifiers),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns the slot number corresponding to where a trinket can be safely inserted.
|
|
43
|
+
*
|
|
44
|
+
* For example:
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* const player = Isaac.GetPlayer();
|
|
48
|
+
* const trinketSlot = getOpenTrinketSlotNum(player);
|
|
49
|
+
* if (trinketSlot !== undefined) {
|
|
50
|
+
* // They have one or more open trinket slots
|
|
51
|
+
* player.AddTrinket(TrinketType.SWALLOWED_PENNY);
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function getOpenTrinketSlot(player: EntityPlayer): int | undefined {
|
|
56
|
+
const maxTrinkets = player.GetMaxTrinkets();
|
|
57
|
+
const trinketType1 = player.GetTrinket(TrinketSlot.SLOT_1);
|
|
58
|
+
const trinketType2 = player.GetTrinket(TrinketSlot.SLOT_2);
|
|
59
|
+
|
|
60
|
+
if (maxTrinkets === 1) {
|
|
61
|
+
return trinketType1 === TrinketType.NULL ? 0 : undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (maxTrinkets === 2) {
|
|
65
|
+
if (trinketType1 === TrinketType.NULL) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return trinketType2 === TrinketType.NULL ? 1 : undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
error(`The player has an unknown number of trinket slots: ${maxTrinkets}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Helper function to get all of the trinkets that the player is currently holding. This will not
|
|
77
|
+
* include any smelted trinkets.
|
|
78
|
+
*/
|
|
79
|
+
export function getPlayerTrinkets(player: EntityPlayer): TrinketType[] {
|
|
80
|
+
const trinketTypes: TrinketType[] = [];
|
|
81
|
+
|
|
82
|
+
for (const trinketSlot of TRINKET_SLOT_VALUES) {
|
|
83
|
+
const trinketType = player.GetTrinket(trinketSlot);
|
|
84
|
+
if (trinketType !== TrinketType.NULL) {
|
|
85
|
+
trinketTypes.push(trinketType);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return trinketTypes;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Helper function to get only the players that have a certain trinket.
|
|
94
|
+
*
|
|
95
|
+
* This function is variadic, meaning that you can supply as many trinket types as you want to check
|
|
96
|
+
* for. It only returns the players that have all of the trinkets.
|
|
97
|
+
*/
|
|
98
|
+
export function getPlayersWithTrinket(
|
|
99
|
+
...trinketTypes: TrinketType[]
|
|
100
|
+
): EntityPlayer[] {
|
|
101
|
+
const players = getPlayers();
|
|
102
|
+
|
|
103
|
+
return players.filter((player) =>
|
|
104
|
+
trinketTypes.every((trinketType) => player.HasTrinket(trinketType)),
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Helper function to check to see if the player is holding one or more trinkets. */
|
|
109
|
+
export function hasAnyTrinket(player: EntityPlayer): boolean {
|
|
110
|
+
const playerTrinketTypes = TRINKET_SLOT_VALUES.map((trinketSlot) =>
|
|
111
|
+
player.GetTrinket(trinketSlot),
|
|
112
|
+
);
|
|
113
|
+
return playerTrinketTypes.some(
|
|
114
|
+
(trinketType) => trinketType !== TrinketType.NULL,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Returns whether the player can hold an additional trinket, beyond what they are currently
|
|
120
|
+
* carrying. This takes into account items that modify the max number of trinkets, like Mom's Purse.
|
|
121
|
+
*
|
|
122
|
+
* If the player is the Tainted Soul, this always returns false, since that character cannot pick up
|
|
123
|
+
* items. (Only Tainted Forgotten can pick up items.)
|
|
124
|
+
*/
|
|
125
|
+
export function hasOpenTrinketSlot(player: EntityPlayer): boolean {
|
|
126
|
+
if (isCharacter(player, PlayerType.SOUL_B)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const openTrinketSlot = getOpenTrinketSlot(player);
|
|
131
|
+
return openTrinketSlot !== undefined;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Helper function to check to see if a player has one or more trinkets.
|
|
136
|
+
*
|
|
137
|
+
* This function is variadic, meaning that you can supply as many trinket types as you want to check
|
|
138
|
+
* for. Returns true if the player has any of the supplied trinket types.
|
|
139
|
+
*
|
|
140
|
+
* This function always passes `false` to the `ignoreModifiers` argument.
|
|
141
|
+
*/
|
|
142
|
+
export function hasTrinket(
|
|
143
|
+
player: EntityPlayer,
|
|
144
|
+
...trinketTypes: TrinketType[]
|
|
145
|
+
): boolean {
|
|
146
|
+
return trinketTypes.some((trinketType) => player.HasTrinket(trinketType));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Helper function to remove all of the held trinkets from a player.
|
|
151
|
+
*
|
|
152
|
+
* This will not remove any smelted trinkets, unless the player happens to also be holding a trinket
|
|
153
|
+
* that they have smelted. (In that case, both the held and the smelted trinket will be removed.)
|
|
154
|
+
*/
|
|
155
|
+
export function removeAllPlayerTrinkets(player: EntityPlayer): void {
|
|
156
|
+
for (const trinketSlot of TRINKET_SLOT_VALUES) {
|
|
157
|
+
const trinketType = player.GetTrinket(trinketSlot);
|
|
158
|
+
if (trinketType === TrinketType.NULL) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let alreadyHasTrinket: boolean;
|
|
163
|
+
do {
|
|
164
|
+
player.TryRemoveTrinket(trinketType);
|
|
165
|
+
alreadyHasTrinket = player.HasTrinket(trinketType);
|
|
166
|
+
} while (alreadyHasTrinket);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Helper function to remove a trinket costume from a player. Use this helper function to avoid
|
|
172
|
+
* having to request the trinket from the item config.
|
|
173
|
+
*/
|
|
174
|
+
export function removeTrinketCostume(
|
|
175
|
+
player: EntityPlayer,
|
|
176
|
+
trinketType: TrinketType,
|
|
177
|
+
): void {
|
|
178
|
+
const itemConfigTrinket = itemConfig.GetTrinket(trinketType);
|
|
179
|
+
if (itemConfigTrinket === undefined) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
player.RemoveCostume(itemConfigTrinket);
|
|
184
|
+
}
|