Merge branch 'main' of github.com:Greenlamp2/pokerogue into feat/inputs_management_rework

This commit is contained in:
Greenlamp 2024-05-03 14:45:36 +02:00
commit a034950969
45 changed files with 684 additions and 323 deletions

View File

@ -42,3 +42,5 @@ jobs:
https://pokerogue.net/ https://pokerogue.net/
https://pokerogue.net/index.html https://pokerogue.net/index.html
https://pokerogue.net/manifest.json https://pokerogue.net/manifest.json
https://pokerogue.net/manifest.webmanifest
https://pokerogue.net/service-worker.js

Binary file not shown.

Before

Width:  |  Height:  |  Size: 458 B

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 B

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View File

@ -3,9 +3,8 @@
"short_name": "PokéRogue", "short_name": "PokéRogue",
"description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.", "description": "A Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, and reaching Pokémon stats you never thought possible.",
"scope": "/", "scope": "/",
"start_url": "/", "start_url": "https://pokerogue.net",
"display": "fullscreen", "display": "fullscreen",
"orientation": "landscape",
"background_color": "#8c8c8c", "background_color": "#8c8c8c",
"theme_color": "#8c8c8c", "theme_color": "#8c8c8c",
"icons": [ "icons": [

View File

@ -919,8 +919,8 @@ export class MovePowerBoostAbAttr extends VariableMovePowerAbAttr {
private condition: PokemonAttackCondition; private condition: PokemonAttackCondition;
private powerMultiplier: number; private powerMultiplier: number;
constructor(condition: PokemonAttackCondition, powerMultiplier: number) { constructor(condition: PokemonAttackCondition, powerMultiplier: number, showAbility: boolean = true) {
super(true); super(showAbility);
this.condition = condition; this.condition = condition;
this.powerMultiplier = powerMultiplier; this.powerMultiplier = powerMultiplier;
} }
@ -2725,7 +2725,7 @@ export function initAbilities() {
.attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPD, 1) .attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPD, 1)
.ignorable(), .ignorable(),
new Ability(Abilities.RIVALRY, 4) new Ability(Abilities.RIVALRY, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25) .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25, true)
.attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75), .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75),
new Ability(Abilities.STEADFAST, 4) new Ability(Abilities.STEADFAST, 4)
.attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1), .attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1),

View File

@ -482,6 +482,20 @@ export class GravityTag extends ArenaTag {
} }
} }
class TailwindTag extends ArenaTag {
constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) {
super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side);
}
onAdd(arena: Arena): void {
arena.scene.queueMessage(`The Tailwind blew from behind${this.side === ArenaTagSide.PLAYER ? '\nyour' : this.side === ArenaTagSide.ENEMY ? '\nthe opposing' : ''} team!`);
}
onRemove(arena: Arena): void {
arena.scene.queueMessage(`${this.side === ArenaTagSide.PLAYER ? 'Your' : this.side === ArenaTagSide.ENEMY ? 'The opposing' : ''} team's Tailwind petered out!`);
}
}
export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag { export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag {
switch (tagType) { switch (tagType) {
case ArenaTagType.MIST: case ArenaTagType.MIST:
@ -513,5 +527,7 @@ export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMov
return new LightScreenTag(turnCount, sourceId, side); return new LightScreenTag(turnCount, sourceId, side);
case ArenaTagType.AURORA_VEIL: case ArenaTagType.AURORA_VEIL:
return new AuroraVeilTag(turnCount, sourceId, side); return new AuroraVeilTag(turnCount, sourceId, side);
case ArenaTagType.TAILWIND:
return new TailwindTag(turnCount, sourceId, side);
} }
} }

View File

@ -163,6 +163,29 @@ export class FlinchedTag extends BattlerTag {
} }
} }
export class InterruptedTag extends BattlerTag {
constructor(sourceMove: Moves){
super(BattlerTagType.INTERRUPTED, BattlerTagLapseType.PRE_MOVE, 0, sourceMove)
}
canAdd(pokemon: Pokemon): boolean {
return !!pokemon.getTag(BattlerTagType.FLYING)
}
onAdd(pokemon: Pokemon): void {
super.onAdd(pokemon);
pokemon.getMoveQueue().shift()
pokemon.pushMoveHistory({move: Moves.NONE, result: MoveResult.OTHER})
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
super.lapse(pokemon, lapseType);
(pokemon.scene.getCurrentPhase() as MovePhase).cancel();
return true
}
}
export class ConfusedTag extends BattlerTag { export class ConfusedTag extends BattlerTag {
constructor(turnCount: integer, sourceMove: Moves) { constructor(turnCount: integer, sourceMove: Moves) {
super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove); super(BattlerTagType.CONFUSED, BattlerTagLapseType.MOVE, turnCount, sourceMove);
@ -368,6 +391,12 @@ export class FrenzyTag extends BattlerTag {
} }
} }
export class ChargingTag extends BattlerTag {
constructor(sourceMove: Moves, sourceId: integer) {
super(BattlerTagType.CHARGING, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId);
}
}
export class EncoreTag extends BattlerTag { export class EncoreTag extends BattlerTag {
public moveId: Moves; public moveId: Moves;
@ -1081,6 +1110,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new RechargingTag(sourceMove); return new RechargingTag(sourceMove);
case BattlerTagType.FLINCHED: case BattlerTagType.FLINCHED:
return new FlinchedTag(sourceMove); return new FlinchedTag(sourceMove);
case BattlerTagType.INTERRUPTED:
return new InterruptedTag(sourceMove);
case BattlerTagType.CONFUSED: case BattlerTagType.CONFUSED:
return new ConfusedTag(turnCount, sourceMove); return new ConfusedTag(turnCount, sourceMove);
case BattlerTagType.INFATUATED: case BattlerTagType.INFATUATED:
@ -1091,6 +1122,8 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: integer, sourc
return new NightmareTag(); return new NightmareTag();
case BattlerTagType.FRENZY: case BattlerTagType.FRENZY:
return new FrenzyTag(sourceMove, sourceId); return new FrenzyTag(sourceMove, sourceId);
case BattlerTagType.CHARGING:
return new ChargingTag(sourceMove, sourceId);
case BattlerTagType.ENCORE: case BattlerTagType.ENCORE:
return new EncoreTag(sourceId); return new EncoreTag(sourceId);
case BattlerTagType.HELPING_HAND: case BattlerTagType.HELPING_HAND:

View File

@ -615,7 +615,7 @@ export const biomePokemonPools: BiomePokemonPools = {
[TimeOfDay.DAY]: [], [TimeOfDay.DAY]: [],
[TimeOfDay.DUSK]: [], [TimeOfDay.DUSK]: [],
[TimeOfDay.NIGHT]: [], [TimeOfDay.NIGHT]: [],
[TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 20: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ] [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 52: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ]
}, },
[BiomePoolTier.SUPER_RARE]: { [BiomePoolTier.SUPER_RARE]: {
[TimeOfDay.DAWN]: [], [TimeOfDay.DAWN]: [],
@ -1128,8 +1128,8 @@ export const biomePokemonPools: BiomePokemonPools = {
] ]
}, },
[BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, Species.KLEFKI ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, Species.KLEFKI ] },
[BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] } ] },
[BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] }, { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] },
[BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ] },
[BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLINKLANG, Species.KLEFKI ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLINKLANG, Species.KLEFKI ] },
[BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] },
@ -1319,7 +1319,7 @@ export const biomePokemonPools: BiomePokemonPools = {
[TimeOfDay.DAY]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] }, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], [TimeOfDay.DAY]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] }, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ],
[TimeOfDay.DUSK]: [ Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], [TimeOfDay.DUSK]: [ Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ],
[TimeOfDay.NIGHT]: [ { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], [TimeOfDay.NIGHT]: [ { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ],
[TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 36: [ Species.TOUCANNON ] } ] [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 28: [ Species.TOUCANNON ] } ]
}, },
[BiomePoolTier.UNCOMMON]: { [BiomePoolTier.UNCOMMON]: {
[TimeOfDay.DAWN]: [ Species.EXEGGCUTE, Species.TROPIUS, Species.COMBEE, Species.KOMALA ], [TimeOfDay.DAWN]: [ Species.EXEGGCUTE, Species.TROPIUS, Species.COMBEE, Species.KOMALA ],
@ -2708,7 +2708,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
] ]
], ],
[ Species.PORYGON, Type.NORMAL, -1, [ [ Species.PORYGON, Type.NORMAL, -1, [
[ Biome.FACTORY, BiomePoolTier.SUPER_RARE ], [ Biome.FACTORY, BiomePoolTier.RARE ],
[ Biome.SPACE, BiomePoolTier.SUPER_RARE ], [ Biome.SPACE, BiomePoolTier.SUPER_RARE ],
[ Biome.LABORATORY, BiomePoolTier.RARE ] [ Biome.LABORATORY, BiomePoolTier.RARE ]
] ]
@ -3165,7 +3165,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
] ]
], ],
[ Species.PORYGON2, Type.NORMAL, -1, [ [ Species.PORYGON2, Type.NORMAL, -1, [
[ Biome.FACTORY, BiomePoolTier.SUPER_RARE ], [ Biome.FACTORY, BiomePoolTier.RARE ],
[ Biome.SPACE, BiomePoolTier.SUPER_RARE ], [ Biome.SPACE, BiomePoolTier.SUPER_RARE ],
[ Biome.LABORATORY, BiomePoolTier.RARE ] [ Biome.LABORATORY, BiomePoolTier.RARE ]
] ]

View File

@ -458,9 +458,9 @@ export const speciesEggMoves = {
[Species.MORPEKO]: [ Moves.TRIPLE_AXEL, Moves.OBSTRUCT, Moves.PARTING_SHOT, Moves.SWORDS_DANCE ], [Species.MORPEKO]: [ Moves.TRIPLE_AXEL, Moves.OBSTRUCT, Moves.PARTING_SHOT, Moves.SWORDS_DANCE ],
[Species.CUFANT]: [ Moves.LIQUIDATION, Moves.HEAVY_SLAM, Moves.CLOSE_COMBAT, Moves.GIGATON_HAMMER ], [Species.CUFANT]: [ Moves.LIQUIDATION, Moves.HEAVY_SLAM, Moves.CLOSE_COMBAT, Moves.GIGATON_HAMMER ],
[Species.DRACOZOLT]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.FIRE_LASH, Moves.DRAGON_DANCE ], [Species.DRACOZOLT]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.FIRE_LASH, Moves.DRAGON_DANCE ],
[Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.EARTHQUAKE, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], [Species.ARCTOZOLT]: [ Moves.TRIPLE_AXEL, Moves.LIQUIDATION, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ],
[Species.DRACOVISH]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.THUNDER_FANG, Moves.DRAGON_DANCE ], [Species.DRACOVISH]: [ Moves.TRIPLE_AXEL, Moves.DRAGON_HAMMER, Moves.THUNDER_FANG, Moves.DRAGON_DANCE ],
[Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.EARTHQUAKE, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ], [Species.ARCTOVISH]: [ Moves.TRIPLE_AXEL, Moves.SUPERCELL_SLAM, Moves.HIGH_HORSEPOWER, Moves.SHIFT_GEAR ],
[Species.DURALUDON]: [ Moves.CALM_MIND, Moves.BODY_PRESS, Moves.EARTH_POWER, Moves.RECOVER ], [Species.DURALUDON]: [ Moves.CALM_MIND, Moves.BODY_PRESS, Moves.EARTH_POWER, Moves.RECOVER ],
[Species.DREEPY]: [ Moves.DRAGON_ENERGY, Moves.SHED_TAIL, Moves.BLAZING_TORQUE, Moves.SPECTRAL_THIEF ], [Species.DREEPY]: [ Moves.DRAGON_ENERGY, Moves.SHED_TAIL, Moves.BLAZING_TORQUE, Moves.SPECTRAL_THIEF ],
[Species.ZACIAN]: [ Moves.MAGICAL_TORQUE, Moves.BITTER_BLADE, Moves.LEAF_BLADE, Moves.VICTORY_DANCE ], [Species.ZACIAN]: [ Moves.MAGICAL_TORQUE, Moves.BITTER_BLADE, Moves.LEAF_BLADE, Moves.VICTORY_DANCE ],

View File

@ -15,5 +15,6 @@ export enum ArenaTagType {
GRAVITY = "GRAVITY", GRAVITY = "GRAVITY",
REFLECT = "REFLECT", REFLECT = "REFLECT",
LIGHT_SCREEN = "LIGHT_SCREEN", LIGHT_SCREEN = "LIGHT_SCREEN",
AURORA_VEIL = "AURORA_VEIL" AURORA_VEIL = "AURORA_VEIL",
TAILWIND = "TAILWIND"
} }

View File

