UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

251 lines (250 loc) • 12.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addCharge = addCharge; exports.addRoomClearCharge = addRoomClearCharge; exports.addRoomClearChargeToSlot = addRoomClearChargeToSlot; exports.addRoomClearCharges = addRoomClearCharges; exports.getChargesAwayFromMax = getChargesAwayFromMax; exports.getTotalCharge = getTotalCharge; exports.getUsableActiveItemSlots = getUsableActiveItemSlots; exports.isActiveSlotDoubleCharged = isActiveSlotDoubleCharged; exports.playChargeSoundEffect = playChargeSoundEffect; const isaac_typescript_definitions_1 = require("isaac-typescript-definitions"); const cachedClasses_1 = require("../core/cachedClasses"); const collectibles_1 = require("./collectibles"); const playerCollectibles_1 = require("./playerCollectibles"); const playerIndex_1 = require("./playerIndex"); const roomShape_1 = require("./roomShape"); /** * Helper function to add a charge to the player's active item. Will flash the HUD and play the * appropriate sound effect, depending on whether the charge is partially full or completely full. * * If the player's active item is already fully charged, then this function will return 0 and not * flash the HUD or play a sound effect. * * This function will take the following things into account: * - The Battery * - AAA Battery * * @param player The player to grant the charges to. * @param activeSlot Optional. The slot to grant the charges to. Default is `ActiveSlot.PRIMARY`. * @param numCharges Optional. The amount of charges to grant. Default is 1. * @param playSoundEffect Optional. Whether to play a charge-related sound effect. Default is true. * @returns The amount of charges that were actually granted. For example, if the active item was * only one away from a full charge, but the `numCharges` provided to this function was 2, * then this function would return 1. */ function addCharge(player, activeSlot = isaac_typescript_definitions_1.ActiveSlot.PRIMARY, numCharges = 1, playSoundEffect = true) { const hud = cachedClasses_1.game.GetHUD(); // Ensure that there is enough space on the active item to store these amount of charges. (If we // add too many charges, it will grant orange "battery" charges, even if the player does not have // The Battery.) const chargesAwayFromMax = getChargesAwayFromMax(player, activeSlot); const chargesToAdd = Math.min(numCharges, chargesAwayFromMax); // The AAA Battery trinket might grant an additional charge. const modifiedChargesToAdd = getChargesToAddWithAAAModifier(player, activeSlot, chargesToAdd); const totalCharge = getTotalCharge(player, activeSlot); const newCharge = totalCharge + modifiedChargesToAdd; if (newCharge === totalCharge) { return 0; } player.SetActiveCharge(newCharge, activeSlot); hud.FlashChargeBar(player, activeSlot); if (playSoundEffect) { playChargeSoundEffect(player, activeSlot); } return modifiedChargesToAdd; } /** * Helper function to add a charge to a player's active item(s), emulating what happens when a room * is cleared. * * This function will take the following things into account: * - 2x2 rooms and L rooms granting a double charge * - The Battery * - AAA Battery * - Not charging active items with `chargetype="special"` * * @param player The player to grant the charges to. * @param bigRoomDoubleCharge Optional. If set to false, it will treat the current room as a 1x1 * room for the purposes of calculating how much charge to grant. Default * is true. * @param playSoundEffect Optional. Whether to play a charge-related sound effect. Default is true. */ function addRoomClearCharge(player, bigRoomDoubleCharge = true, playSoundEffect = true) { for (const activeSlot of [ isaac_typescript_definitions_1.ActiveSlot.PRIMARY, isaac_typescript_definitions_1.ActiveSlot.SECONDARY, isaac_typescript_definitions_1.ActiveSlot.POCKET, ]) { addRoomClearChargeToSlot(player, activeSlot, bigRoomDoubleCharge, playSoundEffect); } } /** * Helper function to add a charge to one of a player's active items, emulating what happens when a * room is cleared. * * This function will take the following things into account: * - L rooms and 2x2 rooms granting a double charge * - The Battery * - AAA Battery * - Not charging active items with `chargetype="special"` * * @param player The player to grant the charges to. * @param activeSlot Optional. The active item slot to grant the charges to. Default is * `ActiveSlot.PRIMARY`. * @param bigRoomDoubleCharge Optional. If set to false, it will treat the current room as a 1x1 * room for the purposes of calculating how much charge to grant. Default * is true. * @param playSoundEffect Optional. Whether to play a charge-related sound effect. Default is true. */ function addRoomClearChargeToSlot(player, activeSlot = isaac_typescript_definitions_1.ActiveSlot.PRIMARY, bigRoomDoubleCharge = true, playSoundEffect = true) { const activeItem = player.GetActiveItem(activeSlot); if (activeItem === isaac_typescript_definitions_1.CollectibleType.NULL) { return; } // Certain collectibles have special charge mechanisms and are not charged upon a room being // cleared. const chargeType = (0, collectibles_1.getCollectibleChargeType)(activeItem); if (chargeType === isaac_typescript_definitions_1.ItemConfigChargeType.SPECIAL) { return; } const room = cachedClasses_1.game.GetRoom(); const roomShape = room.GetRoomShape(); // Big rooms grant two charges and normal rooms grant one charge. let numCharges = bigRoomDoubleCharge ? (0, roomShape_1.getRoomShapeCharges)(roomShape) : 1; // Handle the special case of a timed item. When clearing a room with a timed item, it should // become fully charged. if (chargeType === isaac_typescript_definitions_1.ItemConfigChargeType.TIMED) { // The charges will become clamped to the proper amount in the `addCharge` function. (If the // item is at 50% charge and the player has The Battery, it should go to 150% charged.) numCharges = (0, collectibles_1.getCollectibleMaxCharges)(activeItem); } addCharge(player, activeSlot, numCharges, playSoundEffect); } /** * The AAA Battery should grant an extra charge when the active item is one away from being fully * charged. */ function getChargesToAddWithAAAModifier(player, activeSlot, chargesToAdd) { const hasAAABattery = player.HasTrinket(isaac_typescript_definitions_1.TrinketType.AAA_BATTERY); if (!hasAAABattery) { return chargesToAdd; } const chargesAwayFromMax = getChargesAwayFromMax(player, activeSlot); const AAABatteryShouldApply = chargesToAdd === chargesAwayFromMax - 1; return AAABatteryShouldApply ? chargesToAdd + 1 : chargesToAdd; } /** * Helper function to add a charge to every player's active item, emulating what happens when a room * is cleared. * * This function will take the following things into account: * - L rooms and 2x2 rooms granting a double charge * - The Battery * - AAA Battery * * @param bigRoomDoubleCharge Optional. If set to false, it will treat the current room as a 1x1 * room for the purposes of calculating how much charge to grant. Default * is true. */ function addRoomClearCharges(bigRoomDoubleCharge = true) { for (const player of (0, playerIndex_1.getPlayers)()) { addRoomClearCharge(player, bigRoomDoubleCharge); } } /** * Helper function to get the amount of charges away from the maximum charge that a particular * player is. * * This function accounts for The Battery. For example, if the player has 2/6 charges on a D6, this * function will return 10 (because there are 4 charges remaining on the base charge and 6 charges * remaining on The Battery charge). * * @param player The player to get the charges from. * @param activeSlot Optional. The slot to get the charges from. Default is `ActiveSlot.PRIMARY`. */ function getChargesAwayFromMax(player, activeSlot = isaac_typescript_definitions_1.ActiveSlot.PRIMARY) { const totalCharge = getTotalCharge(player, activeSlot); const activeItem = player.GetActiveItem(activeSlot); const hasBattery = player.HasCollectible(isaac_typescript_definitions_1.CollectibleType.BATTERY); const maxCharges = (0, collectibles_1.getCollectibleMaxCharges)(activeItem); const effectiveMaxCharges = hasBattery ? maxCharges * 2 : maxCharges; return effectiveMaxCharges - totalCharge; } /** * Helper function to get the combined normal charge and the battery charge for the player's active * item. This is useful because you have to add these two values together when setting the active * charge. * * @param player The player to get the charges from. * @param activeSlot Optional. The slot to get the charges from. Default is `ActiveSlot.PRIMARY`. */ function getTotalCharge(player, activeSlot = isaac_typescript_definitions_1.ActiveSlot.PRIMARY) { const activeCharge = player.GetActiveCharge(activeSlot); const batteryCharge = player.GetBatteryCharge(activeSlot); return activeCharge + batteryCharge; } /** * Helper function to find the active slots that the player has the corresponding collectible type * in and have enough charge to be used. Returns an empty array if the player does not have the * collectible in any active slot or does not have enough charges. */ function getUsableActiveItemSlots(player, collectibleType) { const maxCharges = (0, collectibles_1.getCollectibleMaxCharges)(collectibleType); const activeSlots = (0, playerCollectibles_1.getActiveItemSlots)(player, collectibleType); return activeSlots.filter((activeSlot) => { const totalCharge = getTotalCharge(player, activeSlot); return totalCharge >= maxCharges; }); } /** * Helper function to check if a player's active item is "double charged", meaning that it has both * a full normal charge and a full charge from The Battery. * * @param player The player to check. * @param activeSlot Optional. The slot to check. Default is `ActiveSlot.PRIMARY`. */ function isActiveSlotDoubleCharged(player, activeSlot = isaac_typescript_definitions_1.ActiveSlot.PRIMARY) { const collectibleType = player.GetActiveItem(activeSlot); const batteryCharge = player.GetBatteryCharge(activeSlot); const maxCharges = (0, collectibles_1.getCollectibleMaxCharges)(collectibleType); return batteryCharge >= maxCharges; } /** * Helper function to play the appropriate sound effect for a player after getting one or more * charges on their active item. (There is a different sound depending on whether the item is fully * charged.) * * @param player The player to play the sound effect for. * @param activeSlot Optional. The slot that was just charged. Default is `ActiveSlot.PRIMARY`. */ function playChargeSoundEffect(player, activeSlot = isaac_typescript_definitions_1.ActiveSlot.PRIMARY) { for (const soundEffect of [ isaac_typescript_definitions_1.SoundEffect.BATTERY_CHARGE, // 170 isaac_typescript_definitions_1.SoundEffect.BEEP, // 171 ]) { cachedClasses_1.sfxManager.Stop(soundEffect); } const chargeSoundEffect = shouldPlayFullRechargeSound(player, activeSlot) ? isaac_typescript_definitions_1.SoundEffect.BATTERY_CHARGE : isaac_typescript_definitions_1.SoundEffect.BEEP; cachedClasses_1.sfxManager.Play(chargeSoundEffect); } function shouldPlayFullRechargeSound(player, activeSlot) { const activeItem = player.GetActiveItem(activeSlot); const activeCharge = player.GetActiveCharge(activeSlot); const batteryCharge = player.GetBatteryCharge(activeSlot); const hasBattery = player.HasCollectible(isaac_typescript_definitions_1.CollectibleType.BATTERY); const maxCharges = (0, collectibles_1.getCollectibleMaxCharges)(activeItem); // If we do not have The Battery, play the full recharge sound if we are now fully charged. if (!hasBattery) { // We cannot use the `EntityPlayer.NeedsCharge` method because it does not work properly for // items with `chargetype="special"`. return activeCharge === maxCharges; } // If we do have The Battery, play the full recharge sound if we are exactly double charged or // exactly single charged. return (batteryCharge === maxCharges || (activeCharge === maxCharges && batteryCharge === 0)); }