Skip to content

Commit

Permalink
[Bug] Fix strong winds calculation (#2423)
Browse files Browse the repository at this point in the history
* Fix strong winds calculation

* add unit test

* Add strong winds effect message

* Update src/locales/de/weather.ts

Co-authored-by: Jannik Tappert <[email protected]>

* Update src/locales/es/weather.ts

Co-authored-by: Jannik Tappert <[email protected]>

* Update src/locales/fr/weather.ts

Co-authored-by: Jannik Tappert <[email protected]>

* Update src/locales/it/weather.ts

Co-authored-by: Jannik Tappert <[email protected]>

* Update src/locales/ko/weather.ts

Co-authored-by: Jannik Tappert <[email protected]>

---------

Co-authored-by: torranx <[email protected]>
Co-authored-by: Jannik Tappert <[email protected]>
  • Loading branch information
3 people authored Jul 5, 2024
1 parent 160a5ce commit 0f51099
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/field/pokemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return (!cancelled.value ? Number(typeMultiplier.value) : 0) as TypeDamageMultiplier;
}

getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false): TypeDamageMultiplier {
/**
* Calculates the type effectiveness multiplier for an attack type
* @param moveType Type of the move
* @param source the Pokemon using the move
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
* @param simulated tag to only apply the strong winds effect message when the move is used
* @returns a multiplier for the type effectiveness
*/
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
if (moveType === Type.STELLAR) {
return this.isTerastallized() ? 2 : 1;
}
Expand All @@ -1183,8 +1191,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier;

// Handle strong winds lowering effectiveness of types super effective against pure flying
if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && multiplier >= 2 && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) {
if (!ignoreStrongWinds && this.scene.arena.weather?.weatherType === WeatherType.STRONG_WINDS && !this.scene.arena.weather.isEffectSuppressed(this.scene) && this.isOfType(Type.FLYING) && getTypeDamageMultiplier(moveType, Type.FLYING) === 2) {
multiplier /= 2;
if (!simulated) {
this.scene.queueMessage(i18next.t("weather:strongWindsEffectMessage"));
}
}

if (!!this.summonData?.tags.find((tag) => tag instanceof TypeImmuneTag && tag.immuneType === moveType)) {
Expand Down Expand Up @@ -1739,7 +1750,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const cancelled = new Utils.BooleanHolder(false);
const typeless = move.hasAttr(TypelessAttr);
const typeMultiplier = new Utils.NumberHolder(!typeless && (moveCategory !== MoveCategory.STATUS || move.getAttrs(StatusMoveTypeImmunityAttr).find(attr => types.includes(attr.immuneType)))
? this.getAttackTypeEffectiveness(move.type, source)
? this.getAttackTypeEffectiveness(move.type, source, false, false)
: 1);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (typeless) {
Expand Down
1 change: 1 addition & 0 deletions src/locales/de/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "Alle Flug-Pokémon werden von rätselhaften Luftströmungen geschützt!",
"strongWindsLapseMessage": "Die rätselhafte Luftströmung hält an.",
"strongWindsEffectMessage": "Rätselhafte Luftströmungen haben den Angriff abgeschwächt!",
"strongWindsClearMessage": "Die rätselhafte Luftströmung hat sich wieder geleget.",
};
1 change: 1 addition & 0 deletions src/locales/en/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "A heavy wind began!",
"strongWindsLapseMessage": "The wind blows intensely.",
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
"strongWindsClearMessage": "The heavy wind stopped."
};
1 change: 1 addition & 0 deletions src/locales/es/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "¡Comenzó un fuerte viento!",
"strongWindsLapseMessage": "El viento sopla intensamente.",
"strongWindsEffectMessage": "¡Las misteriosas turbulencias atenúan el ataque!",
"strongWindsClearMessage": "El fuerte viento cesó."
};
1 change: 1 addition & 0 deletions src/locales/fr/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "Un vent mystérieux se lève !",
"strongWindsLapseMessage": "Le vent mystérieux souffle violemment !",
"strongWindsEffectMessage": "Le courant aérien mystérieux affaiblit l’attaque !",
"strongWindsClearMessage": "Le vent mystérieux s’est dissipé…"
};
1 change: 1 addition & 0 deletions src/locales/it/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "È apparsa una corrente d'aria misteriosa!",
"strongWindsLapseMessage": "La corrente d'aria soffia intensamente.",
"strongWindsEffectMessage": "La corrente misteriosa indebolisce l’attacco!",
"strongWindsClearMessage": "La corrente d'aria è cessata."
};
1 change: 1 addition & 0 deletions src/locales/ko/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "수수께끼의 난기류가\n비행포켓몬을 지킨다!",
"strongWindsLapseMessage": "수수께끼의 난기류가 강렬하게 불고 있다",
"strongWindsEffectMessage": "수수께끼의 난기류가 공격을 약하게 만들었다!",
"strongWindsClearMessage": "수수께끼의 난기류가 멈췄다!" // 임의번역
};
1 change: 1 addition & 0 deletions src/locales/pt_BR/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "Ventos fortes apareceram!",
"strongWindsLapseMessage": "Os ventos fortes continuam.",
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
"strongWindsClearMessage": "Os ventos fortes diminuíram.",
};
1 change: 1 addition & 0 deletions src/locales/zh_CN/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "吹起了神秘的乱流!",
"strongWindsLapseMessage": "神秘的乱流势头不减。",
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
"strongWindsClearMessage": "神秘的乱流停止了。"
};
1 change: 1 addition & 0 deletions src/locales/zh_TW/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ export const weather: SimpleTranslationEntries = {

"strongWindsStartMessage": "吹起了神秘的亂流!",
"strongWindsLapseMessage": "神秘的亂流勢頭不減。",
"strongWindsEffectMessage": "The mysterious air current weakened the attack!",
"strongWindsClearMessage": "神秘的亂流停止了。"
};
82 changes: 82 additions & 0 deletions src/test/arena/weather_strong_winds.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import Phaser from "phaser";
import GameManager from "#app/test/utils/gameManager";
import * as overrides from "#app/overrides";
import { Species } from "#enums/species";
import {
TurnStartPhase,
} from "#app/phases";
import { Moves } from "#enums/moves";
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
import { Abilities } from "#enums/abilities";
import { allMoves } from "#app/data/move.js";