@ -3,11 +3,13 @@ export enum BattlerTagType {
NONE = "NONE", NONE = "NONE",
RECHARGING = "RECHARGING", RECHARGING = "RECHARGING",
FLINCHED = "FLINCHED", FLINCHED = "FLINCHED",
INTERRUPTED = "INTERRUPTED",
CONFUSED = "CONFUSED", CONFUSED = "CONFUSED",
INFATUATED = "INFATUATED", INFATUATED = "INFATUATED",
SEEDED = "SEEDED", SEEDED = "SEEDED",
NIGHTMARE = "NIGHTMARE", NIGHTMARE = "NIGHTMARE",
FRENZY = "FRENZY", FRENZY = "FRENZY",
CHARGING = "CHARGING",
ENCORE = "ENCORE", ENCORE = "ENCORE",
HELPING_HAND = "HELPING_HAND", HELPING_HAND = "HELPING_HAND",
INGRAIN = "INGRAIN", INGRAIN = "INGRAIN",

View File

@ -557,7 +557,7 @@ export class TargetHalfHpDamageAttr extends FixedDamageAttr {
} }
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
(args[0] as Utils.IntegerHolder).value = Math.floor(target.hp / 2); (args[0] as Utils.IntegerHolder).value = Math.max(Math.floor(target.hp / 2), 1);
return true; return true;
} }
@ -1325,10 +1325,13 @@ export class ChargeAttr extends OverrideMoveEffectAttr {
user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true }); user.getMoveQueue().push({ move: move.id, targets: [ target.getBattlerIndex() ], ignorePP: true });
if (this.sameTurn) if (this.sameTurn)
user.scene.pushMovePhase(new MovePhase(user.scene, user, [ target.getBattlerIndex() ], user.moveset.find(m => m.moveId === move.id), true), this.followUpPriority); user.scene.pushMovePhase(new MovePhase(user.scene, user, [ target.getBattlerIndex() ], user.moveset.find(m => m.moveId === move.id), true), this.followUpPriority);
user.addTag(BattlerTagType.CHARGING, 1, move.id, user.id);
resolve(true); resolve(true);
}); });
} else } else {
user.lapseTag(BattlerTagType.CHARGING);
resolve(false); resolve(false);
}
}); });
} }
@ -1770,13 +1773,13 @@ export class BattleStatRatioPowerAttr extends VariablePowerAttr {
if (this.invert) { if (this.invert) {
// Gyro ball uses a specific formula // Gyro ball uses a specific formula
let userSpeed = user.getStat(this.stat); let userSpeed = user.getBattleStat(this.stat);
if (userSpeed < 1) { if (userSpeed < 1) {
// Gen 6+ always have 1 base power // Gen 6+ always have 1 base power
power.value = 1; power.value = 1;
return true; return true;
} }
let bp = Math.floor(Math.min(150, 25 * target.getStat(this.stat) / userSpeed + 1)); let bp = Math.floor(Math.min(150, 25 * target.getBattleStat(this.stat) / userSpeed + 1));
power.value = bp; power.value = bp;
return true; return true;
} }
@ -3594,6 +3597,23 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr {
} }
} }
export class SuppressAbilitiesAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if (!super.apply(user, target, move, args))
return false;
target.summonData.abilitySuppressed = true;
target.scene.queueMessage(getPokemonMessage(target, ` ability\nwas suppressed!`));
return true;
}
getCondition(): MoveConditionFunc {
return (user, target, move) => !target.getAbility().hasAttr(UnsuppressableAbilityAbAttr);
}
}
export class TransformAttr extends MoveEffectAttr { export class TransformAttr extends MoveEffectAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
return new Promise(resolve => { return new Promise(resolve => {
@ -3645,6 +3665,20 @@ export class MoneyAttr extends MoveEffectAttr {
} }
} }
export class LastResortAttr extends MoveAttr {
getCondition(): MoveConditionFunc {
return (user: Pokemon, target: Pokemon, move: Move) => {
const uniqueUsedMoveIds = new Set<Moves>();
const movesetMoveIds = user.getMoveset().map(m => m.moveId);
user.getMoveHistory().map(m => {
if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move))
uniqueUsedMoveIds.add(m.move);
});
return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1;
};
}
}
const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY); const failOnGravityCondition: MoveConditionFunc = (user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY);
const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune(); const failOnBossCondition: MoveConditionFunc = (user, target, move) => !target.isBossImmune();
@ -4774,8 +4808,8 @@ export function initMoves() {
.partial(), .partial(),
new StatusMove(Moves.TAILWIND, Type.FLYING, -1, 15, -1, 0, 4) new StatusMove(Moves.TAILWIND, Type.FLYING, -1, 15, -1, 0, 4)
.windMove() .windMove()
.target(MoveTarget.USER_SIDE) .attr(AddArenaTagAttr, ArenaTagType.TAILWIND, 4, true)
.unimplemented(), .target(MoveTarget.USER_SIDE),
new StatusMove(Moves.ACUPRESSURE, Type.NORMAL, -1, 30, -1, 0, 4) new StatusMove(Moves.ACUPRESSURE, Type.NORMAL, -1, 30, -1, 0, 4)
.attr(StatChangeAttr, BattleStat.RAND, 2) .attr(StatChangeAttr, BattleStat.RAND, 2)
.target(MoveTarget.USER_OR_NEAR_ALLY), .target(MoveTarget.USER_OR_NEAR_ALLY),
@ -4817,7 +4851,7 @@ export function initMoves() {
new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4) new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4)
.unimplemented(), .unimplemented(),
new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4) new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4)
.unimplemented(), .attr(SuppressAbilitiesAttr),
new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4) new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4)
.attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, false, 5) .attr(AddBattlerTagAttr, BattlerTagType.NO_CRIT, false, false, 5)
.target(MoveTarget.USER_SIDE) .target(MoveTarget.USER_SIDE)
@ -4836,15 +4870,7 @@ export function initMoves() {
new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4) new AttackMove(Moves.PUNISHMENT, Type.DARK, MoveCategory.PHYSICAL, -1, 100, 5, -1, 0, 4)
.unimplemented(), .unimplemented(),
new AttackMove(Moves.LAST_RESORT, Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, 0, 4) new AttackMove(Moves.LAST_RESORT, Type.NORMAL, MoveCategory.PHYSICAL, 140, 100, 5, -1, 0, 4)
.condition((user, target, move) => { .attr(LastResortAttr),
const uniqueUsedMoveIds = new Set<Moves>();
const movesetMoveIds = user.getMoveset().map(m => m.moveId);
user.getMoveHistory().map(m => {
if (m.move !== move.id && movesetMoveIds.find(mm => mm === m.move))
uniqueUsedMoveIds.add(m.move);
});
return uniqueUsedMoveIds.size >= movesetMoveIds.length - 1;
}),
new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4) new StatusMove(Moves.WORRY_SEED, Type.GRASS, 100, 10, -1, 0, 4)
.attr(AbilityChangeAttr, Abilities.INSOMNIA), .attr(AbilityChangeAttr, Abilities.INSOMNIA),
new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4) new AttackMove(Moves.SUCKER_PUNCH, Type.DARK, MoveCategory.PHYSICAL, 70, 100, 5, -1, 1, 4)
@ -5083,6 +5109,8 @@ export function initMoves() {
.unimplemented(), .unimplemented(),
new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5)
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 5)
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING])
.attr(HitsTagAttr, BattlerTagType.FLYING, false) .attr(HitsTagAttr, BattlerTagType.FLYING, false)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5)
@ -5446,6 +5474,8 @@ export function initMoves() {
new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, 100, 0, 6) new AttackMove(Moves.THOUSAND_ARROWS, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, 100, 0, 6)
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
.attr(HitsTagAttr, BattlerTagType.FLYING, false) .attr(HitsTagAttr, BattlerTagType.FLYING, false)
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
.attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING])
.makesContact(false) .makesContact(false)
.target(MoveTarget.ALL_NEAR_ENEMIES), .target(MoveTarget.ALL_NEAR_ENEMIES),
new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
@ -6332,8 +6362,7 @@ export function initMoves() {
}), // TODO Add Instruct/Encore interaction }), // TODO Add Instruct/Encore interaction
new AttackMove(Moves.COMEUPPANCE, Type.DARK, MoveCategory.PHYSICAL, 1, 100, 10, -1, 0, 9) new AttackMove(Moves.COMEUPPANCE, Type.DARK, MoveCategory.PHYSICAL, 1, 100, 10, -1, 0, 9)
.attr(CounterDamageAttr, (move: Move) => (move.category === MoveCategory.PHYSICAL || move.category === MoveCategory.SPECIAL), 1.5) .attr(CounterDamageAttr, (move: Move) => (move.category === MoveCategory.PHYSICAL || move.category === MoveCategory.SPECIAL), 1.5)
.target(MoveTarget.ATTACKER) .target(MoveTarget.ATTACKER),
.partial(),
new AttackMove(Moves.AQUA_CUTTER, Type.WATER, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 9) new AttackMove(Moves.AQUA_CUTTER, Type.WATER, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 9)
.attr(HighCritAttr) .attr(HighCritAttr)
.slicingMove() .slicingMove()

View File

