Compare commits

...

11 Commits

Author SHA1 Message Date
Lugiad
e37b278b4f
Update French modifier-type.ts (#1496) 2024-05-28 10:57:38 -04:00
José Ricardo Fleury Oliveira
0780211901
Quick translation fixes (#1497)
* translation fixes

* quick translation fixes
2024-05-28 10:49:38 -04:00
Benjamin Odom
1f432cf5c0
Create comments.md (#1498) 2024-05-28 10:46:25 -04:00
Matthew
fcdac63759
Add Feature Issue Template 2024-05-28 10:32:18 -04:00
Matthew
578717aab1
Add bug issue template 2024-05-28 10:30:14 -04:00
Matthew Olker
f0cf5cbb19 PR Template from Issue 1304 2024-05-28 10:19:40 -04:00
Dakurei
bf06ce6340
Removes useless '/' make it doubles in somes cases (#1482) 2024-05-28 10:08:53 -04:00
José Ricardo Fleury Oliveira
5512be8f31
Translation fixes ptBR (#1468)
* translation fixes

* info container

* localized position and text size in pokemon-info-container
2024-05-28 10:00:27 -04:00
jjoines
d835cfd13f
Fix battle girl victory dialogue (#1489)
Fixed string to have colon, not a period.
2024-05-28 09:23:29 -04:00
40chyan
77b59a1cef
zh_CN update game-stats-ui-handler.ts (#1481)
* Update game-stats-ui-handler.ts

* Update game-stats-ui-handler.ts

* Update game-stats-ui-handler.ts
2024-05-28 09:09:53 -04:00
Frederico Santos
89f58961cb
Implement Zero to hero (#1131)
* Implemented Zero-To-Hero

* Zero to Hero documentation and form reset on summon

* Zero to Hero: form reset on biome/trainer

* Updated documentation on PreSwitchOutFormChangeAbAttr apply

* Faint bypass on canApplyAbility

* revert zygarde

* zero to hero post-merge
2024-05-28 06:11:04 -05:00
21 changed files with 362 additions and 134 deletions

30
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,30 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: Bug
assignees: ''
---
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
<!-- Steps to reproduce the behavior: -->
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. If it is an existing move or ability -->
**Screenshots / Videos**
<!-- If applicable, add screenshots or videos to help explain your problem. -->
**Device**
<!-- What browser are you playing in, are you on a PC/Mac or Phone? -->
**Additional context**
<!-- Add any other context about the problem here. -->

View File

@ -0,0 +1,18 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[Feature]"
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
**Describe the Feature**
<!-- A clear and concise description of what you want to happen. -->
<!-- Add a link to the feature if it is an existing move/ability/etc -->
**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->

34
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,34 @@
<!-- Make sure the title includes categorization (i.e. [Bug], [QoL], [Localization]) -->
<!-- Make sure that this PR is not overlapping with someone else's work -->
<!-- Please try to keep the PR self-contained (and small) -->
## What are the changes?
<!-- Summarize what are the changes from a user perspective on the application -->
## Why am I doing these changes?
<!-- Explain why you decided to introduce these changes -->
<!-- Does it come from an issue or another PR? Please link it -->
<!-- Explain why you believe this can enhance user experience -->
## What did change?
<!-- Explicitly state what are the changes introduced by the PR -->
<!-- You can make use of a comparison between what was the state before and after your PR changes -->
### Screenshots/Videos
<!-- If your change is changing anything on the user experience, please provide visual proofs of it -->
<!-- Please take screenshots/videos before and after your changes, to show what is brought by this PR -->
## How to test the changes?
<!-- How can a reviewer test your changes once they check out on your branch? -->
<!-- Did you just make use of the `src/overrides.ts` file? -->
<!-- Did you introduce any automated tests? -->
<!-- Do the reviewer need to do something special in order to test your change? -->
## Checklist
- [ ] There is no overlap with another PR?
- [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes?
- [ ] Have I tested the changes (manually)?
- [ ] Are all unit tests still passing? (`npm run test`)
- [ ] Are the changes visual?
- [ ] Have I provided screenshots/videos of the changes?

64
docs/comments.md Normal file
View File

@ -0,0 +1,64 @@
## How do I comment my code?
### While we're not enforcing a strict standard, there are some things to keep in mind:
- Make comments meaningful
- Comments should be explaining why a line or block of code exists and what the reason behind it is
- Comments should not be repeating chunks of code or explaining what 'true' and 'false' means in typescript
- Make sure comments exist on Functions, Classes, Methods, and Properties
- This may be the most important things to comment. When someone goes to use a function/class/method/etc., having a comment reduces the need to flip back and forth between files to figure out how something works. Peek Definition is great until you're three nested functions deep.
- The best example of this is JSDoc-style comments as seen below:
- When formatted this way, the comment gets shown by intellisense in VS Code or similar IDEs just by hovering over the text!
- Functions also show each the comment for parameter as you type them, making keeping track of what each one does in lengthy functions much more clear
```js
/**
* Changes the type-based weather modifier if this move's power would be reduced by it
* @param user {@linkcode Pokemon} using this move
* @param target {@linkcode Pokemon} target of this move
* @param move {@linkcode Move} being used
* @param args [0] {@linkcode Utils.NumberHolder} for arenaAttackTypeMultiplier
* @returns true if the function succeeds
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
}
/** Set to true when experimental animated sprites from Gen6+ are used */
public experimentalSprites: boolean = false;
/**
* Cures the user's party of non-volatile status conditions, ie. Heal Bell, Aromatherapy
* @extends MoveAttr
* @see {@linkcode apply}
*/
export class DontHealThePartyPlsAttr extends MoveAttr {
}
```
You'll notice this contains an `{@linkcode Object}` tag for each parameter. This provides an easy type denomination and hyperlink to that type using VS Code's Intellisense. `@linkcode` is used instead of `@link` so that the text appears in monospace which is more obviously a `type` rather than a random hyperlink.
If you're interested in going more in depth, you can find a reference guide for how comments like these work [here](https://jsdoc.app)
### What not to do:
- Don't leave comments for code you don't understand
- Incorrect information is worse than no information. If you aren't sure how something works, don't make something up to explain it. Ask for help instead.
- Don't over-comment
- Not everything needs an explanation. Try to summarize blocks of code instead of singular lines where possible. Single line comments should call out specific oddities.
## How do Abilities and Moves differ from other classes?
While other classes should be fully documented, Abilities and Moves heavily incoperate inheritance (i.e. the `extends` keyword). Because of this, much of the functionality in these classes is duplicated or only slightly changed between classes.
### With this in mind, there's a few more things to keep in mind for these:
- Do not document any parameters if the function mirrors the one they extend.
- Keep this in mind for functions that are not the `apply` function as they are usually sparce and mostly reused
- The class itself must be documented
- This must include the `@extends BaseClass` and `@see {@linkcode apply}` tags
- Class member variables must be documented
- You can use a single line documentation comment for these `/** i.e. a comment like this */`
- `args` parameters must be documented if used
- This should look something like this when there are multiple:
```ts
/**
...
* @param args [0] {@linkcode Utils.NumberHolder} of arenaAttackTypeMultiplier
* [1] {@linkcode Utils.BooleanHolder} of cancelled
* [2] {@linkcode Utils.BooleanHolder} of rWeDoneYet
...
*/
```

View File

@ -17,7 +17,7 @@ import { Moves } from "./data/enums/moves";
import { allMoves } from "./data/move"; import { allMoves } from "./data/move";
import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from "./modifier/modifier-type"; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from "./modifier/modifier-type";
import AbilityBar from "./ui/ability-bar"; import AbilityBar from "./ui/ability-bar";
import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs } from "./data/ability"; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, PostBattleInitAbAttr, applyAbAttrs, applyPostBattleInitAbAttrs } from "./data/ability";
import { allAbilities } from "./data/ability"; import { allAbilities } from "./data/ability";
import Battle, { BattleType, FixedBattleConfig, fixedBattles } from "./battle"; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from "./battle";
import { GameMode, GameModes, gameModes } from "./game-mode"; import { GameMode, GameModes, gameModes } from "./game-mode";
@ -979,6 +979,7 @@ export default class BattleScene extends SceneBase {
if (pokemon) { if (pokemon) {
if (resetArenaState) { if (resetArenaState) {
pokemon.resetBattleData(); pokemon.resetBattleData();
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon, true);
} }
this.triggerPokemonFormChange(pokemon, SpeciesFormChangeTimeOfDayTrigger); this.triggerPokemonFormChange(pokemon, SpeciesFormChangeTimeOfDayTrigger);
} }

View File

@ -1753,6 +1753,39 @@ export class PreSwitchOutHealAbAttr extends PreSwitchOutAbAttr {
} }
} }
/**
* Attribute for form changes that occur on switching out
* @extends PreSwitchOutAbAttr
* @see {@linkcode applyPreSwitchOut}
*/
export class PreSwitchOutFormChangeAbAttr extends PreSwitchOutAbAttr {
private formFunc: (p: Pokemon) => integer;
constructor(formFunc: ((p: Pokemon) => integer)) {
super();
this.formFunc = formFunc;
}
/**
* On switch out, trigger the form change to the one defined in the ability
* @param pokemon The pokemon switching out and changing form {@linkcode Pokemon}
* @param passive N/A
* @param args N/A
* @returns true if the form change was successful
*/
applyPreSwitchOut(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
const formIndex = this.formFunc(pokemon);
if (formIndex !== pokemon.formIndex) {
pokemon.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeManualTrigger, false);
return true;
}
return false;
}
}
export class PreStatChangeAbAttr extends AbAttr { export class PreStatChangeAbAttr extends AbAttr {
applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> { applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean | Promise<boolean> {
return false; return false;
@ -3038,7 +3071,7 @@ export class MoneyAbAttr extends PostBattleAbAttr {
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr }, function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> { pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
if (!pokemon.canApplyAbility(passive)) { if (!pokemon.canApplyAbility(passive, args[0])) {
if (!passive) { if (!passive) {
return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve()); return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve());
} else { } else {
@ -3712,7 +3745,7 @@ export function initAbilities() {
.attr(PostDefendContactDamageAbAttr, 8) .attr(PostDefendContactDamageAbAttr, 8)
.bypassFaint(), .bypassFaint(),
new Ability(Abilities.ZEN_MODE, 5) new Ability(Abilities.ZEN_MODE, 5)
.attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0) .attr(PostBattleInitFormChangeAbAttr, () => 0)
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0)
.attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0) .attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
@ -3810,7 +3843,7 @@ export function initAbilities() {
new Ability(Abilities.MERCILESS, 7) new Ability(Abilities.MERCILESS, 7)
.attr(ConditionalCritAbAttr, (user, target, move) => target.status?.effect === StatusEffect.TOXIC || target.status?.effect === StatusEffect.POISON), .attr(ConditionalCritAbAttr, (user, target, move) => target.status?.effect === StatusEffect.TOXIC || target.status?.effect === StatusEffect.POISON),
new Ability(Abilities.SHIELDS_DOWN, 7) new Ability(Abilities.SHIELDS_DOWN, 7)
.attr(PostBattleInitFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostBattleInitFormChangeAbAttr, () => 0)
.attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0))
.attr(PostTurnFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostTurnFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0))
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
@ -3843,7 +3876,7 @@ export function initAbilities() {
new Ability(Abilities.SURGE_SURFER, 7) new Ability(Abilities.SURGE_SURFER, 7)
.conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPD, 2), .conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPD, 2),
new Ability(Abilities.SCHOOLING, 7) new Ability(Abilities.SCHOOLING, 7)
.attr(PostBattleInitFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1) .attr(PostBattleInitFormChangeAbAttr, () => 0)
.attr(PostSummonFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1)
.attr(PostTurnFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1) .attr(PostTurnFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
@ -3853,7 +3886,7 @@ export function initAbilities() {
new Ability(Abilities.DISGUISE, 7) new Ability(Abilities.DISGUISE, 7)
.attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex === 0 && target.getAttackTypeEffectiveness(move.type, user) > 0) .attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex === 0 && target.getAttackTypeEffectiveness(move.type, user) > 0)
.attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
.attr(PostBattleInitFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) .attr(PostBattleInitFormChangeAbAttr, () => 0)
.attr(PostDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) .attr(PostDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
.attr(PreDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) .attr(PreDefendFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
.attr(PostDefendDisguiseAbAttr) .attr(PostDefendDisguiseAbAttr)
@ -3865,13 +3898,14 @@ export function initAbilities() {
.ignorable() .ignorable()
.partial(), .partial(),
new Ability(Abilities.BATTLE_BOND, 7) new Ability(Abilities.BATTLE_BOND, 7)
.attr(PostVictoryFormChangeAbAttr, p => p.getFormKey() ? 2 : 1) .attr(PostVictoryFormChangeAbAttr, () => 2)
.attr(PostBattleInitFormChangeAbAttr, () => 1)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(UnsuppressableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr)
.attr(NoFusionAbilityAbAttr), .attr(NoFusionAbilityAbAttr),
new Ability(Abilities.POWER_CONSTRUCT, 7) // TODO: 10% Power Construct Zygarde isn't accounted for yet. If changed, update Zygarde's getSpeciesFormIndex entry accordingly new Ability(Abilities.POWER_CONSTRUCT, 7) // TODO: 10% Power Construct Zygarde isn't accounted for yet. If changed, update Zygarde's getSpeciesFormIndex entry accordingly
.attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) .attr(PostBattleInitFormChangeAbAttr, () => 2)
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
.attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) .attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
@ -4103,7 +4137,8 @@ export function initAbilities() {
.attr(UnsuppressableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr) .attr(NoTransformAbilityAbAttr)
.attr(NoFusionAbilityAbAttr) .attr(NoFusionAbilityAbAttr)
.unimplemented(), .attr(PostBattleInitFormChangeAbAttr, () => 0)
.attr(PreSwitchOutFormChangeAbAttr, () => 1),
new Ability(Abilities.COMMANDER, 9) new Ability(Abilities.COMMANDER, 9)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
@ -4186,22 +4221,26 @@ export function initAbilities() {
.attr(PostBattleInitStatChangeAbAttr, BattleStat.SPD, 1, true) .attr(PostBattleInitStatChangeAbAttr, BattleStat.SPD, 1, true)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr), .attr(NoTransformAbilityAbAttr)
.partial(),
new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9) new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9)
.attr(PostBattleInitStatChangeAbAttr, BattleStat.SPDEF, 1, true) .attr(PostBattleInitStatChangeAbAttr, BattleStat.SPDEF, 1, true)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr), .attr(NoTransformAbilityAbAttr)
.partial(),
new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9) new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9)
.attr(PostBattleInitStatChangeAbAttr, BattleStat.ATK, 1, true) .attr(PostBattleInitStatChangeAbAttr, BattleStat.ATK, 1, true)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr), .attr(NoTransformAbilityAbAttr)
.partial(),
new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9) new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9)
.attr(PostBattleInitStatChangeAbAttr, BattleStat.DEF, 1, true) .attr(PostBattleInitStatChangeAbAttr, BattleStat.DEF, 1, true)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr) .attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr), .attr(NoTransformAbilityAbAttr)
.partial(),
new Ability(Abilities.TERA_SHIFT, 9) new Ability(Abilities.TERA_SHIFT, 9)
.attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1)
.attr(UncopiableAbilityAbAttr) .attr(UncopiableAbilityAbAttr)

