isaacscript-common 6.20.1 → 6.22.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/constants.d.ts +6 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.lua +4 -0
- package/dist/constantsFirstLast.d.ts +2 -2
- package/dist/constantsFirstLast.lua +2 -2
- package/dist/enums/RockAltType.d.ts +12 -1
- package/dist/enums/RockAltType.d.ts.map +1 -1
- package/dist/enums/RockAltType.lua +4 -2
- package/dist/enums/private/StageTravelState.d.ts +4 -3
- package/dist/enums/private/StageTravelState.d.ts.map +1 -1
- package/dist/enums/private/StageTravelState.lua +6 -4
- package/dist/features/customStage/backdrop.d.ts.map +1 -1
- package/dist/features/customStage/backdrop.lua +3 -2
- package/dist/features/customStage/customStageConstants.d.ts +11 -0
- package/dist/features/customStage/customStageConstants.d.ts.map +1 -1
- package/dist/features/customStage/customStageConstants.lua +10 -0
- package/dist/features/customStage/customStageGridEntities.d.ts +1 -0
- package/dist/features/customStage/customStageGridEntities.d.ts.map +1 -1
- package/dist/features/customStage/customStageGridEntities.lua +65 -23
- package/dist/features/customStage/exports.d.ts +17 -3
- package/dist/features/customStage/exports.d.ts.map +1 -1
- package/dist/features/customStage/exports.lua +65 -46
- package/dist/features/customStage/init.d.ts.map +1 -1
- package/dist/features/customStage/init.lua +7 -12
- package/dist/features/customStage/shadows.d.ts.map +1 -1
- package/dist/features/customStage/shadows.lua +2 -1
- package/dist/features/customStage/streakText.d.ts +0 -7
- package/dist/features/customStage/streakText.d.ts.map +1 -1
- package/dist/features/customStage/streakText.lua +52 -85
- package/dist/features/customStage/v.d.ts +13 -0
- package/dist/features/customStage/v.d.ts.map +1 -1
- package/dist/features/customStage/v.lua +6 -1
- package/dist/features/customStage/versusScreen.d.ts.map +1 -1
- package/dist/features/customStage/versusScreen.lua +32 -1
- package/dist/features/customTrapdoor/blackSprite.d.ts.map +1 -1
- package/dist/features/customTrapdoor/blackSprite.lua +2 -1
- package/dist/features/customTrapdoor/customTrapdoorConstants.d.ts +4 -0
- package/dist/features/customTrapdoor/customTrapdoorConstants.d.ts.map +1 -1
- package/dist/features/customTrapdoor/exports.d.ts +11 -7
- package/dist/features/customTrapdoor/exports.d.ts.map +1 -1
- package/dist/features/customTrapdoor/exports.lua +6 -5
- package/dist/features/customTrapdoor/init.d.ts.map +1 -1
- package/dist/features/customTrapdoor/init.lua +35 -20
- package/dist/features/customTrapdoor/touched.lua +1 -1
- package/dist/features/customTrapdoor/v.d.ts +2 -2
- package/dist/features/customTrapdoor/v.d.ts.map +1 -1
- package/dist/features/extraConsoleCommands/commandsSubroutines.d.ts.map +1 -1
- package/dist/features/extraConsoleCommands/commandsSubroutines.lua +3 -3
- package/dist/features/playerInventory.d.ts +7 -0
- package/dist/features/playerInventory.d.ts.map +1 -1
- package/dist/features/playerInventory.lua +7 -0
- package/dist/features/saveDataManager/exports.d.ts +3 -0
- package/dist/features/saveDataManager/exports.d.ts.map +1 -1
- package/dist/features/saveDataManager/exports.lua +3 -0
- package/dist/functions/collectibleSet.d.ts +1 -1
- package/dist/functions/collectibleSet.lua +1 -1
- package/dist/functions/doors.d.ts +10 -0
- package/dist/functions/doors.d.ts.map +1 -1
- package/dist/functions/doors.lua +6 -0
- package/dist/functions/levelGrid.lua +1 -1
- package/dist/functions/log.d.ts +1 -15
- package/dist/functions/log.d.ts.map +1 -1
- package/dist/functions/log.lua +3 -218
- package/dist/functions/logEntities.d.ts +16 -0
- package/dist/functions/logEntities.d.ts.map +1 -0
- package/dist/functions/logEntities.lua +220 -0
- package/dist/functions/rockAlt.d.ts +6 -5
- package/dist/functions/rockAlt.d.ts.map +1 -1
- package/dist/functions/rockAlt.lua +147 -18
- package/dist/functions/roomData.d.ts +1 -1
- package/dist/functions/roomData.d.ts.map +1 -1
- package/dist/functions/roomTransition.d.ts +26 -0
- package/dist/functions/roomTransition.d.ts.map +1 -0
- package/dist/functions/roomTransition.lua +75 -0
- package/dist/functions/rooms.d.ts +36 -35
- package/dist/functions/rooms.d.ts.map +1 -1
- package/dist/functions/rooms.lua +94 -99
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.lua +8 -0
- package/dist/interfaces/private/CustomTrapdoorDescription.d.ts +2 -2
- package/dist/interfaces/private/CustomTrapdoorDescription.d.ts.map +1 -1
- package/dist/objects/backdropTypeToRockAltType.lua +3 -3
- package/dist/types/TrapdoorDestination.d.ts +3 -0
- package/dist/types/TrapdoorDestination.d.ts.map +1 -0
- package/dist/types/TrapdoorDestination.lua +2 -0
- package/package.json +2 -2
- package/src/constants.ts +6 -0
- package/src/constantsFirstLast.ts +2 -2
- package/src/enums/RockAltType.ts +14 -1
- package/src/enums/private/StageTravelState.ts +2 -1
- package/src/features/customStage/backdrop.ts +2 -1
- package/src/features/customStage/customStageConstants.ts +16 -0
- package/src/features/customStage/customStageGridEntities.ts +61 -0
- package/src/features/customStage/exports.ts +81 -42
- package/src/features/customStage/init.ts +7 -18
- package/src/features/customStage/shadows.ts +2 -1
- package/src/features/customStage/streakText.ts +59 -96
- package/src/features/customStage/v.ts +17 -0
- package/src/features/customStage/versusScreen.ts +29 -0
- package/src/features/customTrapdoor/blackSprite.ts +6 -1
- package/src/features/customTrapdoor/customTrapdoorConstants.ts +4 -0
- package/src/features/customTrapdoor/exports.ts +8 -6
- package/src/features/customTrapdoor/init.ts +55 -23
- package/src/features/customTrapdoor/touched.ts +4 -1
- package/src/features/customTrapdoor/v.ts +2 -5
- package/src/features/extraConsoleCommands/commandsSubroutines.ts +4 -1
- package/src/features/playerInventory.ts +7 -0
- package/src/features/saveDataManager/exports.ts +3 -0
- package/src/functions/collectibleSet.ts +1 -1
- package/src/functions/doors.ts +10 -0
- package/src/functions/levelGrid.ts +1 -1
- package/src/functions/log.ts +1 -279
- package/src/functions/logEntities.ts +276 -0
- package/src/functions/rockAlt.ts +147 -19
- package/src/functions/roomData.ts +1 -1
- package/src/functions/roomTransition.ts +78 -0
- package/src/functions/rooms.ts +104 -107
- package/src/index.ts +1 -0
- package/src/interfaces/private/CustomTrapdoorDescription.ts +2 -2
- package/src/objects/backdropTypeToRockAltType.ts +3 -3
- package/src/types/TrapdoorDestination.ts +5 -0
|
@@ -9,13 +9,18 @@ import v from "./v";
|
|
|
9
9
|
const blackSprite = Sprite();
|
|
10
10
|
|
|
11
11
|
export function drawBlackSprite(): void {
|
|
12
|
-
if (
|
|
12
|
+
if (
|
|
13
|
+
v.run.state !== StageTravelState.WAITING_FOR_FIRST_PIXELATION_TO_END &&
|
|
14
|
+
v.run.state !==
|
|
15
|
+
StageTravelState.WAITING_FOR_SECOND_PIXELATION_TO_GET_HALF_WAY
|
|
16
|
+
) {
|
|
13
17
|
return;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
if (!blackSprite.IsLoaded()) {
|
|
17
21
|
blackSprite.Load("gfx/ui/boss/versusscreen.anm2", true);
|
|
18
22
|
blackSprite.SetFrame("Scene", 0);
|
|
23
|
+
blackSprite.Scale = Vector(100, 100);
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
blackSprite.RenderLayer(0, VectorZero);
|
|
@@ -3,6 +3,10 @@ import { GridEntityType } from "isaac-typescript-definitions";
|
|
|
3
3
|
export const CUSTOM_TRAPDOOR_FEATURE_NAME = "customTrapdoor";
|
|
4
4
|
|
|
5
5
|
export const GridEntityTypeCustom = {
|
|
6
|
+
/**
|
|
7
|
+
* We arbitrarily choose 1000 as to not conflict with end-user mods. (The expectation is that
|
|
8
|
+
* end-user mods will begin their enums with values of 1 and increment upwards.)
|
|
9
|
+
*/
|
|
6
10
|
TRAPDOOR_CUSTOM: 1000 as GridEntityType,
|
|
7
11
|
} as const;
|
|
8
12
|
|
|
@@ -10,6 +10,7 @@ import { getNextStage, getNextStageType } from "../../functions/nextStage";
|
|
|
10
10
|
import { getRoomListIndex } from "../../functions/roomData";
|
|
11
11
|
import { isVector } from "../../functions/vector";
|
|
12
12
|
import { CustomTrapdoorDescription } from "../../interfaces/private/CustomTrapdoorDescription";
|
|
13
|
+
import { TrapdoorDestination } from "../../types/TrapdoorDestination";
|
|
13
14
|
import { spawnCustomGridEntity } from "../customGridEntity";
|
|
14
15
|
import {
|
|
15
16
|
CUSTOM_TRAPDOOR_FEATURE_NAME,
|
|
@@ -25,7 +26,6 @@ import v from "./v";
|
|
|
25
26
|
* - custom destination (or custom logic for after the player enters)
|
|
26
27
|
* - custom graphics
|
|
27
28
|
* - custom logic for opening/closing
|
|
28
|
-
* - TODO: player jumping animation?
|
|
29
29
|
*
|
|
30
30
|
* You can use this function to take the player to your custom stage.
|
|
31
31
|
*
|
|
@@ -34,10 +34,12 @@ import v from "./v";
|
|
|
34
34
|
*
|
|
35
35
|
* @param gridIndexOrPosition The location in the room to spawn the trapdoor.
|
|
36
36
|
* @param destination Optional. Used to specify where the player will go after jumping into the
|
|
37
|
-
* trapdoor. Can either be a
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
37
|
+
* trapdoor. Can either be a vanilla stage tuple, a custom stage tuple, or
|
|
38
|
+
* undefined. For example, a destination of `[LevelStage.CAVES_1,
|
|
39
|
+
* StageType.ORIGINAL]` corresponds to Caves 1, and a destination of
|
|
40
|
+
* `["Slaughterhouse", 1]` corresponds to a custom stage of Slaughterhouse 1. If
|
|
41
|
+
* the destination is undefined, then the "normal" destination corresponding to
|
|
42
|
+
* the current stage and room will be used (e.g. the next floor, in most cases).
|
|
41
43
|
* @param anm2Path Optional. The path to the anm2 file to use. By default, the vanilla trapdoor anm2
|
|
42
44
|
* of "gfx/grid/door_11_trapdoor.anm2" will be used. The specified anm2 file must
|
|
43
45
|
* have animations called "Opened", "Closed", and "Open Animation".
|
|
@@ -46,7 +48,7 @@ import v from "./v";
|
|
|
46
48
|
*/
|
|
47
49
|
export function spawnCustomTrapdoor(
|
|
48
50
|
gridIndexOrPosition: int | Vector,
|
|
49
|
-
destination?:
|
|
51
|
+
destination?: TrapdoorDestination,
|
|
50
52
|
anm2Path = "gfx/grid/door_11_trapdoor.anm2",
|
|
51
53
|
spawnOpen?: boolean,
|
|
52
54
|
): GridEntity {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Direction,
|
|
3
|
+
EntityCollisionClass,
|
|
4
|
+
EntityGridCollisionClass,
|
|
3
5
|
ModCallback,
|
|
4
6
|
RoomTransitionAnim,
|
|
7
|
+
StageType,
|
|
5
8
|
} from "isaac-typescript-definitions";
|
|
6
9
|
import { game } from "../../cachedClasses";
|
|
7
10
|
import { ModUpgraded } from "../../classes/ModUpgraded";
|
|
@@ -10,10 +13,10 @@ import { StageTravelState } from "../../enums/private/StageTravelState";
|
|
|
10
13
|
import { movePlayersToCenter } from "../../functions/playerCenter";
|
|
11
14
|
import { getAllPlayers } from "../../functions/playerIndex";
|
|
12
15
|
import { getRoomGridIndex, getRoomListIndex } from "../../functions/roomData";
|
|
13
|
-
import { teleport } from "../../functions/
|
|
16
|
+
import { teleport } from "../../functions/roomTransition";
|
|
14
17
|
import { setStage } from "../../functions/stage";
|
|
15
18
|
import { isString } from "../../functions/types";
|
|
16
|
-
import { setCustomStage } from "../customStage/exports";
|
|
19
|
+
import { disableCustomStage, setCustomStage } from "../customStage/exports";
|
|
17
20
|
import { topStreakTextStart } from "../customStage/streakText";
|
|
18
21
|
import { enableAllInputs } from "../disableInputs";
|
|
19
22
|
import { runNextGameFrame } from "../runInNFrames";
|
|
@@ -45,7 +48,7 @@ export function customTrapdoorInit(mod: ModUpgraded): void {
|
|
|
45
48
|
function postRender() {
|
|
46
49
|
checkAllPlayersJumpComplete();
|
|
47
50
|
checkPixelationToBlackComplete();
|
|
48
|
-
|
|
51
|
+
checkSecondPixelationHalfWay();
|
|
49
52
|
checkAllPlayersLayingDownComplete();
|
|
50
53
|
drawBlackSprite();
|
|
51
54
|
}
|
|
@@ -74,6 +77,8 @@ function checkAllPlayersJumpComplete() {
|
|
|
74
77
|
Direction.NO_DIRECTION,
|
|
75
78
|
RoomTransitionAnim.PIXELATION,
|
|
76
79
|
);
|
|
80
|
+
|
|
81
|
+
// Next, we wait a certain amount of render frames for the pixelation to fade the screen to black.
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
function checkPixelationToBlackComplete() {
|
|
@@ -86,7 +91,6 @@ function checkPixelationToBlackComplete() {
|
|
|
86
91
|
|
|
87
92
|
const hud = game.GetHUD();
|
|
88
93
|
const renderFrameCount = Isaac.GetFrameCount();
|
|
89
|
-
const roomGridIndex = getRoomGridIndex();
|
|
90
94
|
|
|
91
95
|
const renderFrameScreenBlack =
|
|
92
96
|
v.run.stateRenderFrame + PIXELATION_TO_BLACK_FRAMES;
|
|
@@ -94,25 +98,44 @@ function checkPixelationToBlackComplete() {
|
|
|
94
98
|
return;
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
v.run.state = StageTravelState.
|
|
98
|
-
v.run.stateRenderFrame = renderFrameCount;
|
|
101
|
+
v.run.state = StageTravelState.WAITING_FOR_FIRST_PIXELATION_TO_END;
|
|
99
102
|
|
|
103
|
+
// Now, we display a black sprite on top of the pixelation effect, to prevent showing the rest of
|
|
104
|
+
// the animation.
|
|
100
105
|
hud.SetVisible(false);
|
|
101
|
-
goToCustomDestination();
|
|
102
106
|
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
// If the pixelation effect is not fully allowed to complete, the game's internal buffer will not
|
|
108
|
+
// be flushed. The consequence of this is that after 11 custom stage transitions, the "log.txt"
|
|
109
|
+
// starts to become become spammed with: [ASSERT] - PushRenderTarget: stack overflow!
|
|
110
|
+
|
|
111
|
+
// In order to work around this, we fully let the animation complete by only continuing the stage
|
|
112
|
+
// transition on the next game frame.
|
|
113
|
+
runNextGameFrame(() => {
|
|
114
|
+
const level = game.GetLevel();
|
|
115
|
+
const startingRoomIndex = level.GetStartingRoomIndex();
|
|
116
|
+
const futureRenderFrameCount = Isaac.GetFrameCount();
|
|
117
|
+
|
|
118
|
+
v.run.state =
|
|
119
|
+
StageTravelState.WAITING_FOR_SECOND_PIXELATION_TO_GET_HALF_WAY;
|
|
120
|
+
v.run.stateRenderFrame = futureRenderFrameCount;
|
|
121
|
+
|
|
122
|
+
goToCustomDestination();
|
|
123
|
+
|
|
124
|
+
// Start another pixelation effect. This time, we will keep the screen black with the sprite,
|
|
125
|
+
// and then remove the black sprite once the pixelation effect is halfway complete.
|
|
126
|
+
teleport(
|
|
127
|
+
startingRoomIndex,
|
|
128
|
+
Direction.NO_DIRECTION,
|
|
129
|
+
RoomTransitionAnim.PIXELATION,
|
|
130
|
+
true,
|
|
131
|
+
);
|
|
132
|
+
});
|
|
111
133
|
}
|
|
112
134
|
|
|
113
|
-
function
|
|
135
|
+
function checkSecondPixelationHalfWay() {
|
|
114
136
|
if (
|
|
115
|
-
v.run.state !==
|
|
137
|
+
v.run.state !==
|
|
138
|
+
StageTravelState.WAITING_FOR_SECOND_PIXELATION_TO_GET_HALF_WAY ||
|
|
116
139
|
v.run.stateRenderFrame === null
|
|
117
140
|
) {
|
|
118
141
|
return;
|
|
@@ -132,14 +155,18 @@ function checkPausingOnBlackComplete() {
|
|
|
132
155
|
hud.SetVisible(true);
|
|
133
156
|
|
|
134
157
|
runNextRoom(() => {
|
|
158
|
+
v.run.state = StageTravelState.PLAYERS_LAYING_DOWN;
|
|
159
|
+
|
|
135
160
|
// After the room transition, the players will be placed next to a door, but they should be in
|
|
136
161
|
// the center of the room to emulate what happens on a vanilla stage.
|
|
137
162
|
movePlayersToCenter();
|
|
138
163
|
|
|
139
|
-
v.run.state = StageTravelState.PLAYERS_LAYING_DOWN;
|
|
140
|
-
|
|
141
164
|
for (const player of getAllPlayers()) {
|
|
142
165
|
player.AnimateAppear();
|
|
166
|
+
|
|
167
|
+
// We need to restore the original collision classes.
|
|
168
|
+
player.EntityCollisionClass = EntityCollisionClass.ALL;
|
|
169
|
+
player.GridCollisionClass = EntityGridCollisionClass.GROUND;
|
|
143
170
|
}
|
|
144
171
|
});
|
|
145
172
|
|
|
@@ -171,11 +198,16 @@ function goToCustomDestination() {
|
|
|
171
198
|
return;
|
|
172
199
|
}
|
|
173
200
|
|
|
174
|
-
|
|
175
|
-
|
|
201
|
+
const [arg1, arg2] = v.run.destination;
|
|
202
|
+
|
|
203
|
+
if (isString(arg1)) {
|
|
204
|
+
// A string represents a custom stage.
|
|
205
|
+
const firstFloor = arg2 === 1;
|
|
206
|
+
setCustomStage("Slaughterhouse", firstFloor);
|
|
176
207
|
} else {
|
|
177
|
-
|
|
178
|
-
|
|
208
|
+
// A number represents a vanilla `LevelStage`.
|
|
209
|
+
disableCustomStage();
|
|
210
|
+
setStage(arg1, arg2 as StageType);
|
|
179
211
|
}
|
|
180
212
|
}
|
|
181
213
|
|
|
@@ -81,6 +81,9 @@ function playerTouchedCustomTrapdoor(
|
|
|
81
81
|
v.run.state = StageTravelState.PLAYERS_JUMPING_DOWN;
|
|
82
82
|
v.run.destination = trapdoorDescription.destination;
|
|
83
83
|
|
|
84
|
+
// We don't want to allow pausing, since that will allow render frames to pass without advancing
|
|
85
|
+
// the stage traveling logic. (We track how many render frames have passed to know when to move to
|
|
86
|
+
// the next step.)
|
|
84
87
|
const whitelist = new Set([ButtonAction.CONSOLE]);
|
|
85
88
|
disableAllInputsExceptFor(CUSTOM_TRAPDOOR_FEATURE_NAME, whitelist);
|
|
86
89
|
setPlayerAttributes(player, gridEntity.Position);
|
|
@@ -115,7 +118,7 @@ function setPlayerAttributes(trapdoorPlayer: EntityPlayer, position: Vector) {
|
|
|
115
118
|
player.EntityCollisionClass = EntityCollisionClass.NONE;
|
|
116
119
|
player.GridCollisionClass = EntityGridCollisionClass.NONE;
|
|
117
120
|
|
|
118
|
-
player.
|
|
121
|
+
player.StopExtraAnimation();
|
|
119
122
|
}
|
|
120
123
|
}
|
|
121
124
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { LevelStage, StageType } from "isaac-typescript-definitions";
|
|
2
1
|
import { DefaultMap } from "../../classes/DefaultMap";
|
|
3
2
|
import { StageTravelState } from "../../enums/private/StageTravelState";
|
|
4
3
|
import { CustomTrapdoorDescription } from "../../interfaces/private/CustomTrapdoorDescription";
|
|
4
|
+
import { TrapdoorDestination } from "../../types/TrapdoorDestination";
|
|
5
5
|
|
|
6
6
|
const v = {
|
|
7
7
|
run: {
|
|
@@ -10,10 +10,7 @@ const v = {
|
|
|
10
10
|
/** The render frame that this state was reached. */
|
|
11
11
|
stateRenderFrame: null as int | null,
|
|
12
12
|
|
|
13
|
-
destination: null as
|
|
14
|
-
| [stage: LevelStage, stageType: StageType]
|
|
15
|
-
| string
|
|
16
|
-
| null,
|
|
13
|
+
destination: null as TrapdoorDestination | null,
|
|
17
14
|
},
|
|
18
15
|
|
|
19
16
|
level: {
|
|
@@ -10,7 +10,10 @@ import { HealthType } from "../../enums/HealthType";
|
|
|
10
10
|
import { directionToVector } from "../../functions/direction";
|
|
11
11
|
import { spawnGridEntityWithVariant } from "../../functions/gridEntities";
|
|
12
12
|
import { getRoomGridIndexesForType } from "../../functions/levelGrid";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
logAllEntities,
|
|
15
|
+
logAllGridEntities,
|
|
16
|
+
} from "../../functions/logEntities";
|
|
14
17
|
import { addPlayerHealthType } from "../../functions/playerHealth";
|
|
15
18
|
import { getRoomData, getRoomDescriptor } from "../../functions/roomData";
|
|
16
19
|
import { changeRoom } from "../../functions/rooms";
|
|
@@ -114,6 +114,13 @@ function postCollectibleRemoved(
|
|
|
114
114
|
* middle of the run (e.g. with D4), the order of the inventory will not correspond to the order
|
|
115
115
|
* that the items were actually given to the player. In this case, the inventory will be in the
|
|
116
116
|
* order of the lowest `CollectibleType` to the highest.
|
|
117
|
+
*
|
|
118
|
+
* Under the hood, the inventory tracking works by tracking the number of collectibles that a player
|
|
119
|
+
* has on every frame. Thus, in a situation where a collectible was both added and removed to the
|
|
120
|
+
* player on the same frame, the amount of total collectibles would stay the same, and the inventory
|
|
121
|
+
* would not be updated. In vanilla, this situation would never happen, but another mod might do
|
|
122
|
+
* this for some reason. (With that said, the next time that a collectible is normally added or
|
|
123
|
+
* removed, it would trigger a re-scan, and the previous changes would be picked up.)
|
|
117
124
|
*/
|
|
118
125
|
export function getPlayerInventory(
|
|
119
126
|
player: EntityPlayer,
|
|
@@ -76,6 +76,9 @@ import { SAVE_DATA_MANAGER_FEATURE_NAME } from "./saveDataManagerConstants";
|
|
|
76
76
|
* can possibly run).
|
|
77
77
|
* - Save data is recorded to disk in the `PRE_GAME_EXIT` callback.
|
|
78
78
|
*
|
|
79
|
+
* You can put lots of data types on your variable objects, but not everything is supported. For the
|
|
80
|
+
* specific things that are supported, see the documentation for the `deepCopy` helper function.
|
|
81
|
+
*
|
|
79
82
|
* Note that before using the save data manager, you must call the `upgradeMod` function. (Upgrade
|
|
80
83
|
* your mod before registering any of your own callbacks so that the save data manager will run
|
|
81
84
|
* before any of your code does.)
|
|
@@ -58,7 +58,7 @@ function initCollectibleArraysAndSets() {
|
|
|
58
58
|
* collectibles.
|
|
59
59
|
*
|
|
60
60
|
* Use this if you need to iterate over the collectibles in order. If you need to do O(1) lookups,
|
|
61
|
-
* then use the `
|
|
61
|
+
* then use the `getCollectibleSet` helper function instead.
|
|
62
62
|
*/
|
|
63
63
|
export function getCollectibleArray(): readonly CollectibleType[] {
|
|
64
64
|
// Lazy initialize the arrays/sets.
|
package/src/functions/doors.ts
CHANGED
|
@@ -181,6 +181,12 @@ export function getOppositeDoorSlot(doorSlot: DoorSlot): DoorSlot | undefined {
|
|
|
181
181
|
return OPPOSITE_DOOR_SLOTS[doorSlot];
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Helper function to get the door that leads to the "secret exit" off-grid room that takes you to
|
|
186
|
+
* the Repentance floor.
|
|
187
|
+
*
|
|
188
|
+
* Returns undefined if the room has no Repentance doors.
|
|
189
|
+
*/
|
|
184
190
|
export function getRepentanceDoor(): GridEntityDoor | undefined {
|
|
185
191
|
const doors = getDoors();
|
|
186
192
|
return doors.find((door) => isRepentanceDoor(door));
|
|
@@ -330,6 +336,10 @@ export function isHiddenSecretRoomDoor(door: GridEntityDoor): boolean {
|
|
|
330
336
|
return isSecretRoomDoor(door) && animation === "Hidden";
|
|
331
337
|
}
|
|
332
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Helper function to check if the provided door leads to the "secret exit" off-grid room that takes
|
|
341
|
+
* you to the Repentance floor.
|
|
342
|
+
*/
|
|
333
343
|
export function isRepentanceDoor(door: GridEntityDoor): boolean {
|
|
334
344
|
// eslint-disable-next-line isaacscript/strict-enums
|
|
335
345
|
return door.TargetRoomIndex === GridRoom.SECRET_EXIT;
|
|
@@ -207,7 +207,7 @@ export function getNewRoomCandidatesForLevel(): Array<
|
|
|
207
207
|
export function getRoomGridIndexesForType(...roomTypes: RoomType[]): int[] {
|
|
208
208
|
const roomTypesSet = new Set<RoomType>([...roomTypes]);
|
|
209
209
|
|
|
210
|
-
const rooms =
|
|
210
|
+
const rooms = getRoomsInGrid();
|
|
211
211
|
const matchingRooms = rooms.filter(
|
|
212
212
|
(roomDescriptor) =>
|
|
213
213
|
roomDescriptor.Data !== undefined &&
|
package/src/functions/log.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DamageFlag,
|
|
3
|
-
EffectVariant,
|
|
4
3
|
EntityFlag,
|
|
5
|
-
EntityType,
|
|
6
4
|
GameStateFlag,
|
|
7
|
-
GridEntityType,
|
|
8
5
|
GridRoom,
|
|
9
6
|
HeartSubType,
|
|
10
7
|
LevelStateFlag,
|
|
@@ -17,10 +14,9 @@ import {
|
|
|
17
14
|
import { game, sfxManager } from "../cachedClasses";
|
|
18
15
|
import { arrayToString } from "./array";
|
|
19
16
|
import { getCollectibleName } from "./collectibles";
|
|
20
|
-
import {
|
|
17
|
+
import { getEntityID } from "./entities";
|
|
21
18
|
import { getEnumEntries } from "./enums";
|
|
22
19
|
import { hasFlag } from "./flag";
|
|
23
|
-
import { getGridEntities, getGridEntityID } from "./gridEntities";
|
|
24
20
|
import { getIsaacAPIClassName } from "./isaacAPIClass";
|
|
25
21
|
import { getPlayerHealth } from "./playerHealth";
|
|
26
22
|
import { getEffectsList, getPlayerName } from "./players";
|
|
@@ -32,18 +28,6 @@ import { isTable, isUserdata } from "./types";
|
|
|
32
28
|
import { printConsole } from "./utils";
|
|
33
29
|
import { vectorToString } from "./vector";
|
|
34
30
|
|
|
35
|
-
const IGNORE_EFFECT_VARIANTS: ReadonlySet<EffectVariant> = new Set([
|
|
36
|
-
EffectVariant.BLOOD_EXPLOSION, // 2
|
|
37
|
-
EffectVariant.BLOOD_PARTICLE, // 5
|
|
38
|
-
EffectVariant.TINY_BUG, // 21
|
|
39
|
-
EffectVariant.TINY_FLY, // 33
|
|
40
|
-
EffectVariant.WATER_DROPLET, // 41
|
|
41
|
-
EffectVariant.WALL_BUG, // 68
|
|
42
|
-
EffectVariant.FALLING_EMBER, // 87
|
|
43
|
-
EffectVariant.LIGHT, // 121
|
|
44
|
-
EffectVariant.TADPOLE, // 158
|
|
45
|
-
]);
|
|
46
|
-
|
|
47
31
|
/**
|
|
48
32
|
* Helper function to prefix the name of the function and the line number before a debug message.
|
|
49
33
|
*/
|
|
@@ -84,106 +68,6 @@ export function log(this: void, msg: string): void {
|
|
|
84
68
|
Isaac.DebugString(debugMsg);
|
|
85
69
|
}
|
|
86
70
|
|
|
87
|
-
/** Helper function for printing out every entity (or filtered entity) in the current room. */
|
|
88
|
-
export function logAllEntities(
|
|
89
|
-
this: void,
|
|
90
|
-
includeBackgroundEffects: boolean,
|
|
91
|
-
entityTypeFilter?: EntityType,
|
|
92
|
-
): void {
|
|
93
|
-
let msg = "Entities in the room";
|
|
94
|
-
if (entityTypeFilter !== undefined) {
|
|
95
|
-
msg += ` (filtered to entity type ${entityTypeFilter})`;
|
|
96
|
-
} else if (!includeBackgroundEffects) {
|
|
97
|
-
msg += " (not including background effects)";
|
|
98
|
-
}
|
|
99
|
-
msg += ":\n";
|
|
100
|
-
|
|
101
|
-
const entities = getEntities();
|
|
102
|
-
let numMatchedEntities = 0;
|
|
103
|
-
entities.forEach((entity, i) => {
|
|
104
|
-
// If a filter was specified, exclude all entities outside of the filter.
|
|
105
|
-
if (entityTypeFilter !== undefined && entity.Type !== entityTypeFilter) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const effect = entity.ToEffect();
|
|
110
|
-
if (
|
|
111
|
-
!includeBackgroundEffects &&
|
|
112
|
-
effect !== undefined &&
|
|
113
|
-
IGNORE_EFFECT_VARIANTS.has(effect.Variant)
|
|
114
|
-
) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
msg += getEntityLogLine(entity, i + 1);
|
|
119
|
-
numMatchedEntities++;
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
if (numMatchedEntities === 0) {
|
|
123
|
-
msg += "(no entities matched)\n";
|
|
124
|
-
} else {
|
|
125
|
-
msg += `(${numMatchedEntities} total ${
|
|
126
|
-
numMatchedEntities === 1 ? "entity" : "entities"
|
|
127
|
-
})\n`;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
log(msg);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Helper function for printing out every grid entity (or filtered grid entity) in the current room.
|
|
135
|
-
*/
|
|
136
|
-
export function logAllGridEntities(
|
|
137
|
-
this: void,
|
|
138
|
-
includeWalls: boolean,
|
|
139
|
-
gridEntityTypeFilter?: GridEntityType,
|
|
140
|
-
): void {
|
|
141
|
-
let msg = "Grid entities in the room";
|
|
142
|
-
if (gridEntityTypeFilter !== undefined) {
|
|
143
|
-
msg += ` (filtered to grid entity type ${gridEntityTypeFilter})`;
|
|
144
|
-
} else if (!includeWalls) {
|
|
145
|
-
msg += " (not including walls)";
|
|
146
|
-
}
|
|
147
|
-
msg += ":\n";
|
|
148
|
-
|
|
149
|
-
const gridEntities = getGridEntities();
|
|
150
|
-
let numMatchedEntities = 0;
|
|
151
|
-
gridEntities.forEach((gridEntity) => {
|
|
152
|
-
const gridEntityIndex = gridEntity.GetGridIndex();
|
|
153
|
-
const gridEntityType = gridEntity.GetType();
|
|
154
|
-
|
|
155
|
-
// If a filter was specified, exclude all entities outside of the filter.
|
|
156
|
-
if (
|
|
157
|
-
gridEntityTypeFilter !== undefined &&
|
|
158
|
-
gridEntityType !== gridEntityTypeFilter
|
|
159
|
-
) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (
|
|
164
|
-
!includeWalls &&
|
|
165
|
-
gridEntityType === GridEntityType.WALL &&
|
|
166
|
-
gridEntityTypeFilter !== GridEntityType.WALL
|
|
167
|
-
) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
msg += getGridEntityLogLine(gridEntity, gridEntityIndex);
|
|
172
|
-
|
|
173
|
-
numMatchedEntities++;
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
if (numMatchedEntities === 0) {
|
|
177
|
-
msg += "(no grid entities matched)\n";
|
|
178
|
-
} else {
|
|
179
|
-
msg += `(${numMatchedEntities} total grid ${
|
|
180
|
-
numMatchedEntities === 1 ? "entity" : "entities"
|
|
181
|
-
})\n`;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
log(msg);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
71
|
export function logArray<T>(this: void, array: T[] | readonly T[]): void {
|
|
188
72
|
const arrayString = arrayToString(array);
|
|
189
73
|
log(`Array: ${arrayString}`);
|
|
@@ -203,92 +87,6 @@ export function logDamageFlags(
|
|
|
203
87
|
logFlags(flags, DamageFlag, "damage");
|
|
204
88
|
}
|
|
205
89
|
|
|
206
|
-
/** Helper function for logging an array of specific entities. */
|
|
207
|
-
export function logEntities(this: void, entities: Entity[]): void {
|
|
208
|
-
for (const entity of entities) {
|
|
209
|
-
logEntity(entity);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/** Helper function to log information about a specific entity. */
|
|
214
|
-
export function logEntity(this: void, entity: Entity): void {
|
|
215
|
-
const msg = getEntityLogLine(entity);
|
|
216
|
-
log(msg);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function getEntityLogLine(entity: Entity, num?: int): string {
|
|
220
|
-
let msg = num === undefined ? "" : `${num}) `;
|
|
221
|
-
|
|
222
|
-
msg += getEntityID(entity);
|
|
223
|
-
|
|
224
|
-
const bomb = entity.ToBomb();
|
|
225
|
-
if (bomb !== undefined) {
|
|
226
|
-
msg += " (bomb)";
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const effect = entity.ToEffect();
|
|
230
|
-
if (effect !== undefined) {
|
|
231
|
-
msg += ` (effect) (State: ${effect.State})`;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const familiar = entity.ToFamiliar();
|
|
235
|
-
if (familiar !== undefined) {
|
|
236
|
-
msg += ` (familiar) (State: ${familiar.State})`;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const knife = entity.ToKnife();
|
|
240
|
-
if (knife !== undefined) {
|
|
241
|
-
msg += " (knife)";
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const laser = entity.ToLaser();
|
|
245
|
-
if (laser !== undefined) {
|
|
246
|
-
msg += " (laser)";
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const npc = entity.ToNPC();
|
|
250
|
-
if (npc !== undefined) {
|
|
251
|
-
msg += ` (NPC) (State: ${npc.State})`;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const pickup = entity.ToPickup();
|
|
255
|
-
if (pickup !== undefined) {
|
|
256
|
-
msg += ` (pickup) (State: ${pickup.State})`;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const player = entity.ToPlayer();
|
|
260
|
-
if (player !== undefined) {
|
|
261
|
-
msg += " (player)";
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const projectile = entity.ToProjectile();
|
|
265
|
-
if (projectile !== undefined) {
|
|
266
|
-
msg += " (projectile)";
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const tear = entity.ToTear();
|
|
270
|
-
if (tear !== undefined) {
|
|
271
|
-
msg += " (tear)";
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
msg += "\n";
|
|
275
|
-
msg += ` - Index: ${entity.Index}\n`;
|
|
276
|
-
msg += ` - InitSeed: ${entity.InitSeed}\n`;
|
|
277
|
-
msg += ` - DropSeed: ${entity.DropSeed}\n`;
|
|
278
|
-
msg += ` - Position: (${entity.Position.X}, ${entity.Position.Y})\n`;
|
|
279
|
-
msg += ` - Velocity: (${entity.Velocity.X}, ${entity.Velocity.Y})\n`;
|
|
280
|
-
msg += ` - HP: ${entity.HitPoints} / ${entity.MaxHitPoints}\n`;
|
|
281
|
-
msg += ` - Parent: ${entity.Parent}\n`;
|
|
282
|
-
msg += ` - Child: ${entity.Child}\n`;
|
|
283
|
-
msg += ` - SpawnerEntity: ${entity.SpawnerEntity}\n`;
|
|
284
|
-
msg += ` - SpawnerType / SpawnerVariant: ${entity.SpawnerType}.${entity.SpawnerVariant}\n`;
|
|
285
|
-
if (npc !== undefined) {
|
|
286
|
-
msg += ` - CanShutDoors: ${npc.CanShutDoors}\n`;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return msg;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
90
|
/** Helper function for printing out every entity flag that is turned on. Useful when debugging. */
|
|
293
91
|
export function logEntityFlags(
|
|
294
92
|
this: void,
|
|
@@ -363,76 +161,6 @@ export function logGameStateFlags(this: void): void {
|
|
|
363
161
|
}
|
|
364
162
|
}
|
|
365
163
|
|
|
366
|
-
/** Helper function for logging an array of specific grid entities. */
|
|
367
|
-
export function logGridEntities(this: void, gridEntities: GridEntity[]): void {
|
|
368
|
-
for (const gridEntity of gridEntities) {
|
|
369
|
-
logGridEntity(gridEntity);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/** Helper function for log information about a specific grid entity. */
|
|
374
|
-
export function logGridEntity(this: void, gridEntity: GridEntity): void {
|
|
375
|
-
const msg = getGridEntityLogLine(gridEntity);
|
|
376
|
-
log(msg);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function getGridEntityLogLine(gridEntity: GridEntity, num?: int): string {
|
|
380
|
-
const gridEntityDesc = gridEntity.GetSaveState();
|
|
381
|
-
|
|
382
|
-
let msg = num === undefined ? "" : `${num}) `;
|
|
383
|
-
|
|
384
|
-
msg += getGridEntityID(gridEntity);
|
|
385
|
-
|
|
386
|
-
const door = gridEntity.ToDoor();
|
|
387
|
-
if (door !== undefined) {
|
|
388
|
-
msg += " (door)";
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const pit = gridEntity.ToPit();
|
|
392
|
-
if (pit !== undefined) {
|
|
393
|
-
msg += " (pit)";
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const poop = gridEntity.ToPoop();
|
|
397
|
-
if (poop !== undefined) {
|
|
398
|
-
msg += " (poop)";
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const pressurePlate = gridEntity.ToPressurePlate();
|
|
402
|
-
if (pressurePlate !== undefined) {
|
|
403
|
-
msg += " (pressurePlate)";
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
const rock = gridEntity.ToRock();
|
|
407
|
-
if (rock !== undefined) {
|
|
408
|
-
msg += " (rock)";
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const spikes = gridEntity.ToSpikes();
|
|
412
|
-
if (spikes !== undefined) {
|
|
413
|
-
msg += " (spikes)";
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
const tnt = gridEntity.ToTNT();
|
|
417
|
-
if (tnt !== undefined) {
|
|
418
|
-
msg += " (TNT)";
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
msg += ` - State: ${gridEntity.State}\n`;
|
|
422
|
-
msg += ` - VarData: ${gridEntity.VarData}\n`;
|
|
423
|
-
msg += ` - Position: (${gridEntity.Position.X}, ${gridEntity.Position.Y})\n`;
|
|
424
|
-
msg += ` - SpawnSeed: ${gridEntityDesc.SpawnSeed}\n`;
|
|
425
|
-
msg += ` - VariableSeed: ${gridEntityDesc.VariableSeed})\n`;
|
|
426
|
-
if (door !== undefined) {
|
|
427
|
-
msg += ` - Slot: ${door.Slot}\n`;
|
|
428
|
-
msg += ` - Direction: ${door.Direction}\n`;
|
|
429
|
-
msg += ` - TargetRoomIndex: ${door.TargetRoomIndex}\n`;
|
|
430
|
-
msg += ` - TargetRoomType: ${door.TargetRoomType}\n`;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
return msg;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
164
|
export function logKColor(this: void, kColor: KColor): void {
|
|
437
165
|
log(
|
|
438
166
|
`Color: R${kColor.Red}, G${kColor.Green}, B${kColor.Blue}, A${kColor.Alpha}`,
|
|
@@ -764,20 +492,14 @@ export function setLogFunctionsGlobal(): void {
|
|
|
764
492
|
const globals = _G as Record<string, unknown>;
|
|
765
493
|
|
|
766
494
|
globals["log"] = log;
|
|
767
|
-
globals["logAllEntities"] = logAllEntities;
|
|
768
|
-
globals["logAllGridEntities"] = logAllGridEntities;
|
|
769
495
|
globals["logArray"] = logArray;
|
|
770
496
|
globals["logColor"] = logColor;
|
|
771
497
|
globals["logDamageFlags"] = logDamageFlags;
|
|
772
|
-
globals["logEntities"] = logEntities;
|
|
773
|
-
globals["logEntity"] = logEntity;
|
|
774
498
|
globals["logEntityID"] = logEntityID;
|
|
775
499
|
globals["logEntityFlags"] = logEntityFlags;
|
|
776
500
|
globals["logError"] = logError;
|
|
777
501
|
globals["logFlags"] = logFlags;
|
|
778
502
|
globals["logGameStateFlags"] = logGameStateFlags;
|
|
779
|
-
globals["logGridEntities"] = logGridEntities;
|
|
780
|
-
globals["logGridEntity"] = logGridEntity;
|
|
781
503
|
globals["logKColor"] = logKColor;
|
|
782
504
|
globals["logLevelStateFlags"] = logLevelStateFlags;
|
|
783
505
|
globals["logMap"] = logMap;
|