Compare commits

...

5 Commits

Author SHA1 Message Date
Enoch
ec27c14035
[Localization] add missed move trigger and remove getPokemonMessage (#3281)
* localize missed move-trigger message and remove redundant getPokemonMessage

* Update src/locales/zh_CN/move-trigger.ts

Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com>

* Update src/locales/zh_TW/move-trigger.ts

Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com>

* Update src/locales/de/move-trigger.ts

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/data/move.ts

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/de/move-trigger.ts

Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com>

* Update src/locales/zh_TW/move-trigger.ts

Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com>

* Update src/locales/zh_CN/move-trigger.ts

Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com>

* Update src/locales/fr/move-trigger.ts

Co-authored-by: Lugiad' <adrien.grivel@hotmail.fr>

* Update src/locales/it/move-trigger.ts

Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>

* Revert "Update src/data/move.ts"

This reverts commit 4dd6130c39.

* fix italian param error

* Update src/locales/de/move-trigger.ts

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/de/move-trigger.ts

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Update src/locales/pt_BR/move-trigger.ts

Co-authored-by: José Ricardo Fleury Oliveira <josefleury@discente.ufg.br>

---------

Co-authored-by: mercurius-00 <80205689+mercurius-00@users.noreply.github.com>
Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>
Co-authored-by: Lugiad' <adrien.grivel@hotmail.fr>
Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com>
Co-authored-by: José Ricardo Fleury Oliveira <josefleury@discente.ufg.br>
2024-08-02 22:41:55 -04:00
allen925
3055d4500f
[Test] added revive function in gameManager & a double-battle test (#3298)
* added revive function in gamaManager & a double-battle test

* extended timeout of double battle test referencing to battle test

* less code, deleted unused param, clearer description of test

* add back dbond to move in test

* more straight forward testing

* reverse back override

* polish double battle test a bit
2024-08-02 22:30:50 -04:00
NightKev
e1812466a8
[Bug] Weather should be reset upon arena reset (#3301)
* `resetArenaEffects()` should also reset weather

* Update function doc
2024-08-02 22:29:07 -04:00
Opaque02
fc8b708785
[Misc] Tandemaus evolves into 3 family form at a rate of 25% (#2738) 2024-08-02 22:27:54 -04:00
Lugiad
6c6dc01490
[Localization] Small batch of missing French entires (#3309)
* Update trainers.ts

* Update bgm-name.ts

* Update bgm-name.ts
2024-08-02 22:14:09 -04:00
19 changed files with 241 additions and 43 deletions

View File

@ -2,7 +2,7 @@ import { ChargeAnim, MoveChargeAnim, initMoveAnim, loadMoveAnimAssets } from "./
import { BattleEndPhase, MoveEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases"; import { BattleEndPhase, MoveEndPhase, MovePhase, NewBattlePhase, PartyStatusCurePhase, PokemonHealPhase, StatChangePhase, SwitchSummonPhase } from "../phases";
import { BattleStat, getBattleStatName } from "./battle-stat"; import { BattleStat, getBattleStatName } from "./battle-stat";
import { EncoreTag, HelpingHandTag, SemiInvulnerableTag, StockpilingTag, TypeBoostTag } from "./battler-tags"; import { EncoreTag, HelpingHandTag, SemiInvulnerableTag, StockpilingTag, TypeBoostTag } from "./battler-tags";
import { getPokemonMessage, getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "../messages";
import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon"; import Pokemon, { AttackMoveResult, EnemyPokemon, HitResult, MoveResult, PlayerPokemon, PokemonMove, TurnMove } from "../field/pokemon";
import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect"; import { StatusEffect, getStatusEffectHealText, isNonVolatileStatusEffect, getNonVolatileStatusEffects} from "./status-effect";
import { getTypeResistances, Type } from "./type"; import { getTypeResistances, Type } from "./type";
@ -1388,7 +1388,7 @@ export class HealAttr extends MoveEffectAttr {
*/ */
addHealPhase(target: Pokemon, healRatio: number) { addHealPhase(target: Pokemon, healRatio: number) {
target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(),
Math.max(Math.floor(target.getMaxHp() * healRatio), 1), getPokemonMessage(target, " \nhad its HP restored."), true, !this.showAnim)); Math.max(Math.floor(target.getMaxHp() * healRatio), 1), i18next.t("moveTriggers:healHp", {pokemonName: getPokemonNameWithAffix(target)}), true, !this.showAnim));
} }
getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer {
@ -1482,7 +1482,7 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr {
const maxPartyMemberHp = user.scene.getParty().map(p => p.getMaxHp()).reduce((maxHp: integer, hp: integer) => Math.max(hp, maxHp), 0); const maxPartyMemberHp = user.scene.getParty().map(p => p.getMaxHp()).reduce((maxHp: integer, hp: integer) => Math.max(hp, maxHp), 0);
user.scene.pushPhase(new PokemonHealPhase(user.scene, user.getBattlerIndex(), user.scene.pushPhase(new PokemonHealPhase(user.scene, user.getBattlerIndex(),
maxPartyMemberHp, getPokemonMessage(user, "'s Healing Wish\nwas granted!"), true, false, false, true), true); maxPartyMemberHp, i18next.t("moveTriggers:sacrificialFullRestore", {pokemonName: getPokemonNameWithAffix(user)}), true, false, false, true), true);
return true; return true;
} }
@ -2712,7 +2712,7 @@ export class InvertStatsAttr extends MoveEffectAttr {
target.updateInfo(); target.updateInfo();
user.updateInfo(); user.updateInfo();
target.scene.queueMessage(getPokemonMessage(target, "'s stat changes\nwere all reversed!")); target.scene.queueMessage(i18next.t("moveTriggers:invertStats", {pokemonName: getPokemonNameWithAffix(target)}));
return true; return true;
} }
@ -2730,7 +2730,7 @@ export class ResetStatsAttr extends MoveEffectAttr {
target.updateInfo(); target.updateInfo();
user.updateInfo(); user.updateInfo();
target.scene.queueMessage(getPokemonMessage(target, "'s stat changes\nwere eliminated!")); target.scene.queueMessage(i18next.t("moveTriggers:resetStats", {pokemonName: getPokemonNameWithAffix(target)}));
return true; return true;
} }
@ -4138,7 +4138,7 @@ export class DisableMoveAttr extends MoveEffectAttr {
target.summonData.disabledMove = disabledMove.moveId; target.summonData.disabledMove = disabledMove.moveId;
target.summonData.disabledTurns = 4; target.summonData.disabledTurns = 4;
user.scene.queueMessage(getPokemonMessage(target, `'s ${disabledMove.getName()}\nwas disabled!`)); user.scene.queueMessage(i18next.t("abilityTriggers:postDefendMoveDisable", { pokemonNameWithAffix: getPokemonNameWithAffix(target), moveName: disabledMove.getName()}));
return true; return true;
} }
@ -4445,7 +4445,7 @@ export class FaintCountdownAttr extends AddBattlerTagAttr {
return false; return false;
} }
user.scene.queueMessage(getPokemonMessage(target, `\nwill faint in ${this.turnCountMin - 1} turns.`)); user.scene.queueMessage(i18next.t("moveTriggers:faintCountdown", {pokemonName: getPokemonNameWithAffix(target), turnCount: this.turnCountMin - 1}));
return true; return true;
} }
@ -4685,7 +4685,7 @@ export class SwapArenaTagsAttr extends MoveEffectAttr {
} }
user.scene.queueMessage( `${getPokemonNameWithAffix(user)} swapped the battle effects affecting each side of the field!`); user.scene.queueMessage( i18next.t("moveTriggers:swapArenaTags", {pokemonName: getPokemonNameWithAffix(user)}));
return true; return true;
} }
} }
@ -4917,7 +4917,7 @@ export class CopyTypeAttr extends MoveEffectAttr {
user.summonData.types = target.getTypes(true); user.summonData.types = target.getTypes(true);
user.updateInfo(); user.updateInfo();
user.scene.queueMessage(getPokemonMessage(user, `'s type\nchanged to match ${getPokemonNameWithAffix(target)}'s!`)); user.scene.queueMessage(i18next.t("moveTriggers:copyType", {pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target)}));
return true; return true;
} }
@ -5598,7 +5598,7 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr {
target.summonData.abilitySuppressed = true; target.summonData.abilitySuppressed = true;
target.scene.queueMessage(getPokemonMessage(target, "'s ability\nwas suppressed!")); target.scene.queueMessage(i18next.t("moveTriggers:suppressAbilities", {pokemonName: getPokemonNameWithAffix(target)}));
return true; return true;
} }