describe("Weather - Strong Winds", () => {
let phaserGame: Phaser.Game;
let game: GameManager;

beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});

afterEach(() => {
game.phaseInterceptor.restoreOg();
});

beforeEach(() => {
game = new GameManager(phaserGame);
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(10);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.TAILLOW);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DELTA_STREAM);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.THUNDERBOLT, Moves.ICE_BEAM, Moves.ROCK_SLIDE]);
});

it("electric type move is not very effective on Rayquaza", async () => {
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RAYQUAZA);

await game.startBattle([Species.PIKACHU]);
const pikachu = game.scene.getPlayerPokemon();
const enemy = game.scene.getEnemyPokemon();

game.doAttack(getMovePosition(game.scene, 0, Moves.THUNDERBOLT));

await game.phaseInterceptor.to(TurnStartPhase);
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.THUNDERBOLT].type, pikachu)).toBe(0.5);
});

it("electric type move is neutral for flying type pokemon", async () => {
await game.startBattle([Species.PIKACHU]);
const pikachu = game.scene.getPlayerPokemon();
const enemy = game.scene.getEnemyPokemon();

game.doAttack(getMovePosition(game.scene, 0, Moves.THUNDERBOLT));

await game.phaseInterceptor.to(TurnStartPhase);
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.THUNDERBOLT].type, pikachu)).toBe(1);
});

it("ice type move is neutral for flying type pokemon", async () => {
await game.startBattle([Species.PIKACHU]);
const pikachu = game.scene.getPlayerPokemon();
const enemy = game.scene.getEnemyPokemon();

game.doAttack(getMovePosition(game.scene, 0, Moves.ICE_BEAM));

await game.phaseInterceptor.to(TurnStartPhase);
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.ICE_BEAM].type, pikachu)).toBe(1);
});

it("rock type move is neutral for flying type pokemon", async () => {
await game.startBattle([Species.PIKACHU]);
const pikachu = game.scene.getPlayerPokemon();
const enemy = game.scene.getEnemyPokemon();

game.doAttack(getMovePosition(game.scene, 0, Moves.ROCK_SLIDE));

await game.phaseInterceptor.to(TurnStartPhase);
expect(enemy.getAttackTypeEffectiveness(allMoves[Moves.ROCK_SLIDE].type, pikachu)).toBe(1);
});
});

0 comments on commit 0f51099

Please sign in to comment.