isaacscript-common 6.11.2 → 6.12.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/callbacks/postGridEntityCustomRender.d.ts +2 -0
- package/dist/callbacks/postGridEntityCustomRender.d.ts.map +1 -0
- package/dist/callbacks/postGridEntityCustomRender.lua +36 -0
- package/dist/callbacks/postGridEntityCustomUpdate.d.ts +2 -0
- package/dist/callbacks/postGridEntityCustomUpdate.d.ts.map +1 -0
- package/dist/callbacks/postGridEntityCustomUpdate.lua +36 -0
- package/dist/callbacks/postNewRoomEarly.lua +2 -2
- package/dist/callbacks/postPickupInitFirst.lua +1 -20
- package/dist/callbacks/reorderedCallbacks.d.ts +5 -5
- package/dist/callbacks/reorderedCallbacks.d.ts.map +1 -1
- package/dist/callbacks/reorderedCallbacks.lua +5 -5
- package/dist/callbacks/subscriptions/postGridEntityCustomRender.d.ts +6 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomRender.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomRender.lua +29 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomUpdate.d.ts +6 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomUpdate.d.ts.map +1 -0
- package/dist/callbacks/subscriptions/postGridEntityCustomUpdate.lua +29 -0
- package/dist/constants.d.ts +1 -5
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.lua +0 -7
- package/dist/constantsFirstLast.d.ts +5 -1
- package/dist/constantsFirstLast.d.ts.map +1 -1
- package/dist/constantsFirstLast.lua +6 -0
- package/dist/enums/ModCallbackCustom.d.ts +89 -66
- package/dist/enums/ModCallbackCustom.d.ts.map +1 -1
- package/dist/enums/ModCallbackCustom.lua +62 -58
- package/dist/features/customGridEntity.d.ts +9 -0
- package/dist/features/customGridEntity.d.ts.map +1 -1
- package/dist/features/customGridEntity.lua +20 -0
- package/dist/features/customTrapdoor/customTrapdoorConstants.d.ts +2 -2
- package/dist/features/customTrapdoor/customTrapdoorConstants.d.ts.map +1 -1
- package/dist/features/customTrapdoor/customTrapdoorConstants.lua +2 -2
- package/dist/features/customTrapdoor/init.d.ts.map +1 -1
- package/dist/features/customTrapdoor/init.lua +4 -3
- package/dist/features/customTrapdoor/touched.d.ts.map +1 -1
- package/dist/features/customTrapdoor/touched.lua +51 -33
- package/dist/features/deployJSONRoom.d.ts +2 -2
- package/dist/features/deployJSONRoom.lua +2 -2
- package/dist/features/extraConsoleCommands/listCommands.d.ts.map +1 -1
- package/dist/features/extraConsoleCommands/listCommands.lua +4 -4
- package/dist/features/pause.d.ts +1 -1
- package/dist/features/pause.d.ts.map +1 -1
- package/dist/features/pause.lua +87 -8
- package/dist/features/persistentEntities.d.ts.map +1 -1
- package/dist/features/persistentEntities.lua +7 -7
- package/dist/features/pickupIndex.d.ts +19 -0
- package/dist/features/pickupIndex.d.ts.map +1 -0
- package/dist/features/pickupIndex.lua +197 -0
- package/dist/features/roomHistory.d.ts +24 -0
- package/dist/features/roomHistory.d.ts.map +1 -0
- package/dist/features/roomHistory.lua +89 -0
- package/dist/functions/collectibles.d.ts +26 -13
- package/dist/functions/collectibles.d.ts.map +1 -1
- package/dist/functions/collectibles.lua +26 -13
- package/dist/functions/entities.d.ts +3 -3
- package/dist/functions/entities.d.ts.map +1 -1
- package/dist/functions/entities.lua +8 -3
- package/dist/functions/gridEntities.d.ts +2 -2
- package/dist/functions/gridEntities.lua +2 -2
- package/dist/functions/isaacAPIClass.d.ts +64 -0
- package/dist/functions/isaacAPIClass.d.ts.map +1 -1
- package/dist/functions/isaacAPIClass.lua +84 -1
- package/dist/functions/pickupVariants.d.ts +2 -2
- package/dist/functions/pickupVariants.d.ts.map +1 -1
- package/dist/functions/pickupVariants.lua +2 -2
- package/dist/functions/playerCenter.lua +2 -2
- package/dist/functions/playerIndex.d.ts +0 -3
- package/dist/functions/playerIndex.d.ts.map +1 -1
- package/dist/functions/playerIndex.lua +4 -23
- package/dist/functions/roomData.d.ts +3 -2
- package/dist/functions/roomData.d.ts.map +1 -1
- package/dist/functions/roomData.lua +3 -2
- package/dist/functions/rooms.d.ts +6 -6
- package/dist/functions/rooms.lua +6 -6
- package/dist/functions/stage.d.ts +1 -0
- package/dist/functions/stage.d.ts.map +1 -1
- package/dist/functions/stage.lua +4 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.lua +23 -0
- package/dist/initCustomCallbacks.d.ts.map +1 -1
- package/dist/initCustomCallbacks.lua +6 -0
- package/dist/initFeatures.d.ts.map +1 -1
- package/dist/initFeatures.lua +6 -0
- package/dist/interfaces/AddCallbackParameterCustom.d.ts +4 -0
- package/dist/interfaces/AddCallbackParameterCustom.d.ts.map +1 -1
- package/dist/interfaces/RoomDescription.d.ts +14 -0
- package/dist/interfaces/RoomDescription.d.ts.map +1 -0
- package/dist/interfaces/RoomDescription.lua +2 -0
- package/dist/objects/callbackRegisterFunctions.d.ts.map +1 -1
- package/dist/objects/callbackRegisterFunctions.lua +6 -0
- package/dist/types/CollectibleIndex.d.ts +1 -1
- package/dist/types/PickupIndex.d.ts +17 -0
- package/dist/types/PickupIndex.d.ts.map +1 -0
- package/dist/types/PickupIndex.lua +2 -0
- package/dist/types/PlayerIndex.d.ts +1 -1
- package/dist/upgradeMod.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/callbacks/postGridEntityCustomRender.ts +44 -0
- package/src/callbacks/postGridEntityCustomUpdate.ts +44 -0
- package/src/callbacks/postNewRoomEarly.ts +2 -2
- package/src/callbacks/postPickupInitFirst.ts +1 -32
- package/src/callbacks/postPlayerReorderedCallbacks.ts +3 -3
- package/src/callbacks/reorderedCallbacks.ts +9 -8
- package/src/callbacks/subscriptions/postGridEntityCustomRender.ts +41 -0
- package/src/callbacks/subscriptions/postGridEntityCustomUpdate.ts +41 -0
- package/src/constants.ts +1 -9
- package/src/constantsFirstLast.ts +16 -0
- package/src/enums/ModCallbackCustom.ts +33 -8
- package/src/features/customGridEntity.ts +25 -0
- package/src/features/customTrapdoor/customTrapdoorConstants.ts +2 -2
- package/src/features/customTrapdoor/init.ts +7 -5
- package/src/features/customTrapdoor/touched.ts +59 -39
- package/src/features/deployJSONRoom.ts +4 -4
- package/src/features/extraConsoleCommands/listCommands.ts +5 -7
- package/src/features/pause.ts +97 -7
- package/src/features/persistentEntities.ts +9 -8
- package/src/features/pickupIndex.ts +257 -0
- package/src/features/playerInventory.ts +2 -2
- package/src/features/roomHistory.ts +113 -0
- package/src/features/saveDataManager/main.ts +2 -2
- package/src/features/taintedLazarusPlayers.ts +5 -5
- package/src/functions/collectibles.ts +26 -13
- package/src/functions/entities.ts +6 -3
- package/src/functions/gridEntities.ts +2 -2
- package/src/functions/isaacAPIClass.ts +106 -1
- package/src/functions/pickupVariants.ts +2 -2
- package/src/functions/playerCenter.ts +2 -2
- package/src/functions/playerIndex.ts +8 -21
- package/src/functions/roomData.ts +3 -2
- package/src/functions/rooms.ts +6 -6
- package/src/functions/stage.ts +10 -1
- package/src/index.ts +3 -0
- package/src/initCustomCallbacks.ts +4 -0
- package/src/initFeatures.ts +4 -0
- package/src/interfaces/AddCallbackParameterCustom.ts +4 -0
- package/src/interfaces/RoomDescription.ts +19 -0
- package/src/objects/callbackRegisterFunctions.ts +6 -0
- package/src/types/CollectibleIndex.ts +1 -1
- package/src/types/PickupIndex.ts +15 -0
- package/src/types/PlayerIndex.ts +1 -1
- package/src/upgradeMod.ts +2 -1
package/src/constants.ts
CHANGED
|
@@ -2,12 +2,10 @@ import {
|
|
|
2
2
|
CollectibleType,
|
|
3
3
|
Dimension,
|
|
4
4
|
ItemPoolType,
|
|
5
|
-
LevelStage,
|
|
6
|
-
RoomType,
|
|
7
5
|
TrinketSlot,
|
|
8
6
|
} from "isaac-typescript-definitions";
|
|
9
7
|
import { NUM_NORMAL_PILL_COLORS } from "./constantsFirstLast";
|
|
10
|
-
import { getEnumLength
|
|
8
|
+
import { getEnumLength } from "./functions/enums";
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* The distance of the laser when Azazel does not have any range up items yet. For more info, see
|
|
@@ -112,9 +110,6 @@ export const MIN_PLAYER_SHOT_SPEED_STAT = 0.6;
|
|
|
112
110
|
/** If you set `EntityPlayer.Speed` lower than this value, it will have no effect. */
|
|
113
111
|
export const MIN_PLAYER_SPEED_STAT = 0.1;
|
|
114
112
|
|
|
115
|
-
export const FIRST_ROOM_TYPE = RoomType.DEFAULT;
|
|
116
|
-
export const LAST_ROOM_TYPE = getLastEnumValue(RoomType);
|
|
117
|
-
|
|
118
113
|
/**
|
|
119
114
|
* The maximum speed stat that a player can have. Any additional speed beyond this will not take
|
|
120
115
|
* effect.
|
|
@@ -133,9 +128,6 @@ export const NEW_FLOOR_STARTING_POSITION_GREED_MODE = Vector(320, 280);
|
|
|
133
128
|
*/
|
|
134
129
|
export const NEW_RUN_PLAYER_STARTING_POSITION = Vector(320, 380);
|
|
135
130
|
|
|
136
|
-
export const FIRST_STAGE = LevelStage.BASEMENT_1;
|
|
137
|
-
export const LAST_STAGE = getLastEnumValue(LevelStage);
|
|
138
|
-
|
|
139
131
|
/** Corresponds to the maximum value for `EntityPlayer.SamsonBerserkCharge`. */
|
|
140
132
|
export const MAX_TAINTED_SAMSON_BERSERK_CHARGE = 100000;
|
|
141
133
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Card,
|
|
3
3
|
CollectibleType,
|
|
4
|
+
LevelStage,
|
|
4
5
|
PillColor,
|
|
5
6
|
PillEffect,
|
|
6
7
|
PlayerType,
|
|
8
|
+
RoomType,
|
|
7
9
|
TrinketType,
|
|
8
10
|
} from "isaac-typescript-definitions";
|
|
9
11
|
import { itemConfig } from "./cachedClasses";
|
|
@@ -208,3 +210,17 @@ export const LAST_VANILLA_CHARACTER = getLastEnumValue(PlayerType);
|
|
|
208
210
|
*/
|
|
209
211
|
export const FIRST_MODDED_CHARACTER = ((LAST_VANILLA_CHARACTER as int) +
|
|
210
212
|
1) as PlayerType;
|
|
213
|
+
|
|
214
|
+
// ----------
|
|
215
|
+
// Room Types
|
|
216
|
+
// ----------
|
|
217
|
+
|
|
218
|
+
export const FIRST_ROOM_TYPE = RoomType.DEFAULT;
|
|
219
|
+
export const LAST_ROOM_TYPE = getLastEnumValue(RoomType);
|
|
220
|
+
|
|
221
|
+
// ------
|
|
222
|
+
// Stages
|
|
223
|
+
// ------
|
|
224
|
+
|
|
225
|
+
export const FIRST_STAGE = LevelStage.BASEMENT_1;
|
|
226
|
+
export const LAST_STAGE = getLastEnumValue(LevelStage);
|
|
@@ -336,7 +336,7 @@ export enum ModCallbackCustom {
|
|
|
336
336
|
POST_GREED_MODE_WAVE,
|
|
337
337
|
|
|
338
338
|
/**
|
|
339
|
-
* Fires from the `POST_UPDATE`
|
|
339
|
+
* Fires from the `POST_UPDATE` callback when a grid entity changes to a state that corresponds to
|
|
340
340
|
* the broken state for the respective grid entity type.
|
|
341
341
|
*
|
|
342
342
|
* When registering the callback, takes an optional second argument that will make the callback
|
|
@@ -363,6 +363,38 @@ export enum ModCallbackCustom {
|
|
|
363
363
|
*/
|
|
364
364
|
POST_GRID_ENTITY_COLLISION,
|
|
365
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Fires from the `POST_RENDER` callback on every frame that a grid entity created with the
|
|
368
|
+
* `spawnCustomGridEntity` helper function exists.
|
|
369
|
+
*
|
|
370
|
+
* When registering the callback, takes an optional second argument that will make the callback
|
|
371
|
+
* only fire if it matches the `GridEntityType` provided.
|
|
372
|
+
*
|
|
373
|
+
* ```ts
|
|
374
|
+
* function postGridEntityRenderCustom(
|
|
375
|
+
* gridEntity: GridEntity,
|
|
376
|
+
* gridEntityTypeCustom: GridEntityType,
|
|
377
|
+
* ): void {}
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
POST_GRID_ENTITY_CUSTOM_RENDER,
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Fires from the `POST_UPDATE` callback on every frame that a grid entity created with the
|
|
384
|
+
* `spawnCustomGridEntity` helper function exists.
|
|
385
|
+
*
|
|
386
|
+
* When registering the callback, takes an optional second argument that will make the callback
|
|
387
|
+
* only fire if it matches the `GridEntityType` provided.
|
|
388
|
+
*
|
|
389
|
+
* ```ts
|
|
390
|
+
* function postGridEntityUpdateCustom(
|
|
391
|
+
* gridEntity: GridEntity,
|
|
392
|
+
* gridEntityTypeCustom: GridEntityType,
|
|
393
|
+
* ): void {}
|
|
394
|
+
* ```
|
|
395
|
+
*/
|
|
396
|
+
POST_GRID_ENTITY_CUSTOM_UPDATE,
|
|
397
|
+
|
|
366
398
|
/**
|
|
367
399
|
* Fires when a new grid entity is initialized. Specifically, this is either:
|
|
368
400
|
*
|
|
@@ -664,13 +696,6 @@ export enum ModCallbackCustom {
|
|
|
664
696
|
* This callback is useful because pickups will despawn upon leaving the room and respawn upon
|
|
665
697
|
* re-entering the room.
|
|
666
698
|
*
|
|
667
|
-
* For most cases, this callback will simply fire when `POST_PICKUP_INIT` fires and the player is
|
|
668
|
-
* not re-entering a previously visited room.
|
|
669
|
-
*
|
|
670
|
-
* The special case is when a player enters a post-Ascent Treasure Room or Boss Room. For these
|
|
671
|
-
* cases, the `InitSeed` of any pickups seen from previous floors is kept track of to prevent the
|
|
672
|
-
* callback from firing when re-entering the room.
|
|
673
|
-
*
|
|
674
699
|
* When registering the callback, takes an optional second argument that will make the callback
|
|
675
700
|
* only fire if the collectible type matches the `PickupVariant` provided.
|
|
676
701
|
*
|
|
@@ -274,3 +274,28 @@ export function removeCustomGrid(
|
|
|
274
274
|
|
|
275
275
|
return decoration;
|
|
276
276
|
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Helper function to get the custom grid entities in the current room. Returns an array of tuples
|
|
280
|
+
* containing the raw decoration grid entity and the associated entity data.
|
|
281
|
+
*/
|
|
282
|
+
export function getCustomGridEntities(): Array<
|
|
283
|
+
[gridEntity: GridEntity, data: CustomGridEntityData]
|
|
284
|
+
> {
|
|
285
|
+
const roomListIndex = getRoomListIndex();
|
|
286
|
+
const roomCustomGridEntities = v.level.customGridEntities.get(roomListIndex);
|
|
287
|
+
if (roomCustomGridEntities === undefined) {
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const room = game.GetRoom();
|
|
292
|
+
const customGridEntities: Array<[GridEntity, CustomGridEntityData]> = [];
|
|
293
|
+
for (const [gridIndex, data] of roomCustomGridEntities.entries()) {
|
|
294
|
+
const gridEntity = room.GetGridEntity(gridIndex);
|
|
295
|
+
if (gridEntity !== undefined) {
|
|
296
|
+
customGridEntities.push([gridEntity, data]);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return customGridEntities;
|
|
301
|
+
}
|
|
@@ -19,5 +19,5 @@ export const ANIMATIONS_THAT_PREVENT_STAGE_TRAVEL: ReadonlySet<string> =
|
|
|
19
19
|
|
|
20
20
|
export const PIXELATION_TO_BLACK_FRAMES = 52;
|
|
21
21
|
|
|
22
|
-
export const OTHER_PLAYER_TRAPDOOR_JUMP_DELAY_GAME_FRAMES =
|
|
23
|
-
export const OTHER_PLAYER_TRAPDOOR_JUMP_DURATION_GAME_FRAMES =
|
|
22
|
+
export const OTHER_PLAYER_TRAPDOOR_JUMP_DELAY_GAME_FRAMES = 6;
|
|
23
|
+
export const OTHER_PLAYER_TRAPDOOR_JUMP_DURATION_GAME_FRAMES = 5;
|
|
@@ -21,6 +21,7 @@ import { saveDataManager } from "../saveDataManager/exports";
|
|
|
21
21
|
import { drawBlackSprite } from "./blackSprite";
|
|
22
22
|
import {
|
|
23
23
|
CUSTOM_TRAPDOOR_FEATURE_NAME,
|
|
24
|
+
GridEntityTypeCustom,
|
|
24
25
|
PIXELATION_TO_BLACK_FRAMES,
|
|
25
26
|
} from "./customTrapdoorConstants";
|
|
26
27
|
import { checkCustomTrapdoorOpenClose } from "./openClose";
|
|
@@ -33,8 +34,9 @@ export function customTrapdoorInit(mod: ModUpgraded): void {
|
|
|
33
34
|
mod.AddCallback(ModCallback.POST_RENDER, postRender); // 2
|
|
34
35
|
mod.AddCallback(ModCallback.POST_PEFFECT_UPDATE, postPEffectUpdate); // 4
|
|
35
36
|
mod.AddCallbackCustom(
|
|
36
|
-
ModCallbackCustom.
|
|
37
|
-
|
|
37
|
+
ModCallbackCustom.POST_GRID_ENTITY_CUSTOM_UPDATE,
|
|
38
|
+
postGridEntityCustomUpdateTrapdoor,
|
|
39
|
+
GridEntityTypeCustom.TRAPDOOR_CUSTOM,
|
|
38
40
|
);
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -198,9 +200,9 @@ function checkJumpComplete(player: EntityPlayer) {
|
|
|
198
200
|
}
|
|
199
201
|
}
|
|
200
202
|
|
|
201
|
-
// ModCallbackCustom.
|
|
202
|
-
//
|
|
203
|
-
function
|
|
203
|
+
// ModCallbackCustom.POST_GRID_ENTITY_CUSTOM_UPDATE
|
|
204
|
+
// GridEntityTypeCustom.TRAPDOOR_CUSTOM
|
|
205
|
+
function postGridEntityCustomUpdateTrapdoor(gridEntity: GridEntity) {
|
|
204
206
|
const roomListIndex = getRoomListIndex();
|
|
205
207
|
const gridIndex = gridEntity.GetGridIndex();
|
|
206
208
|
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ButtonAction,
|
|
2
3
|
EntityCollisionClass,
|
|
4
|
+
EntityGridCollisionClass,
|
|
3
5
|
EntityPartition,
|
|
4
6
|
PlayerType,
|
|
5
7
|
} from "isaac-typescript-definitions";
|
|
6
8
|
import { VectorZero } from "../../constants";
|
|
7
9
|
import { StageTravelState } from "../../enums/private/StageTravelState";
|
|
10
|
+
import { easeOutSine } from "../../functions/easing";
|
|
8
11
|
import {
|
|
12
|
+
getAllPlayers,
|
|
9
13
|
getOtherPlayers,
|
|
10
|
-
getPlayers,
|
|
11
14
|
isChildPlayer,
|
|
12
15
|
} from "../../functions/playerIndex";
|
|
13
16
|
import { isCharacter } from "../../functions/players";
|
|
14
17
|
import { CustomTrapdoorDescription } from "../../interfaces/private/CustomTrapdoorDescription";
|
|
15
|
-
import {
|
|
18
|
+
import { disableAllInputsExceptFor } from "../disableInputs";
|
|
16
19
|
import { isPlayerUsingPony } from "../ponyDetection";
|
|
17
|
-
import { runInNGameFrames,
|
|
20
|
+
import { runInNGameFrames, runNextRenderFrame } from "../runInNFrames";
|
|
18
21
|
import {
|
|
19
22
|
ANIMATIONS_THAT_PREVENT_STAGE_TRAVEL,
|
|
20
23
|
CUSTOM_TRAPDOOR_FEATURE_NAME,
|
|
@@ -78,7 +81,8 @@ function playerTouchedCustomTrapdoor(
|
|
|
78
81
|
v.run.state = StageTravelState.PLAYERS_JUMPING_DOWN;
|
|
79
82
|
v.run.destination = trapdoorDescription.destination;
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
const whitelist = new Set([ButtonAction.CONSOLE]);
|
|
85
|
+
disableAllInputsExceptFor(CUSTOM_TRAPDOOR_FEATURE_NAME, whitelist);
|
|
82
86
|
setPlayerAttributes(player, gridEntity.Position);
|
|
83
87
|
dropTaintedForgotten(player);
|
|
84
88
|
|
|
@@ -95,6 +99,35 @@ function playerTouchedCustomTrapdoor(
|
|
|
95
99
|
});
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
function setPlayerAttributes(trapdoorPlayer: EntityPlayer, position: Vector) {
|
|
103
|
+
// Snap the player to the exact position of the trapdoor so that they cleanly jump down the hole.
|
|
104
|
+
trapdoorPlayer.Position = position;
|
|
105
|
+
|
|
106
|
+
for (const player of getAllPlayers()) {
|
|
107
|
+
// Disable the controls to prevent the player from moving, shooting, and so on. (We also disable
|
|
108
|
+
// the inputs in the `INPUT_ACTION` callback, but that does not prevent mouse inputs.)
|
|
109
|
+
player.ControlsEnabled = false;
|
|
110
|
+
|
|
111
|
+
// Freeze all players.
|
|
112
|
+
player.Velocity = VectorZero;
|
|
113
|
+
|
|
114
|
+
// We don't want enemy attacks to move the players.
|
|
115
|
+
player.EntityCollisionClass = EntityCollisionClass.NONE;
|
|
116
|
+
player.GridCollisionClass = EntityGridCollisionClass.NONE;
|
|
117
|
+
|
|
118
|
+
player.SubType = -1;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function dropTaintedForgotten(player: EntityPlayer) {
|
|
123
|
+
if (isCharacter(player, PlayerType.THE_FORGOTTEN_B)) {
|
|
124
|
+
const taintedSoul = player.GetOtherTwin();
|
|
125
|
+
if (taintedSoul !== undefined) {
|
|
126
|
+
taintedSoul.ThrowHeldEntity(VectorZero);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
98
131
|
function startDelayedJump(entityPtr: EntityPtr, trapdoorPosition: Vector) {
|
|
99
132
|
const entity = entityPtr.Ref;
|
|
100
133
|
if (entity === undefined) {
|
|
@@ -108,14 +141,18 @@ function startDelayedJump(entityPtr: EntityPtr, trapdoorPosition: Vector) {
|
|
|
108
141
|
|
|
109
142
|
player.PlayExtraAnimation("Trapdoor");
|
|
110
143
|
|
|
111
|
-
|
|
144
|
+
adjustPlayerPositionToTrapdoor(entityPtr, player.Position, trapdoorPosition);
|
|
112
145
|
}
|
|
113
146
|
|
|
114
|
-
function
|
|
147
|
+
function adjustPlayerPositionToTrapdoor(
|
|
115
148
|
entityPtr: EntityPtr,
|
|
116
149
|
startPos: Vector,
|
|
117
150
|
endPos: Vector,
|
|
118
151
|
) {
|
|
152
|
+
if (v.run.state !== StageTravelState.PLAYERS_JUMPING_DOWN) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
119
156
|
const entity = entityPtr.Ref;
|
|
120
157
|
if (entity === undefined) {
|
|
121
158
|
return;
|
|
@@ -126,50 +163,33 @@ function adjustPlayerVelocityToTrapdoor(
|
|
|
126
163
|
return;
|
|
127
164
|
}
|
|
128
165
|
|
|
166
|
+
runNextRenderFrame(() => {
|
|
167
|
+
adjustPlayerPositionToTrapdoor(entityPtr, startPos, endPos);
|
|
168
|
+
});
|
|
169
|
+
|
|
129
170
|
const sprite = player.GetSprite();
|
|
130
171
|
if (sprite.IsFinished("Trapdoor")) {
|
|
172
|
+
player.Position = endPos;
|
|
173
|
+
player.Velocity = VectorZero;
|
|
131
174
|
return;
|
|
132
175
|
}
|
|
133
176
|
|
|
134
177
|
const frame = sprite.GetFrame();
|
|
135
|
-
if (frame
|
|
178
|
+
if (frame >= OTHER_PLAYER_TRAPDOOR_JUMP_DURATION_GAME_FRAMES) {
|
|
136
179
|
// We have already arrived at the trapdoor.
|
|
180
|
+
player.Position = endPos;
|
|
181
|
+
player.Velocity = VectorZero;
|
|
137
182
|
return;
|
|
138
183
|
}
|
|
139
184
|
|
|
185
|
+
// Make the player jump towards the trapdoor. We use an easing function so that the distance
|
|
186
|
+
// traveled is not linear, emulating what the game does.
|
|
140
187
|
const totalDifference = endPos.sub(startPos);
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
);
|
|
144
|
-
const differenceForThisFrame = differencePerFrame.mul(frame + 1);
|
|
188
|
+
const progress = frame / OTHER_PLAYER_TRAPDOOR_JUMP_DURATION_GAME_FRAMES;
|
|
189
|
+
const easeProgress = easeOutSine(progress);
|
|
190
|
+
const differenceForThisFrame = totalDifference.mul(easeProgress);
|
|
145
191
|
const targetPosition = startPos.add(differenceForThisFrame);
|
|
146
|
-
const calculatedVelocity = player.Position.sub(targetPosition);
|
|
147
|
-
|
|
148
|
-
player.Velocity = calculatedVelocity;
|
|
149
|
-
|
|
150
|
-
runNextGameFrame(() => {
|
|
151
|
-
adjustPlayerVelocityToTrapdoor(entityPtr, startPos, endPos);
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
192
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
trapdoorPlayer.Position = position;
|
|
158
|
-
|
|
159
|
-
for (const player of getPlayers()) {
|
|
160
|
-
// Freeze all players.
|
|
161
|
-
player.Velocity = VectorZero;
|
|
162
|
-
|
|
163
|
-
// We don't want enemy attacks to move the players.
|
|
164
|
-
player.EntityCollisionClass = EntityCollisionClass.NONE;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function dropTaintedForgotten(player: EntityPlayer) {
|
|
169
|
-
if (isCharacter(player, PlayerType.THE_FORGOTTEN_B)) {
|
|
170
|
-
const taintedSoul = player.GetOtherTwin();
|
|
171
|
-
if (taintedSoul !== undefined) {
|
|
172
|
-
taintedSoul.ThrowHeldEntity(VectorZero);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
193
|
+
player.Position = targetPosition;
|
|
194
|
+
player.Velocity = VectorZero;
|
|
175
195
|
}
|
|
@@ -225,7 +225,7 @@ function respawnPersistentEntities() {
|
|
|
225
225
|
* Specifically, this will clear the current room of all entities and grid entities, and then spawn
|
|
226
226
|
* all of the entries and grid entities in the provided JSON room.
|
|
227
227
|
*
|
|
228
|
-
* This function is meant to be used in the
|
|
228
|
+
* This function is meant to be used in the `POST_NEW_ROOM` callback.
|
|
229
229
|
*
|
|
230
230
|
* For example:
|
|
231
231
|
*
|
|
@@ -277,7 +277,7 @@ export function deployJSONRoom(
|
|
|
277
277
|
* Specifically, this will clear the current room of all entities and grid entities, and then spawn
|
|
278
278
|
* all of the entries and grid entities in one of the provided JSON rooms.
|
|
279
279
|
*
|
|
280
|
-
* This function is meant to be used in the
|
|
280
|
+
* This function is meant to be used in the `POST_NEW_ROOM` callback.
|
|
281
281
|
*
|
|
282
282
|
* Note that this function does not simply choose a random element in the provided array; it will
|
|
283
283
|
* properly account for each room weight using the algorithm from:
|
|
@@ -355,8 +355,8 @@ export function emptyRoom(fillWithDecorations: boolean): void {
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
/**
|
|
358
|
-
* We remove entities in the
|
|
359
|
-
* that they will not re-appear when we re-enter the room.
|
|
358
|
+
* We remove entities in the `POST_NEW_ROOM` callback instead of in the PreRoomEntitySpawn callback
|
|
359
|
+
* so that they will not re-appear when we re-enter the room.
|
|
360
360
|
*/
|
|
361
361
|
function removeSpecificNPCs() {
|
|
362
362
|
const room = game.GetRoom();
|
|
@@ -33,19 +33,17 @@ import {
|
|
|
33
33
|
TrinketType,
|
|
34
34
|
} from "isaac-typescript-definitions";
|
|
35
35
|
import { game, sfxManager } from "../../cachedClasses";
|
|
36
|
-
import {
|
|
37
|
-
FIRST_ROOM_TYPE,
|
|
38
|
-
FIRST_STAGE,
|
|
39
|
-
LAST_ROOM_TYPE,
|
|
40
|
-
LAST_STAGE,
|
|
41
|
-
MAX_LEVEL_GRID_INDEX,
|
|
42
|
-
} from "../../constants";
|
|
36
|
+
import { MAX_LEVEL_GRID_INDEX } from "../../constants";
|
|
43
37
|
import {
|
|
44
38
|
FIRST_CARD,
|
|
45
39
|
FIRST_CHARACTER,
|
|
46
40
|
FIRST_PILL_EFFECT,
|
|
41
|
+
FIRST_ROOM_TYPE,
|
|
42
|
+
FIRST_STAGE,
|
|
47
43
|
LAST_CARD,
|
|
48
44
|
LAST_PILL_EFFECT,
|
|
45
|
+
LAST_ROOM_TYPE,
|
|
46
|
+
LAST_STAGE,
|
|
49
47
|
LAST_VANILLA_CHARACTER,
|
|
50
48
|
} from "../../constantsFirstLast";
|
|
51
49
|
import { HealthType } from "../../enums/HealthType";
|
package/src/features/pause.ts
CHANGED
|
@@ -4,17 +4,36 @@ import {
|
|
|
4
4
|
InputHook,
|
|
5
5
|
ModCallback,
|
|
6
6
|
} from "isaac-typescript-definitions";
|
|
7
|
+
import { VectorZero } from "../constants";
|
|
8
|
+
import {
|
|
9
|
+
getProjectiles,
|
|
10
|
+
getTears,
|
|
11
|
+
removeAllProjectiles,
|
|
12
|
+
removeAllTears,
|
|
13
|
+
} from "../functions/entitiesSpecific";
|
|
14
|
+
import { isTear } from "../functions/isaacAPIClass";
|
|
7
15
|
import { logError } from "../functions/log";
|
|
16
|
+
import { getAllPlayers } from "../functions/playerIndex";
|
|
8
17
|
import { useActiveItemTemp } from "../functions/players";
|
|
9
18
|
import { disableAllInputsExceptFor, enableAllInputs } from "./disableInputs";
|
|
10
19
|
import { saveDataManager } from "./saveDataManager/exports";
|
|
11
20
|
|
|
12
21
|
const FEATURE_NAME = "pause";
|
|
13
22
|
|
|
23
|
+
interface InitialDescription {
|
|
24
|
+
position: Vector;
|
|
25
|
+
positionOffset: Vector;
|
|
26
|
+
velocity: Vector;
|
|
27
|
+
height: float;
|
|
28
|
+
fallingSpeed: float;
|
|
29
|
+
fallingAcceleration: float;
|
|
30
|
+
}
|
|
31
|
+
|
|
14
32
|
const v = {
|
|
15
33
|
run: {
|
|
16
34
|
isPseudoPaused: false,
|
|
17
35
|
shouldUnpause: false,
|
|
36
|
+
initialDescriptions: new Map<PtrHash, InitialDescription>(),
|
|
18
37
|
},
|
|
19
38
|
};
|
|
20
39
|
|
|
@@ -37,8 +56,34 @@ function postUpdate() {
|
|
|
37
56
|
return;
|
|
38
57
|
}
|
|
39
58
|
|
|
40
|
-
const
|
|
41
|
-
useActiveItemTemp(
|
|
59
|
+
const firstPlayer = Isaac.GetPlayer();
|
|
60
|
+
useActiveItemTemp(firstPlayer, CollectibleType.PAUSE);
|
|
61
|
+
|
|
62
|
+
stopTearsAndProjectilesFromMoving();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function stopTearsAndProjectilesFromMoving() {
|
|
66
|
+
const tearsAndProjectiles = [...getTears(), ...getProjectiles()];
|
|
67
|
+
|
|
68
|
+
for (const tearOrProjectile of tearsAndProjectiles) {
|
|
69
|
+
const ptrHash = GetPtrHash(tearOrProjectile);
|
|
70
|
+
const initialDescription = v.run.initialDescriptions.get(ptrHash);
|
|
71
|
+
if (initialDescription === undefined) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
tearOrProjectile.Position = initialDescription.position;
|
|
76
|
+
tearOrProjectile.PositionOffset = initialDescription.positionOffset;
|
|
77
|
+
tearOrProjectile.Velocity = VectorZero;
|
|
78
|
+
tearOrProjectile.Height = initialDescription.height;
|
|
79
|
+
tearOrProjectile.FallingSpeed = 0;
|
|
80
|
+
if (isTear(tearOrProjectile)) {
|
|
81
|
+
tearOrProjectile.FallingAcceleration =
|
|
82
|
+
initialDescription.fallingAcceleration;
|
|
83
|
+
} else {
|
|
84
|
+
tearOrProjectile.FallingAccel = initialDescription.fallingAcceleration;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
42
87
|
}
|
|
43
88
|
|
|
44
89
|
// ModCallback.INPUT_ACTION (13)
|
|
@@ -57,8 +102,8 @@ function inputActionGetActionValue(
|
|
|
57
102
|
}
|
|
58
103
|
v.run.shouldUnpause = false;
|
|
59
104
|
|
|
60
|
-
// Returning a value of 1 for a single frame will be enough for the game to register an
|
|
61
|
-
// but not enough for a tear to actually be fired.
|
|
105
|
+
// Returning a value of 1 for a single sub-frame will be enough for the game to register an
|
|
106
|
+
// unpause but not enough for a tear to actually be fired.
|
|
62
107
|
return 1;
|
|
63
108
|
}
|
|
64
109
|
|
|
@@ -68,7 +113,7 @@ function inputActionGetActionValue(
|
|
|
68
113
|
*
|
|
69
114
|
* Under the hood, this function:
|
|
70
115
|
* - uses the Pause collectible on every game frame
|
|
71
|
-
* - disables any player inputs (except for `ButtonAction.MENU_CONFIRM`)
|
|
116
|
+
* - disables any player inputs (except for `ButtonAction.MENU_CONFIRM` and `ButtonAction.CONSOLE`)
|
|
72
117
|
*/
|
|
73
118
|
export function pause(): void {
|
|
74
119
|
if (v.run.isPseudoPaused) {
|
|
@@ -79,8 +124,43 @@ export function pause(): void {
|
|
|
79
124
|
}
|
|
80
125
|
v.run.isPseudoPaused = true;
|
|
81
126
|
|
|
82
|
-
|
|
127
|
+
// Tears/projectiles in the room will move slightly on every frame, even when the Pause
|
|
128
|
+
// collectible is active. Thus, we manually reset the initial positions and heights on every
|
|
129
|
+
// frame.
|
|
130
|
+
v.run.initialDescriptions.clear();
|
|
131
|
+
const tearsAndProjectiles = [...getTears(), ...getProjectiles()];
|
|
132
|
+
for (const tearOrProjectile of tearsAndProjectiles) {
|
|
133
|
+
const ptrHash = GetPtrHash(tearOrProjectile);
|
|
134
|
+
const initialDescription: InitialDescription = {
|
|
135
|
+
position: tearOrProjectile.Position,
|
|
136
|
+
positionOffset: tearOrProjectile.PositionOffset,
|
|
137
|
+
velocity: tearOrProjectile.Velocity,
|
|
138
|
+
height: tearOrProjectile.Height,
|
|
139
|
+
fallingSpeed: tearOrProjectile.FallingSpeed,
|
|
140
|
+
fallingAcceleration: isTear(tearOrProjectile)
|
|
141
|
+
? tearOrProjectile.FallingAcceleration
|
|
142
|
+
: tearOrProjectile.FallingAccel,
|
|
143
|
+
};
|
|
144
|
+
v.run.initialDescriptions.set(ptrHash, initialDescription);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const firstPlayer = Isaac.GetPlayer();
|
|
148
|
+
useActiveItemTemp(firstPlayer, CollectibleType.PAUSE);
|
|
149
|
+
|
|
150
|
+
const whitelist = new Set([ButtonAction.MENU_CONFIRM, ButtonAction.CONSOLE]);
|
|
83
151
|
disableAllInputsExceptFor(FEATURE_NAME, whitelist);
|
|
152
|
+
|
|
153
|
+
for (const player of getAllPlayers()) {
|
|
154
|
+
// Disable the controls to prevent the players from moving, shooting, and so on. (We also
|
|
155
|
+
// disable the inputs in the `INPUT_ACTION` callback, but that does not prevent mouse inputs.)
|
|
156
|
+
player.ControlsEnabled = false;
|
|
157
|
+
|
|
158
|
+
// Prevent the players from leaving the room. (If we don't reset the velocity, they can continue
|
|
159
|
+
// to move towards a door.)
|
|
160
|
+
player.Velocity = VectorZero;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
stopTearsAndProjectilesFromMoving();
|
|
84
164
|
}
|
|
85
165
|
|
|
86
166
|
/** Helper function to put things back to normal after the `pause` function was used. */
|
|
@@ -92,7 +172,17 @@ export function unpause(): void {
|
|
|
92
172
|
return;
|
|
93
173
|
}
|
|
94
174
|
v.run.isPseudoPaused = false;
|
|
175
|
+
v.run.shouldUnpause = true;
|
|
95
176
|
|
|
96
177
|
enableAllInputs(FEATURE_NAME);
|
|
97
|
-
|
|
178
|
+
for (const player of getAllPlayers()) {
|
|
179
|
+
player.ControlsEnabled = true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// After a vanilla pause, the tears will not resume their normal velocity and will "stick" to the
|
|
183
|
+
// air. Even if we try to help the tears along by explicitly resetting all of the velocity-related
|
|
184
|
+
// variables to their initial values, this will not make a difference. Thus, revert to removing
|
|
185
|
+
// all of the tears and projectiles in the room.
|
|
186
|
+
removeAllTears();
|
|
187
|
+
removeAllProjectiles();
|
|
98
188
|
}
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
EntityType,
|
|
4
4
|
ModCallback,
|
|
5
5
|
} from "isaac-typescript-definitions";
|
|
6
|
-
import { game } from "../cachedClasses";
|
|
7
6
|
import { ModUpgraded } from "../classes/ModUpgraded";
|
|
8
7
|
import { ModCallbackCustom } from "../enums/ModCallbackCustom";
|
|
9
8
|
import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
|
|
10
9
|
import { spawn } from "../functions/entities";
|
|
11
10
|
import { getRoomListIndex } from "../functions/roomData";
|
|
11
|
+
import { getLatestRoomDescription } from "./roomHistory";
|
|
12
12
|
import { saveDataManager } from "./saveDataManager/exports";
|
|
13
13
|
|
|
14
14
|
interface PersistentEntityDescription {
|
|
@@ -64,18 +64,19 @@ function postEntityRemove(entity: Entity) {
|
|
|
64
64
|
const index = tuple[0];
|
|
65
65
|
|
|
66
66
|
// The persistent entity is despawning, presumably because the player is in the process of leaving
|
|
67
|
-
// the room. Keep track of the position for later. We use the previous room list index because
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const previousRoomListIndex =
|
|
72
|
-
|
|
67
|
+
// the room. Keep track of the position for later. We use the previous room list index because
|
|
68
|
+
// even though the `POST_NEW_ROOM` callback was not fired yet, we have already traveled to the
|
|
69
|
+
// next room.
|
|
70
|
+
const previousRoomDescription = getLatestRoomDescription();
|
|
71
|
+
const previousRoomListIndex = previousRoomDescription.roomListIndex;
|
|
72
|
+
const persistentEntityDescription: PersistentEntityDescription = {
|
|
73
73
|
entityType: entity.Type,
|
|
74
74
|
variant: entity.Variant,
|
|
75
75
|
subType: entity.SubType,
|
|
76
76
|
roomListIndex: previousRoomListIndex,
|
|
77
77
|
position: entity.Position,
|
|
78
|
-
}
|
|
78
|
+
};
|
|
79
|
+
v.level.persistentEntities.set(index, persistentEntityDescription);
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
// ModCallbackCustom.POST_NEW_ROOM_REORDERED
|