diff --git a/public/images/cg/end_f.png b/public/images/cg/end_f_f.png similarity index 100% rename from public/images/cg/end_f.png rename to public/images/cg/end_f_f.png diff --git a/public/images/cg/end_f_m.png b/public/images/cg/end_f_m.png new file mode 100644 index 00000000000..84f94d7e05d Binary files /dev/null and b/public/images/cg/end_f_m.png differ diff --git a/public/images/cg/end_m.png b/public/images/cg/end_m_f.png similarity index 100% rename from public/images/cg/end_m.png rename to public/images/cg/end_m_f.png diff --git a/public/images/cg/end_m_m.png b/public/images/cg/end_m_m.png new file mode 100644 index 00000000000..abdcb49aff9 Binary files /dev/null and b/public/images/cg/end_m_m.png differ diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 850d0baab5d..778dc131832 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -59,7 +59,7 @@ import { Biome } from "#enums/biome"; import { ExpNotification } from "#enums/exp-notification"; import { MoneyFormat } from "#enums/money-format"; import { Moves } from "#enums/moves"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Species } from "#enums/species"; import { UiTheme } from "#enums/ui-theme"; import { TimedEventManager } from "#app/timed-event-manager"; @@ -565,7 +565,7 @@ export default class BattleScene extends SceneBase { field.add(a); }); - const trainer = this.addFieldSprite(0, 0, `trainer_${this.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); + const trainer = this.addFieldSprite(0, 0, `trainer_${this.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back`); trainer.setOrigin(0.5, 1); trainer.setName("sprite-trainer"); @@ -1106,7 +1106,7 @@ export default class BattleScene extends SceneBase { this.arena.init(); - this.trainer.setTexture(`trainer_${this.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); + this.trainer.setTexture(`trainer_${this.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back`); this.trainer.setPosition(406, 186); this.trainer.setVisible(true); diff --git a/src/battle.ts b/src/battle.ts index 6086c2ceb4e..1b7c809589f 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -10,7 +10,7 @@ import Pokemon, { EnemyPokemon, PlayerPokemon, QueuedMove } from "#app/field/pok import { ArenaTagType } from "#enums/arena-tag-type"; import { BattleSpec } from "#enums/battle-spec"; import { Moves } from "#enums/moves"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; import i18next from "#app/plugins/i18n"; @@ -524,14 +524,14 @@ export const classicFixedBattles: FixedBattleConfigs = { [5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), [8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) - .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), + .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.rivalGender === CharacterGender.FEMALE ? 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.rivalGender === CharacterGender.FEMALE ? 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, TrainerType.STAR_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.rivalGender === CharacterGender.FEMALE ? 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, TrainerType.STAR_GRUNT ], true)), @@ -540,7 +540,7 @@ 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, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], 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.rivalGender === CharacterGender.FEMALE ? 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, TrainerType.STAR_GRUNT ], true)), @@ -550,7 +550,7 @@ export const classicFixedBattles: FixedBattleConfigs = { .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ])) .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)) + .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === CharacterGender.FEMALE ? 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, TrainerType.PENNY_2 ])) @@ -566,6 +566,6 @@ export const classicFixedBattles: FixedBattleConfigs = { [190]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) .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)) + .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.rivalGender === CharacterGender.FEMALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }) }; diff --git a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts index 549faa01fa1..da8c216044f 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -13,7 +13,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { Species } from "#enums/species"; import i18next from "i18next"; import { getPokemonNameWithAffix } from "#app/messages"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; import { addPokeballOpenParticles } from "#app/field/anims"; import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase"; @@ -177,7 +177,7 @@ async function summonPlayerPokemon(scene: BattleScene) { let playerAnimationPromise: Promise | undefined; scene.ui.showText(i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(playerPokemon) })); scene.pbTray.hide(); - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back_pb`); scene.time.delayedCall(562, () => { scene.trainer.setFrame("2"); scene.time.delayedCall(64, () => { diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index c6b04b7aca6..752b7f17425 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -7,7 +7,7 @@ import { TrainerSlot } from "#app/data/trainer-config"; import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier"; import { EnemyPokemon } from "#app/field/pokemon"; import { PokeballType } from "#app/data/pokeball"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { IntegerHolder, randSeedInt } from "#app/utils"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; @@ -334,7 +334,7 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise { - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back_pb`); scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => { scene.playSound("se/pb_throw"); @@ -343,7 +343,7 @@ async function throwBait(scene: BattleScene, pokemon: EnemyPokemon): Promise { scene.trainer.setFrame("3"); scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[2], () => { - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back`); }); }); @@ -400,7 +400,7 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise { - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back_pb`); scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[0], () => { scene.playSound("se/pb_throw"); @@ -409,7 +409,7 @@ async function throwMud(scene: BattleScene, pokemon: EnemyPokemon): Promise { scene.trainer.setFrame("3"); scene.time.delayedCall(TRAINER_THROW_ANIMATION_TIMES[2], () => { - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back`); }); }); diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index 5fa8af95f4d..510baac6ce8 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -4,7 +4,7 @@ import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { PokemonHeldItemModifier } from "#app/modifier/modifier"; import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "#app/data/pokeball"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { addPokeballCaptureStars, addPokeballOpenParticles } from "#app/field/anims"; import { getStatusEffectCatchRateMultiplier, StatusEffect } from "#app/data/status-effect"; import { achvs } from "#app/system/achv"; @@ -388,7 +388,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon, }); return new Promise(resolve => { - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back_pb`); scene.time.delayedCall(512, () => { scene.playSound("se/pb_throw"); @@ -397,7 +397,7 @@ export function trainerThrowPokeball(scene: BattleScene, pokemon: EnemyPokemon, scene.time.delayedCall(256, () => { scene.trainer.setFrame("3"); scene.time.delayedCall(768, () => { - scene.trainer.setTexture(`trainer_${scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); + scene.trainer.setTexture(`trainer_${scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back`); }); }); diff --git a/src/enums/character-gender.ts b/src/enums/character-gender.ts new file mode 100644 index 00000000000..3eb6e027ec7 --- /dev/null +++ b/src/enums/character-gender.ts @@ -0,0 +1,8 @@ +/** + * enum for changeable character gender (e.g players, rivals) + */ +export enum CharacterGender { + UNSET, + MALE, + FEMALE +} diff --git a/src/enums/player-gender.ts b/src/enums/player-gender.ts deleted file mode 100644 index b6cd550b1f2..00000000000 --- a/src/enums/player-gender.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * enum for the players gender - */ -export enum PlayerGender { - UNSET, - MALE, - FEMALE -} diff --git a/src/loading-scene.ts b/src/loading-scene.ts index d6512486d0e..bd95a650c6b 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -270,8 +270,10 @@ export class LoadingScene extends SceneBase { this.loadImage("egg_list_bg", "ui"); this.loadImage("egg_summary_bg", "ui"); - this.loadImage("end_m", "cg"); - this.loadImage("end_f", "cg"); + this.loadImage("end_f_f", "cg"); + this.loadImage("end_f_m", "cg"); + this.loadImage("end_m_f", "cg"); + this.loadImage("end_m_m", "cg"); for (let i = 0; i < 10; i++) { this.loadAtlas(`pokemon_icons_${i}`, ""); diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 3610ffed386..c3ff37e7314 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -5,7 +5,7 @@ import { getCharVariantFromDialogue } from "#app/data/dialogue"; import { TrainerSlot } from "#app/data/trainer-config"; import { getRandomWeatherType } from "#app/data/weather"; import { BattleSpec } from "#app/enums/battle-spec"; -import { PlayerGender } from "#app/enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Species } from "#app/enums/species"; import { EncounterPhaseEvent } from "#app/events/battle-scene"; import Pokemon, { FieldPosition } from "#app/field/pokemon"; @@ -507,8 +507,8 @@ export class EncounterPhase extends BattlePhase { // The line below checks if an English ordinal is necessary or not based on whether an entry for encounterLocalizationKey exists in the language or not. const ordinalUsed = !i18next.exists(localizationKey, { fallbackLng: []}) || i18next.resolvedLanguage === "en" ? i18next.t("battleSpecDialogue:key", { count: count, ordinal: true }) : ""; const cycleCount = count.toLocaleString() + ordinalUsed; - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const genderStr = CharacterGender[genderIndex].toLowerCase(); const encounterDialogue = i18next.t(localizationKey, { context: genderStr, cycleCount: cycleCount }); if (!this.scene.gameData.getSeenDialogues()[localizationKey]) { this.scene.gameData.saveSeenDialogue(localizationKey); diff --git a/src/phases/end-card-phase.ts b/src/phases/end-card-phase.ts index 274a745017a..07cc1d76813 100644 --- a/src/phases/end-card-phase.ts +++ b/src/phases/end-card-phase.ts @@ -1,5 +1,5 @@ import BattleScene from "#app/battle-scene"; -import { PlayerGender } from "#app/enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Phase } from "#app/phase"; import { addTextObject, TextStyle } from "#app/ui/text"; import i18next from "i18next"; @@ -18,7 +18,7 @@ export class EndCardPhase extends Phase { this.scene.ui.getMessageHandler().bg.setVisible(false); this.scene.ui.getMessageHandler().nameBoxContainer.setVisible(false); - this.endCard = this.scene.add.image(0, 0, `end_${this.scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}`); + this.endCard = this.scene.add.image(0, 0, `end_${this.scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_${this.scene.gameData.rivalGender === CharacterGender.FEMALE ? "f" : "m"}`); this.endCard.setOrigin(0); this.endCard.setScale(0.5); this.scene.field.add(this.endCard); diff --git a/src/phases/game-over-phase.ts b/src/phases/game-over-phase.ts index 9c444fc40f0..85678fa201f 100644 --- a/src/phases/game-over-phase.ts +++ b/src/phases/game-over-phase.ts @@ -20,7 +20,7 @@ import { achvs, ChallengeAchv } from "#app/system/achv"; import { Unlockables } from "#app/system/unlockables"; import { Mode } from "#app/ui/ui"; import * as Utils from "#app/utils"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { TrainerType } from "#enums/trainer-type"; import i18next from "i18next"; @@ -51,8 +51,8 @@ export class GameOverPhase extends BattlePhase { // Otherwise, continue standard Game Over logic if (this.victory && this.scene.gameMode.isEndless) { - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const genderStr = CharacterGender[genderIndex].toLowerCase(); this.scene.ui.showDialogue(i18next.t("miscDialogue:ending_endless", { context: genderStr }), i18next.t("miscDialogue:ending_name"), 0, () => this.handleGameOver()); } else if (this.victory || !this.scene.enableRetries) { this.handleGameOver(); @@ -144,12 +144,12 @@ export class GameOverPhase extends BattlePhase { if (!this.scene.ui.shouldSkipDialogue(dialogueKey)) { this.scene.ui.fadeIn(500).then(() => { - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.rivalGender ?? CharacterGender.UNSET; + const genderStr = CharacterGender[genderIndex].toLowerCase(); // Dialogue has to be retrieved so that the rival's expressions can be loaded and shown via getCharVariantFromDialogue const dialogue = i18next.t(dialogueKey, { context: genderStr }); - this.scene.charSprite.showCharacter(`rival_${this.scene.gameData.gender === PlayerGender.FEMALE ? "m" : "f"}`, getCharVariantFromDialogue(dialogue)).then(() => { - this.scene.ui.showDialogue(dialogueKey, this.scene.gameData.gender === PlayerGender.FEMALE ? trainerConfigs[TrainerType.RIVAL].name : trainerConfigs[TrainerType.RIVAL].nameFemale, null, () => { + this.scene.charSprite.showCharacter(`rival_${this.scene.gameData.gender === CharacterGender.MALE ? "m" : "f"}`, getCharVariantFromDialogue(dialogue)).then(() => { + this.scene.ui.showDialogue(dialogueKey, this.scene.gameData.gender === CharacterGender.MALE ? trainerConfigs[TrainerType.RIVAL].name : trainerConfigs[TrainerType.RIVAL].nameFemale, null, () => { this.scene.ui.fadeOut(500).then(() => { this.scene.charSprite.hide().then(() => { const endCardPhase = new EndCardPhase(this.scene); diff --git a/src/phases/login-phase.ts b/src/phases/login-phase.ts index ac1e68d1b0e..f361727cff2 100644 --- a/src/phases/login-phase.ts +++ b/src/phases/login-phase.ts @@ -6,6 +6,7 @@ import { Mode } from "#app/ui/ui"; import i18next, { t } from "i18next"; import * as Utils from "#app/utils"; import { SelectGenderPhase } from "./select-gender-phase"; +import { SelectRivalGenderPhase } from "./select-rival-gender-phase"; import { UnavailablePhase } from "./unavailable-phase"; export class LoginPhase extends Phase { @@ -111,6 +112,10 @@ export class LoginPhase extends Phase { this.scene.unshiftPhase(new SelectGenderPhase(this.scene)); } + if (!this.scene.gameData.rivalGender) { + this.scene.unshiftPhase(new SelectRivalGenderPhase(this.scene)); + } + handleTutorial(this.scene, Tutorial.Intro).then(() => super.end()); } } diff --git a/src/phases/select-gender-phase.ts b/src/phases/select-gender-phase.ts index 7f2c965f1d1..a52f49f876d 100644 --- a/src/phases/select-gender-phase.ts +++ b/src/phases/select-gender-phase.ts @@ -1,5 +1,5 @@ import BattleScene from "#app/battle-scene"; -import { PlayerGender } from "#app/enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Phase } from "#app/phase"; import { SettingKeys } from "#app/system/settings/settings"; import { Mode } from "#app/ui/ui"; @@ -19,7 +19,7 @@ export class SelectGenderPhase extends Phase { { label: i18next.t("settings:boy"), handler: () => { - this.scene.gameData.gender = PlayerGender.MALE; + this.scene.gameData.gender = CharacterGender.MALE; this.scene.gameData.saveSetting(SettingKeys.Player_Gender, 0); this.scene.gameData.saveSystem().then(() => this.end()); return true; @@ -28,7 +28,7 @@ export class SelectGenderPhase extends Phase { { label: i18next.t("settings:girl"), handler: () => { - this.scene.gameData.gender = PlayerGender.FEMALE; + this.scene.gameData.gender = CharacterGender.FEMALE; this.scene.gameData.saveSetting(SettingKeys.Player_Gender, 1); this.scene.gameData.saveSystem().then(() => this.end()); return true; diff --git a/src/phases/select-rival-gender-phase.ts b/src/phases/select-rival-gender-phase.ts new file mode 100644 index 00000000000..3ce03983b95 --- /dev/null +++ b/src/phases/select-rival-gender-phase.ts @@ -0,0 +1,46 @@ +import BattleScene from "#app/battle-scene"; +import { CharacterGender } from "#app/enums/character-gender"; +import { Phase } from "#app/phase"; +import { SettingKeys } from "#app/system/settings/settings"; +import { Mode } from "#app/ui/ui"; +import i18next from "i18next"; + +export class SelectRivalGenderPhase extends Phase { + constructor(scene: BattleScene) { + super(scene); + } + + start(): void { + super.start(); + + this.scene.ui.showText(i18next.t("menu:rivalBoyOrGirl"), null, () => { + this.scene.ui.setMode(Mode.OPTION_SELECT, { + options: [ + { + label: i18next.t("settings:boy"), + handler: () => { + this.scene.gameData.gender = CharacterGender.MALE; + this.scene.gameData.saveSetting(SettingKeys.Player_Gender, 0); + this.scene.gameData.saveSystem().then(() => this.end()); + return true; + } + }, + { + label: i18next.t("settings:girl"), + handler: () => { + this.scene.gameData.gender = CharacterGender.FEMALE; + this.scene.gameData.saveSetting(SettingKeys.Player_Gender, 1); + this.scene.gameData.saveSystem().then(() => this.end()); + return true; + } + } + ] + }); + }); + } + + end(): void { + this.scene.ui.setMode(Mode.MESSAGE); + super.end(); + } +} diff --git a/src/phases/show-trainer-phase.ts b/src/phases/show-trainer-phase.ts index 26ccddd53fc..0169a7fa1a8 100644 --- a/src/phases/show-trainer-phase.ts +++ b/src/phases/show-trainer-phase.ts @@ -1,5 +1,5 @@ import BattleScene from "#app/battle-scene"; -import { PlayerGender } from "#app/enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { BattlePhase } from "./battle-phase"; export class ShowTrainerPhase extends BattlePhase { @@ -12,7 +12,7 @@ export class ShowTrainerPhase extends BattlePhase { this.scene.trainer.setVisible(true); - this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back`); + this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back`); this.scene.tweens.add({ targets: this.scene.trainer, diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index 119e550293c..dc7fc6a7e40 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -3,7 +3,7 @@ import { BattleType } from "#app/battle"; import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; import { TrainerSlot } from "#app/data/trainer-config"; -import { PlayerGender } from "#app/enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { addPokeballOpenParticles } from "#app/field/anims"; import Pokemon, { FieldPosition } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; @@ -66,7 +66,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { if (this.player) { this.scene.pbTray.hide(); } - this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === PlayerGender.FEMALE ? "f" : "m"}_back_pb`); + this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === CharacterGender.FEMALE ? "f" : "m"}_back_pb`); this.scene.time.delayedCall(562, () => { this.scene.trainer.setFrame("2"); this.scene.time.delayedCall(64, () => { diff --git a/src/system/achv.ts b/src/system/achv.ts index 7329dd41fd5..ea84469844d 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -4,7 +4,7 @@ import { TurnHeldItemTransferModifier } from "../modifier/modifier"; import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import i18next from "i18next"; import * as Utils from "../utils"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Challenge, FreshStartChallenge, SingleGenerationChallenge, SingleTypeChallenge, InverseBattleChallenge } from "#app/data/challenge"; import { ConditionFn } from "#app/@types/common"; import { Stat, getShortenedStatKey } from "#app/enums/stat"; @@ -43,11 +43,11 @@ export class Achv { /** * Get the name of the achievement based on the gender of the player - * @param playerGender - the gender of the player (default: {@linkcode PlayerGender.UNSET}) + * @param playerGender - the gender of the player (default: {@linkcode CharacterGender.UNSET}) * @returns the name of the achievement localized for the player gender */ - getName(playerGender: PlayerGender = PlayerGender.UNSET): string { - const genderStr = PlayerGender[playerGender].toLowerCase(); + getName(playerGender: CharacterGender = CharacterGender.UNSET): string { + const genderStr = CharacterGender[playerGender].toLowerCase(); // Localization key is used to get the name of the achievement return i18next.t(`achv:${this.localizationKey}.name`, { context: genderStr }); } @@ -152,8 +152,8 @@ export class ChallengeAchv extends Achv { */ export function getAchievementDescription(localizationKey: string): string { // We need to get the player gender from the game data to add the correct prefix to the achievement name - const genderIndex = this?.scene?.gameData?.gender ?? PlayerGender.MALE; //TODO: why is `this` being used here!? We are not inside a scope (copied from original) - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this?.scene?.gameData?.gender ?? CharacterGender.MALE; //TODO: why is `this` being used here!? We are not inside a scope (copied from original) + const genderStr = CharacterGender[genderIndex].toLowerCase(); switch (localizationKey) { case "10K_MONEY": diff --git a/src/system/game-data.ts b/src/system/game-data.ts index b162962fac6..06394eb843e 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -38,7 +38,7 @@ import ChallengeData from "#app/system/challenge-data"; import { Device } from "#enums/devices"; import { GameDataType } from "#enums/game-data-type"; import { Moves } from "#enums/moves"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Species } from "#enums/species"; import { applyChallenges, ChallengeType } from "#app/data/challenge"; import { WeatherType } from "#enums/weather-type"; @@ -102,7 +102,8 @@ export function decrypt(data: string, bypassLogin: boolean): string { export interface SystemSaveData { trainerId: integer; secretId: integer; - gender: PlayerGender; + gender: CharacterGender; + rivalGender: CharacterGender; dexData: DexData; starterData: StarterData; gameStats: GameStats; @@ -304,7 +305,8 @@ export class GameData { public trainerId: integer; public secretId: integer; - public gender: PlayerGender; + public gender: CharacterGender; + public rivalGender: CharacterGender; public dexData: DexData; private defaultDexData: DexData | null; @@ -360,6 +362,7 @@ export class GameData { trainerId: this.trainerId, secretId: this.secretId, gender: this.gender, + rivalGender: this.rivalGender, dexData: this.dexData, starterData: this.starterData, gameStats: this.gameStats, @@ -488,8 +491,10 @@ export class GameData { this.secretId = systemData.secretId; this.gender = systemData.gender; + this.rivalGender = systemData.rivalGender; - this.saveSetting(SettingKeys.Player_Gender, systemData.gender === PlayerGender.FEMALE ? 1 : 0); + this.saveSetting(SettingKeys.Player_Gender, systemData.gender === CharacterGender.FEMALE ? 1 : 0); + this.saveSetting(SettingKeys.Rival_Gender, systemData.rivalGender === CharacterGender.FEMALE ? 1 : 0); if (!systemData.starterData) { this.initStarterData(); diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 66021845c29..3bcfc688b24 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -7,7 +7,7 @@ import { CandyUpgradeNotificationChangedEvent } from "../../events/battle-scene" import SettingsUiHandler from "#app/ui/settings/settings-ui-handler"; import { EaseType } from "#enums/ease-type"; import { MoneyFormat } from "#enums/money-format"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { getIsInitialized, initI18n } from "#app/plugins/i18n"; import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; @@ -151,6 +151,7 @@ export const SettingKeys = { Sprite_Set: "SPRITE_SET", Fusion_Palette_Swaps: "FUSION_PALETTE_SWAPS", Player_Gender: "PLAYER_GENDER", + Rival_Gender: "RIVAL_GENDER", Type_Hints: "TYPE_HINTS", Master_Volume: "MASTER_VOLUME", BGM_Volume: "BGM_VOLUME", @@ -572,6 +573,22 @@ export const Setting: Array = [ default: 0, type: SettingType.DISPLAY }, + { + key: SettingKeys.Rival_Gender, + label: i18next.t("settings:rivalGender"), + options: [ + { + value: "Boy", + label: i18next.t("settings:boy") + }, + { + value: "Girl", + label: i18next.t("settings:girl") + } + ], + default: 1, + type: SettingType.DISPLAY + }, { key: SettingKeys.Type_Hints, label: i18next.t("settings:typeHints"), @@ -820,12 +837,20 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): case SettingKeys.Player_Gender: if (scene.gameData) { const female = Setting[index].options[value].value === "Girl"; - scene.gameData.gender = female ? PlayerGender.FEMALE : PlayerGender.MALE; + scene.gameData.gender = female ? CharacterGender.FEMALE : CharacterGender.MALE; scene.trainer.setTexture(scene.trainer.texture.key.replace(female ? "m" : "f", female ? "f" : "m")); } else { return false; } break; + case SettingKeys.Rival_Gender: + if (scene.gameData) { + const female = Setting[index].options[value].value === "Girl"; + scene.gameData.rivalGender = female ? CharacterGender.FEMALE : CharacterGender.MALE; + } else { + return false; + } + break; case SettingKeys.Touch_Controls: scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); const touchControls = document.getElementById("touchControls"); diff --git a/src/system/voucher.ts b/src/system/voucher.ts index aca7b9fc2f2..74b3ef30a0a 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -1,7 +1,7 @@ import BattleScene from "../battle-scene"; import i18next from "i18next"; import { AchvTier, achvs, getAchievementDescription } from "./achv"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { TrainerType } from "#enums/trainer-type"; import { ConditionFn } from "#app/@types/common"; import { trainerConfigs } from "#app/data/trainer-config"; @@ -35,7 +35,7 @@ export class Voucher { * @param playerGender - this is ignored here. It's only there to match the signature of the function in the Achv class * @returns the name of the voucher */ - getName(playerGender: PlayerGender): string { + getName(playerGender: CharacterGender): string { return getVoucherTypeName(this.voucherType); } diff --git a/src/test/battle/battle.test.ts b/src/test/battle/battle.test.ts index eed76397f85..46b71204613 100644 --- a/src/test/battle/battle.test.ts +++ b/src/test/battle/battle.test.ts @@ -21,7 +21,7 @@ import { generateStarter } from "#app/test/utils/gameManagerUtils"; import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Species } from "#enums/species"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -50,7 +50,7 @@ describe("Test Battle Phase", () => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; + game.scene.gameData.gender = CharacterGender.MALE; game.endPhase(); }); @@ -61,14 +61,14 @@ describe("Test Battle Phase", () => { expect(game.scene.ui?.getMode()).toBe(Mode.TITLE); - expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); + expect(game.scene.gameData.gender).toBe(CharacterGender.MALE); }, 20000); it("test phase interceptor with prompt with preparation for a future prompt", async () => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; + game.scene.gameData.gender = CharacterGender.MALE; game.endPhase(); }); @@ -83,7 +83,7 @@ describe("Test Battle Phase", () => { expect(game.scene.ui?.getMode()).toBe(Mode.TITLE); - expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); + expect(game.scene.gameData.gender).toBe(CharacterGender.MALE); }, 20000); it("newGame one-liner", async () => { @@ -163,7 +163,7 @@ describe("Test Battle Phase", () => { it("good run", async () => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; + game.scene.gameData.gender = CharacterGender.MALE; game.endPhase(); }, () => game.isCurrentPhase(TitlePhase)); await game.phaseInterceptor.run(SelectGenderPhase, () => game.isCurrentPhase(TitlePhase)); @@ -173,7 +173,7 @@ describe("Test Battle Phase", () => { it("good run from select gender to title", async () => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; + game.scene.gameData.gender = CharacterGender.MALE; game.endPhase(); }, () => game.isCurrentPhase(TitlePhase)); await game.phaseInterceptor.runFrom(SelectGenderPhase).to(TitlePhase); @@ -182,7 +182,7 @@ describe("Test Battle Phase", () => { it("good run to SummonPhase phase", async () => { await game.phaseInterceptor.run(LoginPhase); game.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; + game.scene.gameData.gender = CharacterGender.MALE; game.endPhase(); }, () => game.isCurrentPhase(TitlePhase)); game.onNextPrompt("TitlePhase", Mode.TITLE, () => { diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index 86c51972c8b..9de7b03db0e 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -31,7 +31,7 @@ import TargetSelectUiHandler from "#app/ui/target-select-ui-handler"; import { Mode } from "#app/ui/ui"; import { Button } from "#enums/buttons"; import { ExpNotification } from "#enums/exp-notification"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Species } from "#enums/species"; import { generateStarter, waitUntil } from "#test/utils/gameManagerUtils"; import GameWrapper from "#test/utils/gameWrapper"; @@ -155,7 +155,8 @@ export default class GameManager { this.scene.expParty = ExpNotification.SKIP; this.scene.hpBarSpeed = 3; this.scene.enableTutorials = false; - this.scene.gameData.gender = PlayerGender.MALE; // set initial player gender + this.scene.gameData.gender = CharacterGender.MALE; // set initial player gender + this.scene.gameData.rivalGender = CharacterGender.FEMALE; // set initial rival gender this.scene.battleStyle = this.settings.battleStyle; } diff --git a/src/test/utils/helpers/settingsHelper.ts b/src/test/utils/helpers/settingsHelper.ts index 83baa329cec..c20e65ef943 100644 --- a/src/test/utils/helpers/settingsHelper.ts +++ b/src/test/utils/helpers/settingsHelper.ts @@ -1,4 +1,4 @@ -import { PlayerGender } from "#app/enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { BattleStyle } from "#app/enums/battle-style"; import { GameManagerHelper } from "./gameManagerHelper"; import { ExpGainsSpeed } from "#app/enums/exp-gains-speed"; @@ -32,13 +32,23 @@ export class SettingsHelper extends GameManagerHelper { /** * Change the player gender - * @param gender the {@linkcode PlayerGender} to set + * @param gender the {@linkcode CharacterGender} to set */ - playerGender(gender: PlayerGender) { + playerGender(gender: CharacterGender) { this.game.scene.gameData.gender = gender; - this.log(`Gender set to: ${PlayerGender[gender]} (=${gender})` ); + this.log(`Player Gender set to: ${CharacterGender[gender]} (=${gender})` ); } + /** + * Change the rival gender + * @param gender the {@linkcode CharacterGender} to set + */ + rivalGender(gender: CharacterGender) { + this.game.scene.gameData.rivalGender = gender; + this.log(`Rival Gender set to: ${CharacterGender[gender]} (=${gender})` ); + } + + /** * Change the exp gains speed * @param speed the {@linkcode ExpGainsSpeed} to set diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts index ec9309e2405..142f70b17ad 100644 --- a/src/test/utils/phaseInterceptor.ts +++ b/src/test/utils/phaseInterceptor.ts @@ -25,6 +25,7 @@ import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; import { PostSummonPhase } from "#app/phases/post-summon-phase"; import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; import { SelectGenderPhase } from "#app/phases/select-gender-phase"; +import { SelectRivalGenderPhase } from "#app/phases/select-rival-gender-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { SelectStarterPhase } from "#app/phases/select-starter-phase"; import { SelectTargetPhase } from "#app/phases/select-target-phase"; @@ -67,6 +68,7 @@ type PhaseClass = | typeof LoginPhase | typeof TitlePhase | typeof SelectGenderPhase + | typeof SelectRivalGenderPhase | typeof EncounterPhase | typeof NewBiomeEncounterPhase | typeof SelectStarterPhase @@ -120,6 +122,7 @@ type PhaseString = | "LoginPhase" | "TitlePhase" | "SelectGenderPhase" + | "SelectRivalGenderPhase" | "EncounterPhase" | "NewBiomeEncounterPhase" | "SelectStarterPhase" @@ -192,6 +195,7 @@ export default class PhaseInterceptor { [ LoginPhase, this.startPhase ], [ TitlePhase, this.startPhase ], [ SelectGenderPhase, this.startPhase ], + [ SelectRivalGenderPhase, this.startPhase ], [ EncounterPhase, this.startPhase ], [ NewBiomeEncounterPhase, this.startPhase ], [ SelectStarterPhase, this.startPhase ], @@ -243,7 +247,7 @@ export default class PhaseInterceptor { ]; private endBySetMode = [ - TitlePhase, SelectGenderPhase, CommandPhase, SelectModifierPhase, MysteryEncounterPhase, PostMysteryEncounterPhase + TitlePhase, SelectGenderPhase, SelectRivalGenderPhase, CommandPhase, SelectModifierPhase, MysteryEncounterPhase, PostMysteryEncounterPhase ]; /** diff --git a/src/ui/achv-bar.ts b/src/ui/achv-bar.ts index 6e7b3185024..eabb7e3230f 100644 --- a/src/ui/achv-bar.ts +++ b/src/ui/achv-bar.ts @@ -2,7 +2,7 @@ import BattleScene from "../battle-scene"; import { Achv, getAchievementDescription } from "../system/achv"; import { Voucher } from "../system/voucher"; import { TextStyle, addTextObject } from "./text"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; export default class AchvBar extends Phaser.GameObjects.Container { private defaultWidth: number; @@ -15,7 +15,7 @@ export default class AchvBar extends Phaser.GameObjects.Container { private descriptionText: Phaser.GameObjects.Text; private queue: (Achv | Voucher)[] = []; - private playerGender: PlayerGender; + private playerGender: CharacterGender; public shown: boolean; @@ -105,7 +105,7 @@ export default class AchvBar extends Phaser.GameObjects.Container { this.shown = true; } - protected hide(playerGender: PlayerGender): void { + protected hide(playerGender: CharacterGender): void { if (!this.shown) { return; } diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index 4e0e2feea81..945e56be1f7 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -8,7 +8,7 @@ import { addTextObject, TextStyle } from "#app/ui/text"; import { Mode } from "#app/ui/ui"; import { addWindow } from "#app/ui/ui-theme"; import { ScrollBar } from "#app/ui/scroll-bar"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; enum Page { ACHIEVEMENTS, @@ -86,8 +86,8 @@ export default class AchvsUiHandler extends MessageUiHandler { this.headerActionText.setPositionRelative(this.headerBg, 264, 8); // We need to get the player gender from the game data to add the correct prefix to the achievement name - const genderIndex = this.scene.gameData.gender ?? PlayerGender.MALE; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.MALE; + const genderStr = CharacterGender[genderIndex].toLowerCase(); this.achvsName = i18next.t("achv:Achievements.name", { context: genderStr }); this.vouchersName = i18next.t("voucher:vouchers"); @@ -195,8 +195,8 @@ export default class AchvsUiHandler extends MessageUiHandler { protected showAchv(achv: Achv) { // We need to get the player gender from the game data to add the correct prefix to the achievement name - const genderIndex = this.scene.gameData.gender ?? PlayerGender.MALE; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.MALE; + const genderStr = CharacterGender[genderIndex].toLowerCase(); achv.name = i18next.t(`achv:${achv.localizationKey}.name`, { context: genderStr }); achv.description = getAchievementDescription(achv.localizationKey); diff --git a/src/ui/run-history-ui-handler.ts b/src/ui/run-history-ui-handler.ts index 20de7fd832c..dd53ad653dc 100644 --- a/src/ui/run-history-ui-handler.ts +++ b/src/ui/run-history-ui-handler.ts @@ -10,7 +10,7 @@ import i18next from "i18next"; import { Button } from "../enums/buttons"; import { BattleType } from "../battle"; import { RunEntry } from "../system/game-data"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { TrainerVariant } from "../field/trainer"; import { RunDisplayMode } from "#app/ui/run-info-ui-handler"; @@ -288,8 +288,8 @@ class RunEntryContainer extends Phaser.GameObjects.Container { const gameOutcomeLabel = addTextObject(this.scene, 8, 5, `${i18next.t("runHistory:victory")}`, TextStyle.WINDOW); this.add(gameOutcomeLabel); } else { // Run Result: Defeats - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const genderStr = CharacterGender[genderIndex].toLowerCase(); // Defeats from wild Pokemon battles will show the Pokemon responsible by the text of the run result. if (data.battleType === BattleType.WILD || (data.battleType === BattleType.MYSTERY_ENCOUNTER && !data.trainer)) { const enemyContainer = this.scene.add.container(8, 5); diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index 39927f8e071..42c5e26b084 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -21,7 +21,7 @@ import { getNatureStatMultiplier, getNatureName } from "../data/nature"; import { getVariantTint } from "#app/data/variant"; import * as Modifier from "../modifier/modifier"; import { Species } from "#enums/species"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; import { getBiomeName } from "#app/data/balance/biomes"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; @@ -194,8 +194,8 @@ export default class RunInfoUiHandler extends UiHandler { * */ private async parseRunResult() { - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex]; + const genderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const genderStr = CharacterGender[genderIndex]; const runResultTextStyle = this.isVictory ? TextStyle.PERFECT_IV : TextStyle.SUMMARY_RED; const runResultTitle = this.isVictory ? i18next.t("runHistory:victory") : i18next.t("runHistory:defeated", { context: genderStr }); const runResultText = addTextObject(this.scene, 6, 5, `${runResultTitle} - ${i18next.t("saveSlotSelectUiHandler:wave")} ${this.runInfo.waveIndex}`, runResultTextStyle, { fontSize : "65px", lineSpacing: 0.1 }); @@ -823,9 +823,9 @@ export default class RunInfoUiHandler extends UiHandler { */ private createVictorySplash(): void { this.endCardContainer = this.scene.add.container(0, 0); - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const isFemale = genderIndex === PlayerGender.FEMALE; - const endCard = this.scene.add.image(0, 0, `end_${isFemale ? "f" : "m"}`); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const rivalGenderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const endCard = this.scene.add.image(0, 0, `end_${genderIndex === CharacterGender.FEMALE ? "f" : "m"}_${rivalGenderIndex === CharacterGender.FEMALE ? "f" : "m"}`); endCard.setOrigin(0); endCard.setScale(0.5); const text = addTextObject(this.scene, this.scene.game.canvas.width / 12, (this.scene.game.canvas.height / 6) - 16, i18next.t("battle:congratulations"), TextStyle.SUMMARY, { fontSize: "128px" }); @@ -839,9 +839,9 @@ export default class RunInfoUiHandler extends UiHandler { * This could be adapted into a public-facing method for victory screens. Perhaps. */ private createHallofFame(): void { - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const isFemale = genderIndex === PlayerGender.FEMALE; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = this.scene.gameData.gender ?? CharacterGender.UNSET; + const isFemale = genderIndex === CharacterGender.FEMALE; + const genderStr = CharacterGender[genderIndex].toLowerCase(); // Issue Note (08-05-2024): It seems as if fused pokemon do not appear with the averaged color b/c pokemonData's loadAsset requires there to be some active battle? // As an alternative, the icons of the second/bottom fused Pokemon have been placed next to their fellow fused Pokemon in Hall of Fame this.hallofFameContainer = this.scene.add.container(0, 0); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index 86b00f512a9..579a2555961 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -21,7 +21,7 @@ import { Button } from "#enums/buttons"; import { Ability } from "#app/data/ability"; import i18next from "i18next"; import { modifierSortFunc } from "#app/modifier/modifier"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import { Stat, PERMANENT_STATS, getStatKey } from "#enums/stat"; enum Page { @@ -735,7 +735,7 @@ export default class SummaryUiHandler extends UiHandler { pageContainer.add(profileContainer); // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs - const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT); + const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === CharacterGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT); trainerText.setOrigin(0, 0); profileContainer.add(trainerText); diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 373930c5d84..d5492b2934a 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -43,7 +43,7 @@ import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-han import KeyboardBindingUiHandler from "#app/ui/settings/keyboard-binding-ui-handler"; import SettingsDisplayUiHandler from "./settings/settings-display-ui-handler"; import SettingsAudioUiHandler from "./settings/settings-audio-ui-handler"; -import { PlayerGender } from "#enums/player-gender"; +import { CharacterGender } from "#app/enums/character-gender"; import BgmBar from "#app/ui/bgm-bar"; import RenameFormUiHandler from "./rename-form-ui-handler"; import AdminUiHandler from "./admin-ui-handler"; @@ -326,8 +326,8 @@ export default class UI extends Phaser.GameObjects.Container { // Get localized dialogue (if available) let hasi18n = false; let text = keyOrText; - const genderIndex = battleScene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex].toLowerCase(); + const genderIndex = battleScene.gameData.gender ?? CharacterGender.UNSET; + const genderStr = CharacterGender[genderIndex].toLowerCase(); if (i18next.exists(keyOrText) ) { const i18nKey = keyOrText;