From 48e911e03cc71e6bec3883acb9fc8ca045364a1c Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:24:13 -0500 Subject: [PATCH] [Refactor] Remove circular deps 3 (#5959) * Move game-mode to its own file Reduces circular imports to 325 * Move battler-index to own file Reduces circular deps to 314 * Move trainer-variant to own file Reduces circ deps to 313 * Move enums in pokemon to their own file * Move arena-tag-type to its own file * Move pokemon-moves to its own file * Move command to own file * Move learnMoveType to own file * Move form change item to own file * Move battlerTagLapseType to own file * Move anim enums to own shared file * Move enums out of challenges * Move species form change triggers to own file Reduces circ imports to 291 * Update test importing pokemon move * Replace move attribute imports with string names * Untangle circular deps from game data * Fix missing string call in switch summon phase * Apply kev's suggestions from code review Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Ensure ChargeMove's is method calls super * Use InstanceType for proper narrowing * Apply kev's suggestions from code review Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/@types/move-types.ts | 56 ++ src/battle-scene.ts | 19 +- src/battle.ts | 14 +- src/constants.ts | 37 ++ src/data/abilities/ability.ts | 86 ++- src/data/arena-tag.ts | 14 +- src/data/battle-anims.ts | 117 +--- src/data/battler-tags.ts | 35 +- src/data/berry.ts | 2 +- src/data/challenge.ts | 92 +-- src/data/moves/apply-attrs.ts | 58 ++ src/data/moves/move-utils.ts | 96 ++- src/data/moves/move.ts | 546 ++++++++++++------ src/data/moves/pokemon-move.ts | 93 +++ .../encounters/absolute-avarice-encounter.ts | 5 +- .../encounters/bug-type-superfan-encounter.ts | 2 +- .../encounters/clowning-around-encounter.ts | 4 +- .../encounters/dancing-lessons-encounter.ts | 5 +- .../encounters/field-trip-encounter.ts | 3 +- .../encounters/fiery-fallout-encounter.ts | 4 +- .../encounters/fun-and-games-encounter.ts | 4 +- .../global-trade-system-encounter.ts | 3 +- .../encounters/lost-at-sea-encounter.ts | 2 +- .../slumbering-snorlax-encounter.ts | 5 +- .../encounters/the-strong-stuff-encounter.ts | 4 +- .../the-winstrate-challenge-encounter.ts | 2 +- .../encounters/training-session-encounter.ts | 2 +- .../encounters/trash-to-treasure-encounter.ts | 4 +- .../encounters/uncommon-breed-encounter.ts | 7 +- .../encounters/weird-dream-encounter.ts | 2 +- .../mystery-encounter-requirements.ts | 4 +- .../mystery-encounters/mystery-encounter.ts | 7 +- .../can-learn-move-requirement.ts | 2 +- .../utils/encounter-phase-utils.ts | 12 +- src/data/pokemon-forms.ts | 484 +--------------- .../pokemon-forms/form-change-triggers.ts | 348 +++++++++++ src/data/pokemon-species.ts | 3 +- src/data/terrain.ts | 5 +- src/data/trainers/TrainerPartyTemplate.ts | 2 +- src/data/trainers/trainer-config.ts | 4 +- src/data/weather.ts | 5 +- src/enums/ability-attr.ts | 11 + src/enums/ai-type.ts | 5 + src/enums/arena-tag-side.ts | 5 + src/enums/battler-index.ts | 7 + src/enums/battler-tag-lapse-type.ts | 12 + src/enums/challenge-type.ts | 69 +++ src/enums/command.ts | 7 + src/enums/dex-attr.ts | 11 + src/enums/field-position.ts | 5 + src/enums/form-change-item.ts | 119 ++++ src/enums/game-modes.ts | 7 + src/enums/hit-result.ts | 15 + src/enums/learn-move-situation.ts | 8 + src/enums/learn-move-type.ts | 8 + src/enums/move-anims-common.ts | 95 +++ src/enums/move-result.ts | 7 + src/enums/move-source-type.ts | 12 + src/enums/trainer-variant.ts | 5 + src/events/arena.ts | 2 +- src/field/arena.ts | 12 +- src/field/damage-number-handler.ts | 4 +- src/field/pokemon.ts | 257 ++------- src/field/trainer.ts | 10 +- src/game-mode.ts | 12 +- src/modifier/modifier-type.ts | 15 +- src/modifier/modifier.ts | 7 +- src/overrides.ts | 2 +- src/phases/attempt-capture-phase.ts | 2 +- src/phases/berry-phase.ts | 2 +- src/phases/check-status-effect-phase.ts | 2 +- src/phases/command-phase.ts | 8 +- src/phases/common-anim-phase.ts | 4 +- src/phases/damage-anim-phase.ts | 5 +- src/phases/encounter-phase.ts | 4 +- src/phases/enemy-command-phase.ts | 4 +- src/phases/evolution-phase.ts | 2 +- src/phases/faint-phase.ts | 12 +- src/phases/form-change-phase.ts | 2 +- src/phases/learn-move-phase.ts | 12 +- src/phases/move-charge-phase.ts | 12 +- src/phases/move-effect-phase.ts | 62 +- src/phases/move-end-phase.ts | 4 +- src/phases/move-header-phase.ts | 6 +- src/phases/move-phase.ts | 47 +- src/phases/mystery-encounter-phases.ts | 2 +- src/phases/obtain-status-effect-phase.ts | 7 +- src/phases/pokemon-heal-phase.ts | 6 +- src/phases/pokemon-phase.ts | 2 +- src/phases/pokemon-transform-phase.ts | 4 +- src/phases/post-turn-status-effect-phase.ts | 5 +- src/phases/quiet-form-change-phase.ts | 5 +- src/phases/return-phase.ts | 2 +- src/phases/scan-ivs-phase.ts | 2 +- src/phases/select-starter-phase.ts | 5 +- src/phases/select-target-phase.ts | 4 +- src/phases/shiny-sparkle-phase.ts | 2 +- src/phases/show-ability-phase.ts | 2 +- src/phases/stat-stage-change-phase.ts | 5 +- src/phases/summon-phase.ts | 4 +- src/phases/switch-summon-phase.ts | 7 +- src/phases/tera-phase.ts | 5 +- src/phases/title-phase.ts | 3 +- src/phases/toggle-double-position-phase.ts | 2 +- src/phases/turn-end-phase.ts | 2 +- src/phases/turn-init-phase.ts | 2 +- src/phases/turn-start-phase.ts | 9 +- src/phases/victory-phase.ts | 2 +- src/phases/weather-effect-phase.ts | 4 +- src/system/game-data.ts | 111 +--- src/system/pokemon-data.ts | 3 +- src/system/trainer-data.ts | 3 +- src/system/unlockables.ts | 3 +- .../version_migration/versions/v1_0_4.ts | 4 +- .../version_migration/versions/v1_7_0.ts | 3 +- .../version_migration/versions/v1_8_3.ts | 3 +- .../version_migration/versions/v1_9_0.ts | 2 +- src/ui/arena-flyout.ts | 3 +- src/ui/ball-ui-handler.ts | 2 +- src/ui/command-ui-handler.ts | 9 +- src/ui/fight-ui-handler.ts | 5 +- src/ui/game-stats-ui-handler.ts | 2 +- src/ui/hatched-pokemon-container.ts | 2 +- src/ui/party-ui-handler.ts | 16 +- src/ui/pokedex-page-ui-handler.ts | 3 +- src/ui/pokedex-ui-handler.ts | 7 +- src/ui/pokemon-info-container.ts | 2 +- src/ui/run-history-ui-handler.ts | 4 +- src/ui/run-info-ui-handler.ts | 4 +- src/ui/starter-select-ui-handler.ts | 12 +- src/ui/summary-ui-handler.ts | 3 +- src/ui/target-select-ui-handler.ts | 4 +- src/utils/data.ts | 47 ++ test/abilities/analytic.test.ts | 2 +- test/abilities/aroma_veil.test.ts | 2 +- test/abilities/battle_bond.test.ts | 3 +- test/abilities/beast_boost.test.ts | 2 +- test/abilities/commander.test.ts | 4 +- test/abilities/dancer.test.ts | 4 +- test/abilities/desolate-land.test.ts | 2 +- test/abilities/disguise.test.ts | 2 +- test/abilities/early_bird.test.ts | 2 +- test/abilities/flash_fire.test.ts | 2 +- test/abilities/flower_gift.test.ts | 2 +- test/abilities/flower_veil.test.ts | 2 +- test/abilities/forecast.test.ts | 2 +- test/abilities/friend_guard.test.ts | 2 +- test/abilities/good_as_gold.test.ts | 4 +- test/abilities/gorilla_tactics.test.ts | 2 +- test/abilities/gulp_missile.test.ts | 2 +- test/abilities/harvest.test.ts | 2 +- test/abilities/honey_gather.test.ts | 2 +- test/abilities/ice_face.test.ts | 2 +- test/abilities/infiltrator.test.ts | 2 +- test/abilities/lightningrod.test.ts | 2 +- test/abilities/magic_bounce.test.ts | 4 +- test/abilities/magic_guard.test.ts | 3 +- test/abilities/mirror_armor.test.ts | 2 +- test/abilities/mold_breaker.test.ts | 2 +- test/abilities/moxie.test.ts | 2 +- test/abilities/neutralizing_gas.test.ts | 4 +- test/abilities/no_guard.test.ts | 2 +- .../abilities/normal-move-type-change.test.ts | 2 +- test/abilities/pastel_veil.test.ts | 2 +- test/abilities/protosynthesis.test.ts | 2 +- test/abilities/serene_grace.test.ts | 5 +- test/abilities/sheer_force.test.ts | 7 +- test/abilities/shield_dust.test.ts | 2 +- test/abilities/speed_boost.test.ts | 2 +- test/abilities/stakeout.test.ts | 2 +- test/abilities/storm_drain.test.ts | 2 +- test/abilities/supreme_overlord.test.ts | 2 +- test/abilities/sweet_veil.test.ts | 2 +- test/abilities/tera_shell.test.ts | 2 +- test/abilities/unburden.test.ts | 2 +- test/abilities/victory_star.test.ts | 2 +- test/abilities/volt_absorb.test.ts | 2 +- test/abilities/wimp_out.test.ts | 4 +- test/arena/arena_gravity.test.ts | 2 +- test/arena/weather_hail.test.ts | 2 +- test/battle/battle.test.ts | 3 +- test/battle/double_battle.test.ts | 3 +- test/battle/inverse_battle.test.ts | 2 +- test/battlerTags/octolock.test.ts | 3 +- test/battlerTags/substitute.test.ts | 5 +- test/data/status_effect.test.ts | 2 +- test/endless_boss.test.ts | 2 +- test/enemy_command.test.ts | 2 +- test/escape-calculations.test.ts | 2 +- test/final_boss.test.ts | 2 +- test/game-mode.test.ts | 3 +- test/imports.test.ts | 2 +- test/items/grip_claw.test.ts | 2 +- test/items/multi_lens.test.ts | 2 +- test/items/reviver_seed.test.ts | 2 +- test/moves/after_you.test.ts | 4 +- test/moves/alluring_voice.test.ts | 2 +- test/moves/assist.test.ts | 4 +- test/moves/aurora_veil.test.ts | 5 +- test/moves/baneful_bunker.test.ts | 2 +- test/moves/baton_pass.test.ts | 2 +- test/moves/burning_jealousy.test.ts | 2 +- test/moves/camouflage.test.ts | 2 +- test/moves/ceaseless_edge.test.ts | 3 +- test/moves/chloroblast.test.ts | 2 +- test/moves/copycat.test.ts | 8 +- test/moves/destiny_bond.test.ts | 4 +- test/moves/dig.test.ts | 4 +- test/moves/disable.test.ts | 4 +- test/moves/dive.test.ts | 2 +- test/moves/doodle.test.ts | 2 +- test/moves/dragon_cheer.test.ts | 2 +- test/moves/dragon_tail.test.ts | 2 +- test/moves/dynamax_cannon.test.ts | 2 +- test/moves/electrify.test.ts | 2 +- test/moves/electro_shot.test.ts | 2 +- test/moves/encore.test.ts | 4 +- test/moves/fairy_lock.test.ts | 2 +- test/moves/false_swipe.test.ts | 2 +- test/moves/fly.test.ts | 4 +- test/moves/follow_me.test.ts | 2 +- test/moves/freeze_dry.test.ts | 2 +- test/moves/fusion_flare_bolt.test.ts | 2 +- test/moves/gastro_acid.test.ts | 4 +- test/moves/geomancy.test.ts | 2 +- test/moves/gigaton_hammer.test.ts | 2 +- test/moves/grudge.test.ts | 2 +- test/moves/heal_block.test.ts | 4 +- test/moves/instruct.test.ts | 4 +- test/moves/jaw_lock.test.ts | 2 +- test/moves/lash_out.test.ts | 2 +- test/moves/last-resort.test.ts | 4 +- test/moves/last_respects.test.ts | 2 +- test/moves/light_screen.test.ts | 5 +- test/moves/magic_coat.test.ts | 6 +- test/moves/metal_burst.test.ts | 4 +- test/moves/metronome.test.ts | 4 +- test/moves/miracle_eye.test.ts | 2 +- test/moves/mirror_move.test.ts | 4 +- test/moves/moongeist_beam.test.ts | 3 +- test/moves/multi_target.test.ts | 2 +- test/moves/order_up.test.ts | 2 +- test/moves/plasma_fists.test.ts | 2 +- test/moves/pledge_moves.test.ts | 7 +- test/moves/pollen_puff.test.ts | 2 +- test/moves/powder.test.ts | 5 +- test/moves/protect.test.ts | 7 +- test/moves/purify.test.ts | 2 +- test/moves/quash.test.ts | 4 +- test/moves/quick_guard.test.ts | 4 +- test/moves/rage_fist.test.ts | 2 +- test/moves/rage_powder.test.ts | 2 +- test/moves/reflect.test.ts | 5 +- test/moves/revival_blessing.test.ts | 4 +- test/moves/roost.test.ts | 2 +- test/moves/round.test.ts | 2 +- test/moves/safeguard.test.ts | 2 +- test/moves/scale_shot.test.ts | 2 +- test/moves/secret_power.test.ts | 4 +- test/moves/shed_tail.test.ts | 2 +- test/moves/shell_side_arm.test.ts | 6 +- test/moves/shell_trap.test.ts | 4 +- test/moves/sketch.test.ts | 5 +- test/moves/sleep_talk.test.ts | 2 +- test/moves/solar_beam.test.ts | 2 +- test/moves/spectral_thief.test.ts | 2 +- test/moves/spikes.test.ts | 3 +- test/moves/spit_up.test.ts | 2 +- test/moves/spotlight.test.ts | 2 +- test/moves/steamroller.test.ts | 2 +- test/moves/stockpile.test.ts | 2 +- test/moves/substitute.test.ts | 8 +- test/moves/swallow.test.ts | 2 +- test/moves/syrup_bomb.test.ts | 2 +- test/moves/tailwind.test.ts | 2 +- test/moves/tar_shot.test.ts | 2 +- test/moves/taunt.test.ts | 2 +- test/moves/telekinesis.test.ts | 4 +- test/moves/tera_blast.test.ts | 6 +- test/moves/tera_starstorm.test.ts | 2 +- test/moves/throat_chop.test.ts | 2 +- test/moves/torment.test.ts | 2 +- test/moves/toxic.test.ts | 2 +- test/moves/toxic_spikes.test.ts | 5 +- test/moves/transform.test.ts | 2 +- test/moves/triple_arrows.test.ts | 6 +- test/moves/upper_hand.test.ts | 4 +- test/moves/whirlwind.test.ts | 4 +- test/moves/will_o_wisp.test.ts | 2 +- ...an-offer-you-cant-refuse-encounter.test.ts | 2 +- .../bug-type-superfan-encounter.test.ts | 2 +- .../clowning-around-encounter.test.ts | 2 +- .../dancing-lessons-encounter.test.ts | 2 +- .../fight-or-flight-encounter.test.ts | 2 +- .../fun-and-games-encounter.test.ts | 2 +- .../encounters/part-timer-encounter.test.ts | 2 +- .../the-strong-stuff-encounter.test.ts | 2 +- .../trash-to-treasure-encounter.test.ts | 2 +- .../uncommon-breed-encounter.test.ts | 2 +- test/phases/frenzy-move-reset.test.ts | 2 +- test/reload.test.ts | 2 +- test/testUtils/gameManager.ts | 5 +- test/testUtils/gameManagerUtils.ts | 3 +- test/testUtils/helpers/classicModeHelper.ts | 3 +- test/testUtils/helpers/field-helper.ts | 2 +- test/testUtils/helpers/moveHelper.ts | 8 +- test/ui/starter-select.test.ts | 2 +- 307 files changed, 2185 insertions(+), 1774 deletions(-) create mode 100644 src/@types/move-types.ts create mode 100644 src/data/moves/apply-attrs.ts create mode 100644 src/data/moves/pokemon-move.ts create mode 100644 src/data/pokemon-forms/form-change-triggers.ts create mode 100644 src/enums/ability-attr.ts create mode 100644 src/enums/ai-type.ts create mode 100644 src/enums/arena-tag-side.ts create mode 100644 src/enums/battler-index.ts create mode 100644 src/enums/battler-tag-lapse-type.ts create mode 100644 src/enums/challenge-type.ts create mode 100644 src/enums/command.ts create mode 100644 src/enums/dex-attr.ts create mode 100644 src/enums/field-position.ts create mode 100644 src/enums/form-change-item.ts create mode 100644 src/enums/game-modes.ts create mode 100644 src/enums/hit-result.ts create mode 100644 src/enums/learn-move-situation.ts create mode 100644 src/enums/learn-move-type.ts create mode 100644 src/enums/move-anims-common.ts create mode 100644 src/enums/move-result.ts create mode 100644 src/enums/move-source-type.ts create mode 100644 src/enums/trainer-variant.ts diff --git a/src/@types/move-types.ts b/src/@types/move-types.ts new file mode 100644 index 00000000000..d9a06fd20ee --- /dev/null +++ b/src/@types/move-types.ts @@ -0,0 +1,56 @@ +import type { + AttackMove, + StatusMove, + SelfStatusMove, + ChargingAttackMove, + ChargingSelfStatusMove, + MoveAttrConstructorMap, + MoveAttr, +} from "#app/data/moves/move"; + +export type MoveAttrFilter = (attr: MoveAttr) => boolean; + +export type * from "#app/data/moves/move"; + +/** + * Map of move subclass names to their respective classes. + * Does not include the ChargeMove subclasses. For that, use `ChargingMoveClassMap`. + * + * @privateremarks + * The `never` field (`declare private _: never`) in some classes is necessary + * to ensure typescript does not improperly narrow a failed `is` guard to `never`. + * + * For example, if we did not have the never, and wrote + * ``` + * function Foo(move: Move) { + * if (move.is("AttackMove")) { + * + * } else if (move.is("StatusMove")) { // typescript errors on the `is`, saying that `move` is `never` + * + * } + * ``` + */ +export type MoveClassMap = { + AttackMove: AttackMove; + StatusMove: StatusMove; + SelfStatusMove: SelfStatusMove; +}; + +/** + * Union type of all move subclass names + */ +export type MoveKindString = "AttackMove" | "StatusMove" | "SelfStatusMove"; + +/** + * Map of move attribute names to attribute instances. + */ +export type MoveAttrMap = { + [K in keyof MoveAttrConstructorMap]: InstanceType; +}; + +/** + * Union type of all move attribute names as strings. + */ +export type MoveAttrString = keyof MoveAttrMap; + +export type ChargingMove = ChargingAttackMove | ChargingSelfStatusMove; diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 7743302cf94..5586691a48d 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -80,13 +80,15 @@ import type { FixedBattleConfig } from "#app/battle"; import Battle from "#app/battle"; import { BattleType } from "#enums/battle-type"; import type { GameMode } from "#app/game-mode"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import FieldSpritePipeline from "#app/pipelines/field-sprite"; import SpritePipeline from "#app/pipelines/sprite"; import PartyExpBar from "#app/ui/party-exp-bar"; import type { TrainerSlot } from "./enums/trainer-slot"; import { trainerConfigs } from "#app/data/trainers/trainer-config"; -import Trainer, { TrainerVariant } from "#app/field/trainer"; +import Trainer from "#app/field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import type TrainerData from "#app/system/trainer-data"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; @@ -101,13 +103,12 @@ import type UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin"; import { addUiThemeOverrides } from "#app/ui/ui-theme"; import type PokemonData from "#app/system/pokemon-data"; import { Nature } from "#enums/nature"; -import type { SpeciesFormChange, SpeciesFormChangeTrigger } from "#app/data/pokemon-forms"; -import { - FormChangeItem, - pokemonFormChanges, - SpeciesFormChangeManualTrigger, - SpeciesFormChangeTimeOfDayTrigger, -} from "#app/data/pokemon-forms"; +import type { SpeciesFormChange } from "#app/data/pokemon-forms"; +import type { SpeciesFormChangeTrigger } from "./data/pokemon-forms/form-change-triggers"; +import { pokemonFormChanges } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeTimeOfDayTrigger } from "./data/pokemon-forms/form-change-triggers"; +import { SpeciesFormChangeManualTrigger } from "./data/pokemon-forms/form-change-triggers"; +import { FormChangeItem } from "#enums/form-change-item"; import { getTypeRgb } from "#app/data/type"; import { PokemonType } from "#enums/pokemon-type"; import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler"; diff --git a/src/battle.ts b/src/battle.ts index 2ebfb634751..0cf01a0873d 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import type { Command } from "./ui/command-ui-handler"; +import type { Command } from "#enums/command"; import { randomString, getEnumValues, @@ -10,7 +10,8 @@ import { randInt, randSeedFloat, } from "#app/utils/common"; -import Trainer, { TrainerVariant } from "./field/trainer"; +import Trainer from "./field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import type { GameMode } from "./game-mode"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import type { PokeballType } from "#enums/pokeball"; @@ -33,14 +34,7 @@ import { ModifierTier } from "#app/modifier/modifier-tier"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { BattleType } from "#enums/battle-type"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; - -export enum BattlerIndex { - ATTACKER = -1, - PLAYER, - PLAYER_2, - ENEMY, - ENEMY_2, -} +import { BattlerIndex } from "#enums/battler-index"; export interface TurnCommand { command: Command; diff --git a/src/constants.ts b/src/constants.ts index d3594c389b6..62056ecc0d4 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,3 +1,5 @@ +import { SpeciesId } from "#enums/species-id"; + /** The maximum size of the player's party */ export const PLAYER_PARTY_MAX_SIZE: number = 6; @@ -17,3 +19,38 @@ export const CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180 /** The raw percentage power boost for type boost items*/ export const TYPE_BOOST_ITEM_BOOST_PERCENT = 20; + +/** + * The default species that a new player can choose from + */ +export const defaultStarterSpecies: SpeciesId[] = [ + SpeciesId.BULBASAUR, + SpeciesId.CHARMANDER, + SpeciesId.SQUIRTLE, + SpeciesId.CHIKORITA, + SpeciesId.CYNDAQUIL, + SpeciesId.TOTODILE, + SpeciesId.TREECKO, + SpeciesId.TORCHIC, + SpeciesId.MUDKIP, + SpeciesId.TURTWIG, + SpeciesId.CHIMCHAR, + SpeciesId.PIPLUP, + SpeciesId.SNIVY, + SpeciesId.TEPIG, + SpeciesId.OSHAWOTT, + SpeciesId.CHESPIN, + SpeciesId.FENNEKIN, + SpeciesId.FROAKIE, + SpeciesId.ROWLET, + SpeciesId.LITTEN, + SpeciesId.POPPLIO, + SpeciesId.GROOKEY, + SpeciesId.SCORBUNNY, + SpeciesId.SOBBLE, + SpeciesId.SPRIGATITO, + SpeciesId.FUECOCO, + SpeciesId.QUAXLY, +]; + +export const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 34ae8be78b6..128e772217f 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -1,4 +1,5 @@ -import { HitResult, MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; +import { HitResult } from "#enums/hit-result"; import { BooleanHolder, NumberHolder, @@ -10,40 +11,26 @@ import { randSeedFloat, } from "#app/utils/common"; import { getPokemonNameWithAffix } from "#app/messages"; -import { BattlerTagLapseType, GroundedTag } from "#app/data/battler-tags"; +import { GroundedTag } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText, } from "#app/data/status-effect"; import { Gender } from "#app/data/gender"; -import { - AttackMove, - FlinchAttr, - OneHitKOAttr, - HitHealAttr, - StatusMove, - SelfStatusMove, - VariablePowerAttr, - applyMoveAttrs, - RandomMovesetMoveAttr, - RandomMoveAttr, - NaturePowerAttr, - CopyMoveAttr, - NeutralDamageAgainstFlyingTypeMultiplierAttr, - FixedDamageAttr, -} from "#app/data/moves/move"; +import { applyMoveAttrs } from "../moves/apply-attrs"; import { allMoves } from "../data-lists"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { BerryModifier, HitHealModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { TerrainType } from "#app/data/terrain"; import { - SpeciesFormChangeAbilityTrigger, SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger, -} from "#app/data/pokemon-forms"; +} from "../pokemon-forms/form-change-triggers"; +import { SpeciesFormChangeAbilityTrigger } from "../pokemon-forms/form-change-triggers"; import i18next from "i18next"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { BerryModifierType } from "#app/modifier/modifier-type"; import { getPokeballName } from "#app/data/pokeball"; import { BattleType } from "#enums/battle-type"; @@ -69,12 +56,13 @@ import { MoveFlags } from "#enums/MoveFlags"; import { MoveTarget } from "#enums/MoveTarget"; import { MoveCategory } from "#enums/MoveCategory"; import type { BerryType } from "#enums/berry-type"; -import { CommonAnim } from "../battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import { getBerryEffectFunc } from "../berry"; import { BerryUsedEvent } from "#app/events/battle-scene"; // Type imports -import type { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; +import type { EnemyPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "../moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; import type { Weather } from "#app/data/weather"; import type { BattlerTag } from "#app/data/battler-tags"; @@ -86,7 +74,7 @@ import type { AbAttrApplyFunc, AbAttrSuccessFunc, } from "#app/@types/ability-types"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import type Move from "#app/data/moves/move"; import type { ArenaTrapTag, SuppressAbilitiesTag } from "#app/data/arena-tag"; import { noAbilityTypeOverrideMoves } from "../moves/invalid-moves"; @@ -520,7 +508,7 @@ export class AttackTypeImmunityAbAttr extends TypeImmunityAbAttr { ): boolean { return ( move.category !== MoveCategory.STATUS && - !move.hasAttr(NeutralDamageAgainstFlyingTypeMultiplierAttr) && + !move.hasAttr("NeutralDamageAgainstFlyingTypeMultiplierAttr") && super.canApplyPreDefend(pokemon, passive, simulated, attacker, move, cancelled, args) ); } @@ -693,7 +681,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr { args.length > 0 ? (args[0] as NumberHolder).value : pokemon.getAttackTypeEffectiveness(attacker.getMoveType(move), attacker, undefined, undefined, move); - return move instanceof AttackMove && modifierValue < 2; + return move.is("AttackMove") && modifierValue < 2; } override applyPreDefend( @@ -735,7 +723,7 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr { const typeMultiplier = args[0]; return ( typeMultiplier instanceof NumberHolder && - !move?.hasAttr(FixedDamageAttr) && + !move?.hasAttr("FixedDamageAttr") && pokemon.isFullHp() && typeMultiplier.value > 0.5 ); @@ -980,7 +968,7 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr { _hitResult: HitResult | null, _args: any[], ): boolean { - return move.hasAttr(HitHealAttr); + return move.hasAttr("HitHealAttr"); } /** @@ -2061,10 +2049,10 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { */ !move.findAttr( attr => - attr instanceof RandomMovesetMoveAttr || - attr instanceof RandomMoveAttr || - attr instanceof NaturePowerAttr || - attr instanceof CopyMoveAttr, + attr.is("RandomMovesetMoveAttr") || + attr.is("RandomMoveAttr") || + attr.is("NaturePowerAttr") || + attr.is("CopyMoveAttr"), ) ) { const moveType = pokemon.getMoveType(move); @@ -2539,17 +2527,11 @@ export class AllyStatMultiplierAbAttr extends AbAttr { * @extends AbAttr */ export class ExecutedMoveAbAttr extends AbAttr { - canApplyExecutedMove( - _pokemon: Pokemon, - _simulated: boolean, - ): boolean { + canApplyExecutedMove(_pokemon: Pokemon, _simulated: boolean): boolean { return true; } - applyExecutedMove( - _pokemon: Pokemon, - _simulated: boolean, - ): void {} + applyExecutedMove(_pokemon: Pokemon, _simulated: boolean): void {} } /** @@ -2557,7 +2539,7 @@ export class ExecutedMoveAbAttr extends AbAttr { * @extends ExecutedMoveAbAttr */ export class GorillaTacticsAbAttr extends ExecutedMoveAbAttr { - constructor(showAbility: boolean = false) { + constructor(showAbility = false) { super(showAbility); } @@ -4926,13 +4908,13 @@ function getAnticipationCondition(): AbAttrCondition { } // the move's base type (not accounting for variable type changes) is super effective if ( - move.getMove() instanceof AttackMove && + move.getMove().is("AttackMove") && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent, true, undefined, move.getMove()) >= 2 ) { return true; } // move is a OHKO - if (move.getMove().hasAttr(OneHitKOAttr)) { + if (move.getMove().hasAttr("OneHitKOAttr")) { return true; } // edge case for hidden power, type is computed @@ -5001,9 +4983,9 @@ export class ForewarnAbAttr extends PostSummonAbAttr { let movePower = 0; for (const opponent of pokemon.getOpponents()) { for (const move of opponent.moveset) { - if (move?.getMove() instanceof StatusMove) { + if (move?.getMove().is("StatusMove")) { movePower = 1; - } else if (move?.getMove().hasAttr(OneHitKOAttr)) { + } else if (move?.getMove().hasAttr("OneHitKOAttr")) { movePower = 150; } else if ( move?.getMove().id === MoveId.COUNTER || @@ -5874,10 +5856,10 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { dancer.turnData.extraTurns++; const phaseManager = globalScene.phaseManager; // If the move is an AttackMove or a StatusMove the Dancer must replicate the move on the source of the Dance - if (move.getMove() instanceof AttackMove || move.getMove() instanceof StatusMove) { + if (move.getMove().is("AttackMove") || move.getMove().is("StatusMove")) { const target = this.getTarget(dancer, source, targets); phaseManager.unshiftNew("MovePhase", dancer, target, move, true, true); - } else if (move.getMove() instanceof SelfStatusMove) { + } else if (move.getMove().is("SelfStatusMove")) { // If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself phaseManager.unshiftNew("MovePhase", dancer, [dancer.getBattlerIndex()], move, true, true); } @@ -7785,7 +7767,7 @@ export function applyPreAttackAbAttrs( export function applyExecutedMoveAbAttrs( attrType: Constructor, pokemon: Pokemon, - simulated: boolean = false, + simulated = false, ...args: any[] ): void { applyAbAttrsInternal( @@ -8207,7 +8189,7 @@ export function initAbilities() { allAbilities.push( new Ability(AbilityId.NONE, 3), new Ability(AbilityId.STENCH, 3) - .attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => !move.hasAttr(FlinchAttr) && !move.hitsSubstitute(user, target) ? 10 : 0, BattlerTagType.FLINCHED), + .attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => !move.hasAttr("FlinchAttr") && !move.hitsSubstitute(user, target) ? 10 : 0, BattlerTagType.FLINCHED), new Ability(AbilityId.DRIZZLE, 3) .attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.RAIN), @@ -8514,7 +8496,7 @@ export function initAbilities() { new Ability(AbilityId.TECHNICIAN, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => { const power = new NumberHolder(move.power); - applyMoveAttrs(VariablePowerAttr, user, target, move, power); + applyMoveAttrs("VariablePowerAttr", user, target, move, power); return power.value <= 60; }, 1.5), new Ability(AbilityId.LEAF_GUARD, 4) @@ -8635,7 +8617,7 @@ export function initAbilities() { ) .edgeCase(), // Cannot recover berries used up by fling or natural gift (unimplemented) new Ability(AbilityId.TELEPATHY, 5) - .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove) + .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move.is("AttackMove")) .ignorable(), new Ability(AbilityId.MOODY, 5) .attr(MoodyAbAttr), diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 28b8c6acd41..e18ee5ac556 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -7,9 +7,9 @@ import { MoveTarget } from "#enums/MoveTarget"; import { MoveCategory } from "#enums/MoveCategory"; import { getPokemonNameWithAffix } from "#app/messages"; import type Pokemon from "#app/field/pokemon"; -import { HitResult } from "#app/field/pokemon"; +import { HitResult } from "#enums/hit-result"; import { StatusEffect } from "#enums/status-effect"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { BlockNonDirectDamageAbAttr, InfiltratorAbAttr, @@ -20,18 +20,14 @@ import { applyOnLoseAbAttrs, } from "#app/data/abilities/ability"; import { Stat } from "#enums/stat"; -import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims"; +import { CommonBattleAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import i18next from "i18next"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; - -export enum ArenaTagSide { - BOTH, - PLAYER, - ENEMY, -} +import { ArenaTagSide } from "#enums/arena-tag-side"; export abstract class ArenaTag { constructor( diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index 321d9938b2f..0b40469b255 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -1,111 +1,15 @@ import { globalScene } from "#app/global-scene"; -import { AttackMove, BeakBlastHeaderAttr, DelayedAttackAttr, SelfStatusMove } from "./moves/move"; import { allMoves } from "./data-lists"; import { MoveFlags } from "#enums/MoveFlags"; import type Pokemon from "../field/pokemon"; import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils/common"; -import type { BattlerIndex } from "../battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SubstituteTag } from "./battler-tags"; import { isNullOrUndefined } from "../utils/common"; import Phaser from "phaser"; import { EncounterAnim } from "#enums/encounter-anims"; - -export enum AnimFrameTarget { - USER, - TARGET, - GRAPHIC, -} - -enum AnimFocus { - TARGET = 1, - USER, - USER_TARGET, - SCREEN, -} - -enum AnimBlendType { - NORMAL, - ADD, - SUBTRACT, -} - -export enum ChargeAnim { - FLY_CHARGING = 1000, - BOUNCE_CHARGING, - DIG_CHARGING, - FUTURE_SIGHT_CHARGING, - DIVE_CHARGING, - SOLAR_BEAM_CHARGING, - SHADOW_FORCE_CHARGING, - SKULL_BASH_CHARGING, - FREEZE_SHOCK_CHARGING, - SKY_DROP_CHARGING, - SKY_ATTACK_CHARGING, - ICE_BURN_CHARGING, - DOOM_DESIRE_CHARGING, - RAZOR_WIND_CHARGING, - PHANTOM_FORCE_CHARGING, - GEOMANCY_CHARGING, - SHADOW_BLADE_CHARGING, - SOLAR_BLADE_CHARGING, - BEAK_BLAST_CHARGING, - METEOR_BEAM_CHARGING, - ELECTRO_SHOT_CHARGING, -} - -export enum CommonAnim { - USE_ITEM = 2000, - HEALTH_UP, - TERASTALLIZE, - POISON = 2010, - TOXIC, - PARALYSIS, - SLEEP, - FROZEN, - BURN, - CONFUSION, - ATTRACT, - BIND, - WRAP, - CURSE_NO_GHOST, - LEECH_SEED, - FIRE_SPIN, - PROTECT, - COVET, - WHIRLPOOL, - BIDE, - SAND_TOMB, - QUICK_GUARD, - WIDE_GUARD, - CURSE, - MAGMA_STORM, - CLAMP, - SNAP_TRAP, - THUNDER_CAGE, - INFESTATION, - ORDER_UP_CURLY, - ORDER_UP_DROOPY, - ORDER_UP_STRETCHY, - RAGING_BULL_FIRE, - RAGING_BULL_WATER, - SALT_CURE, - POWDER, - SUNNY = 2100, - RAIN, - SANDSTORM, - HAIL, - SNOW, - WIND, - HEAVY_RAIN, - HARSH_SUN, - STRONG_WINDS, - MISTY_TERRAIN = 2110, - ELECTRIC_TERRAIN, - GRASSY_TERRAIN, - PSYCHIC_TERRAIN, - LOCK_ON = 2120, -} +import { AnimBlendType, AnimFrameTarget, AnimFocus, ChargeAnim, CommonAnim } from "#enums/move-anims-common"; export class AnimConfig { public id: number; @@ -531,7 +435,7 @@ export function initMoveAnim(move: MoveId): Promise { if (moveAnims.get(move) !== null) { const chargeAnimSource = allMoves[move].isChargingMove() ? allMoves[move] - : (allMoves[move].getAttrs(DelayedAttackAttr)[0] ?? allMoves[move].getAttrs(BeakBlastHeaderAttr)[0]); + : (allMoves[move].getAttrs("DelayedAttackAttr")[0] ?? allMoves[move].getAttrs("BeakBlastHeaderAttr")[0]); if (chargeAnimSource && chargeAnims.get(chargeAnimSource.chargeAnim) === null) { return; } @@ -542,12 +446,11 @@ export function initMoveAnim(move: MoveId): Promise { } } else { moveAnims.set(move, null); - const defaultMoveAnim = - allMoves[move] instanceof AttackMove - ? MoveId.TACKLE - : allMoves[move] instanceof SelfStatusMove - ? MoveId.FOCUS_ENERGY - : MoveId.TAIL_WHIP; + const defaultMoveAnim = allMoves[move].is("AttackMove") + ? MoveId.TACKLE + : allMoves[move].is("SelfStatusMove") + ? MoveId.FOCUS_ENERGY + : MoveId.TAIL_WHIP; const fetchAnimAndResolve = (move: MoveId) => { globalScene @@ -570,7 +473,7 @@ export function initMoveAnim(move: MoveId): Promise { } const chargeAnimSource = allMoves[move].isChargingMove() ? allMoves[move] - : (allMoves[move].getAttrs(DelayedAttackAttr)[0] ?? allMoves[move].getAttrs(BeakBlastHeaderAttr)[0]); + : (allMoves[move].getAttrs("DelayedAttackAttr")[0] ?? allMoves[move].getAttrs("BeakBlastHeaderAttr")[0]); if (chargeAnimSource) { initMoveChargeAnim(chargeAnimSource.chargeAnim).then(() => resolve()); } else { @@ -703,7 +606,7 @@ export function loadMoveAnimAssets(moveIds: MoveId[], startLoad?: boolean): Prom for (const moveId of moveIds) { const chargeAnimSource = allMoves[moveId].isChargingMove() ? allMoves[moveId] - : (allMoves[moveId].getAttrs(DelayedAttackAttr)[0] ?? allMoves[moveId].getAttrs(BeakBlastHeaderAttr)[0]); + : (allMoves[moveId].getAttrs("DelayedAttackAttr")[0] ?? allMoves[moveId].getAttrs("BeakBlastHeaderAttr")[0]); if (chargeAnimSource) { const moveChargeAnims = chargeAnims.get(chargeAnimSource.chargeAnim); moveAnimations.push(moveChargeAnims instanceof AnimConfig ? moveChargeAnims : moveChargeAnims![0]); // TODO: is the bang correct? diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index d4f62237446..ffa179c6aab 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -9,23 +9,20 @@ import { ReverseDrainAbAttr, } from "#app/data/abilities/ability"; import { allAbilities } from "./data-lists"; -import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "#app/data/battle-anims"; +import { CommonBattleAnim, MoveChargeAnim } from "#app/data/battle-anims"; +import { ChargeAnim, CommonAnim } from "#enums/move-anims-common"; import type Move from "#app/data/moves/move"; -import { - applyMoveAttrs, - ConsecutiveUseDoublePowerAttr, - HealOnAllyAttr, - StatusCategoryOnAllyAttr, -} from "#app/data/moves/move"; +import { applyMoveAttrs } from "./moves/apply-attrs"; import { allMoves } from "./data-lists"; import { MoveFlags } from "#enums/MoveFlags"; import { MoveCategory } from "#enums/MoveCategory"; -import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeAbilityTrigger } from "./pokemon-forms/form-change-triggers"; import { getStatusEffectHealText } from "#app/data/status-effect"; import { TerrainType } from "#app/data/terrain"; import { PokemonType } from "#enums/pokemon-type"; import type Pokemon from "#app/field/pokemon"; -import { HitResult, MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; +import { HitResult } from "#enums/hit-result"; import { getPokemonNameWithAffix } from "#app/messages"; import type { MoveEffectPhase } from "#app/phases/move-effect-phase"; import type { MovePhase } from "#app/phases/move-phase"; @@ -41,19 +38,7 @@ import { EFFECTIVE_STATS, getStatKey, Stat, type BattleStat, type EffectiveStat import { StatusEffect } from "#enums/status-effect"; import { WeatherType } from "#enums/weather-type"; import { isNullOrUndefined } from "#app/utils/common"; - -export enum BattlerTagLapseType { - FAINT, - MOVE, - PRE_MOVE, - AFTER_MOVE, - MOVE_EFFECT, - TURN_END, - HIT, - /** Tag lapses AFTER_HIT, applying its effects even if the user faints */ - AFTER_HIT, - CUSTOM, -} +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; export class BattlerTag { public tagType: BattlerTagType; @@ -2804,8 +2789,8 @@ export class HealBlockTag extends MoveRestrictionBattlerTag { */ override isMoveTargetRestricted(move: MoveId, user: Pokemon, target: Pokemon) { const moveCategory = new NumberHolder(allMoves[move].category); - applyMoveAttrs(StatusCategoryOnAllyAttr, user, target, allMoves[move], moveCategory); - return allMoves[move].hasAttr(HealOnAllyAttr) && moveCategory.value === MoveCategory.STATUS; + applyMoveAttrs("StatusCategoryOnAllyAttr", user, target, allMoves[move], moveCategory); + return allMoves[move].hasAttr("HealOnAllyAttr") && moveCategory.value === MoveCategory.STATUS; } /** @@ -3141,7 +3126,7 @@ export class TormentTag extends MoveRestrictionBattlerTag { // This checks for locking / momentum moves like Rollout and Hydro Cannon + if the user is under the influence of BattlerTagType.FRENZY // Because Uproar's unique behavior is not implemented, it does not check for Uproar. Torment has been marked as partial in moves.ts const moveObj = allMoves[lastMove.move]; - const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || user.getTag(BattlerTagType.FRENZY); + const isUnaffected = moveObj.hasAttr("ConsecutiveUseDoublePowerAttr") || user.getTag(BattlerTagType.FRENZY); const validLastMoveResult = lastMove.result === MoveResult.SUCCESS || lastMove.result === MoveResult.MISS; return lastMove.move === move && validLastMoveResult && lastMove.move !== MoveId.STRUGGLE && !isUnaffected; } diff --git a/src/data/berry.ts b/src/data/berry.ts index 52ea1c44391..df500fa0609 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -1,6 +1,6 @@ import { getPokemonNameWithAffix } from "../messages"; import type Pokemon from "../field/pokemon"; -import { HitResult } from "../field/pokemon"; +import { HitResult } from "#enums/hit-result"; import { getStatusEffectHealText } from "./status-effect"; import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils/common"; import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./abilities/ability"; diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 8dd303c34fd..8bdccb6d5fd 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -2,17 +2,18 @@ import { BooleanHolder, type NumberHolder, randSeedItem } from "#app/utils/commo import { deepCopy } from "#app/utils/data"; import i18next from "i18next"; import type { DexAttrProps, GameData } from "#app/system/game-data"; -import { defaultStarterSpecies } from "#app/system/game-data"; +import { defaultStarterSpecies } from "#app/constants"; import type PokemonSpecies from "#app/data/pokemon-species"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; import { speciesStarterCosts } from "#app/data/balance/starters"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "./moves/pokemon-move"; import type { FixedBattleConfig } from "#app/battle"; import { getRandomTrainerFunc } from "#app/battle"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { BattleType } from "#enums/battle-type"; -import Trainer, { TrainerVariant } from "#app/field/trainer"; +import Trainer from "#app/field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import { PokemonType } from "#enums/pokemon-type"; import { Challenges } from "#enums/challenges"; import { SpeciesId } from "#enums/species-id"; @@ -24,93 +25,12 @@ import { ModifierTier } from "#app/modifier/modifier-tier"; import { globalScene } from "#app/global-scene"; import { pokemonFormChanges } from "./pokemon-forms"; import { pokemonEvolutions } from "./balance/pokemon-evolutions"; +import { ChallengeType } from "#enums/challenge-type"; +import type { MoveSourceType } from "#enums/move-source-type"; /** A constant for the default max cost of the starting party before a run */ const DEFAULT_PARTY_MAX_COST = 10; -/** - * An enum for all the challenge types. The parameter entries on these describe the - * parameters to use when calling the applyChallenges function. - */ -export enum ChallengeType { - /** - * Challenges which modify what starters you can choose - * @see {@link Challenge.applyStarterChoice} - */ - STARTER_CHOICE, - /** - * Challenges which modify how many starter points you have - * @see {@link Challenge.applyStarterPoints} - */ - STARTER_POINTS, - /** - * Challenges which modify how many starter points you have - * @see {@link Challenge.applyStarterPointCost} - */ - STARTER_COST, - /** - * Challenges which modify your starters in some way - * @see {@link Challenge.applyStarterModify} - */ - STARTER_MODIFY, - /** - * Challenges which limit which pokemon you can have in battle. - * @see {@link Challenge.applyPokemonInBattle} - */ - POKEMON_IN_BATTLE, - /** - * Adds or modifies the fixed battles in a run - * @see {@link Challenge.applyFixedBattle} - */ - FIXED_BATTLES, - /** - * Modifies the effectiveness of Type matchups in battle - * @see {@linkcode Challenge.applyTypeEffectiveness} - */ - TYPE_EFFECTIVENESS, - /** - * Modifies what level the AI pokemon are. UNIMPLEMENTED. - */ - AI_LEVEL, - /** - * Modifies how many move slots the AI has. UNIMPLEMENTED. - */ - AI_MOVE_SLOTS, - /** - * Modifies if a pokemon has its passive. UNIMPLEMENTED. - */ - PASSIVE_ACCESS, - /** - * Modifies the game mode settings in some way. UNIMPLEMENTED. - */ - GAME_MODE_MODIFY, - /** - * Modifies what level AI pokemon can access a move. UNIMPLEMENTED. - */ - MOVE_ACCESS, - /** - * Modifies what weight AI pokemon have when generating movesets. UNIMPLEMENTED. - */ - MOVE_WEIGHT, - /** - * Modifies what the pokemon stats for Flip Stat Mode. - */ - FLIP_STAT, -} - -/** - * Used for challenge types that modify movesets, these denote the various sources of moves for pokemon. - */ -export enum MoveSourceType { - LEVEL_UP, // Currently unimplemented for move access - RELEARNER, // Relearner moves currently unimplemented - COMMON_TM, - GREAT_TM, - ULTRA_TM, - COMMON_EGG, - RARE_EGG, -} - /** * A challenge object. Exists only to serve as a base class. */ diff --git a/src/data/moves/apply-attrs.ts b/src/data/moves/apply-attrs.ts new file mode 100644 index 00000000000..98e7b6d791f --- /dev/null +++ b/src/data/moves/apply-attrs.ts @@ -0,0 +1,58 @@ +/** + * Module holding functions to apply move attributes. + * Must not import anything that is not a type. + */ +import type Pokemon from "#app/field/pokemon"; +import type { default as Move, MoveAttr } from "./move"; +import type { ChargingMove } from "#app/@types/move-types"; +import type { MoveAttrFilter, MoveAttrString } from "#app/@types/move-types"; + +function applyMoveAttrsInternal( + attrFilter: MoveAttrFilter, + user: Pokemon | null, + target: Pokemon | null, + move: Move, + args: any[], +): void { + move.attrs.filter(attr => attrFilter(attr)).forEach(attr => attr.apply(user, target, move, args)); +} + +function applyMoveChargeAttrsInternal( + attrFilter: MoveAttrFilter, + user: Pokemon | null, + target: Pokemon | null, + move: ChargingMove, + args: any[], +): void { + move.chargeAttrs.filter(attr => attrFilter(attr)).forEach(attr => attr.apply(user, target, move, args)); +} + +export function applyMoveAttrs( + attrType: MoveAttrString, + user: Pokemon | null, + target: Pokemon | null, + move: Move, + ...args: any[] +): void { + applyMoveAttrsInternal((attr: MoveAttr) => attr.is(attrType), user, target, move, args); +} + +export function applyFilteredMoveAttrs( + attrFilter: MoveAttrFilter, + user: Pokemon, + target: Pokemon | null, + move: Move, + ...args: any[] +): void { + applyMoveAttrsInternal(attrFilter, user, target, move, args); +} + +export function applyMoveChargeAttrs( + attrType: MoveAttrString, + user: Pokemon | null, + target: Pokemon | null, + move: ChargingMove, + ...args: any[] +): void { + applyMoveChargeAttrsInternal((attr: MoveAttr) => attr.is(attrType), user, target, move, args); +} diff --git a/src/data/moves/move-utils.ts b/src/data/moves/move-utils.ts index 3323d6f4a0c..20723ab0347 100644 --- a/src/data/moves/move-utils.ts +++ b/src/data/moves/move-utils.ts @@ -1,5 +1,14 @@ -import { MoveTarget } from "#enums/MoveTarget"; +import type Pokemon from "#app/field/pokemon"; +import type { BattlerIndex } from "#enums/battler-index"; +import type { MoveId } from "#enums/move-id"; +import type { MoveTargetSet, UserMoveConditionFunc } from "./move"; import type Move from "./move"; +import { NumberHolder, isNullOrUndefined } from "#app/utils/common"; +import { MoveTarget } from "#enums/MoveTarget"; +import { PokemonType } from "#enums/pokemon-type"; +import { allMoves } from "#app/data/data-lists"; +import { applyMoveAttrs } from "./apply-attrs"; +import { BattlerTagType } from "#enums/battler-tag-type"; /** * Return whether the move targets the field @@ -18,3 +27,88 @@ export function isFieldTargeted(move: Move): boolean { } return false; } + +export function getMoveTargets(user: Pokemon, move: MoveId, replaceTarget?: MoveTarget): MoveTargetSet { + const variableTarget = new NumberHolder(0); + user.getOpponents(false).forEach(p => applyMoveAttrs("VariableTargetAttr", user, p, allMoves[move], variableTarget)); + + let moveTarget: MoveTarget | undefined; + if (allMoves[move].hasAttr("VariableTargetAttr")) { + moveTarget = variableTarget.value; + } else if (replaceTarget !== undefined) { + moveTarget = replaceTarget; + } else if (move) { + moveTarget = allMoves[move].moveTarget; + } else if (move === undefined) { + moveTarget = MoveTarget.NEAR_ENEMY; + } + const opponents = user.getOpponents(false); + + let set: Pokemon[] = []; + let multiple = false; + const ally: Pokemon | undefined = user.getAlly(); + + switch (moveTarget) { + case MoveTarget.USER: + case MoveTarget.PARTY: + set = [user]; + break; + case MoveTarget.NEAR_OTHER: + case MoveTarget.OTHER: + case MoveTarget.ALL_NEAR_OTHERS: + case MoveTarget.ALL_OTHERS: + set = !isNullOrUndefined(ally) ? opponents.concat([ally]) : opponents; + multiple = moveTarget === MoveTarget.ALL_NEAR_OTHERS || moveTarget === MoveTarget.ALL_OTHERS; + break; + case MoveTarget.NEAR_ENEMY: + case MoveTarget.ALL_NEAR_ENEMIES: + case MoveTarget.ALL_ENEMIES: + case MoveTarget.ENEMY_SIDE: + set = opponents; + multiple = moveTarget !== MoveTarget.NEAR_ENEMY; + break; + case MoveTarget.RANDOM_NEAR_ENEMY: + set = [opponents[user.randBattleSeedInt(opponents.length)]]; + break; + case MoveTarget.ATTACKER: + return { targets: [-1 as BattlerIndex], multiple: false }; + case MoveTarget.NEAR_ALLY: + case MoveTarget.ALLY: + set = !isNullOrUndefined(ally) ? [ally] : []; + break; + case MoveTarget.USER_OR_NEAR_ALLY: + case MoveTarget.USER_AND_ALLIES: + case MoveTarget.USER_SIDE: + set = !isNullOrUndefined(ally) ? [user, ally] : [user]; + multiple = moveTarget !== MoveTarget.USER_OR_NEAR_ALLY; + break; + case MoveTarget.ALL: + case MoveTarget.BOTH_SIDES: + set = (!isNullOrUndefined(ally) ? [user, ally] : [user]).concat(opponents); + multiple = true; + break; + case MoveTarget.CURSE: + { + const extraTargets = !isNullOrUndefined(ally) ? [ally] : []; + set = user.getTypes(true).includes(PokemonType.GHOST) ? opponents.concat(extraTargets) : [user]; + } + break; + } + + return { + targets: set + .filter(p => p?.isActive(true)) + .map(p => p.getBattlerIndex()) + .filter(t => t !== undefined), + multiple, + }; +} + +export const frenzyMissFunc: UserMoveConditionFunc = (user: Pokemon, move: Move) => { + while (user.getMoveQueue().length && user.getMoveQueue()[0].move === move.id) { + user.getMoveQueue().shift(); + } + user.removeTag(BattlerTagType.FRENZY); // FRENZY tag should be disrupted on miss/no effect + + return true; +}; diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 976c0cd7d97..57660b51391 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -1,4 +1,5 @@ -import { ChargeAnim, MoveChargeAnim } from "../battle-anims"; +import { MoveChargeAnim } from "../battle-anims"; +import { ChargeAnim } from "#enums/move-anims-common"; import { CommandedTag, EncoreTag, @@ -14,14 +15,11 @@ import { import { getPokemonNameWithAffix } from "../../messages"; import type { AttackMoveResult, TurnMove } from "../../field/pokemon"; import type Pokemon from "../../field/pokemon"; -import { - EnemyPokemon, - FieldPosition, - HitResult, - MoveResult, - PlayerPokemon, - PokemonMove, -} from "../../field/pokemon"; +import type { EnemyPokemon } from "#app/field/pokemon"; +import { PokemonMove } from "./pokemon-move"; +import { MoveResult } from "#enums/move-result"; +import { HitResult } from "#enums/hit-result"; +import { FieldPosition } from "#enums/field-position"; import { getNonVolatileStatusEffects, getStatusEffectHealText, @@ -32,7 +30,8 @@ import { PokemonType } from "#enums/pokemon-type"; import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor, randSeedFloat } from "#app/utils/common"; import { WeatherType } from "#enums/weather-type"; import type { ArenaTrapTag } from "../arena-tag"; -import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag"; +import { WeakenMoveTypeTag } from "../arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { AllyMoveCategoryPowerBoostAbAttr, applyAbAttrs, @@ -75,11 +74,11 @@ import { PokemonMultiHitModifier, PreserveBerryModifier, } from "../../modifier/modifier"; -import type { BattlerIndex } from "../../battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { BattleType } from "#enums/battle-type"; import { TerrainType } from "../terrain"; import { ModifierPoolType } from "#app/modifier/modifier-type"; -import { Command } from "../../ui/command-ui-handler"; +import { Command } from "#enums/command"; import i18next from "i18next"; import type { Localizable } from "#app/@types/locales"; import { getBerryEffectFunc } from "../berry"; @@ -105,9 +104,10 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { SwitchPhase } from "#app/phases/switch-phase"; import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; -import { SpeciesFormChangeRevertWeatherFormTrigger } from "../pokemon-forms"; +import { SpeciesFormChangeRevertWeatherFormTrigger } from "../pokemon-forms/form-change-triggers"; import type { GameMode } from "#app/game-mode"; -import { applyChallenges, ChallengeType } from "../challenge"; +import { applyChallenges } from "../challenge"; +import { ChallengeType } from "#enums/challenge-type"; import { SwitchType } from "#enums/switch-type"; import { StatusEffect } from "#enums/status-effect"; import { globalScene } from "#app/global-scene"; @@ -123,11 +123,14 @@ import { MoveEffectTrigger } from "#enums/MoveEffectTrigger"; import { MultiHitType } from "#enums/MultiHitType"; import { invalidAssistMoves, invalidCopycatMoves, invalidMetronomeMoves, invalidMirrorMoveMoves, invalidSleepTalkMoves } from "./invalid-moves"; import { SelectBiomePhase } from "#app/phases/select-biome-phase"; +import { ChargingMove, MoveAttrMap, MoveAttrString, MoveKindString, MoveClassMap } from "#app/@types/move-types"; +import { applyMoveAttrs } from "./apply-attrs"; +import { frenzyMissFunc, getMoveTargets } from "./move-utils"; type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean; -type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean; +export type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean; -export default class Move implements Localizable { +export default abstract class Move implements Localizable { public id: MoveId; public name: string; private _type: PokemonType; @@ -147,6 +150,17 @@ export default class Move implements Localizable { private flags: number = 0; private nameAppend: string = ""; + /** + * Check if the move is of the given subclass without requiring `instanceof`. + * + * ⚠️ Does _not_ work for {@linkcode ChargingAttackMove} and {@linkcode ChargingSelfStatusMove} subclasses. For those, + * use {@linkcode isChargingMove} instead. + * + * @param moveKind - The string name of the move to check against + * @returns Whether this move is of the provided type. + */ + public abstract is(moveKind: K): this is MoveClassMap[K]; + constructor(id: MoveId, type: PokemonType, category: MoveCategory, defaultMoveTarget: MoveTarget, power: number, accuracy: number, pp: number, chance: number, priority: number, generation: number) { this.id = id; this._type = type; @@ -188,8 +202,12 @@ 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: Constructor): T[] { - return this.attrs.filter((a): a is T => a instanceof attrType); + getAttrs(attrType: T): (MoveAttrMap[T])[] { + const targetAttr = MoveAttrs[attrType]; + if (!targetAttr) { + return []; + } + return this.attrs.filter((a): a is MoveAttrMap[T] => a instanceof targetAttr); } /** @@ -197,8 +215,13 @@ export default class Move implements Localizable { * @param attrType any attribute that extends {@linkcode MoveAttr} * @returns true if the move has attribute `attrType` */ - hasAttr(attrType: Constructor): boolean { - return this.attrs.some((attr) => attr instanceof attrType); + hasAttr(attrType: MoveAttrString): boolean { + const targetAttr = MoveAttrs[attrType]; + // Guard against invalid attrType + if (!targetAttr) { + return false; + } + return this.attrs.some((attr) => attr instanceof targetAttr); } /** @@ -768,14 +791,14 @@ export default class Move implements Localizable { calculateBattleAccuracy(user: Pokemon, target: Pokemon, simulated: boolean = false) { const moveAccuracy = new NumberHolder(this.accuracy); - applyMoveAttrs(VariableAccuracyAttr, user, target, this, moveAccuracy); + applyMoveAttrs("VariableAccuracyAttr", user, target, this, moveAccuracy); applyPreDefendAbAttrs(WonderSkinAbAttr, target, user, this, { value: false }, simulated, moveAccuracy); if (moveAccuracy.value === -1) { return moveAccuracy.value; } - const isOhko = this.hasAttr(OneHitKOAccuracyAttr); + const isOhko = this.hasAttr("OneHitKOAccuracyAttr"); if (!isOhko) { globalScene.applyModifiers(PokemonMoveAccuracyBoosterModifier, user.isPlayer(), user, moveAccuracy); @@ -815,7 +838,7 @@ export default class Move implements Localizable { applyPreAttackAbAttrs(MoveTypeChangeAbAttr, source, target, this, true, typeChangeHolder, typeChangeMovePowerMultiplier); const sourceTeraType = source.getTeraType(); - if (source.isTerastallized && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr(MultiHitAttr) && !globalScene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) { + if (source.isTerastallized && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr("MultiHitAttr") && !globalScene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) { power.value = 60; } @@ -847,9 +870,9 @@ export default class Move implements Localizable { power.value *= typeBoost.boostValue; } - applyMoveAttrs(VariablePowerAttr, source, target, this, power); + applyMoveAttrs("VariablePowerAttr", source, target, this, power); - if (!this.hasAttr(TypelessAttr)) { + if (!this.hasAttr("TypelessAttr")) { globalScene.arena.applyTags(WeakenMoveTypeTag, simulated, typeChangeHolder.value, power); globalScene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, typeChangeHolder.value, power); } @@ -864,7 +887,7 @@ export default class Move implements Localizable { getPriority(user: Pokemon, simulated: boolean = true) { const priority = new NumberHolder(this.priority); - applyMoveAttrs(IncrementMovePriorityAttr, user, null, this, priority); + applyMoveAttrs("IncrementMovePriorityAttr", user, null, this, priority); applyAbAttrs(ChangeMovePriorityAbAttr, user, null, simulated, this, priority); return priority.value; @@ -885,7 +908,7 @@ export default class Move implements Localizable { } else if (this.id === MoveId.TRIPLE_KICK) { effectivePower = 47.07; } else { - const multiHitAttr = this.getAttrs(MultiHitAttr)[0]; + const multiHitAttr = this.getAttrs("MultiHitAttr")[0]; if (multiHitAttr) { effectivePower = multiHitAttr.calculateExpectedHitCount(this) * this.power; } else { @@ -898,10 +921,10 @@ export default class Move implements Localizable { // These are intentionally not else-if statements even though there are no // pokemon moves that have more than one of these attributes. This allows // the function to future proof new moves / custom move behaviors. - if (this.hasAttr(DelayedAttackAttr)) { + if (this.hasAttr("DelayedAttackAttr")) { numTurns += 2; } - if (this.hasAttr(RechargeAttr)) { + if (this.hasAttr("RechargeAttr")) { numTurns += 1; } if (this.isChargingMove()) { @@ -927,10 +950,10 @@ export default class Move implements Localizable { const isMultiTarget = multiple && targets.length > 1; // ...cannot enhance multi-hit or sacrificial moves - const exceptAttrs: Constructor[] = [ - MultiHitAttr, - SacrificialAttr, - SacrificialAttrOnHit + const exceptAttrs: MoveAttrString[] = [ + "MultiHitAttr", + "SacrificialAttr", + "SacrificialAttrOnHit" ]; // ...and cannot enhance these specific moves @@ -956,6 +979,13 @@ export default class Move implements Localizable { } export class AttackMove extends Move { + /** This field does not exist at runtime and must not be used. + * Its sole purpose is to ensure that typescript is able to properly narrow when the `is` method is called. + */ + declare private _: never; + override is(moveKind: K): this is MoveClassMap[K] { + return moveKind === "AttackMove"; + } constructor(id: MoveId, type: PokemonType, category: MoveCategory, power: number, accuracy: number, pp: number, chance: number, priority: number, generation: number) { super(id, type, category, MoveTarget.NEAR_OTHER, power, accuracy, pp, chance, priority, generation); @@ -985,7 +1015,7 @@ export class AttackMove extends Move { const [ thisStat, offStat ]: EffectiveStat[] = this.category === MoveCategory.PHYSICAL ? [ Stat.ATK, Stat.SPATK ] : [ Stat.SPATK, Stat.ATK ]; const statHolder = new NumberHolder(user.getEffectiveStat(thisStat, target)); const offStatValue = user.getEffectiveStat(offStat, target); - applyMoveAttrs(VariableAtkAttr, user, target, move, statHolder); + applyMoveAttrs("VariableAtkAttr", user, target, move, statHolder); const statRatio = offStatValue / statHolder.value; if (statRatio <= 0.75) { attackScore *= 2; @@ -994,7 +1024,7 @@ export class AttackMove extends Move { } const power = new NumberHolder(this.calculateEffectivePower()); - applyMoveAttrs(VariablePowerAttr, user, target, move, power); + applyMoveAttrs("VariablePowerAttr", user, target, move, power); attackScore += Math.floor(power.value / 5); @@ -1003,20 +1033,42 @@ export class AttackMove extends Move { } export class StatusMove extends Move { + /** This field does not exist at runtime and must not be used. + * Its sole purpose is to ensure that typescript is able to properly narrow when the `is` method is called. + */ + declare private _: never; constructor(id: MoveId, type: PokemonType, accuracy: number, pp: number, chance: number, priority: number, generation: number) { super(id, type, MoveCategory.STATUS, MoveTarget.NEAR_OTHER, -1, accuracy, pp, chance, priority, generation); } + + override is(moveKind: K): this is MoveClassMap[K] { + return moveKind === "StatusMove"; + } } export class SelfStatusMove extends Move { + /** This field does not exist at runtime and must not be used. + * Its sole purpose is to ensure that typescript is able to properly narrow when the `is` method is called. + */ + declare private _: never; constructor(id: MoveId, type: PokemonType, accuracy: number, pp: number, chance: number, priority: number, generation: number) { super(id, type, MoveCategory.STATUS, MoveTarget.USER, -1, accuracy, pp, chance, priority, generation); } + + override is(moveKind: K): this is MoveClassMap[K] { + return moveKind === "SelfStatusMove"; + } } -type SubMove = new (...args: any[]) => Move; +// TODO: Figure out how to improve the signature of this so that +// the `ChargeMove` function knows that the argument `Base` is a specific subclass of move that cannot +// be abstract. +// Right now, I only know how to do this by using the type conjunction (the & operators) +type SubMove = new (...args: any[]) => Move & { + is(moveKind: K): this is MoveClassMap[K]; +}; -function ChargeMove(Base: TBase) { +function ChargeMove(Base: TBase, nameAppend: string) { return class extends Base { /** The animation to play during the move's charging phase */ public readonly chargeAnim: ChargeAnim = ChargeAnim[`${MoveId[this.id]}_CHARGING`]; @@ -1060,8 +1112,12 @@ function ChargeMove(Base: TBase) { * @returns Array of attributes that match `attrType`, or an empty array if * no matches are found. */ - getChargeAttrs(attrType: Constructor): T[] { - return this.chargeAttrs.filter((attr): attr is T => attr instanceof attrType); + getChargeAttrs(attrType: T): (MoveAttrMap[T])[] { + const targetAttr = MoveAttrs[attrType]; + if (!targetAttr) { + return []; + } + return this.chargeAttrs.filter((attr): attr is MoveAttrMap[T] => attr instanceof targetAttr); } /** @@ -1069,8 +1125,12 @@ function ChargeMove(Base: TBase) { * @param attrType any attribute that extends {@linkcode MoveAttr} * @returns `true` if a matching attribute is found; `false` otherwise */ - hasChargeAttr(attrType: Constructor): boolean { - return this.chargeAttrs.some((attr) => attr instanceof attrType); + hasChargeAttr(attrType: T): boolean { + const targetAttr = MoveAttrs[attrType]; + if (!targetAttr) { + return false; + } + return this.chargeAttrs.some((attr) => attr instanceof targetAttr); } /** @@ -1088,10 +1148,8 @@ function ChargeMove(Base: TBase) { }; } -export class ChargingAttackMove extends ChargeMove(AttackMove) {} -export class ChargingSelfStatusMove extends ChargeMove(SelfStatusMove) {} - -export type ChargingMove = ChargingAttackMove | ChargingSelfStatusMove; +export class ChargingAttackMove extends ChargeMove(AttackMove, "ChargingAttackMove") {} +export class ChargingSelfStatusMove extends ChargeMove(SelfStatusMove, "ChargingSelfStatusMove") {} /** * Base class defining all {@linkcode Move} Attributes @@ -1102,6 +1160,22 @@ export abstract class MoveAttr { /** Should this {@linkcode Move} target the user? */ public selfTarget: boolean; + /** + * Return whether this attribute is of the given type. + * + * @remarks + * Used to avoid requring the caller to have imported the specific attribute type, avoiding circular dependencies. + * @param attr - The attribute to check against + * @returns Whether the attribute is an instance of the given type. + */ + public is(attr: T): this is MoveAttrMap[T] { + const targetAttr = MoveAttrs[attr]; + if (!targetAttr) { + return false; + } + return this instanceof targetAttr; + } + constructor(selfTarget: boolean = false) { this.selfTarget = selfTarget; } @@ -1268,7 +1342,7 @@ export class MoveEffectAttr extends MoveAttr { applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, !showAbility, moveChance, move); - if ((!move.hasAttr(FlinchAttr) || moveChance.value <= move.chance) && !move.hasAttr(SecretPowerAttr)) { + if ((!move.hasAttr("FlinchAttr") || moveChance.value <= move.chance) && !move.hasAttr("SecretPowerAttr")) { const userSide = user.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; globalScene.arena.applyTagsForSide(ArenaTagType.WATER_FIRE_PLEDGE, userSide, false, moveChance); } @@ -2331,7 +2405,7 @@ export class MultiHitAttr extends MoveAttr { */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const hitType = new NumberHolder(this.intrinsicMultiHitType); - applyMoveAttrs(ChangeMultiHitTypeAttr, user, target, move, hitType); + applyMoveAttrs("ChangeMultiHitTypeAttr", user, target, move, hitType); this.multiHitType = hitType.value; (args[0] as NumberHolder).value = this.getHitCount(user, target); @@ -3032,7 +3106,11 @@ export class WeatherInstantChargeAttr extends InstantChargeAttr { } export class OverrideMoveEffectAttr extends MoveAttr { - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + /** This field does not exist at runtime and must not be used. + * Its sole purpose is to ensure that typescript is able to properly narrow when the `is` method is called. + */ + declare private _: never; + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { return true; } } @@ -3114,7 +3192,7 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr { const allyMovePhase = globalScene.phaseManager.findPhase((phase) => phase.is("MovePhase") && phase.pokemon.isPlayer() === user.isPlayer()); if (allyMovePhase) { const allyMove = allyMovePhase.move.getMove(); - if (allyMove !== move && allyMove.hasAttr(AwaitCombinedPledgeAttr)) { + if (allyMove !== move && allyMove.hasAttr("AwaitCombinedPledgeAttr")) { [ user, allyMovePhase.pokemon ].forEach((p) => p.turnData.combiningPledge = move.id); // "{userPokemonName} is waiting for {allyPokemonName}'s move..." @@ -3235,22 +3313,22 @@ export class StatStageChangeAttr extends MoveEffectAttr { switch (stat) { case Stat.ATK: if (this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL); + noEffect = !user.getMoveset().find(m => {const mv = m.getMove(); return mv.is("AttackMove") && mv.category === MoveCategory.PHYSICAL;} ); } break; case Stat.DEF: if (!this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL); + noEffect = !user.getMoveset().find(m => {const mv = m.getMove(); return mv.is("AttackMove") && mv.category === MoveCategory.PHYSICAL;} ); } break; case Stat.SPATK: if (this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL); + noEffect = !user.getMoveset().find(m => {const mv = m.getMove(); return mv.is("AttackMove") && mv.category === MoveCategory.PHYSICAL;} ); } break; case Stat.SPDEF: if (!this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL); + noEffect = !user.getMoveset().find(m => {const mv = m.getMove(); return mv.is("AttackMove") && mv.category === MoveCategory.PHYSICAL;} ); } break; } @@ -5410,7 +5488,7 @@ export class FrenzyAttr extends MoveEffectAttr { new Array(turnCount).fill(null).map(() => user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true })); user.addTag(BattlerTagType.FRENZY, turnCount, move.id, user.id); } else { - applyMoveAttrs(AddBattlerTagAttr, user, target, move, args); + applyMoveAttrs("AddBattlerTagAttr", user, target, move, args); user.lapseTag(BattlerTagType.FRENZY); // if FRENZY is already in effect (moveQueue.length > 0), lapse the tag } @@ -5418,15 +5496,6 @@ export class FrenzyAttr extends MoveEffectAttr { } } -export const frenzyMissFunc: UserMoveConditionFunc = (user: Pokemon, move: Move) => { - while (user.getMoveQueue().length && user.getMoveQueue()[0].move === move.id) { - user.getMoveQueue().shift(); - } - user.removeTag(BattlerTagType.FRENZY); // FRENZY tag should be disrupted on miss/no effect - - return true; -}; - /** * Attribute that grants {@link https://bulbapedia.bulbagarden.net/wiki/Semi-invulnerable_turn | semi-invulnerability} to the user during * the associated move's charging phase. Should only be used for {@linkcode ChargingMove | ChargingMoves} as a `chargeAttr`. @@ -5781,7 +5850,7 @@ export class ProtectAttr extends AddBattlerTagAttr { while (moveHistory.length) { turnMove = moveHistory.shift(); - if (!allMoves[turnMove?.move ?? MoveId.NONE].hasAttr(ProtectAttr) || turnMove?.result !== MoveResult.SUCCESS) { + if (!allMoves[turnMove?.move ?? MoveId.NONE].hasAttr("ProtectAttr") || turnMove?.result !== MoveResult.SUCCESS) { break; } timesUsed++; @@ -5912,7 +5981,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { } if ((move.chance < 0 || move.chance === 100 || user.randBattleSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { - const side = ((this.selfSideTarget ? user : target).isPlayer() !== (move.hasAttr(AddArenaTrapTagAttr) && target === user)) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + const side = ((this.selfSideTarget ? user : target).isPlayer() !== (move.hasAttr("AddArenaTrapTagAttr") && target === user)) ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; globalScene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, side); return true; } @@ -6376,7 +6445,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { return (user, target, move) => { const switchOutTarget = (this.selfSwitch ? user : target); const player = switchOutTarget.isPlayer(); - const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH); + const forceSwitchAttr = move.getAttrs("ForceSwitchOutAttr").find(attr => attr.switchType === SwitchType.FORCE_SWITCH); if (!this.selfSwitch) { if (move.hitsSubstitute(user, target)) { @@ -7945,58 +8014,6 @@ const attackedByItemMessageFunc = (user: Pokemon, target: Pokemon, move: Move) = return message; }; -export type MoveAttrFilter = (attr: MoveAttr) => boolean; - -function applyMoveAttrsInternal( - attrFilter: MoveAttrFilter, - user: Pokemon | null, - target: Pokemon | null, - move: Move, - args: any[], -): void { - move.attrs.filter((attr) => attrFilter(attr)).forEach((attr) => attr.apply(user, target, move, args)); -} - -function applyMoveChargeAttrsInternal( - attrFilter: MoveAttrFilter, - user: Pokemon | null, - target: Pokemon | null, - move: ChargingMove, - args: any[], -): void { - move.chargeAttrs.filter((attr) => attrFilter(attr)).forEach((attr) => attr.apply(user, target, move, args)); -} - -export function applyMoveAttrs( - attrType: Constructor, - user: Pokemon | null, - target: Pokemon | null, - move: Move, - ...args: any[] -): void { - applyMoveAttrsInternal((attr: MoveAttr) => attr instanceof attrType, user, target, move, args); -} - -export function applyFilteredMoveAttrs( - attrFilter: MoveAttrFilter, - user: Pokemon, - target: Pokemon | null, - move: Move, - ...args: any[] -): void { - applyMoveAttrsInternal(attrFilter, user, target, move, args); -} - -export function applyMoveChargeAttrs( - attrType: Constructor, - user: Pokemon | null, - target: Pokemon | null, - move: ChargingMove, - ...args: any[] -): void { - applyMoveChargeAttrsInternal((attr: MoveAttr) => attr instanceof attrType, user, target, move, args); -} - export class MoveCondition { protected func: MoveConditionFunc; @@ -8175,73 +8192,232 @@ export type MoveTargetSet = { multiple: boolean; }; -export function getMoveTargets(user: Pokemon, move: MoveId, replaceTarget?: MoveTarget): MoveTargetSet { - const variableTarget = new NumberHolder(0); - user.getOpponents(false).forEach(p => applyMoveAttrs(VariableTargetAttr, user, p, allMoves[move], variableTarget)); +/** + * Map of Move attributes to their respective classes. Used for instanceof checks. + */ +const MoveAttrs = Object.freeze({ + MoveEffectAttr, + MoveHeaderAttr, + MessageHeaderAttr, + AddBattlerTagAttr, + AddBattlerTagHeaderAttr, + BeakBlastHeaderAttr, + PreMoveMessageAttr, + PreUseInterruptAttr, + RespectAttackTypeImmunityAttr, + IgnoreOpponentStatStagesAttr, + HighCritAttr, + CritOnlyAttr, + FixedDamageAttr, + UserHpDamageAttr, + TargetHalfHpDamageAttr, + MatchHpAttr, + CounterDamageAttr, + LevelDamageAttr, + RandomLevelDamageAttr, + ModifiedDamageAttr, + SurviveDamageAttr, + SplashAttr, + CelebrateAttr, + RecoilAttr, + SacrificialAttr, + SacrificialAttrOnHit, + HalfSacrificialAttr, + AddSubstituteAttr, + HealAttr, + PartyStatusCureAttr, + FlameBurstAttr, + SacrificialFullRestoreAttr, + IgnoreWeatherTypeDebuffAttr, + WeatherHealAttr, + PlantHealAttr, + SandHealAttr, + BoostHealAttr, + HealOnAllyAttr, + HitHealAttr, + IncrementMovePriorityAttr, + MultiHitAttr, + ChangeMultiHitTypeAttr, + WaterShurikenMultiHitTypeAttr, + StatusEffectAttr, + MultiStatusEffectAttr, + PsychoShiftEffectAttr, + StealHeldItemChanceAttr, + RemoveHeldItemAttr, + EatBerryAttr, + StealEatBerryAttr, + HealStatusEffectAttr, + BypassSleepAttr, + BypassBurnDamageReductionAttr, + WeatherChangeAttr, + ClearWeatherAttr, + TerrainChangeAttr, + ClearTerrainAttr, + OneHitKOAttr, + InstantChargeAttr, + WeatherInstantChargeAttr, + OverrideMoveEffectAttr, + DelayedAttackAttr, + AwaitCombinedPledgeAttr, + StatStageChangeAttr, + SecretPowerAttr, + PostVictoryStatStageChangeAttr, + AcupressureStatStageChangeAttr, + GrowthStatStageChangeAttr, + CutHpStatStageBoostAttr, + OrderUpStatBoostAttr, + CopyStatsAttr, + InvertStatsAttr, + ResetStatsAttr, + SwapStatStagesAttr, + HpSplitAttr, + VariablePowerAttr, + LessPPMorePowerAttr, + MovePowerMultiplierAttr, + BeatUpAttr, + DoublePowerChanceAttr, + ConsecutiveUsePowerMultiplierAttr, + ConsecutiveUseDoublePowerAttr, + ConsecutiveUseMultiBasePowerAttr, + WeightPowerAttr, + ElectroBallPowerAttr, + GyroBallPowerAttr, + LowHpPowerAttr, + CompareWeightPowerAttr, + HpPowerAttr, + OpponentHighHpPowerAttr, + FirstAttackDoublePowerAttr, + TurnDamagedDoublePowerAttr, + MagnitudePowerAttr, + AntiSunlightPowerDecreaseAttr, + FriendshipPowerAttr, + RageFistPowerAttr, + PositiveStatStagePowerAttr, + PunishmentPowerAttr, + PresentPowerAttr, + WaterShurikenPowerAttr, + SpitUpPowerAttr, + SwallowHealAttr, + MultiHitPowerIncrementAttr, + LastMoveDoublePowerAttr, + CombinedPledgePowerAttr, + CombinedPledgeStabBoostAttr, + RoundPowerAttr, + CueNextRoundAttr, + StatChangeBeforeDmgCalcAttr, + SpectralThiefAttr, + VariableAtkAttr, + TargetAtkUserAtkAttr, + DefAtkAttr, + VariableDefAttr, + DefDefAttr, + VariableAccuracyAttr, + ThunderAccuracyAttr, + StormAccuracyAttr, + AlwaysHitMinimizeAttr, + ToxicAccuracyAttr, + BlizzardAccuracyAttr, + VariableMoveCategoryAttr, + PhotonGeyserCategoryAttr, + TeraMoveCategoryAttr, + TeraBlastPowerAttr, + StatusCategoryOnAllyAttr, + ShellSideArmCategoryAttr, + VariableMoveTypeAttr, + FormChangeItemTypeAttr, + TechnoBlastTypeAttr, + AuraWheelTypeAttr, + RagingBullTypeAttr, + IvyCudgelTypeAttr, + WeatherBallTypeAttr, + TerrainPulseTypeAttr, + HiddenPowerTypeAttr, + TeraBlastTypeAttr, + TeraStarstormTypeAttr, + MatchUserTypeAttr, + CombinedPledgeTypeAttr, + VariableMoveTypeMultiplierAttr, + NeutralDamageAgainstFlyingTypeMultiplierAttr, + IceNoEffectTypeAttr, + FlyingTypeMultiplierAttr, + VariableMoveTypeChartAttr, + FreezeDryAttr, + OneHitKOAccuracyAttr, + SheerColdAccuracyAttr, + MissEffectAttr, + NoEffectAttr, + TypelessAttr, + BypassRedirectAttr, + FrenzyAttr, + SemiInvulnerableAttr, + LeechSeedAttr, + FallDownAttr, + GulpMissileTagAttr, + JawLockAttr, + CurseAttr, + LapseBattlerTagAttr, + RemoveBattlerTagAttr, + FlinchAttr, + ConfuseAttr, + RechargeAttr, + TrapAttr, + ProtectAttr, + IgnoreAccuracyAttr, + FaintCountdownAttr, + RemoveAllSubstitutesAttr, + HitsTagAttr, + HitsTagForDoubleDamageAttr, + AddArenaTagAttr, + RemoveArenaTagsAttr, + AddArenaTrapTagAttr, + AddArenaTrapTagHitAttr, + RemoveArenaTrapAttr, + RemoveScreensAttr, + SwapArenaTagsAttr, + AddPledgeEffectAttr, + RevivalBlessingAttr, + ForceSwitchOutAttr, + ChillyReceptionAttr, + RemoveTypeAttr, + CopyTypeAttr, + CopyBiomeTypeAttr, + ChangeTypeAttr, + AddTypeAttr, + FirstMoveTypeAttr, + CallMoveAttr, + RandomMoveAttr, + RandomMovesetMoveAttr, + NaturePowerAttr, + CopyMoveAttr, + RepeatMoveAttr, + ReducePpMoveAttr, + AttackReducePpMoveAttr, + MovesetCopyMoveAttr, + SketchAttr, + AbilityChangeAttr, + AbilityCopyAttr, + AbilityGiveAttr, + SwitchAbilitiesAttr, + SuppressAbilitiesAttr, + TransformAttr, + SwapStatAttr, + ShiftStatAttr, + AverageStatsAttr, + MoneyAttr, + DestinyBondAttr, + AddBattlerTagIfBoostedAttr, + StatusIfBoostedAttr, + LastResortAttr, + VariableTargetAttr, + AfterYouAttr, + ForceLastAttr, + HitsSameTypeAttr, + ResistLastMoveTypeAttr, + ExposedMoveAttr, +}); - let moveTarget: MoveTarget | undefined; - if (allMoves[move].hasAttr(VariableTargetAttr)) { - moveTarget = variableTarget.value; - } else if (replaceTarget !== undefined) { - moveTarget = replaceTarget; - } else if (move) { - moveTarget = allMoves[move].moveTarget; - } else if (move === undefined) { - moveTarget = MoveTarget.NEAR_ENEMY; - } - const opponents = user.getOpponents(false); - - let set: Pokemon[] = []; - let multiple = false; - const ally: Pokemon | undefined = user.getAlly(); - - switch (moveTarget) { - case MoveTarget.USER: - case MoveTarget.PARTY: - set = [ user ]; - break; - case MoveTarget.NEAR_OTHER: - case MoveTarget.OTHER: - case MoveTarget.ALL_NEAR_OTHERS: - case MoveTarget.ALL_OTHERS: - set = !isNullOrUndefined(ally) ? (opponents.concat([ ally ])) : opponents; - multiple = moveTarget === MoveTarget.ALL_NEAR_OTHERS || moveTarget === MoveTarget.ALL_OTHERS; - break; - case MoveTarget.NEAR_ENEMY: - case MoveTarget.ALL_NEAR_ENEMIES: - case MoveTarget.ALL_ENEMIES: - case MoveTarget.ENEMY_SIDE: - set = opponents; - multiple = moveTarget !== MoveTarget.NEAR_ENEMY; - break; - case MoveTarget.RANDOM_NEAR_ENEMY: - set = [ opponents[user.randBattleSeedInt(opponents.length)] ]; - break; - case MoveTarget.ATTACKER: - return { targets: [ -1 as BattlerIndex ], multiple: false }; - case MoveTarget.NEAR_ALLY: - case MoveTarget.ALLY: - set = !isNullOrUndefined(ally) ? [ ally ] : []; - break; - case MoveTarget.USER_OR_NEAR_ALLY: - case MoveTarget.USER_AND_ALLIES: - case MoveTarget.USER_SIDE: - set = !isNullOrUndefined(ally) ? [ user, ally ] : [ user ]; - multiple = moveTarget !== MoveTarget.USER_OR_NEAR_ALLY; - break; - case MoveTarget.ALL: - case MoveTarget.BOTH_SIDES: - set = (!isNullOrUndefined(ally) ? [ user, ally ] : [ user ]).concat(opponents); - multiple = true; - break; - case MoveTarget.CURSE: - const extraTargets = !isNullOrUndefined(ally) ? [ ally ] : []; - set = user.getTypes(true).includes(PokemonType.GHOST) ? (opponents.concat(extraTargets)) : [ user ]; - break; - } - - return { targets: set.filter(p => p?.isActive(true)).map(p => p.getBattlerIndex()).filter(t => t !== undefined), multiple }; -} +/** Map of of move attribute names to their constructors */ +export type MoveAttrConstructorMap = typeof MoveAttrs; export const selfStatLowerMoves: MoveId[] = []; @@ -11255,7 +11431,7 @@ export function initMoves() { .attr(StatusEffectAttr, StatusEffect.TOXIC) ); allMoves.map(m => { - if (m.getAttrs(StatStageChangeAttr).some(a => a.selfTarget && a.stages < 0)) { + if (m.getAttrs("StatStageChangeAttr").some(a => a.selfTarget && a.stages < 0)) { selfStatLowerMoves.push(m.id); } }); diff --git a/src/data/moves/pokemon-move.ts b/src/data/moves/pokemon-move.ts new file mode 100644 index 00000000000..da46caa819f --- /dev/null +++ b/src/data/moves/pokemon-move.ts @@ -0,0 +1,93 @@ +import type Pokemon from "#app/field/pokemon"; +import { toDmgValue } from "#app/utils/common"; +import type { MoveId } from "#enums/move-id"; +import { allMoves } from "../data-lists"; +import type Move from "./move"; + +/** + * Wrapper class for the {@linkcode Move} class for Pokemon to interact with. + * These are the moves assigned to a {@linkcode Pokemon} object. + * It links to {@linkcode Move} class via the move ID. + * Compared to {@linkcode Move}, this class also tracks things like + * PP Ups recieved, PP used, etc. + * @see {@linkcode isUsable} - checks if move is restricted, out of PP, or not implemented. + * @see {@linkcode getMove} - returns {@linkcode Move} object by looking it up via ID. + * @see {@linkcode usePp} - removes a point of PP from the move. + * @see {@linkcode getMovePp} - returns amount of PP a move currently has. + * @see {@linkcode getPpRatio} - returns the current PP amount / max PP amount. + * @see {@linkcode getName} - returns name of {@linkcode Move}. + **/ +export class PokemonMove { + public moveId: MoveId; + public ppUsed: number; + public ppUp: number; + public virtual: boolean; + + /** + * If defined and nonzero, overrides the maximum PP of the move (e.g., due to move being copied by Transform). + * This also nullifies all effects of `ppUp`. + */ + public maxPpOverride?: number; + + constructor(moveId: MoveId, ppUsed = 0, ppUp = 0, virtual = false, maxPpOverride?: number) { + this.moveId = moveId; + this.ppUsed = ppUsed; + this.ppUp = ppUp; + this.virtual = virtual; + this.maxPpOverride = maxPpOverride; + } + + /** + * Checks whether the move can be selected or performed by a Pokemon, without consideration for the move's targets. + * The move is unusable if it is out of PP, restricted by an effect, or unimplemented. + * + * @param pokemon - {@linkcode Pokemon} that would be using this move + * @param ignorePp - If `true`, skips the PP check + * @param ignoreRestrictionTags - If `true`, skips the check for move restriction tags (see {@link MoveRestrictionBattlerTag}) + * @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`. + */ + isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean { + if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) { + return false; + } + + if (this.getMove().name.endsWith(" (N)")) { + return false; + } + + return ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1; + } + + getMove(): Move { + return allMoves[this.moveId]; + } + + /** + * Sets {@link ppUsed} for this move and ensures the value does not exceed {@link getMovePp} + * @param count Amount of PP to use + */ + usePp(count = 1) { + this.ppUsed = Math.min(this.ppUsed + count, this.getMovePp()); + } + + getMovePp(): number { + return this.maxPpOverride || this.getMove().pp + this.ppUp * toDmgValue(this.getMove().pp / 5); + } + + getPpRatio(): number { + return 1 - this.ppUsed / this.getMovePp(); + } + + getName(): string { + return this.getMove().name; + } + + /** + * Copies an existing move or creates a valid {@linkcode PokemonMove} object from json representing one + * @param source The data for the move to copy; can be a {@linkcode PokemonMove} or JSON object representing one + * @returns A valid {@linkcode PokemonMove} object + */ + static loadMove(source: PokemonMove | any): PokemonMove { + return new PokemonMove(source.moveId, source.ppUsed, source.ppUp, source.virtual, source.maxPpOverride); + } +} diff --git a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts index 82fbc0efd69..2213dc4afaa 100644 --- a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts +++ b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts @@ -7,7 +7,8 @@ import { transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; +import { EnemyPokemon } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import type { BerryModifierType, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; @@ -25,7 +26,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species"; import { MoveId } from "#enums/move-id"; import { BattlerTagType } from "#enums/battler-tag-type"; import { randInt } from "#app/utils/common"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { applyModifierTypeToPlayerPokemon, catchPokemon, diff --git a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts index 938a136bced..c318efc0cb3 100644 --- a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts +++ b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts @@ -24,7 +24,7 @@ import { TrainerType } from "#enums/trainer-type"; import { SpeciesId } from "#enums/species-id"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { MoveId } from "#enums/move-id"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index 19c4948aeab..a81dcc841b7 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -37,11 +37,11 @@ import { UiMode } from "#enums/ui-mode"; import i18next from "i18next"; import type { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler"; import type { PlayerPokemon } from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { Ability } from "#app/data/abilities/ability-class"; import { BerryModifier } from "#app/modifier/modifier"; import { BerryType } from "#enums/berry-type"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { EncounterBattleAnim } from "#app/data/battle-anims"; import { MoveCategory } from "#enums/MoveCategory"; diff --git a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts index 80465e1d20c..a74980919d6 100644 --- a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts +++ b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; import { EncounterBattleAnim } from "#app/data/battle-anims"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; @@ -23,7 +23,8 @@ import { getPokemonSpecies } from "#app/data/pokemon-species"; import { TrainerSlot } from "#enums/trainer-slot"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; +import { EnemyPokemon } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants"; import { modifierTypes } from "#app/modifier/modifier-type"; import PokemonData from "#app/system/pokemon-data"; diff --git a/src/data/mystery-encounters/encounters/field-trip-encounter.ts b/src/data/mystery-encounters/encounters/field-trip-encounter.ts index 2cd6123838b..82fbfd51eec 100644 --- a/src/data/mystery-encounters/encounters/field-trip-encounter.ts +++ b/src/data/mystery-encounters/encounters/field-trip-encounter.ts @@ -7,7 +7,8 @@ import { setEncounterExp, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; -import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; +import type { PlayerPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import { modifierTypes } from "#app/modifier/modifier-type"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index 8b0e5a08020..d42778cb17c 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -24,9 +24,9 @@ import { SpeciesId } from "#enums/species-id"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Gender } from "#app/data/gender"; import { PokemonType } from "#enums/pokemon-type"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { MoveId } from "#enums/move-id"; import { EncounterBattleAnim } from "#app/data/battle-anims"; import { WeatherType } from "#enums/weather-type"; diff --git a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts index a52641f857d..456562ca70e 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -13,7 +13,7 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst import { TrainerSlot } from "#enums/trainer-slot"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { FieldPosition } from "#app/field/pokemon"; +import { FieldPosition } from "#enums/field-position"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; @@ -25,7 +25,7 @@ import { getPokemonNameWithAffix } from "#app/messages"; import { PlayerGender } from "#enums/player-gender"; import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; import { addPokeballOpenParticles } from "#app/field/anims"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { modifierTypes } from "#app/modifier/modifier-type"; import { Nature } from "#enums/nature"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants"; diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index 6ecce46ae24..a84b0af30ed 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -33,7 +33,8 @@ import { } from "#app/utils/common"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; +import { EnemyPokemon } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import type { PokemonHeldItemModifier } from "#app/modifier/modifier"; import { HiddenAbilityRateBoosterModifier, diff --git a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts index 009639291de..8eea0623cd4 100644 --- a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts +++ b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts @@ -11,7 +11,7 @@ import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encount import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; const OPTION_1_REQUIRED_MOVE = MoveId.SURF; const OPTION_2_REQUIRED_MOVE = MoveId.FLY; diff --git a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts index bb1529e3695..1ecd73143fc 100644 --- a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts +++ b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts @@ -21,8 +21,9 @@ import { import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { Nature } from "#enums/nature"; import { MoveId } from "#enums/move-id"; -import { BattlerIndex } from "#app/battle"; -import { AiType, PokemonMove } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; +import { AiType } from "#enums/ai-type"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index be347fb0035..a3eb78f479e 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -17,11 +17,11 @@ import { getPokemonSpecies } from "#app/data/pokemon-species"; import { SpeciesId } from "#enums/species-id"; import { Nature } from "#enums/nature"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { modifyPlayerPokemonBST } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { MoveId } from "#enums/move-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; diff --git a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts index 4b17260098f..91754629821 100644 --- a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts @@ -23,7 +23,7 @@ import { Nature } from "#enums/nature"; import { PokemonType } from "#enums/pokemon-type"; import { BerryType } from "#enums/berry-type"; import { Stat } from "#enums/stat"; -import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeAbilityTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/abilities/ability"; import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index b17a39ae694..9ab91f439bf 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -12,7 +12,7 @@ import { speciesStarterCosts } from "#app/data/balance/starters"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; import type { PokemonHeldItemModifier } from "#app/modifier/modifier"; -import { AbilityAttr } from "#app/system/game-data"; +import { AbilityAttr } from "#enums/ability-attr"; import PokemonData from "#app/system/pokemon-data"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { isNullOrUndefined, randSeedShuffle } from "#app/utils/common"; diff --git a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts index a0051058d02..8bcd024de5c 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -24,8 +24,8 @@ import i18next from "#app/plugins/i18n"; import { ModifierTier } from "#app/modifier/modifier-tier"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { MoveId } from "#enums/move-id"; -import { BattlerIndex } from "#app/battle"; -import { PokemonMove } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants"; import { randSeedInt } from "#app/utils/common"; diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index 411ecdec080..c48f93a9a9d 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -10,7 +10,7 @@ import { import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import type Pokemon from "#app/field/pokemon"; import type { EnemyPokemon } from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { globalScene } from "#app/global-scene"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; @@ -29,8 +29,7 @@ import { import PokemonData from "#app/system/pokemon-data"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common"; import type { MoveId } from "#enums/move-id"; -import { BattlerIndex } from "#app/battle"; -import { SelfStatusMove } from "#app/data/moves/move"; +import { BattlerIndex } from "#enums/battler-index"; import { PokeballType } from "#enums/pokeball"; import { BattlerTagType } from "#enums/battler-tag-type"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; @@ -175,7 +174,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder. // Check what type of move the egg move is to determine target const pokemonMove = new PokemonMove(eggMove); const move = pokemonMove.getMove(); - const target = move instanceof SelfStatusMove ? BattlerIndex.ENEMY : BattlerIndex.PLAYER; + const target = move.is("SelfStatusMove") ? BattlerIndex.ENEMY : BattlerIndex.PLAYER; encounter.startOfBattleEffects.push({ sourceBattlerIndex: BattlerIndex.ENEMY, diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 2b1f775b78e..fe1911c9007 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -16,7 +16,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils/common"; import type PokemonSpecies from "#app/data/pokemon-species"; import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species"; diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index 88d9ba402a9..bca34be723b 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -2,7 +2,9 @@ import { globalScene } from "#app/global-scene"; import { allAbilities } from "../data-lists"; import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { Nature } from "#enums/nature"; -import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms"; +import { pokemonFormChanges } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeItemTrigger } from "../pokemon-forms/form-change-triggers"; +import { FormChangeItem } from "#enums/form-change-item"; import { StatusEffect } from "#enums/status-effect"; import { PokemonType } from "#enums/pokemon-type"; import { WeatherType } from "#enums/weather-type"; diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index e305252ed0f..6510e32fe76 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -1,5 +1,6 @@ import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; -import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; +import type { PlayerPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "../moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils/common"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; @@ -20,11 +21,11 @@ import { StatusEffectRequirement, WaveRangeRequirement, } from "./mystery-encounter-requirements"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; -import type { GameModes } from "#app/game-mode"; +import type { GameModes } from "#enums/game-modes"; import type { EncounterAnim } from "#enums/encounter-anims"; import type { Challenges } from "#enums/challenges"; import { globalScene } from "#app/global-scene"; diff --git a/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts b/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts index 7698be7b15d..c0e45d5401c 100644 --- a/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts +++ b/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts @@ -1,6 +1,6 @@ import type { MoveId } from "#enums/move-id"; import type { PlayerPokemon } from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { isNullOrUndefined } from "#app/utils/common"; import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { globalScene } from "#app/global-scene"; diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index b86cbaa18c9..69984229681 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -1,5 +1,5 @@ import type Battle from "#app/battle"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattleType } from "#enums/battle-type"; import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes"; import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option"; @@ -8,9 +8,12 @@ import { WEIGHT_INCREMENT_ON_SPAWN_MISS, } from "#app/data/mystery-encounters/mystery-encounters"; import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; -import type { AiType, PlayerPokemon } from "#app/field/pokemon"; +import type { PlayerPokemon } from "#app/field/pokemon"; +import type { AiType } from "#enums/ai-type"; import type Pokemon from "#app/field/pokemon"; -import { EnemyPokemon, FieldPosition, PokemonMove } from "#app/field/pokemon"; +import { EnemyPokemon } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; +import { FieldPosition } from "#enums/field-position"; import type { CustomModifierSettings, ModifierType } from "#app/modifier/modifier-type"; import { getPartyLuckValue, @@ -30,7 +33,8 @@ import type { BattlerTagType } from "#enums/battler-tag-type"; import { BiomeId } from "#enums/biome-id"; import type { TrainerType } from "#enums/trainer-type"; import i18next from "i18next"; -import Trainer, { TrainerVariant } from "#app/field/trainer"; +import Trainer from "#app/field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import type { Gender } from "#app/data/gender"; import type { Nature } from "#enums/nature"; import type { MoveId } from "#enums/move-id"; diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 47eb355c8b6..ea129454034 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -1,139 +1,30 @@ -import { PokemonFormChangeItemModifier } from "../modifier/modifier"; import type Pokemon from "../field/pokemon"; -import { StatusEffect } from "#enums/status-effect"; import { allMoves } from "./data-lists"; import { MoveCategory } from "#enums/MoveCategory"; import type { Constructor, nil } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import type { TimeOfDay } from "#enums/time-of-day"; -import { getPokemonNameWithAffix } from "#app/messages"; -import i18next from "i18next"; import { WeatherType } from "#enums/weather-type"; -import { Challenges } from "#app/enums/challenges"; import { SpeciesFormKey } from "#enums/species-form-key"; import { globalScene } from "#app/global-scene"; - -export enum FormChangeItem { - NONE, - - ABOMASITE, - ABSOLITE, - AERODACTYLITE, - AGGRONITE, - ALAKAZITE, - ALTARIANITE, - AMPHAROSITE, - AUDINITE, - BANETTITE, - BEEDRILLITE, - BLASTOISINITE, - BLAZIKENITE, - CAMERUPTITE, - CHARIZARDITE_X, - CHARIZARDITE_Y, - DIANCITE, - GALLADITE, - GARCHOMPITE, - GARDEVOIRITE, - GENGARITE, - GLALITITE, - GYARADOSITE, - HERACRONITE, - HOUNDOOMINITE, - KANGASKHANITE, - LATIASITE, - LATIOSITE, - LOPUNNITE, - LUCARIONITE, - MANECTITE, - MAWILITE, - MEDICHAMITE, - METAGROSSITE, - MEWTWONITE_X, - MEWTWONITE_Y, - PIDGEOTITE, - PINSIRITE, - RAYQUAZITE, - SABLENITE, - SALAMENCITE, - SCEPTILITE, - SCIZORITE, - SHARPEDONITE, - SLOWBRONITE, - STEELIXITE, - SWAMPERTITE, - TYRANITARITE, - VENUSAURITE, - - BLUE_ORB = 50, - RED_ORB, - ADAMANT_CRYSTAL, - LUSTROUS_GLOBE, - GRISEOUS_CORE, - REVEAL_GLASS, - MAX_MUSHROOMS, - DARK_STONE, - LIGHT_STONE, - PRISON_BOTTLE, - RUSTED_SWORD, - RUSTED_SHIELD, - ICY_REINS_OF_UNITY, - SHADOW_REINS_OF_UNITY, - ULTRANECROZIUM_Z, - - SHARP_METEORITE = 100, - HARD_METEORITE, - SMOOTH_METEORITE, - GRACIDEA, - SHOCK_DRIVE, - BURN_DRIVE, - CHILL_DRIVE, - DOUSE_DRIVE, - N_SOLARIZER, - N_LUNARIZER, - WELLSPRING_MASK, - HEARTHFLAME_MASK, - CORNERSTONE_MASK, - FIST_PLATE, - SKY_PLATE, - TOXIC_PLATE, - EARTH_PLATE, - STONE_PLATE, - INSECT_PLATE, - SPOOKY_PLATE, - IRON_PLATE, - FLAME_PLATE, - SPLASH_PLATE, - MEADOW_PLATE, - ZAP_PLATE, - MIND_PLATE, - ICICLE_PLATE, - DRACO_PLATE, - DREAD_PLATE, - PIXIE_PLATE, - BLANK_PLATE, // TODO: Find a potential use for this - LEGEND_PLATE, // TODO: Find a potential use for this - FIGHTING_MEMORY, - FLYING_MEMORY, - POISON_MEMORY, - GROUND_MEMORY, - ROCK_MEMORY, - BUG_MEMORY, - GHOST_MEMORY, - STEEL_MEMORY, - FIRE_MEMORY, - WATER_MEMORY, - GRASS_MEMORY, - ELECTRIC_MEMORY, - PSYCHIC_MEMORY, - ICE_MEMORY, - DRAGON_MEMORY, - DARK_MEMORY, - FAIRY_MEMORY, - NORMAL_MEMORY, // TODO: Find a potential use for this -} +import { FormChangeItem } from "#enums/form-change-item"; +import { + MeloettaFormChangePostMoveTrigger, + SpeciesDefaultFormMatchTrigger, + SpeciesFormChangeAbilityTrigger, + SpeciesFormChangeActiveTrigger, + SpeciesFormChangeCompoundTrigger, + SpeciesFormChangeItemTrigger, + SpeciesFormChangeLapseTeraTrigger, + SpeciesFormChangeManualTrigger, + SpeciesFormChangeMoveLearnedTrigger, + SpeciesFormChangePreMoveTrigger, + SpeciesFormChangeRevertWeatherFormTrigger, + SpeciesFormChangeTeraTrigger, + type SpeciesFormChangeTrigger, + SpeciesFormChangeWeatherTrigger, +} from "./pokemon-forms/form-change-triggers"; export type SpeciesFormChangeConditionPredicate = (p: Pokemon) => boolean; export type SpeciesFormChangeConditionEnforceFunc = (p: Pokemon) => void; @@ -214,347 +105,6 @@ export class SpeciesFormChangeCondition { } } -export abstract class SpeciesFormChangeTrigger { - public description = ""; - - canChange(_pokemon: Pokemon): boolean { - return true; - } - - hasTriggerType(triggerType: Constructor): boolean { - return this instanceof triggerType; - } -} - -export class SpeciesFormChangeManualTrigger extends SpeciesFormChangeTrigger {} - -export class SpeciesFormChangeAbilityTrigger extends SpeciesFormChangeTrigger { - public description: string = i18next.t("pokemonEvolutions:Forms.ability"); -} - -export class SpeciesFormChangeCompoundTrigger { - public description = ""; - public triggers: SpeciesFormChangeTrigger[]; - - constructor(...triggers: SpeciesFormChangeTrigger[]) { - this.triggers = triggers; - this.description = this.triggers - .filter(trigger => trigger?.description?.length > 0) - .map(trigger => trigger.description) - .join(", "); - } - - canChange(pokemon: Pokemon): boolean { - for (const trigger of this.triggers) { - if (!trigger.canChange(pokemon)) { - return false; - } - } - - return true; - } - - hasTriggerType(triggerType: Constructor): boolean { - return !!this.triggers.find(t => t.hasTriggerType(triggerType)); - } -} - -export class SpeciesFormChangeItemTrigger extends SpeciesFormChangeTrigger { - public item: FormChangeItem; - public active: boolean; - - constructor(item: FormChangeItem, active = true) { - super(); - this.item = item; - this.active = active; - this.description = this.active - ? i18next.t("pokemonEvolutions:Forms.item", { - item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`), - }) - : i18next.t("pokemonEvolutions:Forms.deactivateItem", { - item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`), - }); - } - - canChange(pokemon: Pokemon): boolean { - return !!globalScene.findModifier( - m => - m instanceof PokemonFormChangeItemModifier && - m.pokemonId === pokemon.id && - m.formChangeItem === this.item && - m.active === this.active, - ); - } -} - -export class SpeciesFormChangeTimeOfDayTrigger extends SpeciesFormChangeTrigger { - public timesOfDay: TimeOfDay[]; - - constructor(...timesOfDay: TimeOfDay[]) { - super(); - this.timesOfDay = timesOfDay; - this.description = i18next.t("pokemonEvolutions:Forms.timeOfDay"); - } - - canChange(_pokemon: Pokemon): boolean { - return this.timesOfDay.indexOf(globalScene.arena.getTimeOfDay()) > -1; - } -} - -export class SpeciesFormChangeActiveTrigger extends SpeciesFormChangeTrigger { - public active: boolean; - - constructor(active = false) { - super(); - this.active = active; - this.description = this.active - ? i18next.t("pokemonEvolutions:Forms.enter") - : i18next.t("pokemonEvolutions:Forms.leave"); - } - - canChange(pokemon: Pokemon): boolean { - return pokemon.isActive(true) === this.active; - } -} - -export class SpeciesFormChangeStatusEffectTrigger extends SpeciesFormChangeTrigger { - public statusEffects: StatusEffect[]; - public invert: boolean; - - constructor(statusEffects: StatusEffect | StatusEffect[], invert = false) { - super(); - if (!Array.isArray(statusEffects)) { - statusEffects = [statusEffects]; - } - this.statusEffects = statusEffects; - this.invert = invert; - this.description = i18next.t("pokemonEvolutions:Forms.statusEffect"); - } - - canChange(pokemon: Pokemon): boolean { - return this.statusEffects.indexOf(pokemon.status?.effect || StatusEffect.NONE) > -1 !== this.invert; - } -} - -export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigger { - public move: MoveId; - public known: boolean; - - constructor(move: MoveId, known = true) { - super(); - this.move = move; - this.known = known; - const moveKey = MoveId[this.move] - .split("_") - .filter(f => f) - .map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase())) - .join("") as unknown as string; - this.description = known - ? i18next.t("pokemonEvolutions:Forms.moveLearned", { - move: i18next.t(`move:${moveKey}.name`), - }) - : i18next.t("pokemonEvolutions:Forms.moveForgotten", { - move: i18next.t(`move:${moveKey}.name`), - }); - } - - canChange(pokemon: Pokemon): boolean { - return !!pokemon.moveset.filter(m => m.moveId === this.move).length === this.known; - } -} - -export abstract class SpeciesFormChangeMoveTrigger extends SpeciesFormChangeTrigger { - public movePredicate: (m: MoveId) => boolean; - public used: boolean; - - constructor(move: MoveId | ((m: MoveId) => boolean), used = true) { - super(); - this.movePredicate = typeof move === "function" ? move : (m: MoveId) => m === move; - this.used = used; - } -} - -export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigger { - description = i18next.t("pokemonEvolutions:Forms.preMove"); - - canChange(pokemon: Pokemon): boolean { - const command = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; - return !!command?.move && this.movePredicate(command.move.move) === this.used; - } -} - -export class SpeciesFormChangePostMoveTrigger extends SpeciesFormChangeMoveTrigger { - description = i18next.t("pokemonEvolutions:Forms.postMove"); - - canChange(pokemon: Pokemon): boolean { - return ( - pokemon.summonData && !!pokemon.getLastXMoves(1).filter(m => this.movePredicate(m.move)).length === this.used - ); - } -} - -export class MeloettaFormChangePostMoveTrigger extends SpeciesFormChangePostMoveTrigger { - override canChange(pokemon: Pokemon): boolean { - if (globalScene.gameMode.hasChallenge(Challenges.SINGLE_TYPE)) { - return false; - } - // Meloetta will not transform if it has the ability Sheer Force when using Relic Song - if (pokemon.hasAbility(AbilityId.SHEER_FORCE)) { - return false; - } - return super.canChange(pokemon); - } -} - -export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger { - private formKey: string; - - constructor(formKey: string) { - super(); - this.formKey = formKey; - this.description = ""; - } - - canChange(pokemon: Pokemon): boolean { - return ( - this.formKey === - pokemon.species.forms[globalScene.getSpeciesFormIndex(pokemon.species, pokemon.gender, pokemon.getNature(), true)] - .formKey - ); - } -} - -/** - * Class used for triggering form changes based on the user's Tera type. - * Used by Ogerpon and Terapagos. - * @extends SpeciesFormChangeTrigger - */ -export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger { - description = i18next.t("pokemonEvolutions:Forms.tera"); -} - -/** - * Class used for triggering form changes based on the user's lapsed Tera type. - * Used by Ogerpon and Terapagos. - * @extends SpeciesFormChangeTrigger - */ -export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger { - description = i18next.t("pokemonEvolutions:Forms.teraLapse"); -} - -/** - * Class used for triggering form changes based on weather. - * Used by Castform and Cherrim. - * @extends SpeciesFormChangeTrigger - */ -export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger { - /** The ability that triggers the form change */ - public ability: AbilityId; - /** The list of weathers that trigger the form change */ - public weathers: WeatherType[]; - - constructor(ability: AbilityId, weathers: WeatherType[]) { - super(); - this.ability = ability; - this.weathers = weathers; - this.description = i18next.t("pokemonEvolutions:Forms.weather"); - } - - /** - * Checks if the Pokemon has the required ability and is in the correct weather while - * the weather or ability is also not suppressed. - * @param {Pokemon} pokemon the pokemon that is trying to do the form change - * @returns `true` if the Pokemon can change forms, `false` otherwise - */ - canChange(pokemon: Pokemon): boolean { - const currentWeather = globalScene.arena.weather?.weatherType ?? WeatherType.NONE; - const isWeatherSuppressed = globalScene.arena.weather?.isEffectSuppressed(); - const isAbilitySuppressed = pokemon.summonData.abilitySuppressed; - - return ( - !isAbilitySuppressed && - !isWeatherSuppressed && - pokemon.hasAbility(this.ability) && - this.weathers.includes(currentWeather) - ); - } -} - -/** - * Class used for reverting to the original form when the weather runs out - * or when the user loses the ability/is suppressed. - * Used by Castform and Cherrim. - * @extends SpeciesFormChangeTrigger - */ -export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChangeTrigger { - /** The ability that triggers the form change*/ - public ability: AbilityId; - /** The list of weathers that will also trigger a form change to original form */ - public weathers: WeatherType[]; - - constructor(ability: AbilityId, weathers: WeatherType[]) { - super(); - this.ability = ability; - this.weathers = weathers; - this.description = i18next.t("pokemonEvolutions:Forms.weatherRevert"); - } - - /** - * Checks if the Pokemon has the required ability and the weather is one that will revert - * the Pokemon to its original form or the weather or ability is suppressed - * @param {Pokemon} pokemon the pokemon that is trying to do the form change - * @returns `true` if the Pokemon will revert to its original form, `false` otherwise - */ - canChange(pokemon: Pokemon): boolean { - if (pokemon.hasAbility(this.ability, false, true)) { - const currentWeather = globalScene.arena.weather?.weatherType ?? WeatherType.NONE; - const isWeatherSuppressed = globalScene.arena.weather?.isEffectSuppressed(); - const isAbilitySuppressed = pokemon.summonData.abilitySuppressed; - const summonDataAbility = pokemon.summonData.ability; - const isAbilityChanged = summonDataAbility !== this.ability && summonDataAbility !== AbilityId.NONE; - - if (this.weathers.includes(currentWeather) || isWeatherSuppressed || isAbilitySuppressed || isAbilityChanged) { - return true; - } - } - return false; - } -} - -export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: SpeciesFormChange, preName: string): string { - const isMega = formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1; - const isGmax = formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1; - const isEmax = formChange.formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1; - const isRevert = !isMega && formChange.formKey === pokemon.species.forms[0].formKey; - if (isMega) { - return i18next.t("battlePokemonForm:megaChange", { - preName, - pokemonName: pokemon.name, - }); - } - if (isGmax) { - return i18next.t("battlePokemonForm:gigantamaxChange", { - preName, - pokemonName: pokemon.name, - }); - } - if (isEmax) { - return i18next.t("battlePokemonForm:eternamaxChange", { - preName, - pokemonName: pokemon.name, - }); - } - if (isRevert) { - return i18next.t("battlePokemonForm:revertChange", { - pokemonName: getPokemonNameWithAffix(pokemon), - }); - } - if (pokemon.getAbility().id === AbilityId.DISGUISE) { - return i18next.t("battlePokemonForm:disguiseChange"); - } - return i18next.t("battlePokemonForm:formChange", { preName }); -} - /** * Gives a condition for form changing checking if a species is registered as caught in the player's dex data. * Used for fusion forms such as Kyurem and Necrozma. diff --git a/src/data/pokemon-forms/form-change-triggers.ts b/src/data/pokemon-forms/form-change-triggers.ts new file mode 100644 index 00000000000..eb2c0a557c2 --- /dev/null +++ b/src/data/pokemon-forms/form-change-triggers.ts @@ -0,0 +1,348 @@ +import i18next from "i18next"; +import type { Constructor } from "#app/utils/common"; +import type { TimeOfDay } from "#enums/time-of-day"; +import type Pokemon from "#app/field/pokemon"; +import type { SpeciesFormChange } from "#app/data/pokemon-forms"; +import type { PokemonFormChangeItemModifier } from "#app/modifier/modifier"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { globalScene } from "#app/global-scene"; +import { FormChangeItem } from "#enums/form-change-item"; +import { AbilityId } from "#enums/ability-id"; +import { Challenges } from "#enums/challenges"; +import { MoveId } from "#enums/move-id"; +import { SpeciesFormKey } from "#enums/species-form-key"; +import { StatusEffect } from "#enums/status-effect"; +import { WeatherType } from "#enums/weather-type"; + +export abstract class SpeciesFormChangeTrigger { + public description = ""; + + canChange(_pokemon: Pokemon): boolean { + return true; + } + + hasTriggerType(triggerType: Constructor): boolean { + return this instanceof triggerType; + } +} + +export class SpeciesFormChangeManualTrigger extends SpeciesFormChangeTrigger {} + +export class SpeciesFormChangeAbilityTrigger extends SpeciesFormChangeTrigger { + public description: string = i18next.t("pokemonEvolutions:Forms.ability"); +} + +export class SpeciesFormChangeCompoundTrigger { + public description = ""; + public triggers: SpeciesFormChangeTrigger[]; + + constructor(...triggers: SpeciesFormChangeTrigger[]) { + this.triggers = triggers; + this.description = this.triggers + .filter(trigger => trigger?.description?.length > 0) + .map(trigger => trigger.description) + .join(", "); + } + + canChange(pokemon: Pokemon): boolean { + for (const trigger of this.triggers) { + if (!trigger.canChange(pokemon)) { + return false; + } + } + + return true; + } + + hasTriggerType(triggerType: Constructor): boolean { + return !!this.triggers.find(t => t.hasTriggerType(triggerType)); + } +} + +export class SpeciesFormChangeItemTrigger extends SpeciesFormChangeTrigger { + public item: FormChangeItem; + public active: boolean; + + constructor(item: FormChangeItem, active = true) { + super(); + this.item = item; + this.active = active; + this.description = this.active + ? i18next.t("pokemonEvolutions:Forms.item", { + item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`), + }) + : i18next.t("pokemonEvolutions:Forms.deactivateItem", { + item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`), + }); + } + + canChange(pokemon: Pokemon): boolean { + return !!globalScene.findModifier(r => { + // Assume that if m has the `formChangeItem` property, then it is a PokemonFormChangeItemModifier + const m = r as PokemonFormChangeItemModifier; + return ( + "formChangeItem" in m && + m.pokemonId === pokemon.id && + m.formChangeItem === this.item && + m.active === this.active + ); + }); + } +} + +export class SpeciesFormChangeTimeOfDayTrigger extends SpeciesFormChangeTrigger { + public timesOfDay: TimeOfDay[]; + + constructor(...timesOfDay: TimeOfDay[]) { + super(); + this.timesOfDay = timesOfDay; + this.description = i18next.t("pokemonEvolutions:Forms.timeOfDay"); + } + + canChange(_pokemon: Pokemon): boolean { + return this.timesOfDay.indexOf(globalScene.arena.getTimeOfDay()) > -1; + } +} +export class SpeciesFormChangeActiveTrigger extends SpeciesFormChangeTrigger { + public active: boolean; + + constructor(active = false) { + super(); + this.active = active; + this.description = this.active + ? i18next.t("pokemonEvolutions:Forms.enter") + : i18next.t("pokemonEvolutions:Forms.leave"); + } + + canChange(pokemon: Pokemon): boolean { + return pokemon.isActive(true) === this.active; + } +} + +export class SpeciesFormChangeStatusEffectTrigger extends SpeciesFormChangeTrigger { + public statusEffects: StatusEffect[]; + public invert: boolean; + + constructor(statusEffects: StatusEffect | StatusEffect[], invert = false) { + super(); + if (!Array.isArray(statusEffects)) { + statusEffects = [statusEffects]; + } + this.statusEffects = statusEffects; + this.invert = invert; + // this.description = i18next.t("pokemonEvolutions:Forms.statusEffect"); + } + + canChange(pokemon: Pokemon): boolean { + return this.statusEffects.indexOf(pokemon.status?.effect || StatusEffect.NONE) > -1 !== this.invert; + } +} + +export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigger { + public move: MoveId; + public known: boolean; + + constructor(move: MoveId, known = true) { + super(); + this.move = move; + this.known = known; + const moveKey = MoveId[this.move] + .split("_") + .filter(f => f) + .map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase())) + .join("") as unknown as string; + this.description = known + ? i18next.t("pokemonEvolutions:Forms.moveLearned", { + move: i18next.t(`move:${moveKey}.name`), + }) + : i18next.t("pokemonEvolutions:Forms.moveForgotten", { + move: i18next.t(`move:${moveKey}.name`), + }); + } + + canChange(pokemon: Pokemon): boolean { + return !!pokemon.moveset.filter(m => m.moveId === this.move).length === this.known; + } +} + +export abstract class SpeciesFormChangeMoveTrigger extends SpeciesFormChangeTrigger { + public movePredicate: (m: MoveId) => boolean; + public used: boolean; + + constructor(move: MoveId | ((m: MoveId) => boolean), used = true) { + super(); + this.movePredicate = typeof move === "function" ? move : (m: MoveId) => m === move; + this.used = used; + } +} + +export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigger { + description = i18next.t("pokemonEvolutions:Forms.preMove"); + canChange(pokemon: Pokemon): boolean { + const command = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; + return !!command?.move && this.movePredicate(command.move.move) === this.used; + } +} + +export class SpeciesFormChangePostMoveTrigger extends SpeciesFormChangeMoveTrigger { + description = i18next.t("pokemonEvolutions:Forms.postMove"); + canChange(pokemon: Pokemon): boolean { + return ( + pokemon.summonData && !!pokemon.getLastXMoves(1).filter(m => this.movePredicate(m.move)).length === this.used + ); + } +} + +export class MeloettaFormChangePostMoveTrigger extends SpeciesFormChangePostMoveTrigger { + override canChange(pokemon: Pokemon): boolean { + if (globalScene.gameMode.hasChallenge(Challenges.SINGLE_TYPE)) { + return false; + } + // Meloetta will not transform if it has the ability Sheer Force when using Relic Song + if (pokemon.hasAbility(AbilityId.SHEER_FORCE)) { + return false; + } + return super.canChange(pokemon); + } +} + +export class SpeciesDefaultFormMatchTrigger extends SpeciesFormChangeTrigger { + private formKey: string; + + constructor(formKey: string) { + super(); + this.formKey = formKey; + this.description = ""; + } + + canChange(pokemon: Pokemon): boolean { + return ( + this.formKey === + pokemon.species.forms[globalScene.getSpeciesFormIndex(pokemon.species, pokemon.gender, pokemon.getNature(), true)] + .formKey + ); + } +} + +/** + * Class used for triggering form changes based on the user's Tera type. + * Used by Ogerpon and Terapagos. + */ +export class SpeciesFormChangeTeraTrigger extends SpeciesFormChangeTrigger {} + +/** + * Class used for triggering form changes based on the user's lapsed Tera type. + * Used by Ogerpon and Terapagos. + */ +export class SpeciesFormChangeLapseTeraTrigger extends SpeciesFormChangeTrigger {} + +/** + * Class used for triggering form changes based on weather. + * Used by Castform and Cherrim. + */ +export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger { + /** The ability that triggers the form change */ + public ability: AbilityId; + /** The list of weathers that trigger the form change */ + public weathers: WeatherType[]; + + constructor(ability: AbilityId, weathers: WeatherType[]) { + super(); + this.ability = ability; + this.weathers = weathers; + this.description = i18next.t("pokemonEvolutions:Forms.weather"); + } + + /** + * Checks if the Pokemon has the required ability and is in the correct weather while + * the weather or ability is also not suppressed. + * @param pokemon - The pokemon that is trying to do the form change + * @returns `true` if the Pokemon can change forms, `false` otherwise + */ + canChange(pokemon: Pokemon): boolean { + const currentWeather = globalScene.arena.weather?.weatherType ?? WeatherType.NONE; + const isWeatherSuppressed = globalScene.arena.weather?.isEffectSuppressed(); + const isAbilitySuppressed = pokemon.summonData.abilitySuppressed; + + return ( + !isAbilitySuppressed && + !isWeatherSuppressed && + pokemon.hasAbility(this.ability) && + this.weathers.includes(currentWeather) + ); + } +} + +/** + * Class used for reverting to the original form when the weather runs out + * or when the user loses the ability/is suppressed. + * Used by Castform and Cherrim. + */ +export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChangeTrigger { + /** The ability that triggers the form change*/ + public ability: AbilityId; + /** The list of weathers that will also trigger a form change to original form */ + public weathers: WeatherType[]; + + constructor(ability: AbilityId, weathers: WeatherType[]) { + super(); + this.ability = ability; + this.weathers = weathers; + this.description = i18next.t("pokemonEvolutions:Forms.weatherRevert"); + } + + /** + * Checks if the Pokemon has the required ability and the weather is one that will revert + * the Pokemon to its original form or the weather or ability is suppressed + * @param {Pokemon} pokemon the pokemon that is trying to do the form change + * @returns `true` if the Pokemon will revert to its original form, `false` otherwise + */ + canChange(pokemon: Pokemon): boolean { + if (pokemon.hasAbility(this.ability, false, true)) { + const currentWeather = globalScene.arena.weather?.weatherType ?? WeatherType.NONE; + const isWeatherSuppressed = globalScene.arena.weather?.isEffectSuppressed(); + const isAbilitySuppressed = pokemon.summonData.abilitySuppressed; + const summonDataAbility = pokemon.summonData.ability; + const isAbilityChanged = summonDataAbility !== this.ability && summonDataAbility !== AbilityId.NONE; + + if (this.weathers.includes(currentWeather) || isWeatherSuppressed || isAbilitySuppressed || isAbilityChanged) { + return true; + } + } + return false; + } +} + +export function getSpeciesFormChangeMessage(pokemon: Pokemon, formChange: SpeciesFormChange, preName: string): string { + const isMega = formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1; + const isGmax = formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1; + const isEmax = formChange.formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1; + const isRevert = !isMega && formChange.formKey === pokemon.species.forms[0].formKey; + if (isMega) { + return i18next.t("battlePokemonForm:megaChange", { + preName, + pokemonName: pokemon.name, + }); + } + if (isGmax) { + return i18next.t("battlePokemonForm:gigantamaxChange", { + preName, + pokemonName: pokemon.name, + }); + } + if (isEmax) { + return i18next.t("battlePokemonForm:eternamaxChange", { + preName, + pokemonName: pokemon.name, + }); + } + if (isRevert) { + return i18next.t("battlePokemonForm:revertChange", { + pokemonName: getPokemonNameWithAffix(pokemon), + }); + } + if (pokemon.getAbility().id === AbilityId.DISGUISE) { + return i18next.t("battlePokemonForm:disguiseChange"); + } + return i18next.t("battlePokemonForm:formChange", { preName }); +} diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 36a8bbb0520..56dc649afac 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -7,7 +7,8 @@ import i18next from "i18next"; import type { AnySound } from "#app/battle-scene"; import { globalScene } from "#app/global-scene"; import type { GameMode } from "#app/game-mode"; -import { DexAttr, type StarterMoveset } from "#app/system/game-data"; +import type { StarterMoveset } from "#app/system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { isNullOrUndefined, capitalizeString, diff --git a/src/data/terrain.ts b/src/data/terrain.ts index 5b6063cee68..b3ee62ac2f9 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -1,8 +1,7 @@ import type Pokemon from "../field/pokemon"; import type Move from "./moves/move"; import { PokemonType } from "#enums/pokemon-type"; -import { ProtectAttr } from "./moves/move"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import i18next from "i18next"; export enum TerrainType { @@ -55,7 +54,7 @@ export class Terrain { isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean { switch (this.terrainType) { case TerrainType.PSYCHIC: - if (!move.hasAttr(ProtectAttr)) { + if (!move.hasAttr("ProtectAttr")) { // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain return ( move.getPriority(user) > 0 && diff --git a/src/data/trainers/TrainerPartyTemplate.ts b/src/data/trainers/TrainerPartyTemplate.ts index 86201589276..135fe669825 100644 --- a/src/data/trainers/TrainerPartyTemplate.ts +++ b/src/data/trainers/TrainerPartyTemplate.ts @@ -1,7 +1,7 @@ import { startingWave } from "#app/starting-wave"; import { globalScene } from "#app/global-scene"; import { PartyMemberStrength } from "#enums/party-member-strength"; -import { GameModes } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; export class TrainerPartyTemplate { diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 8e704b0b301..2f1f7ed07a8 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -1,12 +1,12 @@ import { globalScene } from "#app/global-scene"; import { modifierTypes } from "#app/modifier/modifier-type"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "../moves/pokemon-move"; import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt, randSeedIntRange } from "#app/utils/common"; import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { tmSpecies } from "#app/data/balance/tms"; import { doubleBattleDialogue } from "#app/data/dialogue"; -import { TrainerVariant } from "#app/field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import { getIsInitialized, initI18n } from "#app/plugins/i18n"; import i18next from "i18next"; import { Gender } from "#app/data/gender"; diff --git a/src/data/weather.ts b/src/data/weather.ts index 3bd2e38824d..822e5aa8303 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -4,7 +4,6 @@ import { getPokemonNameWithAffix } from "../messages"; import type Pokemon from "../field/pokemon"; import { PokemonType } from "#enums/pokemon-type"; import type Move from "./moves/move"; -import { AttackMove } from "./moves/move"; import { randSeedInt } from "#app/utils/common"; import { SuppressWeatherEffectAbAttr } from "./abilities/ability"; import { TerrainType, getTerrainName } from "./terrain"; @@ -95,9 +94,9 @@ export class Weather { switch (this.weatherType) { case WeatherType.HARSH_SUN: - return move instanceof AttackMove && moveType === PokemonType.WATER; + return move.is("AttackMove") && moveType === PokemonType.WATER; case WeatherType.HEAVY_RAIN: - return move instanceof AttackMove && moveType === PokemonType.FIRE; + return move.is("AttackMove") && moveType === PokemonType.FIRE; } return false; diff --git a/src/enums/ability-attr.ts b/src/enums/ability-attr.ts new file mode 100644 index 00000000000..5f7d107f2d1 --- /dev/null +++ b/src/enums/ability-attr.ts @@ -0,0 +1,11 @@ +/** + * Not to be confused with an Ability Attribute. + * This is an object literal storing the slot that an ability can occupy. + */ +export const AbilityAttr = Object.freeze({ + ABILITY_1: 1, + ABILITY_2: 2, + ABILITY_HIDDEN: 4, +}); + +export type AbilityAttr = typeof AbilityAttr[keyof typeof AbilityAttr]; \ No newline at end of file diff --git a/src/enums/ai-type.ts b/src/enums/ai-type.ts new file mode 100644 index 00000000000..13931172a4a --- /dev/null +++ b/src/enums/ai-type.ts @@ -0,0 +1,5 @@ +export enum AiType { + RANDOM, + SMART_RANDOM, + SMART +} diff --git a/src/enums/arena-tag-side.ts b/src/enums/arena-tag-side.ts new file mode 100644 index 00000000000..3e326ce158a --- /dev/null +++ b/src/enums/arena-tag-side.ts @@ -0,0 +1,5 @@ +export enum ArenaTagSide { + BOTH, + PLAYER, + ENEMY +} diff --git a/src/enums/battler-index.ts b/src/enums/battler-index.ts new file mode 100644 index 00000000000..32b1684c86c --- /dev/null +++ b/src/enums/battler-index.ts @@ -0,0 +1,7 @@ +export enum BattlerIndex { + ATTACKER = -1, + PLAYER, + PLAYER_2, + ENEMY, + ENEMY_2 +} diff --git a/src/enums/battler-tag-lapse-type.ts b/src/enums/battler-tag-lapse-type.ts new file mode 100644 index 00000000000..355a084148b --- /dev/null +++ b/src/enums/battler-tag-lapse-type.ts @@ -0,0 +1,12 @@ +export enum BattlerTagLapseType { + FAINT, + MOVE, + PRE_MOVE, + AFTER_MOVE, + MOVE_EFFECT, + TURN_END, + HIT, + /** Tag lapses AFTER_HIT, applying its effects even if the user faints */ + AFTER_HIT, + CUSTOM +} diff --git a/src/enums/challenge-type.ts b/src/enums/challenge-type.ts new file mode 100644 index 00000000000..d9b1fce3e6e --- /dev/null +++ b/src/enums/challenge-type.ts @@ -0,0 +1,69 @@ +/** + * An enum for all the challenge types. The parameter entries on these describe the + * parameters to use when calling the applyChallenges function. + */ +export enum ChallengeType { + /** + * Challenges which modify what starters you can choose + * @see {@link Challenge.applyStarterChoice} + */ + STARTER_CHOICE, + /** + * Challenges which modify how many starter points you have + * @see {@link Challenge.applyStarterPoints} + */ + STARTER_POINTS, + /** + * Challenges which modify how many starter points you have + * @see {@link Challenge.applyStarterPointCost} + */ + STARTER_COST, + /** + * Challenges which modify your starters in some way + * @see {@link Challenge.applyStarterModify} + */ + STARTER_MODIFY, + /** + * Challenges which limit which pokemon you can have in battle. + * @see {@link Challenge.applyPokemonInBattle} + */ + POKEMON_IN_BATTLE, + /** + * Adds or modifies the fixed battles in a run + * @see {@link Challenge.applyFixedBattle} + */ + FIXED_BATTLES, + /** + * Modifies the effectiveness of Type matchups in battle + * @see {@linkcode Challenge.applyTypeEffectiveness} + */ + TYPE_EFFECTIVENESS, + /** + * Modifies what level the AI pokemon are. UNIMPLEMENTED. + */ + AI_LEVEL, + /** + * Modifies how many move slots the AI has. UNIMPLEMENTED. + */ + AI_MOVE_SLOTS, + /** + * Modifies if a pokemon has its passive. UNIMPLEMENTED. + */ + PASSIVE_ACCESS, + /** + * Modifies the game mode settings in some way. UNIMPLEMENTED. + */ + GAME_MODE_MODIFY, + /** + * Modifies what level AI pokemon can access a move. UNIMPLEMENTED. + */ + MOVE_ACCESS, + /** + * Modifies what weight AI pokemon have when generating movesets. UNIMPLEMENTED. + */ + MOVE_WEIGHT, + /** + * Modifies what the pokemon stats for Flip Stat Mode. + */ + FLIP_STAT +} diff --git a/src/enums/command.ts b/src/enums/command.ts new file mode 100644 index 00000000000..4cd626bb066 --- /dev/null +++ b/src/enums/command.ts @@ -0,0 +1,7 @@ +export enum Command { + FIGHT = 0, + BALL, + POKEMON, + RUN, + TERA +} diff --git a/src/enums/dex-attr.ts b/src/enums/dex-attr.ts new file mode 100644 index 00000000000..ee5ceb43ef2 --- /dev/null +++ b/src/enums/dex-attr.ts @@ -0,0 +1,11 @@ +export const DexAttr = Object.freeze({ + NON_SHINY: 1n, + SHINY: 2n, + MALE: 4n, + FEMALE: 8n, + DEFAULT_VARIANT: 16n, + VARIANT_2: 32n, + VARIANT_3: 64n, + DEFAULT_FORM: 128n, +}); +export type DexAttr = typeof DexAttr[keyof typeof DexAttr]; diff --git a/src/enums/field-position.ts b/src/enums/field-position.ts new file mode 100644 index 00000000000..5b7f9c6c570 --- /dev/null +++ b/src/enums/field-position.ts @@ -0,0 +1,5 @@ +export enum FieldPosition { + CENTER, + LEFT, + RIGHT +} diff --git a/src/enums/form-change-item.ts b/src/enums/form-change-item.ts new file mode 100644 index 00000000000..15620eafd0a --- /dev/null +++ b/src/enums/form-change-item.ts @@ -0,0 +1,119 @@ +export enum FormChangeItem { + NONE, + + ABOMASITE, + ABSOLITE, + AERODACTYLITE, + AGGRONITE, + ALAKAZITE, + ALTARIANITE, + AMPHAROSITE, + AUDINITE, + BANETTITE, + BEEDRILLITE, + BLASTOISINITE, + BLAZIKENITE, + CAMERUPTITE, + CHARIZARDITE_X, + CHARIZARDITE_Y, + DIANCITE, + GALLADITE, + GARCHOMPITE, + GARDEVOIRITE, + GENGARITE, + GLALITITE, + GYARADOSITE, + HERACRONITE, + HOUNDOOMINITE, + KANGASKHANITE, + LATIASITE, + LATIOSITE, + LOPUNNITE, + LUCARIONITE, + MANECTITE, + MAWILITE, + MEDICHAMITE, + METAGROSSITE, + MEWTWONITE_X, + MEWTWONITE_Y, + PIDGEOTITE, + PINSIRITE, + RAYQUAZITE, + SABLENITE, + SALAMENCITE, + SCEPTILITE, + SCIZORITE, + SHARPEDONITE, + SLOWBRONITE, + STEELIXITE, + SWAMPERTITE, + TYRANITARITE, + VENUSAURITE, + + BLUE_ORB = 50, + RED_ORB, + ADAMANT_CRYSTAL, + LUSTROUS_GLOBE, + GRISEOUS_CORE, + REVEAL_GLASS, + MAX_MUSHROOMS, + DARK_STONE, + LIGHT_STONE, + PRISON_BOTTLE, + RUSTED_SWORD, + RUSTED_SHIELD, + ICY_REINS_OF_UNITY, + SHADOW_REINS_OF_UNITY, + ULTRANECROZIUM_Z, + + SHARP_METEORITE = 100, + HARD_METEORITE, + SMOOTH_METEORITE, + GRACIDEA, + SHOCK_DRIVE, + BURN_DRIVE, + CHILL_DRIVE, + DOUSE_DRIVE, + N_SOLARIZER, + N_LUNARIZER, + WELLSPRING_MASK, + HEARTHFLAME_MASK, + CORNERSTONE_MASK, + FIST_PLATE, + SKY_PLATE, + TOXIC_PLATE, + EARTH_PLATE, + STONE_PLATE, + INSECT_PLATE, + SPOOKY_PLATE, + IRON_PLATE, + FLAME_PLATE, + SPLASH_PLATE, + MEADOW_PLATE, + ZAP_PLATE, + MIND_PLATE, + ICICLE_PLATE, + DRACO_PLATE, + DREAD_PLATE, + PIXIE_PLATE, + BLANK_PLATE,// TODO: Find a potential use for this + LEGEND_PLATE,// TODO: Find a potential use for this + FIGHTING_MEMORY, + FLYING_MEMORY, + POISON_MEMORY, + GROUND_MEMORY, + ROCK_MEMORY, + BUG_MEMORY, + GHOST_MEMORY, + STEEL_MEMORY, + FIRE_MEMORY, + WATER_MEMORY, + GRASS_MEMORY, + ELECTRIC_MEMORY, + PSYCHIC_MEMORY, + ICE_MEMORY, + DRAGON_MEMORY, + DARK_MEMORY, + FAIRY_MEMORY, + NORMAL_MEMORY +} diff --git a/src/enums/game-modes.ts b/src/enums/game-modes.ts new file mode 100644 index 00000000000..837b634621c --- /dev/null +++ b/src/enums/game-modes.ts @@ -0,0 +1,7 @@ +export enum GameModes { + CLASSIC, + ENDLESS, + SPLICED_ENDLESS, + DAILY, + CHALLENGE +} diff --git a/src/enums/hit-result.ts b/src/enums/hit-result.ts new file mode 100644 index 00000000000..3e62587dd6c --- /dev/null +++ b/src/enums/hit-result.ts @@ -0,0 +1,15 @@ +export enum HitResult { + EFFECTIVE = 1, + SUPER_EFFECTIVE, + NOT_VERY_EFFECTIVE, + ONE_HIT_KO, + NO_EFFECT, + STATUS, + HEAL, + FAIL, + MISS, + INDIRECT, + IMMUNE, + CONFUSION, + INDIRECT_KO +} diff --git a/src/enums/learn-move-situation.ts b/src/enums/learn-move-situation.ts new file mode 100644 index 00000000000..9b329d0f3de --- /dev/null +++ b/src/enums/learn-move-situation.ts @@ -0,0 +1,8 @@ +export enum LearnMoveSituation { + MISC, + LEVEL_UP, + RELEARN, + EVOLUTION, + EVOLUTION_FUSED,// If fusionSpecies has Evolved + EVOLUTION_FUSED_BASE +} diff --git a/src/enums/learn-move-type.ts b/src/enums/learn-move-type.ts new file mode 100644 index 00000000000..442639c1bc7 --- /dev/null +++ b/src/enums/learn-move-type.ts @@ -0,0 +1,8 @@ +export enum LearnMoveType { + /** For learning a move via level-up, evolution, or other non-item-based event */ + LEARN_MOVE, + /** For learning a move via Memory Mushroom */ + MEMORY, + /** For learning a move via TM */ + TM +} diff --git a/src/enums/move-anims-common.ts b/src/enums/move-anims-common.ts new file mode 100644 index 00000000000..f21e4c8be4a --- /dev/null +++ b/src/enums/move-anims-common.ts @@ -0,0 +1,95 @@ +export enum AnimFrameTarget { + USER, + TARGET, + GRAPHIC +} + +export enum AnimFocus { + TARGET = 1, + USER, + USER_TARGET, + SCREEN +} + +export enum AnimBlendType { + NORMAL, + ADD, + SUBTRACT +} + +export enum ChargeAnim { + FLY_CHARGING = 1000, + BOUNCE_CHARGING, + DIG_CHARGING, + FUTURE_SIGHT_CHARGING, + DIVE_CHARGING, + SOLAR_BEAM_CHARGING, + SHADOW_FORCE_CHARGING, + SKULL_BASH_CHARGING, + FREEZE_SHOCK_CHARGING, + SKY_DROP_CHARGING, + SKY_ATTACK_CHARGING, + ICE_BURN_CHARGING, + DOOM_DESIRE_CHARGING, + RAZOR_WIND_CHARGING, + PHANTOM_FORCE_CHARGING, + GEOMANCY_CHARGING, + SHADOW_BLADE_CHARGING, + SOLAR_BLADE_CHARGING, + BEAK_BLAST_CHARGING, + METEOR_BEAM_CHARGING, + ELECTRO_SHOT_CHARGING +} + +export enum CommonAnim { + USE_ITEM = 2000, + HEALTH_UP, + TERASTALLIZE, + POISON = 2010, + TOXIC, + PARALYSIS, + SLEEP, + FROZEN, + BURN, + CONFUSION, + ATTRACT, + BIND, + WRAP, + CURSE_NO_GHOST, + LEECH_SEED, + FIRE_SPIN, + PROTECT, + COVET, + WHIRLPOOL, + BIDE, + SAND_TOMB, + QUICK_GUARD, + WIDE_GUARD, + CURSE, + MAGMA_STORM, + CLAMP, + SNAP_TRAP, + THUNDER_CAGE, + INFESTATION, + ORDER_UP_CURLY, + ORDER_UP_DROOPY, + ORDER_UP_STRETCHY, + RAGING_BULL_FIRE, + RAGING_BULL_WATER, + SALT_CURE, + POWDER, + SUNNY = 2100, + RAIN, + SANDSTORM, + HAIL, + SNOW, + WIND, + HEAVY_RAIN, + HARSH_SUN, + STRONG_WINDS, + MISTY_TERRAIN = 2110, + ELECTRIC_TERRAIN, + GRASSY_TERRAIN, + PSYCHIC_TERRAIN, + LOCK_ON = 2120 +} diff --git a/src/enums/move-result.ts b/src/enums/move-result.ts new file mode 100644 index 00000000000..d402f5b1aed --- /dev/null +++ b/src/enums/move-result.ts @@ -0,0 +1,7 @@ +export enum MoveResult { + PENDING, + SUCCESS, + FAIL, + MISS, + OTHER +} diff --git a/src/enums/move-source-type.ts b/src/enums/move-source-type.ts new file mode 100644 index 00000000000..d9afb07e7f7 --- /dev/null +++ b/src/enums/move-source-type.ts @@ -0,0 +1,12 @@ +/** + * Used for challenge types that modify movesets, these denote the various sources of moves for pokemon. + */ +export enum MoveSourceType { + LEVEL_UP,// Currently unimplemented for move access + RELEARNER,// Relearner moves currently unimplemented + COMMON_TM, + GREAT_TM, + ULTRA_TM, + COMMON_EGG, + RARE_EGG +} diff --git a/src/enums/trainer-variant.ts b/src/enums/trainer-variant.ts new file mode 100644 index 00000000000..cd8d71cc1b9 --- /dev/null +++ b/src/enums/trainer-variant.ts @@ -0,0 +1,5 @@ +export enum TrainerVariant { + DEFAULT, + FEMALE, + DOUBLE +} diff --git a/src/events/arena.ts b/src/events/arena.ts index ad77289b76b..3b65506db98 100644 --- a/src/events/arena.ts +++ b/src/events/arena.ts @@ -1,4 +1,4 @@ -import type { ArenaTagSide } from "#app/data/arena-tag"; +import type { ArenaTagSide } from "#enums/arena-tag-side"; import type { ArenaTagType } from "#enums/arena-tag-type"; import type { TerrainType } from "#app/data/terrain"; import type { WeatherType } from "#enums/weather-type"; diff --git a/src/field/arena.ts b/src/field/arena.ts index 82a8afbedad..fffbf8dfa26 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -12,12 +12,13 @@ import { getLegendaryWeatherContinuesMessage, Weather, } from "#app/data/weather"; -import { CommonAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import type { PokemonType } from "#enums/pokemon-type"; import type Move from "#app/data/moves/move"; import type { ArenaTag } from "#app/data/arena-tag"; -import { ArenaTagSide, ArenaTrapTag, getArenaTag } from "#app/data/arena-tag"; -import type { BattlerIndex } from "#app/battle"; +import { ArenaTrapTag, getArenaTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; +import type { BattlerIndex } from "#enums/battler-index"; import { Terrain, TerrainType } from "#app/data/terrain"; import { applyAbAttrs, @@ -37,7 +38,10 @@ import { SpeciesId } from "#enums/species-id"; import { TimeOfDay } from "#enums/time-of-day"; import { TrainerType } from "#enums/trainer-type"; import { AbilityId } from "#enums/ability-id"; -import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms"; +import { + SpeciesFormChangeRevertWeatherFormTrigger, + SpeciesFormChangeWeatherTrigger, +} from "#app/data/pokemon-forms/form-change-triggers"; import { WeatherType } from "#enums/weather-type"; import { FieldEffectModifier } from "#app/modifier/modifier"; diff --git a/src/field/damage-number-handler.ts b/src/field/damage-number-handler.ts index bfb85018dd6..b8b3ed76e18 100644 --- a/src/field/damage-number-handler.ts +++ b/src/field/damage-number-handler.ts @@ -1,9 +1,9 @@ import { TextStyle, addTextObject } from "../ui/text"; import type { DamageResult } from "./pokemon"; import type Pokemon from "./pokemon"; -import { HitResult } from "./pokemon"; +import { HitResult } from "#enums/hit-result"; import { formatStat, fixedInt } from "#app/utils/common"; -import type { BattlerIndex } from "../battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; type TextAndShadowArr = [string | null, string | null]; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 71b21076ae6..7032cd06131 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -9,36 +9,8 @@ import BattleInfo from "#app/ui/battle-info/battle-info"; import { EnemyBattleInfo } from "#app/ui/battle-info/enemy-battle-info"; import { PlayerBattleInfo } from "#app/ui/battle-info/player-battle-info"; import type Move from "#app/data/moves/move"; -import { - HighCritAttr, - HitsTagAttr, - applyMoveAttrs, - FixedDamageAttr, - VariableAtkAttr, - TypelessAttr, - CritOnlyAttr, - getMoveTargets, - OneHitKOAttr, - VariableMoveTypeAttr, - VariableDefAttr, - AttackMove, - ModifiedDamageAttr, - VariableMoveTypeMultiplierAttr, - IgnoreOpponentStatStagesAttr, - SacrificialAttr, - VariableMoveCategoryAttr, - CounterDamageAttr, - StatStageChangeAttr, - RechargeAttr, - IgnoreWeatherTypeDebuffAttr, - BypassBurnDamageReductionAttr, - SacrificialAttrOnHit, - OneHitKOAccuracyAttr, - RespectAttackTypeImmunityAttr, - CombinedPledgeStabBoostAttr, - VariableMoveTypeChartAttr, - HpSplitAttr, -} from "#app/data/moves/move"; +import { getMoveTargets } from "#app/data/moves/move-utils"; +import { applyMoveAttrs } from "#app/data/moves/apply-attrs"; import { allMoves } from "#app/data/data-lists"; import { MoveTarget } from "#enums/MoveTarget"; import { MoveCategory } from "#enums/MoveCategory"; @@ -116,7 +88,6 @@ import { import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms"; import { BattlerTag, - BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, @@ -135,8 +106,10 @@ import { loadBattlerTag, type GrudgeTag, } from "../data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { WeatherType } from "#enums/weather-type"; -import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag"; +import { NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type { SuppressAbilitiesTag } from "#app/data/arena-tag"; import type { Ability } from "#app/data/abilities/ability-class"; import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr"; @@ -195,7 +168,7 @@ import { } from "#app/data/abilities/ability"; import { allAbilities } from "#app/data/data-lists"; import type PokemonData from "#app/system/pokemon-data"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { UiMode } from "#enums/ui-mode"; import type { PartyOption } from "#app/ui/party-ui-handler"; import PartyUiHandler, { PartyUiMode } from "#app/ui/party-ui-handler"; @@ -204,7 +177,7 @@ import type { LevelMoves } from "#app/data/balance/pokemon-level-moves"; import { EVOLVE_MOVE, RELEARN_MOVE } from "#app/data/balance/pokemon-level-moves"; import { achvs } from "#app/system/achv"; import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data"; -import { DexAttr } from "#app/system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities"; import { getNatureStatMultiplier } from "#app/data/nature"; import type { SpeciesFormChange } from "#app/data/pokemon-forms"; @@ -213,14 +186,15 @@ import { SpeciesFormChangeLapseTeraTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, -} from "#app/data/pokemon-forms"; +} from "#app/data/pokemon-forms/form-change-triggers"; import { TerrainType } from "#app/data/terrain"; import type { TrainerSlot } from "#enums/trainer-slot"; import Overrides from "#app/overrides"; import i18next from "i18next"; import { speciesEggMoves } from "#app/data/balance/egg-moves"; import { ModifierTier } from "#app/modifier/modifier-tier"; -import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { applyChallenges } from "#app/data/challenge"; +import { ChallengeType } from "#enums/challenge-type"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; import { BattleSpec } from "#enums/battle-spec"; @@ -249,21 +223,12 @@ import { doShinySparkleAnim } from "#app/field/anims"; import { MoveFlags } from "#enums/MoveFlags"; import { timedEventManager } from "#app/global-event-manager"; import { loadMoveAnimations } from "#app/sprites/pokemon-asset-loader"; - -export enum LearnMoveSituation { - MISC, - LEVEL_UP, - RELEARN, - EVOLUTION, - EVOLUTION_FUSED, // If fusionSpecies has Evolved - EVOLUTION_FUSED_BASE, // If fusion's base species has Evolved -} - -export enum FieldPosition { - CENTER, - LEFT, - RIGHT, -} +import { FieldPosition } from "#enums/field-position"; +import { LearnMoveSituation } from "#enums/learn-move-situation"; +import { HitResult } from "#enums/hit-result"; +import { AiType } from "#enums/ai-type"; +import type { MoveResult } from "#enums/move-result"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; /** Base typeclass for damage parameter methods, used for DRY */ type damageParams = { @@ -1435,7 +1400,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ getCritStage(source: Pokemon, move: Move): number { const critStage = new NumberHolder(0); - applyMoveAttrs(HighCritAttr, source, this, move, critStage); + applyMoveAttrs("HighCritAttr", source, this, move, critStage); globalScene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critStage); globalScene.applyModifiers(TempCritBoosterModifier, source.isPlayer(), critStage); applyAbAttrs(BonusCritAbAttr, source, null, false, critStage); @@ -1461,7 +1426,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ getMoveCategory(target: Pokemon, move: Move): MoveCategory { const moveCategory = new NumberHolder(move.category); - applyMoveAttrs(VariableMoveCategoryAttr, this, target, move, moveCategory); + applyMoveAttrs("VariableMoveCategoryAttr", this, target, move, moveCategory); return moveCategory.value; } @@ -2356,7 +2321,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public getMoveType(move: Move, simulated = true): PokemonType { const moveTypeHolder = new NumberHolder(move.type); - applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder); + applyMoveAttrs("VariableMoveTypeAttr", this, null, move, moveTypeHolder); applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder); // If the user is terastallized and the move is tera blast, or tera starstorm that is stellar type, @@ -2400,18 +2365,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { return this.turnData?.moveEffectiveness; } - if (move.hasAttr(TypelessAttr)) { + if (move.hasAttr("TypelessAttr")) { return 1; } const moveType = source.getMoveType(move); const typeMultiplier = new NumberHolder( - move.category !== MoveCategory.STATUS || move.hasAttr(RespectAttackTypeImmunityAttr) + move.category !== MoveCategory.STATUS || move.hasAttr("RespectAttackTypeImmunityAttr") ? this.getAttackTypeEffectiveness(moveType, source, false, simulated, move, useIllusion) : 1, ); - applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); + applyMoveAttrs("VariableMoveTypeMultiplierAttr", source, this, move, typeMultiplier); if (this.getTypes(true, true).find(t => move.isTypeImmune(source, this, t))) { typeMultiplier.value = 0; } @@ -2438,7 +2403,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const immuneTags = this.findTags(tag => tag instanceof TypeImmuneTag && tag.immuneType === moveType); for (const tag of immuneTags) { - if (move && !move.getAttrs(HitsTagAttr).some(attr => attr.tagType === tag.tagType)) { + if (move && !move.getAttrs("HitsTagAttr").some(attr => attr.tagType === tag.tagType)) { typeMultiplier.value = 0; break; } @@ -2494,7 +2459,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const multiplier = new NumberHolder(getTypeDamageMultiplier(moveType, defType)); applyChallenges(ChallengeType.TYPE_EFFECTIVENESS, multiplier); if (move) { - applyMoveAttrs(VariableMoveTypeChartAttr, null, this, move, multiplier, defType); + applyMoveAttrs("VariableMoveTypeChartAttr", null, this, move, multiplier, defType); } if (source) { const ignoreImmunity = new BooleanHolder(false); @@ -3130,24 +3095,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Bosses never get self ko moves or Pain Split if (this.isBoss()) { - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr) && !allMoves[m[0]].hasAttr(HpSplitAttr)); + movePool = movePool.filter( + m => !allMoves[m[0]].hasAttr("SacrificialAttr") && !allMoves[m[0]].hasAttr("HpSplitAttr"), + ); } // No one gets Memento or Final Gambit - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit)); + movePool = movePool.filter(m => !allMoves[m[0]].hasAttr("SacrificialAttrOnHit")); if (this.hasTrainer()) { // Trainers never get OHKO moves - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(OneHitKOAttr)); + movePool = movePool.filter(m => !allMoves[m[0]].hasAttr("OneHitKOAttr")); // Half the weight of self KO moves - movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1)]); + movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].hasAttr("SacrificialAttr") ? 0.5 : 1)]); // Trainers get a weight bump to stat buffing moves movePool = movePool.map(m => [ m[0], - m[1] * (allMoves[m[0]].getAttrs(StatStageChangeAttr).some(a => a.stages > 1 && a.selfTarget) ? 1.25 : 1), + m[1] * (allMoves[m[0]].getAttrs("StatStageChangeAttr").some(a => a.stages > 1 && a.selfTarget) ? 1.25 : 1), ]); // Trainers get a weight decrease to multiturn moves movePool = movePool.map(m => [ m[0], - m[1] * (!!allMoves[m[0]].isChargingMove() || !!allMoves[m[0]].hasAttr(RechargeAttr) ? 0.7 : 1), + m[1] * (!!allMoves[m[0]].isChargingMove() || !!allMoves[m[0]].hasAttr("RechargeAttr") ? 0.7 : 1), ]); } @@ -3214,7 +3181,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { !this.moveset.some( mo => m[0] === mo.moveId || - (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)), // Only one self-KO move allowed + (allMoves[m[0]].hasAttr("SacrificialAttr") && mo.getMove().hasAttr("SacrificialAttr")), // Only one self-KO move allowed ), ) .map(m => { @@ -3243,7 +3210,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { !this.moveset.some( mo => m[0] === mo.moveId || - (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)), // Only one self-KO move allowed + (allMoves[m[0]].hasAttr("SacrificialAttr") && mo.getMove().hasAttr("SacrificialAttr")), // Only one self-KO move allowed ), ); } @@ -3451,7 +3418,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyAbAttrs(IgnoreOpponentStatStagesAbAttr, opponent, null, simulated, stat, ignoreStatStage); } if (move) { - applyMoveAttrs(IgnoreOpponentStatStagesAttr, this, opponent, move, ignoreStatStage); + applyMoveAttrs("IgnoreOpponentStatStagesAttr", this, opponent, move, ignoreStatStage); } } @@ -3476,7 +3443,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @returns The calculated accuracy multiplier. */ getAccuracyMultiplier(target: Pokemon, sourceMove: Move): number { - const isOhko = sourceMove.hasAttr(OneHitKOAccuracyAttr); + const isOhko = sourceMove.hasAttr("OneHitKOAccuracyAttr"); if (isOhko) { return 1; } @@ -3489,7 +3456,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyAbAttrs(IgnoreOpponentStatStagesAbAttr, target, null, false, Stat.ACC, ignoreAccStatStage); applyAbAttrs(IgnoreOpponentStatStagesAbAttr, this, null, false, Stat.EVA, ignoreEvaStatStage); - applyMoveAttrs(IgnoreOpponentStatStagesAttr, this, target, sourceMove, ignoreEvaStatStage); + applyMoveAttrs("IgnoreOpponentStatStagesAttr", this, target, sourceMove, ignoreEvaStatStage); globalScene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), Stat.ACC, userAccStage); @@ -3572,7 +3539,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { simulated, ), ); - applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk); + applyMoveAttrs("VariableAtkAttr", source, this, move, sourceAtk); /** * This Pokemon's defensive stat for the given move's category. @@ -3590,7 +3557,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { simulated, ), ); - applyMoveAttrs(VariableDefAttr, source, this, move, targetDef); + applyMoveAttrs("VariableDefAttr", source, this, move, targetDef); /** * The attack's base damage, as determined by the source's level, move power @@ -3617,7 +3584,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ calculateStabMultiplier(source: Pokemon, move: Move, ignoreSourceAbility: boolean, simulated: boolean): number { // If the move has the Typeless attribute, it doesn't get STAB (e.g. struggle) - if (move.hasAttr(TypelessAttr)) { + if (move.hasAttr("TypelessAttr")) { return 1; } const sourceTypes = source.getTypes(); @@ -3629,7 +3596,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { stabMultiplier.value += 0.5; } - applyMoveAttrs(CombinedPledgeStabBoostAttr, source, this, move, stabMultiplier); + applyMoveAttrs("CombinedPledgeStabBoostAttr", source, this, move, stabMultiplier); if (!ignoreSourceAbility) { applyAbAttrs(StabBoostAbAttr, source, null, simulated, stabMultiplier); @@ -3678,7 +3645,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const variableCategory = new NumberHolder(move.category); - applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory); + applyMoveAttrs("VariableMoveCategoryAttr", source, this, move, variableCategory); const moveCategory = variableCategory.value as MoveCategory; /** The move's type after type-changing effects are applied */ @@ -3703,7 +3670,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const arenaAttackTypeMultiplier = new NumberHolder( globalScene.arena.getAttackTypeMultiplier(moveType, source.isGrounded()), ); - applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier); + applyMoveAttrs("IgnoreWeatherTypeDebuffAttr", source, this, move, arenaAttackTypeMultiplier); const isTypeImmune = typeMultiplier * arenaAttackTypeMultiplier.value === 0; @@ -3717,7 +3684,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // If the attack deals fixed damage, return a result with that much damage const fixedDamage = new NumberHolder(0); - applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage); + applyMoveAttrs("FixedDamageAttr", source, this, move, fixedDamage); if (fixedDamage.value) { const multiLensMultiplier = new NumberHolder(1); globalScene.applyModifiers( @@ -3739,7 +3706,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // If the attack is a one-hit KO move, return a result with damage equal to this Pokemon's HP const isOneHitKo = new BooleanHolder(false); - applyMoveAttrs(OneHitKOAttr, source, this, move, isOneHitKo); + applyMoveAttrs("OneHitKOAttr", source, this, move, isOneHitKo); if (isOneHitKo.value) { return { cancelled: false, @@ -3816,7 +3783,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { isPhysical && source.status && source.status.effect === StatusEffect.BURN && - !move.hasAttr(BypassBurnDamageReductionAttr) + !move.hasAttr("BypassBurnDamageReductionAttr") ) { const burnDamageReductionCancelled = new BooleanHolder(false); if (!ignoreSourceAbility) { @@ -3850,7 +3817,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ const hitsTagMultiplier = new NumberHolder(1); move - .getAttrs(HitsTagAttr) + .getAttrs("HitsTagAttr") .filter(hta => hta.doubleDamage) .forEach(hta => { if (this.getTag(hta.tagType)) { @@ -3907,7 +3874,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } // This attribute may modify damage arbitrarily, so be careful about changing its order of application. - applyMoveAttrs(ModifiedDamageAttr, source, this, move, damage); + applyMoveAttrs("ModifiedDamageAttr", source, this, move, damage); if (this.isFullHp() && !ignoreAbility) { applyPreDefendAbAttrs(PreDefendFullHpEndureAbAttr, this, source, move, cancelled, false, damage); @@ -3943,7 +3910,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { getCriticalHitResult(source: Pokemon, move: Move, simulated = true): boolean { const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const noCritTag = globalScene.arena.getTagOnSide(NoCritTag, defendingSide); - if (noCritTag || Overrides.NEVER_CRIT_OVERRIDE || move.hasAttr(FixedDamageAttr)) { + if (noCritTag || Overrides.NEVER_CRIT_OVERRIDE || move.hasAttr("FixedDamageAttr")) { return false; } const isCritical = new BooleanHolder(false); @@ -3951,7 +3918,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (source.getTag(BattlerTagType.ALWAYS_CRIT)) { isCritical.value = true; } - applyMoveAttrs(CritOnlyAttr, source, this, move, isCritical); + applyMoveAttrs("CritOnlyAttr", source, this, move, isCritical); applyAbAttrs(ConditionalCritAbAttr, source, null, simulated, isCritical, this, move); if (!isCritical.value) { const critChance = [24, 8, 2, 1][Math.max(0, Math.min(this.getCritStage(source, move), 3))]; @@ -6272,7 +6239,7 @@ export class EnemyPokemon extends Pokemon { .targets.map(ind => fieldPokemon[ind]) .filter(p => this.isPlayer() !== p.isPlayer()); // Only considers critical hits for crit-only moves or when this Pokemon is under the effect of Laser Focus - const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT); + const isCritical = move.hasAttr("CritOnlyAttr") || !!this.getTag(BattlerTagType.ALWAYS_CRIT); return ( move.category !== MoveCategory.STATUS && @@ -6341,7 +6308,7 @@ export class EnemyPokemon extends Pokemon { ![MoveId.SUCKER_PUNCH, MoveId.UPPER_HAND, MoveId.THUNDERCLAP].includes(move.id) ) { targetScore = -20; - } else if (move instanceof AttackMove) { + } else if (move.is("AttackMove")) { /** * Attack moves are given extra multipliers to their base benefit score based on * the move's type effectiveness against the target and whether the move is a STAB move. @@ -6462,7 +6429,7 @@ export class EnemyPokemon extends Pokemon { if (!sortedBenefitScores.length) { // Set target to BattlerIndex.ATTACKER when using a counter move // This is the same as when the player does so - if (move.hasAttr(CounterDamageAttr)) { + if (move.hasAttr("CounterDamageAttr")) { return [BattlerIndex.ATTACKER]; } @@ -6945,36 +6912,6 @@ export class PokemonTurnData { public berriesEaten: BerryType[] = []; } -export enum AiType { - RANDOM, - SMART_RANDOM, - SMART, -} - -export enum MoveResult { - PENDING, - SUCCESS, - FAIL, - MISS, - OTHER, -} - -export enum HitResult { - EFFECTIVE = 1, - SUPER_EFFECTIVE, - NOT_VERY_EFFECTIVE, - ONE_HIT_KO, - NO_EFFECT, - STATUS, - HEAL, - FAIL, - MISS, - INDIRECT, - IMMUNE, - CONFUSION, - INDIRECT_KO, -} - export type DamageResult = | HitResult.EFFECTIVE | HitResult.SUPER_EFFECTIVE @@ -6993,91 +6930,3 @@ export interface DamageCalculationResult { /** The damage dealt by the move */ damage: number; } - -/** - * Wrapper class for the {@linkcode Move} class for Pokemon to interact with. - * These are the moves assigned to a {@linkcode Pokemon} object. - * It links to {@linkcode Move} class via the move ID. - * Compared to {@linkcode Move}, this class also tracks things like - * PP Ups recieved, PP used, etc. - * @see {@linkcode isUsable} - checks if move is restricted, out of PP, or not implemented. - * @see {@linkcode getMove} - returns {@linkcode Move} object by looking it up via ID. - * @see {@linkcode usePp} - removes a point of PP from the move. - * @see {@linkcode getMovePp} - returns amount of PP a move currently has. - * @see {@linkcode getPpRatio} - returns the current PP amount / max PP amount. - * @see {@linkcode getName} - returns name of {@linkcode Move}. - **/ -export class PokemonMove { - public moveId: MoveId; - public ppUsed: number; - public ppUp: number; - public virtual: boolean; - - /** - * If defined and nonzero, overrides the maximum PP of the move (e.g., due to move being copied by Transform). - * This also nullifies all effects of `ppUp`. - */ - public maxPpOverride?: number; - - constructor(moveId: MoveId, ppUsed = 0, ppUp = 0, virtual = false, maxPpOverride?: number) { - this.moveId = moveId; - this.ppUsed = ppUsed; - this.ppUp = ppUp; - this.virtual = virtual; - this.maxPpOverride = maxPpOverride; - } - - /** - * Checks whether the move can be selected or performed by a Pokemon, without consideration for the move's targets. - * The move is unusable if it is out of PP, restricted by an effect, or unimplemented. - * - * @param pokemon - {@linkcode Pokemon} that would be using this move - * @param ignorePp - If `true`, skips the PP check - * @param ignoreRestrictionTags - If `true`, skips the check for move restriction tags (see {@link MoveRestrictionBattlerTag}) - * @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`. - */ - isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean { - if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) { - return false; - } - - if (this.getMove().name.endsWith(" (N)")) { - return false; - } - - return ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1; - } - - getMove(): Move { - return allMoves[this.moveId]; - } - - /** - * Sets {@link ppUsed} for this move and ensures the value does not exceed {@link getMovePp} - * @param count Amount of PP to use - */ - usePp(count = 1) { - this.ppUsed = Math.min(this.ppUsed + count, this.getMovePp()); - } - - getMovePp(): number { - return this.maxPpOverride || this.getMove().pp + this.ppUp * toDmgValue(this.getMove().pp / 5); - } - - getPpRatio(): number { - return 1 - this.ppUsed / this.getMovePp(); - } - - getName(): string { - return this.getMove().name; - } - - /** - * Copies an existing move or creates a valid {@linkcode PokemonMove} object from json representing one - * @param source The data for the move to copy; can be a {@linkcode PokemonMove} or JSON object representing one - * @returns A valid {@linkcode PokemonMove} object - */ - static loadMove(source: PokemonMove | any): PokemonMove { - return new PokemonMove(source.moveId, source.ppUsed, source.ppUp, source.virtual, source.maxPpOverride); - } -} diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 244a23185da..8d950b08507 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -13,19 +13,15 @@ import { TeraAIMode } from "#enums/tera-ai-mode"; import type { EnemyPokemon } from "#app/field/pokemon"; import { randSeedWeightedItem, randSeedItem, randSeedInt } from "#app/utils/common"; import type { PersistentModifier } from "#app/modifier/modifier"; -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { getIsInitialized, initI18n } from "#app/plugins/i18n"; import i18next from "i18next"; import { PartyMemberStrength } from "#enums/party-member-strength"; import { SpeciesId } from "#enums/species-id"; import { TrainerType } from "#enums/trainer-type"; import { signatureSpecies } from "#app/data/balance/signature-species"; - -export enum TrainerVariant { - DEFAULT, - FEMALE, - DOUBLE, -} +import { TrainerVariant } from "#enums/trainer-variant"; export default class Trainer extends Phaser.GameObjects.Container { public config: TrainerConfig; diff --git a/src/game-mode.ts b/src/game-mode.ts index 7ad8a6a83e9..a6fc8195175 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -2,7 +2,8 @@ import i18next from "i18next"; import type { FixedBattleConfigs } from "./battle"; import { classicFixedBattles, FixedBattleConfig } from "./battle"; import type { Challenge } from "./data/challenge"; -import { allChallenges, applyChallenges, ChallengeType, copyChallenge } from "./data/challenge"; +import { allChallenges, applyChallenges, copyChallenge } from "./data/challenge"; +import { ChallengeType } from "#enums/challenge-type"; import type PokemonSpecies from "./data/pokemon-species"; import { allSpecies } from "./data/pokemon-species"; import type { Arena } from "./field/arena"; @@ -14,14 +15,7 @@ import { Challenges } from "./enums/challenges"; import { globalScene } from "#app/global-scene"; import { getDailyStartingBiome } from "./data/daily-run"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES, CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES } from "./constants"; - -export enum GameModes { - CLASSIC, - ENDLESS, - SPLICED_ENDLESS, - DAILY, - CHALLENGE, -} +import { GameModes } from "#enums/game-modes"; interface GameModeConfig { isClassic?: boolean; diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index ccbc202407b..b37ed7dea3b 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -2,19 +2,16 @@ import { globalScene } from "#app/global-scene"; import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { tmPoolTiers, tmSpecies } from "#app/data/balance/tms"; import { getBerryEffectDescription, getBerryName } from "#app/data/berry"; -import { AttackMove } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { getNatureName, getNatureStatMultiplier } from "#app/data/nature"; import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball"; -import { - FormChangeItem, - pokemonFormChanges, - SpeciesFormChangeCondition, - SpeciesFormChangeItemTrigger, -} from "#app/data/pokemon-forms"; +import { pokemonFormChanges, SpeciesFormChangeCondition } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms/form-change-triggers"; +import { FormChangeItem } from "#enums/form-change-item"; import { getStatusEffectDescriptor } from "#app/data/status-effect"; import { PokemonType } from "#enums/pokemon-type"; -import type { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon"; +import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { @@ -1339,7 +1336,7 @@ class AttackTypeBoosterModifierTypeGenerator extends ModifierTypeGenerator { p .getMoveset() .map(m => m.getMove()) - .filter(m => m instanceof AttackMove) + .filter(m => m.is("AttackMove")) .map(m => m.type), ); if (!attackMoveTypes.length) { diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index b6f96db751a..bfea061b1e8 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -3,14 +3,15 @@ import { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry"; import { getLevelTotalExp } from "#app/data/exp"; import { allMoves } from "#app/data/data-lists"; import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball"; -import { type FormChangeItem, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms/form-change-triggers"; +import type { FormChangeItem } from "#enums/form-change-item"; import { getStatusEffectHealText } from "#app/data/status-effect"; import Pokemon, { type PlayerPokemon } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import Overrides from "#app/overrides"; -import { LearnMoveType } from "#app/phases/learn-move-phase"; +import { LearnMoveType } from "#enums/learn-move-type"; import type { VoucherType } from "#app/system/voucher"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { addTextObject, TextStyle } from "#app/ui/text"; import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, randSeedFloat, toDmgValue } from "#app/utils/common"; import { BattlerTagType } from "#enums/battler-tag-type"; diff --git a/src/overrides.ts b/src/overrides.ts index 86e1708248d..1fbca8e8de1 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -1,7 +1,7 @@ import { type PokeballCounts } from "#app/battle-scene"; import { EvolutionItem } from "#app/data/balance/pokemon-evolutions"; import { Gender } from "#app/data/gender"; -import { FormChangeItem } from "#app/data/pokemon-forms"; +import { FormChangeItem } from "#enums/form-change-item"; import { type ModifierOverride } from "#app/modifier/modifier-type"; import { Variant } from "#app/sprites/variant"; import { Unlockables } from "#app/system/unlockables"; diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index 4f3f54a7e5b..f4e6725935a 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { SubstituteTag } from "#app/data/battler-tags"; import { diff --git a/src/phases/berry-phase.ts b/src/phases/berry-phase.ts index 6e40e299e7c..cc990d1e2ae 100644 --- a/src/phases/berry-phase.ts +++ b/src/phases/berry-phase.ts @@ -4,7 +4,7 @@ import { HealFromBerryUseAbAttr, RepeatBerryNextTurnAbAttr, } from "#app/data/abilities/ability"; -import { CommonAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import { BerryUsedEvent } from "#app/events/battle-scene"; import { getPokemonNameWithAffix } from "#app/messages"; import { BerryModifier } from "#app/modifier/modifier"; diff --git a/src/phases/check-status-effect-phase.ts b/src/phases/check-status-effect-phase.ts index e4793fae076..43495e038e9 100644 --- a/src/phases/check-status-effect-phase.ts +++ b/src/phases/check-status-effect-phase.ts @@ -1,5 +1,5 @@ import { Phase } from "#app/phase"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; export class CheckStatusEffectPhase extends Phase { diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index afd9cb3bf93..d7264b4aff2 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -4,7 +4,7 @@ import { BattleType } from "#enums/battle-type"; import type { EncoreTag } from "#app/data/battler-tags"; import { TrappedTag } from "#app/data/battler-tags"; import type { MoveTargetSet } from "#app/data/moves/move"; -import { getMoveTargets } from "#app/data/moves/move"; +import { getMoveTargets } from "#app/data/moves/move-utils"; import { speciesStarterCosts } from "#app/data/balance/starters"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#app/enums/battler-tag-type"; @@ -12,15 +12,15 @@ import { BiomeId } from "#enums/biome-id"; import { MoveId } from "#enums/move-id"; import { PokeballType } from "#enums/pokeball"; import type { PlayerPokemon, TurnMove } from "#app/field/pokemon"; -import { FieldPosition } from "#app/field/pokemon"; +import { FieldPosition } from "#enums/field-position"; import { getPokemonNameWithAffix } from "#app/messages"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { UiMode } from "#enums/ui-mode"; import i18next from "i18next"; import { FieldPhase } from "./field-phase"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { isNullOrUndefined } from "#app/utils/common"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagType } from "#app/enums/arena-tag-type"; export class CommandPhase extends FieldPhase { diff --git a/src/phases/common-anim-phase.ts b/src/phases/common-anim-phase.ts index 4a27db3a651..abfe8ed99f0 100644 --- a/src/phases/common-anim-phase.ts +++ b/src/phases/common-anim-phase.ts @@ -1,6 +1,6 @@ -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; -import type { CommonAnim } from "#app/data/battle-anims"; +import type { CommonAnim } from "#enums/move-anims-common"; import { CommonBattleAnim } from "#app/data/battle-anims"; import { PokemonPhase } from "./pokemon-phase"; diff --git a/src/phases/damage-anim-phase.ts b/src/phases/damage-anim-phase.ts index 85cb26e0a09..aa5a0a6c3e6 100644 --- a/src/phases/damage-anim-phase.ts +++ b/src/phases/damage-anim-phase.ts @@ -1,7 +1,8 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { BattleSpec } from "#enums/battle-spec"; -import { type DamageResult, HitResult } from "#app/field/pokemon"; +import type { DamageResult } from "#app/field/pokemon"; +import { HitResult } from "#enums/hit-result"; import { fixedInt } from "#app/utils/common"; import { PokemonPhase } from "#app/phases/pokemon-phase"; diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index e3b33122ac2..74623f947ee 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattleType } from "#enums/battle-type"; import { globalScene } from "#app/global-scene"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; @@ -17,7 +17,7 @@ import { TrainerSlot } from "#enums/trainer-slot"; import { getRandomWeatherType } from "#app/data/weather"; import { EncounterPhaseEvent } from "#app/events/battle-scene"; import type Pokemon from "#app/field/pokemon"; -import { FieldPosition } from "#app/field/pokemon"; +import { FieldPosition } from "#enums/field-position"; import { getPokemonNameWithAffix } from "#app/messages"; import { BoostBugSpawnModifier, IvScannerModifier, TurnHeldItemTransferModifier } from "#app/modifier/modifier"; import { ModifierPoolType, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; diff --git a/src/phases/enemy-command-phase.ts b/src/phases/enemy-command-phase.ts index a81fc4d2107..0dc41a592e0 100644 --- a/src/phases/enemy-command-phase.ts +++ b/src/phases/enemy-command-phase.ts @@ -1,6 +1,6 @@ import { globalScene } from "#app/global-scene"; -import { BattlerIndex } from "#app/battle"; -import { Command } from "#app/ui/command-ui-handler"; +import { BattlerIndex } from "#enums/battler-index"; +import { Command } from "#enums/command"; import { FieldPhase } from "./field-phase"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; diff --git a/src/phases/evolution-phase.ts b/src/phases/evolution-phase.ts index eaedb6d32b0..bcc93b028bd 100644 --- a/src/phases/evolution-phase.ts +++ b/src/phases/evolution-phase.ts @@ -10,7 +10,7 @@ import { UiMode } from "#enums/ui-mode"; import { cos, sin } from "#app/field/anims"; import type { PlayerPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { LearnMoveSituation } from "#app/field/pokemon"; +import { LearnMoveSituation } from "#enums/learn-move-situation"; import { getTypeRgb } from "#app/data/type"; import i18next from "i18next"; import { getPokemonNameWithAffix } from "#app/messages"; diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index 38376af4356..ca23b20be12 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -1,4 +1,4 @@ -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { BattleType } from "#enums/battle-type"; import { globalScene } from "#app/global-scene"; import { @@ -9,16 +9,16 @@ import { PostKnockOutAbAttr, PostVictoryAbAttr, } from "#app/data/abilities/ability"; -import { BattlerTagLapseType } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { battleSpecDialogue } from "#app/data/dialogue"; -import { PostVictoryStatStageChangeAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { BattleSpec } from "#app/enums/battle-spec"; import { StatusEffect } from "#app/enums/status-effect"; import type { EnemyPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { HitResult, PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; +import { HitResult } from "#enums/hit-result"; import type { PlayerPokemon } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { PokemonInstantReviveModifier } from "#app/modifier/modifier"; @@ -144,7 +144,7 @@ export class FaintPhase extends PokemonPhase { if (defeatSource?.isOnField()) { applyPostVictoryAbAttrs(PostVictoryAbAttr, defeatSource); const pvmove = allMoves[pokemon.turnData.attacksReceived[0].move]; - const pvattrs = pvmove.getAttrs(PostVictoryStatStageChangeAttr); + const pvattrs = pvmove.getAttrs("PostVictoryStatStageChangeAttr"); if (pvattrs.length) { for (const pvattr of pvattrs) { pvattr.applyPostVictory(defeatSource, defeatSource, pvmove); diff --git a/src/phases/form-change-phase.ts b/src/phases/form-change-phase.ts index 3813359d432..13cd410ef87 100644 --- a/src/phases/form-change-phase.ts +++ b/src/phases/form-change-phase.ts @@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene"; import { fixedInt } from "#app/utils/common"; import { achvs } from "../system/achv"; import type { SpeciesFormChange } from "../data/pokemon-forms"; -import { getSpeciesFormChangeMessage } from "../data/pokemon-forms"; +import { getSpeciesFormChangeMessage } from "#app/data/pokemon-forms/form-change-triggers"; import type { PlayerPokemon } from "../field/pokemon"; import { UiMode } from "#enums/ui-mode"; import type PartyUiHandler from "../ui/party-ui-handler"; diff --git a/src/phases/learn-move-phase.ts b/src/phases/learn-move-phase.ts index 7464cebe7da..e24efa63b5a 100644 --- a/src/phases/learn-move-phase.ts +++ b/src/phases/learn-move-phase.ts @@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene"; import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims"; import type Move from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; -import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { MoveId } from "#enums/move-id"; import { getPokemonNameWithAffix } from "#app/messages"; import Overrides from "#app/overrides"; @@ -12,15 +12,7 @@ import { UiMode } from "#enums/ui-mode"; import i18next from "i18next"; import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase"; import type Pokemon from "#app/field/pokemon"; - -export enum LearnMoveType { - /** For learning a move via level-up, evolution, or other non-item-based event */ - LEARN_MOVE, - /** For learning a move via Memory Mushroom */ - MEMORY, - /** For learning a move via TM */ - TM, -} +import { LearnMoveType } from "#enums/learn-move-type"; export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { public readonly phaseName = "LearnMovePhase"; diff --git a/src/phases/move-charge-phase.ts b/src/phases/move-charge-phase.ts index a481f4e37b8..15a98ebabd2 100644 --- a/src/phases/move-charge-phase.ts +++ b/src/phases/move-charge-phase.ts @@ -1,10 +1,10 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { MoveChargeAnim } from "#app/data/battle-anims"; -import { applyMoveChargeAttrs, MoveEffectAttr, InstantChargeAttr } from "#app/data/moves/move"; -import type { PokemonMove } from "#app/field/pokemon"; +import { applyMoveChargeAttrs } from "#app/data/moves/apply-attrs"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { BooleanHolder } from "#app/utils/common"; import { PokemonPhase } from "#app/phases/pokemon-phase"; import { BattlerTagType } from "#enums/battler-tag-type"; @@ -43,7 +43,7 @@ export class MoveChargePhase extends PokemonPhase { new MoveChargeAnim(move.chargeAnim, move.id, user).play(false, () => { move.showChargeText(user, target); - applyMoveChargeAttrs(MoveEffectAttr, user, target, move); + applyMoveChargeAttrs("MoveEffectAttr", user, target, move); user.addTag(BattlerTagType.CHARGING, 1, move.id, user.id); this.end(); }); @@ -57,7 +57,7 @@ export class MoveChargePhase extends PokemonPhase { if (move.isChargingMove()) { const instantCharge = new BooleanHolder(false); - applyMoveChargeAttrs(InstantChargeAttr, user, null, move, instantCharge); + applyMoveChargeAttrs("InstantChargeAttr", user, null, move, instantCharge); if (instantCharge.value) { // this MoveEndPhase will be duplicated by the queued MovePhase if not removed diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 84072b393f1..68c96ddce1e 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; import { AddSecondStrikeAbAttr, @@ -16,43 +16,31 @@ import { PostDefendAbAttr, ReflectStatusMoveAbAttr, } from "#app/data/abilities/ability"; -import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag"; +import { ConditionalProtectTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { MoveAnim } from "#app/data/battle-anims"; import { - BattlerTagLapseType, DamageProtectedTag, ProtectedTag, SemiInvulnerableTag, SubstituteTag, TypeBoostTag, } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import type { MoveAttr } from "#app/data/moves/move"; -import { - applyFilteredMoveAttrs, - applyMoveAttrs, - AttackMove, - DelayedAttackAttr, - FlinchAttr, - getMoveTargets, - HitsTagAttr, - MissEffectAttr, - MoveEffectAttr, - MultiHitAttr, - NoEffectAttr, - OneHitKOAttr, - OverrideMoveEffectAttr, - StatChangeBeforeDmgCalcAttr, - ToxicAccuracyAttr, -} from "#app/data/moves/move"; +import { getMoveTargets } from "#app/data/moves/move-utils"; +import { applyFilteredMoveAttrs, applyMoveAttrs } from "#app/data/moves/apply-attrs"; import { MoveEffectTrigger } from "#enums/MoveEffectTrigger"; import { MoveFlags } from "#enums/MoveFlags"; import { MoveTarget } from "#enums/MoveTarget"; import { MoveCategory } from "#enums/MoveCategory"; -import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { PokemonType } from "#enums/pokemon-type"; -import { type DamageResult, PokemonMove, type TurnMove } from "#app/field/pokemon"; +import type { DamageResult, TurnMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; -import { HitResult, MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; +import { HitResult } from "#enums/hit-result"; import { getPokemonNameWithAffix } from "#app/messages"; import { ContactHeldItemTransferChanceModifier, @@ -238,13 +226,13 @@ export class MoveEffectPhase extends PokemonPhase { case HitCheckResult.NO_EFFECT_NO_MESSAGE: case HitCheckResult.PROTECTED: case HitCheckResult.TARGET_NOT_ON_FIELD: - applyMoveAttrs(NoEffectAttr, user, target, this.move); + applyMoveAttrs("NoEffectAttr", user, target, this.move); break; case HitCheckResult.MISS: globalScene.phaseManager.queueMessage( i18next.t("battle:attackMissed", { pokemonNameWithAffix: getPokemonNameWithAffix(target) }), ); - applyMoveAttrs(MissEffectAttr, user, target, this.move); + applyMoveAttrs("MissEffectAttr", user, target, this.move); break; case HitCheckResult.REFLECTED: this.queueReflectedMove(user, target); @@ -274,7 +262,7 @@ export class MoveEffectPhase extends PokemonPhase { globalScene.currentBattle.lastPlayerInvolved = this.fieldIndex; } - const isDelayedAttack = this.move.hasAttr(DelayedAttackAttr); + const isDelayedAttack = this.move.hasAttr("DelayedAttackAttr"); /** If the user was somehow removed from the field and it's not a delayed attack, end this phase */ if (!user.isOnField()) { if (!isDelayedAttack) { @@ -300,7 +288,7 @@ export class MoveEffectPhase extends PokemonPhase { const move = this.move; // Assume single target for override - applyMoveAttrs(OverrideMoveEffectAttr, user, this.getFirstTarget() ?? null, move, overridden, this.virtual); + applyMoveAttrs("OverrideMoveEffectAttr", user, this.getFirstTarget() ?? null, move, overridden, this.virtual); // If other effects were overriden, stop this phase before they can be applied if (overridden.value) { @@ -327,7 +315,7 @@ export class MoveEffectPhase extends PokemonPhase { if (user.turnData.hitsLeft === -1) { const hitCount = new NumberHolder(1); // Assume single target for multi hit - applyMoveAttrs(MultiHitAttr, user, this.getFirstTarget() ?? null, move, hitCount); + applyMoveAttrs("MultiHitAttr", user, this.getFirstTarget() ?? null, move, hitCount); // If Parental Bond is applicable, add another hit applyPreAttackAbAttrs(AddSecondStrikeAbAttr, user, null, move, false, hitCount, null); // If Multi-Lens is applicable, add hits equal to the number of held Multi-Lenses @@ -359,7 +347,7 @@ export class MoveEffectPhase extends PokemonPhase { // Play the animation if the move was successful against any of its targets or it has a POST_TARGET effect (like self destruct) if ( this.moveHistoryEntry.result === MoveResult.SUCCESS || - move.getAttrs(MoveEffectAttr).some(attr => attr.trigger === MoveEffectTrigger.POST_TARGET) + move.getAttrs("MoveEffectAttr").some(attr => attr.trigger === MoveEffectTrigger.POST_TARGET) ) { const firstTarget = this.getFirstTarget(); new MoveAnim( @@ -458,7 +446,7 @@ export class MoveEffectPhase extends PokemonPhase { * @returns a function intended to be passed into a `then()` call. */ protected applyHeldItemFlinchCheck(user: Pokemon, target: Pokemon, dealsDamage: boolean): void { - if (this.move.hasAttr(FlinchAttr)) { + if (this.move.hasAttr("FlinchAttr")) { return; } @@ -600,7 +588,7 @@ export class MoveEffectPhase extends PokemonPhase { const bypassAccuracy = bypassAccAndInvuln || target.getTag(BattlerTagType.ALWAYS_GET_HIT) || - (target.getTag(BattlerTagType.TELEKINESIS) && !this.move.hasAttr(OneHitKOAttr)); + (target.getTag(BattlerTagType.TELEKINESIS) && !this.move.hasAttr("OneHitKOAttr")); if (moveAccuracy === -1 || bypassAccuracy) { return [HitCheckResult.HIT, effectiveness]; @@ -641,7 +629,7 @@ export class MoveEffectPhase extends PokemonPhase { if (user.hasAbilityWithAttr(AlwaysHitAbAttr) || target.hasAbilityWithAttr(AlwaysHitAbAttr)) { return true; } - if (this.move.hasAttr(ToxicAccuracyAttr) && user.isOfType(PokemonType.POISON)) { + if (this.move.hasAttr("ToxicAccuracyAttr") && user.isOfType(PokemonType.POISON)) { return true; } // TODO: Fix lock on / mind reader check. @@ -666,7 +654,7 @@ export class MoveEffectPhase extends PokemonPhase { return false; } const move = this.move; - return move.getAttrs(HitsTagAttr).some(hta => hta.tagType === semiInvulnerableTag.tagType); + return move.getAttrs("HitsTagAttr").some(hta => hta.tagType === semiInvulnerableTag.tagType); } /** @returns The {@linkcode Pokemon} using this phase's invoked move */ @@ -757,7 +745,7 @@ export class MoveEffectPhase extends PokemonPhase { ): void { applyFilteredMoveAttrs( (attr: MoveAttr) => - attr instanceof MoveEffectAttr && + attr.is("MoveEffectAttr") && attr.trigger === triggerType && (isNullOrUndefined(selfTarget) || attr.selfTarget === selfTarget) && (!attr.firstHitOnly || this.firstHit) && @@ -820,7 +808,7 @@ export class MoveEffectPhase extends PokemonPhase { * Apply stat changes from {@linkcode move} and gives it to {@linkcode source} * before damage calculation */ - applyMoveAttrs(StatChangeBeforeDmgCalcAttr, user, target, this.move); + applyMoveAttrs("StatChangeBeforeDmgCalcAttr", user, target, this.move); const { result, damage: dmg } = target.getAttackDamage({ source: user, @@ -998,12 +986,12 @@ export class MoveEffectPhase extends PokemonPhase { applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult); // We assume only enemy Pokemon are able to have the EnemyAttackStatusEffectChanceModifier from tokens - if (!user.isPlayer() && this.move instanceof AttackMove) { + if (!user.isPlayer() && this.move.is("AttackMove")) { globalScene.applyShuffledModifiers(EnemyAttackStatusEffectChanceModifier, false, target); } // Apply Grip Claw's chance to steal an item from the target - if (this.move instanceof AttackMove) { + if (this.move.is("AttackMove")) { globalScene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target); } } diff --git a/src/phases/move-end-phase.ts b/src/phases/move-end-phase.ts index 6642b97773b..e5f87089fae 100644 --- a/src/phases/move-end-phase.ts +++ b/src/phases/move-end-phase.ts @@ -1,7 +1,7 @@ import { globalScene } from "#app/global-scene"; -import { BattlerTagLapseType } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { PokemonPhase } from "./pokemon-phase"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { applyPostSummonAbAttrs, PostSummonRemoveEffectAbAttr } from "#app/data/abilities/ability"; import type Pokemon from "#app/field/pokemon"; diff --git a/src/phases/move-header-phase.ts b/src/phases/move-header-phase.ts index 50100e827d6..8c2d184c3f5 100644 --- a/src/phases/move-header-phase.ts +++ b/src/phases/move-header-phase.ts @@ -1,5 +1,5 @@ -import { applyMoveAttrs, MoveHeaderAttr } from "#app/data/moves/move"; -import type { PokemonMove } from "#app/field/pokemon"; +import { applyMoveAttrs } from "#app/data/moves/apply-attrs"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; import { BattlePhase } from "./battle-phase"; @@ -23,7 +23,7 @@ export class MoveHeaderPhase extends BattlePhase { super.start(); if (this.canMove()) { - applyMoveAttrs(MoveHeaderAttr, this.pokemon, null, this.move.getMove()); + applyMoveAttrs("MoveHeaderAttr", this.pokemon, null, this.move.getMove()); } this.end(); } diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 7fc6a86e3f7..ca66ca745e7 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; import { applyAbAttrs, @@ -12,30 +12,21 @@ import { ReduceStatusEffectDurationAbAttr, } from "#app/data/abilities/ability"; import type { DelayedAttackTag } from "#app/data/arena-tag"; -import { CommonAnim } from "#app/data/battle-anims"; -import { BattlerTagLapseType, CenterOfAttentionTag } from "#app/data/battler-tags"; -import { - AddArenaTrapTagAttr, - applyMoveAttrs, - BypassRedirectAttr, - BypassSleepAttr, - CopyMoveAttr, - DelayedAttackAttr, - frenzyMissFunc, - HealStatusEffectAttr, - PreMoveMessageAttr, - PreUseInterruptAttr, -} from "#app/data/moves/move"; +import { CommonAnim } from "#enums/move-anims-common"; +import { CenterOfAttentionTag } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; +import type { HealStatusEffectAttr } from "#app/data/moves/move"; +import { applyMoveAttrs } from "#app/data/moves/apply-attrs"; import { allMoves } from "#app/data/data-lists"; import { MoveFlags } from "#enums/MoveFlags"; -import { SpeciesFormChangePreMoveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangePreMoveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { getStatusEffectActivationText, getStatusEffectHealText } from "#app/data/status-effect"; import { PokemonType } from "#enums/pokemon-type"; import { getTerrainBlockMessage, getWeatherBlockMessage } from "#app/data/weather"; import { MoveUsedEvent } from "#app/events/battle-scene"; -import type { PokemonMove } from "#app/field/pokemon"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { getPokemonNameWithAffix } from "#app/messages"; import Overrides from "#app/overrides"; import { BattlePhase } from "#app/phases/battle-phase"; @@ -46,6 +37,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; import { StatusEffect } from "#enums/status-effect"; import i18next from "i18next"; +import { frenzyMissFunc } from "#app/data/moves/move-utils"; export class MovePhase extends BattlePhase { public readonly phaseName = "MovePhase"; @@ -204,7 +196,7 @@ export class MovePhase extends BattlePhase { const moveQueue = this.pokemon.getMoveQueue(); if ( - (targets.length === 0 && !this.move.getMove().hasAttr(AddArenaTrapTagAttr)) || + (targets.length === 0 && !this.move.getMove().hasAttr("AddArenaTrapTagAttr")) || (moveQueue.length && moveQueue[0].move === MoveId.NONE) ) { this.showMoveText(); @@ -233,7 +225,7 @@ export class MovePhase extends BattlePhase { Overrides.STATUS_ACTIVATION_OVERRIDE !== false; break; case StatusEffect.SLEEP: { - applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove()); + applyMoveAttrs("BypassSleepAttr", this.pokemon, null, this.move.getMove()); const turnsRemaining = new NumberHolder(this.pokemon.status.sleepTurnsRemaining ?? 0); applyAbAttrs( ReduceStatusEffectDurationAbAttr, @@ -253,7 +245,10 @@ export class MovePhase extends BattlePhase { !!this.move .getMove() .findAttr( - attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE), + attr => + attr.is("HealStatusEffectAttr") && + attr.selfTarget && + (attr as unknown as HealStatusEffectAttr).isOfEffect(StatusEffect.FREEZE), ) || (!this.pokemon.randBattleSeedInt(5) && Overrides.STATUS_ACTIVATION_OVERRIDE !== true) || Overrides.STATUS_ACTIVATION_OVERRIDE === false; @@ -303,7 +298,7 @@ export class MovePhase extends BattlePhase { // form changes happen even before we know that the move wll execute. globalScene.triggerPokemonFormChange(this.pokemon, SpeciesFormChangePreMoveTrigger); - const isDelayedAttack = this.move.getMove().hasAttr(DelayedAttackAttr); + const isDelayedAttack = this.move.getMove().hasAttr("DelayedAttackAttr"); if (isDelayedAttack) { // Check the player side arena if future sight is active const futureSightTags = globalScene.arena.findTags(t => t.tagType === ArenaTagType.FUTURE_SIGHT); @@ -331,7 +326,7 @@ export class MovePhase extends BattlePhase { let success = true; // Check if there are any attributes that can interrupt the move, overriding the fail message. - for (const move of this.move.getMove().getAttrs(PreUseInterruptAttr)) { + for (const move of this.move.getMove().getAttrs("PreUseInterruptAttr")) { if (move.apply(this.pokemon, targets[0], this.move.getMove())) { success = false; break; @@ -386,7 +381,7 @@ export class MovePhase extends BattlePhase { } // Update the battle's "last move" pointer, unless we're currently mimicking a move. - if (!allMoves[this.move.moveId].hasAttr(CopyMoveAttr)) { + if (!allMoves[this.move.moveId].hasAttr("CopyMoveAttr")) { // The last move used is unaffected by moves that fail if (success) { globalScene.currentBattle.lastMove = this.move.moveId; @@ -543,7 +538,7 @@ export class MovePhase extends BattlePhase { }); if (currentTarget !== redirectTarget.value) { - const bypassRedirectAttrs = this.move.getMove().getAttrs(BypassRedirectAttr); + const bypassRedirectAttrs = this.move.getMove().getAttrs("BypassRedirectAttr"); bypassRedirectAttrs.forEach(attr => { if (!attr.abilitiesOnly || redirectedByAbility) { redirectTarget.value = currentTarget; @@ -664,7 +659,7 @@ export class MovePhase extends BattlePhase { }), 500, ); - applyMoveAttrs(PreMoveMessageAttr, this.pokemon, this.pokemon.getOpponents(false)[0], this.move.getMove()); + applyMoveAttrs("PreMoveMessageAttr", this.pokemon, this.pokemon.getOpponents(false)[0], this.move.getMove()); } public showFailedText(failedText: string = i18next.t("battle:attackFailed")): void { diff --git a/src/phases/mystery-encounter-phases.ts b/src/phases/mystery-encounter-phases.ts index 1f27db7ff64..9aae796211f 100644 --- a/src/phases/mystery-encounter-phases.ts +++ b/src/phases/mystery-encounter-phases.ts @@ -1,4 +1,4 @@ -import { BattlerTagLapseType } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import type { OptionPhaseCallback } from "#app/data/mystery-encounters/mystery-encounter-option"; import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option"; import { SeenEncounterData } from "#app/data/mystery-encounters/mystery-encounter-save-data"; diff --git a/src/phases/obtain-status-effect-phase.ts b/src/phases/obtain-status-effect-phase.ts index 2982bc982d9..bf172269d5f 100644 --- a/src/phases/obtain-status-effect-phase.ts +++ b/src/phases/obtain-status-effect-phase.ts @@ -1,12 +1,13 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; -import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims"; +import type { BattlerIndex } from "#enums/battler-index"; +import { CommonBattleAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import { getStatusEffectObtainText, getStatusEffectOverlapText } from "#app/data/status-effect"; import { StatusEffect } from "#app/enums/status-effect"; import type Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { PokemonPhase } from "./pokemon-phase"; -import { SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { applyPostSetStatusAbAttrs, PostSetStatusAbAttr } from "#app/data/abilities/ability"; import { isNullOrUndefined } from "#app/utils/common"; diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index 6e9b6b5c622..cf6cf40a923 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -1,9 +1,9 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; -import { CommonAnim } from "#app/data/battle-anims"; +import type { BattlerIndex } from "#enums/battler-index"; +import { CommonAnim } from "#enums/move-anims-common"; import { getStatusEffectHealText } from "#app/data/status-effect"; import { StatusEffect } from "#app/enums/status-effect"; -import { HitResult } from "#app/field/pokemon"; +import { HitResult } from "#enums/hit-result"; import { getPokemonNameWithAffix } from "#app/messages"; import { HealingBoosterModifier } from "#app/modifier/modifier"; import { HealAchv } from "#app/system/achv"; diff --git a/src/phases/pokemon-phase.ts b/src/phases/pokemon-phase.ts index 8c30512cdc4..d7fe58d0b80 100644 --- a/src/phases/pokemon-phase.ts +++ b/src/phases/pokemon-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import type Pokemon from "#app/field/pokemon"; import { FieldPhase } from "./field-phase"; diff --git a/src/phases/pokemon-transform-phase.ts b/src/phases/pokemon-transform-phase.ts index 4f18a19b2fb..ab0949c42b9 100644 --- a/src/phases/pokemon-transform-phase.ts +++ b/src/phases/pokemon-transform-phase.ts @@ -1,8 +1,8 @@ -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; import { EFFECTIVE_STATS, BATTLE_STATS } from "#enums/stat"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { globalScene } from "#app/global-scene"; import { PokemonPhase } from "./pokemon-phase"; import { getPokemonNameWithAffix } from "#app/messages"; diff --git a/src/phases/post-turn-status-effect-phase.ts b/src/phases/post-turn-status-effect-phase.ts index 33fb012492d..c868b963f39 100644 --- a/src/phases/post-turn-status-effect-phase.ts +++ b/src/phases/post-turn-status-effect-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { applyAbAttrs, applyPostDamageAbAttrs, @@ -8,7 +8,8 @@ import { PostDamageAbAttr, ReduceBurnDamageAbAttr, } from "#app/data/abilities/ability"; -import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims"; +import { CommonBattleAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import { getStatusEffectActivationText } from "#app/data/status-effect"; import { BattleSpec } from "#app/enums/battle-spec"; import { StatusEffect } from "#app/enums/status-effect"; diff --git a/src/phases/quiet-form-change-phase.ts b/src/phases/quiet-form-change-phase.ts index 6b65c2a5140..cfd9c521e2b 100644 --- a/src/phases/quiet-form-change-phase.ts +++ b/src/phases/quiet-form-change-phase.ts @@ -1,7 +1,10 @@ import { globalScene } from "#app/global-scene"; import { SemiInvulnerableTag } from "#app/data/battler-tags"; import type { SpeciesFormChange } from "#app/data/pokemon-forms"; -import { getSpeciesFormChangeMessage, SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms"; +import { + getSpeciesFormChangeMessage, + SpeciesFormChangeTeraTrigger, +} from "#app/data/pokemon-forms/form-change-triggers"; import { getTypeRgb } from "#app/data/type"; import { BattleSpec } from "#app/enums/battle-spec"; import { BattlerTagType } from "#app/enums/battler-tag-type"; diff --git a/src/phases/return-phase.ts b/src/phases/return-phase.ts index 6365256d40a..a8233f98bd1 100644 --- a/src/phases/return-phase.ts +++ b/src/phases/return-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { SwitchType } from "#enums/switch-type"; import { SwitchSummonPhase } from "./switch-summon-phase"; diff --git a/src/phases/scan-ivs-phase.ts b/src/phases/scan-ivs-phase.ts index df68a2d1cab..d296d87ca88 100644 --- a/src/phases/scan-ivs-phase.ts +++ b/src/phases/scan-ivs-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { PERMANENT_STATS, Stat } from "#app/enums/stat"; import { getPokemonNameWithAffix } from "#app/messages"; import { getTextColor, TextStyle } from "#app/ui/text"; diff --git a/src/phases/select-starter-phase.ts b/src/phases/select-starter-phase.ts index 88d4fe06a9b..e7e87f5a25f 100644 --- a/src/phases/select-starter-phase.ts +++ b/src/phases/select-starter-phase.ts @@ -1,7 +1,8 @@ import { globalScene } from "#app/global-scene"; -import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { applyChallenges } from "#app/data/challenge"; +import { ChallengeType } from "#enums/challenge-type"; import { Gender } from "#app/data/gender"; -import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { overrideHeldItems, overrideModifiers } from "#app/modifier/modifier"; import Overrides from "#app/overrides"; diff --git a/src/phases/select-target-phase.ts b/src/phases/select-target-phase.ts index fcbd3aeb679..6d47ac18021 100644 --- a/src/phases/select-target-phase.ts +++ b/src/phases/select-target-phase.ts @@ -1,6 +1,6 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; -import { Command } from "#app/ui/command-ui-handler"; +import type { BattlerIndex } from "#enums/battler-index"; +import { Command } from "#enums/command"; import { UiMode } from "#enums/ui-mode"; import { PokemonPhase } from "./pokemon-phase"; import i18next from "#app/plugins/i18n"; diff --git a/src/phases/shiny-sparkle-phase.ts b/src/phases/shiny-sparkle-phase.ts index 93d7dd67209..53866af89e6 100644 --- a/src/phases/shiny-sparkle-phase.ts +++ b/src/phases/shiny-sparkle-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { PokemonPhase } from "./pokemon-phase"; export class ShinySparklePhase extends PokemonPhase { diff --git a/src/phases/show-ability-phase.ts b/src/phases/show-ability-phase.ts index af295b72622..0f568819cde 100644 --- a/src/phases/show-ability-phase.ts +++ b/src/phases/show-ability-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { PokemonPhase } from "./pokemon-phase"; import { getPokemonNameWithAffix } from "#app/messages"; diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index ad2eeae1c48..9c351096180 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { applyAbAttrs, applyPostStatStageChangeAbAttrs, @@ -11,7 +11,8 @@ import { StatStageChangeCopyAbAttr, StatStageChangeMultiplierAbAttr, } from "#app/data/abilities/ability"; -import { ArenaTagSide, MistTag } from "#app/data/arena-tag"; +import { MistTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type { ArenaTag } from "#app/data/arena-tag"; import type Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index 921466dfead..e902fd0183e 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -1,11 +1,11 @@ import { BattleType } from "#enums/battle-type"; import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { TrainerSlot } from "#enums/trainer-slot"; import { PlayerGender } from "#app/enums/player-gender"; import { addPokeballOpenParticles } from "#app/field/anims"; import type Pokemon from "#app/field/pokemon"; -import { FieldPosition } from "#app/field/pokemon"; +import { FieldPosition } from "#enums/field-position"; import { getPokemonNameWithAffix } from "#app/messages"; import i18next from "i18next"; import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; diff --git a/src/phases/switch-summon-phase.ts b/src/phases/switch-summon-phase.ts index 103af3db275..f6395397920 100644 --- a/src/phases/switch-summon-phase.ts +++ b/src/phases/switch-summon-phase.ts @@ -6,15 +6,14 @@ import { PreSummonAbAttr, PreSwitchOutAbAttr, } from "#app/data/abilities/ability"; -import { ForceSwitchOutAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { getPokeballTintColor } from "#app/data/pokeball"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms/form-change-triggers"; import { TrainerSlot } from "#enums/trainer-slot"; import type Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { SwitchEffectTransferModifier } from "#app/modifier/modifier"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import i18next from "i18next"; import { SummonPhase } from "./summon-phase"; import { SubstituteTag } from "#app/data/battler-tags"; @@ -226,7 +225,7 @@ export class SwitchSummonPhase extends SummonPhase { const currentCommand = globalScene.currentBattle.turnCommands[this.fieldIndex]?.command; const lastPokemonIsForceSwitchedAndNotFainted = - lastUsedMove?.hasAttr(ForceSwitchOutAttr) && !this.lastPokemon.isFainted(); + lastUsedMove?.hasAttr("ForceSwitchOutAttr") && !this.lastPokemon.isFainted(); const lastPokemonHasForceSwitchAbAttr = this.lastPokemon.hasAbilityWithAttr(PostDamageForceSwitchAbAttr) && !this.lastPokemon.isFainted(); diff --git a/src/phases/tera-phase.ts b/src/phases/tera-phase.ts index 5f403f5419e..a6025e20488 100644 --- a/src/phases/tera-phase.ts +++ b/src/phases/tera-phase.ts @@ -5,8 +5,9 @@ import i18next from "i18next"; import { globalScene } from "#app/global-scene"; import { PokemonType } from "#enums/pokemon-type"; import { achvs } from "#app/system/achv"; -import { SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms"; -import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims"; +import { SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms/form-change-triggers"; +import { CommonBattleAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; export class TeraPhase extends BattlePhase { public readonly phaseName = "TeraPhase"; diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index 37ce294f237..26311d52ab8 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -3,7 +3,8 @@ import { BattleType } from "#enums/battle-type"; import { fetchDailyRunSeed, getDailyRunStarters } from "#app/data/daily-run"; import { Gender } from "#app/data/gender"; import { getBiomeKey } from "#app/field/arena"; -import { GameMode, GameModes, getGameMode } from "#app/game-mode"; +import { GameMode, getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import type { Modifier } from "#app/modifier/modifier"; import { getDailyRunStarterModifiers, diff --git a/src/phases/toggle-double-position-phase.ts b/src/phases/toggle-double-position-phase.ts index a6b8705f580..596bf87eb5b 100644 --- a/src/phases/toggle-double-position-phase.ts +++ b/src/phases/toggle-double-position-phase.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import { FieldPosition } from "#app/field/pokemon"; +import { FieldPosition } from "#enums/field-position"; import { BattlePhase } from "./battle-phase"; export class ToggleDoublePositionPhase extends BattlePhase { diff --git a/src/phases/turn-end-phase.ts b/src/phases/turn-end-phase.ts index 85590d667d6..a539b234a18 100644 --- a/src/phases/turn-end-phase.ts +++ b/src/phases/turn-end-phase.ts @@ -1,5 +1,5 @@ import { applyPostTurnAbAttrs, PostTurnAbAttr } from "#app/data/abilities/ability"; -import { BattlerTagLapseType } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { TerrainType } from "#app/data/terrain"; import { WeatherType } from "#app/enums/weather-type"; import { TurnEndEvent } from "#app/events/battle-scene"; diff --git a/src/phases/turn-init-phase.ts b/src/phases/turn-init-phase.ts index e9d6f60af5e..8d0508c5ebb 100644 --- a/src/phases/turn-init-phase.ts +++ b/src/phases/turn-init-phase.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { handleMysteryEncounterBattleStartEffects, handleMysteryEncounterTurnStartEffects, diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index 557b67b6091..e9a8a82afdc 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -1,15 +1,14 @@ import { applyAbAttrs, BypassSpeedChanceAbAttr, PreventBypassSpeedChanceAbAttr } from "#app/data/abilities/ability"; -import { MoveHeaderAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { Stat } from "#app/enums/stat"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { BypassSpeedChanceModifier } from "#app/modifier/modifier"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { randSeedShuffle, BooleanHolder } from "#app/utils/common"; import { FieldPhase } from "./field-phase"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { TrickRoomTag } from "#app/data/arena-tag"; import { SwitchType } from "#enums/switch-type"; import { globalScene } from "#app/global-scene"; @@ -168,7 +167,7 @@ export class TurnStartPhase extends FieldPhase { const move = pokemon.getMoveset().find(m => m.moveId === queuedMove.move && m.ppUsed < m.getMovePp()) || new PokemonMove(queuedMove.move); - if (move.getMove().hasAttr(MoveHeaderAttr)) { + if (move.getMove().hasAttr("MoveHeaderAttr")) { phaseManager.unshiftNew("MoveHeaderPhase", pokemon, move); } if (pokemon.isPlayer()) { diff --git a/src/phases/victory-phase.ts b/src/phases/victory-phase.ts index ca24e474cde..bf6ea6d4a43 100644 --- a/src/phases/victory-phase.ts +++ b/src/phases/victory-phase.ts @@ -1,4 +1,4 @@ -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { BattleType } from "#enums/battle-type"; import type { CustomModifierSettings } from "#app/modifier/modifier-type"; diff --git a/src/phases/weather-effect-phase.ts b/src/phases/weather-effect-phase.ts index 2918cd462df..0873283652e 100644 --- a/src/phases/weather-effect-phase.ts +++ b/src/phases/weather-effect-phase.ts @@ -8,13 +8,13 @@ import { applyPostWeatherLapseAbAttrs, PostWeatherLapseAbAttr, } from "#app/data/abilities/ability"; -import { CommonAnim } from "#app/data/battle-anims"; +import { CommonAnim } from "#enums/move-anims-common"; import type { Weather } from "#app/data/weather"; import { getWeatherDamageMessage, getWeatherLapseMessage } from "#app/data/weather"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { WeatherType } from "#app/enums/weather-type"; import type Pokemon from "#app/field/pokemon"; -import { HitResult } from "#app/field/pokemon"; +import { HitResult } from "#enums/hit-result"; import { BooleanHolder, toDmgValue } from "#app/utils/common"; import { CommonAnimPhase } from "./common-anim-phase"; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 2949ecd51cf..31c7ad7e41c 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -14,7 +14,8 @@ import PokemonData from "#app/system/pokemon-data"; import PersistentModifierData from "#app/system/modifier-data"; import ArenaData from "#app/system/arena-data"; import { Unlockables } from "#app/system/unlockables"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { BattleType } from "#enums/battle-type"; import TrainerData from "#app/system/trainer-data"; import { trainerConfigs } from "#app/data/trainers/trainer-config"; @@ -31,7 +32,7 @@ import { GameStats } from "#app/system/game-stats"; import { Tutorial } from "#app/tutorial"; import { speciesEggMoves } from "#app/data/balance/egg-moves"; import { allMoves } from "#app/data/data-lists"; -import { TrainerVariant } from "#app/field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import type { Variant } from "#app/sprites/variant"; import { setSettingGamepad, SettingGamepad, settingGamepadDefaults } from "#app/system/settings/settings-gamepad"; import type { SettingKeyboard } from "#app/system/settings/settings-keyboard"; @@ -46,7 +47,8 @@ import { GameDataType } from "#enums/game-data-type"; import type { MoveId } from "#enums/move-id"; import { PlayerGender } from "#enums/player-gender"; import { SpeciesId } from "#enums/species-id"; -import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { applyChallenges } from "#app/data/challenge"; +import { ChallengeType } from "#enums/challenge-type"; import { WeatherType } from "#enums/weather-type"; import { TerrainType } from "#app/data/terrain"; import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler"; @@ -62,40 +64,12 @@ import { ArenaTrapTag } from "#app/data/arena-tag"; import { pokemonFormChanges } from "#app/data/pokemon-forms"; import type { PokemonType } from "#enums/pokemon-type"; import type { DexData, DexEntry } from "../@types/dex-data"; +import { DexAttr } from "#enums/dex-attr"; +import { AbilityAttr } from "#enums/ability-attr"; +import { defaultStarterSpecies, saveKey } from "#app/constants"; +import { encrypt, decrypt } from "#app/utils/data"; -export const defaultStarterSpecies: SpeciesId[] = [ - SpeciesId.BULBASAUR, - SpeciesId.CHARMANDER, - SpeciesId.SQUIRTLE, - SpeciesId.CHIKORITA, - SpeciesId.CYNDAQUIL, - SpeciesId.TOTODILE, - SpeciesId.TREECKO, - SpeciesId.TORCHIC, - SpeciesId.MUDKIP, - SpeciesId.TURTWIG, - SpeciesId.CHIMCHAR, - SpeciesId.PIPLUP, - SpeciesId.SNIVY, - SpeciesId.TEPIG, - SpeciesId.OSHAWOTT, - SpeciesId.CHESPIN, - SpeciesId.FENNEKIN, - SpeciesId.FROAKIE, - SpeciesId.ROWLET, - SpeciesId.LITTEN, - SpeciesId.POPPLIO, - SpeciesId.GROOKEY, - SpeciesId.SCORBUNNY, - SpeciesId.SOBBLE, - SpeciesId.SPRIGATITO, - SpeciesId.FUECOCO, - SpeciesId.QUAXLY, -]; - -const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary - -export function getDataTypeKey(dataType: GameDataType, slotId = 0): string { +function getDataTypeKey(dataType: GameDataType, slotId = 0): string { switch (dataType) { case GameDataType.SYSTEM: return "data"; @@ -117,20 +91,6 @@ export function getDataTypeKey(dataType: GameDataType, slotId = 0): string { } } -export function encrypt(data: string, bypassLogin: boolean): string { - return (bypassLogin - ? (data: string) => btoa(encodeURIComponent(data)) - : (data: string) => AES.encrypt(data, saveKey))(data) as unknown as string; // TODO: is this correct? -} - -export function decrypt(data: string, bypassLogin: boolean): string { - return ( - bypassLogin - ? (data: string) => decodeURIComponent(atob(data)) - : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8) - )(data); -} - // TODO: Move all these exported interfaces to @types export interface SystemSaveData { trainerId: number; @@ -214,10 +174,6 @@ export interface StarterAttributes { tera?: PokemonType; } -export interface StarterPreferences { - [key: number]: StarterAttributes; -} - export interface DexAttrProps { shiny: boolean; female: boolean; @@ -234,53 +190,6 @@ export interface RunEntry { isFavorite: boolean; } -export const DexAttr = { - NON_SHINY: 1n, - SHINY: 2n, - MALE: 4n, - FEMALE: 8n, - DEFAULT_VARIANT: 16n, - VARIANT_2: 32n, - VARIANT_3: 64n, - DEFAULT_FORM: 128n, -}; - -export const AbilityAttr = { - ABILITY_1: 1, - ABILITY_2: 2, - ABILITY_HIDDEN: 4, -}; - -// the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present. -// if they ever add private static variables, move this into StarterPrefs -const StarterPrefers_DEFAULT: string = "{}"; -let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT; - -// called on starter selection show once -export function loadStarterPreferences(): StarterPreferences { - return JSON.parse( - (StarterPrefers_private_latest = - localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT), - ); -} - -// called on starter selection clear, always -export function saveStarterPreferences(prefs: StarterPreferences): void { - const pStr: string = JSON.stringify(prefs); - if (pStr !== StarterPrefers_private_latest) { - // something changed, store the update - localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr); - // update the latest prefs - StarterPrefers_private_latest = pStr; - } -} -// This is its own class as StarterPreferences... -// - don't need to be loaded on startup -// - isn't stored with other data -// - don't require to be encrypted -// - shouldn't require calls outside of the starter selection -export class StarterPrefs {} - export interface StarterDataEntry { moveset: StarterMoveset | StarterFormMoveData | null; eggMoves: number; diff --git a/src/system/pokemon-data.ts b/src/system/pokemon-data.ts index 62fb2f4a2e4..7571f0cc82f 100644 --- a/src/system/pokemon-data.ts +++ b/src/system/pokemon-data.ts @@ -5,7 +5,8 @@ import { Nature } from "#enums/nature"; import { PokeballType } from "#enums/pokeball"; import { getPokemonSpecies, getPokemonSpeciesForm } from "../data/pokemon-species"; import { Status } from "../data/status-effect"; -import Pokemon, { EnemyPokemon, PokemonBattleData, PokemonMove, PokemonSummonData } from "../field/pokemon"; +import Pokemon, { EnemyPokemon, PokemonBattleData, PokemonSummonData } from "../field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { TrainerSlot } from "#enums/trainer-slot"; import type { Variant } from "#app/sprites/variant"; import type { BiomeId } from "#enums/biome-id"; diff --git a/src/system/trainer-data.ts b/src/system/trainer-data.ts index 0e6298309bc..7c9bffd99ee 100644 --- a/src/system/trainer-data.ts +++ b/src/system/trainer-data.ts @@ -1,5 +1,6 @@ import type { TrainerType } from "#enums/trainer-type"; -import Trainer, { TrainerVariant } from "../field/trainer"; +import Trainer from "../field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; export default class TrainerData { public trainerType: TrainerType; diff --git a/src/system/unlockables.ts b/src/system/unlockables.ts index 2c396aad1f9..f64d4d33966 100644 --- a/src/system/unlockables.ts +++ b/src/system/unlockables.ts @@ -1,5 +1,6 @@ import i18next from "i18next"; -import { GameMode, GameModes } from "../game-mode"; +import { GameMode } from "../game-mode"; +import { GameModes } from "#enums/game-modes"; export enum Unlockables { ENDLESS_MODE, diff --git a/src/system/version_migration/versions/v1_0_4.ts b/src/system/version_migration/versions/v1_0_4.ts index 9e30ccdc2a7..fbbde49bc08 100644 --- a/src/system/version_migration/versions/v1_0_4.ts +++ b/src/system/version_migration/versions/v1_0_4.ts @@ -1,6 +1,8 @@ import { SettingKeys } from "#app/system/settings/settings"; import type { SystemSaveData, SessionSaveData } from "#app/system/game-data"; -import { AbilityAttr, defaultStarterSpecies, DexAttr } from "#app/system/game-data"; +import { defaultStarterSpecies } from "#app/constants"; +import { AbilityAttr } from "#enums/ability-attr"; +import { DexAttr } from "#enums/dex-attr"; import { allSpecies } from "#app/data/pokemon-species"; import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { isNullOrUndefined } from "#app/utils/common"; diff --git a/src/system/version_migration/versions/v1_7_0.ts b/src/system/version_migration/versions/v1_7_0.ts index dc7c0f48640..e309959317e 100644 --- a/src/system/version_migration/versions/v1_7_0.ts +++ b/src/system/version_migration/versions/v1_7_0.ts @@ -2,7 +2,8 @@ import type { SessionSaveMigrator } from "#app/@types/SessionSaveMigrator"; import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; import { globalScene } from "#app/global-scene"; -import { DexAttr, type SessionSaveData, type SystemSaveData } from "#app/system/game-data"; +import type { SessionSaveData, SystemSaveData } from "#app/system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { isNullOrUndefined } from "#app/utils/common"; /** diff --git a/src/system/version_migration/versions/v1_8_3.ts b/src/system/version_migration/versions/v1_8_3.ts index cce37a53767..bd963290800 100644 --- a/src/system/version_migration/versions/v1_8_3.ts +++ b/src/system/version_migration/versions/v1_8_3.ts @@ -1,6 +1,7 @@ import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator"; import { getPokemonSpecies } from "#app/data/pokemon-species"; -import { DexAttr, type SystemSaveData } from "#app/system/game-data"; +import type { SystemSaveData } from "#app/system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { SpeciesId } from "#enums/species-id"; /** diff --git a/src/system/version_migration/versions/v1_9_0.ts b/src/system/version_migration/versions/v1_9_0.ts index 0f22b85d072..0bd5a422ffb 100644 --- a/src/system/version_migration/versions/v1_9_0.ts +++ b/src/system/version_migration/versions/v1_9_0.ts @@ -1,5 +1,5 @@ import type { SessionSaveMigrator } from "#app/@types/SessionSaveMigrator"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import type { SessionSaveData } from "#app/system/game-data"; import type PokemonData from "#app/system/pokemon-data"; import { MoveId } from "#enums/move-id"; diff --git a/src/ui/arena-flyout.ts b/src/ui/arena-flyout.ts index ab3bd13b47a..fec02ffb660 100644 --- a/src/ui/arena-flyout.ts +++ b/src/ui/arena-flyout.ts @@ -1,6 +1,7 @@ import { addTextObject, TextStyle } from "./text"; import { globalScene } from "#app/global-scene"; -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { WeatherType } from "#enums/weather-type"; import { TerrainType } from "#app/data/terrain"; import { addWindow, WindowVariant } from "./ui-theme"; diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index bb1e8d0e85e..11fb485164a 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -1,6 +1,6 @@ import { getPokeballName } from "../data/pokeball"; import { addTextObject, getTextStyleOptions, TextStyle } from "./text"; -import { Command } from "./command-ui-handler"; +import { Command } from "#enums/command"; import { UiMode } from "#enums/ui-mode"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 0d38672323a..8df399b6d9b 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -11,14 +11,7 @@ import { TerastallizeAccessModifier } from "#app/modifier/modifier"; import { PokemonType } from "#enums/pokemon-type"; import { getTypeRgb } from "#app/data/type"; import { SpeciesId } from "#enums/species-id"; - -export enum Command { - FIGHT = 0, - BALL, - POKEMON, - RUN, - TERA, -} +import { Command } from "#enums/command"; export default class CommandUiHandler extends UiHandler { private commandsContainer: Phaser.GameObjects.Container; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 3fe06cdf039..f30c7a4935c 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -3,14 +3,15 @@ import { globalScene } from "#app/global-scene"; import { addTextObject, TextStyle } from "./text"; import { getTypeDamageMultiplierColor } from "#app/data/type"; import { PokemonType } from "#enums/pokemon-type"; -import { Command } from "./command-ui-handler"; +import { Command } from "#enums/command"; import { UiMode } from "#enums/ui-mode"; import UiHandler from "./ui-handler"; import { getLocalizedSpriteKey, fixedInt, padInt } from "#app/utils/common"; import { MoveCategory } from "#enums/MoveCategory"; import i18next from "i18next"; import { Button } from "#enums/buttons"; -import type { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; +import type { EnemyPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; import type { CommandPhase } from "#app/phases/command-phase"; import MoveInfoOverlay from "./move-info-overlay"; diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index dc184a34866..4213a244fdb 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -5,7 +5,7 @@ import UiHandler from "#app/ui/ui-handler"; import { addWindow } from "#app/ui/ui-theme"; import { getPlayTimeString, formatFancyLargeNumber, toReadableString } from "#app/utils/common"; import type { GameData } from "#app/system/game-data"; -import { DexAttr } from "#app/system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { speciesStarterCosts } from "#app/data/balance/starters"; import { Button } from "#enums/buttons"; import i18next from "i18next"; diff --git a/src/ui/hatched-pokemon-container.ts b/src/ui/hatched-pokemon-container.ts index 9d1c13e19d5..8b9a5309a9c 100644 --- a/src/ui/hatched-pokemon-container.ts +++ b/src/ui/hatched-pokemon-container.ts @@ -1,7 +1,7 @@ import type { EggHatchData } from "#app/data/egg-hatch-data"; import { Gender } from "#app/data/gender"; import { getVariantTint } from "#app/sprites/variant"; -import { DexAttr } from "#app/system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { globalScene } from "#app/global-scene"; import type PokemonSpecies from "#app/data/pokemon-species"; import type PokemonIconAnimHandler from "./pokemon-icon-anim-handler"; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 6ce192751df..f60bfa808ca 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -1,8 +1,9 @@ -import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; +import type { PlayerPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#app/ui/text"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import MessageUiHandler from "#app/ui/message-ui-handler"; import { UiMode } from "#enums/ui-mode"; import { BooleanHolder, toReadableString, randInt, getLocalizedSpriteKey } from "#app/utils/common"; @@ -11,17 +12,18 @@ import { PokemonHeldItemModifier, SwitchEffectTransferModifier, } from "#app/modifier/modifier"; -import { ForceSwitchOutAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { Gender, getGenderColor, getGenderSymbol } from "#app/data/gender"; import { StatusEffect } from "#enums/status-effect"; import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler"; import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { addWindow } from "#app/ui/ui-theme"; -import { SpeciesFormChangeItemTrigger, FormChangeItem } from "#app/data/pokemon-forms"; +import { SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms/form-change-triggers"; +import { FormChangeItem } from "#enums/form-change-item"; import { getVariantTint } from "#app/sprites/variant"; import { Button } from "#enums/buttons"; -import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { applyChallenges } from "#app/data/challenge"; +import { ChallengeType } from "#enums/challenge-type"; import MoveInfoOverlay from "#app/ui/move-info-overlay"; import i18next from "i18next"; import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; @@ -1175,7 +1177,7 @@ export default class PartyUiHandler extends MessageUiHandler { return !!( this.partyUiMode === PartyUiMode.FAINT_SWITCH && moveHistory.length && - allMoves[moveHistory[moveHistory.length - 1].move].getAttrs(ForceSwitchOutAttr)[0]?.isBatonPass() && + allMoves[moveHistory[moveHistory.length - 1].move].getAttrs("ForceSwitchOutAttr")[0]?.isBatonPass() && moveHistory[moveHistory.length - 1].result === MoveResult.SUCCESS ); } diff --git a/src/ui/pokedex-page-ui-handler.ts b/src/ui/pokedex-page-ui-handler.ts index a81265e1a55..7ef4f8f920b 100644 --- a/src/ui/pokedex-page-ui-handler.ts +++ b/src/ui/pokedex-page-ui-handler.ts @@ -22,7 +22,8 @@ import { starterPassiveAbilities } from "#app/data/balance/passives"; import { PokemonType } from "#enums/pokemon-type"; import type { StarterAttributes } from "#app/system/game-data"; import type { DexEntry } from "#app/@types/dex-data"; -import { AbilityAttr, DexAttr } from "#app/system/game-data"; +import { AbilityAttr } from "#enums/ability-attr"; +import { DexAttr } from "#enums/dex-attr"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import MessageUiHandler from "#app/ui/message-ui-handler"; import { StatsContainer } from "#app/ui/stats-container"; diff --git a/src/ui/pokedex-ui-handler.ts b/src/ui/pokedex-ui-handler.ts index 96451041306..5b292e7232f 100644 --- a/src/ui/pokedex-ui-handler.ts +++ b/src/ui/pokedex-ui-handler.ts @@ -11,9 +11,12 @@ import { allSpecies, getPokemonSpeciesForm, getPokerusStarters, normalForm } fro import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters"; import { catchableSpecies } from "#app/data/balance/biomes"; import { PokemonType } from "#enums/pokemon-type"; -import type { DexAttrProps, StarterAttributes, StarterPreferences } from "#app/system/game-data"; +import type { DexAttrProps, StarterAttributes } from "#app/system/game-data"; +import type { StarterPreferences } from "#app/utils/data"; import type { DexEntry } from "#app/@types/dex-data"; -import { AbilityAttr, DexAttr, loadStarterPreferences } from "#app/system/game-data"; +import { loadStarterPreferences } from "#app/utils/data"; +import { AbilityAttr } from "#enums/ability-attr"; +import { DexAttr } from "#enums/dex-attr"; import MessageUiHandler from "#app/ui/message-ui-handler"; import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler"; import { TextStyle, addTextObject } from "#app/ui/text"; diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index 3dbe3b7af7d..0056c3e2f11 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -8,7 +8,7 @@ import type Pokemon from "../field/pokemon"; import i18next from "i18next"; import type { StarterDataEntry } from "../system/game-data"; import type { DexEntry } from "#app/@types/dex-data"; -import { DexAttr } from "../system/game-data"; +import { DexAttr } from "#enums/dex-attr"; import { fixedInt, getShinyDescriptor } from "#app/utils/common"; import ConfirmUiHandler from "./confirm-ui-handler"; import { StatsContainer } from "./stats-container"; diff --git a/src/ui/run-history-ui-handler.ts b/src/ui/run-history-ui-handler.ts index 92c5a2fde07..06ef590c1e8 100644 --- a/src/ui/run-history-ui-handler.ts +++ b/src/ui/run-history-ui-handler.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import { GameModes } from "../game-mode"; +import { GameModes } from "#enums/game-modes"; import { TextStyle, addTextObject } from "./text"; import { UiMode } from "#enums/ui-mode"; import { addWindow } from "./ui-theme"; @@ -11,7 +11,7 @@ import { Button } from "../enums/buttons"; import { BattleType } from "#enums/battle-type"; import type { RunEntry } from "../system/game-data"; import { PlayerGender } from "#enums/player-gender"; -import { TrainerVariant } from "../field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import { RunDisplayMode } from "#app/ui/run-info-ui-handler"; export type RunSelectCallback = (cursor: number) => void; diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index c8dade8878f..a4de2215fa4 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -1,4 +1,4 @@ -import { GameModes } from "../game-mode"; +import { GameModes } from "#enums/game-modes"; import UiHandler from "./ui-handler"; import type { SessionSaveData } from "../system/game-data"; import { TextStyle, addTextObject, addBBCodeTextObject, getTextColor } from "./text"; @@ -10,7 +10,7 @@ import type PokemonData from "../system/pokemon-data"; import i18next from "i18next"; import { Button } from "../enums/buttons"; import { BattleType } from "#enums/battle-type"; -import { TrainerVariant } from "../field/trainer"; +import { TrainerVariant } from "#enums/trainer-variant"; import { Challenges } from "#enums/challenges"; import { getLuckString, getLuckTextTint } from "../modifier/modifier-type"; import RoundRectangle from "phaser3-rex-plugins/plugins/roundrectangle"; diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 47226de3354..0b1e690a918 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -22,10 +22,13 @@ import type PokemonSpecies from "#app/data/pokemon-species"; import { allSpecies, getPokemonSpeciesForm, getPokerusStarters } from "#app/data/pokemon-species"; import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters"; import { PokemonType } from "#enums/pokemon-type"; -import { GameModes } from "#app/game-mode"; -import type { DexAttrProps, StarterMoveset, StarterAttributes, StarterPreferences } from "#app/system/game-data"; +import { GameModes } from "#enums/game-modes"; +import type { DexAttrProps, StarterMoveset, StarterAttributes } from "#app/system/game-data"; +import type { StarterPreferences } from "#app/utils/data"; import type { DexEntry } from "#app/@types/dex-data"; -import { AbilityAttr, DexAttr, loadStarterPreferences, saveStarterPreferences } from "#app/system/game-data"; +import { loadStarterPreferences, saveStarterPreferences } from "#app/utils/data"; +import { AbilityAttr } from "#enums/ability-attr"; +import { DexAttr } from "#enums/dex-attr"; import { Tutorial, handleTutorial } from "#app/tutorial"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import MessageUiHandler from "#app/ui/message-ui-handler"; @@ -38,7 +41,8 @@ import { Egg } from "#app/data/egg"; import Overrides from "#app/overrides"; import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; import { Passive as PassiveAttr } from "#enums/passive"; -import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { applyChallenges } from "#app/data/challenge"; +import { ChallengeType } from "#enums/challenge-type"; import MoveInfoOverlay from "#app/ui/move-info-overlay"; import { getEggTierForSpecies } from "#app/data/egg"; import { Device } from "#enums/devices"; diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index a6f640b436f..05b0ea2097f 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -13,7 +13,8 @@ import { formatStat, getShinyDescriptor, } from "#app/utils/common"; -import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; +import type { PlayerPokemon } from "#app/field/pokemon"; +import type { PokemonMove } from "#app/data/moves/pokemon-move"; import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; import { argbFromRgba } from "@material/material-color-utilities"; import { getTypeRgb } from "#app/data/type"; diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index a2f89d38970..8106e4de2da 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -1,8 +1,8 @@ -import { BattlerIndex } from "../battle"; +import { BattlerIndex } from "#enums/battler-index"; import { UiMode } from "#enums/ui-mode"; import UiHandler from "./ui-handler"; import { isNullOrUndefined, fixedInt } from "#app/utils/common"; -import { getMoveTargets } from "../data/moves/move"; +import { getMoveTargets } from "#app/data/moves/move-utils"; import { Button } from "#enums/buttons"; import type { MoveId } from "#enums/move-id"; import type Pokemon from "#app/field/pokemon"; diff --git a/src/utils/data.ts b/src/utils/data.ts index 33623dc5e40..5a28657d034 100644 --- a/src/utils/data.ts +++ b/src/utils/data.ts @@ -1,3 +1,8 @@ +import { loggedInUser } from "#app/account"; +import type { StarterAttributes } from "#app/system/game-data"; +import { AES, enc } from "crypto-js"; +import { saveKey } from "#app/constants"; + /** * Perform a deep copy of an object. * @param values - The object to be deep copied. @@ -38,3 +43,45 @@ export function deepMergeSpriteData(dest: object, source: object) { } } } + +export function encrypt(data: string, bypassLogin: boolean): string { + return (bypassLogin + ? (data: string) => btoa(encodeURIComponent(data)) + : (data: string) => AES.encrypt(data, saveKey))(data) as unknown as string; // TODO: is this correct? +} + +export function decrypt(data: string, bypassLogin: boolean): string { + return ( + bypassLogin + ? (data: string) => decodeURIComponent(atob(data)) + : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8) + )(data); +} + +// the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present. +// if they ever add private static variables, move this into StarterPrefs +const StarterPrefers_DEFAULT: string = "{}"; +let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT; + +export interface StarterPreferences { + [key: number]: StarterAttributes; +} +// called on starter selection show once + +export function loadStarterPreferences(): StarterPreferences { + return JSON.parse( + (StarterPrefers_private_latest = + localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT), + ); +} +// called on starter selection clear, always + +export function saveStarterPreferences(prefs: StarterPreferences): void { + const pStr: string = JSON.stringify(prefs); + if (pStr !== StarterPrefers_private_latest) { + // something changed, store the update + localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr); + // update the latest prefs + StarterPrefers_private_latest = pStr; + } +} diff --git a/test/abilities/analytic.test.ts b/test/abilities/analytic.test.ts index bf6ef72c3f1..2cfea64d20e 100644 --- a/test/abilities/analytic.test.ts +++ b/test/abilities/analytic.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { isBetween, toDmgValue } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/abilities/aroma_veil.test.ts b/test/abilities/aroma_veil.test.ts index 00baa6b6268..56cce749b9f 100644 --- a/test/abilities/aroma_veil.test.ts +++ b/test/abilities/aroma_veil.test.ts @@ -6,7 +6,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { BattlerTagType } from "#enums/battler-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import type { PlayerPokemon } from "#app/field/pokemon"; describe("Moves - Aroma Veil", () => { diff --git a/test/abilities/battle_bond.test.ts b/test/abilities/battle_bond.test.ts index b4ce73d107b..adb4a9c6e7a 100644 --- a/test/abilities/battle_bond.test.ts +++ b/test/abilities/battle_bond.test.ts @@ -1,4 +1,3 @@ -import { MultiHitAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { MultiHitType } from "#enums/MultiHitType"; import { Status } from "#app/data/status-effect"; @@ -66,7 +65,7 @@ describe("Abilities - BATTLE BOND", () => { vi.spyOn(waterShuriken, "calculateBattlePower"); let actualMultiHitType: MultiHitType | null = null; - const multiHitAttr = waterShuriken.getAttrs(MultiHitAttr)[0]; + const multiHitAttr = waterShuriken.getAttrs("MultiHitAttr")[0]; vi.spyOn(multiHitAttr, "getHitCount").mockImplementation(() => { actualMultiHitType = multiHitAttr.getMultiHitType(); return 3; diff --git a/test/abilities/beast_boost.test.ts b/test/abilities/beast_boost.test.ts index 17ba4020961..1d9eb5c5f2e 100644 --- a/test/abilities/beast_boost.test.ts +++ b/test/abilities/beast_boost.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/commander.test.ts b/test/abilities/commander.test.ts index bb2670ec2f0..39d9d0f4d7f 100644 --- a/test/abilities/commander.test.ts +++ b/test/abilities/commander.test.ts @@ -1,11 +1,11 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattlerTagType } from "#enums/battler-tag-type"; import { PokemonAnimType } from "#enums/pokemon-anim-type"; import type { EffectiveStat } from "#enums/stat"; import { Stat } from "#enums/stat"; import { StatusEffect } from "#enums/status-effect"; import { WeatherType } from "#enums/weather-type"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/dancer.test.ts b/test/abilities/dancer.test.ts index 518c96ea124..2a4a3c36bcc 100644 --- a/test/abilities/dancer.test.ts +++ b/test/abilities/dancer.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import type { MovePhase } from "#app/phases/move-phase"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/abilities/desolate-land.test.ts b/test/abilities/desolate-land.test.ts index bcd980187ac..90565d9caf8 100644 --- a/test/abilities/desolate-land.test.ts +++ b/test/abilities/desolate-land.test.ts @@ -1,7 +1,7 @@ import { PokeballType } from "#app/enums/pokeball"; import { WeatherType } from "#app/enums/weather-type"; import type { CommandPhase } from "#app/phases/command-phase"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/disguise.test.ts b/test/abilities/disguise.test.ts index 15ded41527a..64e0715774d 100644 --- a/test/abilities/disguise.test.ts +++ b/test/abilities/disguise.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { toDmgValue } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/abilities/early_bird.test.ts b/test/abilities/early_bird.test.ts index e158ce1888b..e19f2653b57 100644 --- a/test/abilities/early_bird.test.ts +++ b/test/abilities/early_bird.test.ts @@ -1,5 +1,5 @@ import { Status } from "#app/data/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/flash_fire.test.ts b/test/abilities/flash_fire.test.ts index 8fabda95c80..92bd7b52e57 100644 --- a/test/abilities/flash_fire.test.ts +++ b/test/abilities/flash_fire.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { SpeciesId } from "#enums/species-id"; import { MovePhase } from "#app/phases/move-phase"; diff --git a/test/abilities/flower_gift.test.ts b/test/abilities/flower_gift.test.ts index d4a03bb2330..26180492cbd 100644 --- a/test/abilities/flower_gift.test.ts +++ b/test/abilities/flower_gift.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allAbilities } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { Stat } from "#app/enums/stat"; diff --git a/test/abilities/flower_veil.test.ts b/test/abilities/flower_veil.test.ts index bd76541495d..c59d8c6eb29 100644 --- a/test/abilities/flower_veil.test.ts +++ b/test/abilities/flower_veil.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/forecast.test.ts b/test/abilities/forecast.test.ts index b87519ae80a..8d3a679c917 100644 --- a/test/abilities/forecast.test.ts +++ b/test/abilities/forecast.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allAbilities } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { WeatherType } from "#app/enums/weather-type"; diff --git a/test/abilities/friend_guard.test.ts b/test/abilities/friend_guard.test.ts index d401fa96feb..c5809e18e96 100644 --- a/test/abilities/friend_guard.test.ts +++ b/test/abilities/friend_guard.test.ts @@ -4,7 +4,7 @@ import { AbilityId } from "#enums/ability-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allAbilities } from "#app/data/data-lists"; import { allMoves } from "#app/data/data-lists"; import { MoveCategory } from "#enums/MoveCategory"; diff --git a/test/abilities/good_as_gold.test.ts b/test/abilities/good_as_gold.test.ts index d6c80a5347f..85fadd472dc 100644 --- a/test/abilities/good_as_gold.test.ts +++ b/test/abilities/good_as_gold.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { BattlerIndex } from "#enums/battler-index"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allAbilities } from "#app/data/data-lists"; import { ArenaTagType } from "#app/enums/arena-tag-type"; import { BattlerTagType } from "#app/enums/battler-tag-type"; diff --git a/test/abilities/gorilla_tactics.test.ts b/test/abilities/gorilla_tactics.test.ts index 3ad138749a8..1759267f16d 100644 --- a/test/abilities/gorilla_tactics.test.ts +++ b/test/abilities/gorilla_tactics.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#app/enums/stat"; diff --git a/test/abilities/gulp_missile.test.ts b/test/abilities/gulp_missile.test.ts index b56b316484f..b41eea9ce18 100644 --- a/test/abilities/gulp_missile.test.ts +++ b/test/abilities/gulp_missile.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import type Pokemon from "#app/field/pokemon"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; diff --git a/test/abilities/harvest.test.ts b/test/abilities/harvest.test.ts index 5a6ddf35459..40e6a6abd62 100644 --- a/test/abilities/harvest.test.ts +++ b/test/abilities/harvest.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PostTurnRestoreBerryAbAttr } from "#app/data/abilities/ability"; import type Pokemon from "#app/field/pokemon"; import { BerryModifier, PreserveBerryModifier } from "#app/modifier/modifier"; diff --git a/test/abilities/honey_gather.test.ts b/test/abilities/honey_gather.test.ts index a069654ae21..06d351b2a61 100644 --- a/test/abilities/honey_gather.test.ts +++ b/test/abilities/honey_gather.test.ts @@ -1,5 +1,5 @@ import type { CommandPhase } from "#app/phases/command-phase"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/ice_face.test.ts b/test/abilities/ice_face.test.ts index 6ef91981cf3..2899120db5a 100644 --- a/test/abilities/ice_face.test.ts +++ b/test/abilities/ice_face.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase"; import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; diff --git a/test/abilities/infiltrator.test.ts b/test/abilities/infiltrator.test.ts index 891a716f7a4..03b55e925cd 100644 --- a/test/abilities/infiltrator.test.ts +++ b/test/abilities/infiltrator.test.ts @@ -1,4 +1,4 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import { ArenaTagType } from "#enums/arena-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type"; diff --git a/test/abilities/lightningrod.test.ts b/test/abilities/lightningrod.test.ts index 777ccb88ba9..a69f5e94067 100644 --- a/test/abilities/lightningrod.test.ts +++ b/test/abilities/lightningrod.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/magic_bounce.test.ts b/test/abilities/magic_bounce.test.ts index 8c3eeec974c..3c4ff2ad909 100644 --- a/test/abilities/magic_bounce.test.ts +++ b/test/abilities/magic_bounce.test.ts @@ -1,6 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allAbilities } from "#app/data/data-lists"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import { ArenaTagType } from "#app/enums/arena-tag-type"; import { BattlerTagType } from "#app/enums/battler-tag-type"; diff --git a/test/abilities/magic_guard.test.ts b/test/abilities/magic_guard.test.ts index c36b35c09b7..40bb3203673 100644 --- a/test/abilities/magic_guard.test.ts +++ b/test/abilities/magic_guard.test.ts @@ -1,4 +1,5 @@ -import { ArenaTagSide, getArenaTag } from "#app/data/arena-tag"; +import { getArenaTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/abilities/mirror_armor.test.ts b/test/abilities/mirror_armor.test.ts index 319e47cbfb3..540a3b5d426 100644 --- a/test/abilities/mirror_armor.test.ts +++ b/test/abilities/mirror_armor.test.ts @@ -5,7 +5,7 @@ import { SpeciesId } from "#enums/species-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; // TODO: When Magic Bounce is implemented, make a test for its interaction with mirror guard, use screech diff --git a/test/abilities/mold_breaker.test.ts b/test/abilities/mold_breaker.test.ts index 099fb54c998..e2e8a73da9d 100644 --- a/test/abilities/mold_breaker.test.ts +++ b/test/abilities/mold_breaker.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { globalScene } from "#app/global-scene"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/abilities/moxie.test.ts b/test/abilities/moxie.test.ts index 04ca68325e6..8b658f60bf6 100644 --- a/test/abilities/moxie.test.ts +++ b/test/abilities/moxie.test.ts @@ -5,7 +5,7 @@ import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { VictoryPhase } from "#app/phases/victory-phase"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; diff --git a/test/abilities/neutralizing_gas.test.ts b/test/abilities/neutralizing_gas.test.ts index 2d1fef29688..067d164e835 100644 --- a/test/abilities/neutralizing_gas.test.ts +++ b/test/abilities/neutralizing_gas.test.ts @@ -1,6 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import type { CommandPhase } from "#app/phases/command-phase"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { PostSummonWeatherChangeAbAttr } from "#app/data/abilities/ability"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; diff --git a/test/abilities/no_guard.test.ts b/test/abilities/no_guard.test.ts index 5b127204f9f..dc35e0e1b9a 100644 --- a/test/abilities/no_guard.test.ts +++ b/test/abilities/no_guard.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/abilities/normal-move-type-change.test.ts b/test/abilities/normal-move-type-change.test.ts index 578a6ad2a21..03fb5b2e7be 100644 --- a/test/abilities/normal-move-type-change.test.ts +++ b/test/abilities/normal-move-type-change.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { PokemonType } from "#enums/pokemon-type"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/abilities/pastel_veil.test.ts b/test/abilities/pastel_veil.test.ts index 8a3aec918d0..b8e8873ed36 100644 --- a/test/abilities/pastel_veil.test.ts +++ b/test/abilities/pastel_veil.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { CommandPhase } from "#app/phases/command-phase"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; diff --git a/test/abilities/protosynthesis.test.ts b/test/abilities/protosynthesis.test.ts index 3bf74acaca7..ba7bb5d084b 100644 --- a/test/abilities/protosynthesis.test.ts +++ b/test/abilities/protosynthesis.test.ts @@ -5,7 +5,7 @@ import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Abilities - Protosynthesis", () => { diff --git a/test/abilities/serene_grace.test.ts b/test/abilities/serene_grace.test.ts index bfdbd5324bb..c5c12fe217e 100644 --- a/test/abilities/serene_grace.test.ts +++ b/test/abilities/serene_grace.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; @@ -6,7 +6,6 @@ import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { allMoves } from "#app/data/data-lists"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { FlinchAttr } from "#app/data/moves/move"; describe("Abilities - Serene Grace", () => { let phaserGame: Phaser.Game; @@ -39,7 +38,7 @@ describe("Abilities - Serene Grace", () => { await game.classicMode.startBattle([SpeciesId.SHUCKLE]); const airSlashMove = allMoves[MoveId.AIR_SLASH]; - const airSlashFlinchAttr = airSlashMove.getAttrs(FlinchAttr)[0]; + const airSlashFlinchAttr = airSlashMove.getAttrs("FlinchAttr")[0]; vi.spyOn(airSlashFlinchAttr, "getMoveChance"); game.move.select(MoveId.AIR_SLASH); diff --git a/test/abilities/sheer_force.test.ts b/test/abilities/sheer_force.test.ts index a5b1cf3b5b2..922025d8be2 100644 --- a/test/abilities/sheer_force.test.ts +++ b/test/abilities/sheer_force.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; @@ -7,7 +7,6 @@ import { Stat } from "#enums/stat"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { FlinchAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; describe("Abilities - Sheer Force", () => { @@ -43,7 +42,7 @@ describe("Abilities - Sheer Force", () => { const airSlashMove = allMoves[MoveId.AIR_SLASH]; vi.spyOn(airSlashMove, "calculateBattlePower"); - const airSlashFlinchAttr = airSlashMove.getAttrs(FlinchAttr)[0]; + const airSlashFlinchAttr = airSlashMove.getAttrs("FlinchAttr")[0]; vi.spyOn(airSlashFlinchAttr, "getMoveChance"); game.move.select(MoveId.AIR_SLASH); @@ -98,7 +97,7 @@ describe("Abilities - Sheer Force", () => { const enemyPokemon = game.scene.getEnemyPokemon(); const headbuttMove = allMoves[MoveId.HEADBUTT]; vi.spyOn(headbuttMove, "calculateBattlePower"); - const headbuttFlinchAttr = headbuttMove.getAttrs(FlinchAttr)[0]; + const headbuttFlinchAttr = headbuttMove.getAttrs("FlinchAttr")[0]; vi.spyOn(headbuttFlinchAttr, "getMoveChance"); game.move.select(MoveId.HEADBUTT); diff --git a/test/abilities/shield_dust.test.ts b/test/abilities/shield_dust.test.ts index 03b175c3ca5..e071cf7a245 100644 --- a/test/abilities/shield_dust.test.ts +++ b/test/abilities/shield_dust.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { applyAbAttrs, applyPreDefendAbAttrs, diff --git a/test/abilities/speed_boost.test.ts b/test/abilities/speed_boost.test.ts index 245bf22345d..a4445d085f3 100644 --- a/test/abilities/speed_boost.test.ts +++ b/test/abilities/speed_boost.test.ts @@ -6,7 +6,7 @@ import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import type { CommandPhase } from "#app/phases/command-phase"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { AttemptRunPhase } from "#app/phases/attempt-run-phase"; describe("Abilities - Speed Boost", () => { diff --git a/test/abilities/stakeout.test.ts b/test/abilities/stakeout.test.ts index 24c8c47df5c..ba4325e0295 100644 --- a/test/abilities/stakeout.test.ts +++ b/test/abilities/stakeout.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { isBetween } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/abilities/storm_drain.test.ts b/test/abilities/storm_drain.test.ts index 36a2112edda..3a6c0aba100 100644 --- a/test/abilities/storm_drain.test.ts +++ b/test/abilities/storm_drain.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/supreme_overlord.test.ts b/test/abilities/supreme_overlord.test.ts index 6c2ca2d3677..7143b590f68 100644 --- a/test/abilities/supreme_overlord.test.ts +++ b/test/abilities/supreme_overlord.test.ts @@ -2,7 +2,7 @@ import { MoveId } from "#enums/move-id"; import type Move from "#app/data/moves/move"; import { AbilityId } from "#enums/ability-id"; import { SpeciesId } from "#enums/species-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; diff --git a/test/abilities/sweet_veil.test.ts b/test/abilities/sweet_veil.test.ts index 131feaf7f56..8a31e676ec5 100644 --- a/test/abilities/sweet_veil.test.ts +++ b/test/abilities/sweet_veil.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { CommandPhase } from "#app/phases/command-phase"; diff --git a/test/abilities/tera_shell.test.ts b/test/abilities/tera_shell.test.ts index 5889115ee95..26babca240d 100644 --- a/test/abilities/tera_shell.test.ts +++ b/test/abilities/tera_shell.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/abilities/unburden.test.ts b/test/abilities/unburden.test.ts index b1b10c378a3..9748b6340f0 100644 --- a/test/abilities/unburden.test.ts +++ b/test/abilities/unburden.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PostItemLostAbAttr } from "#app/data/abilities/ability"; import { StealHeldItemChanceAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; diff --git a/test/abilities/victory_star.test.ts b/test/abilities/victory_star.test.ts index 77f5de41bb1..a15beac8b2c 100644 --- a/test/abilities/victory_star.test.ts +++ b/test/abilities/victory_star.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/abilities/volt_absorb.test.ts b/test/abilities/volt_absorb.test.ts index 2e6abf30885..34dbbbd4783 100644 --- a/test/abilities/volt_absorb.test.ts +++ b/test/abilities/volt_absorb.test.ts @@ -7,7 +7,7 @@ import { SpeciesId } from "#enums/species-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; // See also: TypeImmunityAbAttr describe("Abilities - Volt Absorb", () => { diff --git a/test/abilities/wimp_out.test.ts b/test/abilities/wimp_out.test.ts index 2c2ab636961..05c848a75c0 100644 --- a/test/abilities/wimp_out.test.ts +++ b/test/abilities/wimp_out.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { BattlerIndex } from "#enums/battler-index"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import GameManager from "#test/testUtils/gameManager"; import { toDmgValue } from "#app/utils/common"; diff --git a/test/arena/arena_gravity.test.ts b/test/arena/arena_gravity.test.ts index 776bfa0a564..36fe0b58308 100644 --- a/test/arena/arena_gravity.test.ts +++ b/test/arena/arena_gravity.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; diff --git a/test/arena/weather_hail.test.ts b/test/arena/weather_hail.test.ts index 072fbd20498..27cf46fa9f2 100644 --- a/test/arena/weather_hail.test.ts +++ b/test/arena/weather_hail.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { WeatherType } from "#enums/weather-type"; diff --git a/test/battle/battle.test.ts b/test/battle/battle.test.ts index b93c913d09a..3eab06e2f48 100644 --- a/test/battle/battle.test.ts +++ b/test/battle/battle.test.ts @@ -1,6 +1,7 @@ import { allSpecies } from "#app/data/pokemon-species"; import { Stat } from "#enums/stat"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { BattleEndPhase } from "#app/phases/battle-end-phase"; import { CommandPhase } from "#app/phases/command-phase"; import { DamageAnimPhase } from "#app/phases/damage-anim-phase"; diff --git a/test/battle/double_battle.test.ts b/test/battle/double_battle.test.ts index 31bfc480c47..54c573813d7 100644 --- a/test/battle/double_battle.test.ts +++ b/test/battle/double_battle.test.ts @@ -1,6 +1,7 @@ import { Status } from "#app/data/status-effect"; import { AbilityId } from "#enums/ability-id"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { BattleEndPhase } from "#app/phases/battle-end-phase"; import { TurnInitPhase } from "#app/phases/turn-init-phase"; import { MoveId } from "#enums/move-id"; diff --git a/test/battle/inverse_battle.test.ts b/test/battle/inverse_battle.test.ts index b0d9c7bb755..66cab3e2d84 100644 --- a/test/battle/inverse_battle.test.ts +++ b/test/battle/inverse_battle.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; diff --git a/test/battlerTags/octolock.test.ts b/test/battlerTags/octolock.test.ts index 63784ed7f1b..d0214f495fc 100644 --- a/test/battlerTags/octolock.test.ts +++ b/test/battlerTags/octolock.test.ts @@ -1,6 +1,7 @@ import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import type Pokemon from "#app/field/pokemon"; -import { BattlerTagLapseType, OctolockTag, TrappedTag } from "#app/data/battler-tags"; +import { OctolockTag, TrappedTag } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { Stat } from "#enums/stat"; import GameManager from "#test/testUtils/gameManager"; diff --git a/test/battlerTags/substitute.test.ts b/test/battlerTags/substitute.test.ts index 703e0ae75f6..06aedab19f4 100644 --- a/test/battlerTags/substitute.test.ts +++ b/test/battlerTags/substitute.test.ts @@ -1,9 +1,10 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import type { PokemonTurnData, TurnMove } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import type BattleScene from "#app/battle-scene"; -import { BattlerTagLapseType, BindTag, SubstituteTag } from "#app/data/battler-tags"; +import { BindTag, SubstituteTag } from "#app/data/battler-tags"; +import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { MoveId } from "#enums/move-id"; import { PokemonAnimType } from "#app/enums/pokemon-anim-type"; import * as messages from "#app/messages"; diff --git a/test/data/status_effect.test.ts b/test/data/status_effect.test.ts index 4a543a04a1b..06e11dfeb76 100644 --- a/test/data/status_effect.test.ts +++ b/test/data/status_effect.test.ts @@ -6,7 +6,7 @@ import { getStatusEffectObtainText, getStatusEffectOverlapText, } from "#app/data/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/endless_boss.test.ts b/test/endless_boss.test.ts index 05c6594bad6..6814cf5e12a 100644 --- a/test/endless_boss.test.ts +++ b/test/endless_boss.test.ts @@ -1,6 +1,6 @@ import { BiomeId } from "#enums/biome-id"; import { SpeciesId } from "#enums/species-id"; -import { GameModes } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "#test/testUtils/gameManager"; diff --git a/test/enemy_command.test.ts b/test/enemy_command.test.ts index 8d6d1756a69..fabb1f1fdb0 100644 --- a/test/enemy_command.test.ts +++ b/test/enemy_command.test.ts @@ -5,7 +5,7 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import type { EnemyPokemon } from "#app/field/pokemon"; -import { AiType } from "#app/field/pokemon"; +import { AiType } from "#enums/ai-type"; import { randSeedInt } from "#app/utils/common"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; diff --git a/test/escape-calculations.test.ts b/test/escape-calculations.test.ts index fd1e411e786..ca51f40a509 100644 --- a/test/escape-calculations.test.ts +++ b/test/escape-calculations.test.ts @@ -1,6 +1,6 @@ import { AttemptRunPhase } from "#app/phases/attempt-run-phase"; import type { CommandPhase } from "#app/phases/command-phase"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { NumberHolder } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/final_boss.test.ts b/test/final_boss.test.ts index f1f894a5984..d3fcd3214bb 100644 --- a/test/final_boss.test.ts +++ b/test/final_boss.test.ts @@ -1,4 +1,4 @@ -import { GameModes } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { TurnHeldItemTransferModifier } from "#app/modifier/modifier"; import { AbilityId } from "#enums/ability-id"; import { BiomeId } from "#enums/biome-id"; diff --git a/test/game-mode.test.ts b/test/game-mode.test.ts index 0483d18e492..4a53739c45e 100644 --- a/test/game-mode.test.ts +++ b/test/game-mode.test.ts @@ -1,5 +1,6 @@ import type { GameMode } from "#app/game-mode"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import * as Utils from "#app/utils/common"; import GameManager from "#test/testUtils/gameManager"; diff --git a/test/imports.test.ts b/test/imports.test.ts index 540620d8bb4..8a5c735e950 100644 --- a/test/imports.test.ts +++ b/test/imports.test.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest"; async function importModule() { try { initStatsKeys(); - const { PokemonMove } = await import("#app/field/pokemon"); + const { PokemonMove } = await import("#app/data/moves/pokemon-move"); const { SpeciesId: Species } = await import("#enums/species-id"); return { PokemonMove, diff --git a/test/items/grip_claw.test.ts b/test/items/grip_claw.test.ts index 3c51e7f868d..9c3e6548140 100644 --- a/test/items/grip_claw.test.ts +++ b/test/items/grip_claw.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import type Pokemon from "#app/field/pokemon"; import type { ContactHeldItemTransferChanceModifier } from "#app/modifier/modifier"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/items/multi_lens.test.ts b/test/items/multi_lens.test.ts index be697eabcf8..11e4c04ec21 100644 --- a/test/items/multi_lens.test.ts +++ b/test/items/multi_lens.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Stat } from "#enums/stat"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/items/reviver_seed.test.ts b/test/items/reviver_seed.test.ts index 2ab3c5ffe74..54927130869 100644 --- a/test/items/reviver_seed.test.ts +++ b/test/items/reviver_seed.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import type { PokemonInstantReviveModifier } from "#app/modifier/modifier"; diff --git a/test/moves/after_you.test.ts b/test/moves/after_you.test.ts index 0e5ee1e7a8f..78372de3fb6 100644 --- a/test/moves/after_you.test.ts +++ b/test/moves/after_you.test.ts @@ -1,6 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { MovePhase } from "#app/phases/move-phase"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/alluring_voice.test.ts b/test/moves/alluring_voice.test.ts index 2cfb7a76317..132f83cd4c1 100644 --- a/test/moves/alluring_voice.test.ts +++ b/test/moves/alluring_voice.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BerryPhase } from "#app/phases/berry-phase"; diff --git a/test/moves/assist.test.ts b/test/moves/assist.test.ts index c0bdf2deea2..bc51f8bd06a 100644 --- a/test/moves/assist.test.ts +++ b/test/moves/assist.test.ts @@ -1,6 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Stat } from "#app/enums/stat"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { CommandPhase } from "#app/phases/command-phase"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/aurora_veil.test.ts b/test/moves/aurora_veil.test.ts index 7a00be40d3d..98b490b0e32 100644 --- a/test/moves/aurora_veil.test.ts +++ b/test/moves/aurora_veil.test.ts @@ -1,7 +1,6 @@ import type BattleScene from "#app/battle-scene"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type Move from "#app/data/moves/move"; -import { CritOnlyAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { ArenaTagType } from "#app/enums/arena-tag-type"; import type Pokemon from "#app/field/pokemon"; @@ -166,7 +165,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) = const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (globalScene.arena.getTagOnSide(ArenaTagType.AURORA_VEIL, side)) { - if (move.getAttrs(CritOnlyAttr).length === 0) { + if (move.getAttrs("CritOnlyAttr").length === 0) { globalScene.arena.applyTagsForSide( ArenaTagType.AURORA_VEIL, side, diff --git a/test/moves/baneful_bunker.test.ts b/test/moves/baneful_bunker.test.ts index 80b9b5470b1..eddfa87ead4 100644 --- a/test/moves/baneful_bunker.test.ts +++ b/test/moves/baneful_bunker.test.ts @@ -4,7 +4,7 @@ import GameManager from "#test/testUtils/gameManager"; import { SpeciesId } from "#enums/species-id"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { StatusEffect } from "#app/enums/status-effect"; describe("Moves - Baneful Bunker", () => { diff --git a/test/moves/baton_pass.test.ts b/test/moves/baton_pass.test.ts index b39e51428b1..f6256e95ce8 100644 --- a/test/moves/baton_pass.test.ts +++ b/test/moves/baton_pass.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import GameManager from "#test/testUtils/gameManager"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; diff --git a/test/moves/burning_jealousy.test.ts b/test/moves/burning_jealousy.test.ts index 2a74f661922..9e1898d9cd1 100644 --- a/test/moves/burning_jealousy.test.ts +++ b/test/moves/burning_jealousy.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { StatusEffect } from "#app/enums/status-effect"; diff --git a/test/moves/camouflage.test.ts b/test/moves/camouflage.test.ts index 53c44f1386b..03364265179 100644 --- a/test/moves/camouflage.test.ts +++ b/test/moves/camouflage.test.ts @@ -3,7 +3,7 @@ import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { TerrainType } from "#app/data/terrain"; import { PokemonType } from "#enums/pokemon-type"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; diff --git a/test/moves/ceaseless_edge.test.ts b/test/moves/ceaseless_edge.test.ts index 65f9b69509d..fcaddfb0d76 100644 --- a/test/moves/ceaseless_edge.test.ts +++ b/test/moves/ceaseless_edge.test.ts @@ -1,4 +1,5 @@ -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#app/enums/arena-tag-type"; diff --git a/test/moves/chloroblast.test.ts b/test/moves/chloroblast.test.ts index 02f7ac2165c..cf5e791d0b9 100644 --- a/test/moves/chloroblast.test.ts +++ b/test/moves/chloroblast.test.ts @@ -1,4 +1,4 @@ -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/copycat.test.ts b/test/moves/copycat.test.ts index 51d7d36535f..1691cc1478c 100644 --- a/test/moves/copycat.test.ts +++ b/test/moves/copycat.test.ts @@ -1,8 +1,8 @@ -import { BattlerIndex } from "#app/battle"; -import { RandomMoveAttr } from "#app/data/moves/move"; +import { BattlerIndex } from "#enums/battler-index"; +import type { RandomMoveAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { Stat } from "#app/enums/stat"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; @@ -27,7 +27,7 @@ describe("Moves - Copycat", () => { }); beforeEach(() => { - randomMoveAttr = allMoves[MoveId.METRONOME].getAttrs(RandomMoveAttr)[0]; + randomMoveAttr = allMoves[MoveId.METRONOME].getAttrs("RandomMoveAttr")[0]; game = new GameManager(phaserGame); game.override .moveset([MoveId.COPYCAT, MoveId.SPIKY_SHIELD, MoveId.SWORDS_DANCE, MoveId.SPLASH]) diff --git a/test/moves/destiny_bond.test.ts b/test/moves/destiny_bond.test.ts index 81c17551bec..a78d46b464b 100644 --- a/test/moves/destiny_bond.test.ts +++ b/test/moves/destiny_bond.test.ts @@ -1,5 +1,5 @@ import type { ArenaTrapTag } from "#app/data/arena-tag"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; @@ -8,7 +8,7 @@ import { SpeciesId } from "#enums/species-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { StatusEffect } from "#enums/status-effect"; import { PokemonInstantReviveModifier } from "#app/modifier/modifier"; diff --git a/test/moves/dig.test.ts b/test/moves/dig.test.ts index 052845ec50d..73540c6ed48 100644 --- a/test/moves/dig.test.ts +++ b/test/moves/dig.test.ts @@ -1,11 +1,11 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { StatusEffect } from "#enums/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { describe, beforeAll, afterEach, beforeEach, it, expect } from "vitest"; import GameManager from "#test/testUtils/gameManager"; diff --git a/test/moves/disable.test.ts b/test/moves/disable.test.ts index eacf8bf4857..a269a8177aa 100644 --- a/test/moves/disable.test.ts +++ b/test/moves/disable.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/dive.test.ts b/test/moves/dive.test.ts index cce1b5a6d26..9c467976775 100644 --- a/test/moves/dive.test.ts +++ b/test/moves/dive.test.ts @@ -1,6 +1,6 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { StatusEffect } from "#enums/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/doodle.test.ts b/test/moves/doodle.test.ts index 686bef144dd..d4d09b3a195 100644 --- a/test/moves/doodle.test.ts +++ b/test/moves/doodle.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Stat } from "#app/enums/stat"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/dragon_cheer.test.ts b/test/moves/dragon_cheer.test.ts index b1eaa3ad747..56feac513a1 100644 --- a/test/moves/dragon_cheer.test.ts +++ b/test/moves/dragon_cheer.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/dragon_tail.test.ts b/test/moves/dragon_tail.test.ts index 07441d9fb2d..8c456f27853 100644 --- a/test/moves/dragon_tail.test.ts +++ b/test/moves/dragon_tail.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { Status } from "#app/data/status-effect"; import { Challenges } from "#enums/challenges"; diff --git a/test/moves/dynamax_cannon.test.ts b/test/moves/dynamax_cannon.test.ts index 6207ef9b6ca..2cdba48c0ea 100644 --- a/test/moves/dynamax_cannon.test.ts +++ b/test/moves/dynamax_cannon.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { DamageAnimPhase } from "#app/phases/damage-anim-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; diff --git a/test/moves/electrify.test.ts b/test/moves/electrify.test.ts index 00f96d570a3..b6a3cac9fff 100644 --- a/test/moves/electrify.test.ts +++ b/test/moves/electrify.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/electro_shot.test.ts b/test/moves/electro_shot.test.ts index 160f90163e3..3f751687c59 100644 --- a/test/moves/electro_shot.test.ts +++ b/test/moves/electro_shot.test.ts @@ -1,7 +1,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { Stat } from "#enums/stat"; import { WeatherType } from "#enums/weather-type"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/encore.test.ts b/test/moves/encore.test.ts index cded90c4a73..120d065d528 100644 --- a/test/moves/encore.test.ts +++ b/test/moves/encore.test.ts @@ -1,6 +1,6 @@ import { BattlerTagType } from "#enums/battler-tag-type"; -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/fairy_lock.test.ts b/test/moves/fairy_lock.test.ts index 5624d038595..74524d67b38 100644 --- a/test/moves/fairy_lock.test.ts +++ b/test/moves/fairy_lock.test.ts @@ -1,4 +1,4 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagType } from "#app/enums/arena-tag-type"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/false_swipe.test.ts b/test/moves/false_swipe.test.ts index 48e4de6fb65..c98b76f1ef1 100644 --- a/test/moves/false_swipe.test.ts +++ b/test/moves/false_swipe.test.ts @@ -1,4 +1,4 @@ -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/fly.test.ts b/test/moves/fly.test.ts index 964d1b65a1e..7d8a6ee659e 100644 --- a/test/moves/fly.test.ts +++ b/test/moves/fly.test.ts @@ -1,13 +1,13 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { StatusEffect } from "#enums/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; describe("Moves - Fly", () => { diff --git a/test/moves/follow_me.test.ts b/test/moves/follow_me.test.ts index 567320a18e9..8279e7b325a 100644 --- a/test/moves/follow_me.test.ts +++ b/test/moves/follow_me.test.ts @@ -1,5 +1,5 @@ import { Stat } from "#enums/stat"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/freeze_dry.test.ts b/test/moves/freeze_dry.test.ts index dc6af507b16..f1577d3d6c5 100644 --- a/test/moves/freeze_dry.test.ts +++ b/test/moves/freeze_dry.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/fusion_flare_bolt.test.ts b/test/moves/fusion_flare_bolt.test.ts index 1a5d9e44bab..f10ede8717c 100644 --- a/test/moves/fusion_flare_bolt.test.ts +++ b/test/moves/fusion_flare_bolt.test.ts @@ -1,5 +1,5 @@ import { Stat } from "#enums/stat"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import type Move from "#app/data/moves/move"; import { DamageAnimPhase } from "#app/phases/damage-anim-phase"; diff --git a/test/moves/gastro_acid.test.ts b/test/moves/gastro_acid.test.ts index 6e06f441959..28f2c8e8476 100644 --- a/test/moves/gastro_acid.test.ts +++ b/test/moves/gastro_acid.test.ts @@ -1,8 +1,8 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import GameManager from "#test/testUtils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; diff --git a/test/moves/geomancy.test.ts b/test/moves/geomancy.test.ts index 16244fed93f..452022b4cf1 100644 --- a/test/moves/geomancy.test.ts +++ b/test/moves/geomancy.test.ts @@ -1,6 +1,6 @@ import type { EffectiveStat } from "#enums/stat"; import { Stat } from "#enums/stat"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/gigaton_hammer.test.ts b/test/moves/gigaton_hammer.test.ts index e61a383acc5..be7adf53aa7 100644 --- a/test/moves/gigaton_hammer.test.ts +++ b/test/moves/gigaton_hammer.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import GameManager from "#test/testUtils/gameManager"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/grudge.test.ts b/test/moves/grudge.test.ts index b6ef25d41ff..63018a419e3 100644 --- a/test/moves/grudge.test.ts +++ b/test/moves/grudge.test.ts @@ -1,7 +1,7 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; diff --git a/test/moves/heal_block.test.ts b/test/moves/heal_block.test.ts index 58e1a5e04a5..39e8efea827 100644 --- a/test/moves/heal_block.test.ts +++ b/test/moves/heal_block.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { BattlerIndex } from "#enums/battler-index"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import GameManager from "#test/testUtils/gameManager"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; diff --git a/test/moves/instruct.test.ts b/test/moves/instruct.test.ts index e0cfa93cf59..74de4c5da17 100644 --- a/test/moves/instruct.test.ts +++ b/test/moves/instruct.test.ts @@ -1,7 +1,7 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import type Pokemon from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import type { MovePhase } from "#app/phases/move-phase"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/jaw_lock.test.ts b/test/moves/jaw_lock.test.ts index 6084a47ad99..e0815a4c3c9 100644 --- a/test/moves/jaw_lock.test.ts +++ b/test/moves/jaw_lock.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BerryPhase } from "#app/phases/berry-phase"; diff --git a/test/moves/lash_out.test.ts b/test/moves/lash_out.test.ts index a63ab2a467c..c0c0881b340 100644 --- a/test/moves/lash_out.test.ts +++ b/test/moves/lash_out.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/last-resort.test.ts b/test/moves/last-resort.test.ts index 0e6c1a6ba15..e4b8346053b 100644 --- a/test/moves/last-resort.test.ts +++ b/test/moves/last-resort.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/last_respects.test.ts b/test/moves/last_respects.test.ts index 96a8b5955d0..b2eb4c6695b 100644 --- a/test/moves/last_respects.test.ts +++ b/test/moves/last_respects.test.ts @@ -1,5 +1,5 @@ import { MoveId } from "#enums/move-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { SpeciesId } from "#enums/species-id"; import { AbilityId } from "#enums/ability-id"; import GameManager from "#test/testUtils/gameManager"; diff --git a/test/moves/light_screen.test.ts b/test/moves/light_screen.test.ts index 4230790e688..404d30920c7 100644 --- a/test/moves/light_screen.test.ts +++ b/test/moves/light_screen.test.ts @@ -1,7 +1,6 @@ import type BattleScene from "#app/battle-scene"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type Move from "#app/data/moves/move"; -import { CritOnlyAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#app/enums/arena-tag-type"; @@ -129,7 +128,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) = const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (globalScene.arena.getTagOnSide(ArenaTagType.LIGHT_SCREEN, side)) { - if (move.getAttrs(CritOnlyAttr).length === 0) { + if (move.getAttrs("CritOnlyAttr").length === 0) { globalScene.arena.applyTagsForSide( ArenaTagType.LIGHT_SCREEN, side, diff --git a/test/moves/magic_coat.test.ts b/test/moves/magic_coat.test.ts index 4f9e3977305..a20aaf38043 100644 --- a/test/moves/magic_coat.test.ts +++ b/test/moves/magic_coat.test.ts @@ -1,11 +1,11 @@ -import { BattlerIndex } from "#app/battle"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { BattlerIndex } from "#enums/battler-index"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import { ArenaTagType } from "#app/enums/arena-tag-type"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { Stat } from "#app/enums/stat"; import { StatusEffect } from "#app/enums/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/metal_burst.test.ts b/test/moves/metal_burst.test.ts index 0222dd222be..bcb9d938985 100644 --- a/test/moves/metal_burst.test.ts +++ b/test/moves/metal_burst.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/metronome.test.ts b/test/moves/metronome.test.ts index 0e6db09ae5c..ec610eeed45 100644 --- a/test/moves/metronome.test.ts +++ b/test/moves/metronome.test.ts @@ -1,5 +1,5 @@ import { RechargingTag, SemiInvulnerableTag } from "#app/data/battler-tags"; -import { RandomMoveAttr } from "#app/data/moves/move"; +import type { RandomMoveAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { Stat } from "#app/enums/stat"; @@ -27,7 +27,7 @@ describe("Moves - Metronome", () => { }); beforeEach(() => { - randomMoveAttr = allMoves[MoveId.METRONOME].getAttrs(RandomMoveAttr)[0]; + randomMoveAttr = allMoves[MoveId.METRONOME].getAttrs("RandomMoveAttr")[0]; game = new GameManager(phaserGame); game.override .moveset([MoveId.METRONOME, MoveId.SPLASH]) diff --git a/test/moves/miracle_eye.test.ts b/test/moves/miracle_eye.test.ts index dd5fb1c355b..1238ae6a650 100644 --- a/test/moves/miracle_eye.test.ts +++ b/test/moves/miracle_eye.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; diff --git a/test/moves/mirror_move.test.ts b/test/moves/mirror_move.test.ts index 18e115745b9..fe40402e5a2 100644 --- a/test/moves/mirror_move.test.ts +++ b/test/moves/mirror_move.test.ts @@ -1,6 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Stat } from "#app/enums/stat"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/moongeist_beam.test.ts b/test/moves/moongeist_beam.test.ts index f462d81943f..28bd3f70daa 100644 --- a/test/moves/moongeist_beam.test.ts +++ b/test/moves/moongeist_beam.test.ts @@ -1,4 +1,3 @@ -import { RandomMoveAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; @@ -49,7 +48,7 @@ describe("Moves - Moongeist Beam", () => { // Also covers Photon Geyser and Sunsteel Strike it("should not ignore enemy abilities when called by another move, such as metronome", async () => { await game.classicMode.startBattle([SpeciesId.MILOTIC]); - vi.spyOn(allMoves[MoveId.METRONOME].getAttrs(RandomMoveAttr)[0], "getMoveOverride").mockReturnValue( + vi.spyOn(allMoves[MoveId.METRONOME].getAttrs("RandomMoveAttr")[0], "getMoveOverride").mockReturnValue( MoveId.MOONGEIST_BEAM, ); diff --git a/test/moves/multi_target.test.ts b/test/moves/multi_target.test.ts index 4572097296c..139b669da7b 100644 --- a/test/moves/multi_target.test.ts +++ b/test/moves/multi_target.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { SpeciesId } from "#enums/species-id"; import { toDmgValue } from "#app/utils/common"; diff --git a/test/moves/order_up.test.ts b/test/moves/order_up.test.ts index c6ca7ac06da..adf37c0719e 100644 --- a/test/moves/order_up.test.ts +++ b/test/moves/order_up.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattlerTagType } from "#enums/battler-tag-type"; import { PokemonAnimType } from "#enums/pokemon-anim-type"; import type { EffectiveStat } from "#enums/stat"; diff --git a/test/moves/plasma_fists.test.ts b/test/moves/plasma_fists.test.ts index 9493f69d70f..7d1985be13e 100644 --- a/test/moves/plasma_fists.test.ts +++ b/test/moves/plasma_fists.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/pledge_moves.test.ts b/test/moves/pledge_moves.test.ts index 2500563d44e..f653e245f6f 100644 --- a/test/moves/pledge_moves.test.ts +++ b/test/moves/pledge_moves.test.ts @@ -1,7 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allAbilities } from "#app/data/data-lists"; -import { ArenaTagSide } from "#app/data/arena-tag"; -import { FlinchAttr } from "#app/data/moves/move"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { allMoves } from "#app/data/data-lists"; import { PokemonType } from "#enums/pokemon-type"; import { ArenaTagType } from "#enums/arena-tag-type"; @@ -228,7 +227,7 @@ describe("Moves - Pledge Moves", () => { await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); - const ironHeadFlinchAttr = allMoves[MoveId.IRON_HEAD].getAttrs(FlinchAttr)[0]; + const ironHeadFlinchAttr = allMoves[MoveId.IRON_HEAD].getAttrs("FlinchAttr")[0]; vi.spyOn(ironHeadFlinchAttr, "getMoveChance"); game.move.select(MoveId.WATER_PLEDGE, 0, BattlerIndex.ENEMY); diff --git a/test/moves/pollen_puff.test.ts b/test/moves/pollen_puff.test.ts index d61303bcfcc..e6dcd2c41d0 100644 --- a/test/moves/pollen_puff.test.ts +++ b/test/moves/pollen_puff.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/powder.test.ts b/test/moves/powder.test.ts index d335e29996e..38e35d60335 100644 --- a/test/moves/powder.test.ts +++ b/test/moves/powder.test.ts @@ -1,5 +1,6 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult, PokemonMove } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; +import { MoveResult } from "#enums/move-result"; import { BerryPhase } from "#app/phases/berry-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/moves/protect.test.ts b/test/moves/protect.test.ts index 519021023fa..754a3433701 100644 --- a/test/moves/protect.test.ts +++ b/test/moves/protect.test.ts @@ -6,9 +6,10 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { Stat } from "#enums/stat"; import { allMoves } from "#app/data/data-lists"; -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; describe("Moves - Protect", () => { let phaserGame: Phaser.Game; diff --git a/test/moves/purify.test.ts b/test/moves/purify.test.ts index cab0a70818f..0510260b755 100644 --- a/test/moves/purify.test.ts +++ b/test/moves/purify.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Status } from "#app/data/status-effect"; import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import { MoveEndPhase } from "#app/phases/move-end-phase"; diff --git a/test/moves/quash.test.ts b/test/moves/quash.test.ts index 88cb0aba31f..7c8306acd22 100644 --- a/test/moves/quash.test.ts +++ b/test/moves/quash.test.ts @@ -1,9 +1,9 @@ import { SpeciesId } from "#enums/species-id"; import { MoveId } from "#enums/move-id"; import { AbilityId } from "#enums/ability-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { WeatherType } from "#enums/weather-type"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { describe, beforeAll, afterEach, beforeEach, it, expect } from "vitest"; diff --git a/test/moves/quick_guard.test.ts b/test/moves/quick_guard.test.ts index 0c0ab8d6ad0..49f501fb839 100644 --- a/test/moves/quick_guard.test.ts +++ b/test/moves/quick_guard.test.ts @@ -5,8 +5,8 @@ import { SpeciesId } from "#enums/species-id"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { Stat } from "#enums/stat"; -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; describe("Moves - Quick Guard", () => { let phaserGame: Phaser.Game; diff --git a/test/moves/rage_fist.test.ts b/test/moves/rage_fist.test.ts index cd9147637a5..31dd987cb87 100644 --- a/test/moves/rage_fist.test.ts +++ b/test/moves/rage_fist.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/rage_powder.test.ts b/test/moves/rage_powder.test.ts index e3212e9876c..807000a0ff0 100644 --- a/test/moves/rage_powder.test.ts +++ b/test/moves/rage_powder.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/reflect.test.ts b/test/moves/reflect.test.ts index d13fb7a095c..5e10de42a3c 100644 --- a/test/moves/reflect.test.ts +++ b/test/moves/reflect.test.ts @@ -1,7 +1,6 @@ import type BattleScene from "#app/battle-scene"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type Move from "#app/data/moves/move"; -import { CritOnlyAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#app/enums/arena-tag-type"; @@ -145,7 +144,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) = const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (globalScene.arena.getTagOnSide(ArenaTagType.REFLECT, side)) { - if (move.getAttrs(CritOnlyAttr).length === 0) { + if (move.getAttrs("CritOnlyAttr").length === 0) { globalScene.arena.applyTagsForSide(ArenaTagType.REFLECT, side, false, attacker, move.category, multiplierHolder); } } diff --git a/test/moves/revival_blessing.test.ts b/test/moves/revival_blessing.test.ts index 07ebf657c66..f22c0467378 100644 --- a/test/moves/revival_blessing.test.ts +++ b/test/moves/revival_blessing.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import { toDmgValue } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/roost.test.ts b/test/moves/roost.test.ts index 76aab1e572f..1e588cb1e15 100644 --- a/test/moves/roost.test.ts +++ b/test/moves/roost.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/round.test.ts b/test/moves/round.test.ts index 503ce125582..630137b7dce 100644 --- a/test/moves/round.test.ts +++ b/test/moves/round.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import type { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/moves/safeguard.test.ts b/test/moves/safeguard.test.ts index fc8bef80d6d..2ba53016833 100644 --- a/test/moves/safeguard.test.ts +++ b/test/moves/safeguard.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PostDefendContactApplyStatusEffectAbAttr } from "#app/data/abilities/ability"; import { allAbilities } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/moves/scale_shot.test.ts b/test/moves/scale_shot.test.ts index f61a9a1e276..a5872579003 100644 --- a/test/moves/scale_shot.test.ts +++ b/test/moves/scale_shot.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { DamageAnimPhase } from "#app/phases/damage-anim-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; diff --git a/test/moves/secret_power.test.ts b/test/moves/secret_power.test.ts index ac06f03698c..d555431656f 100644 --- a/test/moves/secret_power.test.ts +++ b/test/moves/secret_power.test.ts @@ -8,9 +8,9 @@ import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { StatusEffect } from "#enums/status-effect"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { ArenaTagType } from "#enums/arena-tag-type"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { MoveEffectChanceMultiplierAbAttr } from "#app/data/abilities/ability"; import { allAbilities } from "#app/data/data-lists"; diff --git a/test/moves/shed_tail.test.ts b/test/moves/shed_tail.test.ts index 84a5d5ba914..81ab9215bc9 100644 --- a/test/moves/shed_tail.test.ts +++ b/test/moves/shed_tail.test.ts @@ -1,5 +1,5 @@ import { SubstituteTag } from "#app/data/battler-tags"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/shell_side_arm.test.ts b/test/moves/shell_side_arm.test.ts index ad79091a5e3..35246e10e3f 100644 --- a/test/moves/shell_side_arm.test.ts +++ b/test/moves/shell_side_arm.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { ShellSideArmCategoryAttr } from "#app/data/moves/move"; +import { BattlerIndex } from "#enums/battler-index"; +import type { ShellSideArmCategoryAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import type Move from "#app/data/moves/move"; import { AbilityId } from "#enums/ability-id"; @@ -27,7 +27,7 @@ describe("Moves - Shell Side Arm", () => { beforeEach(() => { shellSideArm = allMoves[MoveId.SHELL_SIDE_ARM]; - shellSideArmAttr = shellSideArm.getAttrs(ShellSideArmCategoryAttr)[0]; + shellSideArmAttr = shellSideArm.getAttrs("ShellSideArmCategoryAttr")[0]; game = new GameManager(phaserGame); game.override .moveset([MoveId.SHELL_SIDE_ARM, MoveId.SPLASH]) diff --git a/test/moves/shell_trap.test.ts b/test/moves/shell_trap.test.ts index 9a38bf4486b..a3f55cef10f 100644 --- a/test/moves/shell_trap.test.ts +++ b/test/moves/shell_trap.test.ts @@ -1,8 +1,8 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { BerryPhase } from "#app/phases/berry-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase"; import { MovePhase } from "#app/phases/move-phase"; diff --git a/test/moves/sketch.test.ts b/test/moves/sketch.test.ts index 23e7f4ef3ab..c6fb7b4a32a 100644 --- a/test/moves/sketch.test.ts +++ b/test/moves/sketch.test.ts @@ -1,12 +1,13 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { MoveResult, PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; +import { MoveResult } from "#enums/move-result"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { StatusEffect } from "#app/enums/status-effect"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { RandomMoveAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; diff --git a/test/moves/sleep_talk.test.ts b/test/moves/sleep_talk.test.ts index 820a5f9082a..1d9aec77ea2 100644 --- a/test/moves/sleep_talk.test.ts +++ b/test/moves/sleep_talk.test.ts @@ -1,6 +1,6 @@ import { Stat } from "#app/enums/stat"; import { StatusEffect } from "#app/enums/status-effect"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/solar_beam.test.ts b/test/moves/solar_beam.test.ts index 7515843a13f..55d2ee5d13c 100644 --- a/test/moves/solar_beam.test.ts +++ b/test/moves/solar_beam.test.ts @@ -1,7 +1,7 @@ import { allMoves } from "#app/data/data-lists"; import { BattlerTagType } from "#enums/battler-tag-type"; import { WeatherType } from "#enums/weather-type"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/spectral_thief.test.ts b/test/moves/spectral_thief.test.ts index df560169078..808e9174caf 100644 --- a/test/moves/spectral_thief.test.ts +++ b/test/moves/spectral_thief.test.ts @@ -1,5 +1,5 @@ import { AbilityId } from "#enums/ability-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Stat } from "#enums/stat"; import { allMoves } from "#app/data/data-lists"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/spikes.test.ts b/test/moves/spikes.test.ts index 278c4510239..d847f296e59 100644 --- a/test/moves/spikes.test.ts +++ b/test/moves/spikes.test.ts @@ -4,7 +4,8 @@ import { SpeciesId } from "#enums/species-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTrapTag } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; describe("Moves - Spikes", () => { let phaserGame: Phaser.Game; diff --git a/test/moves/spit_up.test.ts b/test/moves/spit_up.test.ts index 2d576168f4c..83549c28f40 100644 --- a/test/moves/spit_up.test.ts +++ b/test/moves/spit_up.test.ts @@ -3,7 +3,7 @@ import { StockpilingTag } from "#app/data/battler-tags"; import { allMoves } from "#app/data/data-lists"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import type { TurnMove } from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import GameManager from "#test/testUtils/gameManager"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/spotlight.test.ts b/test/moves/spotlight.test.ts index 2798dfa282a..602cedcaec9 100644 --- a/test/moves/spotlight.test.ts +++ b/test/moves/spotlight.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/steamroller.test.ts b/test/moves/steamroller.test.ts index f4f8131ff7b..4eb011c47f5 100644 --- a/test/moves/steamroller.test.ts +++ b/test/moves/steamroller.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import type { DamageCalculationResult } from "#app/field/pokemon"; diff --git a/test/moves/stockpile.test.ts b/test/moves/stockpile.test.ts index 5bf2b74d4d9..4baa7949bc6 100644 --- a/test/moves/stockpile.test.ts +++ b/test/moves/stockpile.test.ts @@ -1,7 +1,7 @@ import { Stat } from "#enums/stat"; import { StockpilingTag } from "#app/data/battler-tags"; import type { TurnMove } from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { CommandPhase } from "#app/phases/command-phase"; import { TurnInitPhase } from "#app/phases/turn-init-phase"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/moves/substitute.test.ts b/test/moves/substitute.test.ts index 454e729a67b..857f20c7fa0 100644 --- a/test/moves/substitute.test.ts +++ b/test/moves/substitute.test.ts @@ -1,12 +1,12 @@ -import { BattlerIndex } from "#app/battle"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { BattlerIndex } from "#enums/battler-index"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { SubstituteTag, TrappedTag } from "#app/data/battler-tags"; import { StealHeldItemChanceAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import type { CommandPhase } from "#app/phases/command-phase"; import GameManager from "#test/testUtils/gameManager"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { UiMode } from "#enums/ui-mode"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; diff --git a/test/moves/swallow.test.ts b/test/moves/swallow.test.ts index 4452636c3af..bb95c2c593d 100644 --- a/test/moves/swallow.test.ts +++ b/test/moves/swallow.test.ts @@ -2,7 +2,7 @@ import { Stat } from "#enums/stat"; import { StockpilingTag } from "#app/data/battler-tags"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import type { TurnMove } from "#app/field/pokemon"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { MovePhase } from "#app/phases/move-phase"; import { TurnInitPhase } from "#app/phases/turn-init-phase"; import { AbilityId } from "#enums/ability-id"; diff --git a/test/moves/syrup_bomb.test.ts b/test/moves/syrup_bomb.test.ts index 76bc7e7bae0..4b2821b439c 100644 --- a/test/moves/syrup_bomb.test.ts +++ b/test/moves/syrup_bomb.test.ts @@ -5,7 +5,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { Stat } from "#enums/stat"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - SYRUP BOMB", () => { diff --git a/test/moves/tailwind.test.ts b/test/moves/tailwind.test.ts index 83078d7bf58..874934fc8f3 100644 --- a/test/moves/tailwind.test.ts +++ b/test/moves/tailwind.test.ts @@ -1,4 +1,4 @@ -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagType } from "#app/enums/arena-tag-type"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/tar_shot.test.ts b/test/moves/tar_shot.test.ts index 21eace0ef1f..fefd1a30e1e 100644 --- a/test/moves/tar_shot.test.ts +++ b/test/moves/tar_shot.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/taunt.test.ts b/test/moves/taunt.test.ts index e214bd77ef7..fabb95f98b2 100644 --- a/test/moves/taunt.test.ts +++ b/test/moves/taunt.test.ts @@ -4,7 +4,7 @@ import { AbilityId } from "#enums/ability-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { BattlerTagType } from "#enums/battler-tag-type"; describe("Moves - Taunt", () => { diff --git a/test/moves/telekinesis.test.ts b/test/moves/telekinesis.test.ts index 18df17f1587..5c9f1e22395 100644 --- a/test/moves/telekinesis.test.ts +++ b/test/moves/telekinesis.test.ts @@ -3,11 +3,11 @@ import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; describe("Moves - Telekinesis", () => { let phaserGame: Phaser.Game; diff --git a/test/moves/tera_blast.test.ts b/test/moves/tera_blast.test.ts index 4e3f9c6869b..2f3bdcebfcf 100644 --- a/test/moves/tera_blast.test.ts +++ b/test/moves/tera_blast.test.ts @@ -1,6 +1,6 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { Stat } from "#enums/stat"; -import { TeraMoveCategoryAttr } from "#app/data/moves/move"; +import type { TeraMoveCategoryAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import type Move from "#app/data/moves/move"; import { PokemonType } from "#enums/pokemon-type"; @@ -23,7 +23,7 @@ describe("Moves - Tera Blast", () => { type: Phaser.HEADLESS, }); moveToCheck = allMoves[MoveId.TERA_BLAST]; - teraBlastAttr = moveToCheck.getAttrs(TeraMoveCategoryAttr)[0]; + teraBlastAttr = moveToCheck.getAttrs("TeraMoveCategoryAttr")[0]; }); afterEach(() => { diff --git a/test/moves/tera_starstorm.test.ts b/test/moves/tera_starstorm.test.ts index bd1fa14398d..2eaf2ec0372 100644 --- a/test/moves/tera_starstorm.test.ts +++ b/test/moves/tera_starstorm.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { PokemonType } from "#enums/pokemon-type"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/throat_chop.test.ts b/test/moves/throat_chop.test.ts index c1c9c4e94ad..aa92f657c86 100644 --- a/test/moves/throat_chop.test.ts +++ b/test/moves/throat_chop.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#app/enums/stat"; diff --git a/test/moves/torment.test.ts b/test/moves/torment.test.ts index b35b16249ef..e4d926d9601 100644 --- a/test/moves/torment.test.ts +++ b/test/moves/torment.test.ts @@ -4,7 +4,7 @@ import { AbilityId } from "#enums/ability-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { BattlerTagType } from "#enums/battler-tag-type"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; diff --git a/test/moves/toxic.test.ts b/test/moves/toxic.test.ts index 5cdfe78d502..eb23885b4b5 100644 --- a/test/moves/toxic.test.ts +++ b/test/moves/toxic.test.ts @@ -4,7 +4,7 @@ import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { StatusEffect } from "#enums/status-effect"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { allMoves } from "#app/data/data-lists"; describe("Moves - Toxic", () => { diff --git a/test/moves/toxic_spikes.test.ts b/test/moves/toxic_spikes.test.ts index 11ed7514633..bf1f5acc1cb 100644 --- a/test/moves/toxic_spikes.test.ts +++ b/test/moves/toxic_spikes.test.ts @@ -1,7 +1,8 @@ import type { ArenaTrapTag } from "#app/data/arena-tag"; -import { ArenaTagSide } from "#app/data/arena-tag"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type { SessionSaveData } from "#app/system/game-data"; -import { decrypt, encrypt, GameData } from "#app/system/game-data"; +import { GameData } from "#app/system/game-data"; +import { decrypt, encrypt } from "#app/utils/data"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagType } from "#enums/arena-tag-type"; import { MoveId } from "#enums/move-id"; diff --git a/test/moves/transform.test.ts b/test/moves/transform.test.ts index ca326da5748..8ee65802b37 100644 --- a/test/moves/transform.test.ts +++ b/test/moves/transform.test.ts @@ -6,7 +6,7 @@ import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { MoveId } from "#enums/move-id"; import { Stat, EFFECTIVE_STATS } from "#enums/stat"; import { AbilityId } from "#enums/ability-id"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; // TODO: Add more tests once Transform is fully implemented describe("Moves - Transform", () => { diff --git a/test/moves/triple_arrows.test.ts b/test/moves/triple_arrows.test.ts index 6a14a7642fa..89ccb4e5b04 100644 --- a/test/moves/triple_arrows.test.ts +++ b/test/moves/triple_arrows.test.ts @@ -1,4 +1,4 @@ -import { FlinchAttr, StatStageChangeAttr } from "#app/data/moves/move"; +import type { FlinchAttr, StatStageChangeAttr } from "#app/data/moves/move"; import { allMoves } from "#app/data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; @@ -20,8 +20,8 @@ describe("Moves - Triple Arrows", () => { type: Phaser.HEADLESS, }); tripleArrows = allMoves[MoveId.TRIPLE_ARROWS]; - flinchAttr = tripleArrows.getAttrs(FlinchAttr)[0]; - defDropAttr = tripleArrows.getAttrs(StatStageChangeAttr)[0]; + flinchAttr = tripleArrows.getAttrs("FlinchAttr")[0]; + defDropAttr = tripleArrows.getAttrs("StatStageChangeAttr")[0]; }); afterEach(() => { diff --git a/test/moves/upper_hand.test.ts b/test/moves/upper_hand.test.ts index 741594c7e47..e3d490ba6fa 100644 --- a/test/moves/upper_hand.test.ts +++ b/test/moves/upper_hand.test.ts @@ -1,5 +1,5 @@ -import { BattlerIndex } from "#app/battle"; -import { MoveResult } from "#app/field/pokemon"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/moves/whirlwind.test.ts b/test/moves/whirlwind.test.ts index c457bdb67d7..00d7c16561c 100644 --- a/test/moves/whirlwind.test.ts +++ b/test/moves/whirlwind.test.ts @@ -1,7 +1,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { Challenges } from "#enums/challenges"; import { PokemonType } from "#enums/pokemon-type"; -import { MoveResult } from "#app/field/pokemon"; +import { MoveResult } from "#enums/move-result"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; @@ -11,7 +11,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite import { Status } from "#app/data/status-effect"; import { StatusEffect } from "#enums/status-effect"; import { globalScene } from "#app/global-scene"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { BattleType } from "#enums/battle-type"; import { TrainerType } from "#enums/trainer-type"; diff --git a/test/moves/will_o_wisp.test.ts b/test/moves/will_o_wisp.test.ts index ce747dbad0b..40495009d2a 100644 --- a/test/moves/will_o_wisp.test.ts +++ b/test/moves/will_o_wisp.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; diff --git a/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts b/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts index 786090aa8d6..d208a859825 100644 --- a/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts +++ b/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts @@ -8,7 +8,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vite import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils"; import type BattleScene from "#app/battle-scene"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { AnOfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; diff --git a/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts b/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts index 7e569d0cdf7..8e58a0ca242 100644 --- a/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts +++ b/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts @@ -11,7 +11,7 @@ import { } from "#test/mystery-encounter/encounter-test-utils"; import { MoveId } from "#enums/move-id"; import type BattleScene from "#app/battle-scene"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { UiMode } from "#enums/ui-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; diff --git a/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index fc0ef0e5a86..778f8397417 100644 --- a/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -15,7 +15,7 @@ import { import { MoveId } from "#enums/move-id"; import type BattleScene from "#app/battle-scene"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { UiMode } from "#enums/ui-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; diff --git a/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts b/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts index 76a562b5851..ee4aefd9904 100644 --- a/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts +++ b/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts @@ -17,7 +17,7 @@ import { MoveId } from "#enums/move-id"; import { DancingLessonsEncounter } from "#app/data/mystery-encounters/encounters/dancing-lessons-encounter"; import { UiMode } from "#enums/ui-mode"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; import { CommandPhase } from "#app/phases/command-phase"; import { MovePhase } from "#app/phases/move-phase"; diff --git a/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts b/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts index 7038fff3117..e0e8b3d90d6 100644 --- a/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts +++ b/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts @@ -11,7 +11,7 @@ import { } from "#test/mystery-encounter/encounter-test-utils"; import { MoveId } from "#enums/move-id"; import type BattleScene from "#app/battle-scene"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { UiMode } from "#enums/ui-mode"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; diff --git a/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts b/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts index 4eaf2cef1da..e31a3a5cc3c 100644 --- a/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts +++ b/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts @@ -22,7 +22,7 @@ import { CommandPhase } from "#app/phases/command-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fun-and-games-encounter"; import { MoveId } from "#enums/move-id"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; const namespace = "mysteryEncounters/funAndGames"; diff --git a/test/mystery-encounter/encounters/part-timer-encounter.test.ts b/test/mystery-encounter/encounters/part-timer-encounter.test.ts index fa85f373a35..be985ea0593 100644 --- a/test/mystery-encounter/encounters/part-timer-encounter.test.ts +++ b/test/mystery-encounter/encounters/part-timer-encounter.test.ts @@ -14,7 +14,7 @@ import { CIVILIZATION_ENCOUNTER_BIOMES } from "#app/data/mystery-encounters/myst import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { PartTimerEncounter } from "#app/data/mystery-encounters/encounters/part-timer-encounter"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { MoveId } from "#enums/move-id"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; diff --git a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts index e50a19a0a80..5926c1ed2e7 100644 --- a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts @@ -17,7 +17,7 @@ import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters import { Nature } from "#enums/nature"; import { BerryType } from "#enums/berry-type"; import { BattlerTagType } from "#enums/battler-tag-type"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { UiMode } from "#enums/ui-mode"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import { BerryModifier, PokemonBaseStatTotalModifier } from "#app/modifier/modifier"; diff --git a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts index 999936c8832..47c75eb19fc 100644 --- a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -12,7 +12,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species"; import { BiomeId } from "#enums/biome-id"; import { MysteryEncounterType } from "#app/enums/mystery-encounter-type"; import { SpeciesId } from "#enums/species-id"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { HealShopCostModifier, HitHealModifier, TurnHealModifier } from "#app/modifier/modifier"; import { ModifierTier } from "#app/modifier/modifier-tier"; import { modifierTypes, type PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; diff --git a/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts b/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts index 0c3131de1d2..12545b8d70a 100644 --- a/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts +++ b/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts @@ -10,7 +10,7 @@ import { } from "#test/mystery-encounter/encounter-test-utils"; import { MoveId } from "#enums/move-id"; import type BattleScene from "#app/battle-scene"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { initSceneWithoutEncounterPhase } from "#test/testUtils/gameManagerUtils"; diff --git a/test/phases/frenzy-move-reset.test.ts b/test/phases/frenzy-move-reset.test.ts index 1879a14d301..878c58d8666 100644 --- a/test/phases/frenzy-move-reset.test.ts +++ b/test/phases/frenzy-move-reset.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; import { StatusEffect } from "#enums/status-effect"; diff --git a/test/reload.test.ts b/test/reload.test.ts index 6c535ca4722..8b817bbfe97 100644 --- a/test/reload.test.ts +++ b/test/reload.test.ts @@ -1,4 +1,4 @@ -import { GameModes } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import type OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler"; import { UiMode } from "#enums/ui-mode"; diff --git a/test/testUtils/gameManager.ts b/test/testUtils/gameManager.ts index 437c8d9f083..128217a6472 100644 --- a/test/testUtils/gameManager.ts +++ b/test/testUtils/gameManager.ts @@ -1,9 +1,10 @@ import { updateUserInfo } from "#app/account"; -import { BattlerIndex } from "#app/battle"; +import { BattlerIndex } from "#enums/battler-index"; import BattleScene from "#app/battle-scene"; import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import Trainer from "#app/field/trainer"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { globalScene } from "#app/global-scene"; import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; import overrides from "#app/overrides"; diff --git a/test/testUtils/gameManagerUtils.ts b/test/testUtils/gameManagerUtils.ts index 18dd83995a3..d582f8c04e3 100644 --- a/test/testUtils/gameManagerUtils.ts +++ b/test/testUtils/gameManagerUtils.ts @@ -5,7 +5,8 @@ import { getDailyRunStarters } from "#app/data/daily-run"; import { Gender } from "#app/data/gender"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; import { PlayerPokemon } from "#app/field/pokemon"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import type { StarterMoveset } from "#app/system/game-data"; import type { Starter } from "#app/ui/starter-select-ui-handler"; import { MoveId } from "#enums/move-id"; diff --git a/test/testUtils/helpers/classicModeHelper.ts b/test/testUtils/helpers/classicModeHelper.ts index c4f086bd628..eff97483777 100644 --- a/test/testUtils/helpers/classicModeHelper.ts +++ b/test/testUtils/helpers/classicModeHelper.ts @@ -1,6 +1,7 @@ import { BattleStyle } from "#app/enums/battle-style"; import type { SpeciesId } from "#enums/species-id"; -import { GameModes, getGameMode } from "#app/game-mode"; +import { getGameMode } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import overrides from "#app/overrides"; import { CommandPhase } from "#app/phases/command-phase"; import { EncounterPhase } from "#app/phases/encounter-phase"; diff --git a/test/testUtils/helpers/field-helper.ts b/test/testUtils/helpers/field-helper.ts index aa01ef7497d..72498fd8e16 100644 --- a/test/testUtils/helpers/field-helper.ts +++ b/test/testUtils/helpers/field-helper.ts @@ -3,7 +3,7 @@ import type { globalScene } from "#app/global-scene"; // -- end tsdoc imports -- -import type { BattlerIndex } from "#app/battle"; +import type { BattlerIndex } from "#enums/battler-index"; import type { Ability } from "#app/data/abilities/ability-class"; import { allAbilities } from "#app/data/data-lists"; import type Pokemon from "#app/field/pokemon"; diff --git a/test/testUtils/helpers/moveHelper.ts b/test/testUtils/helpers/moveHelper.ts index c7dea05b095..1b799e12da7 100644 --- a/test/testUtils/helpers/moveHelper.ts +++ b/test/testUtils/helpers/moveHelper.ts @@ -1,12 +1,12 @@ -import type { BattlerIndex } from "#app/battle"; -import { getMoveTargets } from "#app/data/moves/move"; +import type { BattlerIndex } from "#enums/battler-index"; +import { getMoveTargets } from "#app/data/moves/move-utils"; import type Pokemon from "#app/field/pokemon"; -import { PokemonMove } from "#app/field/pokemon"; +import { PokemonMove } from "#app/data/moves/pokemon-move"; import Overrides from "#app/overrides"; import type { CommandPhase } from "#app/phases/command-phase"; import type { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; -import { Command } from "#app/ui/command-ui-handler"; +import { Command } from "#enums/command"; import { MoveId } from "#enums/move-id"; import { UiMode } from "#enums/ui-mode"; import { getMovePosition } from "#test/testUtils/gameManagerUtils"; diff --git a/test/ui/starter-select.test.ts b/test/ui/starter-select.test.ts index 2884323b4ea..be508a2b69c 100644 --- a/test/ui/starter-select.test.ts +++ b/test/ui/starter-select.test.ts @@ -1,7 +1,7 @@ import { Gender } from "#app/data/gender"; import { Nature } from "#enums/nature"; import { allSpecies } from "#app/data/pokemon-species"; -import { GameModes } from "#app/game-mode"; +import { GameModes } from "#enums/game-modes"; import { EncounterPhase } from "#app/phases/encounter-phase"; import { SelectStarterPhase } from "#app/phases/select-starter-phase"; import type { TitlePhase } from "#app/phases/title-phase";