View File

@ -1145,6 +1145,11 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.PAWMOT, 32, null, null) new SpeciesEvolution(Species.PAWMOT, 32, null, null)
], ],
[Species.TANDEMAUS]: [ [Species.TANDEMAUS]: [
new SpeciesFormEvolution(Species.MAUSHOLD, "", "three", 25, null, new SpeciesEvolutionCondition(p => {
let ret = false;
p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id);
return ret;
})),
new SpeciesEvolution(Species.MAUSHOLD, 25, null, null) new SpeciesEvolution(Species.MAUSHOLD, 25, null, null)
], ],
[Species.FIDOUGH]: [ [Species.FIDOUGH]: [

View File

@ -2459,8 +2459,8 @@ export function initSpecies() {
new PokemonSpecies(Species.PAWMOT, 9, false, false, false, "Hands-On Pokémon", Type.ELECTRIC, Type.FIGHTING, 0.9, 41, Abilities.VOLT_ABSORB, Abilities.NATURAL_CURE, Abilities.IRON_FIST, 490, 70, 115, 70, 70, 60, 105, 45, 50, 245, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.PAWMOT, 9, false, false, false, "Hands-On Pokémon", Type.ELECTRIC, Type.FIGHTING, 0.9, 41, Abilities.VOLT_ABSORB, Abilities.NATURAL_CURE, Abilities.IRON_FIST, 490, 70, 115, 70, 70, 60, 105, 45, 50, 245, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(Species.TANDEMAUS, 9, false, false, false, "Couple Pokémon", Type.NORMAL, null, 0.3, 1.8, Abilities.RUN_AWAY, Abilities.PICKUP, Abilities.OWN_TEMPO, 305, 50, 50, 45, 40, 45, 75, 150, 50, 61, GrowthRate.FAST, null, false), new PokemonSpecies(Species.TANDEMAUS, 9, false, false, false, "Couple Pokémon", Type.NORMAL, null, 0.3, 1.8, Abilities.RUN_AWAY, Abilities.PICKUP, Abilities.OWN_TEMPO, 305, 50, 50, 45, 40, 45, 75, 150, 50, 61, GrowthRate.FAST, null, false),
new PokemonSpecies(Species.MAUSHOLD, 9, false, false, false, "Family Pokémon", Type.NORMAL, null, 0.3, 2.3, Abilities.FRIEND_GUARD, Abilities.CHEEK_POUCH, Abilities.TECHNICIAN, 470, 74, 75, 70, 65, 75, 111, 75, 50, 165, GrowthRate.FAST, null, false, false, new PokemonSpecies(Species.MAUSHOLD, 9, false, false, false, "Family Pokémon", Type.NORMAL, null, 0.3, 2.3, Abilities.FRIEND_GUARD, Abilities.CHEEK_POUCH, Abilities.TECHNICIAN, 470, 74, 75, 70, 65, 75, 111, 75, 50, 165, GrowthRate.FAST, null, false, false,
new PokemonForm("Family of Four", "four", Type.NORMAL, null, 0.3, 2.3, Abilities.FRIEND_GUARD, Abilities.CHEEK_POUCH, Abilities.TECHNICIAN, 470, 74, 75, 70, 65, 75, 111, 75, 50, 165), new PokemonForm("Family of Four", "four", Type.NORMAL, null, 0.3, 2.8, Abilities.FRIEND_GUARD, Abilities.CHEEK_POUCH, Abilities.TECHNICIAN, 470, 74, 75, 70, 65, 75, 111, 75, 50, 165),
new PokemonForm("Family of Three", "three", Type.NORMAL, null, 0.3, 2.8, Abilities.FRIEND_GUARD, Abilities.CHEEK_POUCH, Abilities.TECHNICIAN, 470, 74, 75, 70, 65, 75, 111, 75, 50, 165), new PokemonForm("Family of Three", "three", Type.NORMAL, null, 0.3, 2.3, Abilities.FRIEND_GUARD, Abilities.CHEEK_POUCH, Abilities.TECHNICIAN, 470, 74, 75, 70, 65, 75, 111, 75, 50, 165),
), ),
new PokemonSpecies(Species.FIDOUGH, 9, false, false, false, "Puppy Pokémon", Type.FAIRY, null, 0.3, 10.9, Abilities.OWN_TEMPO, Abilities.NONE, Abilities.KLUTZ, 312, 37, 55, 70, 30, 55, 65, 190, 50, 62, GrowthRate.MEDIUM_SLOW, 50, false), new PokemonSpecies(Species.FIDOUGH, 9, false, false, false, "Puppy Pokémon", Type.FAIRY, null, 0.3, 10.9, Abilities.OWN_TEMPO, Abilities.NONE, Abilities.KLUTZ, 312, 37, 55, 70, 30, 55, 65, 190, 50, 62, GrowthRate.MEDIUM_SLOW, 50, false),
new PokemonSpecies(Species.DACHSBUN, 9, false, false, false, "Dog Pokémon", Type.FAIRY, null, 0.5, 14.9, Abilities.WELL_BAKED_BODY, Abilities.NONE, Abilities.AROMA_VEIL, 477, 57, 80, 115, 50, 80, 95, 90, 50, 167, GrowthRate.MEDIUM_SLOW, 50, false), new PokemonSpecies(Species.DACHSBUN, 9, false, false, false, "Dog Pokémon", Type.FAIRY, null, 0.5, 14.9, Abilities.WELL_BAKED_BODY, Abilities.NONE, Abilities.AROMA_VEIL, 477, 57, 80, 115, 50, 80, 95, 90, 50, 167, GrowthRate.MEDIUM_SLOW, 50, false),

View File

@ -639,9 +639,13 @@ export class Arena {
} }
/** /**
* Clears terrain and arena tags when entering new biome or trainer battle. * Clears weather, terrain and arena tags when entering new biome or trainer battle.
*/ */
resetArenaEffects(): void { resetArenaEffects(): void {
// Don't reset weather if a Biome's permanent weather is active
if (this.weather?.turnsLeft !== 0) {
this.trySetWeather(WeatherType.NONE, false);
}
this.trySetTerrain(TerrainType.NONE, false, true); this.trySetTerrain(TerrainType.NONE, false, true);
this.removeAllTags(); this.removeAllTags();
} }

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}} verwandelt sich in {{targetName}}!", "transformedIntoTarget": "{{pokemonName}} verwandelt sich in {{targetName}}!",
"tryingToTakeFoeDown": "{{pokemonName}} versucht, den Angreifer mit sich zu nehmen!", "tryingToTakeFoeDown": "{{pokemonName}} versucht, den Angreifer mit sich zu nehmen!",
"addType": "{{pokemonName}} nimmt zusätzlich den Typ {{typeName}} an!", "addType": "{{pokemonName}} nimmt zusätzlich den Typ {{typeName}} an!",
"cannotUseMove": "{{pokemonName}} kann {{moveName}} nicht einsetzen!" "cannotUseMove": "{{pokemonName}} kann {{moveName}} nicht einsetzen!",
"healHp": "KP von {{pokemonName}} wurden aufgefrischt!",
"sacrificialFullRestore": "Das Heilopfer von {{pokemonName}} erreicht sein Ziel!",
"invertStats": "Alle Statusveränderungen von {{pokemonName}} wurden invertiert!",
"resetStats": "Die Statusveränderungen von {{pokemonName}} wurden aufgehoben!",
"faintCountdown": "{{pokemonName}} geht nach {{turnCount}} Runden K.O.!",
"copyType": "{{pokemonName}} hat den Typ von {{targetPokemonName}} angenommen!",
"suppressAbilities": "Die Fähigkeit von {{pokemonName}} wirkt nicht mehr!",
"swapArenaTags": "{{pokemonName}} hat die Effekte, die auf den beiden Seiten des Kampffeldes wirken, miteinander getauscht!",
} as const; } as const;

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}} transformed\ninto {{targetName}}!", "transformedIntoTarget": "{{pokemonName}} transformed\ninto {{targetName}}!",
"tryingToTakeFoeDown": "{{pokemonName}} is hoping to take its attacker down with it!", "tryingToTakeFoeDown": "{{pokemonName}} is hoping to take its attacker down with it!",
"addType": "{{typeName}} was added to\n{{pokemonName}}!", "addType": "{{typeName}} was added to\n{{pokemonName}}!",
"cannotUseMove": "{{pokemonName}} cannot use {{moveName}}!" "cannotUseMove": "{{pokemonName}} cannot use {{moveName}}!",
"healHp": "{{pokemonName}} had its HP restored.",
"sacrificialFullRestore": "{{pokemonName}}'s Healing Wish\nwas granted!",
"invertStats": "{{pokemonName}}'s stat changes\nwere all reversed!",
"resetStats": "{{pokemonName}}'s stat changes\nwere eliminated!",
"faintCountdown": "{{pokemonName}}\nwill faint in {{turnCount}} turns.",
"copyType": "{{pokemonName}}'s type became the same as\n{{targetPokemonName}}'s type!",
"suppressAbilities": "{{pokemonName}}'s ability\nwas suppressed!",
"swapArenaTags": "{{pokemonName}} swapped the battle effects affecting each side of the field!",
} as const; } as const;

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}} transformed\ninto {{targetName}}!", "transformedIntoTarget": "{{pokemonName}} transformed\ninto {{targetName}}!",
"tryingToTakeFoeDown": "{{pokemonName}} is hoping to take its attacker down with it!", "tryingToTakeFoeDown": "{{pokemonName}} is hoping to take its attacker down with it!",
"addType": "{{typeName}} was added to\n{{pokemonName}}!", "addType": "{{typeName}} was added to\n{{pokemonName}}!",
"cannotUseMove": "{{pokemonName}} cannot use {{moveName}}!" "cannotUseMove": "{{pokemonName}} cannot use {{moveName}}!",
"healHp": "{{pokemonName}} had its HP restored.",
"sacrificialFullRestore": "{{pokemonName}}'s Healing Wish\nwas granted!",
"invertStats": "{{pokemonName}}'s stat changes\nwere all reversed!",
"resetStats": "{{pokemonName}}'s stat changes\nwere eliminated!",
"faintCountdown": "{{pokemonName}}\nwill faint in {{turnCount}} turns.",
"copyType": "{{pokemonName}}'s type\nchanged to match {{targetPokemonName}}'s!",
"suppressAbilities": "{{pokemonName}}'s ability\nwas suppressed!",
"swapArenaTags": "{{pokemonName}} swapped the battle effects affecting each side of the field!",
} as const; } as const;