@ -367,8 +367,8 @@ export abstract class PokemonSpeciesForm {
loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise<void> { loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant); const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant);
scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`);
scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant)); scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant));
scene.load.audio(this.getCryKey(formIndex), `audio/cry/${this.getCryKey(formIndex)}.m4a`);
scene.load.once(Phaser.Loader.Events.COMPLETE, () => { scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
const originalWarn = console.warn; const originalWarn = console.warn;
// Ignore warnings for missing frames, because there will be a lot // Ignore warnings for missing frames, because there will be a lot
@ -3156,6 +3156,30 @@ export const noStarterFormKeys: string[] = [
SpeciesFormKey.ETERNAMAX SpeciesFormKey.ETERNAMAX
].map(k => k.toString()); ].map(k => k.toString());
export function getStarterValueFriendshipCap(value: integer): integer {
switch (value) {
case 1:
return 20;
case 2:
return 40;
case 3:
return 60;
case 4:
return 100;
case 5:
return 140;
case 6:
return 200;
case 7:
return 280;
case 8:
case 9:
return 450;
default:
return 600;
}
}
export const starterPassiveAbilities = { export const starterPassiveAbilities = {
[Species.BULBASAUR]: Abilities.SOLAR_POWER, [Species.BULBASAUR]: Abilities.SOLAR_POWER,
[Species.CHARMANDER]: Abilities.INTIMIDATE, [Species.CHARMANDER]: Abilities.INTIMIDATE,

View File

@ -5,12 +5,12 @@ import { variantData } from '#app/data/variant';
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info'; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from '../ui/battle-info';
import { Moves } from "../data/enums/moves"; import { Moves } from "../data/enums/moves";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move"; import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, VariablePowerAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, MultiHitAttr, StatusMoveTypeImmunityAttr, MoveTarget, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatChangesAttr, SacrificialAttr, VariableMoveTypeAttr, VariableMoveCategoryAttr } from "../data/move";
import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, starterPassiveAbilities } from '../data/pokemon-species'; import { default as PokemonSpecies, PokemonSpeciesForm, SpeciesFormKey, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm, getStarterValueFriendshipCap, speciesStarters, starterPassiveAbilities } from '../data/pokemon-species';
import * as Utils from '../utils'; import * as Utils from '../utils';
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type'; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from '../data/type';
import { getLevelTotalExp } from '../data/exp'; import { getLevelTotalExp } from '../data/exp';
import { Stat } from '../data/pokemon-stat'; import { Stat } from '../data/pokemon-stat';
import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier'; import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from '../modifier/modifier';
import { PokeballType } from '../data/pokeball'; import { PokeballType } from '../data/pokeball';
import { Gender } from '../data/gender'; import { Gender } from '../data/gender';
import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims'; import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims';
@ -37,7 +37,7 @@ import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler
import SoundFade from 'phaser3-rex-plugins/plugins/soundfade'; import SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
import { LevelMoves } from '../data/pokemon-level-moves'; import { LevelMoves } from '../data/pokemon-level-moves';
import { DamageAchv, achvs } from '../system/achv'; import { DamageAchv, achvs } from '../system/achv';
import { DexAttr, StarterMoveset } from '../system/game-data'; import { DexAttr, StarterDataEntry, StarterMoveset } from '../system/game-data';
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from '@material/material-color-utilities'; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from '@material/material-color-utilities';
import { Nature, getNatureStatMultiplier } from '../data/nature'; import { Nature, getNatureStatMultiplier } from '../data/nature';
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms'; import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from '../data/pokemon-forms';
@ -45,6 +45,7 @@ import { TerrainType } from '../data/terrain';
import { TrainerSlot } from '../data/trainer-config'; import { TrainerSlot } from '../data/trainer-config';
import { BerryType } from '../data/berry'; import { BerryType } from '../data/berry';
import { ABILITY_OVERRIDE, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides'; import { ABILITY_OVERRIDE, MOVE_OVERRIDE, OPP_ABILITY_OVERRIDE, OPP_MOVE_OVERRIDE, OPP_SHINY_OVERRIDE, OPP_VARIANT_OVERRIDE } from '../overrides';
import i18next from '../plugins/i18n';
export enum FieldPosition { export enum FieldPosition {
CENTER, CENTER,
@ -588,6 +589,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
ret *= 1.5; ret *= 1.5;
break; break;
case Stat.SPD: case Stat.SPD:
// Check both the player and enemy to see if Tailwind should be multiplying the speed of the Pokemon
if ((this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER))
|| (!this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.ENEMY)))
ret *= 2;
if (this.getTag(BattlerTagType.SLOW_START)) if (this.getTag(BattlerTagType.SLOW_START))
ret >>= 1; ret >>= 1;
if (this.status && this.status.effect === StatusEffect.PARALYSIS) if (this.status && this.status.effect === StatusEffect.PARALYSIS)
@ -1417,7 +1423,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo); damage.value = this.damageAndUpdate(damage.value, result as DamageResult, isCritical, oneHitKo, oneHitKo);
this.turnData.damageTaken += damage.value; this.turnData.damageTaken += damage.value;
if (isCritical) if (isCritical)
this.scene.queueMessage('A critical hit!'); this.scene.queueMessage(i18next.t('battle:hitResultCriticalHit'));
this.scene.setPhaseQueueSplice(); this.scene.setPhaseQueueSplice();
if (source.isPlayer()) { if (source.isPlayer()) {
this.scene.validateAchvs(DamageAchv, damage); this.scene.validateAchvs(DamageAchv, damage);
@ -1435,16 +1441,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (source.turnData.hitsLeft === 1) { if (source.turnData.hitsLeft === 1) {
switch (result) { switch (result) {
case HitResult.SUPER_EFFECTIVE: case HitResult.SUPER_EFFECTIVE:
this.scene.queueMessage('It\'s super effective!'); this.scene.queueMessage(i18next.t('battle:hitResultSuperEffective'));
break; break;
case HitResult.NOT_VERY_EFFECTIVE: case HitResult.NOT_VERY_EFFECTIVE:
this.scene.queueMessage('It\'s not very effective…'); this.scene.queueMessage(i18next.t('battle:hitResultNotVeryEffective'));
break; break;
case HitResult.NO_EFFECT: case HitResult.NO_EFFECT:
this.scene.queueMessage(`It doesn\'t affect ${this.name}!`); this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name }));
break; break;
case HitResult.ONE_HIT_KO: case HitResult.ONE_HIT_KO:
this.scene.queueMessage('It\'s a one-hit KO!'); this.scene.queueMessage(i18next.t('battle:hitResultOneHitKO'));
break; break;
} }
} }
@ -1461,7 +1467,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier)); defendingSidePlayField.forEach((p) => applyPreDefendAbAttrs(FieldPriorityMoveImmunityAbAttr, p, source, battlerMove, cancelled, typeMultiplier));
} }
if (!typeMultiplier.value) if (!typeMultiplier.value)
this.scene.queueMessage(`It doesn\'t affect ${this.name}!`); this.scene.queueMessage(i18next.t('battle:hitResultNoEffect', { pokemonName: this.name }));
result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS; result = cancelled.value || !typeMultiplier.value ? HitResult.NO_EFFECT : HitResult.STATUS;
break; break;
} }
@ -2362,6 +2368,37 @@ export class PlayerPokemon extends Pokemon {
}); });
} }
addFriendship(friendship: integer): void {
const starterSpeciesId = this.species.getRootSpeciesId();
const fusionStarterSpeciesId = this.isFusion() ? this.fusionSpecies.getRootSpeciesId() : 0;
const starterData = [
this.scene.gameData.starterData[starterSpeciesId],
fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null
].filter(d => d);
const amount = new Utils.IntegerHolder(friendship);
const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic ? 2 : 1) / (fusionStarterSpeciesId ? 2 : 1)));
if (amount.value > 0) {
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount);
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount);
this.friendship = Math.min(this.friendship + amount.value, 255);
if (this.friendship === 255)
this.scene.validateAchv(achvs.MAX_FRIENDSHIP);
starterData.forEach((sd: StarterDataEntry, i: integer) => {
const speciesId = !i ? starterSpeciesId : fusionStarterSpeciesId as Species;
sd.friendship = (sd.friendship || 0) + starterAmount.value;
if (sd.friendship >= getStarterValueFriendshipCap(speciesStarters[speciesId])) {
this.scene.gameData.addStarterCandy(getPokemonSpecies(speciesId), 1);
sd.friendship = 0;
}
});
} else {
this.friendship = Math.max(this.friendship + amount.value, 0);
for (let sd of starterData)
sd.friendship = Math.max((sd.friendship || 0) + starterAmount.value, 0);
}
}
getPossibleEvolution(evolution: SpeciesFormEvolution): Promise<Pokemon> { getPossibleEvolution(evolution: SpeciesFormEvolution): Promise<Pokemon> {
return new Promise(resolve => { return new Promise(resolve => {
const evolutionSpecies = getPokemonSpecies(evolution.speciesId); const evolutionSpecies = getPokemonSpecies(evolution.speciesId);
@ -2428,12 +2465,17 @@ export class PlayerPokemon extends Pokemon {
private handleSpecialEvolutions(evolution: SpeciesFormEvolution) { private handleSpecialEvolutions(evolution: SpeciesFormEvolution) {
const isFusion = evolution instanceof FusionSpeciesFormEvolution; const isFusion = evolution instanceof FusionSpeciesFormEvolution;
if ((!isFusion ? this.species : this.fusionSpecies).speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) {
const newEvolution = pokemonEvolutions[this.species.speciesId][1]; const evoSpecies = (!isFusion ? this.species : this.fusionSpecies)
if (evoSpecies.speciesId === Species.NINCADA && evolution.speciesId === Species.NINJASK) {
const newEvolution = pokemonEvolutions[evoSpecies.speciesId][1];
if (newEvolution.condition.predicate(this)) { if (newEvolution.condition.predicate(this)) {
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature); const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, undefined, this.shiny, this.variant, this.ivs, this.nature);
newPokemon.natureOverride = this.natureOverride; newPokemon.natureOverride = this.natureOverride;
newPokemon.moveset = this.moveset.slice(); newPokemon.moveset = this.copyMoveset();
newPokemon.luck = this.luck;
newPokemon.fusionSpecies = this.fusionSpecies; newPokemon.fusionSpecies = this.fusionSpecies;
newPokemon.fusionFormIndex = this.fusionFormIndex; newPokemon.fusionFormIndex = this.fusionFormIndex;
newPokemon.fusionAbilityIndex = this.fusionAbilityIndex; newPokemon.fusionAbilityIndex = this.fusionAbilityIndex;
@ -2441,8 +2483,9 @@ export class PlayerPokemon extends Pokemon {
newPokemon.fusionVariant = this.fusionVariant; newPokemon.fusionVariant = this.fusionVariant;
newPokemon.fusionGender = this.fusionGender; newPokemon.fusionGender = this.fusionGender;
newPokemon.fusionLuck = this.fusionLuck; newPokemon.fusionLuck = this.fusionLuck;
this.scene.getParty().push(newPokemon); this.scene.getParty().push(newPokemon);
newPokemon.evolve(newEvolution); newPokemon.evolve(!isFusion ? newEvolution : new FusionSpeciesFormEvolution(this.id, newEvolution));
const modifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier const modifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
&& (m as PokemonHeldItemModifier).pokemonId === this.id, true) as PokemonHeldItemModifier[]; && (m as PokemonHeldItemModifier).pokemonId === this.id, true) as PokemonHeldItemModifier[];
modifiers.forEach(m => { modifiers.forEach(m => {
@ -2540,6 +2583,15 @@ export class PlayerPokemon extends Pokemon {
this.updateFusionPalette(); this.updateFusionPalette();
}); });
} }
/** Returns a deep copy of this Pokemon's moveset array */
copyMoveset(): PokemonMove[] {
let newMoveset = [];
this.moveset.forEach(move =>
newMoveset.push(new PokemonMove(move.moveId, 0, move.ppUp, move.virtual)));
return newMoveset;
}
} }
export class EnemyPokemon extends Pokemon { export class EnemyPokemon extends Pokemon {
@ -2680,7 +2732,7 @@ export class EnemyPokemon extends Pokemon {
for (let mt of moveTargets[move.id]) { for (let mt of moveTargets[move.id]) {
const target = this.scene.getField()[mt]; const target = this.scene.getField()[mt];
let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1);
if (move.name.endsWith(' (N)')) if (move.name.endsWith(' (N)') || !move.applyConditions(this, target, move))
targetScore = -20; targetScore = -20;
else if (move instanceof AttackMove) { else if (move instanceof AttackMove) {
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove); const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove);

View File

@ -67,6 +67,7 @@ export class LoadingScene extends SceneBase {
this.loadImage('achv_bar_2', 'ui'); this.loadImage('achv_bar_2', 'ui');
this.loadImage('achv_bar_3', 'ui'); this.loadImage('achv_bar_3', 'ui');
this.loadImage('achv_bar_4', 'ui'); this.loadImage('achv_bar_4', 'ui');
this.loadImage('achv_bar_5', 'ui');
this.loadImage('shiny_star', 'ui', 'shiny.png'); this.loadImage('shiny_star', 'ui', 'shiny.png');
this.loadImage('shiny_star_1', 'ui', 'shiny_1.png'); this.loadImage('shiny_star_1', 'ui', 'shiny_1.png');
this.loadImage('shiny_star_2', 'ui', 'shiny_2.png'); this.loadImage('shiny_star_2', 'ui', 'shiny_2.png');

52
src/locales/de/battle.ts Normal file
View File

@ -0,0 +1,52 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battle: SimpleTranslationEntries = {
"bossAppeared": "{{bossName}} erscheint.",
"trainerAppeared": "{{trainerName}}\nmöchte kämpfen!",
"singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!",
"multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!",
"playerComeBack": "Komm zurück, {{pokemonName}}!",
"trainerComeBack": "{{trainerName}} ruft {{pokemonName}} zurück!",
"playerGo": "Los! {{pokemonName}}!",
"trainerGo": "{{trainerName}} sendet {{pokemonName}} raus!",
"switchQuestion": "Willst du\n{{pokemonName}} auswechseln?",
"trainerDefeated": `You defeated\n{{trainerName}}!`,
"pokemonCaught": "{{pokemonName}} was caught!",
"pokemon": "Pokémon",
"sendOutPokemon": "Los! {{pokemonName}}!",
"hitResultCriticalHit": "A critical hit!",
"hitResultSuperEffective": "It's super effective!",
"hitResultNotVeryEffective": "It's not very effective…",
"hitResultNoEffect": "It doesn't affect {{pokemonName}}!",
"hitResultOneHitKO": "It's a one-hit KO!",
"attackFailed": "But it failed!",
"attackHitsCount": `Hit {{count}} time(s)!`,
"expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!",
"levelUp": "{{pokemonName}} grew to\nLv. {{level}}!",
"learnMove": "{{pokemonName}} learned\n{{moveName}}!",
"learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.",
"learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.",
"learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?",
"learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?",
"learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.",
"learnMoveForgetQuestion": "Which move should be forgotten?",
"learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.",
"levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!",
"moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.",
"moveDisabled": "{{moveName}} ist deaktiviert!",
"noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.",
"noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!",
"noPokeballMulti": "Du kannst erst einen Pokéball werden,\nwenn nur noch ein Pokémon übrig ist!",
"noPokeballStrong": "Das Ziel-Pokémon ist zu stark, um gefangen zu werden!\nDu musst es zuerst schwächen!",
"noEscapeForce": "Eine unsichtbare Kraft\nverhindert die Flucht.",
"noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!",
"noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!",
"runAwaySuccess": "You got away safely!",
"runAwayCannotEscape": 'You can\'t escape!',
"escapeVerbSwitch": "auswechseln",
"escapeVerbFlee": "flucht",
"notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!",
"skipItemQuestion": "Are you sure you want to skip taking an item?",
"eggHatching": "Oh?",
"ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?"
} as const;

View File

@ -0,0 +1,6 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const fightUiHandler: SimpleTranslationEntries = {
"pp": "PP",
"power": "POWER",
} as const;

View File

@ -35,30 +35,6 @@ export const menu: SimpleTranslationEntries = {
"boyOrGirl": "Bist du ein Junge oder ein Mädchen?", "boyOrGirl": "Bist du ein Junge oder ein Mädchen?",
"boy": "Junge", "boy": "Junge",
"girl": "Mädchen", "girl": "Mädchen",
"bossAppeared": "{{bossName}} erscheint.",
"trainerAppeared": "{{trainerName}}\nmöchte kämpfen!",
"singleWildAppeared": "Ein wildes {{pokemonName}} erscheint!",
"multiWildAppeared": "Ein wildes {{pokemonName1}}\nund {{pokemonName2}} erscheinen!",
"playerComeBack": "Komm zurück, {{pokemonName}}!",
"trainerComeBack": "{{trainerName}} ruft {{pokemonName}} zurück!",
"playerGo": "Los! {{pokemonName}}!",
"trainerGo": "{{trainerName}} sendet {{pokemonName}} raus!",
"switchQuestion": "Willst du\n{{pokemonName}} auswechseln?",
"pokemon": "Pokémon",
"sendOutPokemon": "Los! {{pokemonName}}!",
"levelCapUp": "Das Levellimit\nhat sich zu {{levelCap}} erhöht!",
"moveNotImplemented": "{{moveName}} ist noch nicht implementiert und kann nicht ausgewählt werden.",
"moveDisabled": "{{moveName}} ist deaktiviert!",
"noPokeballForce": "Eine unsichtbare Kraft\nverhindert die Nutzung von Pokébällen.",
"noPokeballTrainer": "Du kannst das Pokémon\neines anderen Trainers nicht fangen!",
"noPokeballMulti": "Du kannst erst einen Pokéball werden,\nwenn nur noch ein Pokémon übrig ist!",
"noPokeballStrong": "Das Ziel-Pokémon ist zu stark, um gefangen zu werden!\nDu musst es zuerst schwächen!",
"noEscapeForce": "Eine unsichtbare Kraft\nverhindert die Flucht.",
"noEscapeTrainer": "Du kannst nicht\naus einem Trainerkampf fliehen!",
"noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nverhindert {{escapeVerb}}!",
"escapeVerbSwitch": "auswechseln",
"escapeVerbFlee": "flucht",
"notDisabled": "{{moveName}} ist\nnicht mehr deaktiviert!",
"dailyRankings": "Daily Rankings", "dailyRankings": "Daily Rankings",
"weeklyRankings": "Weekly Rankings", "weeklyRankings": "Weekly Rankings",
"noRankings": "No Rankings", "noRankings": "No Rankings",

52
src/locales/en/battle.ts Normal file
View File

@ -0,0 +1,52 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battle: SimpleTranslationEntries = {
"bossAppeared": "{{bossName}} appeared.",
"trainerAppeared": "{{trainerName}}\nwould like to battle!",
"singleWildAppeared": "A wild {{pokemonName}} appeared!",
"multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!",
"playerComeBack": "Come back, {{pokemonName}}!",
"trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!",
"playerGo": "Go! {{pokemonName}}!",
"trainerGo": "{{trainerName}} sent out {{pokemonName}}!",
"switchQuestion": "Will you switch\n{{pokemonName}}?",
"trainerDefeated": `You defeated\n{{trainerName}}!`,
"pokemonCaught": "{{pokemonName}} was caught!",
"pokemon": "Pokémon",
"sendOutPokemon": "Go! {{pokemonName}}!",
"hitResultCriticalHit": "A critical hit!",
"hitResultSuperEffective": "It's super effective!",
"hitResultNotVeryEffective": "It's not very effective…",
"hitResultNoEffect": "It doesn't affect {{pokemonName}}!",
"hitResultOneHitKO": "It's a one-hit KO!",
"attackFailed": "But it failed!",
"attackHitsCount": `Hit {{count}} time(s)!`,
"expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!",
"levelUp": "{{pokemonName}} grew to\nLv. {{level}}!",
"learnMove": "{{pokemonName}} learned\n{{moveName}}!",
"learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.",
"learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.",
"learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?",
"learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?",
"learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.",
"learnMoveForgetQuestion": "Which move should be forgotten?",
"learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.",
"levelCapUp": "The level cap\nhas increased to {{levelCap}}!",
"moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.",
"moveDisabled": "{{moveName}} is disabled!",
"noPokeballForce": "An unseen force\nprevents using Poké Balls.",
"noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!",
"noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!",
"noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!",
"noEscapeForce": "An unseen force\nprevents escape.",
"noEscapeTrainer": "You can't run\nfrom a trainer battle!",
"noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!",
"runAwaySuccess": "You got away safely!",
"runAwayCannotEscape": 'You can\'t escape!',
"escapeVerbSwitch": "switching",
"escapeVerbFlee": "fleeing",
"notDisabled": "{{moveName}} is disabled\nno more!",
"skipItemQuestion": "Are you sure you want to skip taking an item?",
"eggHatching": "Oh?",
"ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?"
} as const;

View File

@ -35,49 +35,6 @@ export const menu: SimpleTranslationEntries = {
"boyOrGirl": "Are you a boy or a girl?", "boyOrGirl": "Are you a boy or a girl?",
"boy": "Boy", "boy": "Boy",
"girl": "Girl", "girl": "Girl",
"bossAppeared": "{{bossName}} appeared.",
"trainerAppeared": "{{trainerName}}\nwould like to battle!",
"singleWildAppeared": "A wild {{pokemonName}} appeared!",
"multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!",
"playerComeBack": "Come back, {{pokemonName}}!",
"trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!",
"playerGo": "Go! {{pokemonName}}!",
"trainerGo": "{{trainerName}} sent out {{pokemonName}}!",
"switchQuestion": "Will you switch\n{{pokemonName}}?",
"trainerDefeated": `You defeated\n{{trainerName}}!`,
"pokemonCaught": "{{pokemonName}} was caught!",
"pokemon": "Pokémon",
"sendOutPokemon": "Go! {{pokemonName}}!",
"attackFailed": "But it failed!",
"attackHitsCount": `Hit {{count}} time(s)!`,
"expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!",
"levelUp": "{{pokemonName}} grew to\nLv. {{level}}!",
"learnMove": "{{pokemonName}} learned\n{{moveName}}!",
"learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.",
"learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.",
"learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?",
"learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?",
"learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.",
"learnMoveForgetQuestion": "Which move should be forgotten?",
"learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.",
"levelCapUp": "The level cap\nhas increased to {{levelCap}}!",
"moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.",
"moveDisabled": "{{moveName}} is disabled!",
"noPokeballForce": "An unseen force\nprevents using Poké Balls.",
"noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!",
"noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!",
"noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!",
"noEscapeForce": "An unseen force\nprevents escape.",
"noEscapeTrainer": "You can't run\nfrom a trainer battle!",
"noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!",
"runAwaySuccess": "You got away safely!",
"runAwayCannotEscape": 'You can\'t escape!',
"escapeVerbSwitch": "switching",
"escapeVerbFlee": "fleeing",
"notDisabled": "{{moveName}} is disabled\nno more!",
"skipItemQuestion": "Are you sure you want to skip taking an item?",
"eggHatching": "Oh?",
"ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?",
"dailyRankings": "Daily Rankings", "dailyRankings": "Daily Rankings",
"weeklyRankings": "Weekly Rankings", "weeklyRankings": "Weekly Rankings",
"noRankings": "No Rankings", "noRankings": "No Rankings",

52
src/locales/es/battle.ts Normal file
View File

@ -0,0 +1,52 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battle: SimpleTranslationEntries = {
"bossAppeared": "¡{{bossName}} te corta el paso!",
"trainerAppeared": "¡{{trainerName}}\nte desafía!",
"singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!",
"multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!",
"playerComeBack": "¡{{pokemonName}}, ven aquí!",
"trainerComeBack": "¡{{trainerName}} retira a {{pokemonName}} del combate!",
"playerGo": "¡Adelante, {{pokemonName}}!",
"trainerGo": "¡{{trainerName}} saca a {{pokemonName}}!",
"switchQuestion": "¿Quieres cambiar a\n{{pokemonName}}?",
"trainerDefeated": "¡Has derrotado a\n{{trainerName}}!",
"pokemonCaught": "¡{{pokemonName}} atrapado!",
"pokemon": "Pokémon",
"sendOutPokemon": "¡Adelante, {{pokemonName}}!",
"hitResultCriticalHit": "A critical hit!",
"hitResultSuperEffective": "It's super effective!",
"hitResultNotVeryEffective": "It's not very effective…",
"hitResultNoEffect": "It doesn't affect {{pokemonName}}!",
"hitResultOneHitKO": "It's a one-hit KO!",
"attackFailed": "¡Pero ha fallado!",
"attackHitsCount": `N.º de golpes: {{count}}.`,
"expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.",
"levelUp": "¡{{pokemonName}} ha subido al \nNv. {{level}}!",
"learnMove": "¡{{pokemonName}} ha aprendido {{moveName}}!",
"learnMovePrompt": "{{pokemonName}} quiere aprender {{moveName}}.",
"learnMoveLimitReached": "Pero, {{pokemonName}} ya conoce\ncuatro movimientos.",
"learnMoveReplaceQuestion": "¿Quieres sustituir uno de sus movimientos por {{moveName}}?",
"learnMoveStopTeaching": "¿Prefieres que no aprenda\n{{moveName}}?",
"learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.",
"learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?",
"learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.",
"levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!",
"moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.",
"moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!",
"noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.",
"noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!",
"noPokeballMulti": "¡No se pueden lanzar Poké Balls\ncuando hay más de un Pokémon!",
"noPokeballStrong": "¡Este Pokémon es demasiado fuerte para ser capturado!\nNecesitas bajarle los PS primero!",
"noEscapeForce": "Una fuerza misteriosa\nte impide huir.",
"noEscapeTrainer": "¡No puedes huir de los\ncombates contra Entrenadores!",
"noEscapePokemon": "¡El movimiento {{moveName}} de {{pokemonName}} impide la huida!",
"runAwaySuccess": "¡Escapas sin problemas!",
"runAwayCannotEscape": "¡No has podido escapar!",
"escapeVerbSwitch": "cambiar",
"escapeVerbFlee": "huir",
"notDisabled": "¡El movimiento {{moveName}}\nya no está anulado!",
"skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?",
"eggHatching": "¿Y esto?",
"ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?"
} as const;

View File

@ -0,0 +1,6 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const fightUiHandler: SimpleTranslationEntries = {
"pp": "PP",
"power": "POTENCIA",
} as const;

View File

@ -19,49 +19,6 @@ export const menu: SimpleTranslationEntries = {
"boyOrGirl": "¿Eres un chico o una chica?", "boyOrGirl": "¿Eres un chico o una chica?",
"boy": "Chico", "boy": "Chico",
"girl": "Chica", "girl": "Chica",
"bossAppeared": "¡{{bossName}} te corta el paso!",
"trainerAppeared": "¡{{trainerName}}\nte desafía!",
"singleWildAppeared": "¡Un {{pokemonName}} salvaje te corta el paso!",
"multiWildAppeared": "¡Un {{pokemonName1}} y un {{pokemonName2}} salvajes\nte cortan el paso!",
"playerComeBack": "¡{{pokemonName}}, ven aquí!",
"trainerComeBack": "¡{{trainerName}} retira a {{pokemonName}} del combate!",
"playerGo": "¡Adelante, {{pokemonName}}!",
"trainerGo": "¡{{trainerName}} saca a {{pokemonName}}!",
"switchQuestion": "¿Quieres cambiar a\n{{pokemonName}}?",
"trainerDefeated": "¡Has derrotado a\n{{trainerName}}!",
"pokemonCaught": "¡{{pokemonName}} atrapado!",
"pokemon": "Pokémon",
"sendOutPokemon": "¡Adelante, {{pokemonName}}!",
"attackFailed": "¡Pero ha fallado!",
"attackHitsCount": `N.º de golpes: {{count}}.`,
"expGain": "{{pokemonName}} ha ganado\n{{exp}} puntos de experiencia.",
"levelUp": "¡{{pokemonName}} ha subido al \nNv. {{level}}!",
"learnMove": "¡{{pokemonName}} ha aprendido {{moveName}}!",
"learnMovePrompt": "{{pokemonName}} quiere aprender {{moveName}}.",
"learnMoveLimitReached": "Pero, {{pokemonName}} ya conoce\ncuatro movimientos.",
"learnMoveReplaceQuestion": "¿Quieres sustituir uno de sus movimientos por {{moveName}}?",
"learnMoveStopTeaching": "¿Prefieres que no aprenda\n{{moveName}}?",
"learnMoveNotLearned": "{{pokemonName}} no ha aprendido {{moveName}}.",
"learnMoveForgetQuestion": "¿Qué movimiento quieres que olvide?",
"learnMoveForgetSuccess": "{{pokemonName}} ha olvidado cómo utilizar {{moveName}}.",
"levelCapUp": "¡Se ha incrementado el\nnivel máximo a {{levelCap}}!",
"moveNotImplemented": "{{moveName}} aún no está implementado y no se puede seleccionar.",
"moveDisabled": "!No puede usar {{moveName}} porque ha sido anulado!",
"noPokeballForce": "Una fuerza misteriosa\nte impide usar Poké Balls.",
"noPokeballTrainer": "¡No puedes atrapar a los\nPokémon de los demás!",
"noPokeballMulti": "¡No se pueden lanzar Poké Balls\ncuando hay más de un Pokémon!",
"noPokeballStrong": "¡Este Pokémon es demasiado fuerte para ser capturado!\nNecesitas bajarle los PS primero!",
"noEscapeForce": "Una fuerza misteriosa\nte impide huir.",
"noEscapeTrainer": "¡No puedes huir de los\ncombates contra Entrenadores!",
"noEscapePokemon": "¡El movimiento {{moveName}} de {{pokemonName}} impide la huida!",
"runAwaySuccess": "¡Escapas sin problemas!",
"runAwayCannotEscape": "¡No has podido escapar!",
"escapeVerbSwitch": "cambiar",
"escapeVerbFlee": "huir",
"notDisabled": "¡El movimiento {{moveName}}\nya no está anulado!",
"skipItemQuestion": "¿Estás seguro de que no quieres coger un objeto?",
"eggHatching": "¿Y esto?",
"ivScannerUseQuestion": "¿Quieres usar el Escáner de IVs en {{pokemonName}}?",
"dailyRankings": "Daily Rankings", "dailyRankings": "Daily Rankings",
"weeklyRankings": "Weekly Rankings", "weeklyRankings": "Weekly Rankings",
"noRankings": "No Rankings", "noRankings": "No Rankings",

52
src/locales/fr/battle.ts Normal file
View File

@ -0,0 +1,52 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battle: SimpleTranslationEntries = {
"bossAppeared": "Un {{bossName}} apparaît.",
"trainerAppeared": "Un combat est lancé\npar {{trainerName}} !",
"singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !",
"multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !",
"playerComeBack": "{{pokemonName}}, on change !\nReviens !",
"trainerComeBack": "{{trainerName}} retire {{pokemonName}} !",
"playerGo": "{{pokemonName}} ! Go !",
"trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !",
"switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?",
"trainerDefeated": `Vous avez battu\n{{trainerName}} !`,
"pokemonCaught": "Vous avez attrapé {{pokemonName}} !",
"pokemon": "Pokémon",
"sendOutPokemon": "{{pokemonName}} ! Go !",
"hitResultCriticalHit": "Coup critique!",
"hitResultSuperEffective": "Cest super efficace!",
"hitResultNotVeryEffective": "Ce nest pas très efficace…",
"hitResultNoEffect": "Ça naffecte pas {{pokemonName}}…",
"hitResultOneHitKO": "K.O. en un coup!",
"attackFailed": "Mais cela échoue !",
"attackHitsCount": `Touché {{count}} fois !`,
"expGain": "{{pokemonName}} gagne\n{{exp}} Points dExp !",
"levelUp": "{{pokemonName}} monte au\nN. {{level}} !",
"learnMove": "{{pokemonName}} apprend \n{{moveName}} !",
"learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.",
"learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.",
"learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?",
"learnMoveStopTeaching": "Arrêter dapprendre\n{{moveName}} ?",
"learnMoveNotLearned": "{{pokemonName}} na pas appris\n{{moveName}}.",
"learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?",
"learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.",
"levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !",
"moveNotImplemented": "{{moveName}} nest pas encore implémenté et ne peut pas être sélectionné.",
"moveDisabled": "{{moveName}} est sous entrave !",
"noPokeballForce": "Une force mystérieuse\nempêche lutilisation des Poké Balls.",
"noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, cest mal !",
"noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon!",
"noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez dabord laffaiblir !",
"noEscapeForce": "Une force mystérieuse\nempêche la fuite.",
"noEscapeTrainer": "On ne senfuit pas dun\ncombat de Dresseurs !",
"noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !",
"runAwaySuccess": "Vous prenez la fuite !",
"runAwayCannotEscape": "Fuite impossible !",
"escapeVerbSwitch": "le changement",
"escapeVerbFlee": "la fuite",
"notDisabled": "{{moveName}} nest plus sous entrave !",
"skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre dobjet ?",
"eggHatching": "Oh ?",
"ivScannerUseQuestion": "Utiliser le Scanner dIV sur {{pokemonName}} ?"
} as const;

View File

@ -30,49 +30,6 @@ export const menu: SimpleTranslationEntries = {
"boyOrGirl": "Es-tu un garçon ou une fille ?", "boyOrGirl": "Es-tu un garçon ou une fille ?",
"boy": "Garçon", "boy": "Garçon",
"girl": "Fille", "girl": "Fille",
"bossAppeared": "Un {{bossName}} apparaît.",
"trainerAppeared": "Un combat est lancé\npar {{trainerName}} !",
"singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !",
"multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !",
"playerComeBack": "{{pokemonName}}, on change !\nReviens !",
"trainerComeBack": "{{trainerName}} retire {{pokemonName}} !",
"playerGo": "{{pokemonName}} ! Go !",
"trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !",
"switchQuestion": "Voulez-vous changer\n{{pokemonName}} ?",
"trainerDefeated": `Vous avez battu\n{{trainerName}} !`,
"pokemonCaught": "Vous avez attrapé {{pokemonName}} !",
"pokemon": "Pokémon",
"sendOutPokemon": "{{pokemonName}} ! Go !",
"attackFailed": "Mais cela échoue !",
"attackHitsCount": `Touché {{count}} fois !`,
"expGain": "{{pokemonName}} gagne\n{{exp}} Points dExp !",
"levelUp": "{{pokemonName}} monte au\nN. {{level}} !",
"learnMove": "{{pokemonName}} apprend \n{{moveName}} !",
"learnMovePrompt": "{{pokemonName}} veut apprendre\n{{moveName}}.",
"learnMoveLimitReached": "Cependant, {{pokemonName}} connait\ndéjà quatre capacités.",
"learnMoveReplaceQuestion": "Voulez-vous oublier une capacité\net la remplacer par {{moveName}} ?",
"learnMoveStopTeaching": "Arrêter dapprendre\n{{moveName}} ?",
"learnMoveNotLearned": "{{pokemonName}} na pas appris\n{{moveName}}.",
"learnMoveForgetQuestion": "Quelle capacité doit être oubliée ?",
"learnMoveForgetSuccess": "{{pokemonName}} oublie comment\nutiliser {{moveName}}.",
"levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !",
"moveNotImplemented": "{{moveName}} nest pas encore implémenté et ne peut pas être sélectionné.",
"moveDisabled": "{{moveName}} est sous entrave !",
"noPokeballForce": "Une force mystérieuse\nempêche lutilisation des Poké Balls.",
"noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, cest mal !",
"noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon!",
"noPokeballStrong": "Le Pokémon est trop fort pour être capturé !\nVous devez dabord laffaiblir !",
"noEscapeForce": "Une force mystérieuse\nempêche la fuite.",
"noEscapeTrainer": "On ne senfuit pas dun\ncombat de Dresseurs !",
"noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !",
"runAwaySuccess": "Vous prenez la fuite !",
"runAwayCannotEscape": "Fuite impossible !",
"escapeVerbSwitch": "le changement",
"escapeVerbFlee": "la fuite",
"notDisabled": "{{moveName}} nest plus sous entrave !",
"skipItemQuestion": "Êtes-vous sûr·e de ne pas vouloir prendre dobjet ?",
"eggHatching": "Oh ?",
"ivScannerUseQuestion": "Utiliser le Scanner dIV sur {{pokemonName}} ?",
"dailyRankings": "Classement du Jour", "dailyRankings": "Classement du Jour",
"weeklyRankings": "Classement de la Semaine", "weeklyRankings": "Classement de la Semaine",
"noRankings": "Pas de Classement", "noRankings": "Pas de Classement",

View File

@ -8,7 +8,7 @@ export const tutorial: SimpleTranslationEntries = {
$Tout signalement de bugs passe par le serveur Discord. $Tout signalement de bugs passe par le serveur Discord.
$Si le jeu est lent, vérifiez que lAccélération Matérielle est activée dans les paramètres du navigateur.`, $Si le jeu est lent, vérifiez que lAccélération Matérielle est activée dans les paramètres du navigateur.`,
"accessMenu": `Accédez au menu avec M ou Échap lors de l'attente dune\naction. "accessMenu": `Accédez au menu avec M ou Échap lors de lattente dune\naction.
$Il contient les paramètres et diverses fonctionnalités`, $Il contient les paramètres et diverses fonctionnalités`,
"menu": `Vous pouvez accéder aux paramètres depuis ce menu. "menu": `Vous pouvez accéder aux paramètres depuis ce menu.
@ -17,7 +17,7 @@ export const tutorial: SimpleTranslationEntries = {
$jetez-y un œil !`, $jetez-y un œil !`,
"starterSelect": `Choisissez vos starters depuis cet écran.\nIls formeront votre équipe de départ. "starterSelect": `Choisissez vos starters depuis cet écran.\nIls formeront votre équipe de départ.
$Chacun possède une valeur. Votre équipe peut avoir jusquà\n6 membres, tant que vous ne dépassez pas un coût de 10. $Chacun possède une valeur. Votre équipe peut avoir jusquà\n6 membres, tant que vous ne dépassez pas un cout de 10.
$Vous pouvez aussi choisir le sexe, le talent et la forme en\nfonction des variants déjà capturés ou éclos. $Vous pouvez aussi choisir le sexe, le talent et la forme en\nfonction des variants déjà capturés ou éclos.
$Les IVs dun starter sont les meilleurs de tous ceux de son\nespèce déjà obtenus. Essayez donc den obtenir plusieurs !`, $Les IVs dun starter sont les meilleurs de tous ceux de son\nespèce déjà obtenus. Essayez donc den obtenir plusieurs !`,
@ -25,9 +25,12 @@ export const tutorial: SimpleTranslationEntries = {
$violet. Si un starter que vous possédez la, essayez de $violet. Si un starter que vous possédez la, essayez de
$lajouter à votre équipe. Vérifiez bien son résumé !`, $lajouter à votre équipe. Vérifiez bien son résumé !`,
"statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. "statChange": `Les changements de stats restent à travers les combats tant que le Pokémon
$Your Pokémon are recalled before a trainer battle and before entering a new biome. $nest pas rappelé.
$You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, $Vos Pokémon sont rappelés avant un combat de Dresseur et avant dentrer
$dans un nouveau biome.
$Vous pouvez également voir en combat les changements de stats dun Pokémon
$en maintenant C ou Maj.`,
"selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre quun. "selectItem": `Après chaque combat, vous avez le choix entre 3 objets\ntirés au sort. Vous ne pouvez en prendre quun.
$Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents. $Cela peut être des objets consommables, des objets à\nfaire tenir, ou des objets passifs aux effets permanents.

52
src/locales/it/battle.ts Normal file
View File

@ -0,0 +1,52 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battle: SimpleTranslationEntries = {
"bossAppeared": "{{bossName}} appeared.",
"trainerAppeared": "{{trainerName}}\nwould like to battle!",
"singleWildAppeared": "A wild {{pokemonName}} appeared!",
"multiWildAppeared": "A wild {{pokemonName1}}\nand {{pokemonName2}} appeared!",
"playerComeBack": "Come back, {{pokemonName}}!",
"trainerComeBack": "{{trainerName}} withdrew {{pokemonName}}!",
"playerGo": "Go! {{pokemonName}}!",
"trainerGo": "{{trainerName}} sent out {{pokemonName}}!",
"switchQuestion": "Will you switch\n{{pokemonName}}?",
"trainerDefeated": `You defeated\n{{trainerName}}!`,
"pokemonCaught": "{{pokemonName}} was caught!",
"pokemon": "Pokémon",
"sendOutPokemon": "Go! {{pokemonName}}!",
"hitResultCriticalHit": "A critical hit!",
"hitResultSuperEffective": "It's super effective!",
"hitResultNotVeryEffective": "It's not very effective…",
"hitResultNoEffect": "It doesn't affect {{pokemonName}}!",
"hitResultOneHitKO": "It's a one-hit KO!",
"attackFailed": "But it failed!",
"attackHitsCount": `Hit {{count}} time(s)!`,
"expGain": "{{pokemonName}} gained\n{{exp}} EXP. Points!",
"levelUp": "{{pokemonName}} grew to\nLv. {{level}}!",
"learnMove": "{{pokemonName}} learned\n{{moveName}}!",
"learnMovePrompt": "{{pokemonName}} wants to learn the\nmove {{moveName}}.",
"learnMoveLimitReached": "However, {{pokemonName}} already\nknows four moves.",
"learnMoveReplaceQuestion": "Should a move be forgotten and\nreplaced with {{moveName}}?",
"learnMoveStopTeaching": "Stop trying to teach\n{{moveName}}?",
"learnMoveNotLearned": "{{pokemonName}} did not learn the\nmove {{moveName}}.",
"learnMoveForgetQuestion": "Which move should be forgotten?",
"learnMoveForgetSuccess": "{{pokemonName}} forgot how to\nuse {{moveName}}.",
"levelCapUp": "The level cap\nhas increased to {{levelCap}}!",
"moveNotImplemented": "{{moveName}} is not yet implemented and cannot be selected.",
"moveDisabled": "{{moveName}} is disabled!",
"noPokeballForce": "An unseen force\nprevents using Poké Balls.",
"noPokeballTrainer": "You can't catch\nanother trainer's Pokémon!",
"noPokeballMulti": "You can only throw a Poké Ball\nwhen there is one Pokémon remaining!",
"noPokeballStrong": "The target Pokémon is too strong to be caught!\nYou need to weaken it first!",
"noEscapeForce": "An unseen force\nprevents escape.",
"noEscapeTrainer": "You can't run\nfrom a trainer battle!",
"noEscapePokemon": "{{pokemonName}}'s {{moveName}}\nprevents {{escapeVerb}}!",
"runAwaySuccess": "You got away safely!",
"runAwayCannotEscape": 'You can\'t escape!',
"escapeVerbSwitch": "switching",
"escapeVerbFlee": "fleeing",
"notDisabled": "{{moveName}} is disabled\nno more!",
"skipItemQuestion": "Are you sure you want to skip taking an item?",
"eggHatching": "Oh?",
"ivScannerUseQuestion": "Use IV Scanner on {{pokemonName}}?"
} as const;

View File

@ -0,0 +1,6 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const fightUiHandler: SimpleTranslationEntries = {
"pp": "PP",
"power": "POWER",
} as const;

View File

@ -1,5 +1,10 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
/**
* The menu namespace holds most miscellaneous text that isn't directly part of the game's
* contents or directly related to Pokemon data. This includes menu navigation, settings,
* account interactions, descriptive text, etc.
*/
export const menu: SimpleTranslationEntries = { export const menu: SimpleTranslationEntries = {
"cancel": "Annulla", "cancel": "Annulla",
"continue": "Continua", "continue": "Continua",
@ -7,6 +12,29 @@ export const menu: SimpleTranslationEntries = {
"loadGame": "Carica Partita", "loadGame": "Carica Partita",
"dailyRun": "Corsa Giornaliera (Beta)", "dailyRun": "Corsa Giornaliera (Beta)",
"selectGameMode": "Seleziona una modalità di gioco.", "selectGameMode": "Seleziona una modalità di gioco.",
"logInOrCreateAccount": "Log in or create an account to start. No email required!",
"username": "Username",
"password": "Password",
"login": "Login",
"register": "Register",
"emptyUsername": "Username must not be empty",
"invalidLoginUsername": "The provided username is invalid",
"invalidRegisterUsername": "Username must only contain letters, numbers, or underscores",
"invalidLoginPassword": "The provided password is invalid",
"invalidRegisterPassword": "Password must be 6 characters or longer",
"usernameAlreadyUsed": "The provided username is already in use",
"accountNonExistent": "The provided user does not exist",
"unmatchingPassword": "The provided password does not match",
"passwordNotMatchingConfirmPassword": "Password must match confirm password",
"confirmPassword": "Confirm Password",
"registrationAgeWarning": "By registering, you confirm you are of 13 years of age or older.",
"backToLogin": "Back to Login",
"failedToLoadSaveData": "Failed to load save data. Please reload the page.\nIf this continues, please contact the administrator.",
"sessionSuccess": "Session loaded successfully.",
"failedToLoadSession": "Your session data could not be loaded.\nIt may be corrupted.",
"boyOrGirl": "Are you a boy or a girl?",
"boy": "Boy",
"girl": "Girl",
"dailyRankings": "Daily Rankings", "dailyRankings": "Daily Rankings",
"weeklyRankings": "Weekly Rankings", "weeklyRankings": "Weekly Rankings",
"noRankings": "No Rankings", "noRankings": "No Rankings",

View File

@ -1,16 +1,16 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const pokemonStat: SimpleTranslationEntries = { export const pokemonStat: SimpleTranslationEntries = {
"HP": "Max. HP", "HP": "PS Max",
"HPshortened": "MaxHP", "HPshortened": "PS",
"ATK": "Attack", "ATK": "Attacco",
"ATKshortened": "Atk", "ATKshortened": "Att",
"DEF": "Defense", "DEF": "Difesa",
"DEFshortened": "Def", "DEFshortened": "Dif",
"SPATK": "Sp. Atk", "SPATK": "Att. Sp.",
"SPATKshortened": "SpAtk", "SPATKshortened": "AttSp",
"SPDEF": "Sp. Def", "SPDEF": "Dif. Sp.",
"SPDEFshortened": "SpDef", "SPDEFshortened": "DifSp",
"SPD": "Speed", "SPD": "Velocità",
"SPDshortened": "Spd" "SPDshortened": "Vel"
} as const; } as const;

View File

@ -1,42 +1,42 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const tutorial: SimpleTranslationEntries = { export const tutorial: SimpleTranslationEntries = {
"intro": `Welcome to PokéRogue! This is a battle-focused Pokémon fangame with roguelite elements. "intro": `Benvenuto in PokéRogue! Questo gioco si concentra sulle battaglie, con elementi roguelite.
$This game is not monetized and we claim no ownership of Pokémon nor of the copyrighted assets used. $Questo gioco non è monetizzato e non siamo proprietari di Pokemon e Assets presenti nel gioco.
$The game is a work in progress, but fully playable.\nFor bug reports, please use the Discord community. $Il gioco è work-in-progress ma giocabile al 100%.\nPer reportare eventuali bugs è possibile discuterne sul nostro Discord.
$If the game runs slowly, please ensure 'Hardware Acceleration' is turned on in your browser settings.`, $Se il game risulta 'lento', assicurati di aver abilitato l'Accelerazione Hardware nelle impostazioni del tuo Browser`,
"accessMenu": `To access the menu, press M or Escape while awaiting input.\nThe menu contains settings and various features.`, "accessMenu": `Per accedere al menù, press M o Esc.\nDal menù puoi cambiare impostazioni, controllare la wiki e accedere a varie features.`,
"menu": `From this menu you can access the settings. "menu": `Da questo menù puoi accedere alle impostazioni.
$From the settings you can change game speed, window style, and other options. $Dalle impostazioni puoi cambiare velocità di gioco, stile di finestra e altre opzioni.
$There are also various other features here, so be sure to check them all!`, $Ci sono varie funzionalità, controlla bene e non perderti nulla!`,
"starterSelect": `From this screen, you can select your starters.\nThese are your initial party members. "starterSelect": `Da questa schermata puoi selezionare il tuo starter.\nQuesti sono i membri iniziali del tuo parti.
$Each starter has a value. Your party can have up to\n6 members as long as the total does not exceed 10. $Ogni starter ha un valore. Puoi avere fino a \n6 Pokèmon, avendo a disposizione un massimo di 10 punti.
$You can also select gender, ability, and form depending on\nthe variants you've caught or hatched. $Puoi anche selezionare Sesso, Abilità, e Forma a seconda delle\nvarianti che hai catturato o schiuso.
$The IVs for a species are also the best of every one you've\ncaught or hatched, so try to get lots of the same species!`, $Le IVs di una specie sono le migliori rispetto a tutte quelle che hai\ncatturato o schiuso, quindi prova a catturarne il piu possibile!`,
"pokerus": `A daily random 3 selectable starters have a purple border. "pokerus": `Giornalmente 3 Starter casuali disponibili avranno il bordo viola.
$If you see a starter you own with one of these,\ntry adding it to your party. Be sure to check its summary!`, $Se possiedi uno di questi starter,\nprova ad aggiungerlo al party. Ricorda di controllare le info!`,
"statChange": `Stat changes persist across battles as long as your Pokémon aren't recalled. "statChange": `I cambiamenti alle statistiche persistono fintanto che i tuoi pokèmon resteranno in campo.
$Your Pokémon are recalled before a trainer battle and before entering a new biome. $I tuoi pokemon verranno richiamati quando incontrerai un allenatore o al cambiamento di bioma.
$You can also view the stat changes for the Pokémon on the field by holding C or Shift.`, $Puoi anche vedere i cambiamenti alle statistiche in corso tenendo premuto C o Shift`,
"selectItem": `After every battle, you are given a choice of 3 random items.\nYou may only pick one. "selectItem": `Dopo ogni battaglia avrai disponibili tre item.\nPotrai prenderne solo uno.
$These range from consumables, to Pokémon held items, to passive permanent items. $Questi spaziano tra consumabili, item tenuti da Pokèmon o con un effetto passivo permanente.
$Most non-consumable item effects will stack in various ways. $La maggior parte degli Item non Consumabili possono stackare in diversi modi.
$Some items will only show up if they can be used, such as evolution items. $Alcuni Item risulteranno disponibili solo se possono essere usati, come Item Evolutivi.
$You can also transfer held items between Pokémon using the transfer option. $Puoi anche passare un Item tenuto da un Pokèmon ad un altro attraverso l'opzione 'trasferisci strumento'.
$The transfer option will appear in the bottom right once you have obtained a held item. $L'opzione 'trasferisci strumento' sarà disponibile solo dopo aver assegnato uno strumento ad un Pokèmon.
$You may purchase consumable items with money, and a larger variety will be available the further you get. $Puoi acquistare consumabili con le monete, progredendo saranno poi disponibili ulteriori oggetti.
$Be sure to buy these before you pick your random item, as it will progress to the next battle once you do.`, $Assicurati di fare un acquisto prima di selezionare un item casuale, poichè passerai subito alla lotta successiva.`,
"eggGacha": `From this screen, you can redeem your vouchers for\nPokémon eggs. "eggGacha": `Da questa schermata, puoi riscattare i tuoi vouchers in cambio di\nuova Pokèmon.
$Eggs have to be hatched and get closer to hatching after\nevery battle. Rarer eggs take longer to hatch. $Le uova vanno schiuse e saranno sempre più vicine alla schiusura dopo\nogni battaglia. Le uova più rare impiegheranno più battaglie per la schiusura.
$Hatched Pokémon also won't be added to your party, they will\nbe added to your starters. $I Pokémon schiusi non verranno aggiunti alla tua squadra, saranno\naggiunti ai tuoi starters.
$Pokémon hatched from eggs generally have better IVs than\nwild Pokémon. $I Pokémon schiusi generalmente hanno IVs migliori rispetto ai\n Pokémon selvatici.
$Some Pokémon can only even be obtained from eggs. $Alcuni Pokémon possono essere ottenuti solo tramite uova.
$There are 3 different machines to pull from with different\nbonuses, so pick the one that suits you best!`, $Ci sono 3 diversi macchinari con differenti\nbonus, scegli quello che preferisci!`,
} as const; } as const;

View File

@ -9,6 +9,23 @@ import BBCodeText from 'phaser3-rex-plugins/plugins/bbcodetext';
import TransitionImagePackPlugin from 'phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin.js'; import TransitionImagePackPlugin from 'phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin.js';
import { LoadingScene } from './loading-scene'; import { LoadingScene } from './loading-scene';
// Catch global errors and display them in an alert so users can report the issue.
window.onerror = function (message, source, lineno, colno, error) {
console.error(error);
let errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`;
//alert(errorString);
// Avoids logging the error a second time.
return true;
};
// Catch global promise rejections and display them in an alert so users can report the issue.
window.addEventListener('unhandledrejection', (event) => {
let errorString = `Received unhandled promise rejection. Open browser console and click OK to see details.\nReason: ${event.reason}`;
console.error(event.reason);
//alert(errorString);
});
const config: Phaser.Types.Core.GameConfig = { const config: Phaser.Types.Core.GameConfig = {
type: Phaser.WEBGL, type: Phaser.WEBGL,
parent: 'app', parent: 'app',

View File

@ -1058,7 +1058,6 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10), new WeightedModifierType(modifierTypes.ATTACK_TYPE_BOOSTER, 10),
new WeightedModifierType(modifierTypes.TM_ULTRA, 8), new WeightedModifierType(modifierTypes.TM_ULTRA, 8),
new WeightedModifierType(modifierTypes.RARER_CANDY, 4), new WeightedModifierType(modifierTypes.RARER_CANDY, 4),
new WeightedModifierType(modifierTypes.SOOTHE_BELL, (party: Pokemon[]) => party.find(p => (pokemonEvolutions.hasOwnProperty(p.species.speciesId) && pokemonEvolutions[p.species.speciesId].find(e => e.condition && e.condition instanceof SpeciesFriendshipEvolutionCondition)) || p.moveset.find(m => m.moveId === Moves.RETURN)) ? 16 : 0, 16),
new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 2), new WeightedModifierType(modifierTypes.GOLDEN_PUNCH, 2),
new WeightedModifierType(modifierTypes.IV_SCANNER, 4), new WeightedModifierType(modifierTypes.IV_SCANNER, 4),
new WeightedModifierType(modifierTypes.EXP_CHARM, 8), new WeightedModifierType(modifierTypes.EXP_CHARM, 8),
@ -1078,6 +1077,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.BATON, 2), new WeightedModifierType(modifierTypes.BATON, 2),
new WeightedModifierType(modifierTypes.SOUL_DEW, 8), new WeightedModifierType(modifierTypes.SOUL_DEW, 8),
//new WeightedModifierType(modifierTypes.OVAL_CHARM, 6), //new WeightedModifierType(modifierTypes.OVAL_CHARM, 6),
new WeightedModifierType(modifierTypes.SOOTHE_BELL, 4),
new WeightedModifierType(modifierTypes.ABILITY_CHARM, 6), new WeightedModifierType(modifierTypes.ABILITY_CHARM, 6),
new WeightedModifierType(modifierTypes.FOCUS_BAND, 5), new WeightedModifierType(modifierTypes.FOCUS_BAND, 5),
new WeightedModifierType(modifierTypes.KINGS_ROCK, 3), new WeightedModifierType(modifierTypes.KINGS_ROCK, 3),

View File

@ -1111,9 +1111,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
pokemon.levelExp = 0; pokemon.levelExp = 0;
} }
const friendshipIncrease = new Utils.IntegerHolder(5); pokemon.addFriendship(5);
pokemon.scene.applyModifier(PokemonFriendshipBoosterModifier, true, pokemon, friendshipIncrease);
pokemon.friendship = Math.min(pokemon.friendship + friendshipIncrease.value, 255);
pokemon.scene.unshiftPhase(new LevelUpPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.level - levelCount.value, pokemon.level)); pokemon.scene.unshiftPhase(new LevelUpPhase(pokemon.scene, pokemon.scene.getParty().indexOf(pokemon), pokemon.level - levelCount.value, pokemon.level));
@ -1392,13 +1390,14 @@ export class PokemonFriendshipBoosterModifier extends PokemonHeldItemModifier {
} }
apply(args: any[]): boolean { apply(args: any[]): boolean {
(args[1] as Utils.IntegerHolder).value *= 1 + 0.5 * this.getStackCount(); const friendship = args[1] as Utils.IntegerHolder;
friendship.value = Math.floor(friendship.value * (1 + 0.5 * this.getStackCount()));
return true; return true;
} }
getMaxHeldItemCount(pokemon: Pokemon): integer { getMaxHeldItemCount(pokemon: Pokemon): integer {
return 5; return 3;
} }
} }

View File

@ -6,7 +6,7 @@ import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMov
import { Mode } from './ui/ui'; import { Mode } from './ui/ui';
import { Command } from "./ui/command-ui-handler"; import { Command } from "./ui/command-ui-handler";
import { Stat } from "./data/pokemon-stat"; import { Stat } from "./data/pokemon-stat";
import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, PokemonFriendshipBoosterModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier"; import { BerryModifier, ContactHeldItemTransferChanceModifier, EnemyAttackStatusEffectChanceModifier, EnemyPersistentModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, HealingBoosterModifier, HitHealModifier, LapsingPersistentModifier, MapModifier, Modifier, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, PokemonHeldItemModifier, PokemonInstantReviveModifier, SwitchEffectTransferModifier, TempBattleStatBoosterModifier, TurnHealModifier, TurnHeldItemTransferModifier, MoneyMultiplierModifier, MoneyInterestModifier, IvScannerModifier, LapsingPokemonHeldItemModifier, PokemonMultiHitModifier, PokemonMoveAccuracyBoosterModifier } from "./modifier/modifier";
import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler"; import PartyUiHandler, { PartyOption, PartyUiMode } from "./ui/party-ui-handler";
import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball"; import { doPokeballBounceAnim, getPokeballAtlasKey, getPokeballCatchMultiplier, getPokeballTintColor, PokeballType } from "./data/pokeball";
import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims"; import { CommonAnim, CommonBattleAnim, MoveAnim, initMoveAnim, loadMoveAnimAssets } from "./data/battle-anims";
@ -331,6 +331,8 @@ export class TitlePhase extends Phase {
this.scene.sessionPlayTime = 0; this.scene.sessionPlayTime = 0;
this.end(); this.end();
}); });
}).catch(err => {
console.error("Failed to load daily run:\n", err);
}); });
}); });
} }
@ -815,14 +817,14 @@ export class EncounterPhase extends BattlePhase {
const enemyField = this.scene.getEnemyField(); const enemyField = this.scene.getEnemyField();
if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS)
return i18next.t('menu:bossAppeared', {bossName: enemyField[0].name}); return i18next.t('battle:bossAppeared', {bossName: enemyField[0].name});
if (this.scene.currentBattle.battleType === BattleType.TRAINER) if (this.scene.currentBattle.battleType === BattleType.TRAINER)
return i18next.t('menu:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)}); return i18next.t('battle:trainerAppeared', {trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true)});
return enemyField.length === 1 return enemyField.length === 1
? i18next.t('menu:singleWildAppeared', {pokemonName: enemyField[0].name}) ? i18next.t('battle:singleWildAppeared', {pokemonName: enemyField[0].name})
: i18next.t('menu:multiWildAppeared', {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name}) : i18next.t('battle:multiWildAppeared', {pokemonName1: enemyField[0].name, pokemonName2: enemyField[1].name})
} }
doEncounterCommon(showEncounterMessage: boolean = true) { doEncounterCommon(showEncounterMessage: boolean = true) {
@ -1187,7 +1189,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
} }
if (this.player) { if (this.player) {
this.scene.ui.showText(i18next.t('menu:playerGo', { pokemonName: this.getPokemon().name })); this.scene.ui.showText(i18next.t('battle:playerGo', { pokemonName: this.getPokemon().name }));
if (this.player) if (this.player)
this.scene.pbTray.hide(); 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 === PlayerGender.FEMALE ? 'f' : 'm'}_back_pb`);
@ -1355,8 +1357,8 @@ export class SwitchSummonPhase extends SummonPhase {
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, pokemon); applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, pokemon);
this.scene.ui.showText(this.player ? this.scene.ui.showText(this.player ?
i18next.t('menu:playerComeBack', { pokemonName: pokemon.name }) : i18next.t('battle:playerComeBack', { pokemonName: pokemon.name }) :
i18next.t('menu:trainerComeBack', { i18next.t('battle:trainerComeBack', {
trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER),
pokemonName: pokemon.name pokemonName: pokemon.name
}) })
@ -1396,8 +1398,8 @@ export class SwitchSummonPhase extends SummonPhase {
party[this.fieldIndex] = switchedPokemon; party[this.fieldIndex] = switchedPokemon;
const showTextAndSummon = () => { const showTextAndSummon = () => {
this.scene.ui.showText(this.player ? this.scene.ui.showText(this.player ?
i18next.t('menu:playerGo', { pokemonName: switchedPokemon.name }) : i18next.t('battle:playerGo', { pokemonName: switchedPokemon.name }) :
i18next.t('menu:trainerGo', { i18next.t('battle:trainerGo', {
trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER),
pokemonName: this.getPokemon().name pokemonName: this.getPokemon().name
}) })
@ -1544,7 +1546,7 @@ export class CheckSwitchPhase extends BattlePhase {
return; return;
} }
this.scene.ui.showText(i18next.t('menu:switchQuestion', { pokemonName: this.useName ? pokemon.name : i18next.t('menu:pokemon') }), null, () => { this.scene.ui.showText(i18next.t('battle:switchQuestion', { pokemonName: this.useName ? pokemon.name : i18next.t('battle:pokemon') }), null, () => {
this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex);
@ -1564,7 +1566,7 @@ export class SummonMissingPhase extends SummonPhase {
} }
preSummon(): void { preSummon(): void {
this.scene.ui.showText(i18next.t('menu:sendOutPokemon', { pokemonName: this.getPokemon().name})); this.scene.ui.showText(i18next.t('battle:sendOutPokemon', { pokemonName: this.getPokemon().name}));
this.scene.time.delayedCall(250, () => this.summon()); this.scene.time.delayedCall(250, () => this.summon());
} }
} }
@ -1579,7 +1581,7 @@ export class LevelCapPhase extends FieldPhase {
this.scene.ui.setMode(Mode.MESSAGE).then(() => { this.scene.ui.setMode(Mode.MESSAGE).then(() => {
this.scene.playSound('level_up_fanfare'); this.scene.playSound('level_up_fanfare');
this.scene.ui.showText(i18next.t('menu:levelCapUp', { levelCap: this.scene.getMaxExpLevel() }), null, () => this.end(), null, true); this.scene.ui.showText(i18next.t('battle:levelCapUp', { levelCap: this.scene.getMaxExpLevel() }), null, () => this.end(), null, true);
this.executeForAll(pokemon => pokemon.updateInfo(true)); this.executeForAll(pokemon => pokemon.updateInfo(true));
}); });
} }
@ -1673,7 +1675,7 @@ export class CommandPhase extends FieldPhase {
const move = playerPokemon.getMoveset()[cursor]; const move = playerPokemon.getMoveset()[cursor];
if (move.getName().endsWith(' (N)')) { if (move.getName().endsWith(' (N)')) {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => { this.scene.ui.showText(i18next.t('battle:moveNotImplemented', { moveName: move.getName().slice(0, -4) }), null, () => {
this.scene.ui.clearText(); this.scene.ui.clearText();
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
}, null, true); }, null, true);
@ -1684,6 +1686,8 @@ export class CommandPhase extends FieldPhase {
console.log(moveTargets, playerPokemon.name); console.log(moveTargets, playerPokemon.name);
if (moveTargets.targets.length <= 1 || moveTargets.multiple) if (moveTargets.targets.length <= 1 || moveTargets.multiple)
turnCommand.move.targets = moveTargets.targets; turnCommand.move.targets = moveTargets.targets;
else if(playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1)
turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets;
else else
this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex));
this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand; this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
@ -1692,7 +1696,7 @@ export class CommandPhase extends FieldPhase {
const move = playerPokemon.getMoveset()[cursor]; const move = playerPokemon.getMoveset()[cursor];
if (playerPokemon.summonData.disabledMove === move.moveId) { if (playerPokemon.summonData.disabledMove === move.moveId) {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:moveDisabled', { moveName: move.getName() }), null, () => { this.scene.ui.showText(i18next.t('battle:moveDisabled', { moveName: move.getName() }), null, () => {
this.scene.ui.clearText(); this.scene.ui.clearText();
this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex);
}, null, true); }, null, true);
@ -1703,14 +1707,14 @@ export class CommandPhase extends FieldPhase {
if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1))) { if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarters).length - 1))) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:noPokeballForce'), null, () => { this.scene.ui.showText(i18next.t('battle:noPokeballForce'), null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
} else if (this.scene.currentBattle.battleType === BattleType.TRAINER) { } else if (this.scene.currentBattle.battleType === BattleType.TRAINER) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:noPokeballTrainer'), null, () => { this.scene.ui.showText(i18next.t('battle:noPokeballTrainer'), null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
@ -1719,7 +1723,7 @@ export class CommandPhase extends FieldPhase {
if (targets.length > 1) { if (targets.length > 1) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:noPokeballMulti'), null, () => { this.scene.ui.showText(i18next.t('battle:noPokeballMulti'), null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
@ -1728,7 +1732,7 @@ export class CommandPhase extends FieldPhase {
if (targetPokemon.isBoss() && targetPokemon.bossSegmentIndex >= 1 && cursor < PokeballType.MASTER_BALL) { if (targetPokemon.isBoss() && targetPokemon.bossSegmentIndex >= 1 && cursor < PokeballType.MASTER_BALL) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:noPokeballStrong'), null, () => { this.scene.ui.showText(i18next.t('battle:noPokeballStrong'), null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
@ -1748,14 +1752,14 @@ export class CommandPhase extends FieldPhase {
if (!isSwitch && this.scene.arena.biomeType === Biome.END) { if (!isSwitch && this.scene.arena.biomeType === Biome.END) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:noEscapeForce'), null, () => { this.scene.ui.showText(i18next.t('battle:noEscapeForce'), null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
} else if (!isSwitch && this.scene.currentBattle.battleType === BattleType.TRAINER) { } else if (!isSwitch && this.scene.currentBattle.battleType === BattleType.TRAINER) {
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.showText(i18next.t('menu:noEscapeTrainer'), null, () => { this.scene.ui.showText(i18next.t('battle:noEscapeTrainer'), null, () => {
this.scene.ui.showText(null, 0); this.scene.ui.showText(null, 0);
this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex);
}, null, true); }, null, true);
@ -1778,10 +1782,10 @@ export class CommandPhase extends FieldPhase {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
} }
this.scene.ui.showText( this.scene.ui.showText(
i18next.t('menu:noEscapePokemon', { i18next.t('battle:noEscapePokemon', {
pokemonName: this.scene.getPokemonById(trapTag.sourceId).name, pokemonName: this.scene.getPokemonById(trapTag.sourceId).name,
moveName: trapTag.getMoveName(), moveName: trapTag.getMoveName(),
escapeVerb: isSwitch ? i18next.t('menu:escapeVerbSwitch') : i18next.t('menu:escapeVerbFlee') escapeVerb: isSwitch ? i18next.t('battle:escapeVerbSwitch') : i18next.t('battle:escapeVerbFlee')
}), }),
null, null,
() => { () => {
@ -2031,7 +2035,7 @@ export class TurnEndPhase extends FieldPhase {
pokemon.lapseTags(BattlerTagLapseType.TURN_END); pokemon.lapseTags(BattlerTagLapseType.TURN_END);
if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) { if (pokemon.summonData.disabledMove && !--pokemon.summonData.disabledTurns) {
this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('menu:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name }))); this.scene.pushPhase(new MessagePhase(this.scene, i18next.t('battle:notDisabled', { moveName: allMoves[pokemon.summonData.disabledMove].name })));
pokemon.summonData.disabledMove = Moves.NONE; pokemon.summonData.disabledMove = Moves.NONE;
} }
@ -2325,13 +2329,14 @@ export class MovePhase extends BattlePhase {
showMoveText(): void { showMoveText(): void {
if (this.move.getMove().getAttrs(ChargeAttr).length) { if (this.move.getMove().getAttrs(ChargeAttr).length) {
this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500);
const lastMove = this.pokemon.getLastXMoves() as TurnMove[]; const lastMove = this.pokemon.getLastXMoves() as TurnMove[];
if (!lastMove.length || lastMove[0].move !== this.move.getMove().id || lastMove[0].result !== MoveResult.OTHER) if (!lastMove.length || lastMove[0].move !== this.move.getMove().id || lastMove[0].result !== MoveResult.OTHER){
this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500);
return; return;
} }
}
if (this.pokemon.getTag(BattlerTagType.RECHARGING)) if (this.pokemon.getTag(BattlerTagType.RECHARGING || BattlerTagType.INTERRUPTED))
return; return;
this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500); this.scene.queueMessage(getPokemonMessage(this.pokemon, ` used\n${this.move.getName()}!`), 500);
@ -2339,7 +2344,7 @@ export class MovePhase extends BattlePhase {
} }
showFailedText(failedText: string = null): void { showFailedText(failedText: string = null): void {
this.scene.queueMessage(failedText || i18next.t('menu:attackFailed')); this.scene.queueMessage(failedText || i18next.t('battle:attackFailed'));
} }
end() { end() {
@ -2402,7 +2407,7 @@ export class MoveEffectPhase extends PokemonPhase {
moveHistoryEntry.result = MoveResult.MISS; moveHistoryEntry.result = MoveResult.MISS;
applyMoveAttrs(MissEffectAttr, user, null, this.move.getMove()); applyMoveAttrs(MissEffectAttr, user, null, this.move.getMove());
} else { } else {
this.scene.queueMessage(i18next.t('menu:attackFailed')); this.scene.queueMessage(i18next.t('battle:attackFailed'));
moveHistoryEntry.result = MoveResult.FAIL; moveHistoryEntry.result = MoveResult.FAIL;
} }
return this.end(); return this.end();
@ -2486,7 +2491,7 @@ export class MoveEffectPhase extends PokemonPhase {
else { else {
const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0); const hitsTotal = user.turnData.hitCount - Math.max(user.turnData.hitsLeft, 0);
if (hitsTotal > 1) if (hitsTotal > 1)
this.scene.queueMessage(i18next.t('menu:attackHitsCount', { count: hitsTotal })); this.scene.queueMessage(i18next.t('battle:attackHitsCount', { count: hitsTotal }));
this.scene.applyModifiers(HitHealModifier, this.player, user); this.scene.applyModifiers(HitHealModifier, this.player, user);
} }
} }
@ -3152,8 +3157,8 @@ export class FaintPhase extends PokemonPhase {
this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id)); this.scene.getField(true).filter(p => p !== pokemon).forEach(p => p.removeTagsBySourceId(pokemon.id));
pokemon.faintCry(() => { pokemon.faintCry(() => {
const friendshipDecrease = new Utils.IntegerHolder(10); if (pokemon instanceof PlayerPokemon)
pokemon.friendship = Math.max(pokemon.friendship - friendshipDecrease.value, 0); pokemon.addFriendship(-10);
pokemon.hideInfo(); pokemon.hideInfo();
this.scene.playSound('faint'); this.scene.playSound('faint');
this.scene.tweens.add({ this.scene.tweens.add({
@ -3224,13 +3229,8 @@ export class VictoryPhase extends PokemonPhase {
for (let partyMember of expPartyMembers) { for (let partyMember of expPartyMembers) {
const pId = partyMember.id; const pId = partyMember.id;
const participated = participantIds.has(pId); const participated = participantIds.has(pId);
if (participated) { if (participated)
const friendshipIncrease = new Utils.IntegerHolder(2); partyMember.addFriendship(2);
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, partyMember, friendshipIncrease);
partyMember.friendship = Math.min(partyMember.friendship + friendshipIncrease.value, 255);
if (partyMember.friendship === 255)
this.scene.validateAchv(achvs.MAX_FRIENDSHIP);
}
else if (!expShareModifier) { else if (!expShareModifier) {
partyMemberExp.push(0); partyMemberExp.push(0);
continue; continue;
@ -3342,7 +3342,7 @@ export class TrainerVictoryPhase extends BattlePhase {
this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType]));
} }
this.scene.ui.showText(i18next.t('menu:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => { this.scene.ui.showText(i18next.t('battle:trainerDefeated', { trainerName: this.scene.currentBattle.trainer.getName(TrainerSlot.NONE, true) }), null, () => {
const victoryMessages = this.scene.currentBattle.trainer.getVictoryMessages(); const victoryMessages = this.scene.currentBattle.trainer.getVictoryMessages();
const showMessage = () => { const showMessage = () => {
let message: string; let message: string;
@ -3609,7 +3609,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase {
let exp = new Utils.NumberHolder(this.expValue); let exp = new Utils.NumberHolder(this.expValue);
this.scene.applyModifiers(ExpBoosterModifier, true, exp); this.scene.applyModifiers(ExpBoosterModifier, true, exp);
exp.value = Math.floor(exp.value); exp.value = Math.floor(exp.value);
this.scene.ui.showText(i18next.t('menu:expGain', { pokemonName: pokemon.name, exp: exp.value }), null, () => { this.scene.ui.showText(i18next.t('battle:expGain', { pokemonName: pokemon.name, exp: exp.value }), null, () => {
const lastLevel = pokemon.level; const lastLevel = pokemon.level;
let newLevel: integer; let newLevel: integer;
pokemon.addExp(exp.value); pokemon.addExp(exp.value);
@ -3697,7 +3697,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
pokemon.calculateStats(); pokemon.calculateStats();
pokemon.updateInfo(); pokemon.updateInfo();
this.scene.playSound('level_up_fanfare'); this.scene.playSound('level_up_fanfare');
this.scene.ui.showText(i18next.t('menu:levelUp', { pokemonName: this.getPokemon().name, level: this.level }), null, () => this.scene.ui.getMessageHandler().promptLevelUpStats(this.partyMemberIndex, prevStats, false).then(() => this.end()), null, true); 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.level <= 100) { if (this.level <= 100) {
const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1); const levelMoves = this.getPokemon().getLevelMoves(this.lastLevel + 1);
for (let lm of levelMoves) for (let lm of levelMoves)
@ -3746,7 +3746,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
.then(() => { .then(() => {
this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.setMode(messageMode).then(() => {
this.scene.playSound('level_up_fanfare'); this.scene.playSound('level_up_fanfare');
this.scene.ui.showText(i18next.t('menu:learnMove', { pokemonName: pokemon.name, moveName: move.name }), null, () => { this.scene.ui.showText(i18next.t('battle:learnMove', { pokemonName: pokemon.name, moveName: move.name }), null, () => {
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
this.end(); this.end();
}, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true); }, messageMode === Mode.EVOLUTION_SCENE ? 1000 : null, true);
@ -3755,15 +3755,15 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
}); });
} else { } else {
this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.setMode(messageMode).then(() => {
this.scene.ui.showText(i18next.t('menu:learnMovePrompt', { pokemonName: pokemon.name, moveName: move.name }), null, () => { this.scene.ui.showText(i18next.t('battle:learnMovePrompt', { pokemonName: pokemon.name, moveName: move.name }), null, () => {
this.scene.ui.showText(i18next.t('menu:learnMoveLimitReached', { pokemonName: pokemon.name }), null, () => { this.scene.ui.showText(i18next.t('battle:learnMoveLimitReached', { pokemonName: pokemon.name }), null, () => {
this.scene.ui.showText(i18next.t('menu:learnMoveReplaceQuestion', { moveName: move.name }), null, () => { this.scene.ui.showText(i18next.t('battle:learnMoveReplaceQuestion', { moveName: move.name }), null, () => {
const noHandler = () => { const noHandler = () => {
this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.setMode(messageMode).then(() => {
this.scene.ui.showText(i18next.t('menu:learnMoveStopTeaching', { moveName: move.name }), null, () => { this.scene.ui.showText(i18next.t('battle:learnMoveStopTeaching', { moveName: move.name }), null, () => {
this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => {
this.scene.ui.setMode(messageMode); this.scene.ui.setMode(messageMode);
this.scene.ui.showText(i18next.t('menu:learnMoveNotLearned', { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true); this.scene.ui.showText(i18next.t('battle:learnMoveNotLearned', { pokemonName: pokemon.name, moveName: move.name }), null, () => this.end(), null, true);
}, () => { }, () => {
this.scene.ui.setMode(messageMode); this.scene.ui.setMode(messageMode);
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
@ -3774,7 +3774,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
}; };
this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => {
this.scene.ui.setMode(messageMode); this.scene.ui.setMode(messageMode);
this.scene.ui.showText(i18next.t('menu:learnMoveForgetQuestion'), null, () => { this.scene.ui.showText(i18next.t('battle:learnMoveForgetQuestion'), null, () => {
this.scene.ui.setModeWithoutClear(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => { this.scene.ui.setModeWithoutClear(Mode.SUMMARY, this.getPokemon(), SummaryUiMode.LEARN_MOVE, move, (moveIndex: integer) => {
if (moveIndex === 4) { if (moveIndex === 4) {
noHandler(); noHandler();
@ -3782,7 +3782,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
} }
this.scene.ui.setMode(messageMode).then(() => { this.scene.ui.setMode(messageMode).then(() => {
this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!', null, () => { this.scene.ui.showText('@d{32}1, @d{15}2, and@d{15}… @d{15}… @d{15}… @d{15}@s{pb_bounce_1}Poof!', null, () => {
this.scene.ui.showText(i18next.t('menu:learnMoveForgetSuccess', { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => { this.scene.ui.showText(i18next.t('battle:learnMoveForgetSuccess', { pokemonName: pokemon.name, moveName: pokemon.moveset[moveIndex].getName() }), null, () => {
this.scene.ui.showText('And…', null, () => { this.scene.ui.showText('And…', null, () => {
pokemon.setMove(moveIndex, Moves.NONE); pokemon.setMove(moveIndex, Moves.NONE);
this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId)); this.scene.unshiftPhase(new LearnMovePhase(this.scene, this.partyMemberIndex, this.moveId));
@ -4097,7 +4097,7 @@ export class AttemptCapturePhase extends PokemonPhase {
this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs); this.scene.gameData.updateSpeciesDexIvs(pokemon.species.getRootSpeciesId(true), pokemon.ivs);
this.scene.ui.showText(i18next.t('menu:pokemonCaught', { pokemonName: pokemon.name }), null, () => { this.scene.ui.showText(i18next.t('battle:pokemonCaught', { pokemonName: pokemon.name }), null, () => {
const end = () => { const end = () => {
this.scene.pokemonInfoContainer.hide(); this.scene.pokemonInfoContainer.hide();
this.removePb(); this.removePb();
@ -4183,7 +4183,7 @@ export class AttemptRunPhase extends PokemonPhase {
if (playerPokemon.randSeedInt(256) < escapeChance.value) { if (playerPokemon.randSeedInt(256) < escapeChance.value) {
this.scene.playSound('flee'); this.scene.playSound('flee');
this.scene.queueMessage(i18next.t('menu:runAwaySuccess'), null, true, 500); this.scene.queueMessage(i18next.t('battle:runAwaySuccess'), null, true, 500);
this.scene.tweens.add({ this.scene.tweens.add({
targets: [ this.scene.arenaEnemy, enemyField ].flat(), targets: [ this.scene.arenaEnemy, enemyField ].flat(),
@ -4204,7 +4204,7 @@ export class AttemptRunPhase extends PokemonPhase {
this.scene.pushPhase(new BattleEndPhase(this.scene)); this.scene.pushPhase(new BattleEndPhase(this.scene));
this.scene.pushPhase(new NewBattlePhase(this.scene)); this.scene.pushPhase(new NewBattlePhase(this.scene));
} else } else
this.scene.queueMessage(i18next.t('menu:runAwayCannotEscape'), null, true, 500); this.scene.queueMessage(i18next.t('battle:runAwayCannotEscape'), null, true, 500);
this.end(); this.end();
} }
@ -4236,7 +4236,7 @@ export class SelectModifierPhase extends BattlePhase {
const modifierSelectCallback = (rowCursor: integer, cursor: integer) => { const modifierSelectCallback = (rowCursor: integer, cursor: integer) => {
if (rowCursor < 0 || cursor < 0) { if (rowCursor < 0 || cursor < 0) {
this.scene.ui.showText(i18next.t('menu:skipItemQuestion'), null, () => { this.scene.ui.showText(i18next.t('battle:skipItemQuestion'), null, () => {
this.scene.ui.setOverlayMode(Mode.CONFIRM, () => { this.scene.ui.setOverlayMode(Mode.CONFIRM, () => {
this.scene.ui.revertMode(); this.scene.ui.revertMode();
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
@ -4415,7 +4415,7 @@ export class EggLapsePhase extends Phase {
}); });
if (eggsToHatch.length) { if (eggsToHatch.length) {
this.scene.queueMessage(i18next.t('menu:eggHatching')); this.scene.queueMessage(i18next.t('battle:eggHatching'));
for (let egg of eggsToHatch) for (let egg of eggsToHatch)
this.scene.unshiftPhase(new EggHatchPhase(this.scene, egg)); this.scene.unshiftPhase(new EggHatchPhase(this.scene, egg));
@ -4509,7 +4509,7 @@ export class ScanIvsPhase extends PokemonPhase {
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
this.scene.ui.showText(i18next.t('menu:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => { this.scene.ui.showText(i18next.t('battle:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => {
this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.ui.clearText(); this.scene.ui.clearText();

View File

@ -13,6 +13,12 @@ import { menuUiHandler as frMenuUiHandler } from '../locales/fr/menu-ui-handler.
import { menuUiHandler as itMenuUiHandler } from '../locales/it/menu-ui-handler.js'; import { menuUiHandler as itMenuUiHandler } from '../locales/it/menu-ui-handler.js';
import { menuUiHandler as deMenuUiHandler } from '../locales/de/menu-ui-handler.js'; import { menuUiHandler as deMenuUiHandler } from '../locales/de/menu-ui-handler.js';
import { battle as enBattle } from '../locales/en/battle';
import { battle as esBattle } from '../locales/es/battle';
import { battle as itBattle } from '../locales/it/battle';
import { battle as frBattle } from '../locales/fr/battle';
import { battle as deBattle } from '../locales/de/battle';
import { move as enMove } from '../locales/en/move'; import { move as enMove } from '../locales/en/move';
import { move as esMove } from '../locales/es/move'; import { move as esMove } from '../locales/es/move';
import { move as frMove } from '../locales/fr/move'; import { move as frMove } from '../locales/fr/move';
@ -45,7 +51,10 @@ import { commandUiHandler as frCommandUiHandler } from '../locales/fr/command-ui
import { commandUiHandler as deCommandUiHandler } from '../locales/de/command-ui-handler'; import { commandUiHandler as deCommandUiHandler } from '../locales/de/command-ui-handler';
import { fightUiHandler as enFightUiHandler } from '../locales/en/fight-ui-handler'; import { fightUiHandler as enFightUiHandler } from '../locales/en/fight-ui-handler';
import { fightUiHandler as esFightUiHandler } from '../locales/es/fight-ui-handler';
import { fightUiHandler as frFightUiHandler } from '../locales/fr/fight-ui-handler'; import { fightUiHandler as frFightUiHandler } from '../locales/fr/fight-ui-handler';
import { fightUiHandler as itFightUiHandler } from '../locales/it/fight-ui-handler';
import { fightUiHandler as deFightUiHandler } from '../locales/de/fight-ui-handler';
import { tutorial as enTutorial } from '../locales/en/tutorial'; import { tutorial as enTutorial } from '../locales/en/tutorial';
import { tutorial as esTutorial } from '../locales/es/tutorial'; import { tutorial as esTutorial } from '../locales/es/tutorial';
@ -113,6 +122,7 @@ export function initI18n(): void {
en: { en: {
menu: enMenu, menu: enMenu,
menuUiHandler: enMenuUiHandler, menuUiHandler: enMenuUiHandler,
battle: enBattle,
move: enMove, move: enMove,
ability: enAbility, ability: enAbility,
pokeball: enPokeball, pokeball: enPokeball,
@ -125,17 +135,20 @@ export function initI18n(): void {
es: { es: {
menu: esMenu, menu: esMenu,
menuUiHandler: esMenuUiHandler, menuUiHandler: esMenuUiHandler,
battle: esBattle,
move: esMove, move: esMove,
ability: esAbility, ability: esAbility,
pokeball: esPokeball, pokeball: esPokeball,
pokemon: esPokemon, pokemon: esPokemon,
pokemonStat: esPokemonStat, pokemonStat: esPokemonStat,
commandUiHandler: esCommandUiHandler, commandUiHandler: esCommandUiHandler,
fightUiHandler: esFightUiHandler,
tutorial: esTutorial, tutorial: esTutorial,
}, },
fr: { fr: {
menu: frMenu, menu: frMenu,
menuUiHandler: frMenuUiHandler, menuUiHandler: frMenuUiHandler,
battle: frBattle,
move: frMove, move: frMove,
ability: frAbility, ability: frAbility,
pokeball: frPokeball, pokeball: frPokeball,
@ -148,18 +161,22 @@ export function initI18n(): void {
it: { it: {
menu: itMenu, menu: itMenu,
menuUiHandler: itMenuUiHandler, menuUiHandler: itMenuUiHandler,
battle: itBattle,
pokemonStat: itPokemonStat, pokemonStat: itPokemonStat,
fightUiHandler: itFightUiHandler,
tutorial: itTutorial, tutorial: itTutorial,
}, },
de: { de: {
menu: deMenu, menu: deMenu,
menuUiHandler: deMenuUiHandler, menuUiHandler: deMenuUiHandler,
battle: deBattle,
move: deMove, move: deMove,
ability: deAbility, ability: deAbility,
pokeball: dePokeball, pokeball: dePokeball,
pokemon: dePokemon, pokemon: dePokemon,
pokemonStat: dePokemonStat, pokemonStat: dePokemonStat,
commandUiHandler: deCommandUiHandler, commandUiHandler: deCommandUiHandler,
fightUiHandler: deFightUiHandler,
tutorial: deTutorial, tutorial: deTutorial,
} }
}, },
@ -173,6 +190,7 @@ declare module 'i18next' {
menu: typeof enMenu; menu: typeof enMenu;
menuUiHandler: typeof enMenuUiHandler; menuUiHandler: typeof enMenuUiHandler;
move: typeof enMove; move: typeof enMove;
battle: typeof enBattle,
ability: typeof enAbility; ability: typeof enAbility;
pokeball: typeof enPokeball; pokeball: typeof enPokeball;
pokemon: typeof enPokemon; pokemon: typeof enPokemon;

View File

@ -7,6 +7,7 @@ export enum AchvTier {
COMMON, COMMON,
GREAT, GREAT,
ULTRA, ULTRA,
ROGUE,
MASTER MASTER
} }
@ -50,8 +51,10 @@ export class Achv {
} }
getTier(): AchvTier { getTier(): AchvTier {
if (this.score >= 100) if (this.score >= 150)
return AchvTier.MASTER; return AchvTier.MASTER;
if (this.score >= 100)
return AchvTier.ROGUE;
if (this.score >= 50) if (this.score >= 50)
return AchvTier.ULTRA; return AchvTier.ULTRA;
if (this.score >= 25) if (this.score >= 25)

View File

@ -169,6 +169,7 @@ export interface StarterDataEntry {
moveset: StarterMoveset | StarterFormMoveData; moveset: StarterMoveset | StarterFormMoveData;
eggMoves: integer; eggMoves: integer;
candyCount: integer; candyCount: integer;
friendship: integer;
abilityAttr: integer; abilityAttr: integer;
passiveAttr: integer; passiveAttr: integer;
valueReduction: integer; valueReduction: integer;
@ -988,6 +989,7 @@ export class GameData {
moveset: null, moveset: null,
eggMoves: 0, eggMoves: 0,
candyCount: 0, candyCount: 0,
friendship: 0,
abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0, abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0,
passiveAttr: 0, passiveAttr: 0,
valueReduction: 0 valueReduction: 0
@ -1035,6 +1037,7 @@ export class GameData {
const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId); const hasPrevolution = pokemonPrevolutions.hasOwnProperty(species.speciesId);
const newCatch = !caughtAttr; const newCatch = !caughtAttr;
const hasNewAttr = (caughtAttr & dexAttr) !== dexAttr;
if (incrementCount) { if (incrementCount) {
if (!fromEgg) { if (!fromEgg) {
@ -1057,7 +1060,7 @@ export class GameData {
this.gameStats.shinyPokemonHatched++; this.gameStats.shinyPokemonHatched++;
} }
if (!hasPrevolution) if (!hasPrevolution && (!pokemon.scene.gameMode.isDaily || hasNewAttr))
this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant || 0) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1)); this.addStarterCandy(species, (1 * (pokemon.isShiny() ? 5 * Math.pow(2, pokemon.variant || 0) : 1)) * (fromEgg || pokemon.isBoss() ? 2 : 1));
} }

View File

@ -44,7 +44,7 @@ export class Voucher {
case VoucherType.PREMIUM: case VoucherType.PREMIUM:
return AchvTier.ULTRA; return AchvTier.ULTRA;
case VoucherType.GOLDEN: case VoucherType.GOLDEN:
return AchvTier.MASTER; return AchvTier.ROGUE;
} }
} }
} }

View File

@ -498,11 +498,14 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
this.lastLevel = pokemon.level; this.lastLevel = pokemon.level;
} }
if (pokemon.summonData) { const battleStats = pokemon.summonData
const battleStats = pokemon.summonData.battleStats.join(''); ? pokemon.summonData.battleStats
: battleStatOrder.map(() => 0);
const battleStatsStr = battleStats.join('');
if (this.lastBattleStats !== battleStats) if (this.lastBattleStats !== battleStatsStr) {
this.updateBattleStats(pokemon.summonData.battleStats); this.updateBattleStats(battleStats);
this.lastBattleStats = battleStatsStr;
} }
this.shinyIcon.setVisible(pokemon.isShiny()); this.shinyIcon.setVisible(pokemon.isShiny());

View File

@ -167,7 +167,7 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
} else } else
this.loadingLabel.setText(i18next.t('menu:noRankings')); this.loadingLabel.setText(i18next.t('menu:noRankings'));
}); });
}); }).catch(err => { console.error("Failed to load daily rankings:\n", err) });
} }
} }

View File

@ -65,6 +65,9 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`); this.playerCountLabel.setText(`${stats.playerCount} ${i18next.t("menu:playersOnline")}`);
if (this.splashMessage === battleCountSplashMessage) if (this.splashMessage === battleCountSplashMessage)
this.splashMessageText.setText(battleCountSplashMessage.replace('{COUNT}', stats.battleCount.toLocaleString('en-US'))); this.splashMessageText.setText(battleCountSplashMessage.replace('{COUNT}', stats.battleCount.toLocaleString('en-US')));
})
.catch(err => {
console.error("Failed to fetch title stats:\n", err);
}); });
} }