View File

@ -250,7 +250,7 @@ export const trainerTypeDialogue = {
"dialogue:battle_girl.encounter.1", "dialogue:battle_girl.encounter.1",
], ],
victory: [ victory: [
"dialogue.battle_girl.victory.1", "dialogue:battle_girl.victory.1",
] ]
} }
], ],

View File

@ -570,6 +570,10 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.GRENINJA, "battle-bond", "ash", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.GRENINJA, "battle-bond", "ash", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.GRENINJA, "ash", "battle-bond", new SpeciesFormChangeManualTrigger(), true) new SpeciesFormChange(Species.GRENINJA, "ash", "battle-bond", new SpeciesFormChangeManualTrigger(), true)
], ],
[Species.PALAFIN] : [
new SpeciesFormChange(Species.PALAFIN, "zero", "hero", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.PALAFIN, "hero", "zero", new SpeciesFormChangeManualTrigger(), true)
],
[Species.AEGISLASH]: [ [Species.AEGISLASH]: [
new SpeciesFormChange(Species.AEGISLASH, "blade", "shield", new SpeciesFormChangePreMoveTrigger(Moves.KINGS_SHIELD), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))), new SpeciesFormChange(Species.AEGISLASH, "blade", "shield", new SpeciesFormChangePreMoveTrigger(Moves.KINGS_SHIELD), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))),
new SpeciesFormChange(Species.AEGISLASH, "shield", "blade", new SpeciesFormChangePreMoveTrigger(m => allMoves[m].category !== MoveCategory.STATUS), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))), new SpeciesFormChange(Species.AEGISLASH, "shield", "blade", new SpeciesFormChangePreMoveTrigger(m => allMoves[m].category !== MoveCategory.STATUS), true, new SpeciesFormChangeCondition(p => p.hasAbility(Abilities.STANCE_CHANGE))),