View File

@ -74,16 +74,16 @@ export const bgmName: SimpleTranslationEntries = {
"battle_wild": "NB - Vs. Pokémon sauvage", "battle_wild": "NB - Vs. Pokémon sauvage",
"battle_wild_strong": "NB - Vs. Pokémon puissant sauvage", "battle_wild_strong": "NB - Vs. Pokémon puissant sauvage",
"end_summit": "PDM ÉSDX - Tour Céleste", "end_summit": "PDM ÉSDX - Tour Céleste",
"battle_rocket_grunt": "HGSS Team Rocket Battle", "battle_rocket_grunt": "HGSS Vs. Team Rocket",
"battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle", "battle_aqua_magma_grunt": "ROSA Vs. Team Aqua/Magma",
"battle_galactic_grunt": "BDSP Team Galactic Battle", "battle_galactic_grunt": "DÉPS Vs. Team Galaxie",
"battle_plasma_grunt": "NB - Vs. Team Plasma", "battle_plasma_grunt": "NB - Vs. Team Plasma",
"battle_flare_grunt": "XY Team Flare Battle", "battle_flare_grunt": "XY - Vs. Team Flare",
"battle_rocket_boss": "USUM Giovanni Battle", "battle_rocket_boss": "USUL - Vs. Giovanni",
"battle_aqua_magma_boss": "ORAS Archie & Maxie Battle", "battle_aqua_magma_boss": "ROSA - Vs. Max/Arthur",
"battle_galactic_boss": "BDSP Cyrus Battle", "battle_galactic_boss": "DÉPS - Vs. Hélio",
"battle_plasma_boss": "B2W2 Ghetsis Battle", "battle_plasma_boss": "N2B2 - Vs. Ghetis",
"battle_flare_boss": "XY Lysandre Battle", "battle_flare_boss": "XY - Vs. Lysandre",
// Biome Music // Biome Music
"abyss": "PDM EdS - Cratère Obscur", "abyss": "PDM EdS - Cratère Obscur",

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}} prend\nlapparence de {{targetName}} !", "transformedIntoTarget": "{{pokemonName}} prend\nlapparence de {{targetName}} !",
"tryingToTakeFoeDown": "{{pokemonName}} veut entrainer\nson assaillant dans sa chute !", "tryingToTakeFoeDown": "{{pokemonName}} veut entrainer\nson assaillant dans sa chute !",
"addType": "{{pokemonName}} gagne\nle type {{typeName}}.", "addType": "{{pokemonName}} gagne\nle type {{typeName}}.",
"cannotUseMove": "{{pokemonName}} ne peut pas\nutiliser la capacité {{moveName}} !" "cannotUseMove": "{{pokemonName}} ne peut pas\nutiliser la capacité {{moveName}} !",
"healHp": "{{pokemonName}}\nrécupère des PV !",
"sacrificialFullRestore": "Le Vœu Soin est exaucé et profite\nà {{pokemonName}} !",
"invertStats": "Les changements de stats\nde {{pokemonName}} sont inversés !",
"resetStats": "Les changements de stats\nde {{pokemonName}} ont tous été annulés !",
"faintCountdown": "{{pokemonName}}\nsera K.O. dans {{turnCount}} tours !",
"copyType": "{{pokemonName}} prend le type\nde {{targetPokemonName}} !",
"suppressAbilities": "Le talent de {{pokemonName}}\na été rendu inactif !",
"swapArenaTags": "Les effets affectant chaque côté du terrain\nont été échangés par {{pokemonName}} !",
} as const; } as const;

