From 74aa5a80054133bf9656c9b08ff5031308eba9e7 Mon Sep 17 00:00:00 2001 From: Dmitriy K Date: Wed, 19 Jun 2024 12:00:26 -0400 Subject: [PATCH] Create Class constructor utility type. (#2162) --- src/battle-scene.ts | 21 +++++++++----- src/data/ability.ts | 61 ++++++++++++++++++++------------------- src/data/move.ts | 9 +++--- src/data/pokemon-forms.ts | 7 +++-- src/field/arena.ts | 9 +++--- src/field/pokemon.ts | 7 +++-- src/utils.ts | 3 ++ 7 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 163ca41a406..43224ab074b 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -3,6 +3,7 @@ import UI from "./ui/ui"; import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, TurnInitPhase, ReturnPhase, LevelCapPhase, ShowTrainerPhase, LoginPhase, MovePhase, TitlePhase, SwitchPhase } from "./phases"; import Pokemon, { PlayerPokemon, EnemyPokemon } from "./field/pokemon"; import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species"; +import { Constructor } from "#app/utils"; import * as Utils from "./utils"; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier"; import { PokeballType } from "./data/pokeball"; @@ -2340,8 +2341,14 @@ export default class BattleScene extends SceneBase { return false; } - getModifiers(modifierType: { new(...args: any[]): Modifier }, player: boolean = true): PersistentModifier[] { - return (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType); + /** + * Get all of the modifiers that match `modifierType` + * @param modifierType The type of modifier to apply; must extend {@linkcode PersistentModifier} + * @param player Whether to search the player (`true`) or the enemy (`false`); Defaults to `true` + * @returns the list of all modifiers that matched `modifierType`. + */ + getModifiers(modifierType: Constructor, player: boolean = true): T[] { + return (player ? this.modifiers : this.enemyModifiers).filter((m): m is T => m instanceof modifierType); } findModifiers(modifierFilter: ModifierPredicate, player: boolean = true): PersistentModifier[] { @@ -2352,7 +2359,7 @@ export default class BattleScene extends SceneBase { return (player ? this.modifiers : this.enemyModifiers).find(m => (modifierFilter as ModifierPredicate)(m)); } - applyShuffledModifiers(scene: BattleScene, modifierType: { new(...args: any[]): Modifier }, player: boolean = true, ...args: any[]): PersistentModifier[] { + applyShuffledModifiers(scene: BattleScene, modifierType: Constructor, player: boolean = true, ...args: any[]): PersistentModifier[] { let modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args)); scene.executeWithSeedOffset(() => { const shuffleModifiers = mods => { @@ -2367,7 +2374,7 @@ export default class BattleScene extends SceneBase { return this.applyModifiersInternal(modifiers, player, args); } - applyModifiers(modifierType: { new(...args: any[]): Modifier }, player: boolean = true, ...args: any[]): PersistentModifier[] { + applyModifiers(modifierType: Constructor, player: boolean = true, ...args: any[]): PersistentModifier[] { const modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args)); return this.applyModifiersInternal(modifiers, player, args); } @@ -2384,7 +2391,7 @@ export default class BattleScene extends SceneBase { return appliedModifiers; } - applyModifier(modifierType: { new(...args: any[]): Modifier }, player: boolean = true, ...args: any[]): PersistentModifier { + applyModifier(modifierType: Constructor, player: boolean = true, ...args: any[]): PersistentModifier { const modifiers = (player ? this.modifiers : this.enemyModifiers).filter(m => m instanceof modifierType && m.shouldApply(args)); for (const modifier of modifiers) { if (modifier.apply(args)) { @@ -2396,7 +2403,7 @@ export default class BattleScene extends SceneBase { return null; } - triggerPokemonFormChange(pokemon: Pokemon, formChangeTriggerType: { new(...args: any[]): SpeciesFormChangeTrigger }, delayed: boolean = false, modal: boolean = false): boolean { + triggerPokemonFormChange(pokemon: Pokemon, formChangeTriggerType: Constructor, delayed: boolean = false, modal: boolean = false): boolean { if (pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId)) { const matchingFormChange = pokemonFormChanges[pokemon.species.speciesId].find(fc => fc.findTrigger(formChangeTriggerType) && fc.canChange(pokemon)); if (matchingFormChange) { @@ -2420,7 +2427,7 @@ export default class BattleScene extends SceneBase { return false; } - validateAchvs(achvType: { new(...args: any[]): Achv }, ...args: any[]): void { + validateAchvs(achvType: Constructor, ...args: unknown[]): void { const filteredAchvs = Object.values(achvs).filter(a => a instanceof achvType); for (const achv of filteredAchvs) { this.validateAchv(achv, args); diff --git a/src/data/ability.ts b/src/data/ability.ts index 5501425e32e..5a3f1d7b2cd 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -1,5 +1,6 @@ import Pokemon, { HitResult, PokemonMove } from "../field/pokemon"; import { Type } from "./type"; +import { Constructor } from "#app/utils"; import * as Utils from "../utils"; import { BattleStat, getBattleStatName } from "./battle-stat"; import { MovePhase, PokemonHealPhase, ShowAbilityPhase, StatChangePhase } from "../phases"; @@ -61,7 +62,7 @@ export class Ability implements Localizable { * @param attrType any attribute that extends {@linkcode AbAttr} * @returns Array of attributes that match `attrType`, Empty Array if none match. */ - getAttrs(attrType: new(...args: any[]) => T ): T[] { + getAttrs(attrType: Constructor ): T[] { return this.attrs.filter((a): a is T => a instanceof attrType); } @@ -70,18 +71,18 @@ export class Ability implements Localizable { * @param attrType any attribute that extends {@linkcode AbAttr} * @returns true if the ability has attribute `attrType` */ - hasAttr(attrType: new(...args: any[]) => T): boolean { + hasAttr(attrType: Constructor): boolean { return this.attrs.some((attr) => attr instanceof attrType); } - attr AbAttr>(AttrType: T, ...args: ConstructorParameters): Ability { + attr>(AttrType: T, ...args: ConstructorParameters): Ability { const attr = new AttrType(...args); this.attrs.push(attr); return this; } - conditionalAttr AbAttr>(condition: AbAttrCondition, AttrType: T, ...args: ConstructorParameters): Ability { + conditionalAttr>(condition: AbAttrCondition, AttrType: T, ...args: ConstructorParameters): Ability { const attr = new AttrType(...args); attr.addCondition(condition); this.attrs.push(attr); @@ -3728,7 +3729,7 @@ export class IceFaceBlockPhysicalAbAttr extends ReceivedMoveDamageMultiplierAbAt } } -function applyAbAttrsInternal(attrType: { new(...args: any[]): TAttr }, +function applyAbAttrsInternal(attrType: Constructor, pokemon: Pokemon, applyFunc: AbAttrApplyFunc, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise { return new Promise(resolve => { if (!pokemon.canApplyAbility(passive)) { @@ -3806,32 +3807,32 @@ function applyAbAttrsInternal(attrType: { new(...args: any }); } -export function applyAbAttrs(attrType: { new(...args: any[]): AbAttr }, pokemon: Pokemon, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { +export function applyAbAttrs(attrType: Constructor, pokemon: Pokemon, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.apply(pokemon, passive, cancelled, args), args); } -export function applyPostBattleInitAbAttrs(attrType: { new(...args: any[]): PostBattleInitAbAttr }, +export function applyPostBattleInitAbAttrs(attrType: Constructor, pokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattleInit(pokemon, passive, args), args); } -export function applyPreDefendAbAttrs(attrType: { new(...args: any[]): PreDefendAbAttr }, +export function applyPreDefendAbAttrs(attrType: Constructor, pokemon: Pokemon, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreDefend(pokemon, passive, attacker, move, cancelled, args), args, false, false, simulated); } -export function applyPostDefendAbAttrs(attrType: { new(...args: any[]): PostDefendAbAttr }, +export function applyPostDefendAbAttrs(attrType: Constructor, pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostDefend(pokemon, passive, attacker, move, hitResult, args), args); } -export function applyPostMoveUsedAbAttrs(attrType: { new(...args: any[]): PostMoveUsedAbAttr }, +export function applyPostMoveUsedAbAttrs(attrType: Constructor, pokemon: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostMoveUsed(pokemon, move, source, targets, args), args); } -export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]): BattleStatMultiplierAbAttr }, +export function applyBattleStatMultiplierAbAttrs(attrType: Constructor, pokemon: Pokemon, battleStat: BattleStat, statValue: Utils.NumberHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyBattleStat(pokemon, passive, battleStat, statValue, args), args); } @@ -3846,98 +3847,98 @@ export function applyBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]) * @param hasApplied {@linkcode Utils.BooleanHolder} whether or not a FieldMultiplyBattleStatAbAttr has already affected this stat * @param args unused */ -export function applyFieldBattleStatMultiplierAbAttrs(attrType: { new(...args: any[]): FieldMultiplyBattleStatAbAttr }, +export function applyFieldBattleStatMultiplierAbAttrs(attrType: Constructor, pokemon: Pokemon, stat: Stat, statValue: Utils.NumberHolder, checkedPokemon: Pokemon, hasApplied: Utils.BooleanHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyFieldBattleStat(pokemon, passive, stat, statValue, checkedPokemon, hasApplied, args), args); } -export function applyPreAttackAbAttrs(attrType: { new(...args: any[]): PreAttackAbAttr }, +export function applyPreAttackAbAttrs(attrType: Constructor, pokemon: Pokemon, defender: Pokemon, move: Move, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreAttack(pokemon, passive, defender, move, args), args); } -export function applyPostAttackAbAttrs(attrType: { new(...args: any[]): PostAttackAbAttr }, +export function applyPostAttackAbAttrs(attrType: Constructor, pokemon: Pokemon, defender: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostAttack(pokemon, passive, defender, move, hitResult, args), args); } -export function applyPostKnockOutAbAttrs(attrType: { new(...args: any[]): PostKnockOutAbAttr }, +export function applyPostKnockOutAbAttrs(attrType: Constructor, pokemon: Pokemon, knockedOut: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostKnockOut(pokemon, passive, knockedOut, args), args); } -export function applyPostVictoryAbAttrs(attrType: { new(...args: any[]): PostVictoryAbAttr }, +export function applyPostVictoryAbAttrs(attrType: Constructor, pokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostVictory(pokemon, passive, args), args); } -export function applyPostSummonAbAttrs(attrType: { new(...args: any[]): PostSummonAbAttr }, +export function applyPostSummonAbAttrs(attrType: Constructor, pokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, args), args); } -export function applyPreSwitchOutAbAttrs(attrType: { new(...args: any[]): PreSwitchOutAbAttr }, +export function applyPreSwitchOutAbAttrs(attrType: Constructor, pokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, args), args, false, true); } -export function applyPreStatChangeAbAttrs(attrType: { new(...args: any[]): PreStatChangeAbAttr }, +export function applyPreStatChangeAbAttrs(attrType: Constructor, pokemon: Pokemon, stat: BattleStat, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreStatChange(pokemon, passive, stat, cancelled, args), args); } -export function applyPostStatChangeAbAttrs(attrType: { new(...args: any[]): PostStatChangeAbAttr }, +export function applyPostStatChangeAbAttrs(attrType: Constructor, pokemon: Pokemon, stats: BattleStat[], levels: integer, selfTarget: boolean, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostStatChange(pokemon, stats, levels, selfTarget, args), args); } -export function applyPreSetStatusAbAttrs(attrType: { new(...args: any[]): PreSetStatusAbAttr }, +export function applyPreSetStatusAbAttrs(attrType: Constructor, pokemon: Pokemon, effect: StatusEffect, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { const simulated = args.length > 1 && args[1]; return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreSetStatus(pokemon, passive, effect, cancelled, args), args, false, false, !simulated); } -export function applyPreApplyBattlerTagAbAttrs(attrType: { new(...args: any[]): PreApplyBattlerTagAbAttr }, +export function applyPreApplyBattlerTagAbAttrs(attrType: Constructor, pokemon: Pokemon, tag: BattlerTag, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreApplyBattlerTag(pokemon, passive, tag, cancelled, args), args); } -export function applyPreWeatherEffectAbAttrs(attrType: { new(...args: any[]): PreWeatherEffectAbAttr }, +export function applyPreWeatherEffectAbAttrs(attrType: Constructor, pokemon: Pokemon, weather: Weather, cancelled: Utils.BooleanHolder, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPreWeatherEffect(pokemon, passive, weather, cancelled, args), args, false, true); } -export function applyPostTurnAbAttrs(attrType: { new(...args: any[]): PostTurnAbAttr }, +export function applyPostTurnAbAttrs(attrType: Constructor, pokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, args), args); } -export function applyPostWeatherChangeAbAttrs(attrType: { new(...args: any[]): PostWeatherChangeAbAttr }, +export function applyPostWeatherChangeAbAttrs(attrType: Constructor, pokemon: Pokemon, weather: WeatherType, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherChange(pokemon, passive, weather, args), args); } -export function applyPostWeatherLapseAbAttrs(attrType: { new(...args: any[]): PostWeatherLapseAbAttr }, +export function applyPostWeatherLapseAbAttrs(attrType: Constructor, pokemon: Pokemon, weather: Weather, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostWeatherLapse(pokemon, passive, weather, args), args); } -export function applyPostTerrainChangeAbAttrs(attrType: { new(...args: any[]): PostTerrainChangeAbAttr }, +export function applyPostTerrainChangeAbAttrs(attrType: Constructor, pokemon: Pokemon, terrain: TerrainType, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostTerrainChange(pokemon, passive, terrain, args), args); } -export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckTrappedAbAttr }, +export function applyCheckTrappedAbAttrs(attrType: Constructor, pokemon: Pokemon, trapped: Utils.BooleanHolder, otherPokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyCheckTrapped(pokemon, passive, trapped, otherPokemon, args), args, true); } -export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBattleAbAttr }, +export function applyPostBattleAbAttrs(attrType: Constructor, pokemon: Pokemon, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, args), args); } -export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr }, +export function applyPostFaintAbAttrs(attrType: Constructor, pokemon: Pokemon, attacker: Pokemon, move: Move, hitResult: HitResult, ...args: any[]): Promise { return applyAbAttrsInternal(attrType, pokemon, (attr, passive) => attr.applyPostFaint(pokemon, passive, attacker, move, hitResult, args), args); } diff --git a/src/data/move.ts b/src/data/move.ts index 82cf455df3a..dec52b04c57 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -6,6 +6,7 @@ import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon"; import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect"; import { Type } from "./type"; +import { Constructor } from "#app/utils"; import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; @@ -156,7 +157,7 @@ export default class Move implements Localizable { * @param attrType any attribute that extends {@linkcode MoveAttr} * @returns Array of attributes that match `attrType`, Empty Array if none match. */ - getAttrs(attrType: new(...args: any[]) => T): T[] { + getAttrs(attrType: Constructor): T[] { return this.attrs.filter((a): a is T => a instanceof attrType); } @@ -165,7 +166,7 @@ export default class Move implements Localizable { * @param attrType any attribute that extends {@linkcode MoveAttr} * @returns true if the move has attribute `attrType` */ - hasAttr(attrType: new(...args: any[]) => T): boolean { + hasAttr(attrType: Constructor): boolean { return this.attrs.some((attr) => attr instanceof attrType); } @@ -185,7 +186,7 @@ export default class Move implements Localizable { * @param args the args needed to instantiate a the given class * @returns the called object {@linkcode Move} */ - attr MoveAttr>(AttrType: T, ...args: ConstructorParameters): this { + attr>(AttrType: T, ...args: ConstructorParameters): this { const attr = new AttrType(...args); this.attrs.push(attr); let attrCondition = attr.getCondition(); @@ -5507,7 +5508,7 @@ function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon, targe }); } -export function applyMoveAttrs(attrType: { new(...args: any[]): MoveAttr }, user: Pokemon, target: Pokemon, move: Move, ...args: any[]): Promise { +export function applyMoveAttrs(attrType: Constructor, user: Pokemon, target: Pokemon, move: Move, ...args: any[]): Promise { return applyMoveAttrsInternal((attr: MoveAttr) => attr instanceof attrType, user, target, move, args); } diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index cc05af50f6f..ad93bec44e4 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -3,6 +3,7 @@ import Pokemon from "../field/pokemon"; import { SpeciesFormKey } from "./pokemon-species"; import { StatusEffect } from "./status-effect"; import { MoveCategory, allMoves } from "./move"; +import { Constructor } from "#app/utils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; @@ -178,7 +179,7 @@ export class SpeciesFormChange { return true; } - findTrigger(triggerType: { new(...args: any[]): SpeciesFormChangeTrigger }): SpeciesFormChangeTrigger { + findTrigger(triggerType: Constructor): SpeciesFormChangeTrigger { if (!this.trigger.hasTriggerType(triggerType)) { return null; } @@ -208,7 +209,7 @@ export abstract class SpeciesFormChangeTrigger { return true; } - hasTriggerType(triggerType: { new(...args: any[]): SpeciesFormChangeTrigger }): boolean { + hasTriggerType(triggerType: Constructor): boolean { return this instanceof triggerType; } } @@ -236,7 +237,7 @@ export class SpeciesFormChangeCompoundTrigger { return true; } - hasTriggerType(triggerType: { new(...args: any[]): SpeciesFormChangeTrigger }): boolean { + hasTriggerType(triggerType: Constructor): boolean { return !!this.triggers.find(t => t.hasTriggerType(triggerType)); } } diff --git a/src/field/arena.ts b/src/field/arena.ts index de95af69a23..a5e62872152 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -1,5 +1,6 @@ import BattleScene from "../battle-scene"; import { BiomePoolTier, PokemonPools, BiomeTierTrainerPools, biomePokemonPools, biomeTrainerPools } from "../data/biomes"; +import { Constructor } from "#app/utils"; import * as Utils from "../utils"; import PokemonSpecies, { getPokemonSpecies } from "../data/pokemon-species"; import { Weather, WeatherType, getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage } from "../data/weather"; @@ -535,7 +536,7 @@ export class Arena { this.ignoreAbilities = ignoreAbilities; } - applyTagsForSide(tagType: ArenaTagType | { new(...args: any[]): ArenaTag }, side: ArenaTagSide, ...args: any[]): void { + applyTagsForSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide, ...args: unknown[]): void { let tags = typeof tagType === "string" ? this.tags.filter(t => t.tagType === tagType) : this.tags.filter(t => t instanceof tagType); @@ -545,7 +546,7 @@ export class Arena { tags.forEach(t => t.apply(this, args)); } - applyTags(tagType: ArenaTagType | { new(...args: any[]): ArenaTag }, ...args: any[]): void { + applyTags(tagType: ArenaTagType | Constructor, ...args: unknown[]): void { this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); } @@ -573,11 +574,11 @@ export class Arena { return true; } - getTag(tagType: ArenaTagType | { new(...args: any[]): ArenaTag }): ArenaTag { + getTag(tagType: ArenaTagType | Constructor): ArenaTag { return this.getTagOnSide(tagType, ArenaTagSide.BOTH); } - getTagOnSide(tagType: ArenaTagType | { new(...args: any[]): ArenaTag }, side: ArenaTagSide): ArenaTag { + getTagOnSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide): ArenaTag { return typeof(tagType) === "string" ? this.tags.find(t => t.tagType === tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)) : this.tags.find(t => t instanceof tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 4146adee377..5b37365bec1 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5,6 +5,7 @@ import { variantData } from "#app/data/variant"; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "../ui/battle-info"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, VariableMoveTypeAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, MoveFlags } from "../data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from "../data/pokemon-species"; +import { Constructor } from "#app/utils"; import * as Utils from "../utils"; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type"; import { getLevelTotalExp } from "../data/exp"; @@ -1064,7 +1065,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @param {boolean} ignoreOverride If true, it ignores ability changing effects * @returns {boolean} Whether an ability with that attribute is present and active */ - hasAbilityWithAttr(attrType: { new(...args: any[]): AbAttr }, canApply: boolean = true, ignoreOverride?: boolean): boolean { + hasAbilityWithAttr(attrType: Constructor, canApply: boolean = true, ignoreOverride?: boolean): boolean { if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).hasAttr(attrType)) { return true; } @@ -2104,7 +2105,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return false; } - getTag(tagType: BattlerTagType | { new(...args: any[]): BattlerTag }): BattlerTag { + getTag(tagType: BattlerTagType | Constructor): BattlerTag { if (!this.summonData) { return null; } @@ -2120,7 +2121,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.summonData.tags.find(t => tagFilter(t)); } - getTags(tagType: BattlerTagType | { new(...args: any[]): BattlerTag }): BattlerTag[] { + getTags(tagType: BattlerTagType | Constructor): BattlerTag[] { if (!this.summonData) { return []; } diff --git a/src/utils.ts b/src/utils.ts index 7c1a24a6d5e..6667d2522f5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -361,6 +361,9 @@ export function apiPost(path: string, data?: any, contentType: string = "applica }) : new Promise(() => {}); } +/** Alias for the constructor of a class */ +export type Constructor = new(...args: unknown[]) => T; + export class BooleanHolder { public value: boolean;