View File

@ -962,7 +962,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @param {boolean} passive If true, check if passive can be applied instead of non-passive * @param {boolean} passive If true, check if passive can be applied instead of non-passive
* @returns {Ability} The passive ability of the pokemon * @returns {Ability} The passive ability of the pokemon
*/ */
canApplyAbility(passive: boolean = false): boolean { canApplyAbility(passive: boolean = false, forceBypass: boolean = false): boolean {
if (passive && !this.hasPassive()) { if (passive && !this.hasPassive()) {
return false; return false;
} }
@ -990,7 +990,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return false; return false;
} }
} }
return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this)); return (this.hp || ability.isBypassFaint || forceBypass) && !ability.conditions.find(condition => !condition(this));
} }
/** /**

View File

@ -145,7 +145,7 @@ export const modifierType: ModifierTypeTranslationEntries = {
"FULL_HEAL": { name: "Total Soin" }, "FULL_HEAL": { name: "Total Soin" },
"SACRED_ASH": { name: "Cendres Sacrées" }, "SACRED_ASH": { name: "Cendre Sacrée" },
"REVIVER_SEED": { name: "Résugraine", description: "Réanime et restaure la moitié des PV de son porteur sil tombe K.O." }, "REVIVER_SEED": { name: "Résugraine", description: "Réanime et restaure la moitié des PV de son porteur sil tombe K.O." },
@ -193,10 +193,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
"GRIP_CLAW": { name: "Accro Griffe" }, "GRIP_CLAW": { name: "Accro Griffe" },
"WIDE_LENS": { name: "Loupe" }, "WIDE_LENS": { name: "Loupe" },
"MULTI_LENS": { name: "Multi Loupe" }, "MULTI_LENS": { name: "Lentille Multi" },
"HEALING_CHARM": { name: "Charme Soin", description: "Augmente de 10% lefficacité des capacités et objets de soin de PV (hors Rappels)" }, "HEALING_CHARM": { name: "Charme Soin", description: "Augmente de 10% lefficacité des capacités et objets de soin de PV (hors Rappels)" },
"CANDY_JAR": { name: "Jarre de Bonbons", description: "Augmente de 1 le nombre de niveaux gagnés à lutilisation dun Super Bonbon" }, "CANDY_JAR": { name: "Bonbonnière", description: "Augmente de 1 le nombre de niveaux gagnés à lutilisation dun Super Bonbon" },
"BERRY_POUCH": { name: "Sac à Baies", description: "Ajoute 33% de chances quune Baie utilisée ne soit pas consommée" }, "BERRY_POUCH": { name: "Sac à Baies", description: "Ajoute 33% de chances quune Baie utilisée ne soit pas consommée" },

View File

@ -2,4 +2,5 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const abilityTriggers: SimpleTranslationEntries = { export const abilityTriggers: SimpleTranslationEntries = {
"blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!", "blockRecoilDamage" : "{{abilityName}} de {{pokemonName}}\nprotegeu-o do dano de recuo!",
"badDreams": "{{pokemonName}} está tendo pesadelos!",
} as const; } as const;

View File

@ -1,7 +1,7 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const battleMessageUiHandler: SimpleTranslationEntries = { export const battleMessageUiHandler: SimpleTranslationEntries = {
"ivBest": "Melhor", "ivBest": "Perfeito",
"ivFantastic": "Fantástico", "ivFantastic": "Fantástico",
"ivVeryGood": "Muito Bom", "ivVeryGood": "Muito Bom",
"ivPrettyGood": "Bom", "ivPrettyGood": "Bom",

View File

@ -149,7 +149,7 @@ export const move: MoveTranslationEntries = {
name: "Thrash", name: "Thrash",
effect: "O usuário fica furioso e ataca com violência de dois a três turnos. O usuário então se torna confuso." effect: "O usuário fica furioso e ataca com violência de dois a três turnos. O usuário então se torna confuso."
}, },
"double-Edge": { "doubleEdge": {
name: "Double-Edge", name: "Double-Edge",
effect: "Uma investida imprudente e muito perigosa. Isso também fere bastante o usuário." effect: "Uma investida imprudente e muito perigosa. Isso também fere bastante o usuário."
}, },
@ -477,7 +477,7 @@ export const move: MoveTranslationEntries = {
name: "Mirror Move", name: "Mirror Move",
effect: "O usuário contra-ataca o alvo imitando seu último movimento utilizado." effect: "O usuário contra-ataca o alvo imitando seu último movimento utilizado."
}, },
"self-Destruct": { "selfDestruct": {
name: "Self-Destruct", name: "Self-Destruct",
effect: "O usuário ataca tudo ao seu redor causando uma explosão. O usuário desmaia por usar esse golpe." effect: "O usuário ataca tudo ao seu redor causando uma explosão. O usuário desmaia por usar esse golpe."
}, },
@ -537,7 +537,7 @@ export const move: MoveTranslationEntries = {
name: "Kinesis", name: "Kinesis",
effect: "O usuário distrai o alvo entortando uma colher. Isso diminui a Precisão do alvo." effect: "O usuário distrai o alvo entortando uma colher. Isso diminui a Precisão do alvo."
}, },
"soft-Boiled": { "softBoiled": {
name: "Soft-Boiled", name: "Soft-Boiled",
effect: "O usuário restaura os próprios PS pela metade dos seus PS máximos." effect: "O usuário restaura os próprios PS pela metade dos seus PS máximos."
}, },
@ -753,7 +753,7 @@ export const move: MoveTranslationEntries = {
name: "Sludge Bomb", name: "Sludge Bomb",
effect: "Lodo insalubre é no arremessado no alvo. Isso também pode causar envenenamento." effect: "Lodo insalubre é no arremessado no alvo. Isso também pode causar envenenamento."
}, },
"mud-Slap": { "mudSlap": {
name: "Mud-Slap", name: "Mud-Slap",
effect: "O usuário arremessa lama no rosto do adversário para causar dano e prejudicar sua precisão." effect: "O usuário arremessa lama no rosto do adversário para causar dano e prejudicar sua precisão."
}, },
@ -793,7 +793,7 @@ export const move: MoveTranslationEntries = {
name: "Bone Rush", name: "Bone Rush",
effect: "O usuário atinge o alvo com um osso duro de duas a cinco vezes seguidas." effect: "O usuário atinge o alvo com um osso duro de duas a cinco vezes seguidas."
}, },
"lock-On": { "lockOn": {
name: "Lock-On", name: "Lock-On",
effect: "O usuário foca sua mira no alvo. Isso garante que o próximo ataque não erre o alvo." effect: "O usuário foca sua mira no alvo. Isso garante que o próximo ataque não erre o alvo."
}, },
@ -1041,7 +1041,7 @@ export const move: MoveTranslationEntries = {
name: "Flatter", name: "Flatter",
effect: "Bajulação é usada para confundir o oponente. Entretanto, isso também fortalece o Ataque Especial do alvo." effect: "Bajulação é usada para confundir o oponente. Entretanto, isso também fortalece o Ataque Especial do alvo."
}, },
"will-O-Wisp": { "willOWisp": {
name: "Will-O-Wisp", name: "Will-O-Wisp",
effect: "O usuário atira uma sinistra chama azulada no alvo para causar uma queimadura." effect: "O usuário atira uma sinistra chama azulada no alvo para causar uma queimadura."
}, },
@ -1429,7 +1429,7 @@ export const move: MoveTranslationEntries = {
name: "Miracle Eye", name: "Miracle Eye",
effect: "Permite que um alvo tipo Sombrio seja atingido por ataques do tipo Psíquico. Isso também permite que um alvo evasivo possa ser atingido." effect: "Permite que um alvo tipo Sombrio seja atingido por ataques do tipo Psíquico. Isso também permite que um alvo evasivo possa ser atingido."
}, },
"wake-UpSlap": { "wakeUpSlap": {
name: "Wake-Up Slap", name: "Wake-Up Slap",
effect: "Esse ataque causa muito dano em um alvo que estiver dormindo; entretanto, isso também acorda o alvo." effect: "Esse ataque causa muito dano em um alvo que estiver dormindo; entretanto, isso também acorda o alvo."
}, },
@ -1473,7 +1473,7 @@ export const move: MoveTranslationEntries = {
name: "Metal Burst", name: "Metal Burst",
effect: "O usuário revida com muito mais força contra o alvo que lhe infligiu dano por ultimo." effect: "O usuário revida com muito mais força contra o alvo que lhe infligiu dano por ultimo."
}, },
"u-Turn": { "uTurn": {
name: "U-turn", name: "U-turn",
effect: "Depois de fazer o seu ataque, o usuário corre de volta para trocar de lugar com um Pokémon da própria equipe." effect: "Depois de fazer o seu ataque, o usuário corre de volta para trocar de lugar com um Pokémon da própria equipe."
}, },
@ -1613,7 +1613,7 @@ export const move: MoveTranslationEntries = {
name: "Air Slash", name: "Air Slash",
effect: "O usuário ataca com uma lâmina de ar que corta até mesmo o céu. Isso pode fazer o alvo hesitar." effect: "O usuário ataca com uma lâmina de ar que corta até mesmo o céu. Isso pode fazer o alvo hesitar."
}, },
"x-Scissor": { "xScissor": {
name: "X-Scissor", name: "X-Scissor",
effect: "O usuário cutila o alvo cruzando suas foices ou garras como se elas fossem um par de tesouras." effect: "O usuário cutila o alvo cruzando suas foices ou garras como se elas fossem um par de tesouras."
}, },
@ -2225,7 +2225,7 @@ export const move: MoveTranslationEntries = {
name: "Icicle Crash", name: "Icicle Crash",
effect: "O usuário ataca arremessando estacas de gelo no alvo violentamente. Isso também pode fazer o alvo hesitar." effect: "O usuário ataca arremessando estacas de gelo no alvo violentamente. Isso também pode fazer o alvo hesitar."
}, },
"v-Create": { "vCreate": {
name: "V-create", name: "V-create",
effect: "Com uma ardente chama em sua testa, o usuário joga seu corpo em direção ao alvo. Isso diminui a Defesa, Defesa Especial, e Velocidade do usuário." effect: "Com uma ardente chama em sua testa, o usuário joga seu corpo em direção ao alvo. Isso diminui a Defesa, Defesa Especial, e Velocidade do usuário."
}, },
@ -2265,7 +2265,7 @@ export const move: MoveTranslationEntries = {
name: "Phantom Force", name: "Phantom Force",
effect: "O usuário desaparece para algum lugar e então ataca o alvo no próximo turno. Esse movimento acerta mesmo se o alvo estiver se protegendo." effect: "O usuário desaparece para algum lugar e então ataca o alvo no próximo turno. Esse movimento acerta mesmo se o alvo estiver se protegendo."
}, },
"trick-Or-Treat": { "trickOrTreat": {
name: "Trick-or-Treat", name: "Trick-or-Treat",
effect: "O usuário enche o alvo com o espírito do Halloween para celebrarem juntos. Isso adiciona o tipo Fantasma à tipagem do alvo." effect: "O usuário enche o alvo com o espírito do Halloween para celebrarem juntos. Isso adiciona o tipo Fantasma à tipagem do alvo."
}, },
@ -2289,7 +2289,7 @@ export const move: MoveTranslationEntries = {
name: "Petal Blizzard", name: "Petal Blizzard",
effect: "O usuário rotaciona uma violenta nevasca composta por pétalas e ataca tudo ao seu redor." effect: "O usuário rotaciona uma violenta nevasca composta por pétalas e ataca tudo ao seu redor."
}, },
"freeze-Dry": { "freezeDry": {
name: "Freeze-Dry", name: "Freeze-Dry",
effect: "O usuário rapidamente diminui a temperatura do alvo. Isso pode deixar o alvo congelado. Esse movimento é supereficaz contra tipos Água." effect: "O usuário rapidamente diminui a temperatura do alvo. Isso pode deixar o alvo congelado. Esse movimento é supereficaz contra tipos Água."
}, },
@ -2301,7 +2301,7 @@ export const move: MoveTranslationEntries = {
name: "Parting Shot", name: "Parting Shot",
effect: "O usuário diminui os atributos de Ataque e Ataque Esp. do alvo com uma ameaça antes de ser trocado por outro Pokémon na equipe." effect: "O usuário diminui os atributos de Ataque e Ataque Esp. do alvo com uma ameaça antes de ser trocado por outro Pokémon na equipe."
}, },
"topsy-Turvy": { "topsyTurvy": {
name: "Topsy-Turvy", name: "Topsy-Turvy",
effect: "Todas as mudanças de atributos afetando o alvo viram de cabeça para baixo e se tornam o oposto do que eram." effect: "Todas as mudanças de atributos afetando o alvo viram de cabeça para baixo e se tornam o oposto do que eram."
}, },
@ -2429,7 +2429,7 @@ export const move: MoveTranslationEntries = {
name: "Hold Hands", name: "Hold Hands",
effect: "O usuário e um aliado dão as mãos. Isso os deixam muito contentes." effect: "O usuário e um aliado dão as mãos. Isso os deixam muito contentes."
}, },
"baby-DollEyes": { "babyDollEyes": {
name: "Baby-Doll Eyes", name: "Baby-Doll Eyes",
effect: "O usuário encara o alvo com seus olhos adoráveis, o que diminui seu atributo de Ataque. Esse movimento tem prioridade." effect: "O usuário encara o alvo com seus olhos adoráveis, o que diminui seu atributo de Ataque. Esse movimento tem prioridade."
}, },
@ -2445,7 +2445,7 @@ export const move: MoveTranslationEntries = {
name: "Infestation", name: "Infestation",
effect: "O alvo é infestado e atacado de quatro a cinco turnos. O alvo não pode fugir durante esse período." effect: "O alvo é infestado e atacado de quatro a cinco turnos. O alvo não pode fugir durante esse período."
}, },
"power-UpPunch": { "powerUpPunch": {
name: "Power-Up Punch", name: "Power-Up Punch",
effect: "Golpear oponentes repetidamente faz os punhos do usuário enrijecerem. Acertar um alvo aumenta o Ataque." effect: "Golpear oponentes repetidamente faz os punhos do usuário enrijecerem. Acertar um alvo aumenta o Ataque."
}, },
@ -2541,11 +2541,11 @@ export const move: MoveTranslationEntries = {
name: "Savage Spin-Out", name: "Savage Spin-Out",
effect: "Dummy Data" effect: "Dummy Data"
}, },
"never-EndingNightmarePhysical": { "neverEndingNightmarePhysical": {
name: "Never-Ending Nightmare", name: "Never-Ending Nightmare",
effect: "Utilizando o Poder Z, o usuário invoca espectros rancorosos que sufocam o alvo. Seu poder varia dependendo do movimento original." effect: "Utilizando o Poder Z, o usuário invoca espectros rancorosos que sufocam o alvo. Seu poder varia dependendo do movimento original."
}, },
"never-EndingNightmareSpecial": { "neverEndingNightmareSpecial": {
name: "Never-Ending Nightmare", name: "Never-Ending Nightmare",
effect: "Dummy Data" effect: "Dummy Data"
}, },
@ -2793,7 +2793,7 @@ export const move: MoveTranslationEntries = {
name: "Guardian of Alola", name: "Guardian of Alola",
effect: "Utilizando o Poder Z, o Espírito Nativo canaliza a energia de Alola e ataca o alvo com força total. Reduz muito os PS do alvo." effect: "Utilizando o Poder Z, o Espírito Nativo canaliza a energia de Alola e ataca o alvo com força total. Reduz muito os PS do alvo."
}, },
"soul-Stealing7-StarStrike": { "soulStealing7StarStrike": {
name: "Soul-Stealing 7-Star Strike", name: "Soul-Stealing 7-Star Strike",
effect: "Quando um Marshadow obtém o Poder Z, ele ataca o alvo consecutivamente com socos e chutes usando força total." effect: "Quando um Marshadow obtém o Poder Z, ele ataca o alvo consecutivamente com socos e chutes usando força total."
}, },
@ -2865,11 +2865,11 @@ export const move: MoveTranslationEntries = {
name: "Zing Zap", name: "Zing Zap",
effect: "Uma forte explosão elétrica que cai sobre o alvo, eletrocutando-o e podendo fazê-lo hesitar." effect: "Uma forte explosão elétrica que cai sobre o alvo, eletrocutando-o e podendo fazê-lo hesitar."
}, },
"natureSMadness": { "naturesMadness": {
name: "Natures Madness", name: "Nature's Madness",
effect: "O usuário atinge o alvo com a força da natureza. Reduz os PS do alvo pela metade." effect: "O usuário atinge o alvo com a força da natureza. Reduz os PS do alvo pela metade."
}, },
"multi-Attack": { "multiAttack": {
name: "Multi-Attack", name: "Multi-Attack",
effect: "Se envolvendo em energia concentrada, o usuário acerta o alvo. A memória segurada determina o tipo do movimento." effect: "Se envolvendo em energia concentrada, o usuário acerta o alvo. A memória segurada determina o tipo do movimento."
}, },
@ -2915,7 +2915,7 @@ export const move: MoveTranslationEntries = {
}, },
zippyZap: { zippyZap: {
name: "Zippy Zap", name: "Zippy Zap",
effect: "The user attacks the target with bursts of electricity at high speed. This move always goes first and raises the user's evasiveness." effect: "O usuário ataca o alvo com rajadas de eletricidade em alta velocidade. Esse movimento sempre vai primeiro e aumenta a Evasão do usuário."
}, },
splishySplash: { splishySplash: {
name: "Splishy Splash", name: "Splishy Splash",
@ -3479,7 +3479,7 @@ export const move: MoveTranslationEntries = {
}, },
"gMaxTartness": { "gMaxTartness": {
name: "G-Max Tartness", name: "G-Max Tartness",
effect: "Um ataque do tipo Planta que Gigantamax Flapple usa. Este movimento reduz a evasão dos oponentes." effect: "Um ataque do tipo Planta que Gigantamax Flapple usa. Este movimento reduz a Evasão dos oponentes."
}, },
"gMaxSweetness": { "gMaxSweetness": {
name: "G-Max Sweetness", name: "G-Max Sweetness",

View File

@ -4,7 +4,7 @@ export const nature: SimpleTranslationEntries = {
"Hardy": "Destemida", "Hardy": "Destemida",
"Lonely": "Solitária", "Lonely": "Solitária",
"Brave": "Valente", "Brave": "Valente",
"Adamant": "Rígida", "Adamant": "Adamante",
"Naughty": "Teimosa", "Naughty": "Teimosa",
"Bold": "Corajosa", "Bold": "Corajosa",
"Docile": "Dócil", "Docile": "Dócil",
@ -20,7 +20,7 @@ export const nature: SimpleTranslationEntries = {
"Mild": "Mansa", "Mild": "Mansa",
"Quiet": "Quieta", "Quiet": "Quieta",
"Bashful": "Atrapalhada", "Bashful": "Atrapalhada",
"Rash": "Rabugenta", "Rash": "Ousada",
"Calm": "Calma", "Calm": "Calma",
"Gentle": "Gentil", "Gentle": "Gentil",
"Sassy": "Atrevida", "Sassy": "Atrevida",

View File

@ -1,11 +1,11 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const pokemonInfoContainer: SimpleTranslationEntries = { export const pokemonInfoContainer: SimpleTranslationEntries = {
"moveset": "Moveset", "moveset": "Movimentos",
"gender": "Gender:", "gender": "Gênero:",
"ability": "Ability:", "ability": "Habilidade:",
"nature": "Nature:", "nature": "Natureza:",
"epic": "Epic", "epic": "Épico",
"rare": "Rare", "rare": "Raro",
"common": "Common" "common": "Comum",
} as const; } as const;

View File

@ -7,15 +7,15 @@ import { SimpleTranslationEntries } from "#app/plugins/i18n";
*/ */
export const starterSelectUiHandler: SimpleTranslationEntries = { export const starterSelectUiHandler: SimpleTranslationEntries = {
"confirmStartTeam": "Começar com esses Pokémon?", "confirmStartTeam": "Começar com esses Pokémon?",
"gen1": "I", "gen1": "G1",
"gen2": "II", "gen2": "G2",
"gen3": "III", "gen3": "G3",
"gen4": "IV", "gen4": "G4",
"gen5": "V", "gen5": "G5",
"gen6": "VI", "gen6": "G6",
"gen7": "VII", "gen7": "G7",
"gen8": "VIII", "gen8": "G8",
"gen9": "IX", "gen9": "G9",
"growthRate": "Crescimento:", "growthRate": "Crescimento:",
"ability": "Habilidade:", "ability": "Habilidade:",
"passive": "Passiva:", "passive": "Passiva:",
@ -30,12 +30,12 @@ export const starterSelectUiHandler: SimpleTranslationEntries = {
"selectMoveSwapWith": "Escolha o movimento que substituirá", "selectMoveSwapWith": "Escolha o movimento que substituirá",
"unlockPassive": "Aprender Passiva", "unlockPassive": "Aprender Passiva",
"reduceCost": "Reduzir Custo", "reduceCost": "Reduzir Custo",
"cycleShiny": "R: Mudar Shiny", "cycleShiny": "R: » Shiny",
"cycleForm": "F: Mudar Forma", "cycleForm": "F: » Forma",
"cycleGender": "G: Mudar Gênero", "cycleGender": "G: » Gênero",
"cycleAbility": "E: Mudar Habilidade", "cycleAbility": "E: » Habilidade",
"cycleNature": "N: Mudar Natureza", "cycleNature": "N: » Natureza",
"cycleVariant": "V: Mudar Variante", "cycleVariant": "V: » Variante",
"enablePassive": "Ativar Passiva", "enablePassive": "Ativar Passiva",
"disablePassive": "Desativar Passiva", "disablePassive": "Desativar Passiva",
"locked": "Bloqueada", "locked": "Bloqueada",

View File

@ -1,44 +1,44 @@
import { SimpleTranslationEntries } from "#app/plugins/i18n"; import { SimpleTranslationEntries } from "#app/plugins/i18n";
export const gameStatsUiHandler: SimpleTranslationEntries = { export const gameStatsUiHandler: SimpleTranslationEntries = {
"stats": "Stats", "stats": "统计",
"playTime": "Play Time", "playTime": "游戏时间",
"totalBattles": "Total Battles", "totalBattles": "总战斗次数",
"starters": "Starters", "starters": "初始宝可梦",
"shinyStarters": "Shiny Starters", "shinyStarters": "闪光初始宝可梦",
"speciesSeen": "Species Seen", "speciesSeen": "遇到的种类",
"speciesCaught": "Species Caught", "speciesCaught": "捕捉的种类",
"ribbonsOwned": "Ribbons Owned", "ribbonsOwned": "拥有缎带数",
"classicRuns": "Classic Runs", "classicRuns": "经典模式次数",
"classicWins": "Classic Wins", "classicWins": "经典模式通关次数",
"dailyRunAttempts": "Daily Run Attempts", "dailyRunAttempts": "每日挑战次数",
"dailyRunWins": "Daily Run Wins", "dailyRunWins": "每日挑战通关次数",
"endlessRuns": "Endless Runs", "endlessRuns": "无尽模式挑战次数",
"highestWaveEndless": "Highest Wave (Endless)", "highestWaveEndless": "最高层数(无尽)",
"highestMoney": "Highest Money", "highestMoney": "最多金钱",
"highestDamage": "Highest Damage", "highestDamage": "最高伤害",
"highestHPHealed": "Highest HP Healed", "highestHPHealed": "最多治疗",
"pokemonEncountered": "Pokémon Encountered", "pokemonEncountered": "遇敌数量",
"pokemonDefeated": "Pokémon Defeated", "pokemonDefeated": "打倒数量",
"pokemonCaught": "Pokémon Caught", "pokemonCaught": "捕捉数量",
"eggsHatched": "Eggs Hatched", "eggsHatched": "孵蛋数量",
"subLegendsSeen": "Sub-Legends Seen", "subLegendsSeen": "遇到的二级神宝可梦",
"subLegendsCaught": "Sub-Legends Caught", "subLegendsCaught": "捕捉的二级神宝可梦",
"subLegendsHatched": "Sub-Legends Hatched", "subLegendsHatched": "孵化的二级神宝可梦",
"legendsSeen": "Legends Seen", "legendsSeen": "遇到的传说宝可梦",
"legendsCaught": "Legends Caught", "legendsCaught": "捕捉的传说宝可梦",
"legendsHatched": "Legends Hatched", "legendsHatched": "孵化的传说宝可梦",
"mythicalsSeen": "Mythicals Seen", "mythicalsSeen": "遇到的幻兽宝可梦",
"mythicalsCaught": "Mythicals Caught", "mythicalsCaught": "捕捉的幻兽宝可梦",
"mythicalsHatched": "Mythicals Hatched", "mythicalsHatched": "孵化的幻兽宝可梦",
"shiniesSeen": "Shinies Seen", "shiniesSeen": "遇到的闪光宝可梦",
"shiniesCaught": "Shinies Caught", "shiniesCaught": "捕捉的闪光宝可梦",
"shiniesHatched": "Shinies Hatched", "shiniesHatched": "孵化的闪光宝可梦",
"pokemonFused": "Pokémon Fused", "pokemonFused": "融合宝可梦次数",
"trainersDefeated": "Trainers Defeated", "trainersDefeated": "打败的训练师数",
"eggsPulled": "Eggs Pulled", "eggsPulled": "总扭蛋次数",
"rareEggsPulled": "Rare Eggs Pulled", "rareEggsPulled": "稀有扭蛋数",
"epicEggsPulled": "Epic Eggs Pulled", "epicEggsPulled": "史诗扭蛋数",
"legendaryEggsPulled": "Legendary Eggs Pulled", "legendaryEggsPulled": "传说扭蛋数",
"manaphyEggsPulled": "Manaphy Eggs Pulled", "manaphyEggsPulled": "玛娜霏扭蛋数",
} as const; } as const;

View File

@ -30,7 +30,7 @@ import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, get
import { TempBattleStat } from "./data/temp-battle-stat"; import { TempBattleStat } from "./data/temp-battle-stat";
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag"; import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
import { ArenaTagType } from "./data/enums/arena-tag-type"; import { ArenaTagType } from "./data/enums/arena-tag-type";
import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, applyPostBattleInitAbAttrs, PostBattleInitAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr } from "./data/ability"; import { CheckTrappedAbAttr, IgnoreOpponentStatChangesAbAttr, IgnoreOpponentEvasionAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, BattleStatMultiplierAbAttr, applyBattleStatMultiplierAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr } from "./data/ability";
import { Unlockables, getUnlockableName } from "./system/unlockables"; import { Unlockables, getUnlockableName } from "./system/unlockables";
import { getBiomeKey } from "./field/arena"; import { getBiomeKey } from "./field/arena";
import { BattleType, BattlerIndex, TurnCommand } from "./battle"; import { BattleType, BattlerIndex, TurnCommand } from "./battle";
@ -987,18 +987,14 @@ export class EncounterPhase extends BattlePhase {
if (!this.loaded) { if (!this.loaded) {
const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted()); const availablePartyMembers = this.scene.getParty().filter(p => !p.isFainted());
if (availablePartyMembers[0].isOnField()) { if (!availablePartyMembers[0].isOnField()) {
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, availablePartyMembers[0]);
} else {
this.scene.pushPhase(new SummonPhase(this.scene, 0)); this.scene.pushPhase(new SummonPhase(this.scene, 0));
} }
if (this.scene.currentBattle.double) { if (this.scene.currentBattle.double) {
if (availablePartyMembers.length > 1) { if (availablePartyMembers.length > 1) {
this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, true)); this.scene.pushPhase(new ToggleDoublePositionPhase(this.scene, true));
if (availablePartyMembers[1].isOnField()) { if (!availablePartyMembers[1].isOnField()) {
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, availablePartyMembers[1]);
} else {
this.scene.pushPhase(new SummonPhase(this.scene, 1)); this.scene.pushPhase(new SummonPhase(this.scene, 1));
} }
} }
@ -1475,8 +1471,6 @@ export class SwitchSummonPhase extends SummonPhase {
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.removeTagsBySourceId(pokemon.id)); (this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.removeTagsBySourceId(pokemon.id));
} }
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, pokemon);
this.scene.ui.showText(this.player ? this.scene.ui.showText(this.player ?
i18next.t("battle:playerComeBack", { pokemonName: pokemon.name }) : i18next.t("battle:playerComeBack", { pokemonName: pokemon.name }) :
i18next.t("battle:trainerComeBack", { i18next.t("battle:trainerComeBack", {
@ -1505,6 +1499,7 @@ export class SwitchSummonPhase extends SummonPhase {
const party = this.player ? this.getParty() : this.scene.getEnemyParty(); const party = this.player ? this.getParty() : this.scene.getEnemyParty();
const switchedPokemon = party[this.slotIndex]; const switchedPokemon = party[this.slotIndex];
this.lastPokemon = this.getPokemon(); this.lastPokemon = this.getPokemon();
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon);
if (this.batonPass && switchedPokemon) { if (this.batonPass && switchedPokemon) {
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id)); (this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id));
if (!this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) { if (!this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) {

View File

@ -47,11 +47,11 @@ export class SceneBase extends Phaser.Scene {
if (folder) { if (folder) {
folder += "/"; folder += "/";
} }
this.load.atlas(key, this.getCachedUrl(`images/${folder}${filenameRoot}.png`), this.getCachedUrl(`images/${folder}/${filenameRoot}.json`)); this.load.atlas(key, this.getCachedUrl(`images/${folder}${filenameRoot}.png`), this.getCachedUrl(`images/${folder}${filenameRoot}.json`));
if (folder.startsWith("ui")) { if (folder.startsWith("ui")) {
legacyCompatibleImages.push(key); legacyCompatibleImages.push(key);
folder = folder.replace("ui", "ui/legacy"); folder = folder.replace("ui", "ui/legacy");
this.load.atlas(`${key}_legacy`, this.getCachedUrl(`images/${folder}${filenameRoot}.png`), this.getCachedUrl(`images/${folder}/${filenameRoot}.json`)); this.load.atlas(`${key}_legacy`, this.getCachedUrl(`images/${folder}${filenameRoot}.png`), this.getCachedUrl(`images/${folder}${filenameRoot}.json`));
} }
} }

View File

@ -1,16 +1,48 @@
import { getVariantTint } from "#app/data/variant";
import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
import BattleScene from "../battle-scene"; import BattleScene from "../battle-scene";
import { Gender, getGenderColor, getGenderSymbol } from "../data/gender"; import { Gender, getGenderColor, getGenderSymbol } from "../data/gender";
import { getNatureName } from "../data/nature";
import { Type } from "../data/type";
import Pokemon from "../field/pokemon"; import Pokemon from "../field/pokemon";
import i18next from "../plugins/i18n";
import * as Utils from "../utils";
import ConfirmUiHandler from "./confirm-ui-handler";
import { StatsContainer } from "./stats-container"; import { StatsContainer } from "./stats-container";
import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text"; import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text";
import { addWindow } from "./ui-theme"; import { addWindow } from "./ui-theme";
import { getNatureName } from "../data/nature";
import * as Utils from "../utils"; interface LanguageSetting {
import { Type } from "../data/type"; infoContainerTextSize: string;
import { getVariantTint } from "#app/data/variant"; infoContainerLabelXPos?: integer;
import ConfirmUiHandler from "./confirm-ui-handler"; infoContainerTextXPos?: integer;
import i18next from "../plugins/i18n"; }
const languageSettings: { [key: string]: LanguageSetting } = {
"en": {
infoContainerTextSize: "64px"
},
"de": {
infoContainerTextSize: "64px"
},
"es": {
infoContainerTextSize: "64px"
},
"fr": {
infoContainerTextSize: "64px"
},
"it": {
infoContainerTextSize: "64px"
},
"zh": {
infoContainerTextSize: "64px"
},
"pt": {
infoContainerTextSize: "60px",
infoContainerLabelXPos: -16,
infoContainerTextXPos: -12,
},
};
export default class PokemonInfoContainer extends Phaser.GameObjects.Container { export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
private readonly infoWindowWidth = 104; private readonly infoWindowWidth = 104;
@ -41,6 +73,9 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
} }
setup(): void { setup(): void {
const currentLanguage = i18next.language;
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey];
const infoBg = addWindow(this.scene, 0, 0, this.infoWindowWidth, 132); const infoBg = addWindow(this.scene, 0, 0, this.infoWindowWidth, 132);
infoBg.setOrigin(0.5, 0.5); infoBg.setOrigin(0.5, 0.5);
@ -87,29 +122,36 @@ export default class PokemonInfoContainer extends Phaser.GameObjects.Container {
this.add(infoBg); this.add(infoBg);
this.add(this.statsContainer); this.add(this.statsContainer);
this.pokemonGenderLabelText = addTextObject(this.scene, -18, 18, i18next.t("pokemonInfoContainer:gender"), TextStyle.WINDOW, { fontSize: "64px" }); // The position should be set per language
const infoContainerLabelXPos = textSettings?.infoContainerLabelXPos || -18;
const infoContainerTextXPos = textSettings?.infoContainerTextXPos || -14;
// The font size should be set by language
const infoContainerTextSize = textSettings?.infoContainerTextSize || "64px";
this.pokemonGenderLabelText = addTextObject(this.scene, infoContainerLabelXPos, 18, i18next.t("pokemonInfoContainer:gender"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonGenderLabelText.setOrigin(1, 0); this.pokemonGenderLabelText.setOrigin(1, 0);
this.pokemonGenderLabelText.setVisible(false); this.pokemonGenderLabelText.setVisible(false);
this.add(this.pokemonGenderLabelText); this.add(this.pokemonGenderLabelText);
this.pokemonGenderText = addTextObject(this.scene, -14, 18, "", TextStyle.WINDOW, { fontSize: "64px" }); this.pokemonGenderText = addTextObject(this.scene, infoContainerTextXPos, 18, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonGenderText.setOrigin(0, 0); this.pokemonGenderText.setOrigin(0, 0);
this.pokemonGenderText.setVisible(false); this.pokemonGenderText.setVisible(false);
this.add(this.pokemonGenderText); this.add(this.pokemonGenderText);
this.pokemonAbilityLabelText = addTextObject(this.scene, -18, 28, i18next.t("pokemonInfoContainer:ability"), TextStyle.WINDOW, { fontSize: "64px" }); this.pokemonAbilityLabelText = addTextObject(this.scene, infoContainerLabelXPos, 28, i18next.t("pokemonInfoContainer:ability"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonAbilityLabelText.setOrigin(1, 0); this.pokemonAbilityLabelText.setOrigin(1, 0);
this.add(this.pokemonAbilityLabelText); this.add(this.pokemonAbilityLabelText);
this.pokemonAbilityText = addTextObject(this.scene, -14, 28, "", TextStyle.WINDOW, { fontSize: "64px" }); this.pokemonAbilityText = addTextObject(this.scene, infoContainerTextXPos, 28, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonAbilityText.setOrigin(0, 0); this.pokemonAbilityText.setOrigin(0, 0);
this.add(this.pokemonAbilityText); this.add(this.pokemonAbilityText);
this.pokemonNatureLabelText = addTextObject(this.scene, -18, 38, i18next.t("pokemonInfoContainer:nature"), TextStyle.WINDOW, { fontSize: "64px" }); this.pokemonNatureLabelText = addTextObject(this.scene, infoContainerLabelXPos, 38, i18next.t("pokemonInfoContainer:nature"), TextStyle.WINDOW, { fontSize: infoContainerTextSize });
this.pokemonNatureLabelText.setOrigin(1, 0); this.pokemonNatureLabelText.setOrigin(1, 0);
this.add(this.pokemonNatureLabelText); this.add(this.pokemonNatureLabelText);
this.pokemonNatureText = addBBCodeTextObject(this.scene, -14, 38, "", TextStyle.WINDOW, { fontSize: "64px", lineSpacing: 3, maxLines: 2 }); this.pokemonNatureText = addBBCodeTextObject(this.scene, infoContainerTextXPos, 38, "", TextStyle.WINDOW, { fontSize: infoContainerTextSize, lineSpacing: 3, maxLines: 2 });
this.pokemonNatureText.setOrigin(0, 0); this.pokemonNatureText.setOrigin(0, 0);
this.add(this.pokemonNatureText); this.add(this.pokemonNatureText);

View File

@ -76,9 +76,9 @@ const languageSettings: { [key: string]: LanguageSetting } = {
starterInfoYOffset: 2 starterInfoYOffset: 2
}, },
"pt":{ "pt":{
starterInfoTextSize: "47px", starterInfoTextSize: "48px",
instructionTextSize: "38px", instructionTextSize: "42px",
starterInfoXPos: 32, starterInfoXPos: 33,
}, },
}; };