From b32b802ab45fe08cc5756354a17526bb26ca13c9 Mon Sep 17 00:00:00 2001 From: Greenlamp2 <44787002+Greenlamp2@users.noreply.github.com> Date: Fri, 10 May 2024 15:54:14 +0200 Subject: [PATCH 1/6] QOL - Settings to choose party Exp display at the end of fight (#488) * added settings to manage how to display party experience at the end of fight * added back stats changes support when setting is on but ignored when on skip * removed a useless parameter * added new level in the text * only Lv. UP if level is greated than 200 * cleanup * added some comment * TSDoc comment block * EXP_Party -> EXP_Party_Display, Only Up -> Level Up Notification * better duration for the level up notification * typo Co-authored-by: Samuel H --------- Co-authored-by: Samuel H --- src/battle-scene.ts | 13 +++++++++++++ src/phases.ts | 31 ++++++++++++++++++++++++------- src/system/settings.ts | 6 ++++++ src/ui/party-exp-bar.ts | 14 ++++++++++++-- 4 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 28a09a24d..9a51950a5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -101,6 +101,19 @@ export default class BattleScene extends SceneBase { public experimentalSprites: boolean = false; public moveAnimations: boolean = true; public expGainsSpeed: integer = 0; + /** + * Defines the experience gain display mode. + * + * @remarks + * The `expParty` can have several modes: + * - `0` - Default: The normal experience gain display, nothing changed. + * - `1` - Level Up Notification: Displays the level up in the small frame instead of a message. + * - `2` - Skip: No level up frame nor message. + * + * Modes `1` and `2` are still compatible with stats display, level up, new move, etc. + * @default 0 - Uses the default normal experience gain display. + */ + public expParty: integer = 0; public hpBarSpeed: integer = 0; public fusionPaletteSwaps: boolean = true; public enableTouchControls: boolean = false; diff --git a/src/phases.ts b/src/phases.ts index e2532c1c0..b697f7acb 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -3745,11 +3745,20 @@ export class ShowPartyExpBarPhase extends PlayerPartyMemberPokemonPhase { this.scene.unshiftPhase(new HidePartyExpBarPhase(this.scene)); pokemon.updateInfo(); - if (this.scene.expGainsSpeed < 3) { - this.scene.partyExpBar.showPokemonExp(pokemon, exp.value).then(() => { - if (newLevel > lastLevel) - this.end(); - else + if (this.scene.expParty === 2) { // 2 - Skip - no level up frame nor message + this.end(); + } else if (this.scene.expParty === 1) { // 1 - Only level up - we display the level up in the small frame instead of a message + if (newLevel > lastLevel) { // this means if we level up + // instead of displaying the exp gain in the small frame, we display the new level + // we use the same method for mode 0 & 1, by giving a parameter saying to display the exp or the level + this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, this.scene.expParty === 1, newLevel).then(() => { + setTimeout(() => this.end(), 800 / Math.pow(2, this.scene.expGainsSpeed/2)); + }); + } else { + this.end(); + } + } else if (this.scene.expGainsSpeed < 3) { + this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, this.scene.expParty === 1, newLevel).then(() => { setTimeout(() => this.end(), 500 / Math.pow(2, this.scene.expGainsSpeed)); }); } else { @@ -3780,6 +3789,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { this.lastLevel = lastLevel; this.level = level; + this.scene = scene; } start() { @@ -3794,8 +3804,15 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { const prevStats = pokemon.stats.slice(0); pokemon.calculateStats(); pokemon.updateInfo(); - this.scene.playSound('level_up_fanfare'); - this.scene.ui.showText(i18next.t('battle:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); + if (this.scene.expParty === 0) { // 0 - default - the normal exp gain display, nothing changed + this.scene.playSound('level_up_fanfare'); + this.scene.ui.showText(i18next.t('battle:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); + } else if (this.scene.expParty === 2) { // 2 - Skip - no level up frame nor message + this.end(); + } else { // 1 - Only level up - we display the level up in the small frame instead of a message + // we still want to display the stats if activated + this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()); + } if (this.level <= 100) { const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1); for (let lm of levelMoves) diff --git a/src/system/settings.ts b/src/system/settings.ts index 680fadb1e..4b2c9eda1 100644 --- a/src/system/settings.ts +++ b/src/system/settings.ts @@ -21,6 +21,7 @@ export enum Setting { Move_Animations = "MOVE_ANIMATIONS", Show_Stats_on_Level_Up = "SHOW_LEVEL_UP_STATS", EXP_Gains_Speed = "EXP_GAINS_SPEED", + EXP_Party_Display = "EXP_PARTY_DISPLAY", HP_Bar_Speed = "HP_BAR_SPEED", Fusion_Palette_Swaps = "FUSION_PALETTE_SWAPS", Player_Gender = "PLAYER_GENDER", @@ -53,6 +54,7 @@ export const settingOptions: SettingOptions = { [Setting.Move_Animations]: [ 'Off', 'On' ], [Setting.Show_Stats_on_Level_Up]: [ 'Off', 'On' ], [Setting.EXP_Gains_Speed]: [ 'Normal', 'Fast', 'Faster', 'Skip' ], + [Setting.EXP_Party_Display]: [ 'Normal', 'Level Up Notification', 'Skip' ], [Setting.HP_Bar_Speed]: [ 'Normal', 'Fast', 'Faster', 'Instant' ], [Setting.Fusion_Palette_Swaps]: [ 'Off', 'On' ], [Setting.Player_Gender]: [ 'Boy', 'Girl' ], @@ -77,6 +79,7 @@ export const settingDefaults: SettingDefaults = { [Setting.Move_Animations]: 1, [Setting.Show_Stats_on_Level_Up]: 1, [Setting.EXP_Gains_Speed]: 0, + [Setting.EXP_Party_Display]: 0, [Setting.HP_Bar_Speed]: 0, [Setting.Fusion_Palette_Swaps]: 1, [Setting.Player_Gender]: 0, @@ -134,6 +137,9 @@ export function setSetting(scene: BattleScene, setting: Setting, value: integer) case Setting.EXP_Gains_Speed: scene.expGainsSpeed = value; break; + case Setting.EXP_Party_Display: + scene.expParty = value; + break; case Setting.HP_Bar_Speed: scene.hpBarSpeed = value; break; diff --git a/src/ui/party-exp-bar.ts b/src/ui/party-exp-bar.ts index a5451c5f2..93c69ce2c 100644 --- a/src/ui/party-exp-bar.ts +++ b/src/ui/party-exp-bar.ts @@ -29,7 +29,7 @@ export default class PartyExpBar extends Phaser.GameObjects.Container { this.shown = false; } - showPokemonExp(pokemon: Pokemon, expValue: integer): Promise { + showPokemonExp(pokemon: Pokemon, expValue: integer, showOnlyLevelUp: boolean, newLevel: number): Promise { return new Promise(resolve => { if (this.shown) return resolve(); @@ -39,7 +39,17 @@ export default class PartyExpBar extends Phaser.GameObjects.Container { this.add(this.pokemonIcon); - this.expText.setText(`+${expValue.toString()}`); + // if we want to only display the level in the small frame + if (showOnlyLevelUp) { + if (newLevel > 200) { // if the level is greater than 200, we only display Lv. UP + this.expText.setText('Lv. UP'); + } else { // otherwise we display Lv. Up and the new level + this.expText.setText(`Lv. UP: ${newLevel.toString()}`); + } + } else { + // if we want to display the exp + this.expText.setText(`+${expValue.toString()}`); + } this.bg.width = this.expText.displayWidth + 28; From f1935a3e15569a8797e18db3b7ec3ec3cdbe60d5 Mon Sep 17 00:00:00 2001 From: Dakurei Date: Thu, 9 May 2024 23:30:24 -0400 Subject: [PATCH 2/6] Adds 'accuracy' to the move information in the fight ui + Capitalize 'power' and 'accuracy' fields --- src/locales/de/fight-ui-handler.ts | 3 ++- src/locales/en/fight-ui-handler.ts | 3 ++- src/locales/es/fight-ui-handler.ts | 3 ++- src/locales/fr/fight-ui-handler.ts | 3 ++- src/locales/it/fight-ui-handler.ts | 3 ++- src/locales/zh_CN/fight-ui-handler.ts | 3 ++- src/ui/fight-ui-handler.ts | 31 +++++++++++++++++++++------ src/ui/text.ts | 8 ++++++- 8 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/locales/de/fight-ui-handler.ts b/src/locales/de/fight-ui-handler.ts index 1ce9e0317..7546e9af6 100644 --- a/src/locales/de/fight-ui-handler.ts +++ b/src/locales/de/fight-ui-handler.ts @@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POWER", + "power": "Power", + "accuracy": "Accuracy", } as const; \ No newline at end of file diff --git a/src/locales/en/fight-ui-handler.ts b/src/locales/en/fight-ui-handler.ts index 1ce9e0317..7546e9af6 100644 --- a/src/locales/en/fight-ui-handler.ts +++ b/src/locales/en/fight-ui-handler.ts @@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POWER", + "power": "Power", + "accuracy": "Accuracy", } as const; \ No newline at end of file diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts index b431e3b70..5abe60abb 100644 --- a/src/locales/es/fight-ui-handler.ts +++ b/src/locales/es/fight-ui-handler.ts @@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POTENCIA", + "power": "Power", + "accuracy": "Accuracy", } as const; diff --git a/src/locales/fr/fight-ui-handler.ts b/src/locales/fr/fight-ui-handler.ts index 6e355f50c..a96e84c11 100644 --- a/src/locales/fr/fight-ui-handler.ts +++ b/src/locales/fr/fight-ui-handler.ts @@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "PUISSANCE", + "power": "Puissance", + "accuracy": "Précision", } as const; \ No newline at end of file diff --git a/src/locales/it/fight-ui-handler.ts b/src/locales/it/fight-ui-handler.ts index 0743e382c..7546e9af6 100644 --- a/src/locales/it/fight-ui-handler.ts +++ b/src/locales/it/fight-ui-handler.ts @@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POTENZA", + "power": "Power", + "accuracy": "Accuracy", } as const; \ No newline at end of file diff --git a/src/locales/zh_CN/fight-ui-handler.ts b/src/locales/zh_CN/fight-ui-handler.ts index 1ce9e0317..7546e9af6 100644 --- a/src/locales/zh_CN/fight-ui-handler.ts +++ b/src/locales/zh_CN/fight-ui-handler.ts @@ -2,5 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "POWER", + "power": "Power", + "accuracy": "Accuracy", } as const; \ No newline at end of file diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index ee7e413db..084337b40 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -17,6 +17,8 @@ export default class FightUiHandler extends UiHandler { private ppText: Phaser.GameObjects.Text; private powerLabel: Phaser.GameObjects.Text; private powerText: Phaser.GameObjects.Text; + private accuracyLabel: Phaser.GameObjects.Text; + private accuracyText: Phaser.GameObjects.Text; private cursorObj: Phaser.GameObjects.Image; private moveCategoryIcon: Phaser.GameObjects.Sprite; @@ -33,35 +35,46 @@ export default class FightUiHandler extends UiHandler { this.movesContainer = this.scene.add.container(18, -38.7); ui.add(this.movesContainer); - this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 57, -34, 'types', 'unknown'); + this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 57, -36, 'types', 'unknown'); this.typeIcon.setVisible(false); ui.add(this.typeIcon); - this.moveCategoryIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 25, -34, 'categories', 'physical'); + this.moveCategoryIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 25, -36, 'categories', 'physical'); this.moveCategoryIcon.setVisible(false); ui.add(this.moveCategoryIcon); - this.ppLabel = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 70, -22, 'PP', TextStyle.TOOLTIP_CONTENT); + this.ppLabel = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 70, -26, 'PP', TextStyle.MOVE_INFO_CONTENT); this.ppLabel.setOrigin(0.0, 0.5); this.ppLabel.setVisible(false); this.ppLabel.setText(i18next.t('fightUiHandler:pp')); ui.add(this.ppLabel); - this.ppText = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 12, -22, '--/--', TextStyle.TOOLTIP_CONTENT); + this.ppText = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 12, -26, '--/--', TextStyle.MOVE_INFO_CONTENT); this.ppText.setOrigin(1, 0.5); this.ppText.setVisible(false); ui.add(this.ppText); - this.powerLabel = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 70, -12, 'POWER', TextStyle.TOOLTIP_CONTENT); + this.powerLabel = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 70, -18, 'POWER', TextStyle.MOVE_INFO_CONTENT); this.powerLabel.setOrigin(0.0, 0.5); this.powerLabel.setVisible(false); this.powerLabel.setText(i18next.t('fightUiHandler:power')); ui.add(this.powerLabel); - this.powerText = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 12, -12, '---', TextStyle.TOOLTIP_CONTENT); + this.powerText = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 12, -18, '---', TextStyle.MOVE_INFO_CONTENT); this.powerText.setOrigin(1, 0.5); this.powerText.setVisible(false); ui.add(this.powerText); + + this.accuracyLabel = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 70, -10, 'ACC', TextStyle.MOVE_INFO_CONTENT); + this.accuracyLabel.setOrigin(0.0, 0.5); + this.accuracyLabel.setVisible(false); + this.accuracyLabel.setText(i18next.t('fightUiHandler:accuracy')) + ui.add(this.accuracyLabel); + + this.accuracyText = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 12, -10, '---', TextStyle.MOVE_INFO_CONTENT); + this.accuracyText.setOrigin(1, 0.5); + this.accuracyText.setVisible(false); + ui.add(this.accuracyText); } show(args: any[]): boolean { @@ -152,11 +165,13 @@ export default class FightUiHandler extends UiHandler { this.moveCategoryIcon.setTexture('categories', MoveCategory[pokemonMove.getMove().category].toLowerCase()).setScale(1.0); const power = pokemonMove.getMove().power; + const accuracy = pokemonMove.getMove().accuracy; const maxPP = pokemonMove.getMovePp(); const pp = maxPP - pokemonMove.ppUsed; this.ppText.setText(`${Utils.padInt(pp, 2, ' ')}/${Utils.padInt(maxPP, 2, ' ')}`); this.powerText.setText(`${power >= 0 ? power : '---'}`); + this.accuracyText.setText(`${accuracy >= 0 ? accuracy : '---'}`); } this.typeIcon.setVisible(hasMove); @@ -164,6 +179,8 @@ export default class FightUiHandler extends UiHandler { this.ppText.setVisible(hasMove); this.powerLabel.setVisible(hasMove); this.powerText.setVisible(hasMove); + this.accuracyLabel.setVisible(hasMove); + this.accuracyText.setVisible(hasMove); this.moveCategoryIcon.setVisible(hasMove); this.cursorObj.setPosition(13 + (cursor % 2 === 1 ? 100 : 0), -31 + (cursor >= 2 ? 15 : 0)); @@ -189,6 +206,8 @@ export default class FightUiHandler extends UiHandler { this.ppText.setVisible(false); this.powerLabel.setVisible(false); this.powerText.setVisible(false); + this.accuracyLabel.setVisible(false); + this.accuracyText.setVisible(false); this.moveCategoryIcon.setVisible(false); this.eraseCursor(); } diff --git a/src/ui/text.ts b/src/ui/text.ts index a8cce8782..3302c988a 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -24,7 +24,8 @@ export enum TextStyle { SETTINGS_LABEL, SETTINGS_SELECTED, TOOLTIP_TITLE, - TOOLTIP_CONTENT + TOOLTIP_CONTENT, + MOVE_INFO_CONTENT }; export function addTextObject(scene: Phaser.Scene, x: number, y: number, content: string, style: TextStyle, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle): Phaser.GameObjects.Text { @@ -106,6 +107,10 @@ function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptio styleOptions.fontSize = '64px'; shadowSize = 4; break; + case TextStyle.MOVE_INFO_CONTENT: + styleOptions.fontSize = '56px'; + shadowSize = 3; + break; } shadowColor = getTextColor(style, true, uiTheme); @@ -130,6 +135,7 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui case TextStyle.MESSAGE: return !shadow ? '#f8f8f8' : '#6b5a73'; case TextStyle.WINDOW: + case TextStyle.MOVE_INFO_CONTENT: case TextStyle.TOOLTIP_CONTENT: if (uiTheme) return !shadow ? '#484848' : '#d0d0c8'; From 5d62d0bb257143103e41c581ab5eca85c8aecf17 Mon Sep 17 00:00:00 2001 From: Greenlamp Date: Fri, 10 May 2024 16:32:19 +0200 Subject: [PATCH 3/6] fix speed level up notification --- src/phases.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phases.ts b/src/phases.ts index b697f7acb..71de11579 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -3752,7 +3752,7 @@ export class ShowPartyExpBarPhase extends PlayerPartyMemberPokemonPhase { // instead of displaying the exp gain in the small frame, we display the new level // we use the same method for mode 0 & 1, by giving a parameter saying to display the exp or the level this.scene.partyExpBar.showPokemonExp(pokemon, exp.value, this.scene.expParty === 1, newLevel).then(() => { - setTimeout(() => this.end(), 800 / Math.pow(2, this.scene.expGainsSpeed/2)); + setTimeout(() => this.end(), 800 / Math.pow(2, this.scene.expGainsSpeed)); }); } else { this.end(); From 7bdb969a731f59708e1f9c8dd476b62777da174f Mon Sep 17 00:00:00 2001 From: William Burleson <72857839+Admiral-Billy@users.noreply.github.com> Date: Fri, 10 May 2024 06:42:28 -0400 Subject: [PATCH 4/6] Add rich presence support --- src/battle-scene.ts | 17 ++++++++++++++++- src/phases.ts | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 9a51950a5..0171fb96c 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -53,7 +53,7 @@ import PokemonSpriteSparkleHandler from './field/pokemon-sprite-sparkle-handler' import CharSprite from './ui/char-sprite'; import DamageNumberHandler from './field/damage-number-handler'; import PokemonInfoContainer from './ui/pokemon-info-container'; -import { biomeDepths } from './data/biomes'; +import { biomeDepths, getBiomeName } from './data/biomes'; import { UiTheme } from './enums/ui-theme'; import { SceneBase } from './scene-base'; import CandyBar from './ui/candy-bar'; @@ -200,6 +200,7 @@ export default class BattleScene extends SceneBase { this.phaseQueuePrepend = []; this.phaseQueuePrependSpliceIndex = -1; this.nextCommandPhaseQueue = []; + this.updateGameInfo(); } loadPokemonAtlas(key: string, atlasPath: string, experimental?: boolean) { @@ -769,6 +770,8 @@ export default class BattleScene extends SceneBase { this.trainer.setTexture(`trainer_${this.gameData.gender === PlayerGender.FEMALE ? 'f' : 'm'}_back`); this.trainer.setPosition(406, 186); this.trainer.setVisible(true); + + this.updateGameInfo(); if (reloadI18n) { const localizable: Localizable[] = [ @@ -1963,4 +1966,16 @@ export default class BattleScene extends SceneBase { return false; } + + updateGameInfo(): void { + const gameInfo = { + 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, level: p.level }; + }) : [] + }; + (window as any).gameInfo = gameInfo; + } } \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index 71de11579..6144fe47a 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -680,6 +680,8 @@ export class EncounterPhase extends BattlePhase { start() { super.start(); + this.scene.updateGameInfo(); + this.scene.initSession(); const loadEnemyAssets = []; From 593ac38267bc25bd27408b63846ad70cec722606 Mon Sep 17 00:00:00 2001 From: Dakurei Date: Fri, 10 May 2024 17:29:22 +0200 Subject: [PATCH 5/6] Fix some errors from previous PR #711 (#716) --- src/locales/es/fight-ui-handler.ts | 2 +- src/locales/it/fight-ui-handler.ts | 2 +- src/ui/text.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/es/fight-ui-handler.ts b/src/locales/es/fight-ui-handler.ts index 5abe60abb..7a02ce66f 100644 --- a/src/locales/es/fight-ui-handler.ts +++ b/src/locales/es/fight-ui-handler.ts @@ -2,6 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "Power", + "power": "Potencia", "accuracy": "Accuracy", } as const; diff --git a/src/locales/it/fight-ui-handler.ts b/src/locales/it/fight-ui-handler.ts index 7546e9af6..94cb41f72 100644 --- a/src/locales/it/fight-ui-handler.ts +++ b/src/locales/it/fight-ui-handler.ts @@ -2,6 +2,6 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n"; export const fightUiHandler: SimpleTranslationEntries = { "pp": "PP", - "power": "Power", + "power": "Potenza", "accuracy": "Accuracy", } as const; \ No newline at end of file diff --git a/src/ui/text.ts b/src/ui/text.ts index 3302c988a..d7ecd3b25 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -135,7 +135,7 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui case TextStyle.MESSAGE: return !shadow ? '#f8f8f8' : '#6b5a73'; case TextStyle.WINDOW: - case TextStyle.MOVE_INFO_CONTENT: + case TextStyle.MOVE_INFO_CONTENT: case TextStyle.TOOLTIP_CONTENT: if (uiTheme) return !shadow ? '#484848' : '#d0d0c8'; From 2ab335a3c5ea3cbdd1e508f7f013021d240e712b Mon Sep 17 00:00:00 2001 From: Athebyne <30442287+f-raZ0R@users.noreply.github.com> Date: Fri, 10 May 2024 11:40:21 -0400 Subject: [PATCH 6/6] Implement Snipe Shot, and Propeller Tail/Stalwart (#661) * Implemented Snipe Shot and Stalwart/Propeller Tail * Remove Testing Overrides I don't know why these got pushed, they are in the gitignore file. * Snipe Shot also has a high crit rate * Add Comment * Add TsDoc documentation to BypassRedirectAttr * Add ability pop-up for when Propeller Tail/Stalwart proc. * Fix Formatting * Tab align comment --- src/data/ability.ts | 6 ++++-- src/data/move.ts | 8 +++++++- src/phases.ts | 27 ++++++++++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index f2220c850..8a244b85b 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2377,6 +2377,8 @@ export class RedirectTypeMoveAbAttr extends RedirectMoveAbAttr { } } +export class BlockRedirectAbAttr extends AbAttr { } + export class ReduceStatusEffectDurationAbAttr extends AbAttr { private statusEffect: StatusEffect; @@ -3465,7 +3467,7 @@ export function initAbilities() { .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.SPD, -1, false, true) .bypassFaint(), new Ability(Abilities.PROPELLER_TAIL, 8) - .unimplemented(), + .attr(BlockRedirectAbAttr), new Ability(Abilities.MIRROR_ARMOR, 8) .ignorable() .unimplemented(), @@ -3475,7 +3477,7 @@ export function initAbilities() { .attr(NoFusionAbilityAbAttr) .unimplemented(), new Ability(Abilities.STALWART, 8) - .unimplemented(), + .attr(BlockRedirectAbAttr), new Ability(Abilities.STEAM_ENGINE, 8) .attr(PostDefendStatChangeAbAttr, (target, user, move) => (move.type === Type.FIRE || move.type === Type.WATER) && move.category !== MoveCategory.STATUS, BattleStat.SPD, 6), new Ability(Abilities.PUNK_ROCK, 8) diff --git a/src/data/move.ts b/src/data/move.ts index 6e4e3f60f..6ac3af708 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2653,6 +2653,11 @@ const crashDamageFunc = (user: Pokemon, move: Move) => { }; export class TypelessAttr extends MoveAttr { } +/** +* Attribute used for moves which ignore redirection effects, and always target their original target, i.e. Snipe Shot +* Bypasses Storm Drain, Follow Me, Ally Switch, and the like. +*/ +export class BypassRedirectAttr extends MoveAttr { } export class DisableMoveAttr extends MoveEffectAttr { constructor() { @@ -6172,7 +6177,8 @@ export function initMoves() { .attr(DiscourageFrequentUseAttr) .ignoresVirtual(), new AttackMove(Moves.SNIPE_SHOT, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 8) - .partial(), + .attr(HighCritAttr) + .attr(BypassRedirectAttr), new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, false, false, 1) .attr(AddBattlerTagAttr, BattlerTagType.TRAPPED, true, false, 1) diff --git a/src/phases.ts b/src/phases.ts index 6144fe47a..20c4dc737 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2,7 +2,7 @@ import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from './utils'; import { Moves } from "./data/enums/moves"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, BypassRedirectAttr ,FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; @@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get import { TempBattleStat } from "./data/temp-battle-stat"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagType } from "./data/enums/arena-tag-type"; -import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; +import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr } from "./data/ability"; import { Unlockables, getUnlockableName } from "./system/unlockables"; import { getBiomeKey } from "./field/arena"; import { BattleType, BattlerIndex, TurnCommand } from "./battle"; @@ -2211,13 +2211,22 @@ export class MovePhase extends BattlePhase { } // Move redirection abilities (ie. Storm Drain) only support single target moves - const moveTarget = this.targets.length === 1 - ? new Utils.IntegerHolder(this.targets[0]) - : null; - if (moveTarget) { - this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); - this.targets[0] = moveTarget.value; - } +const moveTarget = this.targets.length === 1 + ? new Utils.IntegerHolder(this.targets[0]) + : null; + if (moveTarget) { + var oldTarget = moveTarget.value; + this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); + //Check if this move is immune to being redirected, and restore its target to the intended target if it is. + if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) || this.move.getMove().getAttrs(BypassRedirectAttr).length)) { + //If an ability prevented this move from being redirected, display its ability pop up. + if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) && !this.move.getMove().getAttrs(BypassRedirectAttr).length) && oldTarget != moveTarget.value) { + this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr))); + } + moveTarget.value = oldTarget; + } + this.targets[0] = moveTarget.value; +} if (this.targets.length === 1 && this.targets[0] === BattlerIndex.ATTACKER) { if (this.pokemon.turnData.attacksReceived.length) {