View File

@ -271,7 +271,11 @@ export const trainerNames: SimpleTranslationEntries = {
"leon": "Tarak", "leon": "Tarak",
"rival": "Gwenaël", //Male breton name, a celtic language spoken in Brittany (France) and related to the word for "white" (gwenn). Finn meaning is also "white" in irish/goidelic which are also celtic languages. "rival": "Gwenaël", //Male breton name, a celtic language spoken in Brittany (France) and related to the word for "white" (gwenn). Finn meaning is also "white" in irish/goidelic which are also celtic languages.
"rival_female": "Papina", //Litteral translation of ivy, also used as Female name in a North-American indigenous language "rival_female": "Papina", //Litteral translation of ivy, also used as Female name in a North-American indigenous language
"maxie": "Max",
"archie": "Arthur",
"cyrus": "Hélios",
"ghetsis": "Ghetis",
"lysandre": "Lysandre",
// Double Names // Double Names
"blue_red_double": "Blue & Red", "blue_red_double": "Blue & Red",

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}} assume le sembianze\ndi {{targetName}}!", "transformedIntoTarget": "{{pokemonName}} assume le sembianze\ndi {{targetName}}!",
"tryingToTakeFoeDown": "{{pokemonName}} tenta di far subire a chi lo manda KO la sua stessa sorte!", "tryingToTakeFoeDown": "{{pokemonName}} tenta di far subire a chi lo manda KO la sua stessa sorte!",
"addType": "Adesso {{pokemonName}} è anche\ndi tipo {{typeName}}!", "addType": "Adesso {{pokemonName}} è anche\ndi tipo {{typeName}}!",
"cannotUseMove": "{{pokemonName}} non può usare {{moveName}}!" "cannotUseMove": "{{pokemonName}} non può usare {{moveName}}!",
"healHp": "{{pokemonName}} ha recuperato dei PS.",
"sacrificialFullRestore": "{{pokemonName}} riceve i benefici\neffetti di Curardore!",
"invertStats": "Le modifiche alle statistiche di {{pokemonName}}\nvengono invertite!",
"resetStats": "Tutte le modifiche alle statistiche sono state annullate!",
"faintCountdown": "{{pokemonName}}\nandrà KO dopo {{turnCount}} turni.",
"copyType": "{{pokemonName}} assume il tipo\ndi {{targetPokemonName}}!",
"suppressAbilities": "Labilità di {{pokemonName}}\nperde ogni efficacia!",
"swapArenaTags": "{{pokemonName}} ha invertito gli effetti attivi\nnelle due metà del campo!",
} as const; } as const;

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}}[[는]]\n{{targetName}}[[로]] 변신했다!", "transformedIntoTarget": "{{pokemonName}}[[는]]\n{{targetName}}[[로]] 변신했다!",
"tryingToTakeFoeDown": "{{pokemonName}}[[는]] 상대를\n길동무로 삼으려 하고 있다!", "tryingToTakeFoeDown": "{{pokemonName}}[[는]] 상대를\n길동무로 삼으려 하고 있다!",
"addType": "{{pokemonName}}에게\n{{typeName}}타입이 추가되었다!", "addType": "{{pokemonName}}에게\n{{typeName}}타입이 추가되었다!",
"cannotUseMove": "{{pokemonName}}[[는]]\n{{moveName}}[[를]] 쓸 수 없다!" "cannotUseMove": "{{pokemonName}}[[는]]\n{{moveName}}[[를]] 쓸 수 없다!",
"healHp": "{{pokemonName}}의\n체력이 회복되었다!",
"sacrificialFullRestore": "{{pokemonName}}의\n치유소원이 이루어졌다!",
"invertStats": "{{pokemonName}}[[는]]\n능력 변화가 뒤집혔다!",
"resetStats": "{{pokemonName}}의 모든 상태가\n원래대로 되돌아왔다!",
"faintCountdown": "{{pokemonName}}[[는]]\n{{turnCount}}턴 후에 쓰러져 버린다!",
"copyType": "{{pokemonName}}[[는]]\n{{targetPokemonName}}[[와]] 같은 타입이 되었다!",
"suppressAbilities": "{{pokemonName}}의\n특성이 효과를 발휘하지 못하게 되었다!",
"swapArenaTags": "{{pokemonName}}[[는]]\n서로의 필드 효과를 교체했다!",
} as const; } as const;

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}} se transformou\nem um(a) {{targetName}}!", "transformedIntoTarget": "{{pokemonName}} se transformou\nem um(a) {{targetName}}!",
"tryingToTakeFoeDown": "{{pokemonName}} está tentando derrubar o atacante com ele!", "tryingToTakeFoeDown": "{{pokemonName}} está tentando derrubar o atacante com ele!",
"addType": "{{pokemonName}} recebeu\no tipo {{typeName}}!", "addType": "{{pokemonName}} recebeu\no tipo {{typeName}}!",
"cannotUseMove": "{{pokemonName}} não pode usar {{moveName}}!" "cannotUseMove": "{{pokemonName}} não pode usar {{moveName}}!",
"healHp": "{{pokemonName}} teve seus PS recuperados.",
"sacrificialFullRestore": "O Healing Wish de {{pokemonName}}\nfoi concedido!",
"invertStats": "As mudanças de atributo de {{pokemonName}}\nforam revertidas!",
"resetStats": "As mudanças de atributo de {{pokemonName}}\nforam eliminadas!",
"faintCountdown": "{{pokemonName}}\nirá desmaiar em {{turnCount}} turnos.",
"copyType": "O tipo de {{pokemonName}}\nmudou para combinar com {{targetPokemonName}}!",
"suppressAbilities": "A habilidade de {{pokemonName}}\nfoi suprimida!",
"swapArenaTags": "{{pokemonName}} trocou os efeitos de batalha que afetam cada lado do campo!",
} as const; } as const;

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}}\n变身成了{{targetName}}", "transformedIntoTarget": "{{pokemonName}}\n变身成了{{targetName}}",
"tryingToTakeFoeDown": "{{pokemonName}}\n想和对手同归于尽", "tryingToTakeFoeDown": "{{pokemonName}}\n想和对手同归于尽",
"addType": "{{pokemonName}}\n增加了{{typeName}}属性!", "addType": "{{pokemonName}}\n增加了{{typeName}}属性!",
"cannotUseMove": "{{pokemonName}}\n无法使用{{moveName}}" "cannotUseMove": "{{pokemonName}}\n无法使用{{moveName}}",
"healHp": "{{pokemonName}}的\n体力回复了",
"sacrificialFullRestore": "{{pokemonName}}的\n治愈之愿实现了",
"invertStats": "{{pokemonName}}的\n能力变化颠倒过来了",
"resetStats": "{{pokemonName}}的\n能力变化复原了",
"faintCountdown": "{{pokemonName}}\n将在{{turnCount}}回合后灭亡!",
"copyType": "{{pokemonName}}\n变成了{{targetPokemonName}}的属性!",
"suppressAbilities": "{{pokemonName}}的特性\n变得无效了",
"swapArenaTags": "{{pokemonName}}\n交换了双方的场地效果",
} as const; } as const;

