isaacscript-common 6.6.1-dev.1 → 6.6.1-dev.2
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/cachedClasses.d.ts +1 -0
- package/cachedClasses.js +59 -0
- package/callbacks/customRevive.js +153 -0
- package/callbacks/itemPickup.js +64 -0
- package/callbacks/postAmbush.js +54 -0
- package/callbacks/postBombExploded.js +20 -0
- package/callbacks/postBombInitLate.js +28 -0
- package/callbacks/postBoneSwing.js +49 -0
- package/callbacks/postCollectibleEmpty.js +32 -0
- package/callbacks/postCollectibleInitFirst.js +27 -0
- package/callbacks/postCursedTeleport.js +120 -0
- package/callbacks/postCustomDoorEnter.js +205 -0
- package/callbacks/postDiceRoomActivated.js +39 -0
- package/callbacks/postDoorRender.js +20 -0
- package/callbacks/postDoorUpdate.js +20 -0
- package/callbacks/postEffectInitLate.js +28 -0
- package/callbacks/postEffectStateChanged.js +31 -0
- package/callbacks/postEsauJr.js +70 -0
- package/callbacks/postFamiliarInitLate.js +28 -0
- package/callbacks/postFamiliarStateChanged.js +31 -0
- package/callbacks/postFlip.js +59 -0
- package/callbacks/postGreedModeWave.js +31 -0
- package/callbacks/postGridEntity.js +107 -0
- package/callbacks/postGridEntityCollision.js +49 -0
- package/callbacks/postGridEntityRender.js +20 -0
- package/callbacks/postHolyMantleRemoved.js +33 -0
- package/callbacks/postItemDischarged.js +94 -0
- package/callbacks/postKnifeInitLate.js +28 -0
- package/callbacks/postLaserInitLate.js +28 -0
- package/callbacks/postNPCInitLate.js +28 -0
- package/callbacks/postNPCStateChanged.js +31 -0
- package/callbacks/postNewRoomEarly.js +69 -0
- package/callbacks/postPickupCollect.js +37 -0
- package/callbacks/postPickupInitFirst.js +52 -0
- package/callbacks/postPickupInitLate.js +28 -0
- package/callbacks/postPickupStateChanged.js +31 -0
- package/callbacks/postPitRender.js +20 -0
- package/callbacks/postPitUpdate.js +20 -0
- package/callbacks/postPlayerChangeHealth.js +43 -0
- package/callbacks/postPlayerChangeType.js +31 -0
- package/callbacks/postPlayerCollectible.js +74 -0
- package/callbacks/postPlayerFatalDamage.js +74 -0
- package/callbacks/postPlayerInitLate.js +28 -0
- package/callbacks/postPlayerReordered.js +109 -0
- package/callbacks/postPoopRender.js +20 -0
- package/callbacks/postPoopUpdate.js +20 -0
- package/callbacks/postPressurePlateRender.js +20 -0
- package/callbacks/postPressurePlateUpdate.js +20 -0
- package/callbacks/postProjectileInitLate.js +28 -0
- package/callbacks/postPurchase.js +39 -0
- package/callbacks/postRockRender.js +20 -0
- package/callbacks/postRockUpdate.js +20 -0
- package/callbacks/postRoomClearChanged.js +41 -0
- package/callbacks/postSacrifice.js +38 -0
- package/callbacks/postSlotDestroyed.js +64 -0
- package/callbacks/postSlotInitUpdate.js +49 -0
- package/callbacks/postSlotRender.js +48 -0
- package/callbacks/postSpikesRender.js +20 -0
- package/callbacks/postSpikesUpdate.js +20 -0
- package/callbacks/postTNTRender.js +20 -0
- package/callbacks/postTNTUpdate.js +20 -0
- package/callbacks/postTearInitLate.js +28 -0
- package/callbacks/postTearInitVeryLate.js +32 -0
- package/callbacks/postTransformation.js +37 -0
- package/callbacks/postTrinketBreak.js +64 -0
- package/callbacks/preBerserkDeath.js +35 -0
- package/callbacks/preNewLevel.js +45 -0
- package/callbacks/reorderedCallbacks.js +136 -0
- package/callbacks/subscriptions/postAmbushFinished.js +20 -0
- package/callbacks/subscriptions/postAmbushStarted.js +20 -0
- package/callbacks/subscriptions/postBombInitLate.js +20 -0
- package/callbacks/subscriptions/postBoneExploded.js +20 -0
- package/callbacks/subscriptions/postBoneSwing.js +16 -0
- package/callbacks/subscriptions/postCollectibleEmpty.js +21 -0
- package/callbacks/subscriptions/postCollectibleInitFirst.js +21 -0
- package/callbacks/subscriptions/postCursedTeleport.js +16 -0
- package/callbacks/subscriptions/postCustomDoorEnter.js +21 -0
- package/callbacks/subscriptions/postCustomRevive.js +21 -0
- package/callbacks/subscriptions/postDiceRoomActivated.js +21 -0
- package/callbacks/subscriptions/postDoorRender.js +22 -0
- package/callbacks/subscriptions/postDoorUpdate.js +22 -0
- package/callbacks/subscriptions/postEffectInitLate.js +20 -0
- package/callbacks/subscriptions/postEffectStateChanged.js +20 -0
- package/callbacks/subscriptions/postEsauJr.js +16 -0
- package/callbacks/subscriptions/postFamiliarInitLate.js +20 -0
- package/callbacks/subscriptions/postFamiliarStateChanged.js +20 -0
- package/callbacks/subscriptions/postFirstEsauJr.js +16 -0
- package/callbacks/subscriptions/postFirstFlip.js +16 -0
- package/callbacks/subscriptions/postFlip.js +16 -0
- package/callbacks/subscriptions/postGameStartedReordered.js +16 -0
- package/callbacks/subscriptions/postGreedModeWave.js +16 -0
- package/callbacks/subscriptions/postGridEntityBroken.js +28 -0
- package/callbacks/subscriptions/postGridEntityCollision.js +28 -0
- package/callbacks/subscriptions/postGridEntityInit.js +28 -0
- package/callbacks/subscriptions/postGridEntityRemove.js +26 -0
- package/callbacks/subscriptions/postGridEntityRender.js +28 -0
- package/callbacks/subscriptions/postGridEntityStateChanged.js +28 -0
- package/callbacks/subscriptions/postGridEntityUpdate.js +28 -0
- package/callbacks/subscriptions/postHolyMantleRemoved.js +25 -0
- package/callbacks/subscriptions/postItemDischarged.js +21 -0
- package/callbacks/subscriptions/postItemPickup.js +25 -0
- package/callbacks/subscriptions/postKnifeInitLate.js +20 -0
- package/callbacks/subscriptions/postLaserInitLate.js +20 -0
- package/callbacks/subscriptions/postNPCInitLate.js +20 -0
- package/callbacks/subscriptions/postNPCStateChanged.js +24 -0
- package/callbacks/subscriptions/postNewLevelReordered.js +16 -0
- package/callbacks/subscriptions/postNewRoomEarly.js +16 -0
- package/callbacks/subscriptions/postNewRoomReordered.js +16 -0
- package/callbacks/subscriptions/postPEffectUpdateReordered.js +25 -0
- package/callbacks/subscriptions/postPickupCollect.js +20 -0
- package/callbacks/subscriptions/postPickupInitFirst.js +20 -0
- package/callbacks/subscriptions/postPickupInitLate.js +20 -0
- package/callbacks/subscriptions/postPickupStateChanged.js +20 -0
- package/callbacks/subscriptions/postPitRender.js +22 -0
- package/callbacks/subscriptions/postPitUpdate.js +22 -0
- package/callbacks/subscriptions/postPlayerChangeHealth.js +25 -0
- package/callbacks/subscriptions/postPlayerChangeType.js +20 -0
- package/callbacks/subscriptions/postPlayerCollectibleAdded.js +21 -0
- package/callbacks/subscriptions/postPlayerCollectibleRemoved.js +21 -0
- package/callbacks/subscriptions/postPlayerFatalDamage.js +29 -0
- package/callbacks/subscriptions/postPlayerInitLate.js +25 -0
- package/callbacks/subscriptions/postPlayerInitReordered.js +25 -0
- package/callbacks/subscriptions/postPlayerRenderReordered.js +25 -0
- package/callbacks/subscriptions/postPlayerUpdateReordered.js +25 -0
- package/callbacks/subscriptions/postPoopRender.js +22 -0
- package/callbacks/subscriptions/postPoopUpdate.js +22 -0
- package/callbacks/subscriptions/postPressurePlateRender.js +22 -0
- package/callbacks/subscriptions/postPressurePlateUpdate.js +22 -0
- package/callbacks/subscriptions/postProjectileInitLate.js +21 -0
- package/callbacks/subscriptions/postPurchase.js +16 -0
- package/callbacks/subscriptions/postRockRender.js +22 -0
- package/callbacks/subscriptions/postRockUpdate.js +22 -0
- package/callbacks/subscriptions/postRoomClearChanged.js +20 -0
- package/callbacks/subscriptions/postSacrifice.js +25 -0
- package/callbacks/subscriptions/postSlotAnimationChanged.js +20 -0
- package/callbacks/subscriptions/postSlotDestroyed.js +26 -0
- package/callbacks/subscriptions/postSlotInit.js +20 -0
- package/callbacks/subscriptions/postSlotRender.js +20 -0
- package/callbacks/subscriptions/postSlotUpdate.js +20 -0
- package/callbacks/subscriptions/postSpikesRender.js +22 -0
- package/callbacks/subscriptions/postSpikesUpdate.js +22 -0
- package/callbacks/subscriptions/postTNTRender.js +22 -0
- package/callbacks/subscriptions/postTNTUpdate.js +22 -0
- package/callbacks/subscriptions/postTearInitLate.js +20 -0
- package/callbacks/subscriptions/postTearInitVeryLate.js +20 -0
- package/callbacks/subscriptions/postTransformation.js +20 -0
- package/callbacks/subscriptions/postTrinketBreak.js +21 -0
- package/callbacks/subscriptions/preBerserkDeath.js +26 -0
- package/callbacks/subscriptions/preCustomRevive.js +29 -0
- package/callbacks/subscriptions/preItemPickup.js +25 -0
- package/callbacks/subscriptions/preNewLevel.js +16 -0
- package/classes/DefaultMap.js +145 -0
- package/classes/ModUpgraded.js +57 -0
- package/constants.js +143 -0
- package/constantsFirstLast.js +156 -0
- package/enums/AmbushType.js +6 -0
- package/enums/CornerType.js +8 -0
- package/enums/DecorationVariant.js +11 -0
- package/enums/HealthType.js +18 -0
- package/enums/ModCallbackCustom.js +1213 -0
- package/enums/PocketItemType.js +10 -0
- package/enums/RockAltType.js +9 -0
- package/enums/SerializationType.js +7 -0
- package/enums/SlotDestructionType.js +6 -0
- package/enums/private/CopyableIsaacAPIClassType.js +9 -0
- package/enums/private/SaveDataKey.js +8 -0
- package/enums/private/SerializationBrand.js +41 -0
- package/features/characterHealthConversion.js +86 -0
- package/features/characterStats.js +52 -0
- package/features/collectibleItemPoolType.js +45 -0
- package/features/customGridEntity.js +148 -0
- package/features/customStage/backdrop.js +191 -0
- package/features/customStage/customStageConstants.js +2 -0
- package/features/customStage/exports.js +147 -0
- package/features/customStage/gridEntities.js +138 -0
- package/features/customStage/init.js +104 -0
- package/features/customStage/metadata.json +1 -0
- package/features/customStage/shadows.js +63 -0
- package/features/customStage/streakText.js +35 -0
- package/features/customStage/util.js +36 -0
- package/features/customStage/v.js +18 -0
- package/features/customStage/versusScreen.js +184 -0
- package/features/debugDisplay/debugDisplay.js +183 -0
- package/features/debugDisplay/exports.js +441 -0
- package/features/debugDisplay/v.d.ts +18 -0
- package/features/debugDisplay/v.js +61 -0
- package/features/deployJSONRoom.js +532 -0
- package/features/disableAllSound.js +63 -0
- package/features/disableInputs.js +130 -0
- package/features/extraConsoleCommands/commandsDisplay.js +236 -0
- package/features/extraConsoleCommands/commandsSubroutines.js +109 -0
- package/features/extraConsoleCommands/exports.js +53 -0
- package/features/extraConsoleCommands/init.js +239 -0
- package/features/extraConsoleCommands/listCommands.js +1081 -0
- package/features/extraConsoleCommands/v.js +25 -0
- package/features/fadeInRemover.js +51 -0
- package/features/fastReset.js +61 -0
- package/features/forgottenSwitch.js +33 -0
- package/features/pause.js +68 -0
- package/features/persistentEntities.js +120 -0
- package/features/playerInventory.js +89 -0
- package/features/ponyDetection.js +63 -0
- package/features/preventCollectibleRotation.js +81 -0
- package/features/registerHotkey.js +91 -0
- package/features/roomClearFrame.js +42 -0
- package/features/runInNFrames.js +189 -0
- package/features/runNextRoom.js +34 -0
- package/features/saveDataManager/exports.js +183 -0
- package/features/saveDataManager/load.js +69 -0
- package/features/saveDataManager/main.js +131 -0
- package/features/saveDataManager/maps.js +9 -0
- package/features/saveDataManager/merge.js +139 -0
- package/features/saveDataManager/save.js +43 -0
- package/features/saveDataManager/saveDataManagerConstants.js +4 -0
- package/features/saveDataManager/serializationBrand.js +12 -0
- package/features/sirenHelpers.js +90 -0
- package/features/stageHistory.js +43 -0
- package/features/taintedLazarusPlayers.js +92 -0
- package/featuresInitialized.js +16 -0
- package/functions/ambush.js +35 -0
- package/functions/array.js +423 -0
- package/functions/benchmark.js +28 -0
- package/functions/bitwise.js +74 -0
- package/functions/bombs.js +11 -0
- package/functions/boss.js +137 -0
- package/functions/cacheFlag.js +11 -0
- package/functions/cards.js +217 -0
- package/functions/challenges.js +9 -0
- package/functions/character.js +102 -0
- package/functions/charge.js +202 -0
- package/functions/chargeBar.js +44 -0
- package/functions/collectibleCacheFlag.js +68 -0
- package/functions/collectibleSet.js +108 -0
- package/functions/collectibleTag.js +65 -0
- package/functions/collectibles.js +469 -0
- package/functions/color.d.ts +1 -1
- package/functions/color.js +60 -0
- package/functions/debug.js +60 -0
- package/functions/deepCopy.js +361 -0
- package/functions/deepCopyTests.js +308 -0
- package/functions/direction.js +41 -0
- package/functions/doors.js +326 -0
- package/functions/easing.js +142 -0
- package/functions/eden.js +32 -0
- package/functions/effects.js +11 -0
- package/functions/entity.js +324 -0
- package/functions/entitySpecific.js +481 -0
- package/functions/entityTypes.js +6 -0
- package/functions/enums.js +151 -0
- package/functions/familiars.js +85 -0
- package/functions/flag.js +137 -0
- package/functions/flying.js +88 -0
- package/functions/globals.js +230 -0
- package/functions/gridEntity.js +488 -0
- package/functions/gridEntitySpecific.js +109 -0
- package/functions/input.js +95 -0
- package/functions/isaacAPIClass.js +48 -0
- package/functions/jsonHelpers.js +40 -0
- package/functions/jsonRoom.js +132 -0
- package/functions/kColor.d.ts +1 -1
- package/functions/kColor.js +63 -0
- package/functions/language.js +13 -0
- package/functions/level.js +20 -0
- package/functions/log.js +567 -0
- package/functions/map.js +45 -0
- package/functions/math.js +103 -0
- package/functions/mergeTests.js +213 -0
- package/functions/minimap.js +80 -0
- package/functions/nextStage.js +290 -0
- package/functions/npc.js +101 -0
- package/functions/pickupVariants.js +47 -0
- package/functions/pickups.js +219 -0
- package/functions/pills.js +160 -0
- package/functions/player.js +808 -0
- package/functions/playerCenter.js +50 -0
- package/functions/playerDataStructures.js +114 -0
- package/functions/playerHealth.js +321 -0
- package/functions/playerIndex.js +160 -0
- package/functions/pocketItems.js +124 -0
- package/functions/positionVelocity.js +136 -0
- package/functions/random.js +73 -0
- package/functions/revive.js +140 -0
- package/functions/rng.d.ts +1 -1
- package/functions/rng.js +117 -0
- package/functions/roomData.js +174 -0
- package/functions/roomGrid.js +81 -0
- package/functions/roomShape.js +99 -0
- package/functions/rooms.js +487 -0
- package/functions/run.js +53 -0
- package/functions/saveFile.js +104 -0
- package/functions/seeds.js +18 -0
- package/functions/serialization.js +52 -0
- package/functions/set.js +99 -0
- package/functions/sound.js +9 -0
- package/functions/spawnCollectible.js +66 -0
- package/functions/sprite.js +80 -0
- package/functions/stage.js +172 -0
- package/functions/string.js +37 -0
- package/functions/table.js +143 -0
- package/functions/tears.js +31 -0
- package/functions/transformations.js +101 -0
- package/functions/trinketCacheFlag.js +46 -0
- package/functions/trinketGive.js +121 -0
- package/functions/trinkets.js +169 -0
- package/functions/tstlClass.js +125 -0
- package/functions/types.js +27 -0
- package/functions/ui.js +124 -0
- package/functions/utils.js +172 -0
- package/functions/vector.js +68 -0
- package/index.js +140 -0
- package/initCustomCallbacks.js +133 -0
- package/initFeatures.js +51 -0
- package/interfaces/AddCallbackParameterCustom.js +2 -0
- package/interfaces/ChargeBarSprites.js +2 -0
- package/interfaces/Corner.js +2 -0
- package/interfaces/CustomGridEntityData.js +2 -0
- package/interfaces/CustomStage.js +2 -0
- package/interfaces/CustomStageLua.js +13 -0
- package/interfaces/JSONRoomsFile.js +2 -0
- package/interfaces/PlayerHealth.js +2 -0
- package/interfaces/PocketItemDescription.js +2 -0
- package/interfaces/SaveData.js +2 -0
- package/interfaces/TrinketSituation.js +2 -0
- package/interfaces/private/TSTLClassMetatable.js +2 -0
- package/maps/PHDPillConversions.js +20 -0
- package/maps/cardMap.js +208 -0
- package/maps/characterMap.js +86 -0
- package/maps/collectibleDescriptionMap.js +728 -0
- package/maps/collectibleNameMap.js +727 -0
- package/maps/defaultPlayerStatMap.js +14 -0
- package/maps/falsePHDPillConversions.js +34 -0
- package/maps/gridEntityTypeToBrokenStateMap.js +29 -0
- package/maps/gridEntityXMLMap.js +128 -0
- package/maps/pillEffectMap.js +88 -0
- package/maps/roomShapeToTopLeftWallGridIndexMap.js +14 -0
- package/maps/roomTypeMap.js +39 -0
- package/maps/trinketDescriptionMap.js +196 -0
- package/maps/trinketNameMap.js +195 -0
- package/objects/LRoomShapeToRectangles.js +33 -0
- package/objects/backdropTypeToRockAltType.js +66 -0
- package/objects/bossNamePNGFileNames.js +112 -0
- package/objects/bossPortraitPNGFileNames.js +115 -0
- package/objects/callbackRegisterFunctions.js +170 -0
- package/objects/cardDescriptions.js +104 -0
- package/objects/cardNames.js +104 -0
- package/objects/cardTypes.js +103 -0
- package/objects/challengeNames.js +51 -0
- package/objects/characterNames.js +46 -0
- package/objects/coinSubTypeToValue.js +13 -0
- package/objects/colors.d.ts +1 -0
- package/objects/colors.js +24 -0
- package/objects/directionNames.js +9 -0
- package/objects/directionToDegrees.js +9 -0
- package/objects/directionToVector.js +10 -0
- package/objects/doorSlotFlagToDoorSlot.js +13 -0
- package/objects/doorSlotToDirection.js +13 -0
- package/objects/doorSlotToDoorSlotFlag.js +13 -0
- package/objects/isaacAPIClassTypeToBrand.js +9 -0
- package/objects/isaacAPIClassTypeToCopyFunction.js +12 -0
- package/objects/languageNames.js +11 -0
- package/objects/oppositeDoorSlots.js +13 -0
- package/objects/pillEffectClasses.js +56 -0
- package/objects/pillEffectNames.js +55 -0
- package/objects/pillEffectTypes.js +55 -0
- package/objects/playerNamePNGFileNames.js +55 -0
- package/objects/playerPortraitPNGFileNames.js +52 -0
- package/objects/roomShapeBounds.js +46 -0
- package/objects/roomShapeCorners.js +268 -0
- package/objects/roomShapeLayoutSizes.js +39 -0
- package/objects/roomShapeToBottomRightPosition.js +22 -0
- package/objects/roomShapeToDoorSlotCoordinates.js +109 -0
- package/objects/roomShapeToDoorSlots.js +69 -0
- package/objects/roomShapeToDoorSlotsToGridIndexDelta.js +113 -0
- package/objects/roomShapeToGridWidth.js +18 -0
- package/objects/roomShapeToTopLeftPosition.js +23 -0
- package/objects/roomShapeVolumes.js +30 -0
- package/objects/roomTypeGotoPrefixes.js +33 -0
- package/objects/roomTypeNames.js +34 -0
- package/objects/serializedIsaacAPIClassTypeToIdentityFunction.js +12 -0
- package/objects/stageTypeSuffixes.js +10 -0
- package/objects/stageTypeToLetter.js +12 -0
- package/objects/transformationNames.js +18 -0
- package/objects/versusScreenBackgroundColors.js +36 -0
- package/objects/versusScreenDirtSpotColors.js +36 -0
- package/package.json +1 -1
- package/patchErrorFunctions.js +67 -0
- package/sets/LRoomShapesSet.js +8 -0
- package/sets/bossSets.js +374 -0
- package/sets/charactersThatStartWithAnActiveItemSet.js +15 -0
- package/sets/charactersWithBlackHeartFromEternalHeartSet.js +6 -0
- package/sets/charactersWithFreeDevilDealsSet.js +3 -0
- package/sets/charactersWithNoRedHeartsSet.js +16 -0
- package/sets/charactersWithNoSoulHeartsSet.js +13 -0
- package/sets/chestPickupVariantsSet.js +16 -0
- package/sets/consoleCommandsSet.js +61 -0
- package/sets/familiarsThatShootPlayerTearsSet.js +12 -0
- package/sets/lostStyleCharactersSet.js +13 -0
- package/sets/mineShaftRoomSubTypesSet.js +9 -0
- package/sets/narrowRoomShapesSet.js +8 -0
- package/sets/redHeartSubTypesSet.js +7 -0
- package/sets/sinEntityTypesSet.js +11 -0
- package/sets/singleUseActiveCollectibleTypesSet.js +12 -0
- package/sets/storyBossesSet.js +17 -0
- package/shaderCrashFix.js +17 -0
- package/types/AnyEntity.js +2 -0
- package/types/CollectibleIndex.js +2 -0
- package/types/PickingUpItem.js +38 -0
- package/types/PlayerIndex.js +2 -0
- package/types/private/IsaacAPIClass.js +2 -0
- package/types/private/SerializedIsaacAPIClass.js +2 -0
- package/types/private/TSTLClass.js +2 -0
- package/upgradeMod.js +47 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
// Basement Renovator can create custom rooms that are saved to XML files. These XML files can be
|
|
2
|
+
// converted to JSON so that they can be imported by TypeScript code. Then, existing rooms can be
|
|
3
|
+
// manually replaced with a custom room by manually removing everything in the room and rebuilding
|
|
4
|
+
// it from scratch based on the JSON data.
|
|
5
|
+
import { CollectibleType, EffectVariant, EntityCollisionClass, EntityFlag, EntityGridCollisionClass, EntityType, GridEntityType, ModCallback, PickupVariant, PitfallVariant, RoomType, } from "isaac-typescript-definitions";
|
|
6
|
+
import { game } from "../cachedClasses";
|
|
7
|
+
import { DefaultMap } from "../classes/DefaultMap";
|
|
8
|
+
import { ModCallbackCustom } from "../enums/ModCallbackCustom";
|
|
9
|
+
import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
|
|
10
|
+
import { emptyArray } from "../functions/array";
|
|
11
|
+
import { getEntityIDFromConstituents, removeAllMatchingEntities, spawn, spawnWithSeed, } from "../functions/entity";
|
|
12
|
+
import { getNPCs, removeAllBombs, removeAllPickups, } from "../functions/entitySpecific";
|
|
13
|
+
import { convertXMLGridEntityType, getAllGridIndexes, getGridEntities, getGridEntityIDFromConstituents, removeAllGridExcept, removeGrid, setGridEntityInvisible, spawnGridWithVariant, } from "../functions/gridEntity";
|
|
14
|
+
import { getRandomJSONRoom } from "../functions/jsonRoom";
|
|
15
|
+
import { log } from "../functions/log";
|
|
16
|
+
import { getRandomSeed, isRNG, newRNG } from "../functions/rng";
|
|
17
|
+
import { getRoomListIndex } from "../functions/roomData";
|
|
18
|
+
import { gridCoordinatesToWorldPosition } from "../functions/roomGrid";
|
|
19
|
+
import { setRoomCleared, setRoomUncleared } from "../functions/rooms";
|
|
20
|
+
import { spawnCollectible } from "../functions/spawnCollectible";
|
|
21
|
+
import { runNextGameFrame } from "./runInNFrames";
|
|
22
|
+
import { saveDataManager } from "./saveDataManager/exports";
|
|
23
|
+
const FEATURE_NAME = "deployJSONRoom";
|
|
24
|
+
const NPC_TYPES_TO_NOT_REMOVE = new Set([
|
|
25
|
+
EntityType.DARK_ESAU,
|
|
26
|
+
]);
|
|
27
|
+
const PERSISTENT_ENTITY_TYPES = new Set([
|
|
28
|
+
EntityType.WALL_HUGGER,
|
|
29
|
+
]);
|
|
30
|
+
const v = {
|
|
31
|
+
level: {
|
|
32
|
+
deployedRoomListIndexes: new Set(),
|
|
33
|
+
/** Indexed by room list index. */
|
|
34
|
+
roomToPersistentEntitiesMap: new DefaultMap(() => []),
|
|
35
|
+
/** Indexed by room list index. */
|
|
36
|
+
roomToDecorationGridIndexesMap: new DefaultMap(() => []),
|
|
37
|
+
},
|
|
38
|
+
room: {
|
|
39
|
+
manuallyUsingShovel: false,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
/** @internal */
|
|
43
|
+
export function deployJSONRoomInit(mod) {
|
|
44
|
+
saveDataManager(FEATURE_NAME, v);
|
|
45
|
+
mod.AddCallback(ModCallback.PRE_USE_ITEM, preUseItemWeNeedToGoDeeper, CollectibleType.WE_NEED_TO_GO_DEEPER); // 23
|
|
46
|
+
mod.AddCallbackCustom(ModCallbackCustom.POST_NEW_ROOM_REORDERED, postNewRoomReordered);
|
|
47
|
+
}
|
|
48
|
+
// ModCallback.PRE_USE_ITEM (23)
|
|
49
|
+
// CollectibleType.WE_NEED_TO_GO_DEEPER (84)
|
|
50
|
+
function preUseItemWeNeedToGoDeeper(_collectibleType, _rng, player) {
|
|
51
|
+
if (v.room.manuallyUsingShovel) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
const roomListIndex = getRoomListIndex();
|
|
55
|
+
if (!v.level.deployedRoomListIndexes.has(roomListIndex)) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
// If the player uses the shovel in a JSON room, then it will always reveal a crawl space. This is
|
|
59
|
+
// because the room is filled with invisible decorations to prevent any grid entities from
|
|
60
|
+
// respawning. In order to restore the normal shovel functionality, we cancel the shovel use,
|
|
61
|
+
// remove all the decorations, wait a frame, manually use the shovel again, and then respawn the
|
|
62
|
+
// decorations. (We can't do it all on this frame because updating the room causes two invocations
|
|
63
|
+
// of the shovel to happen.)
|
|
64
|
+
const decorations = getGridEntities(GridEntityType.DECORATION);
|
|
65
|
+
for (const decoration of decorations) {
|
|
66
|
+
removeGrid(decoration, false);
|
|
67
|
+
}
|
|
68
|
+
const playerPtr = EntityPtr(player);
|
|
69
|
+
runNextGameFrame(() => {
|
|
70
|
+
const futureEntity = playerPtr.Ref;
|
|
71
|
+
if (futureEntity === undefined) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const futurePlayer = futureEntity.ToPlayer();
|
|
75
|
+
if (futurePlayer === undefined) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
v.room.manuallyUsingShovel = true;
|
|
79
|
+
futurePlayer.UseActiveItem(CollectibleType.WE_NEED_TO_GO_DEEPER);
|
|
80
|
+
v.room.manuallyUsingShovel = false;
|
|
81
|
+
const decorationGridIndexes = v.level.roomToDecorationGridIndexesMap.getAndSetDefault(roomListIndex);
|
|
82
|
+
emptyArray(decorationGridIndexes);
|
|
83
|
+
fillRoomWithDecorations();
|
|
84
|
+
});
|
|
85
|
+
// Cancel the effect.
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
// ModCallbackCustom.POST_NEW_ROOM_REORDERED
|
|
89
|
+
function postNewRoomReordered() {
|
|
90
|
+
const roomListIndex = getRoomListIndex();
|
|
91
|
+
if (!v.level.deployedRoomListIndexes.has(roomListIndex)) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
setDecorationsInvisible();
|
|
95
|
+
respawnPersistentEntities();
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Every time we re-enter a deployed room, the sprites for all of the decorations will come back, so
|
|
99
|
+
* we have to remove them again.
|
|
100
|
+
*/
|
|
101
|
+
function setDecorationsInvisible() {
|
|
102
|
+
const room = game.GetRoom();
|
|
103
|
+
const roomListIndex = getRoomListIndex();
|
|
104
|
+
const decorationGridIndexes = v.level.roomToDecorationGridIndexesMap.getAndSetDefault(roomListIndex);
|
|
105
|
+
for (const gridIndex of decorationGridIndexes) {
|
|
106
|
+
const gridEntity = room.GetGridEntity(gridIndex);
|
|
107
|
+
if (gridEntity !== undefined) {
|
|
108
|
+
// Other grid entities may have spawned, like trapdoors or crawl spaces. Thus, only make
|
|
109
|
+
// decorations invisible.
|
|
110
|
+
const gridEntityType = gridEntity.GetType();
|
|
111
|
+
if (gridEntityType === GridEntityType.DECORATION) {
|
|
112
|
+
setGridEntityInvisible(gridEntity);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Some entities must be manually respawned every time the player re-enters the room. */
|
|
118
|
+
function respawnPersistentEntities() {
|
|
119
|
+
const room = game.GetRoom();
|
|
120
|
+
const roomListIndex = getRoomListIndex();
|
|
121
|
+
const persistentEntities = v.level.roomToPersistentEntitiesMap.getAndSetDefault(roomListIndex);
|
|
122
|
+
for (const persistentEntity of persistentEntities) {
|
|
123
|
+
const position = room.GetGridPosition(persistentEntity.gridIndex);
|
|
124
|
+
spawn(persistentEntity.entityType, persistentEntity.variant, persistentEntity.subType, position);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Helper function to deconstruct a vanilla room and set up a custom room in its place.
|
|
129
|
+
* Specifically, this will clear the current room of all entities and grid entities, and then spawn
|
|
130
|
+
* all of the entries and grid entities in the provided JSON room.
|
|
131
|
+
*
|
|
132
|
+
* This function is meant to be used in the PostNewRoom callback.
|
|
133
|
+
*
|
|
134
|
+
* For example:
|
|
135
|
+
*
|
|
136
|
+
* ```ts
|
|
137
|
+
*
|
|
138
|
+
* import customRooms from "./customRooms";
|
|
139
|
+
*
|
|
140
|
+
* const firstJSONRoom = customRooms.rooms.room[0];
|
|
141
|
+
* deployJSONRoom(firstJSONRoom);
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @param jsonRoom The JSON room to deploy. *
|
|
145
|
+
* @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
|
|
146
|
+
* `RNG.Next` method will be called. Default is `getRandomSeed()`.
|
|
147
|
+
* @param verbose Optional. If specified, will write entries to the "log.txt" file that describe
|
|
148
|
+
* what the function is doing. Default is false.
|
|
149
|
+
*/
|
|
150
|
+
export function deployJSONRoom(jsonRoom, seedOrRNG = getRandomSeed(), verbose = false) {
|
|
151
|
+
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
152
|
+
const rng = isRNG(seedOrRNG) ? seedOrRNG : newRNG(seedOrRNG);
|
|
153
|
+
if (verbose) {
|
|
154
|
+
log("Starting to empty the room of entities and grid entities.");
|
|
155
|
+
}
|
|
156
|
+
emptyRoom(false);
|
|
157
|
+
if (verbose) {
|
|
158
|
+
log("Finished emptying the room of entities and grid entities.");
|
|
159
|
+
}
|
|
160
|
+
if (verbose) {
|
|
161
|
+
log("Starting to spawn all of the new entities and grid entities.");
|
|
162
|
+
}
|
|
163
|
+
spawnAllEntities(jsonRoom, rng, verbose);
|
|
164
|
+
if (verbose) {
|
|
165
|
+
log("Finished spawning all of the new entities and grid entities.");
|
|
166
|
+
}
|
|
167
|
+
fixPitGraphics();
|
|
168
|
+
fillRoomWithDecorations();
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Helper function to deconstruct a vanilla room and set up a custom room in its place.
|
|
172
|
+
* Specifically, this will clear the current room of all entities and grid entities, and then spawn
|
|
173
|
+
* all of the entries and grid entities in one of the provided JSON rooms.
|
|
174
|
+
*
|
|
175
|
+
* This function is meant to be used in the PostNewRoom callback.
|
|
176
|
+
*
|
|
177
|
+
* Note that this function does not simply choose a random element in the provided array; it will
|
|
178
|
+
* properly account for each room weight using the algorithm from:
|
|
179
|
+
* https://stackoverflow.com/questions/1761626/weighted-random-numbers
|
|
180
|
+
*
|
|
181
|
+
* For example:
|
|
182
|
+
*
|
|
183
|
+
* ```ts
|
|
184
|
+
* import customRooms from "./customRooms";
|
|
185
|
+
*
|
|
186
|
+
* const jsonRooms = customRooms.rooms.room;
|
|
187
|
+
* deployRandomJSONRoom(jsonRooms);
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* @param jsonRooms An array of JSON rooms to randomly select from. In practice, this will be
|
|
191
|
+
* something like.
|
|
192
|
+
* @param seedOrRNG Optional. The `Seed` or `RNG` object to use. If an `RNG` object is provided, the
|
|
193
|
+
* `RNG.Next` method will be called. Default is `getRandomSeed()`.
|
|
194
|
+
* @param verbose Optional. If specified, will write entries to the "log.txt" file that describe
|
|
195
|
+
* what the function is doing. Default is false.
|
|
196
|
+
*/
|
|
197
|
+
export function deployRandomJSONRoom(jsonRooms, seedOrRNG = getRandomSeed(), verbose = false) {
|
|
198
|
+
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
199
|
+
const rng = isRNG(seedOrRNG) ? seedOrRNG : newRNG(seedOrRNG);
|
|
200
|
+
const randomJSONRoom = getRandomJSONRoom(jsonRooms, rng, verbose);
|
|
201
|
+
if (verbose) {
|
|
202
|
+
log(`Randomly chose JSON room ${randomJSONRoom.$.type}.${randomJSONRoom.$.variant}.${randomJSONRoom.$.subtype} with name: ${randomJSONRoom.$.name}`);
|
|
203
|
+
}
|
|
204
|
+
return deployJSONRoom(randomJSONRoom, rng, verbose);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Helper function to remove all naturally spawning entities and grid entities from a room. Notably,
|
|
208
|
+
* this will not remove players (1), tears (2), familiars (3), lasers (7), knives (8), projectiles
|
|
209
|
+
* (9), blacklisted NPCs such as Dark Esau, charmed NPCs, friendly NPCs, persistent NPCs, most
|
|
210
|
+
* effects (1000), doors, and walls.
|
|
211
|
+
*
|
|
212
|
+
* @param fillWithDecorations Optional. Set to true to fill every grid tile with an invisible
|
|
213
|
+
* decoration, which prevents vanilla entities in the room from
|
|
214
|
+
* respawning the next time that the player enters. Default is false.
|
|
215
|
+
*/
|
|
216
|
+
export function emptyRoom(fillWithDecorations) {
|
|
217
|
+
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
218
|
+
const roomListIndex = getRoomListIndex();
|
|
219
|
+
v.level.deployedRoomListIndexes.add(roomListIndex);
|
|
220
|
+
removeAllBombs(); // 4
|
|
221
|
+
removeAllPickups(); // 5
|
|
222
|
+
removeAllMatchingEntities(EntityType.SLOT); // 6
|
|
223
|
+
removeSpecificNPCs();
|
|
224
|
+
removeAllMatchingEntities(EntityType.EFFECT, EffectVariant.DEVIL);
|
|
225
|
+
removeAllMatchingEntities(EntityType.EFFECT, EffectVariant.ANGEL);
|
|
226
|
+
removeAllGridExcept(GridEntityType.WALL, // 15
|
|
227
|
+
GridEntityType.DOOR);
|
|
228
|
+
setRoomCleared();
|
|
229
|
+
if (fillWithDecorations) {
|
|
230
|
+
fillRoomWithDecorations();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* We remove entities in the PostNewRoom callback instead of in the PreRoomEntitySpawn callback so
|
|
235
|
+
* that they will not re-appear when we re-enter the room.
|
|
236
|
+
*/
|
|
237
|
+
function removeSpecificNPCs() {
|
|
238
|
+
const room = game.GetRoom();
|
|
239
|
+
for (const npc of getNPCs()) {
|
|
240
|
+
if (NPC_TYPES_TO_NOT_REMOVE.has(npc.Type)) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (npc.HasEntityFlags(EntityFlag.CHARM) ||
|
|
244
|
+
npc.HasEntityFlags(EntityFlag.FRIENDLY) ||
|
|
245
|
+
npc.HasEntityFlags(EntityFlag.PERSISTENT)) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
npc.ClearEntityFlags(EntityFlag.APPEAR);
|
|
249
|
+
npc.Remove();
|
|
250
|
+
// When fire places are removed, they will leave behind a "path" that will prevent future grid
|
|
251
|
+
// entities from being spawned on the same tile. Thus, reset the path for this tile if this is a
|
|
252
|
+
// fire place.
|
|
253
|
+
if (npc.Type === EntityType.FIREPLACE) {
|
|
254
|
+
const gridIndex = room.GetGridIndex(npc.Position);
|
|
255
|
+
room.SetGridPath(gridIndex, 0);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* We removed most normal entities, which should prevent them from respawning when the player
|
|
261
|
+
* re-enters the room. However, this is not the case for grid entities; even if they are removed,
|
|
262
|
+
* they will come back when the player re-enters the room.
|
|
263
|
+
*
|
|
264
|
+
* In order to prevent this from happening, we can spawn a grid entity on every tile that does not
|
|
265
|
+
* already have a grid entity. The natural grid entity to choose for this purpose is a decoration,
|
|
266
|
+
* since it is non-interacting.
|
|
267
|
+
*
|
|
268
|
+
* Another option besides decorations would be to use a pressure plates with a state of 1, which is
|
|
269
|
+
* a state that is normally unused by the game and makes it invisible & persistent. However, pickups
|
|
270
|
+
* will not be able to spawn on pressure plates, which lead to various bugs (e.g. pickups spawning
|
|
271
|
+
* on top of pits). Thus, we use a decoration and remove its sprite to make it invisible.
|
|
272
|
+
*
|
|
273
|
+
* Yet another option is to replace the room data with that of an empty room. However, the room data
|
|
274
|
+
* must exactly match the room type, the room shape, and the doors, so this is not possible to do in
|
|
275
|
+
* a robust way without adding empty rooms to the mod's `content` folder to draw the data from.
|
|
276
|
+
*/
|
|
277
|
+
function fillRoomWithDecorations() {
|
|
278
|
+
const room = game.GetRoom();
|
|
279
|
+
const roomListIndex = getRoomListIndex();
|
|
280
|
+
const decorationGridIndexes = v.level.roomToDecorationGridIndexesMap.getAndSetDefault(roomListIndex);
|
|
281
|
+
for (const gridIndex of getAllGridIndexes()) {
|
|
282
|
+
const existingGridEntity = room.GetGridEntity(gridIndex);
|
|
283
|
+
if (existingGridEntity !== undefined) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const position = room.GetGridPosition(gridIndex);
|
|
287
|
+
const decoration = Isaac.GridSpawn(GridEntityType.DECORATION, 0, position);
|
|
288
|
+
if (decoration !== undefined) {
|
|
289
|
+
setGridEntityInvisible(decoration);
|
|
290
|
+
}
|
|
291
|
+
decorationGridIndexes.push(gridIndex);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function spawnAllEntities(jsonRoom, rng, verbose = false) {
|
|
295
|
+
let shouldUnclearRoom = false;
|
|
296
|
+
for (const jsonSpawn of jsonRoom.spawn) {
|
|
297
|
+
const xString = jsonSpawn.$.x;
|
|
298
|
+
const x = tonumber(xString);
|
|
299
|
+
if (x === undefined) {
|
|
300
|
+
error(`Failed to convert the following x coordinate to a number (for a spawn): ${xString}`);
|
|
301
|
+
}
|
|
302
|
+
const yString = jsonSpawn.$.y;
|
|
303
|
+
const y = tonumber(yString);
|
|
304
|
+
if (y === undefined) {
|
|
305
|
+
error(`Failed to convert the following y coordinate to a number (for a spawn): ${yString}`);
|
|
306
|
+
}
|
|
307
|
+
if (jsonSpawn.entity.length > 1) {
|
|
308
|
+
error("Stacked entities are not implemented for JSON rooms.");
|
|
309
|
+
}
|
|
310
|
+
const firstXMLEntity = jsonSpawn.entity[0];
|
|
311
|
+
if (firstXMLEntity === undefined) {
|
|
312
|
+
error('Failed to get the first JSON entity from an "entity" array.');
|
|
313
|
+
}
|
|
314
|
+
const entityTypeString = firstXMLEntity.$.type;
|
|
315
|
+
const entityType = tonumber(entityTypeString);
|
|
316
|
+
if (entityType === undefined) {
|
|
317
|
+
error(`Failed to convert the entity type to a number: ${entityTypeString}`);
|
|
318
|
+
}
|
|
319
|
+
const variantString = firstXMLEntity.$.variant;
|
|
320
|
+
const variant = tonumber(variantString);
|
|
321
|
+
if (variant === undefined) {
|
|
322
|
+
error(`Failed to convert the entity variant to a number: ${variant}`);
|
|
323
|
+
}
|
|
324
|
+
const subTypeString = firstXMLEntity.$.subtype;
|
|
325
|
+
const subType = tonumber(subTypeString);
|
|
326
|
+
if (subType === undefined) {
|
|
327
|
+
error(`Failed to convert the entity sub-type to a number: ${subType}`);
|
|
328
|
+
}
|
|
329
|
+
// Note that XML entity type 1000 is a rock, not an effect.
|
|
330
|
+
if (entityType >= 1000) {
|
|
331
|
+
if (verbose) {
|
|
332
|
+
const gridEntityID = getGridEntityIDFromConstituents(entityType, variant);
|
|
333
|
+
log(`Spawning grid entity ${gridEntityID} at: (${x}, ${y})`);
|
|
334
|
+
}
|
|
335
|
+
spawnGridEntityForJSONRoom(entityType, variant, x, y);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
if (verbose) {
|
|
339
|
+
const entityID = getEntityIDFromConstituents(entityType, variant, subType);
|
|
340
|
+
log(`Spawning normal entity ${entityID} at: (${x}, ${y})`);
|
|
341
|
+
}
|
|
342
|
+
const entity = spawnNormalEntityForJSONRoom(entityType, variant, subType, x, y, rng);
|
|
343
|
+
const npc = entity.ToNPC();
|
|
344
|
+
if (npc !== undefined && npc.CanShutDoors) {
|
|
345
|
+
shouldUnclearRoom = true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// After emptying the room, we manually cleared the room. However, if the room layout contains an
|
|
350
|
+
// battle NPC, then we need to reset the clear state and close the doors again.
|
|
351
|
+
if (shouldUnclearRoom) {
|
|
352
|
+
if (verbose) {
|
|
353
|
+
log("Setting the room to be uncleared since there were one or more battle NPCs spawned.");
|
|
354
|
+
}
|
|
355
|
+
setRoomUncleared();
|
|
356
|
+
}
|
|
357
|
+
else if (verbose) {
|
|
358
|
+
log("Leaving the room cleared since there were no battle NPCs spawned.");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function spawnGridEntityForJSONRoom(gridEntityXMLType, gridEntityXMLVariant, x, y) {
|
|
362
|
+
const room = game.GetRoom();
|
|
363
|
+
const gridEntityTuple = convertXMLGridEntityType(gridEntityXMLType, gridEntityXMLVariant);
|
|
364
|
+
if (gridEntityTuple === undefined) {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
const [gridEntityType, variant] = gridEntityTuple;
|
|
368
|
+
const position = gridCoordinatesToWorldPosition(x, y);
|
|
369
|
+
const gridIndex = room.GetGridIndex(position);
|
|
370
|
+
const gridEntity = spawnGridWithVariant(gridEntityType, variant, gridIndex);
|
|
371
|
+
if (gridEntity === undefined) {
|
|
372
|
+
return gridEntity;
|
|
373
|
+
}
|
|
374
|
+
// Prevent poops from playing an appear animation, since that is not supposed to normally happen
|
|
375
|
+
// when entering a new room.
|
|
376
|
+
if (gridEntityType === GridEntityType.POOP) {
|
|
377
|
+
const sprite = gridEntity.GetSprite();
|
|
378
|
+
sprite.Play("State1", true);
|
|
379
|
+
sprite.SetLastFrame();
|
|
380
|
+
}
|
|
381
|
+
return gridEntity;
|
|
382
|
+
}
|
|
383
|
+
function spawnNormalEntityForJSONRoom(entityType, variant, subType, x, y, rng) {
|
|
384
|
+
const room = game.GetRoom();
|
|
385
|
+
const roomType = room.GetType();
|
|
386
|
+
const position = gridCoordinatesToWorldPosition(x, y);
|
|
387
|
+
const seed = rng.Next();
|
|
388
|
+
let entity;
|
|
389
|
+
if (entityType === EntityType.PICKUP &&
|
|
390
|
+
variant === PickupVariant.COLLECTIBLE) {
|
|
391
|
+
const options = roomType === RoomType.ANGEL;
|
|
392
|
+
entity = spawnCollectible(subType, position, seed, options);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
entity = spawnWithSeed(entityType, variant, subType, position, seed);
|
|
396
|
+
}
|
|
397
|
+
// For some reason, Pitfalls do not spawn with the correct collision classes.
|
|
398
|
+
if (entityType === EntityType.PITFALL &&
|
|
399
|
+
variant === PitfallVariant.PITFALL) {
|
|
400
|
+
entity.EntityCollisionClass = EntityCollisionClass.ENEMIES;
|
|
401
|
+
entity.GridCollisionClass = EntityGridCollisionClass.WALLS;
|
|
402
|
+
}
|
|
403
|
+
storePersistentEntity(entity);
|
|
404
|
+
return entity;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Some entities must be manually respawned every time the player re-enters the room. If we just
|
|
408
|
+
* spawned one such entity, then record it for later.
|
|
409
|
+
*/
|
|
410
|
+
function storePersistentEntity(entity) {
|
|
411
|
+
if (!PERSISTENT_ENTITY_TYPES.has(entity.Type)) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const room = game.GetRoom();
|
|
415
|
+
const gridIndex = room.GetGridIndex(entity.Position);
|
|
416
|
+
const roomListIndex = getRoomListIndex();
|
|
417
|
+
const persistentEntity = {
|
|
418
|
+
gridIndex,
|
|
419
|
+
entityType: entity.Type,
|
|
420
|
+
variant: entity.Variant,
|
|
421
|
+
subType: entity.SubType,
|
|
422
|
+
};
|
|
423
|
+
const persistentEntities = v.level.roomToPersistentEntitiesMap.getAndSetDefault(roomListIndex);
|
|
424
|
+
persistentEntities.push(persistentEntity);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* By default, when spawning multiple pits next to each other, the graphics will not "meld"
|
|
428
|
+
* together. Thus, now that all of the entities in the room are spawned, we must iterate over the
|
|
429
|
+
* pits in the room and manually fix their sprites, if necessary.
|
|
430
|
+
*/
|
|
431
|
+
function fixPitGraphics() {
|
|
432
|
+
const room = game.GetRoom();
|
|
433
|
+
const gridWidth = room.GetGridWidth();
|
|
434
|
+
const pitMap = getPitMap();
|
|
435
|
+
for (const [gridIndex, gridEntity] of pitMap.entries()) {
|
|
436
|
+
const gridIndexLeft = gridIndex - 1;
|
|
437
|
+
const L = pitMap.has(gridIndexLeft);
|
|
438
|
+
const gridIndexRight = gridIndex + 1;
|
|
439
|
+
const R = pitMap.has(gridIndexRight);
|
|
440
|
+
const gridIndexUp = gridIndex - gridWidth;
|
|
441
|
+
const U = pitMap.has(gridIndexUp);
|
|
442
|
+
const gridIndexDown = gridIndex + gridWidth;
|
|
443
|
+
const D = pitMap.has(gridIndexDown);
|
|
444
|
+
const gridIndexUpLeft = gridIndex - gridWidth - 1;
|
|
445
|
+
const UL = pitMap.has(gridIndexUpLeft);
|
|
446
|
+
const gridIndexUpRight = gridIndex - gridWidth + 1;
|
|
447
|
+
const UR = pitMap.has(gridIndexUpRight);
|
|
448
|
+
const gridIndexDownLeft = gridIndex + gridWidth - 1;
|
|
449
|
+
const DL = pitMap.has(gridIndexDownLeft);
|
|
450
|
+
const gridIndexDownRight = gridIndex + gridWidth + 1;
|
|
451
|
+
const DR = pitMap.has(gridIndexDownRight);
|
|
452
|
+
const pitFrame = getPitFrame(L, R, U, D, UL, UR, DL, DR);
|
|
453
|
+
const sprite = gridEntity.GetSprite();
|
|
454
|
+
sprite.SetFrame(pitFrame);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
function getPitMap() {
|
|
458
|
+
const pitMap = new Map();
|
|
459
|
+
for (const gridEntity of getGridEntities(GridEntityType.PIT)) {
|
|
460
|
+
const gridIndex = gridEntity.GetGridIndex();
|
|
461
|
+
pitMap.set(gridIndex, gridEntity);
|
|
462
|
+
}
|
|
463
|
+
return pitMap;
|
|
464
|
+
}
|
|
465
|
+
/** The logic in this function is copied from Basement Renovator. */
|
|
466
|
+
function getPitFrame(L, R, U, D, UL, UR, DL, DR) {
|
|
467
|
+
let F = 0;
|
|
468
|
+
// First, check for bitwise frames. (It works for all combinations of just left/up/right/down.)
|
|
469
|
+
if (L) {
|
|
470
|
+
F |= 1;
|
|
471
|
+
}
|
|
472
|
+
if (U) {
|
|
473
|
+
F |= 2;
|
|
474
|
+
}
|
|
475
|
+
if (R) {
|
|
476
|
+
F |= 4;
|
|
477
|
+
}
|
|
478
|
+
if (D) {
|
|
479
|
+
F |= 8;
|
|
480
|
+
}
|
|
481
|
+
// Then, check for other combinations.
|
|
482
|
+
if (U && L && !UL && !R && !D) {
|
|
483
|
+
F = 17;
|
|
484
|
+
}
|
|
485
|
+
if (U && R && !UR && !L && !D) {
|
|
486
|
+
F = 18;
|
|
487
|
+
}
|
|
488
|
+
if (L && D && !DL && !U && !R) {
|
|
489
|
+
F = 19;
|
|
490
|
+
}
|
|
491
|
+
if (R && D && !DR && !L && !U) {
|
|
492
|
+
F = 20;
|
|
493
|
+
}
|
|
494
|
+
if (L && U && R && D && !UL) {
|
|
495
|
+
F = 21;
|
|
496
|
+
}
|
|
497
|
+
if (L && U && R && D && !UR) {
|
|
498
|
+
F = 22;
|
|
499
|
+
}
|
|
500
|
+
if (U && R && D && !L && !UR) {
|
|
501
|
+
F = 25;
|
|
502
|
+
}
|
|
503
|
+
if (L && U && D && !R && !UL) {
|
|
504
|
+
F = 26;
|
|
505
|
+
}
|
|
506
|
+
if (L && U && R && D && !DL && !DR) {
|
|
507
|
+
F = 24;
|
|
508
|
+
}
|
|
509
|
+
if (L && U && R && D && !UR && !UL) {
|
|
510
|
+
F = 23;
|
|
511
|
+
}
|
|
512
|
+
if (L && U && R && UL && !UR && !D) {
|
|
513
|
+
F = 27;
|
|
514
|
+
}
|
|
515
|
+
if (L && U && R && UR && !UL && !D) {
|
|
516
|
+
F = 28;
|
|
517
|
+
}
|
|
518
|
+
if (L && U && R && !D && !UR && !UL) {
|
|
519
|
+
F = 29;
|
|
520
|
+
}
|
|
521
|
+
if (L && R && D && DL && !U && !DR) {
|
|
522
|
+
F = 30;
|
|
523
|
+
}
|
|
524
|
+
if (L && R && D && DR && !U && !DL) {
|
|
525
|
+
F = 31;
|
|
526
|
+
}
|
|
527
|
+
if (L && R && D && !U && !DL && !DR) {
|
|
528
|
+
F = 32;
|
|
529
|
+
}
|
|
530
|
+
return F;
|
|
531
|
+
}
|
|
532
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95SlNPTlJvb20uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wYWNrYWdlcy9pc2FhY3NjcmlwdC1jb21tb24vc3JjL2ZlYXR1cmVzL2RlcGxveUpTT05Sb29tLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGlHQUFpRztBQUNqRyxpR0FBaUc7QUFDakcsa0dBQWtHO0FBQ2xHLDBDQUEwQztBQUUxQyxPQUFPLEVBQ0wsZUFBZSxFQUNmLGFBQWEsRUFDYixvQkFBb0IsRUFDcEIsVUFBVSxFQUNWLHdCQUF3QixFQUN4QixVQUFVLEVBQ1YsY0FBYyxFQUVkLFdBQVcsRUFDWCxhQUFhLEVBQ2IsY0FBYyxFQUNkLFFBQVEsR0FDVCxNQUFNLDhCQUE4QixDQUFDO0FBQ3RDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN4QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFbkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sRUFDTCwyQkFBMkIsRUFDM0IseUJBQXlCLEVBQ3pCLEtBQUssRUFDTCxhQUFhLEdBQ2QsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQ0wsT0FBTyxFQUNQLGNBQWMsRUFDZCxnQkFBZ0IsR0FDakIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQ0wsd0JBQXdCLEVBQ3hCLGlCQUFpQixFQUNqQixlQUFlLEVBQ2YsK0JBQStCLEVBQy9CLG1CQUFtQixFQUNuQixVQUFVLEVBQ1Ysc0JBQXNCLEVBQ3RCLG9CQUFvQixHQUNyQixNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixD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QyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUU7UUFDN0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFO1FBQzdCLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDUjtJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRTtRQUM3QixDQUFDLEdBQUcsRUFBRSxDQUFDO0tBQ1I7SUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUU7UUFDN0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDM0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDM0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUM1QixDQUFDLEdBQUcsRUFBRSxDQUFDO0tBQ1I7SUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQzVCLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDUjtJQUVELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2xDLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDUjtJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ2xDLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDUjtJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO1FBQ2xDLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDUjtJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO1FBQ2xDLENBQUMsR0FBRyxFQUFFLENBQUM7S0FDUjtJQUNELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDbkMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDbEMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDbEMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUNSO0lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNuQyxDQUFDLEdBQUcsRUFBRSxDQUFDO0tBQ1I7SUFFRCxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUMifQ==
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ModCallback } from "isaac-typescript-definitions";
|
|
2
|
+
import { musicManager } from "../cachedClasses";
|
|
3
|
+
import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
|
|
4
|
+
import { stopAllSoundEffects } from "../functions/sound";
|
|
5
|
+
import { saveDataManager } from "./saveDataManager/exports";
|
|
6
|
+
const FEATURE_NAME = "disableAllSound";
|
|
7
|
+
let musicWasEnabled = false;
|
|
8
|
+
const v = {
|
|
9
|
+
run: {
|
|
10
|
+
disableSoundSet: new Set(),
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
/** @internal */
|
|
14
|
+
export function disableAllSoundInit(mod) {
|
|
15
|
+
saveDataManager(FEATURE_NAME, v);
|
|
16
|
+
mod.AddCallback(ModCallback.POST_RENDER, postRender);
|
|
17
|
+
}
|
|
18
|
+
// ModCallback.POST_RENDER (2)
|
|
19
|
+
function postRender() {
|
|
20
|
+
if (v.run.disableSoundSet.size === 0) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
stopAllSoundEffects();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Helper function to stop muting all sound effects and music.
|
|
27
|
+
*
|
|
28
|
+
* Use this function to set things back to normal after having used `disableAllSounds`.
|
|
29
|
+
*
|
|
30
|
+
* @param key The name of the mod feature that is requesting the enable/disable. This is needed so
|
|
31
|
+
* that multiple mod features can work in tandem.
|
|
32
|
+
*/
|
|
33
|
+
export function enableAllSound(key) {
|
|
34
|
+
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
35
|
+
if (!v.run.disableSoundSet.has(key)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
v.run.disableSoundSet.delete(key);
|
|
39
|
+
if (v.run.disableSoundSet.size === 0 && musicWasEnabled) {
|
|
40
|
+
musicManager.Enable();
|
|
41
|
+
}
|
|
42
|
+
// Stop all sound effects that were initialized prior to enabling sounds (in case there was a
|
|
43
|
+
// sound played played previously on this render frame).
|
|
44
|
+
stopAllSoundEffects();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Helper function to disable all sound effects and music (by constantly musting them).
|
|
48
|
+
*
|
|
49
|
+
* Use the `enableAllSounds` helper function to set things back to normal.
|
|
50
|
+
*
|
|
51
|
+
* @param key The name of the mod feature that is requesting the enable/disable. This is needed so
|
|
52
|
+
* that multiple mod features can work in tandem.
|
|
53
|
+
*/
|
|
54
|
+
export function disableAllSound(key) {
|
|
55
|
+
errorIfFeaturesNotInitialized(FEATURE_NAME);
|
|
56
|
+
if (v.run.disableSoundSet.size === 0) {
|
|
57
|
+
musicWasEnabled = musicManager.IsEnabled();
|
|
58
|
+
}
|
|
59
|
+
v.run.disableSoundSet.add(key);
|
|
60
|
+
// Stop all sound effects that were initialized prior to disabling sounds.
|
|
61
|
+
stopAllSoundEffects();
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzYWJsZUFsbFNvdW5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy9kaXNhYmxlQWxsU291bmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFNUQsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUM7QUFFdkMsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO0FBRTVCLE1BQU0sQ0FBQyxHQUFHO0lBQ1IsR0FBRyxFQUFFO1FBQ0gsZUFBZSxFQUFFLElBQUksR0FBRyxFQUFVO0tBQ25DO0NBQ0YsQ0FBQztBQUVGLGdCQUFnQjtBQUNoQixNQUFNLFVBQVUsbUJBQW1CLENBQUMsR0FBUTtJQUMxQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRWpDLEdBQUcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztBQUN2RCxDQUFDO0FBRUQsOEJBQThCO0FBQzlCLFNBQVMsVUFBVTtJQUNqQixJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksS0FBSyxDQUFDLEVBQUU7UUFDcEMsT0FBTztLQUNSO0lBRUQsbUJBQW1CLEVBQUUsQ0FBQztBQUN4QixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsR0FBVztJQUN4Qyw2QkFBNkIsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUU1QyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ25DLE9BQU87S0FDUjtJQUNELENBQUMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUVsQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksS0FBSyxDQUFDLElBQUksZUFBZSxFQUFFO1FBQ3ZELFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztLQUN2QjtJQUVELDZGQUE2RjtJQUM3Rix3REFBd0Q7SUFDeEQsbUJBQW1CLEVBQUUsQ0FBQztBQUN4QixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsR0FBVztJQUN6Qyw2QkFBNkIsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUU1QyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksS0FBSyxDQUFDLEVBQUU7UUFDcEMsZUFBZSxHQUFHLFlBQVksQ0FBQyxTQUFTLEVBQUUsQ0FBQztLQUM1QztJQUVELENBQUMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUUvQiwwRUFBMEU7SUFDMUUsbUJBQW1CLEVBQUUsQ0FBQztBQUN4QixDQUFDIn0=
|