Merge branch 'pagefaultgames:beta' into beta

This commit is contained in:
Chapybara-jp 2024-09-20 16:51:03 +02:00 committed by GitHub
commit cde568101c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 139 additions and 73 deletions

View File

@ -782,6 +782,14 @@ export default class BattleScene extends SceneBase {
return this.getPlayerField().find(p => p.isActive());
}
/**
* Finds the first {@linkcode Pokemon.isActive() | active PlayerPokemon} that isn't also currently switching out
* @returns Either the first {@linkcode PlayerPokemon} satisfying, or undefined if no player pokemon on the field satisfy
*/
getNonSwitchedPlayerPokemon(): PlayerPokemon | undefined {
return this.getPlayerField().find(p => p.isActive() && p.switchOutStatus === false);
}
/**
* Returns an array of PlayerPokemon of length 1 or 2 depending on if double battles or not
* @returns array of {@linkcode PlayerPokemon}
@ -799,6 +807,14 @@ export default class BattleScene extends SceneBase {
return this.getEnemyField().find(p => p.isActive());
}
/**
* Finds the first {@linkcode Pokemon.isActive() | active EnemyPokemon} pokemon from the enemy that isn't also currently switching out
* @returns Either the first {@linkcode EnemyPokemon} satisfying, or undefined if no player pokemon on the field satisfy
*/
getNonSwitchedEnemyPokemon(): EnemyPokemon | undefined {
return this.getEnemyField().find(p => p.isActive() && p.switchOutStatus === false);
}
/**
* Returns an array of EnemyPokemon of length 1 or 2 depending on if double battles or not
* @returns array of {@linkcode EnemyPokemon}

View File

@ -16,6 +16,14 @@ import { TrainerType } from "#enums/trainer-type";
import i18next from "#app/plugins/i18n";
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { CustomModifierSettings } from "#app/modifier/modifier-type";
import { ModifierTier } from "#app/modifier/modifier-tier";
export enum ClassicFixedBossWaves {
// TODO: other fixed wave battles should be added here
EVIL_BOSS_1 = 115,
EVIL_BOSS_2 = 165,
}
export enum BattleType {
WILD,
@ -419,6 +427,7 @@ export class FixedBattleConfig {
public getTrainer: GetTrainerFunc;
public getEnemyParty: GetEnemyPartyFunc;
public seedOffsetWaveIndex: number;
public customModifierRewardSettings?: CustomModifierSettings;
setBattleType(battleType: BattleType): FixedBattleConfig {
this.battleType = battleType;
@ -444,6 +453,11 @@ export class FixedBattleConfig {
this.seedOffsetWaveIndex = seedOffsetWaveIndex;
return this;
}
setCustomModifierRewards(customModifierRewardSettings: CustomModifierSettings) {
this.customModifierRewardSettings = customModifierRewardSettings;
return this;
}
}
@ -503,11 +517,13 @@ export const classicFixedBattles: FixedBattleConfigs = {
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
[35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
[55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }),
[62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
[64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
@ -515,17 +531,21 @@ export const classicFixedBattles: FixedBattleConfigs = {
[66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true)),
[95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
[112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT ], true)),
[114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA ], true, 1)),
[115]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE ])),
[ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE ]))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
[145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
[165]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2 ])),
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
[ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2 ]))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }),
[182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])),
[184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182)
@ -538,4 +558,5 @@ export const classicFixedBattles: FixedBattleConfigs = {
.setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])),
[195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT))
.setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false })
};

View File

@ -428,7 +428,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
moveAnim.bgSprite.setScale(1.25);
moveAnim.bgSprite.setAlpha(this.opacity / 255);
scene.field.add(moveAnim.bgSprite);
const fieldPokemon = scene.getEnemyPokemon() || scene.getPlayerPokemon();
const fieldPokemon = scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon();
if (!isNullOrUndefined(priority)) {
scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority!);
} else if (fieldPokemon?.isOnField()) {
@ -989,7 +989,7 @@ export abstract class BattleAnim {
const setSpritePriority = (priority: integer) => {
switch (priority) {
case 0:
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getEnemyPokemon() || scene.getPlayerPokemon()!); // TODO: is this bang correct?
scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption?
break;
case 1:
scene.field.moveTo(moveSprite, scene.field.getAll().length - 1);

View File

@ -5221,7 +5221,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
switchOutTarget.leaveField(false);
if (switchOutTarget.hp) {
switchOutTarget.setWildFlee(true);
user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500);
// in double battles redirect potential moves off fled pokemon

View File

@ -99,7 +99,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
public luck: integer;
public pauseEvolutions: boolean;
public pokerus: boolean;
public wildFlee: boolean;
public switchOutStatus: boolean;
public evoCounter: integer;
public fusionSpecies: PokemonSpecies | null;
@ -145,7 +145,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.species = species;
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
this.level = level;
this.wildFlee = false;
this.switchOutStatus = false;
// Determine the ability index
if (abilityIndex !== undefined) {
@ -343,7 +343,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
isAllowed(): boolean {
const challengeAllowed = new Utils.BooleanHolder(true);
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed);
return !this.wildFlee && challengeAllowed.value;
return !this.isFainted() && challengeAllowed.value;
}
isActive(onField?: boolean): boolean {
@ -2152,11 +2152,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
/**
* sets if the pokemon has fled (implies it's a wild pokemon)
* sets if the pokemon is switching out (if it's a enemy wild implies it's going to flee)
* @param status - boolean
*/
setWildFlee(status: boolean): void {
this.wildFlee = status;
setSwitchOutStatus(status: boolean): void {
this.switchOutStatus = status;
}
updateInfo(instant?: boolean): Promise<void> {
@ -3384,6 +3384,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.updateFusionPalette();
}
this.summonData = new PokemonSummonData();
this.setSwitchOutStatus(false);
if (!this.battleData) {
this.resetBattleData();
}
@ -3789,6 +3790,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.hideInfo();
}
this.scene.field.remove(this);
this.setSwitchOutStatus(true);
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true);
}
@ -3812,6 +3814,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const rootForm = getPokemonSpecies(this.species.getRootSpeciesId());
return rootForm.getAbility(abilityIndex) === rootForm.getAbility(currentAbilityIndex);
}
/**
* Helper function to check if the player already owns the starter data of the Pokemon's
* current ability
* @param ownedAbilityAttrs the owned abilityAttr of this Pokemon's root form
* @returns true if the player already has it, false otherwise
*/
checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs: number): boolean {
if ((ownedAbilityAttrs & 1) > 0 && this.hasSameAbilityInRootForm(0)) {
return true;
}
if ((ownedAbilityAttrs & 2) > 0 && this.hasSameAbilityInRootForm(1)) {
return true;
}
if ((ownedAbilityAttrs & 4) > 0 && this.hasSameAbilityInRootForm(2)) {
return true;
}
return false;
}
}
export default interface Pokemon {

View File

@ -268,7 +268,6 @@ export class GameMode implements GameModeConfig {
isFixedBattle(waveIndex: integer): boolean {
const dummyConfig = new FixedBattleConfig();
return this.battleConfig.hasOwnProperty(waveIndex) || applyChallenges(this, ChallengeType.FIXED_BATTLES, waveIndex, dummyConfig);
}
/**

View File

@ -1761,7 +1761,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.ABILITY_CHARM, skipInClassicAfterWave(189, 6)),
new WeightedModifierType(modifierTypes.FOCUS_BAND, 5),
new WeightedModifierType(modifierTypes.KINGS_ROCK, 3),
new WeightedModifierType(modifierTypes.LOCK_CAPSULE, skipInLastClassicWaveOrDefault(3)),
new WeightedModifierType(modifierTypes.LOCK_CAPSULE, (party: Pokemon[]) => party[0].scene.gameMode.isClassic ? 0 : 3),
new WeightedModifierType(modifierTypes.SUPER_EXP_CHARM, skipInLastClassicWaveOrDefault(8)),
new WeightedModifierType(modifierTypes.RARE_FORM_CHANGE_ITEM, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 50), 4) * 6, 24),
new WeightedModifierType(modifierTypes.MEGA_BRACELET, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 50), 4) * 9, 36),

View File

@ -40,7 +40,7 @@ export class EggLapsePhase extends Phase {
this.showSummary();
}, () => {
this.hatchEggsRegular(eggsToHatch);
this.showSummary();
this.end();
}
);
}, 100, true);

View File

@ -1,6 +1,6 @@
import BattleScene from "#app/battle-scene";
import { BattlerIndex, BattleType } from "#app/battle";
import { modifierTypes } from "#app/modifier/modifier-type";
import { BattlerIndex, BattleType, ClassicFixedBossWaves } from "#app/battle";
import { CustomModifierSettings, modifierTypes } from "#app/modifier/modifier-type";
import { BattleEndPhase } from "./battle-end-phase";
import { NewBattlePhase } from "./new-battle-phase";
import { PokemonPhase } from "./pokemon-phase";
@ -42,8 +42,12 @@ export class VictoryPhase extends PokemonPhase {
}
if (this.scene.gameMode.isEndless || !this.scene.gameMode.isWaveFinal(this.scene.currentBattle.waveIndex)) {
this.scene.pushPhase(new EggLapsePhase(this.scene));
if (this.scene.gameMode.isClassic && this.scene.currentBattle.waveIndex === ClassicFixedBossWaves.EVIL_BOSS_2) {
// Should get Lock Capsule on 165 before shop phase so it can be used in the rewards shop
this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.LOCK_CAPSULE));
}
if (this.scene.currentBattle.waveIndex % 10) {
this.scene.pushPhase(new SelectModifierPhase(this.scene));
this.scene.pushPhase(new SelectModifierPhase(this.scene, undefined, undefined, this.getFixedBattleCustomModifiers()));
} else if (this.scene.gameMode.isDaily) {
this.scene.pushPhase(new ModifierRewardPhase(this.scene, modifierTypes.EXP_CHARM));
if (this.scene.currentBattle.waveIndex > 10 && !this.scene.gameMode.isWaveFinal(this.scene.currentBattle.waveIndex)) {
@ -76,4 +80,18 @@ export class VictoryPhase extends PokemonPhase {
this.end();
}
/**
* If this wave is a fixed battle with special custom modifier rewards,
* will pass those settings to the upcoming {@linkcode SelectModifierPhase}`.
*/
getFixedBattleCustomModifiers(): CustomModifierSettings | undefined {
const gameMode = this.scene.gameMode;
const waveIndex = this.scene.currentBattle.waveIndex;
if (gameMode.isFixedBattle(waveIndex)) {
return gameMode.getFixedBattle(waveIndex).customModifierRewardSettings;
}
return undefined;
}
}

View File

@ -50,7 +50,7 @@ describe("Moves - Dragon Tail", () => {
await game.phaseInterceptor.to(BerryPhase);
const isVisible = enemyPokemon.visible;
const hasFled = enemyPokemon.wildFlee;
const hasFled = enemyPokemon.switchOutStatus;
expect(!isVisible && hasFled).toBe(true);
// simply want to test that the game makes it this far without crashing
@ -72,7 +72,7 @@ describe("Moves - Dragon Tail", () => {
await game.phaseInterceptor.to(BerryPhase);
const isVisible = enemyPokemon.visible;
const hasFled = enemyPokemon.wildFlee;
const hasFled = enemyPokemon.switchOutStatus;
expect(!isVisible && hasFled).toBe(true);
expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp());
}, TIMEOUT
@ -97,9 +97,9 @@ describe("Moves - Dragon Tail", () => {
await game.phaseInterceptor.to(TurnEndPhase);
const isVisibleLead = enemyLeadPokemon.visible;
const hasFledLead = enemyLeadPokemon.wildFlee;
const hasFledLead = enemyLeadPokemon.switchOutStatus;
const isVisibleSec = enemySecPokemon.visible;
const hasFledSec = enemySecPokemon.wildFlee;
const hasFledSec = enemySecPokemon.switchOutStatus;
expect(!isVisibleLead && hasFledLead && isVisibleSec && !hasFledSec).toBe(true);
expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp());
@ -133,9 +133,9 @@ describe("Moves - Dragon Tail", () => {
await game.phaseInterceptor.to(BerryPhase);
const isVisibleLead = enemyLeadPokemon.visible;
const hasFledLead = enemyLeadPokemon.wildFlee;
const hasFledLead = enemyLeadPokemon.switchOutStatus;
const isVisibleSec = enemySecPokemon.visible;
const hasFledSec = enemySecPokemon.wildFlee;
const hasFledSec = enemySecPokemon.switchOutStatus;
expect(!isVisibleLead && hasFledLead && !isVisibleSec && hasFledSec).toBe(true);
expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp());
expect(secPokemon.hp).toBeLessThan(secPokemon.getMaxHp());

View File

@ -381,17 +381,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
const ownedAbilityAttrs = pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr;
let playerOwnsThisAbility = false;
// Check if the player owns ability for the root form
if ((ownedAbilityAttrs & 1) > 0 && pokemon.hasSameAbilityInRootForm(0)) {
playerOwnsThisAbility = true;
}
if ((ownedAbilityAttrs & 2) > 0 && pokemon.hasSameAbilityInRootForm(1)) {
playerOwnsThisAbility = true;
}
if ((ownedAbilityAttrs & 4) > 0 && pokemon.hasSameAbilityInRootForm(2)) {
playerOwnsThisAbility = true;
}
const playerOwnsThisAbility = pokemon.checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs);
if (missingDexAttrs || !playerOwnsThisAbility) {
this.ownedIcon.setTint(0x808080);

View File

@ -267,18 +267,13 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.pokemonAbilityText.setColor(getTextColor(abilityTextStyle, false, this.scene.uiTheme));
this.pokemonAbilityText.setShadowColor(getTextColor(abilityTextStyle, true, this.scene.uiTheme));
/**
* If the opposing Pokemon only has 1 normal ability and is using the hidden ability it should have the same behavior
* if it had 2 normal abilities. This code checks if that is the case and uses the correct opponent Pokemon abilityIndex (2)
* for calculations so it aligns with where the hidden ability is stored in the starter data's abilityAttr (4)
*/
const opponentPokemonOneNormalAbility = (pokemon.species.getAbilityCount() === 2);
const opponentPokemonAbilityIndex = (opponentPokemonOneNormalAbility && pokemon.abilityIndex === 1) ? 2 : pokemon.abilityIndex;
const opponentPokemonAbilityAttr = 1 << opponentPokemonAbilityIndex;
const rootFormHasHiddenAbility = starterEntry.abilityAttr & opponentPokemonAbilityAttr;
const ownedAbilityAttrs = pokemon.scene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr;
if (!rootFormHasHiddenAbility) {
// Check if the player owns ability for the root form
const playerOwnsThisAbility = pokemon.checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs);
if (!playerOwnsThisAbility) {
this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, this.scene.uiTheme));
this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, this.scene.uiTheme));
} else {

View File

@ -13,7 +13,7 @@ import { RunEntry } from "../system/game-data";
import { PlayerGender } from "#enums/player-gender";
import { TrainerVariant } from "../field/trainer";
export type RunSelectCallback = (cursor: integer) => void;
export type RunSelectCallback = (cursor: number) => void;
export const RUN_HISTORY_LIMIT: number = 25;
@ -25,15 +25,15 @@ export const RUN_HISTORY_LIMIT: number = 25;
*/
export default class RunHistoryUiHandler extends MessageUiHandler {
private readonly maxRows = 3;
private runSelectContainer: Phaser.GameObjects.Container;
private runsContainer: Phaser.GameObjects.Container;
private runSelectMessageBox: Phaser.GameObjects.NineSlice;
private runSelectMessageBoxContainer: Phaser.GameObjects.Container;
private runs: RunEntryContainer[];
private runSelectCallback: RunSelectCallback | null;
private scrollCursor: integer = 0;
private scrollCursor: number = 0;
private cursorObj: Phaser.GameObjects.NineSlice | null;
@ -74,15 +74,15 @@ export default class RunHistoryUiHandler extends MessageUiHandler {
this.getUi().bringToTop(this.runSelectContainer);
this.runSelectContainer.setVisible(true);
this.populateRuns(this.scene);
this.populateRuns(this.scene).then(() => {
this.setScrollCursor(0);
this.setCursor(0);
this.setScrollCursor(0);
this.setCursor(0);
//Destroys the cursor if there are no runs saved so far.
if (this.runs.length === 0) {
this.clearCursor();
}
//Destroys the cursor if there are no runs saved so far.
if (this.runs.length === 0) {
this.clearCursor();
}
});
return true;
}
@ -122,13 +122,21 @@ export default class RunHistoryUiHandler extends MessageUiHandler {
success = this.setCursor(this.cursor - 1);
} else if (this.scrollCursor) {
success = this.setScrollCursor(this.scrollCursor - 1);
} else if (this.runs.length > 1) {
// wrap around to the bottom
success = this.setCursor(Math.min(this.runs.length - 1, this.maxRows - 1));
success = this.setScrollCursor(Math.max(0, this.runs.length - this.maxRows)) || success;
}
break;
case Button.DOWN:
if (this.cursor < 2) {
if (this.cursor < Math.min(this.maxRows - 1, this.runs.length - this.scrollCursor - 1)) {
success = this.setCursor(this.cursor + 1);
} else if (this.scrollCursor < this.runs.length - 3) {
} else if (this.scrollCursor < this.runs.length - this.maxRows) {
success = this.setScrollCursor(this.scrollCursor + 1);
} else if (this.runs.length > 1) {
// wrap around to the top
success = this.setCursor(0);
success = this.setScrollCursor(0) || success;
}
break;
}
@ -218,6 +226,7 @@ export default class RunHistoryUiHandler extends MessageUiHandler {
override clear() {
super.clear();
this.runSelectContainer.setVisible(false);
this.setScrollCursor(0);
this.clearCursor();
this.runSelectCallback = null;
this.clearRuns();
@ -360,7 +369,7 @@ class RunEntryContainer extends Phaser.GameObjects.Container {
// The code here does not account for icon weirdness.
const pokemonIconsContainer = this.scene.add.container(140, 17);
data.party.forEach((p: PokemonData, i: integer) => {
data.party.forEach((p: PokemonData, i: number) => {
const iconContainer = this.scene.add.container(26 * i, 0);
iconContainer.setScale(0.75);
const pokemon = p.toPokemon(this.scene);

View File

@ -49,15 +49,11 @@ export default class RunInfoUiHandler extends UiHandler {
private runResultContainer: Phaser.GameObjects.Container;
private runInfoContainer: Phaser.GameObjects.Container;
private partyContainer: Phaser.GameObjects.Container;
private partyHeldItemsContainer: Phaser.GameObjects.Container;
private statsBgWidth: integer;
private partyContainerHeight: integer;
private partyContainerWidth: integer;
private hallofFameContainer: Phaser.GameObjects.Container;
private endCardContainer: Phaser.GameObjects.Container;
private partyInfo: Phaser.GameObjects.Container[];
private partyVisibility: Boolean;
private modifiersModule: any;
@ -863,7 +859,7 @@ export default class RunInfoUiHandler extends UiHandler {
private buttonCycleOption(button: Button) {
switch (button) {
case Button.CYCLE_FORM:
if (this.isVictory) {
if (this.isVictory && this.pageMode !== RunInfoUiMode.HALL_OF_FAME) {
if (!this.endCardContainer || !this.endCardContainer.visible) {
this.createVictorySplash();
this.endCardContainer.setVisible(true);
@ -877,7 +873,7 @@ export default class RunInfoUiHandler extends UiHandler {
}
break;
case Button.CYCLE_SHINY:
if (this.isVictory) {
if (this.isVictory && this.pageMode !== RunInfoUiMode.ENDING_ART) {
if (!this.hallofFameContainer.visible) {
this.hallofFameContainer.setVisible(true);
this.pageMode = RunInfoUiMode.HALL_OF_FAME;
@ -888,7 +884,7 @@ export default class RunInfoUiHandler extends UiHandler {
}
break;
case Button.CYCLE_ABILITY:
if (this.runInfo.modifiers.length !== 0) {
if (this.runInfo.modifiers.length !== 0 && this.pageMode === RunInfoUiMode.MAIN) {
if (this.partyVisibility) {
this.showParty(false);
} else {

View File

@ -76,7 +76,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
.then(stats => {
this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`);
if (this.splashMessage === "splashMessages:battlesWon") {
this.splashMessageText.setText(i18next.t(this.splashMessage, { count: stats.battlesWon }));
this.splashMessageText.setText(i18next.t(this.splashMessage, { count: stats.battleCount }));
}
})
.catch(err => {

View File

@ -139,7 +139,8 @@ const noTransitionModes = [
Mode.TEST_DIALOGUE,
Mode.AUTO_COMPLETE,
Mode.ADMIN,
Mode.MYSTERY_ENCOUNTER
Mode.MYSTERY_ENCOUNTER,
Mode.RUN_INFO
];
export default class UI extends Phaser.GameObjects.Container {