isaacscript-common 7.4.2 → 7.5.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/postGridEntity.d.ts.map +1 -1
- package/dist/callbacks/postGridEntity.lua +53 -6
- package/dist/callbacks/postPlayerChangeStat.d.ts.map +1 -1
- package/dist/callbacks/postPlayerChangeStat.lua +9 -2
- package/dist/callbacks/subscriptions/postGridEntityCustomBroken.d.ts +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomBroken.d.ts.map +1 -1
- package/dist/callbacks/subscriptions/postGridEntityCustomBroken.lua +5 -2
- package/dist/callbacks/subscriptions/postGridEntityCustomInit.d.ts +9 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomInit.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomInit.lua +23 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomRemove.d.ts +9 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomRemove.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomRemove.lua +23 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomStateChanged.d.ts +9 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomStateChanged.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomStateChanged.lua +29 -0
- package/dist/callbacks/subscriptions/postPlayerChangeStat.d.ts +3 -2
- package/dist/callbacks/subscriptions/postPlayerChangeStat.d.ts.map +1 -1
- package/dist/classes/DefaultMap.d.ts +3 -2
- package/dist/classes/DefaultMap.d.ts.map +1 -1
- package/dist/classes/DefaultMap.lua +2 -1
- package/dist/enums/ModCallbackCustom.d.ts +131 -81
- package/dist/enums/ModCallbackCustom.d.ts.map +1 -1
- package/dist/enums/ModCallbackCustom.lua +67 -61
- package/dist/enums/StatType.d.ts +3 -1
- package/dist/enums/StatType.d.ts.map +1 -1
- package/dist/enums/StatType.lua +2 -0
- package/dist/features/customGridEntity.d.ts +30 -13
- package/dist/features/customGridEntity.d.ts.map +1 -1
- package/dist/features/customGridEntity.lua +67 -48
- package/dist/features/customStage/customStageGridEntities.d.ts.map +1 -1
- package/dist/features/customStage/customStageGridEntities.lua +37 -31
- package/dist/features/customStage/customStageUtils.d.ts +2 -1
- package/dist/features/customStage/customStageUtils.d.ts.map +1 -1
- package/dist/features/customStage/customStageUtils.lua +40 -1
- package/dist/features/customStage/exports.d.ts +1 -25
- package/dist/features/customStage/exports.d.ts.map +1 -1
- package/dist/features/customStage/exports.lua +28 -29
- package/dist/features/customStage/v.d.ts +0 -2
- package/dist/features/customStage/v.d.ts.map +1 -1
- package/dist/features/customStage/v.lua +0 -2
- package/dist/features/customStage/versusScreen.d.ts.map +1 -1
- package/dist/features/customStage/versusScreen.lua +74 -60
- package/dist/functions/dev.d.ts +20 -0
- package/dist/functions/dev.d.ts.map +1 -0
- package/dist/functions/dev.lua +34 -0
- package/dist/functions/doors.d.ts +6 -5
- package/dist/functions/doors.d.ts.map +1 -1
- package/dist/functions/doors.lua +25 -12
- package/dist/functions/enums.d.ts +3 -3
- package/dist/functions/enums.lua +3 -3
- package/dist/functions/gridEntities.d.ts +3 -0
- package/dist/functions/gridEntities.d.ts.map +1 -1
- package/dist/functions/gridEntities.lua +35 -4
- package/dist/functions/playerStats.d.ts.map +1 -1
- package/dist/functions/playerStats.lua +2 -1
- package/dist/functions/players.d.ts.map +1 -1
- package/dist/functions/players.lua +3 -2
- package/dist/functions/rooms.d.ts +5 -0
- package/dist/functions/rooms.d.ts.map +1 -1
- package/dist/functions/rooms.lua +12 -2
- package/dist/index.d.ts +312 -198
- package/dist/index.d.ts.map +1 -1
- package/dist/index.lua +1134 -8
- package/dist/interfaces/{CustomStageLua.d.ts → CustomStageTSConfig.d.ts} +86 -60
- package/dist/interfaces/CustomStageTSConfig.d.ts.map +1 -0
- package/dist/interfaces/{CustomStageLua.lua → CustomStageTSConfig.lua} +0 -0
- package/dist/interfaces/JSONRoomsFile.d.ts +6 -5
- package/dist/interfaces/JSONRoomsFile.d.ts.map +1 -1
- package/dist/interfaces/StatTypeType.d.ts +1 -0
- package/dist/interfaces/StatTypeType.d.ts.map +1 -1
- package/dist/interfaces/private/AddCallbackParameterCustom.d.ts +6 -0
- package/dist/interfaces/private/AddCallbackParameterCustom.d.ts.map +1 -1
- package/dist/interfaces/private/CustomStage.d.ts +1 -1
- package/dist/interfaces/private/CustomStage.d.ts.map +1 -1
- package/dist/objects/callbackRegisterFunctions.d.ts.map +1 -1
- package/dist/objects/callbackRegisterFunctions.lua +9 -0
- package/dist/types/PossibleStatType.d.ts +7 -0
- package/dist/types/PossibleStatType.d.ts.map +1 -0
- package/dist/{interfaces/index.lua → types/PossibleStatType.lua} +0 -0
- package/package.json +1 -1
- package/src/callbacks/postGridEntity.ts +75 -10
- package/src/callbacks/postPlayerChangeStat.ts +8 -4
- package/src/callbacks/subscriptions/postGridEntityCustomBroken.ts +4 -0
- package/src/callbacks/subscriptions/postGridEntityCustomInit.ts +38 -0
- package/src/callbacks/subscriptions/postGridEntityCustomRemove.ts +35 -0
- package/src/callbacks/subscriptions/postGridEntityCustomStateChanged.ts +42 -0
- package/src/callbacks/subscriptions/postPlayerChangeStat.ts +4 -7
- package/src/classes/DefaultMap.ts +3 -2
- package/src/enums/ModCallbackCustom.ts +73 -20
- package/src/enums/StatType.ts +3 -3
- package/src/features/customGridEntity.ts +87 -61
- package/src/features/customStage/customStageGridEntities.ts +16 -7
- package/src/features/customStage/customStageUtils.ts +52 -1
- package/src/features/customStage/exports.ts +33 -45
- package/src/features/customStage/init.ts +1 -1
- package/src/features/customStage/v.ts +0 -6
- package/src/features/customStage/versusScreen.ts +70 -55
- package/src/functions/dev.ts +31 -0
- package/src/functions/doors.ts +37 -21
- package/src/functions/enums.ts +3 -3
- package/src/functions/gridEntities.ts +33 -1
- package/src/functions/playerStats.ts +1 -0
- package/src/functions/players.ts +7 -3
- package/src/functions/rooms.ts +18 -0
- package/src/index.ts +208 -9
- package/src/interfaces/{CustomStageLua.ts → CustomStageTSConfig.ts} +107 -41
- package/src/interfaces/JSONRoomsFile.ts +6 -5
- package/src/interfaces/StatTypeType.ts +1 -0
- package/src/interfaces/private/AddCallbackParameterCustom.ts +6 -0
- package/src/interfaces/private/CustomStage.ts +4 -1
- package/src/objects/callbackRegisterFunctions.ts +9 -0
- package/src/types/PossibleStatType.ts +12 -0
- package/dist/classes/index.d.ts +0 -3
- package/dist/classes/index.d.ts.map +0 -1
- package/dist/classes/index.lua +0 -18
- package/dist/core/index.d.ts +0 -5
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.lua +0 -34
- package/dist/enums/DecorationVariant.d.ts +0 -10
- package/dist/enums/DecorationVariant.d.ts.map +0 -1
- package/dist/enums/DecorationVariant.lua +0 -7
- package/dist/enums/index.d.ts +0 -11
- package/dist/enums/index.d.ts.map +0 -1
- package/dist/enums/index.lua +0 -82
- package/dist/features/index.d.ts +0 -30
- package/dist/features/index.d.ts.map +0 -1
- package/dist/features/index.lua +0 -216
- package/dist/functions/index.d.ts +0 -100
- package/dist/functions/index.d.ts.map +0 -1
- package/dist/functions/index.lua +0 -794
- package/dist/interfaces/CustomStageLua.d.ts.map +0 -1
- package/dist/interfaces/index.d.ts +0 -12
- package/dist/interfaces/index.d.ts.map +0 -1
- package/dist/maps/index.d.ts +0 -5
- package/dist/maps/index.d.ts.map +0 -1
- package/dist/maps/index.lua +0 -34
- package/dist/objects/index.d.ts +0 -2
- package/dist/objects/index.d.ts.map +0 -1
- package/dist/objects/index.lua +0 -10
- package/dist/types/index.d.ts +0 -11
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.lua +0 -10
- package/src/classes/index.ts +0 -2
- package/src/classes/indexTypeDoc.ts +0 -2
- package/src/core/index.ts +0 -4
- package/src/core/indexTypeDoc.ts +0 -4
- package/src/enums/DecorationVariant.ts +0 -10
- package/src/enums/index.ts +0 -10
- package/src/enums/indexTypeDoc.ts +0 -10
- package/src/features/index.ts +0 -59
- package/src/features/indexTypeDoc.ts +0 -30
- package/src/functions/index.ts +0 -101
- package/src/functions/indexTypeDoc.ts +0 -101
- package/src/indexTypeDoc.ts +0 -13
- package/src/interfaces/index.ts +0 -11
- package/src/interfaces/indexTypeDoc.ts +0 -11
- package/src/maps/index.ts +0 -4
- package/src/maps/indexTypeDoc.ts +0 -4
- package/src/objects/index.ts +0 -1
- package/src/objects/indexTypeDoc.ts +0 -1
- package/src/types/index.ts +0 -10
- package/src/types/indexTypeDoc.ts +0 -10
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
ActiveSlot,
|
|
3
3
|
CollectibleType,
|
|
4
4
|
DamageFlag,
|
|
5
|
-
EntityFlag,
|
|
6
5
|
EntityType,
|
|
7
6
|
GridCollisionClass,
|
|
8
7
|
GridEntityType,
|
|
@@ -13,24 +12,24 @@ import { postGridEntityCustomBrokenFire } from "../callbacks/subscriptions/postG
|
|
|
13
12
|
import { DefaultMap } from "../classes/DefaultMap";
|
|
14
13
|
import { ModUpgraded } from "../classes/ModUpgraded";
|
|
15
14
|
import { game } from "../core/cachedClasses";
|
|
16
|
-
import { DecorationVariant } from "../enums/DecorationVariant";
|
|
17
15
|
import { ModCallbackCustom } from "../enums/ModCallbackCustom";
|
|
18
|
-
import {
|
|
19
|
-
|
|
16
|
+
import {
|
|
17
|
+
areFeaturesInitialized,
|
|
18
|
+
errorIfFeaturesNotInitialized,
|
|
19
|
+
} from "../featuresInitialized";
|
|
20
20
|
import { hasFlag } from "../functions/flag";
|
|
21
21
|
import {
|
|
22
22
|
removeGridEntity,
|
|
23
23
|
spawnGridEntityWithVariant,
|
|
24
24
|
} from "../functions/gridEntities";
|
|
25
25
|
import { getRoomListIndex } from "../functions/roomData";
|
|
26
|
-
import {
|
|
26
|
+
import { isNumber } from "../functions/types";
|
|
27
27
|
import { isVector } from "../functions/vector";
|
|
28
28
|
import { GridEntityCustomData } from "../interfaces/GridEntityCustomData";
|
|
29
29
|
import { runNextGameFrame } from "./runInNFrames";
|
|
30
30
|
import { saveDataManager } from "./saveDataManager/exports";
|
|
31
31
|
|
|
32
32
|
const FEATURE_NAME = "customGridEntity";
|
|
33
|
-
const GENERIC_PROP_SIZE_MULTIPLIER = 0.66;
|
|
34
33
|
|
|
35
34
|
const v = {
|
|
36
35
|
level: {
|
|
@@ -200,18 +199,24 @@ function postNewRoomReordered() {
|
|
|
200
199
|
* will reappear if the player leaves and re-enters the room. (It will be manually respawned in the
|
|
201
200
|
* `POST_NEW_ROOM` callback.)
|
|
202
201
|
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
202
|
+
* Custom grid entities are built on top of real grid entities. You can use any existing grid entity
|
|
203
|
+
* type as a base. For example, if you want to create a custom rock that would be breakable like a
|
|
204
|
+
* normal rock, then you should specify `GridEntityType.ROCK` as the base grid entity type.
|
|
206
205
|
*
|
|
207
206
|
* Once a custom grid entity is spawned, you can take advantage of the custom grid callbacks such as
|
|
208
|
-
* `POST_GRID_ENTITY_CUSTOM_UPDATE`.
|
|
207
|
+
* `POST_GRID_ENTITY_CUSTOM_UPDATE`. Note that the "normal" grid entities callbacks will not fire
|
|
208
|
+
* for custom entities. For example, if you had a custom grid entity based on `GridEntityType.ROCK`,
|
|
209
|
+
* and you also had a subscription to the `POST_GRID_ENTITY_UPDATE` callback, the callback would
|
|
210
|
+
* only fire for normal rocks and not the custom entity.
|
|
211
|
+
*
|
|
212
|
+
* Custom grid entities are an IsaacScript feature because the vanilla game does not support any
|
|
213
|
+
* custom grid entities.
|
|
209
214
|
*
|
|
210
215
|
* @param gridEntityTypeCustom An integer that identifies what kind of grid entity you are creating.
|
|
211
|
-
* It should correspond to a local enum value in your mod. The
|
|
212
|
-
* can be any unique value and will not correspond to the actual
|
|
213
|
-
* entity type used. (This integer is used in the various custom
|
|
214
|
-
* entity callbacks.)
|
|
216
|
+
* It should correspond to a local enum value created in your mod. The
|
|
217
|
+
* integer can be any unique value and will not correspond to the actual
|
|
218
|
+
* grid entity type used. (This integer is used in the various custom
|
|
219
|
+
* grid entity callbacks.)
|
|
215
220
|
* @param gridIndexOrPosition The grid index or position in the room that you want to spawn the grid
|
|
216
221
|
* entity at. If a position is specified, the closest grid index will be
|
|
217
222
|
* used.
|
|
@@ -220,10 +225,10 @@ function postNewRoomReordered() {
|
|
|
220
225
|
* @param defaultAnimation Optional. The name of the animation to play after the sprite is
|
|
221
226
|
* initialized and after the player re-enters a room with this grid entity
|
|
222
227
|
* in it. If not specified, the default animation in the anm2 will be used.
|
|
223
|
-
* @param
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
228
|
+
* @param baseGridEntityType Optional. The type of the grid entity to use as a "base" for this
|
|
229
|
+
* custom grid entity. Default is `GridEntityType.DECORATION`.
|
|
230
|
+
* @param baseGridEntityVariant Optional. The variant of the grid entity to use as a "base" for this
|
|
231
|
+
* custom grid entity. Default is 0.
|
|
227
232
|
*/
|
|
228
233
|
export function spawnCustomGridEntity(
|
|
229
234
|
gridEntityTypeCustom: GridEntityType,
|
|
@@ -231,41 +236,28 @@ export function spawnCustomGridEntity(
|
|
|
231
236
|
gridCollisionClass: GridCollisionClass,
|
|
232
237
|
anm2Path: string,
|
|
233
238
|
defaultAnimation?: string,
|
|
234
|
-
|
|
239
|
+
baseGridEntityType = GridEntityType.DECORATION,
|
|
240
|
+
baseGridEntityVariant = 0,
|
|
235
241
|
): GridEntity {
|
|
236
242
|
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
237
243
|
|
|
238
|
-
if (breakable && gridCollisionClass === GridCollisionClass.NONE) {
|
|
239
|
-
error(
|
|
240
|
-
"Failed to spawn a custom grid entity because it is not possible to have breakable custom grid entities with a collision class of: GridCollisionClass.NONE (0)",
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
244
|
const room = game.GetRoom();
|
|
245
245
|
const roomListIndex = getRoomListIndex();
|
|
246
246
|
const gridIndex = isVector(gridIndexOrPosition)
|
|
247
247
|
? room.GetGridIndex(gridIndexOrPosition)
|
|
248
248
|
: gridIndexOrPosition;
|
|
249
249
|
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
? existingGridEntity
|
|
258
|
-
: spawnGridEntityWithVariant(
|
|
259
|
-
GridEntityType.DECORATION,
|
|
260
|
-
DecorationVariant.CUSTOM_GRID_ENTITY,
|
|
261
|
-
gridIndexOrPosition,
|
|
262
|
-
);
|
|
263
|
-
if (decoration === undefined) {
|
|
264
|
-
error("Failed to spawn a decoration for a custom grid entity.");
|
|
250
|
+
const customGridEntity = spawnGridEntityWithVariant(
|
|
251
|
+
baseGridEntityType,
|
|
252
|
+
baseGridEntityVariant,
|
|
253
|
+
gridIndexOrPosition,
|
|
254
|
+
);
|
|
255
|
+
if (customGridEntity === undefined) {
|
|
256
|
+
error("Failed to spawn a custom grid entity.");
|
|
265
257
|
}
|
|
266
|
-
|
|
258
|
+
customGridEntity.CollisionClass = gridCollisionClass;
|
|
267
259
|
|
|
268
|
-
const sprite =
|
|
260
|
+
const sprite = customGridEntity.GetSprite();
|
|
269
261
|
sprite.Load(anm2Path, true);
|
|
270
262
|
const animationToPlay =
|
|
271
263
|
defaultAnimation === undefined
|
|
@@ -286,25 +278,7 @@ export function spawnCustomGridEntity(
|
|
|
286
278
|
v.level.customGridEntities.getAndSetDefault(roomListIndex);
|
|
287
279
|
roomCustomGridEntities.set(gridIndex, customGridEntityData);
|
|
288
280
|
|
|
289
|
-
|
|
290
|
-
// the monitoring for explosions in the `ENTITY_TAKE_DMG` callback.
|
|
291
|
-
if (breakable) {
|
|
292
|
-
const position = room.GetGridPosition(gridIndex);
|
|
293
|
-
const entity = spawn(EntityType.GENERIC_PROP, 0, 0, position);
|
|
294
|
-
entity.ClearEntityFlags(EntityFlag.APPEAR);
|
|
295
|
-
entity.Visible = false;
|
|
296
|
-
|
|
297
|
-
// By default, it is larger than a grid tile, so make it a bit smaller.
|
|
298
|
-
entity.SizeMulti = Vector(
|
|
299
|
-
GENERIC_PROP_SIZE_MULTIPLIER,
|
|
300
|
-
GENERIC_PROP_SIZE_MULTIPLIER,
|
|
301
|
-
);
|
|
302
|
-
|
|
303
|
-
const ptrHash = GetPtrHash(entity);
|
|
304
|
-
v.room.genericPropPtrHashes.add(ptrHash);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return decoration;
|
|
281
|
+
return customGridEntity;
|
|
308
282
|
}
|
|
309
283
|
|
|
310
284
|
/**
|
|
@@ -326,6 +300,8 @@ export function removeCustomGridEntity(
|
|
|
326
300
|
gridIndexOrPositionOrGridEntity: int | Vector | GridEntity,
|
|
327
301
|
updateRoom = true,
|
|
328
302
|
): GridEntity | undefined {
|
|
303
|
+
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
304
|
+
|
|
329
305
|
const room = game.GetRoom();
|
|
330
306
|
const roomListIndex = getRoomListIndex();
|
|
331
307
|
|
|
@@ -371,6 +347,10 @@ export function removeCustomGridEntity(
|
|
|
371
347
|
export function getCustomGridEntities(): Array<
|
|
372
348
|
[gridEntity: GridEntity, data: GridEntityCustomData]
|
|
373
349
|
> {
|
|
350
|
+
if (!areFeaturesInitialized()) {
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
|
|
374
354
|
const roomListIndex = getRoomListIndex();
|
|
375
355
|
const roomCustomGridEntities = v.level.customGridEntities.get(roomListIndex);
|
|
376
356
|
if (roomCustomGridEntities === undefined) {
|
|
@@ -388,3 +368,49 @@ export function getCustomGridEntities(): Array<
|
|
|
388
368
|
|
|
389
369
|
return customGridEntities;
|
|
390
370
|
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Helper function to get the custom `GridEntityType` from a `GridEntity` or grid index. Returns
|
|
374
|
+
* undefined if the provided `GridEntity` is not a custom grid entity, or if there was not a grid
|
|
375
|
+
* entity on the provided grid index.
|
|
376
|
+
*/
|
|
377
|
+
export function getCustomGridEntityType(
|
|
378
|
+
gridEntityOrGridIndex: GridEntity | int,
|
|
379
|
+
): GridEntityType | undefined {
|
|
380
|
+
if (!areFeaturesInitialized()) {
|
|
381
|
+
return undefined;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const gridIndex = isNumber(gridEntityOrGridIndex)
|
|
385
|
+
? gridEntityOrGridIndex
|
|
386
|
+
: gridEntityOrGridIndex.GetGridIndex();
|
|
387
|
+
|
|
388
|
+
const roomListIndex = getRoomListIndex();
|
|
389
|
+
const roomCustomGridEntities = v.level.customGridEntities.get(roomListIndex);
|
|
390
|
+
if (roomCustomGridEntities === undefined) {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
for (const [_gridIndex, data] of roomCustomGridEntities.entries()) {
|
|
395
|
+
if (data.gridIndex === gridIndex) {
|
|
396
|
+
return data.gridEntityTypeCustom;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return undefined;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Helper function to check if a `GridEntity` is a custom grid entity or if a grid index has a
|
|
405
|
+
* custom grid entity.
|
|
406
|
+
*/
|
|
407
|
+
export function isCustomGridEntity(
|
|
408
|
+
gridEntityOrGridIndex: GridEntity | int,
|
|
409
|
+
): boolean {
|
|
410
|
+
if (!areFeaturesInitialized()) {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const gridEntityTypeCustom = getCustomGridEntityType(gridEntityOrGridIndex);
|
|
415
|
+
return gridEntityTypeCustom !== undefined;
|
|
416
|
+
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
LevelStage,
|
|
6
6
|
TrinketType,
|
|
7
7
|
} from "isaac-typescript-definitions";
|
|
8
|
-
import { DecorationVariant } from "../../enums/DecorationVariant";
|
|
9
8
|
import { removeEntities } from "../../functions/entities";
|
|
10
9
|
import { getNPCs } from "../../functions/entitiesSpecific";
|
|
11
10
|
import { removeGridEntity } from "../../functions/gridEntities";
|
|
@@ -15,10 +14,10 @@ import {
|
|
|
15
14
|
getTrinkets,
|
|
16
15
|
} from "../../functions/pickupsSpecific";
|
|
17
16
|
import { calculateStageType } from "../../functions/stage";
|
|
18
|
-
import { asNumber } from "../../functions/types";
|
|
19
17
|
import { vectorEquals } from "../../functions/vector";
|
|
20
18
|
import { CustomStage } from "../../interfaces/private/CustomStage";
|
|
21
19
|
import { TrapdoorDestination } from "../../types/TrapdoorDestination";
|
|
20
|
+
import { isCustomGridEntity } from "../customGridEntity";
|
|
22
21
|
import { spawnCustomTrapdoor } from "../customTrapdoor/exports";
|
|
23
22
|
import { DEFAULT_BASE_STAGE } from "./exports";
|
|
24
23
|
import v from "./v";
|
|
@@ -34,14 +33,12 @@ export function setCustomDecorationGraphics(
|
|
|
34
33
|
return;
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
if (gridEntityType !== GridEntityType.DECORATION) {
|
|
36
|
+
if (isCustomGridEntity(gridEntity)) {
|
|
39
37
|
return;
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (variant !== asNumber(DecorationVariant.VANILLA_DECORATION)) {
|
|
40
|
+
const gridEntityType = gridEntity.GetType();
|
|
41
|
+
if (gridEntityType !== GridEntityType.DECORATION) {
|
|
45
42
|
return;
|
|
46
43
|
}
|
|
47
44
|
|
|
@@ -65,6 +62,10 @@ export function setCustomRockGraphics(
|
|
|
65
62
|
return;
|
|
66
63
|
}
|
|
67
64
|
|
|
65
|
+
if (isCustomGridEntity(gridEntity)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
68
69
|
const gridEntityRock = gridEntity.ToRock();
|
|
69
70
|
if (gridEntityRock === undefined) {
|
|
70
71
|
return;
|
|
@@ -92,6 +93,10 @@ export function setCustomPitGraphics(
|
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
if (isCustomGridEntity(gridEntity)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
95
100
|
const gridEntityPit = gridEntity.ToPit();
|
|
96
101
|
if (gridEntityPit === undefined) {
|
|
97
102
|
return;
|
|
@@ -116,6 +121,10 @@ export function setCustomDoorGraphics(
|
|
|
116
121
|
return;
|
|
117
122
|
}
|
|
118
123
|
|
|
124
|
+
if (isCustomGridEntity(gridEntity)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
119
128
|
const gridEntityDoor = gridEntity.ToDoor();
|
|
120
129
|
if (gridEntityDoor === undefined) {
|
|
121
130
|
return;
|
|
@@ -2,7 +2,10 @@ import { sumArray } from "../../functions/array";
|
|
|
2
2
|
import { log } from "../../functions/log";
|
|
3
3
|
import { getRandomFloat } from "../../functions/random";
|
|
4
4
|
import { getRandomSeed } from "../../functions/rng";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CustomStageBossPoolEntry,
|
|
7
|
+
CustomStageRoomMetadata,
|
|
8
|
+
} from "../../interfaces/CustomStageTSConfig";
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Helper function to get a random custom stage room from an array of custom stage rooms.
|
|
@@ -52,3 +55,51 @@ function getCustomStageRoomWithChosenWeight(
|
|
|
52
55
|
`Failed to get a custom stage room with chosen weight: ${chosenWeight}`,
|
|
53
56
|
);
|
|
54
57
|
}
|
|
58
|
+
|
|
59
|
+
export function getRandomBossRoomFromPool(
|
|
60
|
+
roomsMetadata: readonly CustomStageRoomMetadata[],
|
|
61
|
+
bossPool: readonly CustomStageBossPoolEntry[],
|
|
62
|
+
seedOrRNG: Seed | RNG = getRandomSeed(),
|
|
63
|
+
verbose = false,
|
|
64
|
+
): CustomStageRoomMetadata {
|
|
65
|
+
const totalWeight = getTotalWeightOfBossPool(bossPool);
|
|
66
|
+
if (verbose) {
|
|
67
|
+
log(`Total weight of the custom stage boss pool provided: ${totalWeight}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const chosenWeight = getRandomFloat(0, totalWeight, seedOrRNG);
|
|
71
|
+
if (verbose) {
|
|
72
|
+
log(`Randomly chose weight for custom stage boss pool: ${chosenWeight}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const bossEntry = getBossEntryWithChosenWeight(bossPool, chosenWeight);
|
|
76
|
+
|
|
77
|
+
const roomsMetadataForBoss = roomsMetadata.filter(
|
|
78
|
+
(roomMetadata) => roomMetadata.subType === bossEntry.subType,
|
|
79
|
+
);
|
|
80
|
+
return getRandomCustomStageRoom(roomsMetadataForBoss, seedOrRNG, verbose);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getTotalWeightOfBossPool(
|
|
84
|
+
bossPool: readonly CustomStageBossPoolEntry[],
|
|
85
|
+
): float {
|
|
86
|
+
const weights = bossPool.map((bossEntry) => bossEntry.weight);
|
|
87
|
+
return sumArray(weights);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function getBossEntryWithChosenWeight(
|
|
91
|
+
bossPool: readonly CustomStageBossPoolEntry[],
|
|
92
|
+
chosenWeight: float,
|
|
93
|
+
): CustomStageBossPoolEntry {
|
|
94
|
+
for (const bossEntry of bossPool) {
|
|
95
|
+
if (chosenWeight < bossEntry.weight) {
|
|
96
|
+
return bossEntry;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
chosenWeight -= bossEntry.weight;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
error(
|
|
103
|
+
`Failed to get a custom stage boss entry with chosen weight: ${chosenWeight}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
DoorSlot,
|
|
12
12
|
LevelStage,
|
|
13
13
|
RoomShape,
|
|
14
14
|
RoomType,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "isaac-typescript-definitions";
|
|
17
17
|
import { reorderedCallbacksSetStageInternal } from "../../callbacks/reorderedCallbacks";
|
|
18
18
|
import { game } from "../../core/cachedClasses";
|
|
19
|
-
import {
|
|
19
|
+
import { doorSlotFlagsToDoorSlots } from "../../functions/doors";
|
|
20
20
|
import { logError } from "../../functions/log";
|
|
21
21
|
import { newRNG } from "../../functions/rng";
|
|
22
22
|
import {
|
|
@@ -25,13 +25,13 @@ import {
|
|
|
25
25
|
} from "../../functions/rooms";
|
|
26
26
|
import { setStage } from "../../functions/stage";
|
|
27
27
|
import { asNumber } from "../../functions/types";
|
|
28
|
+
import { CustomStageRoomMetadata } from "../../interfaces/CustomStageTSConfig";
|
|
28
29
|
import { CustomStage } from "../../interfaces/private/CustomStage";
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} from "./v";
|
|
30
|
+
import {
|
|
31
|
+
getRandomBossRoomFromPool,
|
|
32
|
+
getRandomCustomStageRoom,
|
|
33
|
+
} from "./customStageUtils";
|
|
34
|
+
import v, { customStageCachedRoomData, customStagesMap } from "./v";
|
|
35
35
|
|
|
36
36
|
export const DEFAULT_BASE_STAGE = LevelStage.BASEMENT_2;
|
|
37
37
|
export const DEFAULT_BASE_STAGE_TYPE = StageType.ORIGINAL;
|
|
@@ -135,8 +135,8 @@ function setStageRoomsData(
|
|
|
135
135
|
const roomType = room.Data.Type;
|
|
136
136
|
const roomShapeMap = customStage.roomTypeMap.get(roomType);
|
|
137
137
|
if (roomShapeMap === undefined) {
|
|
138
|
-
// Only show errors for non-default room types. (
|
|
139
|
-
// special rooms.)
|
|
138
|
+
// Only show errors for non-default room types. (We do not require that end-users provide
|
|
139
|
+
// custom rooms for shops and other special rooms inside of their XML file.)
|
|
140
140
|
if (roomType === RoomType.DEFAULT) {
|
|
141
141
|
logError(
|
|
142
142
|
`Failed to find any custom rooms for RoomType.${RoomType[roomType]} (${roomType}) for custom stage: ${customStage.name}`,
|
|
@@ -160,10 +160,32 @@ function setStageRoomsData(
|
|
|
160
160
|
logError(
|
|
161
161
|
`Failed to find any custom rooms for RoomType.${RoomType[roomType]} (${roomType}) + RoomShape.${RoomShape[roomShape]} (${roomShape}) + DoorSlotFlags ${doorSlotFlags} for custom stage: ${customStage.name}`,
|
|
162
162
|
);
|
|
163
|
+
|
|
164
|
+
const header = `For reference, a DoorSlotFlags of ${doorSlotFlags} is equal to the following doors being enabled:\n`;
|
|
165
|
+
const doorSlots = doorSlotFlagsToDoorSlots(doorSlotFlags);
|
|
166
|
+
const doorSlotLines = doorSlots.map(
|
|
167
|
+
(doorSlot) => `- DoorSlot.${DoorSlot[doorSlot]} (${doorSlot})`,
|
|
168
|
+
);
|
|
169
|
+
const explanation = header + doorSlotLines.join("\n");
|
|
170
|
+
logError(explanation);
|
|
163
171
|
continue;
|
|
164
172
|
}
|
|
165
173
|
|
|
166
|
-
|
|
174
|
+
let randomRoom: CustomStageRoomMetadata;
|
|
175
|
+
if (roomType === RoomType.BOSS) {
|
|
176
|
+
if (customStage.bossPool === undefined) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
randomRoom = getRandomBossRoomFromPool(
|
|
181
|
+
roomsMetadata,
|
|
182
|
+
customStage.bossPool,
|
|
183
|
+
rng,
|
|
184
|
+
verbose,
|
|
185
|
+
);
|
|
186
|
+
} else {
|
|
187
|
+
randomRoom = getRandomCustomStageRoom(roomsMetadata, rng, verbose);
|
|
188
|
+
}
|
|
167
189
|
|
|
168
190
|
let newRoomData = customStageCachedRoomData.get(randomRoom.variant);
|
|
169
191
|
if (newRoomData === undefined) {
|
|
@@ -187,40 +209,6 @@ function setStageRoomsData(
|
|
|
187
209
|
}
|
|
188
210
|
}
|
|
189
211
|
|
|
190
|
-
/**
|
|
191
|
-
* By default, unknown bosses will be drawn on the boss "versus" screen as "???". If your custom
|
|
192
|
-
* stage has custom bosses, you can use this function to register the corresponding graphic file
|
|
193
|
-
* files for them.
|
|
194
|
-
*
|
|
195
|
-
* For reference:
|
|
196
|
-
* - The vanilla name sprite for Monstro is located at:
|
|
197
|
-
* `resources/gfx/ui/boss/bossname_20.0_monstro.png`
|
|
198
|
-
* - The vanilla portrait sprite for Monstro is located at:
|
|
199
|
-
* `resources/gfx/ui/boss/portrait_20.0_monstro.png`
|
|
200
|
-
*
|
|
201
|
-
* (Note that boss metadata like this cannot be specified with the rest of the custom stage metadata
|
|
202
|
-
* in the "tsconfig.json" file because there is not a way to retrieve the name of an entity at
|
|
203
|
-
* run-time.)
|
|
204
|
-
*
|
|
205
|
-
* @param entityType The entity type of the custom boss.
|
|
206
|
-
* @param variant The variant of the custom boss.
|
|
207
|
-
* @param subType The sub-type of the custom boss.
|
|
208
|
-
* @param namePNGPath The full path to the PNG file that contains the name of the boss that will be
|
|
209
|
-
* displayed on the top of the boss "versus" screen.
|
|
210
|
-
* @param portraitPNGPath The full path to the PNG file that contains the portrait of the boss that
|
|
211
|
-
* will be displayed on the right side of the boss "versus" screen.
|
|
212
|
-
*/
|
|
213
|
-
export function registerCustomBoss(
|
|
214
|
-
entityType: EntityType,
|
|
215
|
-
variant: int,
|
|
216
|
-
subType: int,
|
|
217
|
-
namePNGPath: string,
|
|
218
|
-
portraitPNGPath: string,
|
|
219
|
-
): void {
|
|
220
|
-
const entityID = getEntityIDFromConstituents(entityType, variant, subType);
|
|
221
|
-
customBossPNGPaths.set(entityID, [namePNGPath, portraitPNGPath]);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
212
|
/**
|
|
225
213
|
* Helper function to disable the custom stage. This is typically called before taking the player to
|
|
226
214
|
* a vanilla floor.
|
|
@@ -13,7 +13,7 @@ import { hasFlag, removeFlag } from "../../functions/flag";
|
|
|
13
13
|
import {
|
|
14
14
|
CustomStageLua,
|
|
15
15
|
CustomStageRoomMetadata,
|
|
16
|
-
} from "../../interfaces/
|
|
16
|
+
} from "../../interfaces/CustomStageTSConfig";
|
|
17
17
|
import { CustomStage, RoomTypeMap } from "../../interfaces/private/CustomStage";
|
|
18
18
|
import { saveDataManager } from "../saveDataManager/exports";
|
|
19
19
|
import { setCustomStageBackdrop } from "./backdrop";
|
|
@@ -40,9 +40,3 @@ export const customStagesMap = new Map<string, CustomStage>();
|
|
|
40
40
|
|
|
41
41
|
/** Indexed by room variant. */
|
|
42
42
|
export const customStageCachedRoomData = new Map<int, Readonly<RoomConfig>>();
|
|
43
|
-
|
|
44
|
-
/** Indexed by entity ID. */
|
|
45
|
-
export const customBossPNGPaths = new Map<
|
|
46
|
-
string,
|
|
47
|
-
[namePNGPath: string, portraitPNGPath: string]
|
|
48
|
-
>();
|