isaacscript-common
Version:
Helper functions and features for IsaacScript mods.
135 lines (134 loc) • 7.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAliveNPCs = getAliveNPCs;
exports.isAliveExceptionNPC = isAliveExceptionNPC;
exports.isDaddyLongLegsChildStompEntity = isDaddyLongLegsChildStompEntity;
exports.isDyingDump = isDyingDump;
exports.isDyingEggyWithNoSpidersLeft = isDyingEggyWithNoSpidersLeft;
exports.isRaglingDeathPatch = isRaglingDeathPatch;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
const constants_1 = require("../core/constants");
const ReadonlySet_1 = require("../types/ReadonlySet");
const entitiesSpecific_1 = require("./entitiesSpecific");
/**
* Used to filter out certain NPCs when determining of an NPC is "alive" and/or should keep the
* doors open.
*/
const NON_ALIVE_NPCS_TYPE_VARIANT = new ReadonlySet_1.ReadonlySet([
`${isaac_typescript_definitions_1.EntityType.VIS}.${isaac_typescript_definitions_1.VisVariant.CHUBBER_PROJECTILE}`, // 39.22
`${isaac_typescript_definitions_1.EntityType.DEATH}.${isaac_typescript_definitions_1.DeathVariant.DEATH_SCYTHE}`, // 66.10
`${isaac_typescript_definitions_1.EntityType.PEEP}.${isaac_typescript_definitions_1.PeepVariant.PEEP_EYE}`, // 68.10
`${isaac_typescript_definitions_1.EntityType.PEEP}.${isaac_typescript_definitions_1.PeepVariant.BLOAT_EYE}`, // 68.11
`${isaac_typescript_definitions_1.EntityType.BEGOTTEN}.${isaac_typescript_definitions_1.BegottenVariant.BEGOTTEN_CHAIN}`, // 251.10
`${isaac_typescript_definitions_1.EntityType.MAMA_GURDY}.${isaac_typescript_definitions_1.MamaGurdyVariant.LEFT_HAND}`, // 266.1
`${isaac_typescript_definitions_1.EntityType.MAMA_GURDY}.${isaac_typescript_definitions_1.MamaGurdyVariant.RIGHT_HAND}`, // 266.2
`${isaac_typescript_definitions_1.EntityType.BIG_HORN}.${isaac_typescript_definitions_1.BigHornVariant.SMALL_HOLE}`, // 411.1
`${isaac_typescript_definitions_1.EntityType.BIG_HORN}.${isaac_typescript_definitions_1.BigHornVariant.BIG_HOLE}`, // 411.2
`${isaac_typescript_definitions_1.EntityType.DARK_ESAU}.${isaac_typescript_definitions_1.DarkEsauVariant.DARK_ESAU}`, // 866.0
`${isaac_typescript_definitions_1.EntityType.DARK_ESAU}.${isaac_typescript_definitions_1.DarkEsauVariant.PIT}`, // 866.1
]);
/**
* Used to filter out certain NPCs when determining of an NPC is "alive" and/or should keep the
* doors open.
*/
const NON_ALIVE_NPCS_TYPE_VARIANT_SUB_TYPE = new ReadonlySet_1.ReadonlySet([
`${isaac_typescript_definitions_1.EntityType.CHARGER}.${isaac_typescript_definitions_1.ChargerVariant.CHARGER}.${isaac_typescript_definitions_1.ChargerSubType.MY_SHADOW}`, // 23.0.1
`${isaac_typescript_definitions_1.EntityType.MOTHER}.${isaac_typescript_definitions_1.MotherVariant.MOTHER_1}.${isaac_typescript_definitions_1.MotherSubType.PHASE_2}`, // 912
]);
/**
* Helper function to get all of the non-dead NPCs in the room.
*
* This function will not include NPCs on an internal blacklist, such as Death's scythes or Big Horn
* holes.
*
* @param entityType Optional. If specified, will only get the NPCs that match the type. Default is
* -1, which matches every type.
* @param variant Optional. If specified, will only get the NPCs that match the variant. Default is
* -1, which matches every variant.
* @param subType Optional. If specified, will only get the NPCs that match the sub-type. Default is
* -1, which matches every sub-type.
* @param ignoreFriendly Optional. Default is false.
*/
function getAliveNPCs(entityType = -1, variant = -1, subType = -1, ignoreFriendly = false) {
const npcs = (0, entitiesSpecific_1.getNPCs)(entityType, variant, subType, ignoreFriendly);
return npcs.filter((npc) => !npc.IsDead() && !isAliveExceptionNPC(npc));
}
/**
* Checks for specific NPCs that have "CanShutDoors" set to true naturally by the game, but should
* not actually keep the doors closed (like Death's scythes).
*/
function isAliveExceptionNPC(npc) {
const entityTypeVariant = `${npc.Type}.${npc.Variant}`;
if (NON_ALIVE_NPCS_TYPE_VARIANT.has(entityTypeVariant)) {
return true;
}
const entityTypeVariantSubType = `${npc.Type}.${npc.Variant}.${npc.SubType}`;
if (NON_ALIVE_NPCS_TYPE_VARIANT_SUB_TYPE.has(entityTypeVariantSubType)) {
return true;
}
// EntityType.HOPPER (29)
// HopperVariant.EGGY (2)
if (isDyingEggyWithNoSpidersLeft(npc)) {
return true;
}
// EntityType.DADDY_LONG_LEGS (101)
if (isDaddyLongLegsChildStompEntity(npc)) {
return true;
}
// EntityType.RAGLING (256)
if (isRaglingDeathPatch(npc)) {
return true;
}
// EntityType.DUMP (876)
if (isDyingDump(npc)) {
return true;
}
return false;
}
/**
* Helper function to distinguish between a normal Daddy Long Legs / Triachnid and the child entity
* that is spawned when the boss does the multi-stomp attack.
*
* When this attack occurs, four extra copies of Daddy Long Legs will be spawned with the same
* entity type, variant, and sub-type. The `Entity.Parent` field will be undefined in this case, so
* the way to tell them apart is to check for a non-undefined `Entity.SpawnerEntity` field.
*/
function isDaddyLongLegsChildStompEntity(npc) {
return (npc.Type === isaac_typescript_definitions_1.EntityType.DADDY_LONG_LEGS && npc.SpawnerEntity !== undefined);
}
/**
* Helper function to detect the custom death state of a Dump. When Dumps die, they go to
* `NPCState.SPECIAL`, spit out their head, and then slowly fade away while shooting a burst of
* tears.
*/
function isDyingDump(npc) {
return (npc.Type === isaac_typescript_definitions_1.EntityType.DUMP
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
&& npc.Variant === isaac_typescript_definitions_1.DumpVariant.DUMP
&& npc.State === isaac_typescript_definitions_1.NPCState.SPECIAL);
}
/**
* Helper function to detect the custom death state of an Eggy. Eggies are never actually marked
* dead by the game. Instead, when Eggies take fatal damage, they go into NPCState.STATE_SUICIDE and
* spawn 14 Swarm Spiders while their StateFrame ticks upwards.
*/
function isDyingEggyWithNoSpidersLeft(npc) {
return (npc.Type === isaac_typescript_definitions_1.EntityType.HOPPER
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
&& npc.Variant === isaac_typescript_definitions_1.HopperVariant.EGGY
&& npc.State === isaac_typescript_definitions_1.NPCState.SUICIDE
&& npc.StateFrame >= constants_1.EGGY_STATE_FRAME_OF_FINAL_SPIDER);
}
/**
* Helper function to detect the custom death state of a Rag Man Ragling. When Rag Man Raglings die,
* they turn into a patch on the ground and can be revived by Rag Man at a later time. This causes
* them to show up as an "alive" enemy, so they should usually be filtered out of lists of alive
* enemies.
*/
function isRaglingDeathPatch(npc) {
return (npc.Type === isaac_typescript_definitions_1.EntityType.RAGLING
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
&& npc.Variant === isaac_typescript_definitions_1.RaglingVariant.RAG_MANS_RAGLING
// They go to `STATE_SPECIAL` when they are patches on the ground.
&& npc.State === isaac_typescript_definitions_1.NPCState.SPECIAL);
}