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,191 @@
|
|
|
1
|
+
// This file handles drawing the walls and floors for custom stages.
|
|
2
|
+
// cspell:ignore LTRX,LTLX,LBRX,LBLX
|
|
3
|
+
import { EffectVariant, EntityFlag, RoomShape, RoomType, } from "isaac-typescript-definitions";
|
|
4
|
+
import { game } from "../../cachedClasses";
|
|
5
|
+
import { VectorZero } from "../../constants";
|
|
6
|
+
import { getRandomArrayElement } from "../../functions/array";
|
|
7
|
+
import { spawnEffectWithSeed } from "../../functions/entitySpecific";
|
|
8
|
+
import { newRNG } from "../../functions/rng";
|
|
9
|
+
import { isLRoom, isNarrowRoom } from "../../functions/roomShape";
|
|
10
|
+
import { trimPrefix } from "../../functions/string";
|
|
11
|
+
import { erange, irange } from "../../functions/utils";
|
|
12
|
+
import { ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH } from "./customStageConstants";
|
|
13
|
+
var BackdropKind;
|
|
14
|
+
(function (BackdropKind) {
|
|
15
|
+
/** The "N" stands for narrow rooms. */
|
|
16
|
+
BackdropKind["N_FLOOR"] = "nFloors";
|
|
17
|
+
/** The "L" stands for L rooms. */
|
|
18
|
+
BackdropKind["L_FLOOR"] = "lFloors";
|
|
19
|
+
BackdropKind["WALL"] = "walls";
|
|
20
|
+
BackdropKind["CORNER"] = "corners";
|
|
21
|
+
})(BackdropKind || (BackdropKind = {}));
|
|
22
|
+
/** This is created by the vanilla Basement files. */
|
|
23
|
+
const DEFAULT_BACKDROP = {
|
|
24
|
+
nFloors: [`${ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH}/backdrop/nfloor.png`],
|
|
25
|
+
lFloors: [`${ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH}/backdrop/lfloor.png`],
|
|
26
|
+
walls: [`${ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH}/backdrop/wall.png`],
|
|
27
|
+
corners: [`${ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH}/backdrop/corner.png`],
|
|
28
|
+
};
|
|
29
|
+
const ROOM_SHAPE_WALL_ANM2_LAYERS = {
|
|
30
|
+
[RoomShape.SHAPE_1x1]: 44,
|
|
31
|
+
[RoomShape.IH]: 36,
|
|
32
|
+
[RoomShape.IV]: 28,
|
|
33
|
+
[RoomShape.SHAPE_1x2]: 58,
|
|
34
|
+
[RoomShape.IIV]: 42,
|
|
35
|
+
[RoomShape.SHAPE_2x1]: 63,
|
|
36
|
+
[RoomShape.IIH]: 62,
|
|
37
|
+
[RoomShape.SHAPE_2x2]: 63,
|
|
38
|
+
[RoomShape.LTL]: 63,
|
|
39
|
+
[RoomShape.LTR]: 63,
|
|
40
|
+
[RoomShape.LBL]: 63,
|
|
41
|
+
[RoomShape.LBR]: 63, // 12
|
|
42
|
+
};
|
|
43
|
+
const ROOM_SHAPE_WALL_EXTRA_ANM2_LAYERS = {
|
|
44
|
+
[RoomShape.SHAPE_2x1]: 7,
|
|
45
|
+
[RoomShape.SHAPE_2x2]: 21,
|
|
46
|
+
[RoomShape.LTL]: 19,
|
|
47
|
+
[RoomShape.LTR]: 19,
|
|
48
|
+
[RoomShape.LBL]: 19,
|
|
49
|
+
[RoomShape.LBR]: 19, // 12
|
|
50
|
+
};
|
|
51
|
+
const WALL_OFFSET = Vector(-80, -80);
|
|
52
|
+
/** This corresponds to "floor-backdrop.anm2". */
|
|
53
|
+
const L_FLOOR_ANM2_LAYERS = [16, 17];
|
|
54
|
+
/** This corresponds to "floor-backdrop.anm2". */
|
|
55
|
+
const N_FLOOR_ANM2_LAYERS = [18, 19];
|
|
56
|
+
/**
|
|
57
|
+
* Normally, we would make a custom entity to represent a backdrop effect, but we don't want to
|
|
58
|
+
* interfere with the "entities2.xml" file in end-user mods. Thus, we must select a vanilla effect
|
|
59
|
+
* to masquerade as a backdrop effect.
|
|
60
|
+
*
|
|
61
|
+
* We arbitrarily choose a ladder for this purpose because it will not automatically despawn after
|
|
62
|
+
* time passes, like most other effects.
|
|
63
|
+
*/
|
|
64
|
+
const BACKDROP_EFFECT_VARIANT = EffectVariant.LADDER;
|
|
65
|
+
const BACKDROP_ROOM_TYPE_SET = new Set([
|
|
66
|
+
RoomType.DEFAULT,
|
|
67
|
+
RoomType.BOSS,
|
|
68
|
+
RoomType.MINI_BOSS,
|
|
69
|
+
]);
|
|
70
|
+
export function setBackdrop(customStage) {
|
|
71
|
+
const room = game.GetRoom();
|
|
72
|
+
const roomType = room.GetType();
|
|
73
|
+
const decorationSeed = room.GetDecorationSeed();
|
|
74
|
+
const rng = newRNG(decorationSeed);
|
|
75
|
+
// We do not want to set the backdrop inside shops, Curse Rooms, and so on.
|
|
76
|
+
if (!BACKDROP_ROOM_TYPE_SET.has(roomType)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
spawnWallEntity(customStage, rng, false);
|
|
80
|
+
spawnSecondWallEntity(customStage, rng);
|
|
81
|
+
spawnFloorEntity(customStage, rng);
|
|
82
|
+
}
|
|
83
|
+
function getBackdropPNGPath(customStage, backdropKind, rng) {
|
|
84
|
+
const backdrop = customStage.backdropPNGPaths === undefined
|
|
85
|
+
? DEFAULT_BACKDROP
|
|
86
|
+
: customStage.backdropPNGPaths;
|
|
87
|
+
const pathArray = backdrop[backdropKind];
|
|
88
|
+
return getRandomArrayElement(pathArray, rng);
|
|
89
|
+
}
|
|
90
|
+
function spawnWallEntity(customStage, rng, isExtraWall) {
|
|
91
|
+
const room = game.GetRoom();
|
|
92
|
+
const roomShape = room.GetRoomShape();
|
|
93
|
+
// We spawn an effect instead of simply rendering a static sprite in order to emulate how vanilla
|
|
94
|
+
// does this. (`EntityFlag.RENDER_WALL` is intended for this purpose.)
|
|
95
|
+
const wallEffect = spawnEffectWithSeed(BACKDROP_EFFECT_VARIANT, 0, VectorZero, 1);
|
|
96
|
+
wallEffect.AddEntityFlags(EntityFlag.RENDER_WALL);
|
|
97
|
+
const sprite = wallEffect.GetSprite();
|
|
98
|
+
sprite.Load(`${ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH}/wall-backdrop.anm2`, false);
|
|
99
|
+
const wallLayersArray = isExtraWall
|
|
100
|
+
? ROOM_SHAPE_WALL_EXTRA_ANM2_LAYERS
|
|
101
|
+
: ROOM_SHAPE_WALL_ANM2_LAYERS;
|
|
102
|
+
const numWallLayers = wallLayersArray[roomShape];
|
|
103
|
+
if (numWallLayers === undefined) {
|
|
104
|
+
error(`Failed to get the layers when creating the backdrop for custom stage: ${customStage.name}`);
|
|
105
|
+
}
|
|
106
|
+
if (isLRoom(roomShape)) {
|
|
107
|
+
const cornerPNGPath = getBackdropPNGPath(customStage, BackdropKind.CORNER, rng);
|
|
108
|
+
sprite.ReplaceSpritesheet(0, cornerPNGPath);
|
|
109
|
+
}
|
|
110
|
+
for (const layerID of irange(1, numWallLayers)) {
|
|
111
|
+
const wallPNGPath = getBackdropPNGPath(customStage, BackdropKind.WALL, rng);
|
|
112
|
+
sprite.ReplaceSpritesheet(layerID, wallPNGPath);
|
|
113
|
+
}
|
|
114
|
+
const topLeftPos = room.GetTopLeftPos();
|
|
115
|
+
const renderPos = topLeftPos.add(WALL_OFFSET);
|
|
116
|
+
const modifiedOffset = renderPos.div(40).mul(26);
|
|
117
|
+
wallEffect.SpriteOffset = modifiedOffset;
|
|
118
|
+
sprite.LoadGraphics();
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
120
|
+
const roomShapeName = RoomShape[roomShape];
|
|
121
|
+
const animation = trimPrefix(roomShapeName, "SHAPE_");
|
|
122
|
+
const modifiedAnimation = isExtraWall ? `${animation}X` : animation;
|
|
123
|
+
sprite.Play(modifiedAnimation, true);
|
|
124
|
+
}
|
|
125
|
+
function spawnSecondWallEntity(customStage, rng) {
|
|
126
|
+
const room = game.GetRoom();
|
|
127
|
+
const roomShape = room.GetRoomShape();
|
|
128
|
+
const extraLayers = ROOM_SHAPE_WALL_EXTRA_ANM2_LAYERS[roomShape];
|
|
129
|
+
const roomShapeHasExtraLayers = extraLayers !== undefined;
|
|
130
|
+
if (roomShapeHasExtraLayers) {
|
|
131
|
+
spawnWallEntity(customStage, rng, true);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function spawnFloorEntity(customStage, rng) {
|
|
135
|
+
const room = game.GetRoom();
|
|
136
|
+
const roomShape = room.GetRoomShape();
|
|
137
|
+
// We spawn an effect instead of simply rendering a static sprite in order to emulate how vanilla
|
|
138
|
+
// does this. (`EntityFlag.RENDER_FLOOR` is intended for this purpose.)
|
|
139
|
+
const floorEffect = spawnEffectWithSeed(BACKDROP_EFFECT_VARIANT, 0, VectorZero, 1);
|
|
140
|
+
floorEffect.AddEntityFlags(EntityFlag.RENDER_FLOOR);
|
|
141
|
+
const sprite = floorEffect.GetSprite();
|
|
142
|
+
sprite.Load(`${ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH}/floor-backdrop.anm2`, false);
|
|
143
|
+
const numFloorLayers = getNumFloorLayers(roomShape);
|
|
144
|
+
if (numFloorLayers !== undefined) {
|
|
145
|
+
for (const layerID of erange(0, numFloorLayers)) {
|
|
146
|
+
// The wall spritesheet is used for the "normal" floors.
|
|
147
|
+
const wallPNGPath = getBackdropPNGPath(customStage, BackdropKind.WALL, rng);
|
|
148
|
+
sprite.ReplaceSpritesheet(layerID, wallPNGPath);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else if (isLRoom(roomShape)) {
|
|
152
|
+
for (const layerID of L_FLOOR_ANM2_LAYERS) {
|
|
153
|
+
const LFloorPNGPath = getBackdropPNGPath(customStage, BackdropKind.L_FLOOR, rng);
|
|
154
|
+
sprite.ReplaceSpritesheet(layerID, LFloorPNGPath);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else if (isNarrowRoom(roomShape)) {
|
|
158
|
+
for (const layerID of N_FLOOR_ANM2_LAYERS) {
|
|
159
|
+
const NFloorPNGPath = getBackdropPNGPath(customStage, BackdropKind.N_FLOOR, rng);
|
|
160
|
+
sprite.ReplaceSpritesheet(layerID, NFloorPNGPath);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const topLeftPos = room.GetTopLeftPos();
|
|
164
|
+
const renderPos = topLeftPos;
|
|
165
|
+
const modifiedOffset = renderPos.div(40).mul(26); // The magic numbers are copied from StageAPI.
|
|
166
|
+
floorEffect.SpriteOffset = modifiedOffset;
|
|
167
|
+
sprite.LoadGraphics();
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
169
|
+
const roomShapeName = RoomShape[roomShape];
|
|
170
|
+
const animation = trimPrefix(roomShapeName, "SHAPE_");
|
|
171
|
+
sprite.Play(animation, true);
|
|
172
|
+
}
|
|
173
|
+
function getNumFloorLayers(roomShape) {
|
|
174
|
+
switch (roomShape) {
|
|
175
|
+
case RoomShape.SHAPE_1x1: {
|
|
176
|
+
return 4;
|
|
177
|
+
}
|
|
178
|
+
case RoomShape.SHAPE_1x2:
|
|
179
|
+
case RoomShape.SHAPE_2x1: {
|
|
180
|
+
return 8;
|
|
181
|
+
}
|
|
182
|
+
case RoomShape.SHAPE_2x2: {
|
|
183
|
+
return 16;
|
|
184
|
+
}
|
|
185
|
+
default: {
|
|
186
|
+
// We have explicit logic elsewhere to handle narrow rooms and L rooms.
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2Ryb3AuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9pc2FhY3NjcmlwdC1jb21tb24vc3JjL2ZlYXR1cmVzL2N1c3RvbVN0YWdlL2JhY2tkcm9wLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9FQUFvRTtBQUVwRSxvQ0FBb0M7QUFFcEMsT0FBTyxFQUNMLGFBQWEsRUFDYixVQUFVLEVBQ1YsU0FBUyxFQUNULFFBQVEsR0FDVCxNQUFNLDhCQUE4QixDQUFDO0FBQ3RDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDN0MsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDOUQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDckUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFdkQsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFM0UsSUFBSyxZQVNKO0FBVEQsV0FBSyxZQUFZO0lBQ2YsdUNBQXVDO0lBQ3ZDLG1DQUFtQixDQUFBO0lBRW5CLGtDQUFrQztJQUNsQyxtQ0FBbUIsQ0FBQTtJQUVuQiw4QkFBYyxDQUFBO0lBQ2Qsa0NBQWtCLENBQUE7QUFDcEIsQ0FBQyxFQVRJLFlBQVksS0FBWixZQUFZLFFBU2hCO0FBRUQscURBQXFEO0FBQ3JELE1BQU0sZ0JBQWdCLEdBQWlEO0lBQ3JFLE9BQU8sRUFBRSxDQUFDLEdB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
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export const ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH = "gfx/isaacscript-custom-stage";
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tU3RhZ2VDb25zdGFudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9pc2FhY3NjcmlwdC1jb21tb24vc3JjL2ZlYXR1cmVzL2N1c3RvbVN0YWdlL2N1c3RvbVN0YWdlQ29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFHLDhCQUE4QixDQUFDIn0=
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Direction, GridRoom, LevelStage, RoomShape, RoomTransitionAnim, RoomType, StageType, } from "isaac-typescript-definitions";
|
|
2
|
+
import { game } from "../../cachedClasses";
|
|
3
|
+
import { reorderedCallbacksSetStage } from "../../callbacks/reorderedCallbacks";
|
|
4
|
+
import { getEntityIDFromConstituents } from "../../functions/entity";
|
|
5
|
+
import { log, logError } from "../../functions/log";
|
|
6
|
+
import { movePlayersToCenter } from "../../functions/playerCenter";
|
|
7
|
+
import { newRNG } from "../../functions/rng";
|
|
8
|
+
import { getRoomData } from "../../functions/roomData";
|
|
9
|
+
import { getRooms } from "../../functions/rooms";
|
|
10
|
+
import { getGotoCommand, setStage } from "../../functions/stage";
|
|
11
|
+
import { runNextRoom } from "../runNextRoom";
|
|
12
|
+
import { getRandomCustomStageRoom } from "./util";
|
|
13
|
+
import v, { customBossPNGPaths, customStageCachedRoomData, customStagesMap, } from "./v";
|
|
14
|
+
import { playVersusScreenAnimation } from "./versusScreen";
|
|
15
|
+
const DEFAULT_BASE_STAGE = LevelStage.BASEMENT_2;
|
|
16
|
+
const DEFAULT_BASE_STAGE_TYPE = StageType.ORIGINAL;
|
|
17
|
+
/**
|
|
18
|
+
* Helper function to warp to a custom stage/level.
|
|
19
|
+
*
|
|
20
|
+
* Custom stages/levels must first be defined in the "tsconfig.json" file. See the documentation for
|
|
21
|
+
* more details: https://isaacscript.github.io/main/custom-stages/
|
|
22
|
+
*/
|
|
23
|
+
export function setCustomStage(name, verbose = false) {
|
|
24
|
+
const customStage = customStagesMap.get(name);
|
|
25
|
+
if (customStage === undefined) {
|
|
26
|
+
error(`Failed to set the custom stage of "${name}" because it was not found in the custom stages map. (This means that you probably forgot to define it in your "tsconfig.json" file.) See the website for more details on how to set up custom stages.`);
|
|
27
|
+
}
|
|
28
|
+
const level = game.GetLevel();
|
|
29
|
+
const startingRoomGridIndex = level.GetStartingRoomIndex();
|
|
30
|
+
const seeds = game.GetSeeds();
|
|
31
|
+
const startSeed = seeds.GetStartSeed();
|
|
32
|
+
const rng = newRNG(startSeed);
|
|
33
|
+
v.run.currentCustomStage = customStage;
|
|
34
|
+
const baseStage = customStage.baseStage === undefined
|
|
35
|
+
? DEFAULT_BASE_STAGE
|
|
36
|
+
: customStage.baseStage;
|
|
37
|
+
const baseStageType = customStage.baseStageType === undefined
|
|
38
|
+
? DEFAULT_BASE_STAGE_TYPE
|
|
39
|
+
: customStage.baseStageType;
|
|
40
|
+
setStage(baseStage, baseStageType);
|
|
41
|
+
// Now, we need to pick a custom room for each vanilla room.
|
|
42
|
+
for (const room of getRooms()) {
|
|
43
|
+
// The starting floor of each room should stay empty.
|
|
44
|
+
if (room.SafeGridIndex === startingRoomGridIndex) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (room.Data === undefined) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const roomType = room.Data.Type;
|
|
51
|
+
const roomShapeMap = customStage.roomTypeMap.get(roomType);
|
|
52
|
+
if (roomShapeMap === undefined) {
|
|
53
|
+
// Only show errors for non-default room types. (By default, we won't replace shops and other
|
|
54
|
+
// special rooms.)
|
|
55
|
+
if (roomType === RoomType.DEFAULT) {
|
|
56
|
+
logError(`Failed to find any custom rooms for RoomType.${RoomType[roomType]} (${roomType}) for custom stage: ${name}`);
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const roomShape = room.Data.Shape;
|
|
61
|
+
const roomDoorSlotFlagMap = roomShapeMap.get(roomShape);
|
|
62
|
+
if (roomDoorSlotFlagMap === undefined) {
|
|
63
|
+
logError(`Failed to find any custom rooms for RoomType.${RoomType[roomType]} (${roomType}) + RoomShape.${RoomShape[roomShape]} (${roomShape}) for custom stage: ${name}`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const doorSlotFlags = room.Data.Doors;
|
|
67
|
+
const roomsMetadata = roomDoorSlotFlagMap.get(doorSlotFlags);
|
|
68
|
+
if (roomsMetadata === undefined) {
|
|
69
|
+
logError(`Failed to find any custom rooms for RoomType.${RoomType[roomType]} (${roomType}) + RoomShape.${RoomShape[roomShape]} (${roomShape}) + DoorSlotFlags ${doorSlotFlags} for custom stage: ${name}`);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const randomRoom = getRandomCustomStageRoom(roomsMetadata, rng, verbose);
|
|
73
|
+
let newRoomData = customStageCachedRoomData.get(randomRoom.variant);
|
|
74
|
+
if (newRoomData === undefined) {
|
|
75
|
+
// We need the room data for this room. We can leverage the "goto" console command to load it
|
|
76
|
+
// into the "debug" slot. This is convenient because we do not actually have to travel to the
|
|
77
|
+
// room.
|
|
78
|
+
const command = getGotoCommand(roomType, randomRoom.variant);
|
|
79
|
+
Isaac.ExecuteCommand(command);
|
|
80
|
+
newRoomData = getRoomData(GridRoom.DEBUG);
|
|
81
|
+
if (newRoomData === undefined) {
|
|
82
|
+
logError(`Failed to get the room data for room variant ${randomRoom.variant} for custom stage: ${name}`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
customStageCachedRoomData.set(randomRoom.variant, newRoomData);
|
|
86
|
+
}
|
|
87
|
+
room.Data = newRoomData;
|
|
88
|
+
}
|
|
89
|
+
// Set the stage to an invalid value, which will prevent the walls and floors from loading. We
|
|
90
|
+
// must use `StageType.WRATH_OF_THE_LAMB` instead of `StageType.ORIGINAL` or else the walls will
|
|
91
|
+
// not render properly. DeadInfinity suspects that this might be because it is trying to use the
|
|
92
|
+
// Dark Room's backdrop (instead of The Chest).
|
|
93
|
+
const stage = -1;
|
|
94
|
+
const stageType = StageType.WRATH_OF_THE_LAMB;
|
|
95
|
+
level.SetStage(stage, stageType);
|
|
96
|
+
reorderedCallbacksSetStage(stage, stageType);
|
|
97
|
+
// We must reload the current room in order for the `Level.SetStage` method to take effect.
|
|
98
|
+
// Furthermore, we need to cancel the queued warp to the `GridRoom.DEBUG` room. We can accomplish
|
|
99
|
+
// both of these things by initiating a room transition to the starting room of the floor. (We
|
|
100
|
+
// assume that since we just warped to a new floor, we are already in the starting room.)
|
|
101
|
+
game.StartRoomTransition(startingRoomGridIndex, Direction.NO_DIRECTION, RoomTransitionAnim.FADE);
|
|
102
|
+
// We do more setup once the room is reloaded from the transition.
|
|
103
|
+
runNextRoom(postRoomTransition);
|
|
104
|
+
}
|
|
105
|
+
function postRoomTransition() {
|
|
106
|
+
// After the room transition, the players will be placed next to a door, but they should be in the
|
|
107
|
+
// center of the room to emulate what happens on a vanilla stage.
|
|
108
|
+
movePlayersToCenter();
|
|
109
|
+
}
|
|
110
|
+
export function setCustomStageDebug() {
|
|
111
|
+
const customStage = v.run.currentCustomStage;
|
|
112
|
+
if (customStage === null) {
|
|
113
|
+
log("No custom stage is currently loaded.");
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
playVersusScreenAnimation(customStage, true);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* By default, unknown bosses will be drawn on the boss "versus" screen as "???". If your custom
|
|
120
|
+
* stage has custom bosses, you can use this function to register the corresponding graphic file
|
|
121
|
+
* files for them.
|
|
122
|
+
*
|
|
123
|
+
* For reference:
|
|
124
|
+
* - The vanilla name sprite for Monstro is located at "C:\Program Files
|
|
125
|
+
* (x86)\Steam\steamapps\common\The Binding of Isaac
|
|
126
|
+
* Rebirth\resources\gfx\ui\boss\bossname_20.0_monstro.png".
|
|
127
|
+
* - The vanilla portrait sprite for Monstro is located at "C:\Program Files
|
|
128
|
+
* (x86)\Steam\steamapps\common\The Binding of Isaac
|
|
129
|
+
* Rebirth\resources\gfx\ui\boss\portrait_20.0_monstro.png".
|
|
130
|
+
*
|
|
131
|
+
* (Note that boss metadata like this cannot be specified with the rest of the custom stage metadata
|
|
132
|
+
* in the "tsconfig.json" file because there is not a way to retrieve the name of an entity at
|
|
133
|
+
* run-time.)
|
|
134
|
+
*
|
|
135
|
+
* @param entityType The entity type of the custom boss.
|
|
136
|
+
* @param variant The variant of the custom boss.
|
|
137
|
+
* @param subType The sub-type of the custom boss.
|
|
138
|
+
* @param namePNGPath The full path to the PNG file that contains the name of the boss that will be
|
|
139
|
+
* displayed on the top of the boss "versus" screen.
|
|
140
|
+
* @param portraitPNGPath The full path to the PNG file that contains the portrait of the boss that
|
|
141
|
+
* will be displayed on the right side of the boss "versus" screen.
|
|
142
|
+
*/
|
|
143
|
+
export function registerCustomBoss(entityType, variant, subType, namePNGPath, portraitPNGPath) {
|
|
144
|
+
const entityID = getEntityIDFromConstituents(entityType, variant, subType);
|
|
145
|
+
customBossPNGPaths.set(entityID, [namePNGPath, portraitPNGPath]);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwb3J0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2lzYWFjc2NyaXB0LWNvbW1vbi9zcmMvZmVhdHVyZXMvY3VzdG9tU3RhZ2UvZXhwb3J0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULFFBQVEsRUFDUixVQUFVLEVBQ1YsU0FBUyxFQUNULGtCQUFrQixFQUNsQixRQUFRLEVBQ1IsU0FBUyxHQUNWLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzNDLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbkUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2xELE9BQU8sQ0FBQyxFQUFFLEVBQ1Isa0JBQWtCLEVBQ2xCLHlCQUF5QixFQUN6QixlQUFlLEdBQ2hCLE1BQU0sS0FBSyxDQUFDO0FBQ2IsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0QsTUFB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
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { CollectibleType, EntityType, TrinketType, } from "isaac-typescript-definitions";
|
|
2
|
+
import { DecorationVariant } from "../../enums/DecorationVariant";
|
|
3
|
+
import { removeEntities } from "../../functions/entity";
|
|
4
|
+
import { getNPCs } from "../../functions/entitySpecific";
|
|
5
|
+
import { getCoins, getCollectibles, getTrinkets, } from "../../functions/pickups";
|
|
6
|
+
import { vectorEquals } from "../../functions/vector";
|
|
7
|
+
/** For `GridEntityType.DECORATION` (1) */
|
|
8
|
+
export function setCustomDecorationGraphics(customStage, gridEntity) {
|
|
9
|
+
// If the end-user did not specify custom decoration graphics, default to Basement graphics. (We
|
|
10
|
+
// don't have to adjust anything for this case.)
|
|
11
|
+
if (customStage.decorationsPNGPath === undefined) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// Ignore custom grid entities. (They are represented as decorations with a non-zero variant.)
|
|
15
|
+
const variant = gridEntity.GetVariant();
|
|
16
|
+
if (variant !== DecorationVariant.VANILLA_DECORATION) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const sprite = gridEntity.GetSprite();
|
|
20
|
+
const fileName = sprite.GetFilename();
|
|
21
|
+
// On Windows, this is: gfx/grid/Props_01_Basement.anm2
|
|
22
|
+
if (fileName.toLowerCase() === "gfx/grid/props_01_basement.anm2") {
|
|
23
|
+
sprite.ReplaceSpritesheet(0, customStage.decorationsPNGPath);
|
|
24
|
+
sprite.LoadGraphics();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** For `GridEntityType.ROCK` (2) */
|
|
28
|
+
export function setCustomRockGraphics(customStage, gridEntity) {
|
|
29
|
+
// If the end-user did not specify custom rock graphics, default to Basement graphics. (We don't
|
|
30
|
+
// have to adjust anything for this case.)
|
|
31
|
+
if (customStage.rocksPNGPath === undefined) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const sprite = gridEntity.GetSprite();
|
|
35
|
+
const fileName = sprite.GetFilename();
|
|
36
|
+
if (fileName === "gfx/grid/grid_rock.anm2") {
|
|
37
|
+
sprite.ReplaceSpritesheet(0, customStage.rocksPNGPath);
|
|
38
|
+
sprite.LoadGraphics();
|
|
39
|
+
}
|
|
40
|
+
else if (fileName === "gfx/grid/grid_pit.anm2") {
|
|
41
|
+
sprite.ReplaceSpritesheet(1, customStage.rocksPNGPath);
|
|
42
|
+
sprite.LoadGraphics();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** For `GridEntityType.PIT` (7) */
|
|
46
|
+
export function setCustomPitGraphics(customStage, gridEntity) {
|
|
47
|
+
// If the end-user did not specify custom pit graphics, default to Basement graphics. (We don't
|
|
48
|
+
// have to adjust anything for this case.)
|
|
49
|
+
if (customStage.pitsPNGPath === undefined) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const sprite = gridEntity.GetSprite();
|
|
53
|
+
const fileName = sprite.GetFilename();
|
|
54
|
+
if (fileName === "gfx/grid/grid_pit.anm2") {
|
|
55
|
+
sprite.ReplaceSpritesheet(0, customStage.pitsPNGPath);
|
|
56
|
+
sprite.LoadGraphics();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** For GridEntityType.DOOR (16) */
|
|
60
|
+
export function setCustomDoorGraphics(customStage, gridEntity) {
|
|
61
|
+
const sprite = gridEntity.GetSprite();
|
|
62
|
+
const fileName = sprite.GetFilename();
|
|
63
|
+
const doorPNGPath = getNewDoorPNGPath(customStage, fileName);
|
|
64
|
+
if (doorPNGPath !== undefined) {
|
|
65
|
+
sprite.ReplaceSpritesheet(0, doorPNGPath);
|
|
66
|
+
sprite.LoadGraphics();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function getNewDoorPNGPath(customStage, fileName) {
|
|
70
|
+
switch (fileName) {
|
|
71
|
+
case "gfx/grid/door_01_normaldoor.anm2": {
|
|
72
|
+
return customStage.doorPNGPaths?.normal;
|
|
73
|
+
}
|
|
74
|
+
case "gfx/grid/door_02_treasureroomdoor.anm2": {
|
|
75
|
+
return customStage.doorPNGPaths?.treasureRoom;
|
|
76
|
+
}
|
|
77
|
+
case "gfx/grid/door_03_ambushroomdoor.anm2": {
|
|
78
|
+
return customStage.doorPNGPaths?.normalChallengeRoom;
|
|
79
|
+
}
|
|
80
|
+
case "gfx/grid/door_04_selfsacrificeroomdoor.anm2": {
|
|
81
|
+
return customStage.doorPNGPaths?.curseRoom;
|
|
82
|
+
}
|
|
83
|
+
case "gfx/grid/door_05_arcaderoomdoor.anm2": {
|
|
84
|
+
return customStage.doorPNGPaths?.arcade;
|
|
85
|
+
}
|
|
86
|
+
case "gfx/grid/door_07_devilroomdoor.anm2": {
|
|
87
|
+
return customStage.doorPNGPaths?.devilRoom;
|
|
88
|
+
}
|
|
89
|
+
case "gfx/grid/door_07_holyroomdoor.anm2": {
|
|
90
|
+
return customStage.doorPNGPaths?.angelRoom;
|
|
91
|
+
}
|
|
92
|
+
case "gfx/grid/door_08_holeinwall.anm2": {
|
|
93
|
+
return customStage.doorPNGPaths?.secretRoom;
|
|
94
|
+
}
|
|
95
|
+
case "gfx/grid/door_09_bossambushroomdoor.anm2": {
|
|
96
|
+
return customStage.doorPNGPaths?.bossChallengeRoom;
|
|
97
|
+
}
|
|
98
|
+
case "gfx/grid/door_10_bossroomdoor.anm2": {
|
|
99
|
+
return customStage.doorPNGPaths?.bossRoom;
|
|
100
|
+
}
|
|
101
|
+
case "gfx/grid/door_15_bossrushdoor.anm2": {
|
|
102
|
+
return customStage.doorPNGPaths?.bossRush;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The rewards are based on the ones from the wiki:
|
|
109
|
+
* https://bindingofisaacrebirth.fandom.com/wiki/Rocks#Urns
|
|
110
|
+
*
|
|
111
|
+
* On the bugged stage of -1, only urns will spawn, so we do not have to handle the case of mushroom
|
|
112
|
+
* rewards, skull rewards, and so on.
|
|
113
|
+
*/
|
|
114
|
+
export function removeUrnRewards(customStage, gridEntity) {
|
|
115
|
+
// Assume that if the end-user does not have custom rock graphics specified, they want to keep the
|
|
116
|
+
// vanilla urn reward functionality.
|
|
117
|
+
if (customStage.rocksPNGPath === undefined) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// Spiders
|
|
121
|
+
const spiders = getNPCs(EntityType.SPIDER);
|
|
122
|
+
removeEntitiesSpawnedFromGridEntity(spiders, gridEntity);
|
|
123
|
+
// Coins
|
|
124
|
+
const coins = getCoins();
|
|
125
|
+
removeEntitiesSpawnedFromGridEntity(coins, gridEntity);
|
|
126
|
+
// A Quarter
|
|
127
|
+
const quarters = getCollectibles(CollectibleType.QUARTER);
|
|
128
|
+
removeEntitiesSpawnedFromGridEntity(quarters, gridEntity);
|
|
129
|
+
// Swallowed Penny
|
|
130
|
+
const swallowedPennies = getTrinkets(TrinketType.SWALLOWED_PENNY);
|
|
131
|
+
removeEntitiesSpawnedFromGridEntity(swallowedPennies, gridEntity);
|
|
132
|
+
}
|
|
133
|
+
function removeEntitiesSpawnedFromGridEntity(entities, gridEntity) {
|
|
134
|
+
const entitiesFromGridEntity = entities.filter((entity) => entity.FrameCount === 0 &&
|
|
135
|
+
vectorEquals(entity.Position, gridEntity.Position));
|
|
136
|
+
removeEntities(entitiesFromGridEntity);
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZEVudGl0aWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy9jdXN0b21TdGFnZS9ncmlkRW50aXRpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGVBQWUsRUFDZixVQUFVLEVBQ1YsV0FBVyxHQUNaLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEVBQ0wsUUFBUSxFQUNSLGVBQWUsRUFDZixXQUFXLEdBQ1osTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHdEQsMENBQTBDO0FBQzFDLE1BQU0sVUFBVSwyQkFBMkIsQ0FDekMsV0FBd0IsRUFDeEIsVUFBc0I7SUFFdEIsZ0dBQWdHO0lBQ2hHLGdEQUFnRDtJQUNoRCxJQUFJLFdBQVcsQ0FBQyxrQkFBa0IsS0FBSyxTQUFTLEVBQUU7UUFDaEQsT0FBTztLQUNSO0lBRUQsOEZBQThGO0lBQzlGLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUN4QyxJQUFJLE9BQU8sS0FBTSxpQkFBaUIsQ0FBQyxrQkFBMEIsRUFBRTtRQUM3RCxPQUFPO0tBQ1I7SUFFRCxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDdEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3RDLHVEQUF1RDtJQUN2RCxJQUFJLFFBQVEsQ0FBQyxXQUFXLEVBQUUsS0FBSyxpQ0FBaUMsRUFBRTtRQUNoRSxNQUFN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
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { GridEntityType, ModCallback, } from "isaac-typescript-definitions";
|
|
2
|
+
import { ModCallbackCustom } from "../../enums/ModCallbackCustom";
|
|
3
|
+
import { isArray } from "../../functions/array";
|
|
4
|
+
import { saveDataManager } from "../saveDataManager/exports";
|
|
5
|
+
import { setBackdrop } from "./backdrop";
|
|
6
|
+
import { removeUrnRewards, setCustomDecorationGraphics, setCustomDoorGraphics, setCustomPitGraphics, setCustomRockGraphics, } from "./gridEntities";
|
|
7
|
+
import * as metadataJSON from "./metadata.json"; // This will correspond to "metadata.lua" at run-time.
|
|
8
|
+
import { setShadows } from "./shadows";
|
|
9
|
+
import { streakTextGetShaderParams, streakTextPostRender } from "./streakText";
|
|
10
|
+
import v, { customStagesMap } from "./v";
|
|
11
|
+
import { playVersusScreenAnimation, versusScreenPostRender, } from "./versusScreen";
|
|
12
|
+
export function customStageInit(mod) {
|
|
13
|
+
saveDataManager("customStage", v);
|
|
14
|
+
initRoomTypeMaps();
|
|
15
|
+
mod.AddCallback(ModCallback.POST_RENDER, postRender); // 2
|
|
16
|
+
mod.AddCallback(ModCallback.GET_SHADER_PARAMS, getShaderParams); // 21
|
|
17
|
+
mod.AddCallbackCustom(ModCallbackCustom.POST_GRID_ENTITY_BROKEN, postGridEntityBrokenRockAlt, GridEntityType.ROCK_ALT);
|
|
18
|
+
mod.AddCallbackCustom(ModCallbackCustom.POST_GRID_ENTITY_INIT, postGridEntityBrokenInit);
|
|
19
|
+
mod.AddCallbackCustom(ModCallbackCustom.POST_NEW_ROOM_REORDERED, postNewRoomReordered);
|
|
20
|
+
}
|
|
21
|
+
function initRoomTypeMaps() {
|
|
22
|
+
if (!isArray(metadataJSON)) {
|
|
23
|
+
error('The IsaacScript standard library attempted to read the custom stage metadata from the "metadata.lua" file, but it was not an array.');
|
|
24
|
+
}
|
|
25
|
+
const customStagesLua = metadataJSON;
|
|
26
|
+
for (const customStageLua of customStagesLua) {
|
|
27
|
+
const roomTypeMap = getRoomTypeMap(customStageLua);
|
|
28
|
+
const customStage = {
|
|
29
|
+
...customStageLua,
|
|
30
|
+
roomTypeMap,
|
|
31
|
+
};
|
|
32
|
+
customStagesMap.set(customStage.name, customStage);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function getRoomTypeMap(customStageLua) {
|
|
36
|
+
const roomTypeMap = new Map();
|
|
37
|
+
for (const roomMetadata of customStageLua.roomsMetadata) {
|
|
38
|
+
const roomType = roomMetadata.type;
|
|
39
|
+
let roomShapeMap = roomTypeMap.get(roomType);
|
|
40
|
+
if (roomShapeMap === undefined) {
|
|
41
|
+
roomShapeMap = new Map();
|
|
42
|
+
roomTypeMap.set(roomType, roomShapeMap);
|
|
43
|
+
}
|
|
44
|
+
const roomShape = roomMetadata.shape;
|
|
45
|
+
let roomDoorSlotFlagMap = roomShapeMap.get(roomShape);
|
|
46
|
+
if (roomDoorSlotFlagMap === undefined) {
|
|
47
|
+
roomDoorSlotFlagMap = new Map();
|
|
48
|
+
roomShapeMap.set(roomShape, roomDoorSlotFlagMap);
|
|
49
|
+
}
|
|
50
|
+
const doorSlotFlags = roomMetadata.doorSlotFlags;
|
|
51
|
+
let rooms = roomDoorSlotFlagMap.get(doorSlotFlags);
|
|
52
|
+
if (rooms === undefined) {
|
|
53
|
+
rooms = [];
|
|
54
|
+
roomDoorSlotFlagMap.set(doorSlotFlags, rooms);
|
|
55
|
+
}
|
|
56
|
+
rooms.push(roomMetadata);
|
|
57
|
+
}
|
|
58
|
+
return roomTypeMap;
|
|
59
|
+
}
|
|
60
|
+
// ModCallback.POST_RENDER (2)
|
|
61
|
+
function postRender() {
|
|
62
|
+
const customStage = v.run.currentCustomStage;
|
|
63
|
+
if (customStage === null) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
streakTextPostRender(customStage);
|
|
67
|
+
versusScreenPostRender();
|
|
68
|
+
}
|
|
69
|
+
// ModCallback.GET_SHADER_PARAMS (22)
|
|
70
|
+
function getShaderParams(shaderName) {
|
|
71
|
+
streakTextGetShaderParams(shaderName);
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
// ModCallbackCustom.POST_GRID_ENTITY_BROKEN
|
|
75
|
+
// GridEntityType.ROCK_ALT
|
|
76
|
+
function postGridEntityBrokenRockAlt(gridEntity) {
|
|
77
|
+
const customStage = v.run.currentCustomStage;
|
|
78
|
+
if (customStage === null) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
removeUrnRewards(customStage, gridEntity);
|
|
82
|
+
}
|
|
83
|
+
// ModCallbackCustom.POST_GRID_ENTITY_INIT
|
|
84
|
+
function postGridEntityBrokenInit(gridEntity) {
|
|
85
|
+
const customStage = v.run.currentCustomStage;
|
|
86
|
+
if (customStage === null) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
setCustomDecorationGraphics(customStage, gridEntity);
|
|
90
|
+
setCustomRockGraphics(customStage, gridEntity);
|
|
91
|
+
setCustomPitGraphics(customStage, gridEntity);
|
|
92
|
+
setCustomDoorGraphics(customStage, gridEntity);
|
|
93
|
+
}
|
|
94
|
+
// ModCallbackCustom.POST_NEW_ROOM_REORDERED
|
|
95
|
+
function postNewRoomReordered() {
|
|
96
|
+
const customStage = v.run.currentCustomStage;
|
|
97
|
+
if (customStage === null) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
setBackdrop(customStage);
|
|
101
|
+
setShadows(customStage);
|
|
102
|
+
playVersusScreenAnimation(customStage);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2lzYWFjc2NyaXB0LWNvbW1vbi9zcmMvZmVhdHVyZXMvY3VzdG9tU3RhZ2UvaW5pdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsY0FBYyxFQUNkLFdBQVcsR0FHWixNQUFNLDhCQUE4QixDQUFDO0FBRXRDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQU1oRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN6QyxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLDJCQUEyQixFQUMzQixxQkFBcUIsRUFDckIsb0JBQW9CLEVBQ3BCLHFCQUFxQixHQUN0QixNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sS0FBSyxZQUFZLE1BQU0saUJBQWlCLENBQUMsQ0FBQyxzREFBc0Q7QUFDdkcsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN2QyxPQUFPLEVBQUUseUJBQXlCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDL0UsT0FBTyxDQUFDLEVBQUUsRUFBRSxlQUFlLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDekMsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixzQkFBc0IsR0FDdkIsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixNQUFNLFVBQVUsZUFBZSxDQUFDLEdBQWdCO0lBQzlDLGVBQWUsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDbEMsZ0JBQWdCLEVBQUUsQ0FBQztJQUVuQixHQUFHLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxJ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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|