View File

@ -50,5 +50,13 @@ export const moveTriggers: SimpleTranslationEntries = {
"transformedIntoTarget": "{{pokemonName}}\n變身成了{{targetName}}", "transformedIntoTarget": "{{pokemonName}}\n變身成了{{targetName}}",
"tryingToTakeFoeDown": "{{pokemonName}}\n想和對手同歸於盡", "tryingToTakeFoeDown": "{{pokemonName}}\n想和對手同歸於盡",
"addType": "{{pokemonName}}\n增加了{{typeName}}屬性!", "addType": "{{pokemonName}}\n增加了{{typeName}}屬性!",
"cannotUseMove": "{{pokemonName}}\n無法使用{{moveName}}" "cannotUseMove": "{{pokemonName}}\n無法使用{{moveName}}",
"healHp": "{{pokemonName}}的\n體力回復了",
"sacrificialFullRestore": "{{pokemonName}}的\n治癒之願實現了",
"invertStats": "{{pokemonName}}的\n能力變化顛倒過來了",
"resetStats": "{{pokemonName}}的\n能力變化復原了",
"faintCountdown": "{{pokemonName}}\n將在{{turnCount}}回合後滅亡!",
"copyType": "{{pokemonName}}變成了{{targetPokemonName}}的屬性!",
"suppressAbilities": "{{pokemonName}}的特性\n變得無效了",
"swapArenaTags": "{{pokemonName}}\n交換了雙方的場地效果",
} as const; } as const;

