isaacscript-common 6.14.0 → 6.15.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/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/itemPool.d.ts +10 -0
- package/dist/functions/itemPool.d.ts.map +1 -0
- package/dist/functions/itemPool.lua +116 -0
- package/dist/functions/rockAlt.d.ts +0 -4
- package/dist/functions/rockAlt.d.ts.map +1 -1
- package/dist/functions/rockAlt.lua +210 -65
- 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/trinketGive.d.ts +13 -0
- package/dist/functions/trinketGive.d.ts.map +1 -1
- package/dist/functions/trinketGive.lua +16 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.lua +8 -0
- package/package.json +1 -1
- package/src/functions/collectibles.ts +6 -2
- package/src/functions/itemPool.ts +153 -0
- package/src/functions/rockAlt.ts +251 -59
- package/src/functions/saveFile.ts +13 -119
- package/src/functions/trinketGive.ts +21 -0
- package/src/index.ts +1 -0
package/src/functions/rockAlt.ts
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Card,
|
|
2
3
|
CoinSubType,
|
|
3
4
|
CollectibleType,
|
|
5
|
+
EffectVariant,
|
|
6
|
+
EntityType,
|
|
7
|
+
HeartSubType,
|
|
8
|
+
ItemPoolType,
|
|
9
|
+
PillColor,
|
|
10
|
+
RoomType,
|
|
4
11
|
TrinketType,
|
|
5
12
|
} from "isaac-typescript-definitions";
|
|
13
|
+
import { game } from "../cachedClasses";
|
|
6
14
|
import { DISTANCE_OF_GRID_TILE } from "../constants";
|
|
7
15
|
import { RockAltType } from "../enums/RockAltType";
|
|
8
|
-
import {
|
|
16
|
+
import { spawnEffectWithSeed, spawnNPCWithSeed } from "./entitiesSpecific";
|
|
17
|
+
import { isCollectibleInItemPool } from "./itemPool";
|
|
18
|
+
import {
|
|
19
|
+
spawnCardWithSeed,
|
|
20
|
+
spawnCoinWithSeed,
|
|
21
|
+
spawnHeartWithSeed,
|
|
22
|
+
spawnPillWithSeed,
|
|
23
|
+
spawnTrinketWithSeed,
|
|
24
|
+
} from "./pickupsSpecific";
|
|
9
25
|
import { getRandom } from "./random";
|
|
10
26
|
import { getRandomSeed, isRNG, newRNG } from "./rng";
|
|
11
27
|
import { spawnCollectible } from "./spawnCollectible";
|
|
@@ -19,10 +35,6 @@ import { getRandomVector } from "./vector";
|
|
|
19
35
|
* Note that most of the time, this function will do nothing, similar to how most of the time, when
|
|
20
36
|
* an individual urn is destroyed, nothing will spawn.
|
|
21
37
|
*
|
|
22
|
-
* For the purposes of spawning collectibles, this function assumes that the player has not seen the
|
|
23
|
-
* collectible yet in the current run. In vanilla, it is only possible to get a e.g. Quarter if the
|
|
24
|
-
* collectible still exists in the Treasure Room pool.
|
|
25
|
-
*
|
|
26
38
|
* The logic in this function is based on the rewards listed on the wiki:
|
|
27
39
|
* https://bindingofisaacrebirth.fandom.com/wiki/Rocks
|
|
28
40
|
*
|
|
@@ -40,78 +52,258 @@ export function spawnRockAltReward(
|
|
|
40
52
|
seedOrRNG: Seed | RNG = getRandomSeed(),
|
|
41
53
|
): boolean {
|
|
42
54
|
const rng = isRNG(seedOrRNG) ? seedOrRNG : newRNG(seedOrRNG);
|
|
43
|
-
const chance = getRandom(rng);
|
|
44
55
|
|
|
45
56
|
switch (rockAltType) {
|
|
46
57
|
case RockAltType.URN: {
|
|
47
|
-
|
|
58
|
+
return spawnRockAltRewardUrn(position, rng);
|
|
59
|
+
}
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
61
|
+
case RockAltType.MUSHROOM: {
|
|
62
|
+
return spawnRockAltRewardMushroom(position, rng);
|
|
63
|
+
}
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const numCoinsChance = getRandom(rng);
|
|
59
|
-
const numCoins = numCoinsChance < 0.5 ? 1 : 2;
|
|
60
|
-
repeat(numCoins, () => {
|
|
61
|
-
const velocity = getRandomVector(rng);
|
|
62
|
-
spawnCoinWithSeed(CoinSubType.NULL, position, rng, velocity);
|
|
63
|
-
});
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
65
|
+
case RockAltType.SKULL: {
|
|
66
|
+
return spawnRockAltRewardSkull(position, rng);
|
|
67
|
+
}
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
spawnTrinketWithSeed(TrinketType.SWALLOWED_PENNY, position, rng);
|
|
71
|
-
}
|
|
69
|
+
case RockAltType.POLYP: {
|
|
70
|
+
return spawnRockAltRewardPolyp(position, rng);
|
|
71
|
+
}
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
case RockAltType.BUCKET: {
|
|
74
|
+
return spawnRockAltRewardBucket(position, rng);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function spawnRockAltRewardUrn(position: Vector, rng: RNG): boolean {
|
|
80
|
+
const chance = getRandom(rng);
|
|
81
|
+
let totalChance = 0;
|
|
82
|
+
|
|
83
|
+
// Nothing (68.00%).
|
|
84
|
+
totalChance += 0.68;
|
|
85
|
+
if (chance < totalChance) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// One or two random coins (9.44%).
|
|
90
|
+
totalChance += 0.0944;
|
|
91
|
+
if (chance < totalChance) {
|
|
92
|
+
const numCoinsChance = getRandom(rng);
|
|
93
|
+
const numCoins = numCoinsChance < 0.5 ? 1 : 2;
|
|
94
|
+
const length = DISTANCE_OF_GRID_TILE;
|
|
95
|
+
repeat(numCoins, () => {
|
|
96
|
+
const randomVector = getRandomVector(rng);
|
|
97
|
+
const velocity = randomVector.mul(length);
|
|
98
|
+
spawnCoinWithSeed(CoinSubType.NULL, position, rng, velocity);
|
|
99
|
+
});
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Swallowed Penny (2.50%).
|
|
104
|
+
totalChance += 0.025;
|
|
105
|
+
if (chance < totalChance) {
|
|
106
|
+
spawnTrinketWithSeed(TrinketType.SWALLOWED_PENNY, position, rng);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// A Quarter (0.50%).
|
|
111
|
+
totalChance += 0.005;
|
|
112
|
+
if (chance < totalChance) {
|
|
113
|
+
const stillInPools = isCollectibleInItemPool(
|
|
114
|
+
CollectibleType.QUARTER,
|
|
115
|
+
ItemPoolType.DEVIL,
|
|
116
|
+
);
|
|
117
|
+
if (stillInPools) {
|
|
118
|
+
spawnCollectible(CollectibleType.QUARTER, position, rng);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// One or two spiders (19.48%). (Since this is the final option, so we don't need to check the
|
|
126
|
+
// chance.)
|
|
127
|
+
const numSpidersChance = getRandom(rng);
|
|
128
|
+
const numSpiders = numSpidersChance < 0.5 ? 1 : 2;
|
|
129
|
+
const length = DISTANCE_OF_GRID_TILE * 3;
|
|
130
|
+
repeat(numSpiders, () => {
|
|
131
|
+
const randomVector = getRandomVector(rng);
|
|
132
|
+
const offset = randomVector.mul(length);
|
|
133
|
+
const targetPos = position.add(offset);
|
|
134
|
+
EntityNPC.ThrowSpider(position, undefined, targetPos, false, 0);
|
|
135
|
+
});
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function spawnRockAltRewardMushroom(position: Vector, rng: RNG): boolean {
|
|
140
|
+
const room = game.GetRoom();
|
|
141
|
+
const roomType = room.GetType();
|
|
142
|
+
|
|
143
|
+
const chance = getRandom(rng);
|
|
144
|
+
let totalChance = 0;
|
|
145
|
+
|
|
146
|
+
// Nothing (68.00%).
|
|
147
|
+
totalChance += 0.68;
|
|
148
|
+
if (chance < totalChance) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
78
151
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
152
|
+
// One pill (9.82%).
|
|
153
|
+
totalChance += 0.0982;
|
|
154
|
+
if (chance < totalChance) {
|
|
155
|
+
spawnPillWithSeed(PillColor.NULL, position, rng);
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Liberty Cap (2.50%).
|
|
160
|
+
totalChance += 0.025;
|
|
161
|
+
if (chance < totalChance) {
|
|
162
|
+
spawnTrinketWithSeed(TrinketType.LIBERTY_CAP, position, rng);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Collectible (0.50%).
|
|
167
|
+
totalChance += 0.005;
|
|
168
|
+
if (chance < totalChance) {
|
|
169
|
+
if (roomType === RoomType.SECRET) {
|
|
170
|
+
const wavyCapChance = getRandom(rng);
|
|
171
|
+
if (wavyCapChance < 0.0272) {
|
|
172
|
+
const stillInPools = isCollectibleInItemPool(
|
|
173
|
+
CollectibleType.WAVY_CAP,
|
|
174
|
+
ItemPoolType.SECRET,
|
|
175
|
+
);
|
|
176
|
+
if (stillInPools) {
|
|
177
|
+
spawnCollectible(CollectibleType.WAVY_CAP, position, rng);
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
91
180
|
}
|
|
181
|
+
}
|
|
92
182
|
|
|
93
|
-
|
|
94
|
-
|
|
183
|
+
const magicMushroomStillInPools = isCollectibleInItemPool(
|
|
184
|
+
CollectibleType.MAGIC_MUSHROOM,
|
|
185
|
+
ItemPoolType.TREASURE,
|
|
186
|
+
);
|
|
187
|
+
const miniMushStillInPools = isCollectibleInItemPool(
|
|
188
|
+
CollectibleType.MINI_MUSH,
|
|
189
|
+
ItemPoolType.TREASURE,
|
|
190
|
+
);
|
|
191
|
+
if (magicMushroomStillInPools && miniMushStillInPools) {
|
|
192
|
+
const collectibleChance = getRandom(rng);
|
|
193
|
+
const collectibleType =
|
|
194
|
+
collectibleChance < 0.5
|
|
195
|
+
? CollectibleType.MAGIC_MUSHROOM // 12
|
|
196
|
+
: CollectibleType.MINI_MUSH; // 71
|
|
197
|
+
spawnCollectible(collectibleType, position, rng);
|
|
198
|
+
return true;
|
|
95
199
|
}
|
|
96
200
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return
|
|
201
|
+
if (magicMushroomStillInPools) {
|
|
202
|
+
spawnCollectible(CollectibleType.MINI_MUSH, position, rng);
|
|
203
|
+
return true;
|
|
100
204
|
}
|
|
101
205
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return
|
|
206
|
+
if (miniMushStillInPools) {
|
|
207
|
+
spawnCollectible(CollectibleType.MAGIC_MUSHROOM, position, rng);
|
|
208
|
+
return true;
|
|
105
209
|
}
|
|
106
210
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// One poisonous gas effect (19.24%). (Since this is the final option, so we don't need to check
|
|
215
|
+
// the chance.)
|
|
216
|
+
spawnEffectWithSeed(EffectVariant.FART, 0, position, rng);
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function spawnRockAltRewardSkull(position: Vector, rng: RNG): boolean {
|
|
221
|
+
const chance = getRandom(rng);
|
|
222
|
+
let totalChance = 0;
|
|
223
|
+
|
|
224
|
+
// Nothing (68.00%).
|
|
225
|
+
totalChance += 0.68;
|
|
226
|
+
if (chance < totalChance) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// One card / rune (9.52%).
|
|
231
|
+
totalChance += 0.095;
|
|
232
|
+
if (chance < totalChance) {
|
|
233
|
+
spawnCardWithSeed(Card.NULL, position, rng);
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Black heart (2.50%).
|
|
238
|
+
totalChance += 0.025;
|
|
239
|
+
if (chance < totalChance) {
|
|
240
|
+
spawnHeartWithSeed(HeartSubType.BLACK, position, rng);
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Collectible (0.50%).
|
|
245
|
+
totalChance += 0.005;
|
|
246
|
+
if (chance < totalChance) {
|
|
247
|
+
const ghostBabyStillInPools = isCollectibleInItemPool(
|
|
248
|
+
CollectibleType.GHOST_BABY,
|
|
249
|
+
ItemPoolType.TREASURE,
|
|
250
|
+
);
|
|
251
|
+
const dryBabyStillInPools = isCollectibleInItemPool(
|
|
252
|
+
CollectibleType.DRY_BABY,
|
|
253
|
+
ItemPoolType.TREASURE,
|
|
254
|
+
);
|
|
255
|
+
if (ghostBabyStillInPools && dryBabyStillInPools) {
|
|
256
|
+
const collectibleChance = getRandom(rng);
|
|
257
|
+
const collectibleType =
|
|
258
|
+
collectibleChance < 0.5
|
|
259
|
+
? CollectibleType.GHOST_BABY // 163
|
|
260
|
+
: CollectibleType.DRY_BABY; // 265
|
|
261
|
+
spawnCollectible(collectibleType, position, rng);
|
|
262
|
+
return true;
|
|
110
263
|
}
|
|
111
264
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return
|
|
265
|
+
if (ghostBabyStillInPools) {
|
|
266
|
+
spawnCollectible(CollectibleType.DRY_BABY, position, rng);
|
|
267
|
+
return true;
|
|
115
268
|
}
|
|
269
|
+
|
|
270
|
+
if (dryBabyStillInPools) {
|
|
271
|
+
spawnCollectible(CollectibleType.GHOST_BABY, position, rng);
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// One Host (19.30%). (Since this is the final option, so we don't need to check the chance.)
|
|
279
|
+
spawnNPCWithSeed(EntityType.HOST, 0, 0, position, rng);
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function spawnRockAltRewardPolyp(_position: Vector, rng: RNG): boolean {
|
|
284
|
+
const chance = getRandom(rng);
|
|
285
|
+
let totalChance = 0;
|
|
286
|
+
|
|
287
|
+
// Nothing (68.00%).
|
|
288
|
+
totalChance += 0.68;
|
|
289
|
+
if (chance < totalChance) {
|
|
290
|
+
return false;
|
|
116
291
|
}
|
|
292
|
+
|
|
293
|
+
// TODO
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function spawnRockAltRewardBucket(_position: Vector, rng: RNG): boolean {
|
|
298
|
+
const chance = getRandom(rng);
|
|
299
|
+
let totalChance = 0;
|
|
300
|
+
|
|
301
|
+
// Nothing (68.00%).
|
|
302
|
+
totalChance += 0.68;
|
|
303
|
+
if (chance < totalChance) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// TODO
|
|
308
|
+
return false;
|
|
117
309
|
}
|
|
@@ -1,133 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
ItemPoolType,
|
|
4
|
-
PlayerType,
|
|
5
|
-
TrinketType,
|
|
6
|
-
} from "isaac-typescript-definitions";
|
|
7
|
-
import { game } from "../cachedClasses";
|
|
8
|
-
import { PlayerIndex } from "../types/PlayerIndex";
|
|
9
|
-
import { getCollectibleSet } from "./collectibleSet";
|
|
10
|
-
import { mapGetPlayer, mapSetPlayer } from "./playerDataStructures";
|
|
11
|
-
import { getPlayers } from "./playerIndex";
|
|
12
|
-
import { anyPlayerHasCollectible, getPlayersOfType } from "./players";
|
|
13
|
-
import { repeat } from "./utils";
|
|
14
|
-
|
|
15
|
-
const COLLECTIBLES_THAT_AFFECT_ITEM_POOLS: readonly CollectibleType[] = [
|
|
16
|
-
CollectibleType.CHAOS, // 402
|
|
17
|
-
CollectibleType.SACRED_ORB, // 691
|
|
18
|
-
CollectibleType.TMTRAINER, // 721
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
const TRINKETS_THAT_AFFECT_ITEM_POOLS: readonly TrinketType[] = [
|
|
22
|
-
TrinketType.NO,
|
|
23
|
-
];
|
|
1
|
+
import { CollectibleType, ItemPoolType } from "isaac-typescript-definitions";
|
|
2
|
+
import { anyPlayerHasCollectible } from "./players";
|
|
24
3
|
|
|
25
4
|
/**
|
|
26
|
-
* Helper function to see if the given collectible is unlocked on the
|
|
5
|
+
* Helper function to see if the given collectible is unlocked on the current save file. This
|
|
27
6
|
* requires providing the corresponding item pool that the collectible is located in.
|
|
28
7
|
*
|
|
29
|
-
* - If any player currently has the
|
|
30
|
-
*
|
|
31
|
-
* from all pools.)
|
|
8
|
+
* - If any player currently has the collectible, then it is assumed to be unlocked. (This is
|
|
9
|
+
* because in almost all cases, when a collectible is added to a player's inventory, it is
|
|
10
|
+
* subsequently removed from all pools.)
|
|
32
11
|
* - If the collectible is located in more than one item pool, then any item pool can be provided.
|
|
33
12
|
* - If the collectible is not located in any item pools, then this function will always return
|
|
34
13
|
* false.
|
|
35
|
-
* - If
|
|
36
|
-
* changed back (because Tainted Lost is not able to retrieve
|
|
14
|
+
* - If the collectible is non-offensive, any Tainted Losts will be temporarily changed to Isaac and
|
|
15
|
+
* then changed back. (This is because Tainted Lost is not able to retrieve non-offensive
|
|
16
|
+
* collectibles from item pools).
|
|
37
17
|
*/
|
|
38
18
|
export function isCollectibleUnlocked(
|
|
39
|
-
|
|
40
|
-
|
|
19
|
+
collectibleType: CollectibleType,
|
|
20
|
+
itemPoolType: ItemPoolType,
|
|
41
21
|
): boolean {
|
|
42
|
-
|
|
43
|
-
// from pools, so the below check won't work).
|
|
44
|
-
if (anyPlayerHasCollectible(collectibleTypeToCheckFor)) {
|
|
22
|
+
if (anyPlayerHasCollectible(collectibleType)) {
|
|
45
23
|
return true;
|
|
46
24
|
}
|
|
47
25
|
|
|
48
|
-
|
|
49
|
-
// temporarily change the character to Isaac.
|
|
50
|
-
const taintedLosts = getPlayersOfType(PlayerType.THE_LOST_B);
|
|
51
|
-
for (const player of taintedLosts) {
|
|
52
|
-
player.ChangePlayerType(PlayerType.ISAAC);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Before checking the item pools, remove any collectibles or trinkets that affect retrieved
|
|
56
|
-
// collectible types.
|
|
57
|
-
const removedItemsMap = new Map<PlayerIndex, CollectibleType[]>();
|
|
58
|
-
const removedTrinketsMap = new Map<PlayerIndex, TrinketType[]>();
|
|
59
|
-
for (const player of getPlayers()) {
|
|
60
|
-
const removedItems: CollectibleType[] = [];
|
|
61
|
-
for (const itemToRemove of COLLECTIBLES_THAT_AFFECT_ITEM_POOLS) {
|
|
62
|
-
if (player.HasCollectible(itemToRemove)) {
|
|
63
|
-
const numCollectibles = player.GetCollectibleNum(itemToRemove);
|
|
64
|
-
repeat(numCollectibles, () => {
|
|
65
|
-
player.RemoveCollectible(itemToRemove);
|
|
66
|
-
removedItems.push(itemToRemove);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
mapSetPlayer(removedItemsMap, player, removedItems);
|
|
72
|
-
|
|
73
|
-
const removedTrinkets: TrinketType[] = [];
|
|
74
|
-
for (const trinketToRemove of TRINKETS_THAT_AFFECT_ITEM_POOLS) {
|
|
75
|
-
if (player.HasTrinket(trinketToRemove)) {
|
|
76
|
-
const numTrinkets = player.GetTrinketMultiplier(trinketToRemove);
|
|
77
|
-
repeat(numTrinkets, () => {
|
|
78
|
-
player.TryRemoveTrinket(trinketToRemove);
|
|
79
|
-
removedTrinkets.push(trinketToRemove);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
mapSetPlayer(removedTrinketsMap, player, removedTrinkets);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Blacklist every collectible in the game except for the provided collectible.
|
|
88
|
-
const itemPool = game.GetItemPool();
|
|
89
|
-
const collectibleSet = getCollectibleSet();
|
|
90
|
-
for (const collectibleType of collectibleSet.values()) {
|
|
91
|
-
if (collectibleType !== collectibleTypeToCheckFor) {
|
|
92
|
-
itemPool.AddRoomBlacklist(collectibleType);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Get a collectible from the pool and see if it is the intended collectible. (We can use any
|
|
97
|
-
// arbitrary value as the seed since it should not influence the result.)
|
|
98
|
-
const retrievedCollectibleType = itemPool.GetCollectible(
|
|
99
|
-
itemPoolToCheckFor,
|
|
100
|
-
false,
|
|
101
|
-
1 as Seed,
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
const collectibleUnlocked =
|
|
105
|
-
retrievedCollectibleType === collectibleTypeToCheckFor;
|
|
106
|
-
|
|
107
|
-
// Reset the blacklist
|
|
108
|
-
itemPool.ResetRoomBlacklist();
|
|
109
|
-
|
|
110
|
-
// Give back items/trinkets, if necessary.
|
|
111
|
-
for (const player of getPlayers()) {
|
|
112
|
-
const removedItems = mapGetPlayer(removedItemsMap, player);
|
|
113
|
-
if (removedItems !== undefined) {
|
|
114
|
-
for (const collectibleType of removedItems) {
|
|
115
|
-
player.AddCollectible(collectibleType, 0, false); // Prevent Chaos from spawning pickups
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const removedTrinkets = mapGetPlayer(removedTrinketsMap, player);
|
|
120
|
-
if (removedTrinkets !== undefined) {
|
|
121
|
-
for (const trinketType of removedTrinkets) {
|
|
122
|
-
player.AddTrinket(trinketType, false);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Change any players back to Tainted Lost, if necessary.
|
|
128
|
-
for (const player of taintedLosts) {
|
|
129
|
-
player.ChangePlayerType(PlayerType.THE_LOST_B);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return collectibleUnlocked;
|
|
26
|
+
return isCollectibleUnlocked(collectibleType, itemPoolType);
|
|
133
27
|
}
|
|
@@ -74,6 +74,27 @@ export function smeltTrinket(
|
|
|
74
74
|
giveTrinketsBack(player, trinketSituation);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Helper function to smelt two or more different trinkets. If you want to smelt one trinket (or
|
|
79
|
+
* multiple copies of one trinket), then use the `smeltTrinket` helper function instead.
|
|
80
|
+
*
|
|
81
|
+
* This function is variadic, meaning that you can pass as many trinket types as you want to smelt.
|
|
82
|
+
*
|
|
83
|
+
* Before smelting, this function will automatically remove the trinkets that the player is holding,
|
|
84
|
+
* if any, and then give them back after the new trinket is smelted.
|
|
85
|
+
*
|
|
86
|
+
* @param player The player to smelt the trinkets to.
|
|
87
|
+
* @param trinketTypes The trinket types to smelt.
|
|
88
|
+
*/
|
|
89
|
+
export function smeltTrinkets(
|
|
90
|
+
player: EntityPlayer,
|
|
91
|
+
...trinketTypes: TrinketType[]
|
|
92
|
+
): void {
|
|
93
|
+
for (const trinketType of trinketTypes) {
|
|
94
|
+
smeltTrinket(player, trinketType);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
77
98
|
/**
|
|
78
99
|
* Helper function to temporarily remove a specific kind of trinket from the player. Use this in
|
|
79
100
|
* combination with the `giveTrinketsBack` function to take away and give back a trinket on the same
|
package/src/index.ts
CHANGED
|
@@ -117,6 +117,7 @@ export * from "./functions/gridEntities";
|
|
|
117
117
|
export * from "./functions/gridEntitiesSpecific";
|
|
118
118
|
export * from "./functions/input";
|
|
119
119
|
export * from "./functions/isaacAPIClass";
|
|
120
|
+
export * from "./functions/itemPool";
|
|
120
121
|
export * from "./functions/jsonHelpers";
|
|
121
122
|
export * from "./functions/jsonRoom";
|
|
122
123
|
export * from "./functions/kColor";
|