mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-04 08:58:30 +01:00
236 lines
8.0 KiB
TypeScript
236 lines
8.0 KiB
TypeScript
import { globalScene } from "#app/global-scene";
|
|
import BattleFlyout from "../battle-flyout";
|
|
import { addTextObject, TextStyle } from "#app/ui/text";
|
|
import { addWindow, WindowVariant } from "#app/ui/ui-theme";
|
|
import { Stat } from "#enums/stat";
|
|
import i18next from "i18next";
|
|
import type { EnemyPokemon } from "#app/field/pokemon";
|
|
import type { GameObjects } from "phaser";
|
|
import BattleInfo from "./battle-info";
|
|
import type { BattleInfoParamList } from "./battle-info";
|
|
|
|
export class EnemyBattleInfo extends BattleInfo {
|
|
protected player: false = false;
|
|
protected championRibbon: Phaser.GameObjects.Sprite;
|
|
protected ownedIcon: Phaser.GameObjects.Sprite;
|
|
protected flyoutMenu: BattleFlyout;
|
|
|
|
protected hpBarSegmentDividers: GameObjects.Rectangle[] = [];
|
|
|
|
// #region Type effectiveness hint objects
|
|
protected effectivenessContainer: Phaser.GameObjects.Container;
|
|
protected effectivenessWindow: Phaser.GameObjects.NineSlice;
|
|
protected effectivenessText: Phaser.GameObjects.Text;
|
|
protected currentEffectiveness?: string;
|
|
// #endregion
|
|
|
|
override get statOrder(): Stat[] {
|
|
return [Stat.HP, Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.ACC, Stat.EVA, Stat.SPD];
|
|
}
|
|
|
|
override getTextureName(): string {
|
|
return this.boss ? "pbinfo_enemy_boss" : "pbinfo_enemy_mini";
|
|
}
|
|
|
|
override constructTypeIcons(): void {
|
|
this.type1Icon = globalScene.add.sprite(-15, -15.5, "pbinfo_enemy_type1").setName("icon_type_1").setOrigin(0);
|
|
this.type2Icon = globalScene.add.sprite(-15, -2.5, "pbinfo_enemy_type2").setName("icon_type_2").setOrigin(0);
|
|
this.type3Icon = globalScene.add.sprite(0, 15.5, "pbinfo_enemy_type3").setName("icon_type_3").setOrigin(0);
|
|
this.add([this.type1Icon, this.type2Icon, this.type3Icon]);
|
|
}
|
|
|
|
constructor() {
|
|
const posParams: BattleInfoParamList = {
|
|
nameTextX: -124,
|
|
nameTextY: -11.2,
|
|
levelContainerX: -50,
|
|
levelContainerY: -5,
|
|
hpBarX: -71,
|
|
hpBarY: 4.5,
|
|
statBox: {
|
|
xOffset: 5,
|
|
paddingX: 2,
|
|
statOverflow: 0,
|
|
},
|
|
};
|
|
|
|
super(140, -141, false, posParams);
|
|
|
|
this.ownedIcon = globalScene.add
|
|
.sprite(0, 0, "icon_owned")
|
|
.setName("icon_owned")
|
|
.setVisible(false)
|
|
.setOrigin(0, 0)
|
|
.setPositionRelative(this.nameText, 0, 11.75);
|
|
|
|
this.championRibbon = globalScene.add
|
|
.sprite(0, 0, "champion_ribbon")
|
|
.setName("icon_champion_ribbon")
|
|
.setVisible(false)
|
|
.setOrigin(0, 0)
|
|
.setPositionRelative(this.nameText, 8, 11.75);
|
|
// Ensure these two icons are positioned below the stats container
|
|
this.addAt([this.ownedIcon, this.championRibbon], this.getIndex(this.statsContainer));
|
|
|
|
this.flyoutMenu = new BattleFlyout(this.player);
|
|
this.add(this.flyoutMenu);
|
|
|
|
this.moveBelow<Phaser.GameObjects.GameObject>(this.flyoutMenu, this.box);
|
|
|
|
this.effectivenessContainer = globalScene.add
|
|
.container(0, 0)
|
|
.setVisible(false)
|
|
.setPositionRelative(this.type1Icon, 22, 4);
|
|
this.add(this.effectivenessContainer);
|
|
|
|
this.effectivenessText = addTextObject(5, 4.5, "", TextStyle.BATTLE_INFO);
|
|
this.effectivenessWindow = addWindow(0, 0, 0, 20, undefined, false, undefined, undefined, WindowVariant.XTHIN);
|
|
|
|
this.effectivenessContainer.add([this.effectivenessWindow, this.effectivenessText]);
|
|
}
|
|
|
|
override initInfo(pokemon: EnemyPokemon): void {
|
|
this.flyoutMenu.initInfo(pokemon);
|
|
super.initInfo(pokemon);
|
|
|
|
if (this.nameText.visible) {
|
|
this.nameText
|
|
.on("pointerover", () =>
|
|
globalScene.ui.showTooltip(
|
|
"",
|
|
i18next.t("battleInfo:generation", {
|
|
generation: i18next.t(`starterSelectUiHandler:gen${pokemon.species.generation}`),
|
|
}),
|
|
),
|
|
)
|
|
.on("pointerout", () => globalScene.ui.hideTooltip());
|
|
}
|
|
|
|
const dexEntry = globalScene.gameData.dexData[pokemon.species.speciesId];
|
|
this.ownedIcon.setVisible(!!dexEntry.caughtAttr);
|
|
const opponentPokemonDexAttr = pokemon.getDexAttr();
|
|
if (
|
|
globalScene.gameMode.isClassic &&
|
|
globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].classicWinCount > 0 &&
|
|
globalScene.gameData.starterData[pokemon.species.getRootSpeciesId(true)].classicWinCount > 0
|
|
) {
|
|
this.championRibbon.setVisible(true);
|
|
}
|
|
|
|
// Check if Player owns all genders and forms of the Pokemon
|
|
const missingDexAttrs = (dexEntry.caughtAttr & opponentPokemonDexAttr) < opponentPokemonDexAttr;
|
|
|
|
const ownedAbilityAttrs = globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].abilityAttr;
|
|
|
|
// Check if the player owns ability for the root form
|
|
const playerOwnsThisAbility = pokemon.checkIfPlayerHasAbilityOfStarter(ownedAbilityAttrs);
|
|
|
|
if (missingDexAttrs || !playerOwnsThisAbility) {
|
|
this.ownedIcon.setTint(0x808080);
|
|
}
|
|
|
|
if (this.boss) {
|
|
this.updateBossSegmentDividers(pokemon as EnemyPokemon);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Show or hide the type effectiveness multiplier window
|
|
* Passing undefined will hide the window
|
|
*/
|
|
updateEffectiveness(effectiveness?: string) {
|
|
this.currentEffectiveness = effectiveness;
|
|
|
|
if (!globalScene.typeHints || effectiveness === undefined || this.flyoutMenu.flyoutVisible) {
|
|
this.effectivenessContainer.setVisible(false);
|
|
return;
|
|
}
|
|
|
|
this.effectivenessText.setText(effectiveness);
|
|
this.effectivenessWindow.width = 10 + this.effectivenessText.displayWidth;
|
|
this.effectivenessContainer.setVisible(true);
|
|
}
|
|
|
|
/**
|
|
* Request the flyoutMenu to toggle if available and hides or shows the effectiveness window where necessary
|
|
*/
|
|
toggleFlyout(visible: boolean): void {
|
|
this.flyoutMenu.toggleFlyout(visible);
|
|
|
|
if (visible) {
|
|
this.effectivenessContainer.setVisible(false);
|
|
} else {
|
|
this.updateEffectiveness(this.currentEffectiveness);
|
|
}
|
|
}
|
|
|
|
updateBossSegments(pokemon: EnemyPokemon): void {
|
|
const boss = !!pokemon.bossSegments;
|
|
|
|
if (boss !== this.boss) {
|
|
this.boss = boss;
|
|
|
|
[
|
|
this.nameText,
|
|
this.genderText,
|
|
this.teraIcon,
|
|
this.splicedIcon,
|
|
this.shinyIcon,
|
|
this.ownedIcon,
|
|
this.championRibbon,
|
|
this.statusIndicator,
|
|
this.levelContainer,
|
|
this.statValuesContainer,
|
|
].map(e => (e.x += 48 * (boss ? -1 : 1)));
|
|
this.hpBar.x += 38 * (boss ? -1 : 1);
|
|
this.hpBar.y += 2 * (this.boss ? -1 : 1);
|
|
this.hpBar.setTexture(`overlay_hp${boss ? "_boss" : ""}`);
|
|
this.box.setTexture(this.getTextureName());
|
|
this.statsBox.setTexture(`${this.getTextureName()}_stats`);
|
|
}
|
|
|
|
this.bossSegments = boss ? pokemon.bossSegments : 0;
|
|
this.updateBossSegmentDividers(pokemon);
|
|
}
|
|
|
|
updateBossSegmentDividers(pokemon: EnemyPokemon): void {
|
|
while (this.hpBarSegmentDividers.length) {
|
|
this.hpBarSegmentDividers.pop()?.destroy();
|
|
}
|
|
|
|
if (this.boss && this.bossSegments > 1) {
|
|
const uiTheme = globalScene.uiTheme;
|
|
const maxHp = pokemon.getMaxHp();
|
|
for (let s = 1; s < this.bossSegments; s++) {
|
|
const dividerX = (Math.round((maxHp / this.bossSegments) * s) / maxHp) * this.hpBar.width;
|
|
const divider = globalScene.add.rectangle(
|
|
0,
|
|
0,
|
|
1,
|
|
this.hpBar.height - (uiTheme ? 0 : 1),
|
|
pokemon.bossSegmentIndex >= s ? 0xffffff : 0x404040,
|
|
);
|
|
divider.setOrigin(0.5, 0).setName("hpBar_divider_" + s.toString());
|
|
this.add(divider);
|
|
this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer);
|
|
|
|
divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1);
|
|
this.hpBarSegmentDividers.push(divider);
|
|
}
|
|
}
|
|
}
|
|
|
|
override updateStatusIcon(pokemon: EnemyPokemon): void {
|
|
super.updateStatusIcon(pokemon, (this.ownedIcon.visible ? 8 : 0) + (this.championRibbon.visible ? 8 : 0));
|
|
}
|
|
|
|
protected override updatePokemonHp(
|
|
pokemon: EnemyPokemon,
|
|
resolve: (r: void | PromiseLike<void>) => void,
|
|
instant?: boolean,
|
|
): void {
|
|
super.updatePokemonHp(pokemon, resolve, instant);
|
|
this.lastHp = pokemon.hp;
|
|
}
|
|
}
|