mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-04 07:22:19 +02:00
Merge branch 'beta' into test-doc
This commit is contained in:
commit
c7746bc1ca
@ -42,9 +42,6 @@
|
||||
// TODO: Remove if we ever get down to 0 circular imports
|
||||
"organizeImports": { "enabled": false },
|
||||
"linter": {
|
||||
"ignore": [
|
||||
"src/phases/move-effect-phase.ts" // TODO: unignore after move-effect-phase refactor
|
||||
],
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
|
@ -145,6 +145,5 @@
|
||||
</div>
|
||||
<script type="module" src="./src/main.ts"></script>
|
||||
<script src="./src/touch-controls.ts" type="module"></script>
|
||||
<script src="./src/debug.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
@ -12,3 +12,8 @@ post-merge:
|
||||
commands:
|
||||
update-submodules:
|
||||
run: git submodule update --init --recursive
|
||||
|
||||
post-checkout:
|
||||
commands:
|
||||
update-submodules:
|
||||
run: git submodule update --init --recursive
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 3.7 KiB |
@ -1,6 +1,7 @@
|
||||
/**
|
||||
* Dex entry for a single Pokemon Species
|
||||
*/
|
||||
export interface DexData {
|
||||
[key: number]: DexEntry;
|
||||
}
|
||||
|
||||
export interface DexEntry {
|
||||
seenAttr: bigint;
|
||||
caughtAttr: bigint;
|
||||
@ -10,7 +11,3 @@ export interface DexEntry {
|
||||
hatchedCount: number;
|
||||
ivs: number[];
|
||||
}
|
||||
|
||||
export interface DexData {
|
||||
[key: number]: DexEntry;
|
||||
}
|
@ -2,9 +2,6 @@ export interface Localizable {
|
||||
localize(): void;
|
||||
}
|
||||
|
||||
export interface TranslationEntries {
|
||||
[key: string]: string | { [key: string]: string };
|
||||
}
|
||||
export interface SimpleTranslationEntries {
|
||||
[key: string]: string;
|
||||
}
|
286
src/@types/phase-types.ts
Normal file
286
src/@types/phase-types.ts
Normal file
@ -0,0 +1,286 @@
|
||||
import type { MoveAnim } from "#app/data/battle-anims";
|
||||
import type { AddEnemyBuffModifierPhase } from "#app/phases/add-enemy-buff-modifier-phase";
|
||||
import type { AttemptCapturePhase } from "#app/phases/attempt-capture-phase";
|
||||
import type { AttemptRunPhase } from "#app/phases/attempt-run-phase";
|
||||
import type { BattleEndPhase } from "#app/phases/battle-end-phase";
|
||||
import type { BerryPhase } from "#app/phases/berry-phase";
|
||||
import type { CheckStatusEffectPhase } from "#app/phases/check-status-effect-phase";
|
||||
import type { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
||||
import type { CommandPhase } from "#app/phases/command-phase";
|
||||
import type { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||
import type { DamageAnimPhase } from "#app/phases/damage-anim-phase";
|
||||
import type { EggHatchPhase } from "#app/phases/egg-hatch-phase";
|
||||
import type { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||
import type { EggSummaryPhase } from "#app/phases/egg-summary-phase";
|
||||
import type { EncounterPhase } from "#app/phases/encounter-phase";
|
||||
import type { EndCardPhase } from "#app/phases/end-card-phase";
|
||||
import type { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
|
||||
import type { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
|
||||
import type { EvolutionPhase } from "#app/phases/evolution-phase";
|
||||
import type { ExpPhase } from "#app/phases/exp-phase";
|
||||
import type { FaintPhase } from "#app/phases/faint-phase";
|
||||
import type { FormChangePhase } from "#app/phases/form-change-phase";
|
||||
import type { GameOverModifierRewardPhase } from "#app/phases/game-over-modifier-reward-phase";
|
||||
import type { GameOverPhase } from "#app/phases/game-over-phase";
|
||||
import type { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
||||
import type { HidePartyExpBarPhase } from "#app/phases/hide-party-exp-bar-phase";
|
||||
import type { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import type { LevelCapPhase } from "#app/phases/level-cap-phase";
|
||||
import type { LevelUpPhase } from "#app/phases/level-up-phase";
|
||||
import type { LoadMoveAnimPhase } from "#app/phases/load-move-anim-phase";
|
||||
import type { LoginPhase } from "#app/phases/login-phase";
|
||||
import type { MessagePhase } from "#app/phases/message-phase";
|
||||
import type { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
|
||||
import type { MoneyRewardPhase } from "#app/phases/money-reward-phase";
|
||||
import type { MoveAnimPhase } from "#app/phases/move-anim-phase";
|
||||
import type { MoveChargePhase } from "#app/phases/move-charge-phase";
|
||||
import type { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import type { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import type { MoveHeaderPhase } from "#app/phases/move-header-phase";
|
||||
import type { MovePhase } from "#app/phases/move-phase";
|
||||
import type {
|
||||
MysteryEncounterPhase,
|
||||
MysteryEncounterOptionSelectedPhase,
|
||||
MysteryEncounterBattlePhase,
|
||||
MysteryEncounterRewardsPhase,
|
||||
PostMysteryEncounterPhase,
|
||||
MysteryEncounterBattleStartCleanupPhase,
|
||||
} from "#app/phases/mystery-encounter-phases";
|
||||
import type { NewBattlePhase } from "#app/phases/new-battle-phase";
|
||||
import type { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
|
||||
import type { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
||||
import type { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase";
|
||||
import type { PartyExpPhase } from "#app/phases/party-exp-phase";
|
||||
import type { PartyHealPhase } from "#app/phases/party-heal-phase";
|
||||
import type { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase";
|
||||
import type { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import type { PokemonTransformPhase } from "#app/phases/pokemon-transform-phase";
|
||||
import type { PostGameOverPhase } from "#app/phases/post-game-over-phase";
|
||||
import type { PostSummonPhase } from "#app/phases/post-summon-phase";
|
||||
import type { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase";
|
||||
import type { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
|
||||
import type { ReloadSessionPhase } from "#app/phases/reload-session-phase";
|
||||
import type { ResetStatusPhase } from "#app/phases/reset-status-phase";
|
||||
import type { ReturnPhase } from "#app/phases/return-phase";
|
||||
import type { RevivalBlessingPhase } from "#app/phases/revival-blessing-phase";
|
||||
import type { RibbonModifierRewardPhase } from "#app/phases/ribbon-modifier-reward-phase";
|
||||
import type { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
||||
import type { SelectBiomePhase } from "#app/phases/select-biome-phase";
|
||||
import type { SelectChallengePhase } from "#app/phases/select-challenge-phase";
|
||||
import type { SelectGenderPhase } from "#app/phases/select-gender-phase";
|
||||
import type { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
import type { SelectStarterPhase } from "#app/phases/select-starter-phase";
|
||||
import type { SelectTargetPhase } from "#app/phases/select-target-phase";
|
||||
import type { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase";
|
||||
import type { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||
import type { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||
import type { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
||||
import type { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import type { SummonMissingPhase } from "#app/phases/summon-missing-phase";
|
||||
import type { SummonPhase } from "#app/phases/summon-phase";
|
||||
import type { SwitchBiomePhase } from "#app/phases/switch-biome-phase";
|
||||
import type { SwitchPhase } from "#app/phases/switch-phase";
|
||||
import type { SwitchSummonPhase } from "#app/phases/switch-summon-phase";
|
||||
import type { TeraPhase } from "#app/phases/tera-phase";
|
||||
import type { TitlePhase } from "#app/phases/title-phase";
|
||||
import type { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||
import type { TrainerVictoryPhase } from "#app/phases/trainer-victory-phase";
|
||||
import type { TurnEndPhase } from "#app/phases/turn-end-phase";
|
||||
import type { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||
import type { TurnStartPhase } from "#app/phases/turn-start-phase";
|
||||
import type { UnavailablePhase } from "#app/phases/unavailable-phase";
|
||||
import type { UnlockPhase } from "#app/phases/unlock-phase";
|
||||
import type { VictoryPhase } from "#app/phases/victory-phase";
|
||||
import type { WeatherEffectPhase } from "#app/phases/weather-effect-phase";
|
||||
|
||||
export type PhaseClass =
|
||||
| typeof AddEnemyBuffModifierPhase
|
||||
| typeof AttemptCapturePhase
|
||||
| typeof AttemptRunPhase
|
||||
| typeof BattleEndPhase
|
||||
| typeof BerryPhase
|
||||
| typeof CheckStatusEffectPhase
|
||||
| typeof CheckSwitchPhase
|
||||
| typeof CommandPhase
|
||||
| typeof CommonAnimPhase
|
||||
| typeof DamageAnimPhase
|
||||
| typeof EggHatchPhase
|
||||
| typeof EggLapsePhase
|
||||
| typeof EggSummaryPhase
|
||||
| typeof EncounterPhase
|
||||
| typeof EndCardPhase
|
||||
| typeof EndEvolutionPhase
|
||||
| typeof EnemyCommandPhase
|
||||
| typeof EvolutionPhase
|
||||
| typeof FormChangePhase
|
||||
| typeof ExpPhase
|
||||
| typeof FaintPhase
|
||||
| typeof FormChangePhase
|
||||
| typeof GameOverPhase
|
||||
| typeof GameOverModifierRewardPhase
|
||||
| typeof HideAbilityPhase
|
||||
| typeof HidePartyExpBarPhase
|
||||
| typeof LearnMovePhase
|
||||
| typeof LevelUpPhase
|
||||
| typeof LevelCapPhase
|
||||
| typeof LoadMoveAnimPhase
|
||||
| typeof LoginPhase
|
||||
| typeof MessagePhase
|
||||
| typeof ModifierRewardPhase
|
||||
| typeof MoneyRewardPhase
|
||||
| typeof MoveAnimPhase
|
||||
| typeof MoveChargePhase
|
||||
| typeof MoveEffectPhase
|
||||
| typeof MoveEndPhase
|
||||
| typeof MoveHeaderPhase
|
||||
| typeof MovePhase
|
||||
| typeof MysteryEncounterPhase
|
||||
| typeof MysteryEncounterOptionSelectedPhase
|
||||
| typeof MysteryEncounterBattlePhase
|
||||
| typeof MysteryEncounterRewardsPhase
|
||||
| typeof MysteryEncounterBattleStartCleanupPhase
|
||||
| typeof MysteryEncounterRewardsPhase
|
||||
| typeof PostMysteryEncounterPhase
|
||||
| typeof NewBattlePhase
|
||||
| typeof NewBiomeEncounterPhase
|
||||
| typeof NextEncounterPhase
|
||||
| typeof ObtainStatusEffectPhase
|
||||
| typeof PartyExpPhase
|
||||
| typeof PartyHealPhase
|
||||
| typeof PokemonAnimPhase
|
||||
| typeof PokemonHealPhase
|
||||
| typeof PokemonTransformPhase
|
||||
| typeof PostGameOverPhase
|
||||
| typeof PostSummonPhase
|
||||
| typeof PostTurnStatusEffectPhase
|
||||
| typeof QuietFormChangePhase
|
||||
| typeof ReloadSessionPhase
|
||||
| typeof ResetStatusPhase
|
||||
| typeof ReturnPhase
|
||||
| typeof RevivalBlessingPhase
|
||||
| typeof RibbonModifierRewardPhase
|
||||
| typeof ScanIvsPhase
|
||||
| typeof SelectBiomePhase
|
||||
| typeof SelectChallengePhase
|
||||
| typeof SelectGenderPhase
|
||||
| typeof SelectModifierPhase
|
||||
| typeof SelectStarterPhase
|
||||
| typeof SelectTargetPhase
|
||||
| typeof ShinySparklePhase
|
||||
| typeof ShowAbilityPhase
|
||||
| typeof ShowTrainerPhase
|
||||
| typeof ShowPartyExpBarPhase
|
||||
| typeof StatStageChangePhase
|
||||
| typeof SummonMissingPhase
|
||||
| typeof SummonPhase
|
||||
| typeof SwitchBiomePhase
|
||||
| typeof SwitchPhase
|
||||
| typeof SwitchSummonPhase
|
||||
| typeof TeraPhase
|
||||
| typeof TitlePhase
|
||||
| typeof ToggleDoublePositionPhase
|
||||
| typeof TrainerVictoryPhase
|
||||
| typeof TurnEndPhase
|
||||
| typeof TurnInitPhase
|
||||
| typeof TurnStartPhase
|
||||
| typeof UnavailablePhase
|
||||
| typeof UnlockPhase
|
||||
| typeof VictoryPhase
|
||||
| typeof WeatherEffectPhase;
|
||||
|
||||
/** Typescript map used to map a string phase to the actual phase type */
|
||||
export type PhaseMap = {
|
||||
AddEnemyBuffModifierPhase: AddEnemyBuffModifierPhase;
|
||||
AttemptCapturePhase: AttemptCapturePhase;
|
||||
AttemptRunPhase: AttemptRunPhase;
|
||||
BattleEndPhase: BattleEndPhase;
|
||||
BerryPhase: BerryPhase;
|
||||
CheckStatusEffectPhase: CheckStatusEffectPhase;
|
||||
CheckSwitchPhase: CheckSwitchPhase;
|
||||
CommandPhase: CommandPhase;
|
||||
CommonAnimPhase: CommonAnimPhase;
|
||||
DamageAnimPhase: DamageAnimPhase;
|
||||
EggHatchPhase: EggHatchPhase;
|
||||
EggLapsePhase: EggLapsePhase;
|
||||
EggSummaryPhase: EggSummaryPhase;
|
||||
EncounterPhase: EncounterPhase;
|
||||
EndCardPhase: EndCardPhase;
|
||||
EndEvolutionPhase: EndEvolutionPhase;
|
||||
EnemyCommandPhase: EnemyCommandPhase;
|
||||
EvolutionPhase: EvolutionPhase;
|
||||
ExpPhase: ExpPhase;
|
||||
FaintPhase: FaintPhase;
|
||||
FormChangePhase: FormChangePhase;
|
||||
GameOverPhase: GameOverPhase;
|
||||
GameOverModifierRewardPhase: GameOverModifierRewardPhase;
|
||||
HideAbilityPhase: HideAbilityPhase;
|
||||
HidePartyExpBarPhase: HidePartyExpBarPhase;
|
||||
LearnMovePhase: LearnMovePhase;
|
||||
LevelCapPhase: LevelCapPhase;
|
||||
LevelUpPhase: LevelUpPhase;
|
||||
LoadMoveAnimPhase: LoadMoveAnimPhase;
|
||||
LoginPhase: LoginPhase;
|
||||
MessagePhase: MessagePhase;
|
||||
ModifierRewardPhase: ModifierRewardPhase;
|
||||
MoneyRewardPhase: MoneyRewardPhase;
|
||||
MoveAnimPhase: MoveAnimPhase<MoveAnim>;
|
||||
MoveChargePhase: MoveChargePhase;
|
||||
MoveEffectPhase: MoveEffectPhase;
|
||||
MoveEndPhase: MoveEndPhase;
|
||||
MoveHeaderPhase: MoveHeaderPhase;
|
||||
MovePhase: MovePhase;
|
||||
MysteryEncounterPhase: MysteryEncounterPhase;
|
||||
MysteryEncounterOptionSelectedPhase: MysteryEncounterOptionSelectedPhase;
|
||||
MysteryEncounterBattlePhase: MysteryEncounterBattlePhase;
|
||||
MysteryEncounterBattleStartCleanupPhase: MysteryEncounterBattleStartCleanupPhase;
|
||||
MysteryEncounterRewardsPhase: MysteryEncounterRewardsPhase;
|
||||
PostMysteryEncounterPhase: PostMysteryEncounterPhase;
|
||||
NewBattlePhase: NewBattlePhase;
|
||||
NewBiomeEncounterPhase: NewBiomeEncounterPhase;
|
||||
NextEncounterPhase: NextEncounterPhase;
|
||||
ObtainStatusEffectPhase: ObtainStatusEffectPhase;
|
||||
PartyExpPhase: PartyExpPhase;
|
||||
PartyHealPhase: PartyHealPhase;
|
||||
PokemonAnimPhase: PokemonAnimPhase;
|
||||
PokemonHealPhase: PokemonHealPhase;
|
||||
PokemonTransformPhase: PokemonTransformPhase;
|
||||
PostGameOverPhase: PostGameOverPhase;
|
||||
PostSummonPhase: PostSummonPhase;
|
||||
PostTurnStatusEffectPhase: PostTurnStatusEffectPhase;
|
||||
QuietFormChangePhase: QuietFormChangePhase;
|
||||
ReloadSessionPhase: ReloadSessionPhase;
|
||||
ResetStatusPhase: ResetStatusPhase;
|
||||
ReturnPhase: ReturnPhase;
|
||||
RevivalBlessingPhase: RevivalBlessingPhase;
|
||||
RibbonModifierRewardPhase: RibbonModifierRewardPhase;
|
||||
ScanIvsPhase: ScanIvsPhase;
|
||||
SelectBiomePhase: SelectBiomePhase;
|
||||
SelectChallengePhase: SelectChallengePhase;
|
||||
SelectGenderPhase: SelectGenderPhase;
|
||||
SelectModifierPhase: SelectModifierPhase;
|
||||
SelectStarterPhase: SelectStarterPhase;
|
||||
SelectTargetPhase: SelectTargetPhase;
|
||||
ShinySparklePhase: ShinySparklePhase;
|
||||
ShowAbilityPhase: ShowAbilityPhase;
|
||||
ShowPartyExpBarPhase: ShowPartyExpBarPhase;
|
||||
ShowTrainerPhase: ShowTrainerPhase;
|
||||
StatStageChangePhase: StatStageChangePhase;
|
||||
SummonMissingPhase: SummonMissingPhase;
|
||||
SummonPhase: SummonPhase;
|
||||
SwitchBiomePhase: SwitchBiomePhase;
|
||||
SwitchPhase: SwitchPhase;
|
||||
SwitchSummonPhase: SwitchSummonPhase;
|
||||
TeraPhase: TeraPhase;
|
||||
TitlePhase: TitlePhase;
|
||||
ToggleDoublePositionPhase: ToggleDoublePositionPhase;
|
||||
TrainerVictoryPhase: TrainerVictoryPhase;
|
||||
TurnEndPhase: TurnEndPhase;
|
||||
TurnInitPhase: TurnInitPhase;
|
||||
TurnStartPhase: TurnStartPhase;
|
||||
UnavailablePhase: UnavailablePhase;
|
||||
UnlockPhase: UnlockPhase;
|
||||
VictoryPhase: VictoryPhase;
|
||||
WeatherEffectPhase: WeatherEffectPhase;
|
||||
};
|
||||
|
||||
export type PhaseString = keyof PhaseMap;
|
@ -2,8 +2,8 @@ import type { EnemyPokemon } from "#app/field/pokemon";
|
||||
import type { PersistentModifier } from "#app/modifier/modifier";
|
||||
import type { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import type { SpeciesId } from "#enums/species-id";
|
||||
import type { TrainerConfig } from "./trainer-config";
|
||||
import type { TrainerPartyTemplate } from "./TrainerPartyTemplate";
|
||||
import type { TrainerConfig } from "../data/trainers/trainer-config";
|
||||
import type { TrainerPartyTemplate } from "../data/trainers/TrainerPartyTemplate";
|
||||
|
||||
export type PartyTemplateFunc = () => TrainerPartyTemplate;
|
||||
export type PartyMemberFunc = (level: number, strength: PartyMemberStrength) => EnemyPokemon;
|
@ -120,7 +120,7 @@ import { SceneBase } from "#app/scene-base";
|
||||
import CandyBar from "#app/ui/candy-bar";
|
||||
import type { Variant } from "#app/sprites/variant";
|
||||
import { variantData, clearVariantData } from "#app/sprites/variant";
|
||||
import type { Localizable } from "#app/interfaces/locales";
|
||||
import type { Localizable } from "#app/@types/locales";
|
||||
import Overrides from "#app/overrides";
|
||||
import { InputsController } from "#app/inputs-controller";
|
||||
import { UiInputs } from "#app/ui-inputs";
|
||||
@ -145,7 +145,7 @@ import { LoadingScene } from "#app/loading-scene";
|
||||
import { LevelCapPhase } from "#app/phases/level-cap-phase";
|
||||
import { LoginPhase } from "#app/phases/login-phase";
|
||||
import { MessagePhase } from "#app/phases/message-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import type { MovePhase } from "#app/phases/move-phase";
|
||||
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase";
|
||||
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
||||
import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase";
|
||||
@ -153,7 +153,6 @@ import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase";
|
||||
import { ReturnPhase } from "#app/phases/return-phase";
|
||||
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase";
|
||||
import { SummonPhase } from "#app/phases/summon-phase";
|
||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||
import { TitlePhase } from "#app/phases/title-phase";
|
||||
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
|
||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||
@ -170,7 +169,7 @@ import {
|
||||
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||
import { ExpPhase } from "#app/phases/exp-phase";
|
||||
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase";
|
||||
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
|
||||
@ -812,6 +811,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add a `getPartyOnSide` function for getting the party of a pokemon
|
||||
public getPlayerParty(): PlayerPokemon[] {
|
||||
return this.party;
|
||||
}
|
||||
@ -901,7 +901,7 @@ export default class BattleScene extends SceneBase {
|
||||
do {
|
||||
targetingMovePhase = this.findPhase(
|
||||
mp =>
|
||||
mp instanceof MovePhase &&
|
||||
mp.is("MovePhase") &&
|
||||
mp.targets.length === 1 &&
|
||||
mp.targets[0] === removedPokemon.getBattlerIndex() &&
|
||||
mp.pokemon.isPlayer() !== allyPokemon.isPlayer(),
|
||||
@ -1450,7 +1450,7 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
|
||||
if (lastBattle?.double && !newDouble) {
|
||||
this.tryRemovePhase(p => p instanceof SwitchPhase);
|
||||
this.tryRemovePhase((p: Phase) => p.is("SwitchPhase"));
|
||||
for (const p of this.getPlayerField()) {
|
||||
p.lapseTag(BattlerTagType.COMMANDED);
|
||||
}
|
||||
@ -1588,9 +1588,7 @@ export default class BattleScene extends SceneBase {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes(
|
||||
this.getCurrentPhase()?.constructor.name ?? "",
|
||||
);
|
||||
const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes(this.getCurrentPhase()?.phaseName ?? "");
|
||||
|
||||
if (
|
||||
// Give trainers with specialty types an appropriately-typed form for Wormadam, Rotom, Arceus, Oricorio, Silvally, or Paldean Tauros.
|
||||
@ -3089,9 +3087,9 @@ export default class BattleScene extends SceneBase {
|
||||
|
||||
const removeOld = itemModifier.stackCount === 0;
|
||||
|
||||
if (!removeOld || !source || this.removeModifier(itemModifier, !source.isPlayer())) {
|
||||
if (!removeOld || !source || this.removeModifier(itemModifier, source.isEnemy())) {
|
||||
const addModifier = () => {
|
||||
if (!matchingModifier || this.removeModifier(matchingModifier, !target.isPlayer())) {
|
||||
if (!matchingModifier || this.removeModifier(matchingModifier, target.isEnemy())) {
|
||||
if (target.isPlayer()) {
|
||||
this.addModifier(newItemModifier, ignoreUpdate, playSound, false, instant);
|
||||
if (source && itemLost) {
|
||||
@ -3495,12 +3493,12 @@ export default class BattleScene extends SceneBase {
|
||||
}
|
||||
if (matchingFormChange) {
|
||||
let phase: Phase;
|
||||
if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet) {
|
||||
if (pokemon.isPlayer() && !matchingFormChange.quiet) {
|
||||
phase = new FormChangePhase(pokemon, matchingFormChange, modal);
|
||||
} else {
|
||||
phase = new QuietFormChangePhase(pokemon, matchingFormChange);
|
||||
}
|
||||
if (pokemon instanceof PlayerPokemon && !matchingFormChange.quiet && modal) {
|
||||
if (pokemon.isPlayer() && !matchingFormChange.quiet && modal) {
|
||||
this.overridePhase(phase);
|
||||
} else if (delayed) {
|
||||
this.pushPhase(phase);
|
||||
@ -3569,21 +3567,18 @@ export default class BattleScene extends SceneBase {
|
||||
gameMode: this.currentBattle ? this.gameMode.getName() : "Title",
|
||||
biome: this.currentBattle ? getBiomeName(this.arena.biomeType) : "",
|
||||
wave: this.currentBattle?.waveIndex ?? 0,
|
||||
party: this.party
|
||||
? this.party.map(p => {
|
||||
return {
|
||||
name: p.name,
|
||||
form: p.getFormKey(),
|
||||
types: p.getTypes().map(type => PokemonType[type]),
|
||||
teraType: PokemonType[p.getTeraType()],
|
||||
isTerastallized: p.isTerastallized,
|
||||
level: p.level,
|
||||
currentHP: p.hp,
|
||||
maxHP: p.getMaxHp(),
|
||||
status: p.status?.effect ? StatusEffect[p.status.effect] : "",
|
||||
};
|
||||
})
|
||||
: [],
|
||||
party:
|
||||
this.party?.map(p => ({
|
||||
name: p.name,
|
||||
form: p.getFormKey(),
|
||||
types: p.getTypes().map(type => PokemonType[type]),
|
||||
teraType: PokemonType[p.getTeraType()],
|
||||
isTerastallized: p.isTerastallized,
|
||||
level: p.level,
|
||||
currentHP: p.hp,
|
||||
maxHP: p.getMaxHp(),
|
||||
status: p.status?.effect ? StatusEffect[p.status.effect] : "",
|
||||
})) ?? [], // TODO: review if this can be nullish
|
||||
modeChain: this.ui?.getModeChain() ?? [],
|
||||
};
|
||||
(window as any).gameInfo = gameInfo;
|
||||
@ -3601,7 +3596,7 @@ export default class BattleScene extends SceneBase {
|
||||
activePokemon = activePokemon.concat(this.getEnemyParty());
|
||||
for (const p of activePokemon) {
|
||||
keys.push(p.getSpriteKey(true));
|
||||
if (p instanceof PlayerPokemon) {
|
||||
if (p.isPlayer()) {
|
||||
keys.push(p.getBattleSpriteKey(true, true));
|
||||
}
|
||||
keys.push(p.species.getCryKey(p.formIndex));
|
||||
@ -3617,7 +3612,7 @@ export default class BattleScene extends SceneBase {
|
||||
* @param pokemon The (enemy) pokemon
|
||||
*/
|
||||
initFinalBossPhaseTwo(pokemon: Pokemon): void {
|
||||
if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
||||
if (pokemon.isEnemy() && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
|
||||
this.fadeOutBgm(fixedInt(2000), false);
|
||||
this.ui.showDialogue(
|
||||
battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin,
|
||||
@ -3966,16 +3961,13 @@ export default class BattleScene extends SceneBase {
|
||||
if (previousEncounter !== null && encounterType === previousEncounter) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
return !(
|
||||
this.mysteryEncounterSaveData.encounteredEvents.length > 0 &&
|
||||
encounterCandidate.maxAllowedEncounters &&
|
||||
encounterCandidate.maxAllowedEncounters > 0 &&
|
||||
this.mysteryEncounterSaveData.encounteredEvents.filter(e => e.type === encounterType).length >=
|
||||
encounterCandidate.maxAllowedEncounters
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
);
|
||||
})
|
||||
.map(m => allMysteryEncounters[m]);
|
||||
// Decrement tier
|
||||
|
@ -197,10 +197,7 @@ export function canIAssignThisKey(config, key) {
|
||||
export function canIOverrideThisSetting(config, settingName) {
|
||||
const key = getKeyWithSettingName(config, settingName);
|
||||
// || isTheLatestBind(config, settingName) no longer needed since action and cancel are protected
|
||||
if (config.blacklist?.includes(key)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !config.blacklist?.includes(key);
|
||||
}
|
||||
|
||||
export function canIDeleteThisKey(config, key) {
|
||||
|
@ -2,7 +2,7 @@ import { AbilityId } from "#enums/ability-id";
|
||||
import type { AbAttrCondition } from "#app/@types/ability-types";
|
||||
import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
|
||||
import i18next from "i18next";
|
||||
import type { Localizable } from "#app/interfaces/locales";
|
||||
import type { Localizable } from "#app/@types/locales";
|
||||
import type { Constructor } from "#app/utils/common";
|
||||
|
||||
export class Ability implements Localizable {
|
||||
|
@ -2617,7 +2617,7 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt
|
||||
}
|
||||
|
||||
override canApplyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
const party = pokemon instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
const party = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
return party.filter(p => p.isAllowedInBattle()).length > 0;
|
||||
}
|
||||
|
||||
@ -2629,7 +2629,7 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt
|
||||
* @param args - n/a
|
||||
*/
|
||||
override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {
|
||||
const party = pokemon instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
const party = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
const allowedParty = party.filter(p => p.isAllowedInBattle());
|
||||
|
||||
if (!simulated) {
|
||||
@ -2653,11 +2653,7 @@ export class PostSummonCopyAllyStatsAbAttr extends PostSummonAbAttr {
|
||||
}
|
||||
|
||||
const ally = pokemon.getAlly();
|
||||
if (isNullOrUndefined(ally) || ally.getStatStages().every(s => s === 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(isNullOrUndefined(ally) || ally.getStatStages().every(s => s === 0));
|
||||
}
|
||||
|
||||
override applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {
|
||||
@ -2723,11 +2719,7 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
|
||||
}
|
||||
|
||||
// transforming from or into fusion pokemon causes various problems (including crashes and save corruption)
|
||||
if (this.getTarget(targets).fusionSpecies || pokemon.fusionSpecies) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(this.getTarget(targets).fusionSpecies || pokemon.fusionSpecies);
|
||||
}
|
||||
|
||||
override applyPostSummon(pokemon: Pokemon, _passive: boolean, simulated: boolean, _args: any[]): void {
|
||||
@ -2828,7 +2820,7 @@ export class CommanderAbAttr extends AbAttr {
|
||||
// Apply boosts from this effect to the ally Dondozo
|
||||
pokemon.getAlly()?.addTag(BattlerTagType.COMMANDED, 0, MoveId.NONE, pokemon.id);
|
||||
// Cancel the source Pokemon's next move (if a move is queued)
|
||||
globalScene.tryRemovePhase((phase) => phase instanceof MovePhase && phase.pokemon === pokemon);
|
||||
globalScene.tryRemovePhase((phase) => phase.is("MovePhase") && phase.pokemon === pokemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3544,10 +3536,7 @@ export class BlockStatusDamageAbAttr extends AbAttr {
|
||||
}
|
||||
|
||||
override canApply(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
|
||||
if (pokemon.status && this.effects.includes(pokemon.status.effect)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return !!pokemon.status?.effect && this.effects.includes(pokemon.status.effect);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4449,6 +4438,7 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr {
|
||||
simulated: boolean,
|
||||
args: any[]): void {
|
||||
if (!simulated) {
|
||||
dancer.turnData.extraTurns++;
|
||||
// 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) {
|
||||
const target = this.getTarget(dancer, source, targets);
|
||||
@ -4803,11 +4793,7 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
|
||||
const diedToDirectDamage = move !== undefined && attacker !== undefined && move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon});
|
||||
const cancelled = new BooleanHolder(false);
|
||||
globalScene.getField(true).map(p => applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled, simulated));
|
||||
if (!diedToDirectDamage || cancelled.value || attacker!.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !(!diedToDirectDamage || cancelled.value || attacker!.hasAbilityWithAttr(BlockNonDirectDamageAbAttr));
|
||||
}
|
||||
|
||||
override applyPostFaint(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker?: Pokemon, move?: Move, hitResult?: HitResult, ...args: any[]): void {
|
||||
@ -5553,7 +5539,7 @@ class ForceSwitchOutHelper {
|
||||
* - Whether there are available party members to switch in.
|
||||
* - If the Pokémon is still alive (hp > 0), and if so, it leaves the field and a new SwitchPhase is initiated.
|
||||
*/
|
||||
if (switchOutTarget instanceof PlayerPokemon) {
|
||||
if (switchOutTarget.isPlayer()) {
|
||||
if (globalScene.getPlayerParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) {
|
||||
return false;
|
||||
}
|
||||
@ -5622,7 +5608,7 @@ class ForceSwitchOutHelper {
|
||||
*/
|
||||
public getSwitchOutCondition(pokemon: Pokemon, opponent: Pokemon): boolean {
|
||||
const switchOutTarget = pokemon;
|
||||
const player = switchOutTarget instanceof PlayerPokemon;
|
||||
const player = switchOutTarget.isPlayer();
|
||||
|
||||
if (player) {
|
||||
const blockedByAbility = new BooleanHolder(false);
|
||||
@ -6508,12 +6494,7 @@ export function initAbilities() {
|
||||
new Ability(AbilityId.INTIMIDATE, 3)
|
||||
.attr(PostSummonStatStageChangeAbAttr, [ Stat.ATK ], -1, false, true),
|
||||
new Ability(AbilityId.SHADOW_TAG, 3)
|
||||
.attr(ArenaTrapAbAttr, (user, target) => {
|
||||
if (target.hasAbility(AbilityId.SHADOW_TAG)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
.attr(ArenaTrapAbAttr, (_user, target) => !target.hasAbility(AbilityId.SHADOW_TAG)),
|
||||
new Ability(AbilityId.ROUGH_SKIN, 3)
|
||||
.attr(PostDefendContactDamageAbAttr, 8)
|
||||
.bypassFaint(),
|
||||
@ -6573,10 +6554,7 @@ export function initAbilities() {
|
||||
.ignorable(),
|
||||
new Ability(AbilityId.MAGNET_PULL, 3)
|
||||
.attr(ArenaTrapAbAttr, (user, target) => {
|
||||
if (target.getTypes(true).includes(PokemonType.STEEL) || (target.getTypes(true).includes(PokemonType.STELLAR) && target.getTypes().includes(PokemonType.STEEL))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return target.getTypes(true).includes(PokemonType.STEEL) || (target.getTypes(true).includes(PokemonType.STELLAR) && target.getTypes().includes(PokemonType.STEEL));
|
||||
}),
|
||||
new Ability(AbilityId.SOUNDPROOF, 3)
|
||||
.attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.SOUND_BASED))
|
||||
@ -6654,12 +6632,7 @@ export function initAbilities() {
|
||||
.attr(PostSummonWeatherChangeAbAttr, WeatherType.SUNNY)
|
||||
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SUNNY),
|
||||
new Ability(AbilityId.ARENA_TRAP, 3)
|
||||
.attr(ArenaTrapAbAttr, (user, target) => {
|
||||
if (target.isGrounded()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.attr(ArenaTrapAbAttr, (user, target) => target.isGrounded())
|
||||
.attr(DoubleBattleChanceAbAttr),
|
||||
new Ability(AbilityId.VITAL_SPIRIT, 3)
|
||||
.attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP)
|
||||
@ -6897,7 +6870,7 @@ export function initAbilities() {
|
||||
.ignorable(),
|
||||
new Ability(AbilityId.ANALYTIC, 5)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => {
|
||||
const movePhase = globalScene.findPhase((phase) => phase instanceof MovePhase && phase.pokemon.id !== user?.id);
|
||||
const movePhase = globalScene.findPhase((phase) => phase.is("MovePhase") && phase.pokemon.id !== user?.id);
|
||||
return isNullOrUndefined(movePhase);
|
||||
}, 1.3),
|
||||
new Ability(AbilityId.ILLUSION, 5)
|
||||
|
@ -383,7 +383,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => {
|
||||
const move = allMoves[moveId];
|
||||
const effectPhase = globalScene.getCurrentPhase();
|
||||
|
||||
if (effectPhase instanceof MoveEffectPhase) {
|
||||
if (effectPhase?.is("MoveEffectPhase")) {
|
||||
const attacker = effectPhase.getUserPokemon();
|
||||
if (attacker) {
|
||||
return move.getPriority(attacker) > 0;
|
||||
|
@ -28,7 +28,7 @@ import type Pokemon from "#app/field/pokemon";
|
||||
import { HitResult, MoveResult } from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import type { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
|
||||
import type { StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
|
||||
@ -553,9 +553,9 @@ export class ShellTrapTag extends BattlerTag {
|
||||
// Trap should only be triggered by opponent's Physical moves
|
||||
if (phaseData?.move.category === MoveCategory.PHYSICAL && pokemon.isOpponent(phaseData.attacker)) {
|
||||
const shellTrapPhaseIndex = globalScene.phaseQueue.findIndex(
|
||||
phase => phase instanceof MovePhase && phase.pokemon === pokemon,
|
||||
phase => phase.is("MovePhase") && phase.pokemon === pokemon,
|
||||
);
|
||||
const firstMovePhaseIndex = globalScene.phaseQueue.findIndex(phase => phase instanceof MovePhase);
|
||||
const firstMovePhaseIndex = globalScene.phaseQueue.findIndex(phase => phase.is("MovePhase"));
|
||||
|
||||
// Only shift MovePhase timing if it's not already next up
|
||||
if (shellTrapPhaseIndex !== -1 && shellTrapPhaseIndex !== firstMovePhaseIndex) {
|
||||
@ -649,20 +649,14 @@ class NoRetreatTag extends TrappedTag {
|
||||
*/
|
||||
export class FlinchedTag extends BattlerTag {
|
||||
constructor(sourceMove: MoveId) {
|
||||
super(BattlerTagType.FLINCHED, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END], 0, sourceMove);
|
||||
}
|
||||
|
||||
onAdd(pokemon: Pokemon): void {
|
||||
super.onAdd(pokemon);
|
||||
|
||||
applyAbAttrs(FlinchEffectAbAttr, pokemon, null);
|
||||
super(BattlerTagType.FLINCHED, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.TURN_END], 1, sourceMove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the Pokemon's next Move on the turn this tag is applied
|
||||
* @param pokemon The {@linkcode Pokemon} with this tag
|
||||
* @param lapseType The {@linkcode BattlerTagLapseType lapse type} used for this function call
|
||||
* @returns `false` (This tag is always removed after applying its effects)
|
||||
* Cancels the flinched Pokemon's currently used move this turn if called mid-execution, or removes the tag at end of turn.
|
||||
* @param pokemon - The {@linkcode Pokemon} with this tag.
|
||||
* @param lapseType - The {@linkcode BattlerTagLapseType | lapse type} used for this function call.
|
||||
* @returns Whether the tag should remain active.
|
||||
*/
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
||||
@ -672,6 +666,8 @@ export class FlinchedTag extends BattlerTag {
|
||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||
}),
|
||||
);
|
||||
applyAbAttrs(FlinchEffectAbAttr, pokemon, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.lapse(pokemon, lapseType);
|
||||
@ -1027,7 +1023,7 @@ export class PowderTag extends BattlerTag {
|
||||
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
||||
const movePhase = globalScene.getCurrentPhase();
|
||||
if (movePhase instanceof MovePhase) {
|
||||
if (movePhase?.is("MovePhase")) {
|
||||
const move = movePhase.move.getMove();
|
||||
const weather = globalScene.arena.weather;
|
||||
if (
|
||||
@ -1183,13 +1179,13 @@ export class EncoreTag extends MoveRestrictionBattlerTag {
|
||||
}),
|
||||
);
|
||||
|
||||
const movePhase = globalScene.findPhase(m => m instanceof MovePhase && m.pokemon === pokemon);
|
||||
const movePhase = globalScene.findPhase(m => m.is("MovePhase") && m.pokemon === pokemon);
|
||||
if (movePhase) {
|
||||
const movesetMove = pokemon.getMoveset().find(m => m.moveId === this.moveId);
|
||||
if (movesetMove) {
|
||||
const lastMove = pokemon.getLastXMoves(1)[0];
|
||||
globalScene.tryReplacePhase(
|
||||
m => m instanceof MovePhase && m.pokemon === pokemon,
|
||||
m => m.is("MovePhase") && m.pokemon === pokemon,
|
||||
new MovePhase(pokemon, lastMove.targets ?? [], movesetMove),
|
||||
);
|
||||
}
|
||||
@ -1203,10 +1199,7 @@ export class EncoreTag extends MoveRestrictionBattlerTag {
|
||||
override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||
if (lapseType === BattlerTagLapseType.CUSTOM) {
|
||||
const encoredMove = pokemon.getMoveset().find(m => m.moveId === this.moveId);
|
||||
if (encoredMove && encoredMove?.getPpRatio() > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return !isNullOrUndefined(encoredMove) && encoredMove.getPpRatio() > 0;
|
||||
}
|
||||
return super.lapse(pokemon, lapseType);
|
||||
}
|
||||
@ -1218,10 +1211,7 @@ export class EncoreTag extends MoveRestrictionBattlerTag {
|
||||
* @returns `true` if the move does not match with the moveId stored and as a result, restricted
|
||||
*/
|
||||
override isMoveRestricted(move: MoveId, _user?: Pokemon): boolean {
|
||||
if (move !== this.moveId) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return move !== this.moveId;
|
||||
}
|
||||
|
||||
override selectionDeniedText(_pokemon: Pokemon, move: MoveId): string {
|
||||
@ -1624,7 +1614,7 @@ export class ProtectedTag extends BattlerTag {
|
||||
|
||||
// Stop multi-hit moves early
|
||||
const effectPhase = globalScene.getCurrentPhase();
|
||||
if (effectPhase instanceof MoveEffectPhase) {
|
||||
if (effectPhase?.is("MoveEffectPhase")) {
|
||||
effectPhase.stopMultiHit(pokemon);
|
||||
}
|
||||
return true;
|
||||
@ -2646,7 +2636,7 @@ export class GulpMissileTag extends BattlerTag {
|
||||
}
|
||||
|
||||
const moveEffectPhase = globalScene.getCurrentPhase();
|
||||
if (moveEffectPhase instanceof MoveEffectPhase) {
|
||||
if (moveEffectPhase?.is("MoveEffectPhase")) {
|
||||
const attacker = moveEffectPhase.getUserPokemon();
|
||||
|
||||
if (!attacker) {
|
||||
@ -2768,10 +2758,7 @@ export class HealBlockTag extends MoveRestrictionBattlerTag {
|
||||
* @returns `true` if the move has a TRIAGE_MOVE flag and is a status move
|
||||
*/
|
||||
override isMoveRestricted(move: MoveId): boolean {
|
||||
if (allMoves[move].hasFlag(MoveFlags.TRIAGE_MOVE) && allMoves[move].category === MoveCategory.STATUS) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return allMoves[move].hasFlag(MoveFlags.TRIAGE_MOVE) && allMoves[move].category === MoveCategory.STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2785,10 +2772,7 @@ 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);
|
||||
if (allMoves[move].hasAttr(HealOnAllyAttr) && moveCategory.value === MoveCategory.STATUS) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return allMoves[move].hasAttr(HealOnAllyAttr) && moveCategory.value === MoveCategory.STATUS;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3004,7 +2988,7 @@ export class SubstituteTag extends BattlerTag {
|
||||
/** If the Substitute redirects damage, queue a message to indicate it. */
|
||||
onHit(pokemon: Pokemon): void {
|
||||
const moveEffectPhase = globalScene.getCurrentPhase();
|
||||
if (moveEffectPhase instanceof MoveEffectPhase) {
|
||||
if (moveEffectPhase?.is("MoveEffectPhase")) {
|
||||
const attacker = moveEffectPhase.getUserPokemon();
|
||||
if (!attacker) {
|
||||
return;
|
||||
@ -3126,10 +3110,7 @@ export class TormentTag extends MoveRestrictionBattlerTag {
|
||||
const moveObj = allMoves[lastMove.move];
|
||||
const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || user.getTag(BattlerTagType.FRENZY);
|
||||
const validLastMoveResult = lastMove.result === MoveResult.SUCCESS || lastMove.result === MoveResult.MISS;
|
||||
if (lastMove.move === move && validLastMoveResult && lastMove.move !== MoveId.STRUGGLE && !isUnaffected) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return lastMove.move === move && validLastMoveResult && lastMove.move !== MoveId.STRUGGLE && !isUnaffected;
|
||||
}
|
||||
|
||||
override selectionDeniedText(pokemon: Pokemon, _move: MoveId): string {
|
||||
@ -3693,7 +3674,7 @@ export function loadBattlerTag(source: BattlerTag | any): BattlerTag {
|
||||
*/
|
||||
function getMoveEffectPhaseData(_pokemon: Pokemon): { phase: MoveEffectPhase; attacker: Pokemon; move: Move } | null {
|
||||
const phase = globalScene.getCurrentPhase();
|
||||
if (phase instanceof MoveEffectPhase) {
|
||||
if (phase?.is("MoveEffectPhase")) {
|
||||
return {
|
||||
phase: phase,
|
||||
attacker: phase.getPokemon(),
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||
import type { DexEntry, StarterDataEntry } from "#app/system/game-data";
|
||||
import type { StarterDataEntry } from "#app/system/game-data";
|
||||
import type { DexEntry } from "#app/@types/dex-data";
|
||||
|
||||
/**
|
||||
* Stores data associated with a specific egg and the hatched pokemon
|
||||
|
@ -81,7 +81,7 @@ import { TerrainType } from "../terrain";
|
||||
import { ModifierPoolType } from "#app/modifier/modifier-type";
|
||||
import { Command } from "../../ui/command-ui-handler";
|
||||
import i18next from "i18next";
|
||||
import type { Localizable } from "#app/interfaces/locales";
|
||||
import type { Localizable } from "#app/@types/locales";
|
||||
import { getBerryEffectFunc } from "../berry";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
@ -837,7 +837,7 @@ export default class Move implements Localizable {
|
||||
aura.applyPreAttack(source, null, simulated, target, this, [ power ]);
|
||||
}
|
||||
|
||||
const alliedField: Pokemon[] = source instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
const alliedField: Pokemon[] = source.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
alliedField.forEach(p => applyPreAttackAbAttrs(UserFieldMoveTypePowerBoostAbAttr, p, target, this, simulated, power));
|
||||
|
||||
power.value *= typeChangeMovePowerMultiplier.value;
|
||||
@ -3109,7 +3109,7 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
|
||||
|
||||
const overridden = args[0] as BooleanHolder;
|
||||
|
||||
const allyMovePhase = globalScene.findPhase<MovePhase>((phase) => phase instanceof MovePhase && phase.pokemon.isPlayer() === user.isPlayer());
|
||||
const allyMovePhase = globalScene.findPhase<MovePhase>((phase) => phase.is("MovePhase") && phase.pokemon.isPlayer() === user.isPlayer());
|
||||
if (allyMovePhase) {
|
||||
const allyMove = allyMovePhase.move.getMove();
|
||||
if (allyMove !== move && allyMove.hasAttr(AwaitCombinedPledgeAttr)) {
|
||||
@ -3123,7 +3123,7 @@ export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr {
|
||||
|
||||
// Move the ally's MovePhase (if needed) so that the ally moves next
|
||||
const allyMovePhaseIndex = globalScene.phaseQueue.indexOf(allyMovePhase);
|
||||
const firstMovePhaseIndex = globalScene.phaseQueue.findIndex((phase) => phase instanceof MovePhase);
|
||||
const firstMovePhaseIndex = globalScene.phaseQueue.findIndex((phase) => phase.is("MovePhase"));
|
||||
if (allyMovePhaseIndex !== firstMovePhaseIndex) {
|
||||
globalScene.prependToPhase(globalScene.phaseQueue.splice(allyMovePhaseIndex, 1)[0], MovePhase);
|
||||
}
|
||||
@ -4125,7 +4125,7 @@ export class FriendshipPowerAttr extends VariablePowerAttr {
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
const power = args[0] as NumberHolder;
|
||||
|
||||
const friendshipPower = Math.floor(Math.min(user instanceof PlayerPokemon ? user.friendship : user.species.baseFriendship, 255) / 2.5);
|
||||
const friendshipPower = Math.floor(Math.min(user.isPlayer() ? user.friendship : user.species.baseFriendship, 255) / 2.5);
|
||||
power.value = Math.max(!this.invert ? friendshipPower : 102 - friendshipPower, 1);
|
||||
|
||||
return true;
|
||||
@ -4477,7 +4477,7 @@ export class CueNextRoundAttr extends MoveEffectAttr {
|
||||
|
||||
override apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean {
|
||||
const nextRoundPhase = globalScene.findPhase<MovePhase>(phase =>
|
||||
phase instanceof MovePhase && phase.move.moveId === MoveId.ROUND
|
||||
phase.is("MovePhase") && phase.move.moveId === MoveId.ROUND
|
||||
);
|
||||
|
||||
if (!nextRoundPhase) {
|
||||
@ -4486,7 +4486,7 @@ export class CueNextRoundAttr extends MoveEffectAttr {
|
||||
|
||||
// Update the phase queue so that the next Pokemon using Round moves next
|
||||
const nextRoundIndex = globalScene.phaseQueue.indexOf(nextRoundPhase);
|
||||
const nextMoveIndex = globalScene.phaseQueue.findIndex(phase => phase instanceof MovePhase);
|
||||
const nextMoveIndex = globalScene.phaseQueue.findIndex(phase => phase.is("MovePhase"));
|
||||
if (nextRoundIndex !== nextMoveIndex) {
|
||||
globalScene.prependToPhase(globalScene.phaseQueue.splice(nextRoundIndex, 1)[0], MovePhase);
|
||||
}
|
||||
@ -5472,13 +5472,6 @@ export class AddBattlerTagAttr extends MoveEffectAttr {
|
||||
this.failOnOverlap = !!failOnOverlap;
|
||||
}
|
||||
|
||||
canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.canApply(user, target, move, args)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
if (!super.apply(user, target, move, args)) {
|
||||
return false;
|
||||
@ -6156,14 +6149,14 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
||||
* @param target {@linkcode Pokemon} target of this move
|
||||
* @param move {@linkcode Move} being used
|
||||
* @param args N/A
|
||||
* @returns Promise, true if function succeeds.
|
||||
* @returns `true` if function succeeds.
|
||||
*/
|
||||
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||
// If user is player, checks if the user has fainted pokemon
|
||||
if (user instanceof PlayerPokemon) {
|
||||
if (user.isPlayer()) {
|
||||
globalScene.unshiftPhase(new RevivalBlessingPhase(user));
|
||||
return true;
|
||||
} else if (user instanceof EnemyPokemon && user.hasTrainer() && globalScene.getEnemyParty().findIndex((p) => p.isFainted() && !p.isBoss()) > -1) {
|
||||
} else if (user.isEnemy() && user.hasTrainer() && globalScene.getEnemyParty().findIndex((p) => p.isFainted() && !p.isBoss()) > -1) {
|
||||
// If used by an enemy trainer with at least one fainted non-boss Pokemon, this
|
||||
// revives one of said Pokemon selected at random.
|
||||
const faintedPokemon = globalScene.getEnemyParty().filter((p) => p.isFainted() && !p.isBoss());
|
||||
@ -6177,7 +6170,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
||||
// Handle cases where revived pokemon needs to get switched in on same turn
|
||||
if (allyPokemon.isFainted() || allyPokemon === pokemon) {
|
||||
// Enemy switch phase should be removed and replaced with the revived pkmn switching in
|
||||
globalScene.tryRemovePhase((phase: SwitchSummonPhase) => phase instanceof SwitchSummonPhase && phase.getPokemon() === pokemon);
|
||||
globalScene.tryRemovePhase((phase: SwitchSummonPhase) => phase.is("SwitchSummonPhase") && phase.getPokemon() === pokemon);
|
||||
// If the pokemon being revived was alive earlier in the turn, cancel its move
|
||||
// (revived pokemon can't move in the turn they're brought back)
|
||||
globalScene.findPhase((phase: MovePhase) => phase.pokemon === pokemon)?.cancel();
|
||||
@ -6194,10 +6187,8 @@ export class RevivalBlessingAttr extends MoveEffectAttr {
|
||||
|
||||
getCondition(): MoveConditionFunc {
|
||||
return (user, target, move) =>
|
||||
(user instanceof PlayerPokemon && globalScene.getPlayerParty().some((p) => p.isFainted())) ||
|
||||
(user instanceof EnemyPokemon &&
|
||||
user.hasTrainer() &&
|
||||
globalScene.getEnemyParty().some((p) => p.isFainted() && !p.isBoss()));
|
||||
user.hasTrainer() &&
|
||||
(user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty()).some((p: Pokemon) => p.isFainted() && !p.isBoss());
|
||||
}
|
||||
|
||||
override getUserBenefitScore(user: Pokemon, _target: Pokemon, _move: Move): number {
|
||||
@ -6235,7 +6226,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
||||
// (e.g. when it uses Flip Turn), make it spit out the Tatsugiri before switching out.
|
||||
switchOutTarget.lapseTag(BattlerTagType.COMMANDED);
|
||||
|
||||
if (switchOutTarget instanceof PlayerPokemon) {
|
||||
if (switchOutTarget.isPlayer()) {
|
||||
/**
|
||||
* Check if Wimp Out/Emergency Exit activates due to being hit by U-turn or Volt Switch
|
||||
* If it did, the user of U-turn or Volt Switch will not be switched out.
|
||||
@ -6389,7 +6380,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
|
||||
getSwitchOutCondition(): MoveConditionFunc {
|
||||
return (user, target, move) => {
|
||||
const switchOutTarget = (this.selfSwitch ? user : target);
|
||||
const player = switchOutTarget instanceof PlayerPokemon;
|
||||
const player = switchOutTarget.isPlayer();
|
||||
const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH);
|
||||
|
||||
if (!this.selfSwitch) {
|
||||
@ -6832,7 +6823,7 @@ export class RandomMovesetMoveAttr extends CallMoveAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.moveId = moves[user.randBattleSeedInt(moves.length)]!.moveId;
|
||||
this.moveId = moves[user.randBattleSeedInt(moves.length)].moveId;
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@ -7367,11 +7358,7 @@ export class SketchAttr extends MoveEffectAttr {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (user.getMoveset().find(m => m.moveId === targetMove.move)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !user.getMoveset().some(m => m.moveId === targetMove.move);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -7896,7 +7883,7 @@ export class ForceLastAttr extends MoveEffectAttr {
|
||||
// Either the end of the turn or in front of another, slower move which has also been forced last
|
||||
const prependPhase = globalScene.findPhase((phase) =>
|
||||
[ MovePhase, MoveEndPhase ].every(cls => !(phase instanceof cls))
|
||||
|| (phase instanceof MovePhase) && phaseForcedSlower(phase, target, !!globalScene.arena.getTag(ArenaTagType.TRICK_ROOM))
|
||||
|| (phase.is("MovePhase")) && phaseForcedSlower(phase, target, !!globalScene.arena.getTag(ArenaTagType.TRICK_ROOM))
|
||||
);
|
||||
if (prependPhase) {
|
||||
globalScene.phaseQueue.splice(
|
||||
@ -7942,7 +7929,7 @@ const userSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target:
|
||||
|
||||
const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => target.status?.effect === StatusEffect.SLEEP || target.hasAbility(AbilityId.COMATOSE);
|
||||
|
||||
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => globalScene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
||||
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => globalScene.phaseQueue.find(phase => phase.is("MovePhase")) !== undefined;
|
||||
|
||||
const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => {
|
||||
const party: Pokemon[] = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
|
||||
@ -9868,7 +9855,7 @@ export function initMoves() {
|
||||
const lastEnemyFaint = globalScene.currentBattle.enemyFaintsHistory[globalScene.currentBattle.enemyFaintsHistory.length - 1];
|
||||
return (
|
||||
(lastPlayerFaint !== undefined && turn - lastPlayerFaint.turn === 1 && user.isPlayer()) ||
|
||||
(lastEnemyFaint !== undefined && turn - lastEnemyFaint.turn === 1 && !user.isPlayer())
|
||||
(lastEnemyFaint !== undefined && turn - lastEnemyFaint.turn === 1 && user.isEnemy())
|
||||
) ? 2 : 1;
|
||||
}),
|
||||
new AttackMove(MoveId.FINAL_GAMBIT, PokemonType.FIGHTING, MoveCategory.SPECIAL, -1, 100, 5, -1, 0, 5)
|
||||
|
@ -33,7 +33,7 @@ import {
|
||||
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
|
||||
import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||
import type { BerryType } from "#enums/berry-type";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
import { Stat } from "#enums/stat";
|
||||
|
@ -25,7 +25,7 @@ import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/myst
|
||||
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||
import i18next from "i18next";
|
||||
import { getStatKey } from "#enums/stat";
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
|
@ -39,7 +39,7 @@ import { PlayerGender } from "#enums/player-gender";
|
||||
import { TrainerType } from "#enums/trainer-type";
|
||||
import PokemonData from "#app/system/pokemon-data";
|
||||
import { Nature } from "#enums/nature";
|
||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||
import { trainerConfigs } from "#app/data/trainers/trainer-config";
|
||||
import { TrainerPartyTemplate } from "#app/data/trainers/TrainerPartyTemplate";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
|
@ -275,15 +275,11 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement {
|
||||
|
||||
override meetsRequirement(): boolean {
|
||||
const timeOfDay = globalScene.arena?.getTimeOfDay();
|
||||
if (
|
||||
return !(
|
||||
!isNullOrUndefined(timeOfDay) &&
|
||||
this.requiredTimeOfDay?.length > 0 &&
|
||||
!this.requiredTimeOfDay.includes(timeOfDay)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
);
|
||||
}
|
||||
|
||||
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
||||
@ -301,15 +297,11 @@ export class WeatherRequirement extends EncounterSceneRequirement {
|
||||
|
||||
override meetsRequirement(): boolean {
|
||||
const currentWeather = globalScene.arena.weather?.weatherType;
|
||||
if (
|
||||
return !(
|
||||
!isNullOrUndefined(currentWeather) &&
|
||||
this.requiredWeather?.length > 0 &&
|
||||
!this.requiredWeather.includes(currentWeather!)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
);
|
||||
}
|
||||
|
||||
override getDialogueToken(_pokemon?: PlayerPokemon): [string, string] {
|
||||
@ -803,7 +795,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
||||
}
|
||||
|
||||
filterByForm(pokemon, formChangeItem) {
|
||||
if (
|
||||
return (
|
||||
pokemonFormChanges.hasOwnProperty(pokemon.species.speciesId) &&
|
||||
// Get all form changes for this species with an item trigger, including any compound triggers
|
||||
pokemonFormChanges[pokemon.species.speciesId]
|
||||
@ -812,10 +804,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen
|
||||
.flatMap(fc => fc.findTrigger(SpeciesFormChangeItemTrigger) as SpeciesFormChangeItemTrigger)
|
||||
.flatMap(fc => fc.item)
|
||||
.includes(formChangeItem)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
);
|
||||
}
|
||||
|
||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||
@ -873,17 +862,15 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
|
||||
return (
|
||||
pokemon.isFusion() &&
|
||||
pokemonEvolutions.hasOwnProperty(pokemon.fusionSpecies.speciesId) &&
|
||||
pokemonEvolutions[pokemon.fusionSpecies.speciesId].filter(
|
||||
e => e.item === evolutionItem && (!e.condition || e.condition.predicate(pokemon)),
|
||||
).length &&
|
||||
pokemon.getFusionFormKey() !== SpeciesFormKey.GIGANTAMAX
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
);
|
||||
}
|
||||
|
||||
override queryParty(partyPokemon: PlayerPokemon[]): PlayerPokemon[] {
|
||||
|
@ -50,7 +50,7 @@ import type PokemonSpecies from "#app/data/pokemon-species";
|
||||
import type { IEggOptions } from "#app/data/egg";
|
||||
import { Egg } from "#app/data/egg";
|
||||
import type { CustomPokemonData } from "#app/data/custom-pokemon-data";
|
||||
import type HeldModifierConfig from "#app/interfaces/held-modifier-config";
|
||||
import type HeldModifierConfig from "#app/@types/held-modifier-config";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { EggLapsePhase } from "#app/phases/egg-lapse-phase";
|
||||
import { TrainerVictoryPhase } from "#app/phases/trainer-victory-phase";
|
||||
@ -769,7 +769,7 @@ export function setEncounterRewards(
|
||||
if (customShopRewards) {
|
||||
globalScene.unshiftPhase(new SelectModifierPhase(0, undefined, customShopRewards));
|
||||
} else {
|
||||
globalScene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
||||
globalScene.tryRemovePhase(p => p.is("MysteryEncounterRewardsPhase"));
|
||||
}
|
||||
|
||||
if (eggRewards) {
|
||||
|
@ -186,11 +186,7 @@ export class SpeciesFormChange {
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.trigger.canChange(pokemon)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return this.trigger.canChange(pokemon);
|
||||
}
|
||||
|
||||
findTrigger(triggerType: Constructor<SpeciesFormChangeTrigger>): SpeciesFormChangeTrigger | nil {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Localizable } from "#app/interfaces/locales";
|
||||
import type { Localizable } from "#app/@types/locales";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
@ -1281,10 +1281,6 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
||||
};
|
||||
}
|
||||
|
||||
isObtainable() {
|
||||
return super.isObtainable();
|
||||
}
|
||||
|
||||
hasVariants() {
|
||||
let variantDataIndex: string | number = this.speciesId;
|
||||
if (this.forms.length > 0) {
|
||||
@ -2026,9 +2022,9 @@ export function initSpecies() {
|
||||
new PokemonForm("Normal", "", PokemonType.GROUND, null, 3.5, 950, AbilityId.DROUGHT, AbilityId.NONE, AbilityId.NONE, 670, 100, 150, 140, 100, 90, 90, 3, 0, 335, false, null, true),
|
||||
new PokemonForm("Primal", "primal", PokemonType.GROUND, PokemonType.FIRE, 5, 999.7, AbilityId.DESOLATE_LAND, AbilityId.NONE, AbilityId.NONE, 770, 100, 180, 160, 150, 90, 90, 3, 0, 335),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.RAYQUAZA, 3, false, true, false, "Sky High Pokémon", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 45, 0, 340, GrowthRate.SLOW, null, false, true,
|
||||
new PokemonForm("Normal", "", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 45, 0, 340, false, null, true),
|
||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, PokemonType.DRAGON, PokemonType.FLYING, 10.8, 392, AbilityId.DELTA_STREAM, AbilityId.NONE, AbilityId.NONE, 780, 105, 180, 100, 180, 100, 115, 45, 0, 340),
|
||||
new PokemonSpecies(SpeciesId.RAYQUAZA, 3, false, true, false, "Sky High Pokémon", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 3, 0, 340, GrowthRate.SLOW, null, false, true,
|
||||
new PokemonForm("Normal", "", PokemonType.DRAGON, PokemonType.FLYING, 7, 206.5, AbilityId.AIR_LOCK, AbilityId.NONE, AbilityId.NONE, 680, 105, 150, 90, 150, 90, 95, 3, 0, 340, false, null, true),
|
||||
new PokemonForm("Mega", SpeciesFormKey.MEGA, PokemonType.DRAGON, PokemonType.FLYING, 10.8, 392, AbilityId.DELTA_STREAM, AbilityId.NONE, AbilityId.NONE, 780, 105, 180, 100, 180, 100, 115, 3, 0, 340),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.JIRACHI, 3, false, false, true, "Wish Pokémon", PokemonType.STEEL, PokemonType.PSYCHIC, 0.3, 1.1, AbilityId.SERENE_GRACE, AbilityId.NONE, AbilityId.NONE, 600, 100, 100, 100, 100, 100, 100, 3, 100, 300, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.DEOXYS, 3, false, false, true, "DNA Pokémon", PokemonType.PSYCHIC, null, 1.7, 60.8, AbilityId.PRESSURE, AbilityId.NONE, AbilityId.NONE, 600, 50, 150, 50, 150, 50, 150, 3, 0, 300, GrowthRate.SLOW, null, false, true,
|
||||
@ -2274,10 +2270,10 @@ export function initSpecies() {
|
||||
new PokemonSpecies(SpeciesId.WHIMSICOTT, 5, false, false, false, "Windveiled Pokémon", PokemonType.GRASS, PokemonType.FAIRY, 0.7, 6.6, AbilityId.PRANKSTER, AbilityId.INFILTRATOR, AbilityId.CHLOROPHYLL, 480, 60, 67, 85, 77, 75, 116, 75, 50, 168, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.PETILIL, 5, false, false, false, "Bulb Pokémon", PokemonType.GRASS, null, 0.5, 6.6, AbilityId.CHLOROPHYLL, AbilityId.OWN_TEMPO, AbilityId.LEAF_GUARD, 280, 45, 35, 50, 70, 50, 30, 190, 50, 56, GrowthRate.MEDIUM_FAST, 0, false),
|
||||
new PokemonSpecies(SpeciesId.LILLIGANT, 5, false, false, false, "Flowering Pokémon", PokemonType.GRASS, null, 1.1, 16.3, AbilityId.CHLOROPHYLL, AbilityId.OWN_TEMPO, AbilityId.LEAF_GUARD, 480, 70, 60, 75, 110, 75, 90, 75, 50, 168, GrowthRate.MEDIUM_FAST, 0, false),
|
||||
new PokemonSpecies(SpeciesId.BASCULIN, 5, false, false, false, "Hostile Pokémon", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||
new PokemonForm("Red-Striped Form", "red-striped", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, false, null, true),
|
||||
new PokemonForm("Blue-Striped Form", "blue-striped", PokemonType.WATER, null, 1, 18, AbilityId.ROCK_HEAD, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, false, null, true),
|
||||
new PokemonForm("White-Striped Form", "white-striped", PokemonType.WATER, null, 1, 18, AbilityId.RATTLED, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 25, 50, 161, false, null, true),
|
||||
new PokemonSpecies(SpeciesId.BASCULIN, 5, false, false, false, "Hostile Pokémon", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||
new PokemonForm("Red-Striped Form", "red-striped", PokemonType.WATER, null, 1, 18, AbilityId.RECKLESS, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, false, null, true),
|
||||
new PokemonForm("Blue-Striped Form", "blue-striped", PokemonType.WATER, null, 1, 18, AbilityId.ROCK_HEAD, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, false, null, true),
|
||||
new PokemonForm("White-Striped Form", "white-striped", PokemonType.WATER, null, 1, 18, AbilityId.RATTLED, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 460, 70, 92, 65, 80, 55, 98, 190, 50, 161, false, null, true),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.SANDILE, 5, false, false, false, "Desert Croc Pokémon", PokemonType.GROUND, PokemonType.DARK, 0.7, 15.2, AbilityId.INTIMIDATE, AbilityId.MOXIE, AbilityId.ANGER_POINT, 292, 50, 72, 35, 35, 35, 65, 180, 50, 58, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
new PokemonSpecies(SpeciesId.KROKOROK, 5, false, false, false, "Desert Croc Pokémon", PokemonType.GROUND, PokemonType.DARK, 1, 33.4, AbilityId.INTIMIDATE, AbilityId.MOXIE, AbilityId.ANGER_POINT, 351, 60, 82, 45, 45, 45, 74, 90, 50, 123, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
@ -2744,10 +2740,10 @@ export function initSpecies() {
|
||||
new PokemonSpecies(SpeciesId.TAPU_LELE, 7, true, false, false, "Land Spirit Pokémon", PokemonType.PSYCHIC, PokemonType.FAIRY, 1.2, 18.6, AbilityId.PSYCHIC_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 85, 75, 130, 115, 95, 3, 50, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.TAPU_BULU, 7, true, false, false, "Land Spirit Pokémon", PokemonType.GRASS, PokemonType.FAIRY, 1.9, 45.5, AbilityId.GRASSY_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 130, 115, 85, 95, 75, 3, 50, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.TAPU_FINI, 7, true, false, false, "Land Spirit Pokémon", PokemonType.WATER, PokemonType.FAIRY, 1.3, 21.2, AbilityId.MISTY_SURGE, AbilityId.NONE, AbilityId.TELEPATHY, 570, 70, 75, 115, 95, 130, 85, 3, 50, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.COSMOG, 7, true, false, false, "Nebula Pokémon", PokemonType.PSYCHIC, null, 0.2, 0.1, AbilityId.UNAWARE, AbilityId.NONE, AbilityId.NONE, 200, 43, 29, 31, 29, 31, 37, 45, 0, 40, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.COSMOEM, 7, true, false, false, "Protostar Pokémon", PokemonType.PSYCHIC, null, 0.1, 999.9, AbilityId.STURDY, AbilityId.NONE, AbilityId.NONE, 400, 43, 29, 131, 29, 131, 37, 45, 0, 140, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.SOLGALEO, 7, false, true, false, "Sunne Pokémon", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, AbilityId.FULL_METAL_BODY, AbilityId.NONE, AbilityId.NONE, 680, 137, 137, 107, 113, 89, 97, 45, 0, 340, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.LUNALA, 7, false, true, false, "Moone Pokémon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, AbilityId.SHADOW_SHIELD, AbilityId.NONE, AbilityId.NONE, 680, 137, 113, 89, 137, 107, 97, 45, 0, 340, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.COSMOG, 7, true, false, false, "Nebula Pokémon", PokemonType.PSYCHIC, null, 0.2, 0.1, AbilityId.UNAWARE, AbilityId.NONE, AbilityId.NONE, 200, 43, 29, 31, 29, 31, 37, 3, 0, 40, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.COSMOEM, 7, true, false, false, "Protostar Pokémon", PokemonType.PSYCHIC, null, 0.1, 999.9, AbilityId.STURDY, AbilityId.NONE, AbilityId.NONE, 400, 43, 29, 131, 29, 131, 37, 3, 0, 140, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.SOLGALEO, 7, false, true, false, "Sunne Pokémon", PokemonType.PSYCHIC, PokemonType.STEEL, 3.4, 230, AbilityId.FULL_METAL_BODY, AbilityId.NONE, AbilityId.NONE, 680, 137, 137, 107, 113, 89, 97, 3, 0, 340, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.LUNALA, 7, false, true, false, "Moone Pokémon", PokemonType.PSYCHIC, PokemonType.GHOST, 4, 120, AbilityId.SHADOW_SHIELD, AbilityId.NONE, AbilityId.NONE, 680, 137, 113, 89, 137, 107, 97, 3, 0, 340, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.NIHILEGO, 7, true, false, false, "Parasite Pokémon", PokemonType.ROCK, PokemonType.POISON, 1.2, 55.5, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 109, 53, 47, 127, 131, 103, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.BUZZWOLE, 7, true, false, false, "Swollen Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 2.4, 333.6, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 107, 139, 139, 53, 53, 79, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.PHEROMOSA, 7, true, false, false, "Lissome Pokémon", PokemonType.BUG, PokemonType.FIGHTING, 1.8, 25, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 71, 137, 37, 137, 37, 151, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||
@ -2755,11 +2751,11 @@ export function initSpecies() {
|
||||
new PokemonSpecies(SpeciesId.CELESTEELA, 7, true, false, false, "Launch Pokémon", PokemonType.STEEL, PokemonType.FLYING, 9.2, 999.9, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 97, 101, 103, 107, 101, 61, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.KARTANA, 7, true, false, false, "Drawn Sword Pokémon", PokemonType.GRASS, PokemonType.STEEL, 0.3, 0.1, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 59, 181, 131, 59, 31, 109, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.GUZZLORD, 7, true, false, false, "Junkivore Pokémon", PokemonType.DARK, PokemonType.DRAGON, 5.5, 888, AbilityId.BEAST_BOOST, AbilityId.NONE, AbilityId.NONE, 570, 223, 101, 53, 97, 53, 43, 45, 0, 285, GrowthRate.SLOW, null, false),
|
||||
new PokemonSpecies(SpeciesId.NECROZMA, 7, false, true, false, "Prism Pokémon", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 255, 0, 300, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Normal", "", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 255, 0, 300, false, null, true),
|
||||
new PokemonForm("Dusk Mane", "dusk-mane", PokemonType.PSYCHIC, PokemonType.STEEL, 3.8, 460, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 157, 127, 113, 109, 77, 255, 0, 340),
|
||||
new PokemonForm("Dawn Wings", "dawn-wings", PokemonType.PSYCHIC, PokemonType.GHOST, 4.2, 350, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 113, 109, 157, 127, 77, 255, 0, 340),
|
||||
new PokemonForm("Ultra", "ultra", PokemonType.PSYCHIC, PokemonType.DRAGON, 7.5, 230, AbilityId.NEUROFORCE, AbilityId.NONE, AbilityId.NONE, 754, 97, 167, 97, 167, 97, 129, 255, 0, 377),
|
||||
new PokemonSpecies(SpeciesId.NECROZMA, 7, false, true, false, "Prism Pokémon", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 3, 0, 300, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Normal", "", PokemonType.PSYCHIC, null, 2.4, 230, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 600, 97, 107, 101, 127, 89, 79, 3, 0, 300, false, null, true),
|
||||
new PokemonForm("Dusk Mane", "dusk-mane", PokemonType.PSYCHIC, PokemonType.STEEL, 3.8, 460, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 157, 127, 113, 109, 77, 3, 0, 340),
|
||||
new PokemonForm("Dawn Wings", "dawn-wings", PokemonType.PSYCHIC, PokemonType.GHOST, 4.2, 350, AbilityId.PRISM_ARMOR, AbilityId.NONE, AbilityId.NONE, 680, 97, 113, 109, 157, 127, 77, 3, 0, 340),
|
||||
new PokemonForm("Ultra", "ultra", PokemonType.PSYCHIC, PokemonType.DRAGON, 7.5, 230, AbilityId.NEUROFORCE, AbilityId.NONE, AbilityId.NONE, 754, 97, 167, 97, 167, 97, 129, 3, 0, 377),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.MAGEARNA, 7, false, false, true, "Artificial Pokémon", PokemonType.STEEL, PokemonType.FAIRY, 1, 80.5, AbilityId.SOUL_HEART, AbilityId.NONE, AbilityId.NONE, 600, 80, 95, 115, 130, 115, 65, 3, 0, 300, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.FAIRY, 1, 80.5, AbilityId.SOUL_HEART, AbilityId.NONE, AbilityId.NONE, 600, 80, 95, 115, 130, 115, 65, 3, 0, 300, false, null, true),
|
||||
@ -2968,15 +2964,15 @@ export function initSpecies() {
|
||||
new PokemonForm("Ice", "ice", PokemonType.PSYCHIC, PokemonType.ICE, 2.4, 809.1, AbilityId.AS_ONE_GLASTRIER, AbilityId.NONE, AbilityId.NONE, 680, 100, 165, 150, 85, 130, 50, 3, 100, 340),
|
||||
new PokemonForm("Shadow", "shadow", PokemonType.PSYCHIC, PokemonType.GHOST, 2.4, 53.6, AbilityId.AS_ONE_SPECTRIER, AbilityId.NONE, AbilityId.NONE, 680, 100, 85, 80, 165, 100, 150, 3, 100, 340),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.WYRDEER, 8, false, false, false, "Big Horn Pokémon", PokemonType.NORMAL, PokemonType.PSYCHIC, 1.8, 95.1, AbilityId.INTIMIDATE, AbilityId.FRISK, AbilityId.SAP_SIPPER, 525, 103, 105, 72, 105, 75, 65, 135, 50, 263, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(SpeciesId.KLEAVOR, 8, false, false, false, "Axe Pokémon", PokemonType.BUG, PokemonType.ROCK, 1.8, 89, AbilityId.SWARM, AbilityId.SHEER_FORCE, AbilityId.SHARPNESS, 500, 70, 135, 95, 45, 70, 85, 115, 50, 175, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.URSALUNA, 8, false, false, false, "Peat Pokémon", PokemonType.GROUND, PokemonType.NORMAL, 2.4, 290, AbilityId.GUTS, AbilityId.BULLETPROOF, AbilityId.UNNERVE, 550, 130, 140, 105, 45, 80, 50, 75, 50, 275, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.BASCULEGION, 8, false, false, false, "Big Fish Pokémon", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 135, 50, 265, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||
new PokemonForm("Male", "male", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 135, 50, 265, false, "", true),
|
||||
new PokemonForm("Female", "female", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 92, 65, 100, 75, 78, 135, 50, 265, false, null, true),
|
||||
new PokemonSpecies(SpeciesId.WYRDEER, 8, false, false, false, "Big Horn Pokémon", PokemonType.NORMAL, PokemonType.PSYCHIC, 1.8, 95.1, AbilityId.INTIMIDATE, AbilityId.FRISK, AbilityId.SAP_SIPPER, 525, 103, 105, 72, 105, 75, 65, 45, 50, 263, GrowthRate.SLOW, 50, false),
|
||||
new PokemonSpecies(SpeciesId.KLEAVOR, 8, false, false, false, "Axe Pokémon", PokemonType.BUG, PokemonType.ROCK, 1.8, 89, AbilityId.SWARM, AbilityId.SHEER_FORCE, AbilityId.SHARPNESS, 500, 70, 135, 95, 45, 70, 85, 15, 50, 175, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.URSALUNA, 8, false, false, false, "Peat Pokémon", PokemonType.GROUND, PokemonType.NORMAL, 2.4, 290, AbilityId.GUTS, AbilityId.BULLETPROOF, AbilityId.UNNERVE, 550, 130, 140, 105, 45, 80, 50, 20, 50, 275, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.BASCULEGION, 8, false, false, false, "Big Fish Pokémon", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 45, 50, 265, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||
new PokemonForm("Male", "male", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 112, 65, 80, 75, 78, 45, 50, 265, false, "", true),
|
||||
new PokemonForm("Female", "female", PokemonType.WATER, PokemonType.GHOST, 3, 110, AbilityId.SWIFT_SWIM, AbilityId.ADAPTABILITY, AbilityId.MOLD_BREAKER, 530, 120, 92, 65, 100, 75, 78, 45, 50, 265, false, null, true),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.SNEASLER, 8, false, false, false, "Free Climb Pokémon", PokemonType.FIGHTING, PokemonType.POISON, 1.3, 43, AbilityId.PRESSURE, AbilityId.UNBURDEN, AbilityId.POISON_TOUCH, 510, 80, 130, 60, 40, 80, 120, 135, 50, 102, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
new PokemonSpecies(SpeciesId.OVERQWIL, 8, false, false, false, "Pin Cluster Pokémon", PokemonType.DARK, PokemonType.POISON, 2.5, 60.5, AbilityId.POISON_POINT, AbilityId.SWIFT_SWIM, AbilityId.INTIMIDATE, 510, 85, 115, 95, 65, 65, 85, 135, 50, 179, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.SNEASLER, 8, false, false, false, "Free Climb Pokémon", PokemonType.FIGHTING, PokemonType.POISON, 1.3, 43, AbilityId.PRESSURE, AbilityId.UNBURDEN, AbilityId.POISON_TOUCH, 510, 80, 130, 60, 40, 80, 120, 20, 50, 102, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
new PokemonSpecies(SpeciesId.OVERQWIL, 8, false, false, false, "Pin Cluster Pokémon", PokemonType.DARK, PokemonType.POISON, 2.5, 60.5, AbilityId.POISON_POINT, AbilityId.SWIFT_SWIM, AbilityId.INTIMIDATE, 510, 85, 115, 95, 65, 65, 85, 45, 50, 179, GrowthRate.MEDIUM_FAST, 50, false),
|
||||
new PokemonSpecies(SpeciesId.ENAMORUS, 8, true, false, false, "Love-Hate Pokémon", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.CUTE_CHARM, AbilityId.NONE, AbilityId.CONTRARY, 580, 74, 115, 70, 135, 80, 106, 3, 50, 116, GrowthRate.SLOW, 0, false, true,
|
||||
new PokemonForm("Incarnate Forme", "incarnate", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.CUTE_CHARM, AbilityId.NONE, AbilityId.CONTRARY, 580, 74, 115, 70, 135, 80, 106, 3, 50, 116, false, null, true),
|
||||
new PokemonForm("Therian Forme", "therian", PokemonType.FAIRY, PokemonType.FLYING, 1.6, 48, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 580, 74, 115, 110, 135, 100, 46, 3, 50, 116),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { TrainerTierPools } from "#app/data/trainers/typedefs";
|
||||
import type { TrainerTierPools } from "#app/@types/trainer-funcs";
|
||||
import { TrainerPoolTier } from "#enums/trainer-pool-tier";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
|
||||
|
@ -48,7 +48,7 @@ import type {
|
||||
TrainerTierPools,
|
||||
TrainerConfigs,
|
||||
PartyMemberFuncs,
|
||||
} from "./typedefs";
|
||||
} from "../../@types/trainer-funcs";
|
||||
|
||||
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
||||
const ELITE_FOUR_MINIMUM_BST = 460;
|
||||
|
17
src/debug.js
17
src/debug.js
@ -1,17 +0,0 @@
|
||||
export function getData() {
|
||||
const dataStr = localStorage.getItem("data");
|
||||
if (!dataStr) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(atob(dataStr), (k, v) =>
|
||||
k.endsWith("Attr") && !["natureAttr", "abilityAttr", "passiveAttr"].includes(k) ? BigInt(v) : v,
|
||||
);
|
||||
}
|
||||
|
||||
export function getSession() {
|
||||
const sessionStr = localStorage.getItem("sessionData");
|
||||
if (!sessionStr) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(atob(sessionStr));
|
||||
}
|
@ -232,7 +232,6 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { DamageAnimPhase } from "#app/phases/damage-anim-phase";
|
||||
import { FaintPhase } from "#app/phases/faint-phase";
|
||||
import { LearnMovePhase } from "#app/phases/learn-move-phase";
|
||||
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase";
|
||||
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
|
||||
@ -504,7 +503,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
if (level > 1) {
|
||||
const fused = new BooleanHolder(globalScene.gameMode.isSplicedOnly);
|
||||
if (!fused.value && !this.isPlayer() && !this.hasTrainer()) {
|
||||
if (!fused.value && this.isEnemy() && !this.hasTrainer()) {
|
||||
globalScene.applyModifier(EnemyFusionChanceModifier, false, fused);
|
||||
}
|
||||
|
||||
@ -789,7 +788,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract isPlayer(): boolean;
|
||||
abstract isPlayer(): this is PlayerPokemon;
|
||||
|
||||
abstract isEnemy(): this is EnemyPokemon;
|
||||
|
||||
abstract hasTrainer(): boolean;
|
||||
|
||||
@ -1293,19 +1294,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*/
|
||||
isOffsetBySubstitute(): boolean {
|
||||
const substitute = this.getTag(SubstituteTag);
|
||||
if (substitute) {
|
||||
if (substitute.sprite === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// During the Pokemon's MoveEffect phase, the offset is removed to put the Pokemon "in focus"
|
||||
const currentPhase = globalScene.getCurrentPhase();
|
||||
if (currentPhase instanceof MoveEffectPhase && currentPhase.getPokemon() === this) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!substitute || substitute.sprite === undefined) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
// During the Pokemon's MoveEffect phase, the offset is removed to put the Pokemon "in focus"
|
||||
const currentPhase = globalScene.getCurrentPhase();
|
||||
return !(currentPhase?.is("MoveEffectPhase") && currentPhase.getPokemon() === this);
|
||||
}
|
||||
|
||||
/** If this Pokemon has a Substitute on the field, removes its sprite from the field. */
|
||||
@ -2058,7 +2052,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (Overrides.ABILITY_OVERRIDE && this.isPlayer()) {
|
||||
return allAbilities[Overrides.ABILITY_OVERRIDE];
|
||||
}
|
||||
if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) {
|
||||
if (Overrides.OPP_ABILITY_OVERRIDE && this.isEnemy()) {
|
||||
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
|
||||
}
|
||||
if (this.isFusion()) {
|
||||
@ -2088,7 +2082,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (Overrides.PASSIVE_ABILITY_OVERRIDE && this.isPlayer()) {
|
||||
return allAbilities[Overrides.PASSIVE_ABILITY_OVERRIDE];
|
||||
}
|
||||
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
|
||||
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && this.isEnemy()) {
|
||||
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
|
||||
}
|
||||
if (!isNullOrUndefined(this.customPokemonData.passive) && this.customPokemonData.passive !== -1) {
|
||||
@ -2160,7 +2154,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
// returns override if valid for current case
|
||||
if (
|
||||
(Overrides.HAS_PASSIVE_ABILITY_OVERRIDE === false && this.isPlayer()) ||
|
||||
(Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE === false && !this.isPlayer())
|
||||
(Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE === false && this.isEnemy())
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@ -2168,7 +2162,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
((Overrides.PASSIVE_ABILITY_OVERRIDE !== AbilityId.NONE || Overrides.HAS_PASSIVE_ABILITY_OVERRIDE) &&
|
||||
this.isPlayer()) ||
|
||||
((Overrides.OPP_PASSIVE_ABILITY_OVERRIDE !== AbilityId.NONE || Overrides.OPP_HAS_PASSIVE_ABILITY_OVERRIDE) &&
|
||||
!this.isPlayer())
|
||||
this.isEnemy())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@ -2177,7 +2171,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
const { currentBattle, gameMode } = globalScene;
|
||||
const waveIndex = currentBattle?.waveIndex;
|
||||
if (
|
||||
this instanceof EnemyPokemon &&
|
||||
this.isEnemy() &&
|
||||
(currentBattle?.battleSpec === BattleSpec.FINAL_BOSS ||
|
||||
gameMode.isEndlessMinorBoss(waveIndex) ||
|
||||
gameMode.isEndlessMajorBoss(waveIndex))
|
||||
@ -2242,10 +2236,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if (this.getAbility(ignoreOverride).id === ability && (!canApply || this.canApplyAbility())) {
|
||||
return true;
|
||||
}
|
||||
if (this.getPassiveAbility().id === ability && this.hasPassive() && (!canApply || this.canApplyAbility(true))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return this.getPassiveAbility().id === ability && this.hasPassive() && (!canApply || this.canApplyAbility(true));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2262,10 +2253,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).hasAttr(attrType)) {
|
||||
return true;
|
||||
}
|
||||
if (this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().hasAttr(attrType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().hasAttr(attrType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2993,9 +2981,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
let fusionOverride: PokemonSpecies | undefined = undefined;
|
||||
|
||||
if (forStarter && this instanceof PlayerPokemon && Overrides.STARTER_FUSION_SPECIES_OVERRIDE) {
|
||||
if (forStarter && this.isPlayer() && Overrides.STARTER_FUSION_SPECIES_OVERRIDE) {
|
||||
fusionOverride = getPokemonSpecies(Overrides.STARTER_FUSION_SPECIES_OVERRIDE);
|
||||
} else if (this instanceof EnemyPokemon && Overrides.OPP_FUSION_SPECIES_OVERRIDE) {
|
||||
} else if (this.isEnemy() && Overrides.OPP_FUSION_SPECIES_OVERRIDE) {
|
||||
fusionOverride = getPokemonSpecies(Overrides.OPP_FUSION_SPECIES_OVERRIDE);
|
||||
}
|
||||
|
||||
@ -3306,7 +3294,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
this.battleInfo.setX(this.battleInfo.x + (this.isPlayer() ? 150 : !this.isBoss() ? -150 : -198));
|
||||
this.battleInfo.setVisible(true);
|
||||
if (this.isPlayer()) {
|
||||
this.battleInfo.expMaskRect.x += 150;
|
||||
// TODO: How do you get this to not require a private property access?
|
||||
this["battleInfo"].expMaskRect.x += 150;
|
||||
}
|
||||
globalScene.tweens.add({
|
||||
targets: [this.battleInfo, this.battleInfo.expMaskRect],
|
||||
@ -3327,7 +3316,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
ease: "Cubic.easeIn",
|
||||
onComplete: () => {
|
||||
if (this.isPlayer()) {
|
||||
this.battleInfo.expMaskRect.x -= 150;
|
||||
// TODO: How do you get this to not require a private property access?
|
||||
this["battleInfo"].expMaskRect.x -= 150;
|
||||
}
|
||||
this.battleInfo.setVisible(false);
|
||||
this.battleInfo.setX(this.battleInfo.x - (this.isPlayer() ? 150 : !this.isBoss() ? -150 : -198));
|
||||
@ -3422,7 +3412,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @returns An array of Pokémon on the allied field.
|
||||
*/
|
||||
getAlliedField(): Pokemon[] {
|
||||
return this instanceof PlayerPokemon ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
return this.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4274,7 +4264,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
// Copy all stat stages
|
||||
for (const s of BATTLE_STATS) {
|
||||
const sourceStage = source.getStatStage(s);
|
||||
if (this instanceof PlayerPokemon && sourceStage === 6) {
|
||||
if (this.isPlayer() && sourceStage === 6) {
|
||||
globalScene.validateAchv(achvs.TRANSFER_MAX_STAT_STAGE);
|
||||
}
|
||||
this.setStatStage(s, sourceStage);
|
||||
@ -4775,7 +4765,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
*/
|
||||
if (effect === StatusEffect.SLEEP || effect === StatusEffect.FREEZE) {
|
||||
const currentPhase = globalScene.getCurrentPhase();
|
||||
if (currentPhase instanceof MoveEffectPhase && currentPhase.getUserPokemon() === this) {
|
||||
if (currentPhase?.is("MoveEffectPhase") && currentPhase.getUserPokemon() === this) {
|
||||
this.turnData.hitCount = 1;
|
||||
this.turnData.hitsLeft = 1;
|
||||
}
|
||||
@ -5465,10 +5455,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
if ((ownedAbilityAttrs & 2) > 0 && this.hasSameAbilityInRootForm(1)) {
|
||||
return true;
|
||||
}
|
||||
if ((ownedAbilityAttrs & 4) > 0 && this.hasSameAbilityInRootForm(2)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return (ownedAbilityAttrs & 4) > 0 && this.hasSameAbilityInRootForm(2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5485,7 +5472,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
|
||||
heldItem.stackCount--;
|
||||
if (heldItem.stackCount <= 0) {
|
||||
globalScene.removeModifier(heldItem, !this.isPlayer());
|
||||
globalScene.removeModifier(heldItem, this.isEnemy());
|
||||
}
|
||||
if (forBattle) {
|
||||
applyPostItemLostAbAttrs(PostItemLostAbAttr, this, false);
|
||||
@ -5558,15 +5545,19 @@ export class PlayerPokemon extends Pokemon {
|
||||
this.battleInfo.initInfo(this);
|
||||
}
|
||||
|
||||
isPlayer(): boolean {
|
||||
override isPlayer(): this is PlayerPokemon {
|
||||
return true;
|
||||
}
|
||||
|
||||
hasTrainer(): boolean {
|
||||
override isEnemy(): this is EnemyPokemon {
|
||||
return false;
|
||||
}
|
||||
|
||||
override hasTrainer(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
isBoss(): boolean {
|
||||
override isBoss(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -6511,15 +6502,19 @@ export class EnemyPokemon extends Pokemon {
|
||||
return [sortedBenefitScores[targetIndex][0]];
|
||||
}
|
||||
|
||||
isPlayer() {
|
||||
override isPlayer(): this is PlayerPokemon {
|
||||
return false;
|
||||
}
|
||||
|
||||
hasTrainer(): boolean {
|
||||
override isEnemy(): this is EnemyPokemon {
|
||||
return true;
|
||||
}
|
||||
|
||||
override hasTrainer(): boolean {
|
||||
return !!this.trainerSlot;
|
||||
}
|
||||
|
||||
isBoss(): boolean {
|
||||
override isBoss(): boolean {
|
||||
return !!this.bossSegments;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
export const starterColors: StarterColors = {};
|
||||
interface StarterColors {
|
||||
export const starterColors: {
|
||||
[key: string]: [string, string];
|
||||
}
|
||||
} = {};
|
||||
|
@ -16,7 +16,7 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined, useIllusio
|
||||
|
||||
switch (globalScene.currentBattle.battleSpec) {
|
||||
case BattleSpec.DEFAULT:
|
||||
return !pokemon.isPlayer()
|
||||
return pokemon.isEnemy()
|
||||
? pokemon.hasTrainer()
|
||||
? i18next.t("battle:foePokemonWithAffix", {
|
||||
pokemonName: pokemon.getNameToRender(useIllusion),
|
||||
@ -26,7 +26,7 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined, useIllusio
|
||||
})
|
||||
: pokemon.getNameToRender(useIllusion);
|
||||
case BattleSpec.FINAL_BOSS:
|
||||
return !pokemon.isPlayer()
|
||||
return pokemon.isEnemy()
|
||||
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender(useIllusion) })
|
||||
: pokemon.getNameToRender(useIllusion);
|
||||
default:
|
||||
|
@ -40,7 +40,6 @@ import {
|
||||
type TerastallizeModifierType,
|
||||
type TmModifierType,
|
||||
getModifierType,
|
||||
ModifierPoolType,
|
||||
ModifierTypeGenerator,
|
||||
modifierTypes,
|
||||
PokemonHeldItemModifierType,
|
||||
@ -1091,10 +1090,6 @@ export class PokemonIncrementingStatModifier extends PokemonHeldItemModifier {
|
||||
return new PokemonIncrementingStatModifier(this.type, this.pokemonId, this.stackCount);
|
||||
}
|
||||
|
||||
getArgs(): any[] {
|
||||
return super.getArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@linkcode PokemonIncrementingStatModifier} should be applied to the {@linkcode Pokemon}.
|
||||
* @param pokemon The {@linkcode Pokemon} that holds the item
|
||||
@ -1217,10 +1212,6 @@ export class StatBoosterModifier extends PokemonHeldItemModifier {
|
||||
* @see {@linkcode apply}
|
||||
*/
|
||||
export class EvolutionStatBoosterModifier extends StatBoosterModifier {
|
||||
clone() {
|
||||
return super.clone() as EvolutionStatBoosterModifier;
|
||||
}
|
||||
|
||||
matchType(modifier: Modifier): boolean {
|
||||
return modifier instanceof EvolutionStatBoosterModifier;
|
||||
}
|
||||
@ -3232,8 +3223,7 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
||||
}
|
||||
|
||||
/**
|
||||
* Steals an item from a set of target Pokemon.
|
||||
* This prioritizes high-tier held items when selecting the item to steal.
|
||||
* Steals an item, chosen randomly, from a set of target Pokemon.
|
||||
* @param pokemon The {@linkcode Pokemon} holding this item
|
||||
* @param target The {@linkcode Pokemon} to steal from (optional)
|
||||
* @param _args N/A
|
||||
@ -3253,30 +3243,15 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier {
|
||||
return false;
|
||||
}
|
||||
|
||||
const poolType = pokemon.isPlayer()
|
||||
? ModifierPoolType.PLAYER
|
||||
: pokemon.hasTrainer()
|
||||
? ModifierPoolType.TRAINER
|
||||
: ModifierPoolType.WILD;
|
||||
|
||||
const transferredModifierTypes: ModifierType[] = [];
|
||||
const itemModifiers = globalScene.findModifiers(
|
||||
m => m instanceof PokemonHeldItemModifier && m.pokemonId === targetPokemon.id && m.isTransferable,
|
||||
targetPokemon.isPlayer(),
|
||||
) as PokemonHeldItemModifier[];
|
||||
let highestItemTier = itemModifiers
|
||||
.map(m => m.type.getOrInferTier(poolType))
|
||||
.reduce((highestTier, tier) => Math.max(tier!, highestTier), 0); // TODO: is this bang correct?
|
||||
let tierItemModifiers = itemModifiers.filter(m => m.type.getOrInferTier(poolType) === highestItemTier);
|
||||
|
||||
for (let i = 0; i < transferredItemCount; i++) {
|
||||
if (!tierItemModifiers.length) {
|
||||
while (highestItemTier-- && !tierItemModifiers.length) {
|
||||
tierItemModifiers = itemModifiers.filter(m => m.type.tier === highestItemTier);
|
||||
}
|
||||
if (!tierItemModifiers.length) {
|
||||
break;
|
||||
}
|
||||
if (!itemModifiers.length) {
|
||||
break;
|
||||
}
|
||||
const randItemIndex = pokemon.randBattleSeedInt(itemModifiers.length);
|
||||
const randItem = itemModifiers[randItemIndex];
|
||||
|
26
src/phase.ts
26
src/phase.ts
@ -1,9 +1,33 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import type { PhaseMap, PhaseString } from "./@types/phase-types";
|
||||
|
||||
export class Phase {
|
||||
export abstract class Phase {
|
||||
start() {}
|
||||
|
||||
end() {
|
||||
globalScene.shiftPhase();
|
||||
}
|
||||
|
||||
/**
|
||||
* The string name of the phase, used to identify the phase type for {@linkcode is}
|
||||
*
|
||||
* @privateremarks
|
||||
*
|
||||
* When implementing a phase, you must set the `phaseName` property to the name of the phase.
|
||||
*/
|
||||
public abstract readonly phaseName: PhaseString;
|
||||
|
||||
/**
|
||||
* Check if the phase is of the given type without requiring `instanceof`.
|
||||
*
|
||||
* @param phase - The string name of the phase to check.
|
||||
* @returns Whether this phase is of the provided type.
|
||||
*
|
||||
* @remarks
|
||||
* This does not check for subclasses! It only checks if the phase is *exactly* the given type.
|
||||
* This method exists to avoid circular import issues, as using `instanceof` would require importing each phase.
|
||||
*/
|
||||
is<K extends keyof PhaseMap>(phase: K): this is PhaseMap[K] {
|
||||
return this.phaseName === phase;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import { Phase } from "#app/phase";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
|
||||
export class AddEnemyBuffModifierPhase extends Phase {
|
||||
public readonly phaseName = "AddEnemyBuffModifierPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -27,6 +27,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { Gender } from "#app/data/gender";
|
||||
|
||||
export class AttemptCapturePhase extends PokemonPhase {
|
||||
public readonly phaseName = "AttemptCapturePhase";
|
||||
private pokeballType: PokeballType;
|
||||
private pokeball: Phaser.GameObjects.Sprite;
|
||||
private originalY: number;
|
||||
|
@ -17,6 +17,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { SelectBiomePhase } from "./select-biome-phase";
|
||||
|
||||
export class AttemptRunPhase extends PokemonPhase {
|
||||
public readonly phaseName = "AttemptRunPhase";
|
||||
/** For testing purposes: this is to force the pokemon to fail and escape */
|
||||
public forceFailEscape = false;
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { BattlePhase } from "./battle-phase";
|
||||
import { GameOverPhase } from "./game-over-phase";
|
||||
|
||||
export class BattleEndPhase extends BattlePhase {
|
||||
public readonly phaseName = "BattleEndPhase";
|
||||
/** If true, will increment battles won */
|
||||
isVictory: boolean;
|
||||
|
||||
@ -19,7 +20,7 @@ export class BattleEndPhase extends BattlePhase {
|
||||
|
||||
// cull any extra `BattleEnd` phases from the queue.
|
||||
globalScene.phaseQueue = globalScene.phaseQueue.filter(phase => {
|
||||
if (phase instanceof BattleEndPhase) {
|
||||
if (phase.is("BattleEndPhase")) {
|
||||
this.isVictory ||= phase.isVictory;
|
||||
return false;
|
||||
}
|
||||
@ -28,7 +29,7 @@ export class BattleEndPhase extends BattlePhase {
|
||||
// `phaseQueuePrepend` is private, so we have to use this inefficient loop.
|
||||
while (
|
||||
globalScene.tryRemoveUnshiftedPhase(phase => {
|
||||
if (phase instanceof BattleEndPhase) {
|
||||
if (phase.is("BattleEndPhase")) {
|
||||
this.isVictory ||= phase.isVictory;
|
||||
return true;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { TrainerSlot } from "#enums/trainer-slot";
|
||||
import { Phase } from "#app/phase";
|
||||
|
||||
export class BattlePhase extends Phase {
|
||||
export abstract class BattlePhase extends Phase {
|
||||
showEnemyTrainer(trainerSlot: TrainerSlot = TrainerSlot.NONE): void {
|
||||
if (!globalScene.currentBattle.trainer) {
|
||||
console.warn("Enemy trainer is missing!");
|
||||
|
@ -20,6 +20,7 @@ import type Pokemon from "#app/field/pokemon";
|
||||
* Also triggers Cud Chew's "repeat berry use" effects
|
||||
*/
|
||||
export class BerryPhase extends FieldPhase {
|
||||
public readonly phaseName = "BerryPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -4,6 +4,7 @@ import type { BattlerIndex } from "#app/battle";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
|
||||
export class CheckStatusEffectPhase extends Phase {
|
||||
public readonly phaseName = "CheckStatusEffectPhase";
|
||||
private order: BattlerIndex[];
|
||||
constructor(order: BattlerIndex[]) {
|
||||
super();
|
||||
|
@ -10,6 +10,7 @@ import { SwitchPhase } from "./switch-phase";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
|
||||
export class CheckSwitchPhase extends BattlePhase {
|
||||
public readonly phaseName = "CheckSwitchPhase";
|
||||
protected fieldIndex: number;
|
||||
protected useName: boolean;
|
||||
|
||||
|
@ -25,6 +25,7 @@ import { ArenaTagSide } from "#app/data/arena-tag";
|
||||
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
||||
|
||||
export class CommandPhase extends FieldPhase {
|
||||
public readonly phaseName = "CommandPhase";
|
||||
protected fieldIndex: number;
|
||||
|
||||
constructor(fieldIndex: number) {
|
||||
|
@ -5,6 +5,9 @@ import { CommonBattleAnim } from "#app/data/battle-anims";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
|
||||
export class CommonAnimPhase extends PokemonPhase {
|
||||
// PokemonHealPhase extends CommonAnimPhase, and to make typescript happy,
|
||||
// we need to allow phaseName to be a union of the two
|
||||
public readonly phaseName: "CommonAnimPhase" | "PokemonHealPhase" | "WeatherEffectPhase" = "CommonAnimPhase";
|
||||
private anim: CommonAnim | null;
|
||||
private targetIndex?: BattlerIndex;
|
||||
private playOnEmptyField: boolean;
|
||||
|
@ -6,6 +6,7 @@ import { fixedInt } from "#app/utils/common";
|
||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||
|
||||
export class DamageAnimPhase extends PokemonPhase {
|
||||
public readonly phaseName = "DamageAnimPhase";
|
||||
private amount: number;
|
||||
private damageResult: DamageResult;
|
||||
private critical: boolean;
|
||||
|
@ -20,6 +20,7 @@ import { doShinySparkleAnim } from "#app/field/anims";
|
||||
* Class that represents egg hatching
|
||||
*/
|
||||
export class EggHatchPhase extends Phase {
|
||||
public readonly phaseName = "EggHatchPhase";
|
||||
/** The egg that is hatching */
|
||||
private egg: Egg;
|
||||
/** The new EggHatchData for the egg/pokemon that hatches */
|
||||
@ -224,7 +225,7 @@ export class EggHatchPhase extends Phase {
|
||||
}
|
||||
|
||||
end() {
|
||||
if (globalScene.findPhase(p => p instanceof EggHatchPhase)) {
|
||||
if (globalScene.findPhase(p => p.is("EggHatchPhase"))) {
|
||||
this.eggHatchHandler.clear();
|
||||
} else {
|
||||
globalScene.time.delayedCall(250, () => globalScene.setModifiersVisible(true));
|
||||
|
@ -16,6 +16,7 @@ import { EggHatchData } from "#app/data/egg-hatch-data";
|
||||
* Also handles prompts for skipping animation, and calling the egg summary phase
|
||||
*/
|
||||
export class EggLapsePhase extends Phase {
|
||||
public readonly phaseName = "EggLapsePhase";
|
||||
private eggHatchData: EggHatchData[] = [];
|
||||
private readonly minEggsToSkip: number = 2;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import type { EggHatchData } from "#app/data/egg-hatch-data";
|
||||
* Phase is handled mostly by the egg-hatch-scene-handler UI
|
||||
*/
|
||||
export class EggSummaryPhase extends Phase {
|
||||
public readonly phaseName = "EggSummaryPhase";
|
||||
private eggHatchData: EggHatchData[];
|
||||
|
||||
constructor(eggHatchData: EggHatchData[]) {
|
||||
|
@ -47,6 +47,8 @@ import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mys
|
||||
import { getNatureName } from "#app/data/nature";
|
||||
|
||||
export class EncounterPhase extends BattlePhase {
|
||||
// Union type is necessary as this is subclassed, and typescript will otherwise complain
|
||||
public readonly phaseName: "EncounterPhase" | "NextEncounterPhase" | "NewBiomeEncounterPhase" = "EncounterPhase";
|
||||
private loaded: boolean;
|
||||
|
||||
constructor(loaded = false) {
|
||||
|
@ -5,6 +5,7 @@ import { addTextObject, TextStyle } from "#app/ui/text";
|
||||
import i18next from "i18next";
|
||||
|
||||
export class EndCardPhase extends Phase {
|
||||
public readonly phaseName = "EndCardPhase";
|
||||
public endCard: Phaser.GameObjects.Image;
|
||||
public text: Phaser.GameObjects.Text;
|
||||
start(): void {
|
||||
|
@ -3,6 +3,7 @@ import { Phase } from "#app/phase";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
|
||||
export class EndEvolutionPhase extends Phase {
|
||||
public readonly phaseName = "EndEvolutionPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -15,6 +15,7 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
* @see {@linkcode EnemyPokemon.getNextMove}
|
||||
*/
|
||||
export class EnemyCommandPhase extends FieldPhase {
|
||||
public readonly phaseName = "EnemyCommandPhase";
|
||||
protected fieldIndex: number;
|
||||
protected skipTurn = false;
|
||||
|
||||
|
@ -19,6 +19,9 @@ import { EndEvolutionPhase } from "#app/phases/end-evolution-phase";
|
||||
import { EVOLVE_MOVE } from "#app/data/balance/pokemon-level-moves";
|
||||
|
||||
export class EvolutionPhase extends Phase {
|
||||
// FormChangePhase inherits from this, but EvolutionPhase is not abstract.
|
||||
// We have to use the union here
|
||||
public readonly phaseName: "EvolutionPhase" | "FormChangePhase" = "EvolutionPhase";
|
||||
protected pokemon: PlayerPokemon;
|
||||
protected lastLevel: number;
|
||||
|
||||
|
@ -7,6 +7,7 @@ import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-pha
|
||||
import { LevelUpPhase } from "./level-up-phase";
|
||||
|
||||
export class ExpPhase extends PlayerPartyMemberPokemonPhase {
|
||||
public readonly phaseName = "ExpPhase";
|
||||
private expValue: number;
|
||||
|
||||
constructor(partyMemberIndex: number, expValue: number) {
|
||||
|
@ -18,7 +18,8 @@ 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, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
|
||||
import { HitResult, PokemonMove } from "#app/field/pokemon";
|
||||
import type { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { PokemonInstantReviveModifier } from "#app/modifier/modifier";
|
||||
import { SwitchType } from "#enums/switch-type";
|
||||
@ -35,6 +36,7 @@ import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
|
||||
export class FaintPhase extends PokemonPhase {
|
||||
public readonly phaseName = "FaintPhase";
|
||||
/**
|
||||
* Whether or not instant revive should be prevented
|
||||
*/
|
||||
@ -78,10 +80,15 @@ export class FaintPhase extends PokemonPhase {
|
||||
}
|
||||
}
|
||||
|
||||
/** In case the current pokemon was just switched in, make sure it is counted as participating in the combat */
|
||||
/**
|
||||
* In case the current pokemon was just switched in, make sure it is counted as participating in the combat.
|
||||
* For EXP_SHARE purposes, if the current pokemon faints as the combat ends and it was the ONLY player pokemon
|
||||
* involved in combat, it needs to be counted as a participant so the other party pokemon can get their EXP,
|
||||
* so the fainted pokemon has been included.
|
||||
*/
|
||||
for (const pokemon of globalScene.getPlayerField()) {
|
||||
if (pokemon?.isActive(true) && pokemon.isPlayer()) {
|
||||
globalScene.currentBattle.addParticipant(pokemon as PlayerPokemon);
|
||||
if (pokemon?.isActive() || pokemon?.isFainted()) {
|
||||
globalScene.currentBattle.addParticipant(pokemon);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +204,7 @@ export class FaintPhase extends PokemonPhase {
|
||||
}
|
||||
|
||||
pokemon.faintCry(() => {
|
||||
if (pokemon instanceof PlayerPokemon) {
|
||||
if (pokemon.isPlayer()) {
|
||||
pokemon.addFriendship(-FRIENDSHIP_LOSS_FROM_FAINT);
|
||||
}
|
||||
pokemon.hideInfo();
|
||||
|
@ -13,6 +13,7 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
|
||||
export class FormChangePhase extends EvolutionPhase {
|
||||
public readonly phaseName = "FormChangePhase";
|
||||
private formChange: SpeciesFormChange;
|
||||
private modal: boolean;
|
||||
|
||||
|
@ -4,6 +4,7 @@ import i18next from "i18next";
|
||||
import { ModifierRewardPhase } from "./modifier-reward-phase";
|
||||
|
||||
export class GameOverModifierRewardPhase extends ModifierRewardPhase {
|
||||
public readonly phaseName = "GameOverModifierRewardPhase";
|
||||
doReward(): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
const newModifier = this.modifierType.newModifier();
|
||||
|
@ -34,6 +34,7 @@ import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
|
||||
import { MessagePhase } from "./message-phase";
|
||||
|
||||
export class GameOverPhase extends BattlePhase {
|
||||
public readonly phaseName = "GameOverPhase";
|
||||
private isVictory: boolean;
|
||||
private firstRibbons: PokemonSpecies[] = [];
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { Phase } from "#app/phase";
|
||||
|
||||
export class HideAbilityPhase extends Phase {
|
||||
public readonly phaseName = "HideAbilityPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
||||
export class HidePartyExpBarPhase extends BattlePhase {
|
||||
public readonly phaseName = "HidePartyExpBarPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -12,7 +12,6 @@ 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";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
|
||||
export enum LearnMoveType {
|
||||
/** For learning a move via level-up, evolution, or other non-item-based event */
|
||||
@ -24,6 +23,7 @@ export enum LearnMoveType {
|
||||
}
|
||||
|
||||
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||
public readonly phaseName = "LearnMovePhase";
|
||||
private moveId: MoveId;
|
||||
private messageMode: UiMode;
|
||||
private learnMoveType: LearnMoveType;
|
||||
@ -195,7 +195,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||
pokemon.usedTMs = [];
|
||||
}
|
||||
pokemon.usedTMs.push(this.moveId);
|
||||
globalScene.tryRemovePhase(phase => phase instanceof SelectModifierPhase);
|
||||
globalScene.tryRemovePhase(phase => phase.is("SelectModifierPhase"));
|
||||
} else if (this.learnMoveType === LearnMoveType.MEMORY) {
|
||||
if (this.cost !== -1) {
|
||||
if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) {
|
||||
@ -205,7 +205,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||
}
|
||||
globalScene.playSound("se/buy");
|
||||
} else {
|
||||
globalScene.tryRemovePhase(phase => phase instanceof SelectModifierPhase);
|
||||
globalScene.tryRemovePhase(phase => phase.is("SelectModifierPhase"));
|
||||
}
|
||||
}
|
||||
pokemon.setMove(index, this.moveId);
|
||||
|
@ -4,6 +4,7 @@ import i18next from "i18next";
|
||||
import { FieldPhase } from "./field-phase";
|
||||
|
||||
export class LevelCapPhase extends FieldPhase {
|
||||
public readonly phaseName = "LevelCapPhase";
|
||||
start(): void {
|
||||
super.start();
|
||||
|
||||
|
@ -10,6 +10,7 @@ import { NumberHolder } from "#app/utils/common";
|
||||
import i18next from "i18next";
|
||||
|
||||
export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
|
||||
public readonly phaseName = "LevelUpPhase";
|
||||
protected lastLevel: number;
|
||||
protected level: number;
|
||||
protected pokemon: PlayerPokemon = this.getPlayerPokemon();
|
||||
|
@ -8,6 +8,7 @@ import { Phase } from "#app/phase";
|
||||
* isn't already loaded (e.g. for Metronome)
|
||||
*/
|
||||
export class LoadMoveAnimPhase extends Phase {
|
||||
public readonly phaseName = "LoadMoveAnimPhase";
|
||||
constructor(protected moveId: MoveId) {
|
||||
super();
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { SelectGenderPhase } from "./select-gender-phase";
|
||||
import { UnavailablePhase } from "./unavailable-phase";
|
||||
|
||||
export class LoginPhase extends Phase {
|
||||
public readonly phaseName = "LoginPhase";
|
||||
private showText: boolean;
|
||||
|
||||
constructor(showText = true) {
|
||||
|
@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene";
|
||||
import { Phase } from "#app/phase";
|
||||
|
||||
export class MessagePhase extends Phase {
|
||||
public readonly phaseName = "MessagePhase";
|
||||
private text: string;
|
||||
private callbackDelay?: number | null;
|
||||
private prompt?: boolean | null;
|
||||
|
@ -5,6 +5,10 @@ import i18next from "i18next";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
||||
export class ModifierRewardPhase extends BattlePhase {
|
||||
// RibbonModifierRewardPhase extends ModifierRewardPhase and to make typescript happy
|
||||
// we need to use a union type here
|
||||
public readonly phaseName: "ModifierRewardPhase" | "RibbonModifierRewardPhase" | "GameOverModifierRewardPhase" =
|
||||
"ModifierRewardPhase";
|
||||
protected modifierType: ModifierType;
|
||||
|
||||
constructor(modifierTypeFunc: ModifierTypeFunc) {
|
||||
|
@ -6,6 +6,7 @@ import { NumberHolder } from "#app/utils/common";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
||||
export class MoneyRewardPhase extends BattlePhase {
|
||||
public readonly phaseName = "MoneyRewardPhase";
|
||||
private moneyMultiplier: number;
|
||||
|
||||
constructor(moneyMultiplier: number) {
|
||||
|
@ -5,6 +5,8 @@ import { Phase } from "#app/phase";
|
||||
* Plays the given {@linkcode MoveAnim} sequentially.
|
||||
*/
|
||||
export class MoveAnimPhase<Anim extends MoveAnim> extends Phase {
|
||||
public readonly phaseName = "MoveAnimPhase";
|
||||
|
||||
constructor(
|
||||
protected anim: Anim,
|
||||
protected onSubstitute = false,
|
||||
|
@ -9,13 +9,13 @@ import { BooleanHolder } from "#app/utils/common";
|
||||
import { MovePhase } from "#app/phases/move-phase";
|
||||
import { PokemonPhase } from "#app/phases/pokemon-phase";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MoveEndPhase } from "#app/phases/move-end-phase";
|
||||
|
||||
/**
|
||||
* Phase for the "charging turn" of two-turn moves (e.g. Dig).
|
||||
* @extends {@linkcode PokemonPhase}
|
||||
*/
|
||||
export class MoveChargePhase extends PokemonPhase {
|
||||
public readonly phaseName = "MoveChargePhase";
|
||||
/** The move instance that this phase applies */
|
||||
public move: PokemonMove;
|
||||
/** The field index targeted by the move (Charging moves assume single target) */
|
||||
@ -62,7 +62,7 @@ export class MoveChargePhase extends PokemonPhase {
|
||||
|
||||
if (instantCharge.value) {
|
||||
// this MoveEndPhase will be duplicated by the queued MovePhase if not removed
|
||||
globalScene.tryRemovePhase(phase => phase instanceof MoveEndPhase && phase.getPokemon() === user);
|
||||
globalScene.tryRemovePhase(phase => phase.is("MoveEndPhase") && phase.getPokemon() === user);
|
||||
// queue a new MovePhase for this move's attack phase
|
||||
globalScene.unshiftPhase(new MovePhase(user, [this.targetIndex], this.move, false));
|
||||
} else {
|
||||
|
@ -82,6 +82,7 @@ import { DamageAchv } from "#app/system/achv";
|
||||
type HitCheckEntry = [HitCheckResult, TypeDamageMultiplier];
|
||||
|
||||
export class MoveEffectPhase extends PokemonPhase {
|
||||
public readonly phaseName = "MoveEffectPhase";
|
||||
public move: Move;
|
||||
private virtual = false;
|
||||
protected targets: BattlerIndex[];
|
||||
@ -218,6 +219,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: The fallthrough is intentional
|
||||
case HitCheckResult.NO_EFFECT:
|
||||
globalScene.queueMessage(
|
||||
i18next.t(this.move.id === MoveId.SHEER_COLD ? "battle:hitResultImmune" : "battle:hitResultNoEffect", {
|
||||
@ -293,7 +295,8 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
|
||||
// If other effects were overriden, stop this phase before they can be applied
|
||||
if (overridden.value) {
|
||||
return this.end();
|
||||
this.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Lapse `MOVE_EFFECT` effects (i.e. semi-invulnerability) when applicable
|
||||
@ -742,7 +745,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
firstTarget?: boolean | null,
|
||||
selfTarget?: boolean,
|
||||
): void {
|
||||
return applyFilteredMoveAttrs(
|
||||
applyFilteredMoveAttrs(
|
||||
(attr: MoveAttr) =>
|
||||
attr instanceof MoveEffectAttr &&
|
||||
attr.trigger === triggerType &&
|
||||
@ -884,7 +887,7 @@ export class MoveEffectPhase extends PokemonPhase {
|
||||
sourceBattlerIndex: user.getBattlerIndex(),
|
||||
});
|
||||
|
||||
if (user.isPlayer() && !target.isPlayer()) {
|
||||
if (user.isPlayer() && target.isEnemy()) {
|
||||
globalScene.applyModifiers(DamageMoneyRewardModifier, true, user, new NumberHolder(damage));
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { applyPostSummonAbAttrs, PostSummonRemoveEffectAbAttr } from "#app/data/
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
|
||||
export class MoveEndPhase extends PokemonPhase {
|
||||
public readonly phaseName = "MoveEndPhase";
|
||||
private wasFollowUp: boolean;
|
||||
|
||||
/** Targets from the preceding MovePhase */
|
||||
|
@ -4,6 +4,7 @@ import type Pokemon from "#app/field/pokemon";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
||||
export class MoveHeaderPhase extends BattlePhase {
|
||||
public readonly phaseName = "MoveHeaderPhase";
|
||||
public pokemon: Pokemon;
|
||||
public move: PokemonMove;
|
||||
|
||||
|
@ -52,6 +52,7 @@ import { StatusEffect } from "#enums/status-effect";
|
||||
import i18next from "i18next";
|
||||
|
||||
export class MovePhase extends BattlePhase {
|
||||
public readonly phaseName = "MovePhase";
|
||||
protected _pokemon: Pokemon;
|
||||
protected _move: PokemonMove;
|
||||
protected _targets: BattlerIndex[];
|
||||
|
@ -6,7 +6,6 @@ import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-d
|
||||
import { CheckSwitchPhase } from "#app/phases/check-switch-phase";
|
||||
import { GameOverPhase } from "#app/phases/game-over-phase";
|
||||
import { NewBattlePhase } from "#app/phases/new-battle-phase";
|
||||
import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase";
|
||||
import { ReturnPhase } from "#app/phases/return-phase";
|
||||
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase";
|
||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
||||
@ -39,6 +38,7 @@ import { SelectBiomePhase } from "./select-biome-phase";
|
||||
* - Queuing of the {@linkcode MysteryEncounterOptionSelectedPhase}
|
||||
*/
|
||||
export class MysteryEncounterPhase extends Phase {
|
||||
public readonly phaseName = "MysteryEncounterPhase";
|
||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 300;
|
||||
optionSelectSettings?: OptionSelectSettings;
|
||||
|
||||
@ -180,6 +180,7 @@ export class MysteryEncounterPhase extends Phase {
|
||||
* Any phase that is meant to follow this one MUST be queued via the onOptionSelect() logic of the selected option
|
||||
*/
|
||||
export class MysteryEncounterOptionSelectedPhase extends Phase {
|
||||
public readonly phaseName = "MysteryEncounterOptionSelectedPhase";
|
||||
onOptionSelect: OptionPhaseCallback;
|
||||
|
||||
constructor() {
|
||||
@ -221,6 +222,7 @@ export class MysteryEncounterOptionSelectedPhase extends Phase {
|
||||
* See {@linkcode TurnEndPhase} for more details
|
||||
*/
|
||||
export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
||||
public readonly phaseName = "MysteryEncounterBattleStartCleanupPhase";
|
||||
/**
|
||||
* Cleans up `TURN_END` tags, any {@linkcode PostTurnStatusEffectPhase}s, checks for Pokemon switches, then continues
|
||||
*/
|
||||
@ -245,8 +247,8 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
||||
});
|
||||
|
||||
// Remove any status tick phases
|
||||
while (globalScene.findPhase(p => p instanceof PostTurnStatusEffectPhase)) {
|
||||
globalScene.tryRemovePhase(p => p instanceof PostTurnStatusEffectPhase);
|
||||
while (globalScene.findPhase(p => p.is("PostTurnStatusEffectPhase"))) {
|
||||
globalScene.tryRemovePhase(p => p.is("PostTurnStatusEffectPhase"));
|
||||
}
|
||||
|
||||
// The total number of Pokemon in the player's party that can legally fight
|
||||
@ -284,6 +286,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
|
||||
* - Queue the {@linkcode SummonPhase}s, {@linkcode PostSummonPhase}s, etc., required to initialize the phase queue for a battle
|
||||
*/
|
||||
export class MysteryEncounterBattlePhase extends Phase {
|
||||
public readonly phaseName = "MysteryEncounterBattlePhase";
|
||||
disableSwitch: boolean;
|
||||
|
||||
constructor(disableSwitch = false) {
|
||||
@ -513,6 +516,7 @@ export class MysteryEncounterBattlePhase extends Phase {
|
||||
* - Queuing of the {@linkcode PostMysteryEncounterPhase}
|
||||
*/
|
||||
export class MysteryEncounterRewardsPhase extends Phase {
|
||||
public readonly phaseName = "MysteryEncounterRewardsPhase";
|
||||
addHealPhase: boolean;
|
||||
|
||||
constructor(addHealPhase = false) {
|
||||
@ -558,7 +562,7 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
||||
if (encounter.doEncounterRewards) {
|
||||
encounter.doEncounterRewards();
|
||||
} else if (this.addHealPhase) {
|
||||
globalScene.tryRemovePhase(p => p instanceof SelectModifierPhase);
|
||||
globalScene.tryRemovePhase(p => p.is("SelectModifierPhase"));
|
||||
globalScene.unshiftPhase(
|
||||
new SelectModifierPhase(0, undefined, {
|
||||
fillRemaining: false,
|
||||
@ -580,6 +584,7 @@ export class MysteryEncounterRewardsPhase extends Phase {
|
||||
* - Queuing of the next wave
|
||||
*/
|
||||
export class PostMysteryEncounterPhase extends Phase {
|
||||
public readonly phaseName = "PostMysteryEncounterPhase";
|
||||
private readonly FIRST_DIALOGUE_PROMPT_DELAY = 750;
|
||||
onPostOptionSelect?: OptionPhaseCallback;
|
||||
|
||||
|
@ -2,13 +2,14 @@ import { globalScene } from "#app/global-scene";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
||||
export class NewBattlePhase extends BattlePhase {
|
||||
public readonly phaseName = "NewBattlePhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
// cull any extra `NewBattle` phases from the queue.
|
||||
globalScene.phaseQueue = globalScene.phaseQueue.filter(phase => !(phase instanceof NewBattlePhase));
|
||||
globalScene.phaseQueue = globalScene.phaseQueue.filter(phase => !phase.is("NewBattlePhase"));
|
||||
// `phaseQueuePrepend` is private, so we have to use this inefficient loop.
|
||||
while (globalScene.tryRemoveUnshiftedPhase(phase => phase instanceof NewBattlePhase)) {}
|
||||
while (globalScene.tryRemoveUnshiftedPhase(phase => phase.is("NewBattlePhase"))) {}
|
||||
|
||||
globalScene.newBattle();
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { getRandomWeatherType } from "#app/data/weather";
|
||||
import { NextEncounterPhase } from "./next-encounter-phase";
|
||||
|
||||
export class NewBiomeEncounterPhase extends NextEncounterPhase {
|
||||
public readonly phaseName = "NewBiomeEncounterPhase";
|
||||
doEncounter(): void {
|
||||
globalScene.playBgm(undefined, true);
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { EncounterPhase } from "./encounter-phase";
|
||||
* Handles generating, loading and preparing for it.
|
||||
*/
|
||||
export class NextEncounterPhase extends EncounterPhase {
|
||||
public readonly phaseName: "NextEncounterPhase" | "NewBiomeEncounterPhase" = "NextEncounterPhase";
|
||||
start() {
|
||||
super.start();
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { applyPostSetStatusAbAttrs, PostSetStatusAbAttr } from "#app/data/abilit
|
||||
import { isNullOrUndefined } from "#app/utils/common";
|
||||
|
||||
export class ObtainStatusEffectPhase extends PokemonPhase {
|
||||
public readonly phaseName = "ObtainStatusEffectPhase";
|
||||
private statusEffect?: StatusEffect;
|
||||
private turnsRemaining?: number;
|
||||
private sourceText?: string | null;
|
||||
|
@ -6,6 +6,7 @@ import { Phase } from "#app/phase";
|
||||
* Intended to be used as a more 1-off phase to provide exp to the party (such as during MEs), rather than cleanup a battle entirely
|
||||
*/
|
||||
export class PartyExpPhase extends Phase {
|
||||
public readonly phaseName = "PartyExpPhase";
|
||||
expValue: number;
|
||||
useWaveIndexMultiplier?: boolean;
|
||||
pokemonParticipantIds?: Set<number>;
|
||||
|
@ -3,6 +3,7 @@ import { fixedInt } from "#app/utils/common";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
|
||||
export class PartyHealPhase extends BattlePhase {
|
||||
public readonly phaseName = "PartyHealPhase";
|
||||
private resumeBgm: boolean;
|
||||
|
||||
constructor(resumeBgm: boolean) {
|
||||
|
@ -7,6 +7,7 @@ import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
|
||||
export class PokemonAnimPhase extends BattlePhase {
|
||||
public readonly phaseName = "PokemonAnimPhase";
|
||||
/** The type of animation to play in this phase */
|
||||
protected key: PokemonAnimType;
|
||||
/** The Pokemon to which this animation applies */
|
||||
|
@ -14,6 +14,7 @@ import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||
import type { HealBlockTag } from "#app/data/battler-tags";
|
||||
|
||||
export class PokemonHealPhase extends CommonAnimPhase {
|
||||
public readonly phaseName = "PokemonHealPhase";
|
||||
private hpHealed: number;
|
||||
private message: string | null;
|
||||
private showFullHpMessage: boolean;
|
||||
|
@ -13,6 +13,7 @@ import i18next from "i18next";
|
||||
* Used for Transform (move) and Imposter (ability)
|
||||
*/
|
||||
export class PokemonTransformPhase extends PokemonPhase {
|
||||
public readonly phaseName = "PokemonTransformPhase";
|
||||
protected targetIndex: BattlerIndex;
|
||||
private playSound: boolean;
|
||||
|
||||
|
@ -4,6 +4,7 @@ import type { EndCardPhase } from "./end-card-phase";
|
||||
import { TitlePhase } from "./title-phase";
|
||||
|
||||
export class PostGameOverPhase extends Phase {
|
||||
public readonly phaseName = "PostGameOverPhase";
|
||||
private endCardPhase?: EndCardPhase;
|
||||
|
||||
constructor(endCardPhase?: EndCardPhase) {
|
||||
|
@ -7,6 +7,7 @@ import { MysteryEncounterPostSummonTag } from "#app/data/battler-tags";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
|
||||
export class PostSummonPhase extends PokemonPhase {
|
||||
public readonly phaseName = "PostSummonPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -17,6 +17,7 @@ import { BooleanHolder, NumberHolder } from "#app/utils/common";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
|
||||
export class PostTurnStatusEffectPhase extends PokemonPhase {
|
||||
public readonly phaseName = "PostTurnStatusEffectPhase";
|
||||
// biome-ignore lint/complexity/noUselessConstructor: Not unnecessary as it makes battlerIndex required
|
||||
constructor(battlerIndex: BattlerIndex) {
|
||||
super(battlerIndex);
|
||||
|
@ -6,10 +6,9 @@ import { getTypeRgb } from "#app/data/type";
|
||||
import { BattleSpec } from "#app/enums/battle-spec";
|
||||
import { BattlerTagType } from "#app/enums/battler-tag-type";
|
||||
import type Pokemon from "#app/field/pokemon";
|
||||
import { EnemyPokemon } from "#app/field/pokemon";
|
||||
import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { BattlePhase } from "./battle-phase";
|
||||
import { MovePhase } from "./move-phase";
|
||||
import type { MovePhase } from "./move-phase";
|
||||
import { PokemonHealPhase } from "./pokemon-heal-phase";
|
||||
import {
|
||||
applyAbAttrs,
|
||||
@ -19,6 +18,7 @@ import {
|
||||
} from "#app/data/abilities/ability";
|
||||
|
||||
export class QuietFormChangePhase extends BattlePhase {
|
||||
public readonly phaseName = "QuietFormChangePhase";
|
||||
protected pokemon: Pokemon;
|
||||
protected formChange: SpeciesFormChange;
|
||||
|
||||
@ -157,7 +157,7 @@ export class QuietFormChangePhase extends BattlePhase {
|
||||
|
||||
end(): void {
|
||||
this.pokemon.findAndRemoveTags(t => t.tagType === BattlerTagType.AUTOTOMIZED);
|
||||
if (globalScene?.currentBattle.battleSpec === BattleSpec.FINAL_BOSS && this.pokemon instanceof EnemyPokemon) {
|
||||
if (globalScene?.currentBattle.battleSpec === BattleSpec.FINAL_BOSS && this.pokemon.isEnemy()) {
|
||||
globalScene.playBgm();
|
||||
globalScene.unshiftPhase(
|
||||
new PokemonHealPhase(this.pokemon.getBattlerIndex(), this.pokemon.getMaxHp(), null, false, false, false, true),
|
||||
@ -168,7 +168,7 @@ export class QuietFormChangePhase extends BattlePhase {
|
||||
this.pokemon.initBattleInfo();
|
||||
this.pokemon.cry();
|
||||
|
||||
const movePhase = globalScene.findPhase(p => p instanceof MovePhase && p.pokemon === this.pokemon) as MovePhase;
|
||||
const movePhase = globalScene.findPhase(p => p.is("MovePhase") && p.pokemon === this.pokemon) as MovePhase;
|
||||
if (movePhase) {
|
||||
movePhase.cancel();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { UiMode } from "#enums/ui-mode";
|
||||
import { fixedInt } from "#app/utils/common";
|
||||
|
||||
export class ReloadSessionPhase extends Phase {
|
||||
public readonly phaseName = "ReloadSessionPhase";
|
||||
private systemDataStr?: string;
|
||||
|
||||
constructor(systemDataStr?: string) {
|
||||
|
@ -7,6 +7,7 @@ import { BattlePhase } from "#app/phases/battle-phase";
|
||||
* This is necessary to perform in a phase primarly to ensure that the status icon disappears at the correct time in the battle
|
||||
*/
|
||||
export class ResetStatusPhase extends BattlePhase {
|
||||
public readonly phaseName = "ResetStatusPhase";
|
||||
private readonly pokemon: Pokemon;
|
||||
private readonly affectConfusion: boolean;
|
||||
private readonly reloadAssets: boolean;
|
||||
|
@ -4,6 +4,7 @@ import { SwitchType } from "#enums/switch-type";
|
||||
import { SwitchSummonPhase } from "./switch-summon-phase";
|
||||
|
||||
export class ReturnPhase extends SwitchSummonPhase {
|
||||
public readonly phaseName = "ReturnPhase";
|
||||
constructor(fieldIndex: number) {
|
||||
super(SwitchType.SWITCH, fieldIndex, -1, true);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import type { PlayerPokemon } from "#app/field/pokemon";
|
||||
* when used by one of the player's Pokemon.
|
||||
*/
|
||||
export class RevivalBlessingPhase extends BattlePhase {
|
||||
public readonly phaseName = "RevivalBlessingPhase";
|
||||
constructor(protected user: PlayerPokemon) {
|
||||
super();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import i18next from "i18next";
|
||||
import { ModifierRewardPhase } from "./modifier-reward-phase";
|
||||
|
||||
export class RibbonModifierRewardPhase extends ModifierRewardPhase {
|
||||
public readonly phaseName = "RibbonModifierRewardPhase";
|
||||
private species: PokemonSpecies;
|
||||
|
||||
constructor(modifierTypeFunc: ModifierTypeFunc, species: PokemonSpecies) {
|
||||
|
@ -8,6 +8,7 @@ import i18next from "i18next";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
|
||||
export class ScanIvsPhase extends PokemonPhase {
|
||||
public readonly phaseName = "ScanIvsPhase";
|
||||
// biome-ignore lint/complexity/noUselessConstructor: This changes `battlerIndex` to be required
|
||||
constructor(battlerIndex: BattlerIndex) {
|
||||
super(battlerIndex);
|
||||
|
@ -10,6 +10,7 @@ import { PartyHealPhase } from "./party-heal-phase";
|
||||
import { SwitchBiomePhase } from "./switch-biome-phase";
|
||||
|
||||
export class SelectBiomePhase extends BattlePhase {
|
||||
public readonly phaseName = "SelectBiomePhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { Phase } from "#app/phase";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
|
||||
export class SelectChallengePhase extends Phase {
|
||||
public readonly phaseName = "SelectChallengePhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { UiMode } from "#enums/ui-mode";
|
||||
import i18next from "i18next";
|
||||
|
||||
export class SelectGenderPhase extends Phase {
|
||||
public readonly phaseName = "SelectGenderPhase";
|
||||
start(): void {
|
||||
super.start();
|
||||
|
||||
|
@ -32,6 +32,7 @@ import type { CustomModifierSettings } from "#app/modifier/modifier-type";
|
||||
import { isNullOrUndefined, NumberHolder } from "#app/utils/common";
|
||||
|
||||
export class SelectModifierPhase extends BattlePhase {
|
||||
public readonly phaseName = "SelectModifierPhase";
|
||||
private rerollCount: number;
|
||||
private modifierTiers?: ModifierTier[];
|
||||
private customModifierSettings?: CustomModifierSettings;
|
||||
|
@ -15,6 +15,7 @@ import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
|
||||
import { isNullOrUndefined } from "#app/utils/common";
|
||||
|
||||
export class SelectStarterPhase extends Phase {
|
||||
public readonly phaseName = "SelectStarterPhase";
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
|
@ -8,6 +8,7 @@ import i18next from "#app/plugins/i18n";
|
||||
import { allMoves } from "#app/data/data-lists";
|
||||
|
||||
export class SelectTargetPhase extends PokemonPhase {
|
||||
public readonly phaseName = "SelectTargetPhase";
|
||||
// biome-ignore lint/complexity/noUselessConstructor: This makes `fieldIndex` required
|
||||
constructor(fieldIndex: number) {
|
||||
super(fieldIndex);
|
||||
|
@ -3,6 +3,7 @@ import type { BattlerIndex } from "#app/battle";
|
||||
import { PokemonPhase } from "./pokemon-phase";
|
||||
|
||||
export class ShinySparklePhase extends PokemonPhase {
|
||||
public readonly phaseName = "ShinySparklePhase";
|
||||
// biome-ignore lint/complexity/noUselessConstructor: This makes `battlerIndex` required
|
||||
constructor(battlerIndex: BattlerIndex) {
|
||||
super(battlerIndex);
|
||||
|
@ -5,6 +5,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
|
||||
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
||||
|
||||
export class ShowAbilityPhase extends PokemonPhase {
|
||||
public readonly phaseName = "ShowAbilityPhase";
|
||||
private passive: boolean;
|
||||
private pokemonName: string;
|
||||
private abilityName: string;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user