View File

@ -2,17 +2,6 @@ import { BattleSpec } from "#enums/battle-spec";
import Pokemon from "./field/pokemon"; import Pokemon from "./field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
/**
* Builds a message by concatenating the Pokemon name with its potential affix and the given text
* @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance for {@linkcode getPokemonNameWithAffix}
* @param {string} content any text
* @returns {string} ex: "Wild Gengar fainted!", "Ectoplasma sauvage est K.O!"
* @see {@linkcode getPokemonNameWithAffix} for the Pokemon's name and potentiel affix
*/
export function getPokemonMessage(pokemon: Pokemon, content: string): string {
return `${getPokemonNameWithAffix(pokemon)}${content}`;
}
/** /**
* Retrieves the Pokemon's name, potentially with an affix indicating its role (wild or foe) in the current battle context, translated * Retrieves the Pokemon's name, potentially with an affix indicating its role (wild or foe) in the current battle context, translated
* @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance * @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance

View File

@ -0,0 +1,64 @@
import {
BattleEndPhase,
TurnInitPhase,
} from "#app/phases";
import GameManager from "#app/test/utils/gameManager";
import { getMovePosition, } from "#app/test/utils/gameManagerUtils";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
import { SPLASH_ONLY } from "../utils/testUtils";
import { Status, StatusEffect } from "#app/data/status-effect.js";
describe("Test Battle Phase", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
});
// double-battle player's pokemon both fainted in same round, then revive one, and next double battle summons two player's pokemon successfully.
// (There were bugs that either only summon one when can summon two, player stuck in switchPhase etc)
it("3v2 edge case: player summons 2 pokemon on the next battle after being fainted and revived", async() => {
game.override.battleType("double").enemyMoveset(SPLASH_ONLY).moveset(SPLASH_ONLY);
await game.startBattle([
Species.BULBASAUR,
Species.CHARIZARD,
Species.SQUIRTLE,
]);
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
game.doAttack(getMovePosition(game.scene, 1, Moves.SPLASH));
for (const pokemon of game.scene.getPlayerField()) {
expect(pokemon).toBeDefined();
pokemon.hp = 0;
pokemon.status = new Status(StatusEffect.FAINT);
expect(pokemon.isFainted()).toBe(true);
}
await game.doKillOpponents();
await game.phaseInterceptor.to(BattleEndPhase);
game.doSelectModifier();
const charizard = game.scene.getParty().findIndex(p => p.species.speciesId === Species.CHARIZARD);
game.doRevivePokemon(charizard);
await game.phaseInterceptor.to(TurnInitPhase);
expect(game.scene.getPlayerField().filter(p => !p.isFainted())).toHaveLength(2);
}, 20000);
});

View File

@ -0,0 +1,48 @@
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import Phaser from "phaser";
import GameManager from "#app/test/utils/gameManager";
import { Species } from "#enums/species";
import * as Utils from "#app/utils";
describe("Evolution tests", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
});
it("tandemaus evolution form test", async () => {
/* this test checks to make sure that tandemaus will
* evolve into a 3 family maushold 25% of the time
* and a 4 family maushold the other 75% of the time
* This is done by using the getEvolution method in pokemon.ts
* getEvolution will give back the form that the pokemon can evolve into
* It does this by checking the pokemon conditions in pokemon-forms.ts
* For tandemaus, the conditions are random due to a randSeedInt(4)
* If the value is 0, it's a 3 family maushold, whereas if the value is
* 1, 2 or 3, it's a 4 family maushold
*/
await game.startBattle([Species.TANDEMAUS]); // starts us off with a tandemaus
const playerPokemon = game.scene.getPlayerPokemon();
playerPokemon.level = 25; // tandemaus evolves at level 25
vi.spyOn(Utils, "randSeedInt").mockReturnValue(0); // setting the random generator to be 0 to force a three family maushold
const threeForm = playerPokemon.getEvolution();
expect(threeForm.evoFormKey).toBe("three"); // as per pokemon-forms, the evoFormKey for 3 family mausholds is "three"
for (let f = 1; f < 4; f++) {
vi.spyOn(Utils, "randSeedInt").mockReturnValue(f); // setting the random generator to 1, 2 and 3 to force 4 family mausholds
const fourForm = playerPokemon.getEvolution();
expect(fourForm.evoFormKey).toBe(null); // meanwhile, according to the pokemon-forms, the evoFormKey for a 4 family maushold is null
}
}, 5000);
});

View File

@ -35,6 +35,7 @@ import { Button } from "#enums/buttons";
import { BattlerIndex } from "#app/battle.js"; import { BattlerIndex } from "#app/battle.js";
import TargetSelectUiHandler from "#app/ui/target-select-ui-handler.js"; import TargetSelectUiHandler from "#app/ui/target-select-ui-handler.js";
import { OverridesHelper } from "./overridesHelper"; import { OverridesHelper } from "./overridesHelper";
import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type.js";
/** /**
* Class to manage the game state and transitions between phases. * Class to manage the game state and transitions between phases.
@ -328,4 +329,15 @@ export default class GameManager {
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, pokemonIndex, false); (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, pokemonIndex, false);
}); });
} }
/**
* Revive pokemon, currently player's only.
* @param pokemonIndex the index of the pokemon in your party to revive
*/
doRevivePokemon(pokemonIndex: number) {
const party = this.scene.getParty();
const candidate = new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0);
const modifier = candidate.type.newModifier(party[pokemonIndex]);
this.scene.addModifier(modifier, false);
}
} }