Merge branch 'beta' of https://github.com/pagefaultgames/pokerogue into new-modifier-rework

This commit is contained in:
Wlowscha 2025-08-09 22:35:54 +02:00
commit 238691c8bf
No known key found for this signature in database
GPG Key ID: 3C8F1AD330565D04
118 changed files with 2357 additions and 1394 deletions

12
.github/CODEOWNERS vendored
View File

@ -3,9 +3,6 @@
# everything (whole code-base) - Junior Devs # everything (whole code-base) - Junior Devs
* @pagefaultgames/junior-dev-team * @pagefaultgames/junior-dev-team
# github actions/templates etc. - Dev Leads
/.github @pagefaultgames/senior-dev-team
# Art Team # Art Team
/public/**/*.png @pagefaultgames/art-team /public/**/*.png @pagefaultgames/art-team
/public/**/*.json @pagefaultgames/art-team /public/**/*.json @pagefaultgames/art-team
@ -19,4 +16,11 @@
/public/audio @pagefaultgames/composer-team /public/audio @pagefaultgames/composer-team
# Balance Files; contain actual code logic and must also be owned by dev team # Balance Files; contain actual code logic and must also be owned by dev team
/src/data/balance @pagefaultgames/balance-team @pagefaultgames/junior-dev-team /src/data/balance @pagefaultgames/balance-team @pagefaultgames/junior-dev-team
/src/data/trainers @pagefaultgames/balance-team @pagefaultgames/junior-dev-team
# GitHub actions/templates etc. - Senior Devs
# Should be defined last in the file to make sure these always override all other definitions
/.github @pagefaultgames/senior-dev-team
package.json @pagefaultgames/senior-dev-team
pnpm-lock.yaml @pagefaultgames/senior-dev-team

BIN
public/images/logo_fake.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "rocket_boss_giovanni_1.png",
"format": "RGBA8888",
"size": {
"w": 79,
"h": 79
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 39,
"h": 79
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 39,
"h": 79
},
"frame": {
"x": 0,
"y": 0,
"w": 39,
"h": 79
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:d6c5e1804414106d43a7c46f83468d39:1f3f7898a58950988acac6ee7167e012:5f742cbdaafcd5ae864f18ec2af7512a$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 292 B

@ -1 +1 @@
Subproject commit fa35780fed762017c89d1e9ece8a2779dff56c4d Subproject commit ab2716d5440c25f73986664aa3f3131821c3c392

View File

@ -16,7 +16,7 @@ export type * from "#moves/move";
* Map of move subclass names to their respective classes. * Map of move subclass names to their respective classes.
* Does not include the ChargeMove subclasses. For that, use `ChargingMoveClassMap`. * Does not include the ChargeMove subclasses. For that, use `ChargingMoveClassMap`.
* *
* @privateremarks * @privateRemarks
* The `never` field (`declare private _: never`) in some classes is necessary * The `never` field (`declare private _: never`) in some classes is necessary
* to ensure typescript does not improperly narrow a failed `is` guard to `never`. * to ensure typescript does not improperly narrow a failed `is` guard to `never`.
* *

View File

@ -232,8 +232,8 @@ export class BattleScene extends SceneBase {
public battleStyle: BattleStyle = BattleStyle.SWITCH; public battleStyle: BattleStyle = BattleStyle.SWITCH;
/** /**
* Defines whether or not to show type effectiveness hints * Defines whether or not to show type effectiveness hints
* - true: No hints * - true: Show hints for moves
* - false: Show hints for moves * - false: No hints
*/ */
public typeHints = false; public typeHints = false;
@ -468,8 +468,8 @@ export class BattleScene extends SceneBase {
this.uiContainer = uiContainer; this.uiContainer = uiContainer;
const overlayWidth = this.game.canvas.width / 6; const overlayWidth = this.scaledCanvas.width;
const overlayHeight = this.game.canvas.height / 6 - 48; const overlayHeight = this.scaledCanvas.height - 48;
this.fieldOverlay = this.add.rectangle(0, overlayHeight * -1 - 48, overlayWidth, overlayHeight, 0x424242); this.fieldOverlay = this.add.rectangle(0, overlayHeight * -1 - 48, overlayWidth, overlayHeight, 0x424242);
this.fieldOverlay.setName("rect-field-overlay"); this.fieldOverlay.setName("rect-field-overlay");
this.fieldOverlay.setOrigin(0, 0); this.fieldOverlay.setOrigin(0, 0);
@ -527,34 +527,29 @@ export class BattleScene extends SceneBase {
this.candyBar.setup(); this.candyBar.setup();
this.fieldUI.add(this.candyBar); this.fieldUI.add(this.candyBar);
this.biomeWaveText = addTextObject( this.biomeWaveText = addTextObject(this.scaledCanvas.width - 2, 0, startingWave.toString(), TextStyle.BATTLE_INFO);
this.game.canvas.width / 6 - 2,
0,
startingWave.toString(),
TextStyle.BATTLE_INFO,
);
this.biomeWaveText.setName("text-biome-wave"); this.biomeWaveText.setName("text-biome-wave");
this.biomeWaveText.setOrigin(1, 0.5); this.biomeWaveText.setOrigin(1, 0.5);
this.fieldUI.add(this.biomeWaveText); this.fieldUI.add(this.biomeWaveText);
this.moneyText = addTextObject(this.game.canvas.width / 6 - 2, 0, "", TextStyle.MONEY); this.moneyText = addTextObject(this.scaledCanvas.width - 2, 0, "", TextStyle.MONEY);
this.moneyText.setName("text-money"); this.moneyText.setName("text-money");
this.moneyText.setOrigin(1, 0.5); this.moneyText.setOrigin(1, 0.5);
this.fieldUI.add(this.moneyText); this.fieldUI.add(this.moneyText);
this.scoreText = addTextObject(this.game.canvas.width / 6 - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" }); this.scoreText = addTextObject(this.scaledCanvas.width - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" });
this.scoreText.setName("text-score"); this.scoreText.setName("text-score");
this.scoreText.setOrigin(1, 0.5); this.scoreText.setOrigin(1, 0.5);
this.fieldUI.add(this.scoreText); this.fieldUI.add(this.scoreText);
this.luckText = addTextObject(this.game.canvas.width / 6 - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" }); this.luckText = addTextObject(this.scaledCanvas.width - 2, 0, "", TextStyle.PARTY, { fontSize: "54px" });
this.luckText.setName("text-luck"); this.luckText.setName("text-luck");
this.luckText.setOrigin(1, 0.5); this.luckText.setOrigin(1, 0.5);
this.luckText.setVisible(false); this.luckText.setVisible(false);
this.fieldUI.add(this.luckText); this.fieldUI.add(this.luckText);
this.luckLabelText = addTextObject( this.luckLabelText = addTextObject(
this.game.canvas.width / 6 - 2, this.scaledCanvas.width - 2,
0, 0,
i18next.t("common:luckIndicator"), i18next.t("common:luckIndicator"),
TextStyle.PARTY, TextStyle.PARTY,
@ -576,10 +571,7 @@ export class BattleScene extends SceneBase {
this.spriteSparkleHandler = new PokemonSpriteSparkleHandler(); this.spriteSparkleHandler = new PokemonSpriteSparkleHandler();
this.spriteSparkleHandler.setup(); this.spriteSparkleHandler.setup();
this.pokemonInfoContainer = new PokemonInfoContainer( this.pokemonInfoContainer = new PokemonInfoContainer(this.scaledCanvas.width + 52, -this.scaledCanvas.height + 66);
this.game.canvas.width / 6 + 52,
-(this.game.canvas.height / 6) + 66,
);
this.pokemonInfoContainer.setup(); this.pokemonInfoContainer.setup();
this.fieldUI.add(this.pokemonInfoContainer); this.fieldUI.add(this.pokemonInfoContainer);
@ -2040,7 +2032,7 @@ export class BattleScene extends SceneBase {
} else { } else {
this.luckText.setTint(0xffef5c, 0x47ff69, 0x6b6bff, 0xff6969); this.luckText.setTint(0xffef5c, 0x47ff69, 0x6b6bff, 0xff6969);
} }
this.luckLabelText.setX(this.game.canvas.width / 6 - 2 - (this.luckText.displayWidth + 2)); this.luckLabelText.setX(this.scaledCanvas.width - 2 - (this.luckText.displayWidth + 2));
this.tweens.add({ this.tweens.add({
targets: labels, targets: labels,
duration: duration, duration: duration,
@ -2074,7 +2066,7 @@ export class BattleScene extends SceneBase {
const enemyItemCount = this.enemyItemBar.totalVisibleLength; const enemyItemCount = this.enemyItemBar.totalVisibleLength;
const biomeWaveTextHeight = this.biomeWaveText.getBottomLeft().y - this.biomeWaveText.getTopLeft().y; const biomeWaveTextHeight = this.biomeWaveText.getBottomLeft().y - this.biomeWaveText.getTopLeft().y;
this.biomeWaveText.setY( this.biomeWaveText.setY(
-(this.game.canvas.height / 6) + -this.scaledCanvas.height +
(enemyItemCount ? (enemyItemCount <= 12 ? 15 : 24) : 0) + (enemyItemCount ? (enemyItemCount <= 12 ? 15 : 24) : 0) +
biomeWaveTextHeight / 2, biomeWaveTextHeight / 2,
); );
@ -2086,7 +2078,7 @@ export class BattleScene extends SceneBase {
const offsetY = (this.scoreText.visible ? this.scoreText : this.moneyText).y + 15; const offsetY = (this.scoreText.visible ? this.scoreText : this.moneyText).y + 15;
this.partyExpBar.setY(offsetY); this.partyExpBar.setY(offsetY);
this.candyBar.setY(offsetY + 15); this.candyBar.setY(offsetY + 15);
this.ui?.achvBar.setY(this.game.canvas.height / 6 + offsetY); this.ui?.achvBar.setY(this.scaledCanvas.height + offsetY);
} }
/** /**

View File

@ -94,3 +94,10 @@ export const AVERAGE_ENCOUNTERS_PER_RUN_TARGET = 12;
* So anti-variance adds -15/256 to the spawn weight check for ME spawn. * So anti-variance adds -15/256 to the spawn weight check for ME spawn.
*/ */
export const ANTI_VARIANCE_WEIGHT_MODIFIER = 15; export const ANTI_VARIANCE_WEIGHT_MODIFIER = 15;
/**
* The chance (out of 1) that a different title logo will show when the title screen is drawn.
* Inverted during April Fools (such that this becomes the chance for the _normal_ title logo is displayed).
* Default: `10000` (0.01%)
*/
export const FAKE_TITLE_LOGO_CHANCE = 10000;

View File

@ -1284,7 +1284,7 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr {
/** /**
* Set stat stages when the user gets hit by a critical hit * Set stat stages when the user gets hit by a critical hit
* *
* @privateremarks * @privateRemarks
* It is the responsibility of the caller to ensure that this ability attribute is only applied * It is the responsibility of the caller to ensure that this ability attribute is only applied
* when the user has been hit by a critical hit; such an event is not checked here. * when the user has been hit by a critical hit; such an event is not checked here.
* *
@ -2043,7 +2043,7 @@ export class AllyStatMultiplierAbAttr extends AbAttr {
/** /**
* @param stat - The stat being modified * @param stat - The stat being modified
* @param multipler - The multiplier to apply to the stat * @param multiplier - The multiplier to apply to the stat
* @param ignorable - Whether the multiplier can be ignored by mold breaker-like moves and abilities * @param ignorable - Whether the multiplier can be ignored by mold breaker-like moves and abilities
*/ */
constructor(stat: BattleStat, multiplier: number, ignorable = true) { constructor(stat: BattleStat, multiplier: number, ignorable = true) {
@ -5465,7 +5465,7 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr {
* Attribute used for abilities that damage opponents causing the user to faint * Attribute used for abilities that damage opponents causing the user to faint
* equal to the amount of damage the last attack inflicted. * equal to the amount of damage the last attack inflicted.
* *
* Used for {@linkcode Abilities.INNARDS_OUT}. * Used for {@linkcode AbilityId.INNARDS_OUT | Innards Out}.
* @sealed * @sealed
*/ */
export class PostFaintHPDamageAbAttr extends PostFaintAbAttr { export class PostFaintHPDamageAbAttr extends PostFaintAbAttr {
@ -6414,23 +6414,23 @@ export class PostDamageForceSwitchAbAttr extends PostDamageAbAttr {
public override canApply({ pokemon, source, damage }: PostDamageAbAttrParams): boolean { public override canApply({ pokemon, source, damage }: PostDamageAbAttrParams): boolean {
const moveHistory = pokemon.getMoveHistory(); const moveHistory = pokemon.getMoveHistory();
// Will not activate when the Pokémon's HP is lowered by cutting its own HP // Will not activate when the Pokémon's HP is lowered by cutting its own HP
const fordbiddenAttackingMoves = [MoveId.BELLY_DRUM, MoveId.SUBSTITUTE, MoveId.CURSE, MoveId.PAIN_SPLIT]; const forbiddenAttackingMoves = [MoveId.BELLY_DRUM, MoveId.SUBSTITUTE, MoveId.CURSE, MoveId.PAIN_SPLIT];
if (moveHistory.length > 0) { if (moveHistory.length > 0) {
const lastMoveUsed = moveHistory[moveHistory.length - 1]; const lastMoveUsed = moveHistory[moveHistory.length - 1];
if (fordbiddenAttackingMoves.includes(lastMoveUsed.move)) { if (forbiddenAttackingMoves.includes(lastMoveUsed.move)) {
return false; return false;
} }
} }
// Dragon Tail and Circle Throw switch out Pokémon before the Ability activates. // Dragon Tail and Circle Throw switch out Pokémon before the Ability activates.
const fordbiddenDefendingMoves = [MoveId.DRAGON_TAIL, MoveId.CIRCLE_THROW]; const forbiddenDefendingMoves = [MoveId.DRAGON_TAIL, MoveId.CIRCLE_THROW];
if (source) { if (source) {
const enemyMoveHistory = source.getMoveHistory(); const enemyMoveHistory = source.getMoveHistory();
if (enemyMoveHistory.length > 0) { if (enemyMoveHistory.length > 0) {
const enemyLastMoveUsed = enemyMoveHistory[enemyMoveHistory.length - 1]; const enemyLastMoveUsed = enemyMoveHistory[enemyMoveHistory.length - 1];
// Will not activate if the Pokémon's HP falls below half while it is in the air during Sky Drop. // Will not activate if the Pokémon's HP falls below half while it is in the air during Sky Drop.
if ( if (
fordbiddenDefendingMoves.includes(enemyLastMoveUsed.move) || forbiddenDefendingMoves.includes(enemyLastMoveUsed.move) ||
(enemyLastMoveUsed.move === MoveId.SKY_DROP && enemyLastMoveUsed.result === MoveResult.OTHER) (enemyLastMoveUsed.move === MoveId.SKY_DROP && enemyLastMoveUsed.result === MoveResult.OTHER)
) { ) {
return false; return false;
@ -7277,7 +7277,7 @@ export function initAbilities() {
.attr(HealFromBerryUseAbAttr, 1 / 3), .attr(HealFromBerryUseAbAttr, 1 / 3),
new Ability(AbilityId.PROTEAN, 6) new Ability(AbilityId.PROTEAN, 6)
.attr(PokemonTypeChangeAbAttr) .attr(PokemonTypeChangeAbAttr)
// .condition((p) => !p.summonData.abilitiesApplied.includes(Abilities.PROTEAN)) //Gen 9 Implementation // .condition((p) => !p.summonData.abilitiesApplied.includes(AbilityId.PROTEAN)) //Gen 9 Implementation
// TODO: needs testing on interaction with weather blockage // TODO: needs testing on interaction with weather blockage
.edgeCase(), .edgeCase(),
new Ability(AbilityId.FUR_COAT, 6) new Ability(AbilityId.FUR_COAT, 6)
@ -7536,7 +7536,7 @@ export function initAbilities() {
.attr(PostSummonStatStageChangeAbAttr, [ Stat.DEF ], 1, true), .attr(PostSummonStatStageChangeAbAttr, [ Stat.DEF ], 1, true),
new Ability(AbilityId.LIBERO, 8) new Ability(AbilityId.LIBERO, 8)
.attr(PokemonTypeChangeAbAttr) .attr(PokemonTypeChangeAbAttr)
//.condition((p) => !p.summonData.abilitiesApplied.includes(Abilities.LIBERO)), //Gen 9 Implementation //.condition((p) => !p.summonData.abilitiesApplied.includes(AbilityId.LIBERO)), //Gen 9 Implementation
// TODO: needs testing on interaction with weather blockage // TODO: needs testing on interaction with weather blockage
.edgeCase(), .edgeCase(),
new Ability(AbilityId.BALL_FETCH, 8) new Ability(AbilityId.BALL_FETCH, 8)

View File

@ -15,7 +15,7 @@ export const speciesEggMoves = {
[SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.EXTREME_SPEED, MoveId.KNOCK_OFF, MoveId.TRIPLE_ARROWS ], [SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.EXTREME_SPEED, MoveId.KNOCK_OFF, MoveId.TRIPLE_ARROWS ],
[SpeciesId.EKANS]: [ MoveId.NOXIOUS_TORQUE, MoveId.DRAGON_DANCE, MoveId.SLACK_OFF, MoveId.SHED_TAIL ], [SpeciesId.EKANS]: [ MoveId.NOXIOUS_TORQUE, MoveId.DRAGON_DANCE, MoveId.SLACK_OFF, MoveId.SHED_TAIL ],
[SpeciesId.SANDSHREW]: [ MoveId.HIGH_HORSEPOWER, MoveId.DIRE_CLAW, MoveId.SHORE_UP, MoveId.MIGHTY_CLEAVE ], [SpeciesId.SANDSHREW]: [ MoveId.HIGH_HORSEPOWER, MoveId.DIRE_CLAW, MoveId.SHORE_UP, MoveId.MIGHTY_CLEAVE ],
[SpeciesId.NIDORAN_F]: [ MoveId.CALM_MIND, MoveId.MOONLIGHT, MoveId.MALIGNANT_CHAIN, MoveId.SANDSEAR_STORM ], [SpeciesId.NIDORAN_F]: [ MoveId.BANEFUL_BUNKER, MoveId.MOONLIGHT, MoveId.BARB_BARRAGE, MoveId.THOUSAND_WAVES ],
[SpeciesId.NIDORAN_M]: [ MoveId.DRAGON_DANCE, MoveId.MOUNTAIN_GALE, MoveId.NOXIOUS_TORQUE, MoveId.PRECIPICE_BLADES ], [SpeciesId.NIDORAN_M]: [ MoveId.DRAGON_DANCE, MoveId.MOUNTAIN_GALE, MoveId.NOXIOUS_TORQUE, MoveId.PRECIPICE_BLADES ],
[SpeciesId.VULPIX]: [ MoveId.MOONBLAST, MoveId.INFERNAL_PARADE, MoveId.MORNING_SUN, MoveId.TAIL_GLOW ], [SpeciesId.VULPIX]: [ MoveId.MOONBLAST, MoveId.INFERNAL_PARADE, MoveId.MORNING_SUN, MoveId.TAIL_GLOW ],
[SpeciesId.ZUBAT]: [ MoveId.FLOATY_FALL, MoveId.DIRE_CLAW, MoveId.SWORDS_DANCE, MoveId.COLLISION_COURSE ], [SpeciesId.ZUBAT]: [ MoveId.FLOATY_FALL, MoveId.DIRE_CLAW, MoveId.SWORDS_DANCE, MoveId.COLLISION_COURSE ],
@ -293,7 +293,7 @@ export const speciesEggMoves = {
[SpeciesId.ARCHEN]: [ MoveId.ROOST, MoveId.EARTHQUAKE, MoveId.FLOATY_FALL, MoveId.MIGHTY_CLEAVE ], [SpeciesId.ARCHEN]: [ MoveId.ROOST, MoveId.EARTHQUAKE, MoveId.FLOATY_FALL, MoveId.MIGHTY_CLEAVE ],
[SpeciesId.TRUBBISH]: [ MoveId.COIL, MoveId.RECOVER, MoveId.DIRE_CLAW, MoveId.GIGATON_HAMMER ], [SpeciesId.TRUBBISH]: [ MoveId.COIL, MoveId.RECOVER, MoveId.DIRE_CLAW, MoveId.GIGATON_HAMMER ],
[SpeciesId.ZORUA]: [ MoveId.MALIGNANT_CHAIN, MoveId.MOONBLAST, MoveId.SECRET_SWORD, MoveId.FIERY_WRATH ], [SpeciesId.ZORUA]: [ MoveId.MALIGNANT_CHAIN, MoveId.MOONBLAST, MoveId.SECRET_SWORD, MoveId.FIERY_WRATH ],
[SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.KNOCK_OFF, MoveId.POPULATION_BOMB ], [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.LOW_KICK, MoveId.POPULATION_BOMB ],
[SpeciesId.GOTHITA]: [ MoveId.RECOVER, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.LUMINA_CRASH ], [SpeciesId.GOTHITA]: [ MoveId.RECOVER, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.LUMINA_CRASH ],
[SpeciesId.SOLOSIS]: [ MoveId.MIST_BALL, MoveId.SPEED_SWAP, MoveId.FLAMETHROWER, MoveId.LIGHT_OF_RUIN ], [SpeciesId.SOLOSIS]: [ MoveId.MIST_BALL, MoveId.SPEED_SWAP, MoveId.FLAMETHROWER, MoveId.LIGHT_OF_RUIN ],
[SpeciesId.DUCKLETT]: [ MoveId.SPLISHY_SPLASH, MoveId.SANDSEAR_STORM, MoveId.WILDBOLT_STORM, MoveId.QUIVER_DANCE ], [SpeciesId.DUCKLETT]: [ MoveId.SPLISHY_SPLASH, MoveId.SANDSEAR_STORM, MoveId.WILDBOLT_STORM, MoveId.QUIVER_DANCE ],
@ -310,7 +310,7 @@ export const speciesEggMoves = {
[SpeciesId.TYNAMO]: [ MoveId.SCALD, MoveId.STRENGTH_SAP, MoveId.FIRE_LASH, MoveId.AURA_WHEEL ], [SpeciesId.TYNAMO]: [ MoveId.SCALD, MoveId.STRENGTH_SAP, MoveId.FIRE_LASH, MoveId.AURA_WHEEL ],
[SpeciesId.ELGYEM]: [ MoveId.THUNDERCLAP, MoveId.BADDY_BAD, MoveId.AURA_SPHERE, MoveId.PHOTON_GEYSER ], [SpeciesId.ELGYEM]: [ MoveId.THUNDERCLAP, MoveId.BADDY_BAD, MoveId.AURA_SPHERE, MoveId.PHOTON_GEYSER ],
[SpeciesId.LITWICK]: [ MoveId.GIGA_DRAIN, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.TORCH_SONG ], [SpeciesId.LITWICK]: [ MoveId.GIGA_DRAIN, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.TORCH_SONG ],
[SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.BITTER_BLADE, MoveId.GLAIVE_RUSH ], [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.RAGING_FURY, MoveId.BITTER_BLADE ],
[SpeciesId.CUBCHOO]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.ICE_SHARD, MoveId.COLLISION_COURSE ], [SpeciesId.CUBCHOO]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.ICE_SHARD, MoveId.COLLISION_COURSE ],
[SpeciesId.CRYOGONAL]: [ MoveId.FREEZING_GLARE, MoveId.AURORA_VEIL, MoveId.NASTY_PLOT, MoveId.ORIGIN_PULSE ], [SpeciesId.CRYOGONAL]: [ MoveId.FREEZING_GLARE, MoveId.AURORA_VEIL, MoveId.NASTY_PLOT, MoveId.ORIGIN_PULSE ],
[SpeciesId.SHELMET]: [ MoveId.POWER_GEM, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.STEAM_ERUPTION ], [SpeciesId.SHELMET]: [ MoveId.POWER_GEM, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.STEAM_ERUPTION ],
@ -448,7 +448,7 @@ export const speciesEggMoves = {
[SpeciesId.ROOKIDEE]: [ MoveId.ROOST, MoveId.BODY_PRESS, MoveId.KINGS_SHIELD, MoveId.BEHEMOTH_BASH ], [SpeciesId.ROOKIDEE]: [ MoveId.ROOST, MoveId.BODY_PRESS, MoveId.KINGS_SHIELD, MoveId.BEHEMOTH_BASH ],
[SpeciesId.BLIPBUG]: [ MoveId.HEAL_ORDER, MoveId.LUSTER_PURGE, MoveId.SLEEP_POWDER, MoveId.TAIL_GLOW ], [SpeciesId.BLIPBUG]: [ MoveId.HEAL_ORDER, MoveId.LUSTER_PURGE, MoveId.SLEEP_POWDER, MoveId.TAIL_GLOW ],
[SpeciesId.NICKIT]: [ MoveId.BADDY_BAD, MoveId.MYSTICAL_FIRE, MoveId.SPARKLY_SWIRL, MoveId.MAKE_IT_RAIN ], [SpeciesId.NICKIT]: [ MoveId.BADDY_BAD, MoveId.MYSTICAL_FIRE, MoveId.SPARKLY_SWIRL, MoveId.MAKE_IT_RAIN ],
[SpeciesId.GOSSIFLEUR]: [ MoveId.PARTING_SHOT, MoveId.STRENGTH_SAP, MoveId.SAPPY_SEED, MoveId.SEED_FLARE ], [SpeciesId.GOSSIFLEUR]: [ MoveId.BATON_PASS, MoveId.TAILWIND, MoveId.SAPPY_SEED, MoveId.SPORE ],
[SpeciesId.WOOLOO]: [ MoveId.NUZZLE, MoveId.MILK_DRINK, MoveId.BODY_PRESS, MoveId.MULTI_ATTACK ], [SpeciesId.WOOLOO]: [ MoveId.NUZZLE, MoveId.MILK_DRINK, MoveId.BODY_PRESS, MoveId.MULTI_ATTACK ],
[SpeciesId.CHEWTLE]: [ MoveId.ICE_FANG, MoveId.PSYCHIC_FANGS, MoveId.SHELL_SMASH, MoveId.MIGHTY_CLEAVE ], [SpeciesId.CHEWTLE]: [ MoveId.ICE_FANG, MoveId.PSYCHIC_FANGS, MoveId.SHELL_SMASH, MoveId.MIGHTY_CLEAVE ],
[SpeciesId.YAMPER]: [ MoveId.ICE_FANG, MoveId.SWORDS_DANCE, MoveId.THUNDER_FANG, MoveId.BOLT_STRIKE ], [SpeciesId.YAMPER]: [ MoveId.ICE_FANG, MoveId.SWORDS_DANCE, MoveId.THUNDER_FANG, MoveId.BOLT_STRIKE ],
@ -514,7 +514,7 @@ export const speciesEggMoves = {
[SpeciesId.TAROUNTULA]: [ MoveId.STONE_AXE, MoveId.LEECH_LIFE, MoveId.FAKE_OUT, MoveId.SPORE ], [SpeciesId.TAROUNTULA]: [ MoveId.STONE_AXE, MoveId.LEECH_LIFE, MoveId.FAKE_OUT, MoveId.SPORE ],
[SpeciesId.NYMBLE]: [ MoveId.KNOCK_OFF, MoveId.FELL_STINGER, MoveId.ATTACK_ORDER, MoveId.WICKED_BLOW ], [SpeciesId.NYMBLE]: [ MoveId.KNOCK_OFF, MoveId.FELL_STINGER, MoveId.ATTACK_ORDER, MoveId.WICKED_BLOW ],
[SpeciesId.PAWMI]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.JET_PUNCH, MoveId.PLASMA_FISTS ], [SpeciesId.PAWMI]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.JET_PUNCH, MoveId.PLASMA_FISTS ],
[SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.COVET, MoveId.SIZZLY_SLIDE, MoveId.REVIVAL_BLESSING ], [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.FAKE_OUT, MoveId.POWER_UP_PUNCH, MoveId.REVIVAL_BLESSING ],
[SpeciesId.FIDOUGH]: [ MoveId.SOFT_BOILED, MoveId.HIGH_HORSEPOWER, MoveId.SIZZLY_SLIDE, MoveId.TIDY_UP ], [SpeciesId.FIDOUGH]: [ MoveId.SOFT_BOILED, MoveId.HIGH_HORSEPOWER, MoveId.SIZZLY_SLIDE, MoveId.TIDY_UP ],
[SpeciesId.SMOLIV]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.BOOMBURST ], [SpeciesId.SMOLIV]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.BOOMBURST ],
[SpeciesId.SQUAWKABILLY]: [ MoveId.PARTING_SHOT, MoveId.EARTHQUAKE, MoveId.FLARE_BLITZ, MoveId.EXTREME_SPEED ], [SpeciesId.SQUAWKABILLY]: [ MoveId.PARTING_SHOT, MoveId.EARTHQUAKE, MoveId.FLARE_BLITZ, MoveId.EXTREME_SPEED ],

View File

@ -36,9 +36,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
[SpeciesId.ARBOK]: { 0: AbilityId.REGENERATOR }, [SpeciesId.ARBOK]: { 0: AbilityId.REGENERATOR },
[SpeciesId.SANDSHREW]: { 0: AbilityId.TOUGH_CLAWS }, [SpeciesId.SANDSHREW]: { 0: AbilityId.TOUGH_CLAWS },
[SpeciesId.SANDSLASH]: { 0: AbilityId.TOUGH_CLAWS }, [SpeciesId.SANDSLASH]: { 0: AbilityId.TOUGH_CLAWS },
[SpeciesId.NIDORAN_F]: { 0: AbilityId.FLARE_BOOST }, [SpeciesId.NIDORAN_F]: { 0: AbilityId.TOXIC_DEBRIS },
[SpeciesId.NIDORINA]: { 0: AbilityId.FLARE_BOOST }, [SpeciesId.NIDORINA]: { 0: AbilityId.TOXIC_DEBRIS },
[SpeciesId.NIDOQUEEN]: { 0: AbilityId.FLARE_BOOST }, [SpeciesId.NIDOQUEEN]: { 0: AbilityId.TOXIC_DEBRIS },
[SpeciesId.NIDORAN_M]: { 0: AbilityId.GUTS }, [SpeciesId.NIDORAN_M]: { 0: AbilityId.GUTS },
[SpeciesId.NIDORINO]: { 0: AbilityId.GUTS }, [SpeciesId.NIDORINO]: { 0: AbilityId.GUTS },
[SpeciesId.NIDOKING]: { 0: AbilityId.GUTS }, [SpeciesId.NIDOKING]: { 0: AbilityId.GUTS },
@ -220,8 +220,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
[SpeciesId.YANMEGA]: { 0: AbilityId.SHEER_FORCE }, [SpeciesId.YANMEGA]: { 0: AbilityId.SHEER_FORCE },
[SpeciesId.WOOPER]: { 0: AbilityId.WATER_VEIL }, [SpeciesId.WOOPER]: { 0: AbilityId.WATER_VEIL },
[SpeciesId.QUAGSIRE]: { 0: AbilityId.COMATOSE }, [SpeciesId.QUAGSIRE]: { 0: AbilityId.COMATOSE },
[SpeciesId.MURKROW]: { 0: AbilityId.DARK_AURA }, [SpeciesId.MURKROW]: { 0: AbilityId.UNNERVE },
[SpeciesId.HONCHKROW]: { 0: AbilityId.DARK_AURA }, [SpeciesId.HONCHKROW]: { 0: AbilityId.INTIMIDATE },
[SpeciesId.MISDREAVUS]: { 0: AbilityId.BEADS_OF_RUIN }, [SpeciesId.MISDREAVUS]: { 0: AbilityId.BEADS_OF_RUIN },
[SpeciesId.MISMAGIUS]: { 0: AbilityId.BEADS_OF_RUIN }, [SpeciesId.MISMAGIUS]: { 0: AbilityId.BEADS_OF_RUIN },
[SpeciesId.UNOWN]: { 0: AbilityId.ADAPTABILITY, 1: AbilityId.BEAST_BOOST, 2: AbilityId.CONTRARY, 3: AbilityId.DAZZLING, 4: AbilityId.EMERGENCY_EXIT, 5: AbilityId.FRIEND_GUARD, 6: AbilityId.GOOD_AS_GOLD, 7: AbilityId.HONEY_GATHER, 8: AbilityId.IMPOSTER, 9: AbilityId.JUSTIFIED, 10: AbilityId.KLUTZ, 11: AbilityId.LIBERO, 12: AbilityId.MOODY, 13: AbilityId.NEUTRALIZING_GAS, 14: AbilityId.OPPORTUNIST, 15: AbilityId.PICKUP, 16: AbilityId.QUICK_DRAW, 17: AbilityId.RUN_AWAY, 18: AbilityId.SIMPLE, 19: AbilityId.TRACE, 20: AbilityId.UNNERVE, 21: AbilityId.VICTORY_STAR, 22: AbilityId.WANDERING_SPIRIT, 23: AbilityId.FAIRY_AURA, 24: AbilityId.DARK_AURA, 25: AbilityId.AURA_BREAK, 26: AbilityId.PURE_POWER, 27: AbilityId.UNAWARE }, [SpeciesId.UNOWN]: { 0: AbilityId.ADAPTABILITY, 1: AbilityId.BEAST_BOOST, 2: AbilityId.CONTRARY, 3: AbilityId.DAZZLING, 4: AbilityId.EMERGENCY_EXIT, 5: AbilityId.FRIEND_GUARD, 6: AbilityId.GOOD_AS_GOLD, 7: AbilityId.HONEY_GATHER, 8: AbilityId.IMPOSTER, 9: AbilityId.JUSTIFIED, 10: AbilityId.KLUTZ, 11: AbilityId.LIBERO, 12: AbilityId.MOODY, 13: AbilityId.NEUTRALIZING_GAS, 14: AbilityId.OPPORTUNIST, 15: AbilityId.PICKUP, 16: AbilityId.QUICK_DRAW, 17: AbilityId.RUN_AWAY, 18: AbilityId.SIMPLE, 19: AbilityId.TRACE, 20: AbilityId.UNNERVE, 21: AbilityId.VICTORY_STAR, 22: AbilityId.WANDERING_SPIRIT, 23: AbilityId.FAIRY_AURA, 24: AbilityId.DARK_AURA, 25: AbilityId.AURA_BREAK, 26: AbilityId.PURE_POWER, 27: AbilityId.UNAWARE },
@ -391,7 +391,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
[SpeciesId.BANETTE]: { 0: AbilityId.SHADOW_SHIELD, 1: AbilityId.SHADOW_SHIELD }, [SpeciesId.BANETTE]: { 0: AbilityId.SHADOW_SHIELD, 1: AbilityId.SHADOW_SHIELD },
[SpeciesId.DUSKULL]: { 0: AbilityId.UNNERVE }, [SpeciesId.DUSKULL]: { 0: AbilityId.UNNERVE },
[SpeciesId.DUSCLOPS]: { 0: AbilityId.UNNERVE }, [SpeciesId.DUSCLOPS]: { 0: AbilityId.UNNERVE },
[SpeciesId.DUSKNOIR]: { 0: AbilityId.UNNERVE }, [SpeciesId.DUSKNOIR]: { 0: AbilityId.LEVITATE },
[SpeciesId.TROPIUS]: { 0: AbilityId.RIPEN }, [SpeciesId.TROPIUS]: { 0: AbilityId.RIPEN },
[SpeciesId.ABSOL]: { 0: AbilityId.SHARPNESS, 1: AbilityId.SHARPNESS }, [SpeciesId.ABSOL]: { 0: AbilityId.SHARPNESS, 1: AbilityId.SHARPNESS },
[SpeciesId.WYNAUT]: { 0: AbilityId.STURDY }, [SpeciesId.WYNAUT]: { 0: AbilityId.STURDY },
@ -640,9 +640,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
[SpeciesId.LITWICK]: { 0: AbilityId.SHADOW_TAG }, [SpeciesId.LITWICK]: { 0: AbilityId.SHADOW_TAG },
[SpeciesId.LAMPENT]: { 0: AbilityId.SHADOW_TAG }, [SpeciesId.LAMPENT]: { 0: AbilityId.SHADOW_TAG },
[SpeciesId.CHANDELURE]: { 0: AbilityId.SHADOW_TAG }, [SpeciesId.CHANDELURE]: { 0: AbilityId.SHADOW_TAG },
[SpeciesId.AXEW]: { 0: AbilityId.DRAGONS_MAW }, [SpeciesId.AXEW]: { 0: AbilityId.OWN_TEMPO },
[SpeciesId.FRAXURE]: { 0: AbilityId.DRAGONS_MAW }, [SpeciesId.FRAXURE]: { 0: AbilityId.OWN_TEMPO },
[SpeciesId.HAXORUS]: { 0: AbilityId.DRAGONS_MAW }, [SpeciesId.HAXORUS]: { 0: AbilityId.OWN_TEMPO },
[SpeciesId.CUBCHOO]: { 0: AbilityId.FUR_COAT }, [SpeciesId.CUBCHOO]: { 0: AbilityId.FUR_COAT },
[SpeciesId.BEARTIC]: { 0: AbilityId.FUR_COAT }, [SpeciesId.BEARTIC]: { 0: AbilityId.FUR_COAT },
[SpeciesId.CRYOGONAL]: { 0: AbilityId.SNOW_WARNING }, [SpeciesId.CRYOGONAL]: { 0: AbilityId.SNOW_WARNING },
@ -827,7 +827,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
[SpeciesId.TAPU_LELE]: { 0: AbilityId.BERSERK }, [SpeciesId.TAPU_LELE]: { 0: AbilityId.BERSERK },
[SpeciesId.TAPU_BULU]: { 0: AbilityId.FLOWER_VEIL }, [SpeciesId.TAPU_BULU]: { 0: AbilityId.FLOWER_VEIL },
[SpeciesId.TAPU_FINI]: { 0: AbilityId.FAIRY_AURA }, [SpeciesId.TAPU_FINI]: { 0: AbilityId.FAIRY_AURA },
[SpeciesId.COSMOG]: { 0: AbilityId.PICKUP }, [SpeciesId.COSMOG]: { 0: AbilityId.POWER_SPOT },
[SpeciesId.COSMOEM]: { 0: AbilityId.POWER_SPOT }, [SpeciesId.COSMOEM]: { 0: AbilityId.POWER_SPOT },
[SpeciesId.SOLGALEO]: { 0: AbilityId.BEAST_BOOST }, [SpeciesId.SOLGALEO]: { 0: AbilityId.BEAST_BOOST },
[SpeciesId.LUNALA]: { 0: AbilityId.BEAST_BOOST }, [SpeciesId.LUNALA]: { 0: AbilityId.BEAST_BOOST },
@ -1044,7 +1044,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = {
[SpeciesId.FINIZEN]: { 0: AbilityId.FRIEND_GUARD }, [SpeciesId.FINIZEN]: { 0: AbilityId.FRIEND_GUARD },
[SpeciesId.PALAFIN]: { 0: AbilityId.EMERGENCY_EXIT, 1: AbilityId.IRON_FIST }, [SpeciesId.PALAFIN]: { 0: AbilityId.EMERGENCY_EXIT, 1: AbilityId.IRON_FIST },
[SpeciesId.VAROOM]: { 0: AbilityId.LEVITATE }, [SpeciesId.VAROOM]: { 0: AbilityId.LEVITATE },
[SpeciesId.REVAVROOM]: { 0: AbilityId.LEVITATE, 1: AbilityId.DARK_AURA, 2: AbilityId.FLASH_FIRE, 3: AbilityId.MERCILESS, 4: AbilityId.FILTER, 5: AbilityId.SCRAPPY }, [SpeciesId.REVAVROOM]: { 0: AbilityId.LEVITATE, 1: AbilityId.INTIMIDATE, 2: AbilityId.SPEED_BOOST, 3: AbilityId.TOXIC_DEBRIS, 4: AbilityId.MISTY_SURGE, 5: AbilityId.STAMINA },
[SpeciesId.CYCLIZAR]: { 0: AbilityId.PROTEAN }, [SpeciesId.CYCLIZAR]: { 0: AbilityId.PROTEAN },
[SpeciesId.ORTHWORM]: { 0: AbilityId.REGENERATOR }, [SpeciesId.ORTHWORM]: { 0: AbilityId.REGENERATOR },
[SpeciesId.GLIMMET]: { 0: AbilityId.STURDY }, [SpeciesId.GLIMMET]: { 0: AbilityId.STURDY },

View File

@ -1618,11 +1618,11 @@ export function initSpecies() {
new PokemonSpecies(SpeciesId.VAROOM, 9, false, false, false, "Single-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1, 35, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.SLOW_START, 300, 45, 70, 63, 30, 45, 47, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(SpeciesId.VAROOM, 9, false, false, false, "Single-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1, 35, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.SLOW_START, 300, 45, 70, 63, 30, 45, 47, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
new PokemonSpecies(SpeciesId.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, false, new PokemonSpecies(SpeciesId.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, false,
new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, false, null, true), new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, false, null, true),
new PokemonForm("Segin Starmobile", "segin-starmobile", PokemonType.STEEL, PokemonType.DARK, 1.8, 240, AbilityId.INTIMIDATE, AbilityId.NONE, AbilityId.INTIMIDATE, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true), new PokemonForm("Segin Starmobile", "segin-starmobile", PokemonType.STEEL, PokemonType.DARK, 1.8, 240, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
new PokemonForm("Schedar Starmobile", "schedar-starmobile", PokemonType.STEEL, PokemonType.FIRE, 1.8, 240, AbilityId.SPEED_BOOST, AbilityId.NONE, AbilityId.SPEED_BOOST, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true), new PokemonForm("Schedar Starmobile", "schedar-starmobile", PokemonType.STEEL, PokemonType.FIRE, 1.8, 240, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
new PokemonForm("Navi Starmobile", "navi-starmobile", PokemonType.STEEL, PokemonType.POISON, 1.8, 240, AbilityId.TOXIC_DEBRIS, AbilityId.NONE, AbilityId.TOXIC_DEBRIS, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true), new PokemonForm("Navi Starmobile", "navi-starmobile", PokemonType.STEEL, PokemonType.POISON, 1.8, 240, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
new PokemonForm("Ruchbah Starmobile", "ruchbah-starmobile", PokemonType.STEEL, PokemonType.FAIRY, 1.8, 240, AbilityId.MISTY_SURGE, AbilityId.NONE, AbilityId.MISTY_SURGE, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true), new PokemonForm("Ruchbah Starmobile", "ruchbah-starmobile", PokemonType.STEEL, PokemonType.FAIRY, 1.8, 240, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
new PokemonForm("Caph Starmobile", "caph-starmobile", PokemonType.STEEL, PokemonType.FIGHTING, 1.8, 240, AbilityId.STAMINA, AbilityId.NONE, AbilityId.STAMINA, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true) new PokemonForm("Caph Starmobile", "caph-starmobile", PokemonType.STEEL, PokemonType.FIGHTING, 1.8, 240, AbilityId.OVERCOAT, AbilityId.NONE, AbilityId.OVERCOAT, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true)
), ),
new PokemonSpecies(SpeciesId.CYCLIZAR, 9, false, false, false, "Mount Pokémon", PokemonType.DRAGON, PokemonType.NORMAL, 1.6, 63, AbilityId.SHED_SKIN, AbilityId.NONE, AbilityId.REGENERATOR, 501, 70, 95, 65, 85, 65, 121, 190, 50, 175, GrowthRate.MEDIUM_SLOW, 50, false), new PokemonSpecies(SpeciesId.CYCLIZAR, 9, false, false, false, "Mount Pokémon", PokemonType.DRAGON, PokemonType.NORMAL, 1.6, 63, AbilityId.SHED_SKIN, AbilityId.NONE, AbilityId.REGENERATOR, 501, 70, 95, 65, 85, 65, 121, 190, 50, 175, GrowthRate.MEDIUM_SLOW, 50, false),
new PokemonSpecies(SpeciesId.ORTHWORM, 9, false, false, false, "Earthworm Pokémon", PokemonType.STEEL, null, 2.5, 310, AbilityId.EARTH_EATER, AbilityId.NONE, AbilityId.SAND_VEIL, 480, 70, 85, 145, 60, 55, 65, 25, 50, 240, GrowthRate.SLOW, 50, false), new PokemonSpecies(SpeciesId.ORTHWORM, 9, false, false, false, "Earthworm Pokémon", PokemonType.STEEL, null, 2.5, 310, AbilityId.EARTH_EATER, AbilityId.NONE, AbilityId.SAND_VEIL, 480, 70, 85, 145, 60, 55, 65, 25, 50, 240, GrowthRate.SLOW, 50, false),

View File

@ -30,7 +30,7 @@ export const signatureSpecies: SignatureSpecies = new Proxy({
FALKNER: [SpeciesId.PIDGEY, SpeciesId.HOOTHOOT, SpeciesId.NATU, SpeciesId.MURKROW], FALKNER: [SpeciesId.PIDGEY, SpeciesId.HOOTHOOT, SpeciesId.NATU, SpeciesId.MURKROW],
BUGSY: [SpeciesId.SCYTHER, SpeciesId.SHUCKLE, SpeciesId.YANMA, [SpeciesId.PINSIR, SpeciesId.HERACROSS]], BUGSY: [SpeciesId.SCYTHER, SpeciesId.SHUCKLE, SpeciesId.YANMA, [SpeciesId.PINSIR, SpeciesId.HERACROSS]],
WHITNEY: [SpeciesId.MILTANK, SpeciesId.AIPOM, SpeciesId.IGGLYBUFF, [SpeciesId.GIRAFARIG, SpeciesId.STANTLER]], WHITNEY: [SpeciesId.MILTANK, SpeciesId.AIPOM, SpeciesId.IGGLYBUFF, [SpeciesId.GIRAFARIG, SpeciesId.STANTLER]],
MORTY: [SpeciesId.GASTLY, SpeciesId.MISDREAVUS, SpeciesId.DUSKULL, SpeciesId.SABLEYE], MORTY: [SpeciesId.GASTLY, SpeciesId.MISDREAVUS, SpeciesId.DUSKULL, SpeciesId.HISUI_TYPHLOSION],
CHUCK: [SpeciesId.POLIWRATH, SpeciesId.MANKEY, SpeciesId.TYROGUE, SpeciesId.MACHOP], CHUCK: [SpeciesId.POLIWRATH, SpeciesId.MANKEY, SpeciesId.TYROGUE, SpeciesId.MACHOP],
JASMINE: [SpeciesId.STEELIX, SpeciesId.MAGNEMITE, SpeciesId.PINECO, SpeciesId.SKARMORY], JASMINE: [SpeciesId.STEELIX, SpeciesId.MAGNEMITE, SpeciesId.PINECO, SpeciesId.SKARMORY],
PRYCE: [SpeciesId.SWINUB, SpeciesId.SEEL, SpeciesId.SHELLDER, SpeciesId.SNEASEL], PRYCE: [SpeciesId.SWINUB, SpeciesId.SEEL, SpeciesId.SHELLDER, SpeciesId.SNEASEL],

View File

@ -566,7 +566,7 @@ export const speciesStarterCosts = {
[SpeciesId.FLITTLE]: 3, [SpeciesId.FLITTLE]: 3,
[SpeciesId.TINKATINK]: 4, [SpeciesId.TINKATINK]: 4,
[SpeciesId.WIGLETT]: 2, [SpeciesId.WIGLETT]: 2,
[SpeciesId.BOMBIRDIER]: 3, [SpeciesId.BOMBIRDIER]: 4,
[SpeciesId.FINIZEN]: 3, [SpeciesId.FINIZEN]: 3,
[SpeciesId.VAROOM]: 4, [SpeciesId.VAROOM]: 4,
[SpeciesId.CYCLIZAR]: 4, [SpeciesId.CYCLIZAR]: 4,

View File

@ -1,17 +1,13 @@
import type { FixedBattleConfig } from "#app/battle"; import type { FixedBattleConfig } from "#app/battle";
import { getRandomTrainerFunc } from "#app/battle"; import { getRandomTrainerFunc } from "#app/battle";
import { defaultStarterSpecies } from "#app/constants"; import { defaultStarterSpecies } from "#app/constants";
import { globalScene } from "#app/global-scene";
import { pokemonEvolutions } from "#balance/pokemon-evolutions";
import { speciesStarterCosts } from "#balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { pokemonFormChanges } from "#data/pokemon-forms";
import type { PokemonSpecies } from "#data/pokemon-species"; import type { PokemonSpecies } from "#data/pokemon-species";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import { ChallengeType } from "#enums/challenge-type";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";
import { TypeColor, TypeShadow } from "#enums/color"; import { TypeColor, TypeShadow } from "#enums/color";
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
import type { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
import type { MoveSourceType } from "#enums/move-source-type"; import type { MoveSourceType } from "#enums/move-source-type";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
@ -19,11 +15,12 @@ import { RarityTier } from "#enums/reward-tier";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { TrainerVariant } from "#enums/trainer-variant"; import { TrainerVariant } from "#enums/trainer-variant";
import type { Pokemon } from "#field/pokemon"; import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon";
import { Trainer } from "#field/trainer"; import { Trainer } from "#field/trainer";
import type { ModifierTypeOption } from "#modifiers/modifier-type";
import { PokemonMove } from "#moves/pokemon-move"; import { PokemonMove } from "#moves/pokemon-move";
import type { DexAttrProps, GameData } from "#system/game-data"; import type { DexAttrProps, GameData } from "#system/game-data";
import { BooleanHolder, isBetween, type NumberHolder, randSeedItem } from "#utils/common"; import { type BooleanHolder, isBetween, type NumberHolder, randSeedItem } from "#utils/common";
import { deepCopy } from "#utils/data"; import { deepCopy } from "#utils/data";
import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils";
import { toCamelCase, toSnakeCase } from "#utils/strings"; import { toCamelCase, toSnakeCase } from "#utils/strings";
@ -341,6 +338,83 @@ export abstract class Challenge {
applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) { applyFlipStat(_pokemon: Pokemon, _baseStats: number[]) {
return false; return false;
} }
/**
* An apply function for PARTY_HEAL. Derived classes should alter this.
* @param _status - Whether party healing is enabled or not
* @returns Whether this function did anything
*/
applyPartyHeal(_status: BooleanHolder): boolean {
return false;
}
/**
* An apply function for SHOP. Derived classes should alter this.
* @param _status - Whether the shop is or is not available after a wave
* @returns Whether this function did anything
*/
applyShop(_status: BooleanHolder) {
return false;
}
/**
* An apply function for POKEMON_ADD_TO_PARTY. Derived classes should alter this.
* @param _pokemon - The pokemon being caught
* @param _status - Whether the pokemon can be added to the party or not
* @return Whether this function did anything
*/
applyPokemonAddToParty(_pokemon: EnemyPokemon, _status: BooleanHolder): boolean {
return false;
}
/**
* An apply function for POKEMON_FUSION. Derived classes should alter this.
* @param _pokemon - The pokemon being checked
* @param _status - Whether the selected pokemon is allowed to fuse or not
* @returns Whether this function did anything
*/
applyPokemonFusion(_pokemon: PlayerPokemon, _status: BooleanHolder): boolean {
return false;
}
/**
* An apply function for POKEMON_MOVE. Derived classes should alter this.
* @param _moveId - The {@linkcode MoveId} being checked
* @param _status - A {@linkcode BooleanHolder} containing the move's usability status
* @returns Whether this function did anything
*/
applyPokemonMove(_moveId: MoveId, _status: BooleanHolder): boolean {
return false;
}
/**
* An apply function for SHOP_ITEM. Derived classes should alter this.
* @param _shopItem - The item being checked
* @param _status - Whether the item should be added to the shop or not
* @returns Whether this function did anything
*/
applyShopItem(_shopItem: ModifierTypeOption | null, _status: BooleanHolder): boolean {
return false;
}
/**
* An apply function for WAVE_REWARD. Derived classes should alter this.
* @param _reward - The reward being checked
* @param _status - Whether the reward should be added to the reward options or not
* @returns Whether this function did anything
*/
applyWaveReward(_reward: ModifierTypeOption | null, _status: BooleanHolder): boolean {
return false;
}
/**
* An apply function for PREVENT_REVIVE. Derived classes should alter this.
* @param _status - Whether fainting is a permanent status or not
* @returns Whether this function did anything
*/
applyPreventRevive(_status: BooleanHolder): boolean {
return false;
}
} }
type ChallengeCondition = (data: GameData) => boolean; type ChallengeCondition = (data: GameData) => boolean;
@ -864,208 +938,108 @@ export class LowerStarterPointsChallenge extends Challenge {
} }
/** /**
* Apply all challenges that modify starter choice. * Implements a No Support challenge
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_CHOICE
* @param pokemon {@link PokemonSpecies} The pokemon to check the validity of.
* @param valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
* @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges( export class LimitedSupportChallenge extends Challenge {
challengeType: ChallengeType.STARTER_CHOICE, constructor() {
pokemon: PokemonSpecies, super(Challenges.LIMITED_SUPPORT, 3);
valid: BooleanHolder, }
dexAttr: DexAttrProps,
): boolean;
/**
* Apply all challenges that modify available total starter points.
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_POINTS
* @param points {@link NumberHolder} The amount of points you have available.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(challengeType: ChallengeType.STARTER_POINTS, points: NumberHolder): boolean;
/**
* Apply all challenges that modify the cost of a starter.
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_COST
* @param species {@link SpeciesId} The pokemon to change the cost of.
* @param points {@link NumberHolder} The cost of the pokemon.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.STARTER_COST,
species: SpeciesId,
cost: NumberHolder,
): boolean;
/**
* Apply all challenges that modify a starter after selection.
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_MODIFY
* @param pokemon {@link Pokemon} The starter pokemon to modify.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(challengeType: ChallengeType.STARTER_MODIFY, pokemon: Pokemon): boolean;
/**
* Apply all challenges that what pokemon you can have in battle.
* @param challengeType {@link ChallengeType} ChallengeType.POKEMON_IN_BATTLE
* @param pokemon {@link Pokemon} The pokemon to check the validity of.
* @param valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.POKEMON_IN_BATTLE,
pokemon: Pokemon,
valid: BooleanHolder,
): boolean;
/**
* Apply all challenges that modify what fixed battles there are.
* @param challengeType {@link ChallengeType} ChallengeType.FIXED_BATTLES
* @param waveIndex {@link Number} The current wave index.
* @param battleConfig {@link FixedBattleConfig} The battle config to modify.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.FIXED_BATTLES,
waveIndex: number,
battleConfig: FixedBattleConfig,
): boolean;
/**
* Apply all challenges that modify type effectiveness.
* @param challengeType {@linkcode ChallengeType} ChallengeType.TYPE_EFFECTIVENESS
* @param effectiveness {@linkcode NumberHolder} The current effectiveness of the move.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(challengeType: ChallengeType.TYPE_EFFECTIVENESS, effectiveness: NumberHolder): boolean;
/**
* Apply all challenges that modify what level AI are.
* @param challengeType {@link ChallengeType} ChallengeType.AI_LEVEL
* @param level {@link NumberHolder} The generated level of the pokemon.
* @param levelCap {@link Number} The maximum level cap for the current wave.
* @param isTrainer {@link Boolean} Whether this is a trainer pokemon.
* @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.AI_LEVEL,
level: NumberHolder,
levelCap: number,
isTrainer: boolean,
isBoss: boolean,
): boolean;
/**
* Apply all challenges that modify how many move slots the AI has.
* @param challengeType {@link ChallengeType} ChallengeType.AI_MOVE_SLOTS
* @param pokemon {@link Pokemon} The pokemon being considered.
* @param moveSlots {@link NumberHolder} The amount of move slots.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.AI_MOVE_SLOTS,
pokemon: Pokemon,
moveSlots: NumberHolder,
): boolean;
/**
* Apply all challenges that modify whether a pokemon has its passive.
* @param challengeType {@link ChallengeType} ChallengeType.PASSIVE_ACCESS
* @param pokemon {@link Pokemon} The pokemon to modify.
* @param hasPassive {@link BooleanHolder} Whether it has its passive.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.PASSIVE_ACCESS,
pokemon: Pokemon,
hasPassive: BooleanHolder,
): boolean;
/**
* Apply all challenges that modify the game modes settings.
* @param challengeType {@link ChallengeType} ChallengeType.GAME_MODE_MODIFY
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(challengeType: ChallengeType.GAME_MODE_MODIFY): boolean;
/**
* Apply all challenges that modify what level a pokemon can access a move.
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_ACCESS
* @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
* @param move {@link MoveId} The move in question.
* @param level {@link NumberHolder} The level threshold for access.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.MOVE_ACCESS,
pokemon: Pokemon,
moveSource: MoveSourceType,
move: MoveId,
level: NumberHolder,
): boolean;
/**
* Apply all challenges that modify what weight a pokemon gives to move generation
* @param challengeType {@link ChallengeType} ChallengeType.MOVE_WEIGHT
* @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
* @param move {@link MoveId} The move in question.
* @param weight {@link NumberHolder} The weight of the move.
* @returns True if any challenge was successfully applied.
*/
export function applyChallenges(
challengeType: ChallengeType.MOVE_WEIGHT,
pokemon: Pokemon,
moveSource: MoveSourceType,
move: MoveId,
weight: NumberHolder,
): boolean;
export function applyChallenges(challengeType: ChallengeType.FLIP_STAT, pokemon: Pokemon, baseStats: number[]): boolean; override applyPartyHeal(status: BooleanHolder): boolean {
if (status.value) {
export function applyChallenges(challengeType: ChallengeType, ...args: any[]): boolean { status.value = this.value === 2;
let ret = false; return true;
globalScene.gameMode.challenges.forEach(c => {
if (c.value !== 0) {
switch (challengeType) {
case ChallengeType.STARTER_CHOICE:
ret ||= c.applyStarterChoice(args[0], args[1], args[2]);
break;
case ChallengeType.STARTER_POINTS:
ret ||= c.applyStarterPoints(args[0]);
break;
case ChallengeType.STARTER_COST:
ret ||= c.applyStarterCost(args[0], args[1]);
break;
case ChallengeType.STARTER_MODIFY:
ret ||= c.applyStarterModify(args[0]);
break;
case ChallengeType.POKEMON_IN_BATTLE:
ret ||= c.applyPokemonInBattle(args[0], args[1]);
break;
case ChallengeType.FIXED_BATTLES:
ret ||= c.applyFixedBattle(args[0], args[1]);
break;
case ChallengeType.TYPE_EFFECTIVENESS:
ret ||= c.applyTypeEffectiveness(args[0]);
break;
case ChallengeType.AI_LEVEL:
ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]);
break;
case ChallengeType.AI_MOVE_SLOTS:
ret ||= c.applyMoveSlot(args[0], args[1]);
break;
case ChallengeType.PASSIVE_ACCESS:
ret ||= c.applyPassiveAccess(args[0], args[1]);
break;
case ChallengeType.GAME_MODE_MODIFY:
ret ||= c.applyGameModeModify();
break;
case ChallengeType.MOVE_ACCESS:
ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]);
break;
case ChallengeType.MOVE_WEIGHT:
ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]);
break;
case ChallengeType.FLIP_STAT:
ret ||= c.applyFlipStat(args[0], args[1]);
break;
}
} }
}); return false;
return ret; }
override applyShop(status: BooleanHolder): boolean {
if (status.value) {
status.value = this.value === 1;
return true;
}
return false;
}
static override loadChallenge(source: LimitedSupportChallenge | any): LimitedSupportChallenge {
const newChallenge = new LimitedSupportChallenge();
newChallenge.value = source.value;
newChallenge.severity = source.severity;
return newChallenge;
}
}
/**
* Implements a Limited Catch challenge
*/
export class LimitedCatchChallenge extends Challenge {
constructor() {
super(Challenges.LIMITED_CATCH, 1);
}
override applyPokemonAddToParty(pokemon: EnemyPokemon, status: BooleanHolder): boolean {
if (status.value) {
status.value = pokemon.metWave % 10 === 1;
return true;
}
return false;
}
static override loadChallenge(source: LimitedCatchChallenge | any): LimitedCatchChallenge {
const newChallenge = new LimitedCatchChallenge();
newChallenge.value = source.value;
newChallenge.severity = source.severity;
return newChallenge;
}
}
/**
* Implements a Permanent Faint challenge
*/
export class HardcoreChallenge extends Challenge {
constructor() {
super(Challenges.HARDCORE, 1);
}
override applyPokemonFusion(pokemon: PlayerPokemon, status: BooleanHolder): boolean {
if (!status.value) {
status.value = pokemon.isFainted();
return true;
}
return false;
}
override applyShopItem(shopItem: ModifierTypeOption | null, status: BooleanHolder): boolean {
status.value = shopItem?.type.group !== "revive";
return true;
}
override applyWaveReward(reward: ModifierTypeOption | null, status: BooleanHolder): boolean {
return this.applyShopItem(reward, status);
}
override applyPokemonMove(moveId: MoveId, status: BooleanHolder) {
if (status.value) {
status.value = moveId !== MoveId.REVIVAL_BLESSING;
return true;
}
return false;
}
override applyPreventRevive(status: BooleanHolder): boolean {
if (!status.value) {
status.value = true;
return true;
}
return false;
}
static override loadChallenge(source: HardcoreChallenge | any): HardcoreChallenge {
const newChallenge = new HardcoreChallenge();
newChallenge.value = source.value;
newChallenge.severity = source.severity;
return newChallenge;
}
} }
/** /**
@ -1089,6 +1063,12 @@ export function copyChallenge(source: Challenge | any): Challenge {
return InverseBattleChallenge.loadChallenge(source); return InverseBattleChallenge.loadChallenge(source);
case Challenges.FLIP_STAT: case Challenges.FLIP_STAT:
return FlipStatChallenge.loadChallenge(source); return FlipStatChallenge.loadChallenge(source);
case Challenges.LIMITED_CATCH:
return LimitedCatchChallenge.loadChallenge(source);
case Challenges.LIMITED_SUPPORT:
return LimitedSupportChallenge.loadChallenge(source);
case Challenges.HARDCORE:
return HardcoreChallenge.loadChallenge(source);
} }
throw new Error("Unknown challenge copied"); throw new Error("Unknown challenge copied");
} }
@ -1097,87 +1077,13 @@ export const allChallenges: Challenge[] = [];
export function initChallenges() { export function initChallenges() {
allChallenges.push( allChallenges.push(
new FreshStartChallenge(),
new HardcoreChallenge(),
new LimitedCatchChallenge(),
new LimitedSupportChallenge(),
new SingleGenerationChallenge(), new SingleGenerationChallenge(),
new SingleTypeChallenge(), new SingleTypeChallenge(),
new FreshStartChallenge(),
new InverseBattleChallenge(), new InverseBattleChallenge(),
new FlipStatChallenge(), new FlipStatChallenge(),
); );
} }
/**
* Apply all challenges to the given starter (and form) to check its validity.
* Differs from {@linkcode checkSpeciesValidForChallenge} which only checks form changes.
* @param species - The {@linkcode PokemonSpecies} to check the validity of.
* @param dexAttr - The {@linkcode DexAttrProps | dex attributes} of the species, including its form index.
* @param soft - If `true`, allow it if it could become valid through evolution or form change.
* @returns `true` if the species is considered valid.
*/
export function checkStarterValidForChallenge(species: PokemonSpecies, props: DexAttrProps, soft: boolean) {
if (!soft) {
const isValidForChallenge = new BooleanHolder(true);
applyChallenges(ChallengeType.STARTER_CHOICE, species, isValidForChallenge, props);
return isValidForChallenge.value;
}
// We check the validity of every evolution and form change, and require that at least one is valid
const speciesToCheck = [species.speciesId];
while (speciesToCheck.length) {
const checking = speciesToCheck.pop();
// Linter complains if we don't handle this
if (!checking) {
return false;
}
const checkingSpecies = getPokemonSpecies(checking);
if (checkSpeciesValidForChallenge(checkingSpecies, props, true)) {
return true;
}
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
pokemonEvolutions[checking].forEach(e => {
// Form check to deal with cases such as Basculin -> Basculegion
// TODO: does this miss anything if checking forms of a stage 2 Pokémon?
if (!e?.preFormKey || e.preFormKey === species.forms[props.formIndex].formKey) {
speciesToCheck.push(e.speciesId);
}
});
}
}
return false;
}
/**
* Apply all challenges to the given species (and form) to check its validity.
* Differs from {@linkcode checkStarterValidForChallenge} which also checks evolutions.
* @param species - The {@linkcode PokemonSpecies} to check the validity of.
* @param dexAttr - The {@linkcode DexAttrProps | dex attributes} of the species, including its form index.
* @param soft - If `true`, allow it if it could become valid through a form change.
* @returns `true` if the species is considered valid.
*/
function checkSpeciesValidForChallenge(species: PokemonSpecies, props: DexAttrProps, soft: boolean) {
const isValidForChallenge = new BooleanHolder(true);
applyChallenges(ChallengeType.STARTER_CHOICE, species, isValidForChallenge, props);
if (!soft || !pokemonFormChanges.hasOwnProperty(species.speciesId)) {
return isValidForChallenge.value;
}
// If the form in props is valid, return true before checking other form changes
if (soft && isValidForChallenge.value) {
return true;
}
const result = pokemonFormChanges[species.speciesId].some(f1 => {
// Exclude form changes that require the mon to be on the field to begin with
if (!("item" in f1.trigger)) {
return false;
}
return species.forms.some((f2, formIndex) => {
if (f1.formKey === f2.formKey) {
const formProps = { ...props, formIndex };
const isFormValidForChallenge = new BooleanHolder(true);
applyChallenges(ChallengeType.STARTER_CHOICE, species, isFormValidForChallenge, formProps);
return isFormValidForChallenge.value;
}
return false;
});
});
return result;
}

View File

@ -22,7 +22,6 @@ import {
TypeBoostTag, TypeBoostTag,
} from "#data/battler-tags"; } from "#data/battler-tags";
import { getBerryEffectFunc } from "#data/berry"; import { getBerryEffectFunc } from "#data/berry";
import { applyChallenges } from "#data/challenge";
import { allAbilities, allHeldItems, allMoves } from "#data/data-lists"; import { allAbilities, allHeldItems, allMoves } from "#data/data-lists";
import { SpeciesFormChangeRevertWeatherFormTrigger } from "#data/form-change-triggers"; import { SpeciesFormChangeRevertWeatherFormTrigger } from "#data/form-change-triggers";
import { DelayedAttackTag } from "#data/positional-tags/positional-tag"; import { DelayedAttackTag } from "#data/positional-tags/positional-tag";
@ -89,6 +88,7 @@ import { BooleanHolder, type Constructor, isNullOrUndefined, NumberHolder, randS
import { getEnumValues } from "#utils/enums"; import { getEnumValues } from "#utils/enums";
import { toTitleCase } from "#utils/strings"; import { toTitleCase } from "#utils/strings";
import i18next from "i18next"; import i18next from "i18next";
import { applyChallenges } from "#utils/challenge-utils";
/** /**
* A function used to conditionally determine execution of a given {@linkcode MoveAttr}. * A function used to conditionally determine execution of a given {@linkcode MoveAttr}.
@ -120,7 +120,7 @@ export abstract class Move implements Localizable {
/** /**
* Check if the move is of the given subclass without requiring `instanceof`. * Check if the move is of the given subclass without requiring `instanceof`.
* *
* Does _not_ work for {@linkcode ChargingAttackMove} and {@linkcode ChargingSelfStatusMove} subclasses. For those, * ! Does _not_ work for {@linkcode ChargingAttackMove} and {@linkcode ChargingSelfStatusMove} subclasses. For those,
* use {@linkcode isChargingMove} instead. * use {@linkcode isChargingMove} instead.
* *
* @param moveKind - The string name of the move to check against * @param moveKind - The string name of the move to check against
@ -6903,13 +6903,19 @@ export class RandomMoveAttr extends CallMoveAttr {
* @param move Move being used * @param move Move being used
* @param args Unused * @param args Unused
*/ */
override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { override apply(user: Pokemon, target: Pokemon, _move: Move, args: any[]): boolean {
// TODO: Move this into the constructor to avoid constructing this every call
const moveIds = getEnumValues(MoveId).map(m => !this.invalidMoves.has(m) && !allMoves[m].name.endsWith(" (N)") ? m : MoveId.NONE); const moveIds = getEnumValues(MoveId).map(m => !this.invalidMoves.has(m) && !allMoves[m].name.endsWith(" (N)") ? m : MoveId.NONE);
let moveId: MoveId = MoveId.NONE; let moveId: MoveId = MoveId.NONE;
const moveStatus = new BooleanHolder(true);
do { do {
moveId = this.getMoveOverride() ?? moveIds[user.randBattleSeedInt(moveIds.length)]; moveId = this.getMoveOverride() ?? moveIds[user.randBattleSeedInt(moveIds.length)];
moveStatus.value = moveId !== MoveId.NONE;
if (user.isPlayer()) {
applyChallenges(ChallengeType.POKEMON_MOVE, moveId, moveStatus);
}
} }
while (moveId === MoveId.NONE); while (!moveStatus.value);
return super.apply(user, target, allMoves[moveId], args); return super.apply(user, target, allMoves[moveId], args);
} }
} }

View File

@ -1,8 +1,10 @@
import { allMoves } from "#data/data-lists"; import { allMoves } from "#data/data-lists";
import type { MoveId } from "#enums/move-id"; import { ChallengeType } from "#enums/challenge-type";
import { MoveId } from "#enums/move-id";
import type { Pokemon } from "#field/pokemon"; import type { Pokemon } from "#field/pokemon";
import type { Move } from "#moves/move"; import type { Move } from "#moves/move";
import { toDmgValue } from "#utils/common"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, toDmgValue } from "#utils/common";
/** /**
* Wrapper class for the {@linkcode Move} class for Pokemon to interact with. * Wrapper class for the {@linkcode Move} class for Pokemon to interact with.
@ -45,16 +47,18 @@ export class PokemonMove {
* @returns Whether this {@linkcode PokemonMove} can be selected by this Pokemon. * @returns Whether this {@linkcode PokemonMove} can be selected by this Pokemon.
*/ */
isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean { isUsable(pokemon: Pokemon, ignorePp = false, ignoreRestrictionTags = false): boolean {
const move = this.getMove();
// TODO: Add Sky Drop's 1 turn stall // TODO: Add Sky Drop's 1 turn stall
if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) { const usability = new BooleanHolder(
return false; !move.name.endsWith(" (N)") &&
(ignorePp || this.ppUsed < this.getMovePp() || move.pp === -1) &&
// TODO: Review if the `MoveId.NONE` check is even necessary anymore
!(this.moveId !== MoveId.NONE && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)),
);
if (pokemon.isPlayer()) {
applyChallenges(ChallengeType.POKEMON_MOVE, move.id, usability);
} }
return usability.value;
if (this.getMove().name.endsWith(" (N)")) {
return false;
}
return ignorePp || this.ppUsed < this.getMovePp() || this.getMove().pp === -1;
} }
getMove(): Move { getMove(): Move {

View File

@ -63,12 +63,12 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
break; break;
case 3: case 3:
trainerType = TrainerType.MIRA; trainerType = TrainerType.MIRA;
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.ALAKAZAM, false, 1); spriteKeys = getSpriteKeysFromSpecies(SpeciesId.ALAKAZAM);
trainerNameKey = "mira"; trainerNameKey = "mira";
break; break;
case 4: case 4:
trainerType = TrainerType.RILEY; trainerType = TrainerType.RILEY;
spriteKeys = getSpriteKeysFromSpecies(SpeciesId.LUCARIO, false, 1); spriteKeys = getSpriteKeysFromSpecies(SpeciesId.LUCARIO);
trainerNameKey = "riley"; trainerNameKey = "riley";
break; break;
default: default:
@ -164,8 +164,8 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder.
encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`)); encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`));
setEncounterRewards( setEncounterRewards(
{ {
guaranteedRewardSpecs: [RewardId.SACRED_ASH], guaranteedRewardSpecs: [RewardId.RELIC_GOLD],
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ULTRA], guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE],
fillRemaining: true, fillRemaining: true,
}, },
[eggOptions], [eggOptions],

View File

@ -39,7 +39,7 @@ import {
} from "#mystery-encounters/mystery-encounter-requirements"; } from "#mystery-encounters/mystery-encounter-requirements";
import { getRandomPartyMemberFunc, trainerConfigs } from "#trainers/trainer-config"; import { getRandomPartyMemberFunc, trainerConfigs } from "#trainers/trainer-config";
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template"; import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { MoveInfoOverlay } from "#ui/move-info-overlay"; import { MoveInfoOverlay } from "#ui/move-info-overlay";
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#utils/common"; import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
@ -689,15 +689,13 @@ function doBugTypeMoveTutor(): Promise<void> {
const moveOptions = globalScene.currentBattle.mysteryEncounter!.misc.moveTutorOptions; const moveOptions = globalScene.currentBattle.mysteryEncounter!.misc.moveTutorOptions;
await showEncounterDialogue(`${namespace}:battle_won`, `${namespace}:speaker`); await showEncounterDialogue(`${namespace}:battle_won`, `${namespace}:speaker`);
const overlayScale = 1;
const moveInfoOverlay = new MoveInfoOverlay({ const moveInfoOverlay = new MoveInfoOverlay({
delayVisibility: false, delayVisibility: false,
scale: overlayScale,
onSide: true, onSide: true,
right: true, right: true,
x: 1, x: 1,
y: -MoveInfoOverlay.getHeight(overlayScale, true) - 1, y: -MoveInfoOverlay.getHeight(true) - 1,
width: globalScene.game.canvas.width / 6 - 2, width: globalScene.scaledCanvas.width - 2,
}); });
globalScene.ui.add(moveInfoOverlay); globalScene.ui.add(moveInfoOverlay);

View File

@ -40,7 +40,7 @@ import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { trainerConfigs } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config";
import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template"; import { TrainerPartyCompoundTemplate, TrainerPartyTemplate } from "#trainers/trainer-party-template";
import type { OptionSelectConfig } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig } from "#ui/abstract-option-select-ui-handler";
import { randSeedInt, randSeedShuffle } from "#utils/common"; import { randSeedInt, randSeedShuffle } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -37,7 +37,7 @@ import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encou
import { MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements"; import { MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { DANCING_MOVES } from "#mystery-encounters/requirement-groups"; import { DANCING_MOVES } from "#mystery-encounters/requirement-groups";
import { PokemonData } from "#system/pokemon-data"; import { PokemonData } from "#system/pokemon-data";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -22,12 +22,8 @@ const namespace = "mysteryEncounters/darkDeal";
/** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and Mythicals */ /** Exclude Ultra Beasts (inludes Cosmog/Solgaleo/Lunala/Necrozma), Paradox (includes Miraidon/Koraidon), Eternatus, and Mythicals */
const excludedBosses = [ const excludedBosses = [
SpeciesId.NECROZMA,
SpeciesId.COSMOG,
SpeciesId.COSMOEM,
SpeciesId.SOLGALEO,
SpeciesId.LUNALA,
SpeciesId.ETERNATUS, SpeciesId.ETERNATUS,
/** UBs */
SpeciesId.NIHILEGO, SpeciesId.NIHILEGO,
SpeciesId.BUZZWOLE, SpeciesId.BUZZWOLE,
SpeciesId.PHEROMOSA, SpeciesId.PHEROMOSA,
@ -39,6 +35,12 @@ const excludedBosses = [
SpeciesId.NAGANADEL, SpeciesId.NAGANADEL,
SpeciesId.STAKATAKA, SpeciesId.STAKATAKA,
SpeciesId.BLACEPHALON, SpeciesId.BLACEPHALON,
SpeciesId.COSMOG,
SpeciesId.COSMOEM,
SpeciesId.SOLGALEO,
SpeciesId.LUNALA,
SpeciesId.NECROZMA,
/** Paradox */
SpeciesId.GREAT_TUSK, SpeciesId.GREAT_TUSK,
SpeciesId.SCREAM_TAIL, SpeciesId.SCREAM_TAIL,
SpeciesId.BRUTE_BONNET, SpeciesId.BRUTE_BONNET,
@ -46,10 +48,10 @@ const excludedBosses = [
SpeciesId.SLITHER_WING, SpeciesId.SLITHER_WING,
SpeciesId.SANDY_SHOCKS, SpeciesId.SANDY_SHOCKS,
SpeciesId.ROARING_MOON, SpeciesId.ROARING_MOON,
SpeciesId.KORAIDON,
SpeciesId.WALKING_WAKE, SpeciesId.WALKING_WAKE,
SpeciesId.GOUGING_FIRE, SpeciesId.GOUGING_FIRE,
SpeciesId.RAGING_BOLT, SpeciesId.RAGING_BOLT,
SpeciesId.KORAIDON,
SpeciesId.IRON_TREADS, SpeciesId.IRON_TREADS,
SpeciesId.IRON_BUNDLE, SpeciesId.IRON_BUNDLE,
SpeciesId.IRON_HANDS, SpeciesId.IRON_HANDS,
@ -57,22 +59,23 @@ const excludedBosses = [
SpeciesId.IRON_MOTH, SpeciesId.IRON_MOTH,
SpeciesId.IRON_THORNS, SpeciesId.IRON_THORNS,
SpeciesId.IRON_VALIANT, SpeciesId.IRON_VALIANT,
SpeciesId.MIRAIDON,
SpeciesId.IRON_LEAVES, SpeciesId.IRON_LEAVES,
SpeciesId.IRON_BOULDER, SpeciesId.IRON_BOULDER,
SpeciesId.IRON_CROWN, SpeciesId.IRON_CROWN,
SpeciesId.MIRAIDON,
/** Mythical */
SpeciesId.MEW, SpeciesId.MEW,
SpeciesId.CELEBI, SpeciesId.CELEBI,
SpeciesId.DEOXYS,
SpeciesId.JIRACHI, SpeciesId.JIRACHI,
SpeciesId.DARKRAI, SpeciesId.DEOXYS,
SpeciesId.PHIONE, SpeciesId.PHIONE,
SpeciesId.MANAPHY, SpeciesId.MANAPHY,
SpeciesId.ARCEUS, SpeciesId.DARKRAI,
SpeciesId.SHAYMIN, SpeciesId.SHAYMIN,
SpeciesId.ARCEUS,
SpeciesId.VICTINI, SpeciesId.VICTINI,
SpeciesId.MELOETTA,
SpeciesId.KELDEO, SpeciesId.KELDEO,
SpeciesId.MELOETTA,
SpeciesId.GENESECT, SpeciesId.GENESECT,
SpeciesId.DIANCIE, SpeciesId.DIANCIE,
SpeciesId.HOOPA, SpeciesId.HOOPA,
@ -80,9 +83,9 @@ const excludedBosses = [
SpeciesId.MAGEARNA, SpeciesId.MAGEARNA,
SpeciesId.MARSHADOW, SpeciesId.MARSHADOW,
SpeciesId.ZERAORA, SpeciesId.ZERAORA,
SpeciesId.ZARUDE,
SpeciesId.MELTAN, SpeciesId.MELTAN,
SpeciesId.MELMETAL, SpeciesId.MELMETAL,
SpeciesId.ZARUDE,
SpeciesId.PECHARUNT, SpeciesId.PECHARUNT,
]; ];

View File

@ -25,7 +25,7 @@ import {
MoneyRequirement, MoneyRequirement,
} from "#mystery-encounters/mystery-encounter-requirements"; } from "#mystery-encounters/mystery-encounter-requirements";
import i18next from "#plugins/i18n"; import i18next from "#plugins/i18n";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { randSeedItem } from "#utils/common"; import { randSeedItem } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";

View File

@ -19,7 +19,7 @@ import {
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter"; import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter"; import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import i18next from "i18next"; import i18next from "i18next";
/** i18n namespace for the encounter */ /** i18n namespace for the encounter */

View File

@ -39,7 +39,7 @@ import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encou
import { PartySizeRequirement } from "#mystery-encounters/mystery-encounter-requirements"; import { PartySizeRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { PokemonData } from "#system/pokemon-data"; import { PokemonData } from "#system/pokemon-data";
import { MusicPreference } from "#system/settings"; import { MusicPreference } from "#system/settings";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { isNullOrUndefined, NumberHolder, randInt, randSeedInt, randSeedItem, randSeedShuffle } from "#utils/common"; import { isNullOrUndefined, NumberHolder, randInt, randSeedInt, randSeedItem, randSeedShuffle } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import i18next from "i18next"; import i18next from "i18next";
@ -542,14 +542,14 @@ function generateTradeOption(alreadyUsedSpecies: PokemonSpecies[], originalBst?:
function showTradeBackground() { function showTradeBackground() {
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
const tradeContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); const tradeContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
tradeContainer.setName("Trade Background"); tradeContainer.setName("Trade Background");
const flyByStaticBg = globalScene.add.rectangle( const flyByStaticBg = globalScene.add.rectangle(
0, 0,
0, 0,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6, globalScene.scaledCanvas.height,
0, 0,
); );
flyByStaticBg.setName("Black Background"); flyByStaticBg.setName("Black Background");

View File

@ -52,37 +52,6 @@ class BreederSpeciesEvolution {
} }
const POOL_1_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [ const POOL_1_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [
[SpeciesId.MUNCHLAX, new BreederSpeciesEvolution(SpeciesId.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
[
SpeciesId.HAPPINY,
new BreederSpeciesEvolution(SpeciesId.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE),
],
[
SpeciesId.MAGBY,
new BreederSpeciesEvolution(SpeciesId.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE),
],
[
SpeciesId.ELEKID,
new BreederSpeciesEvolution(SpeciesId.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE),
],
[SpeciesId.RIOLU, new BreederSpeciesEvolution(SpeciesId.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
[
SpeciesId.BUDEW,
new BreederSpeciesEvolution(SpeciesId.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE),
],
[SpeciesId.TOXEL, new BreederSpeciesEvolution(SpeciesId.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
[
SpeciesId.MIME_JR,
new BreederSpeciesEvolution(SpeciesId.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE),
],
];
const POOL_2_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [
[ [
SpeciesId.PICHU, SpeciesId.PICHU,
new BreederSpeciesEvolution(SpeciesId.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE),
@ -93,24 +62,63 @@ const POOL_2_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [
new BreederSpeciesEvolution(SpeciesId.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE),
], ],
[SpeciesId.SMOOCHUM, new BreederSpeciesEvolution(SpeciesId.JYNX, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
[ [
SpeciesId.IGGLYBUFF, SpeciesId.IGGLYBUFF,
new BreederSpeciesEvolution(SpeciesId.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE),
], ],
[
SpeciesId.TOGEPI,
new BreederSpeciesEvolution(SpeciesId.TOGETIC, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.TOGEKISS, FINAL_STAGE_EVOLUTION_WAVE),
],
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.TYROGUE, new BreederSpeciesEvolution(SpeciesId.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.SMOOCHUM, new BreederSpeciesEvolution(SpeciesId.JYNX, FIRST_STAGE_EVOLUTION_WAVE)],
[ [
SpeciesId.AZURILL, SpeciesId.AZURILL,
new BreederSpeciesEvolution(SpeciesId.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.MARILL, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(SpeciesId.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE),
], ],
[SpeciesId.WYNAUT, new BreederSpeciesEvolution(SpeciesId.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)], [
SpeciesId.BUDEW,
new BreederSpeciesEvolution(SpeciesId.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE),
],
[SpeciesId.CHINGLING, new BreederSpeciesEvolution(SpeciesId.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)], [SpeciesId.CHINGLING, new BreederSpeciesEvolution(SpeciesId.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.BONSLY, new BreederSpeciesEvolution(SpeciesId.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)], [SpeciesId.BONSLY, new BreederSpeciesEvolution(SpeciesId.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.MIME_JR, new BreederSpeciesEvolution(SpeciesId.MR_MIME, SECOND_STAGE_EVOLUTION_WAVE)],
[
SpeciesId.MIME_JR,
new BreederSpeciesEvolution(SpeciesId.GALAR_MR_MIME, SECOND_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE),
],
[
SpeciesId.HAPPINY,
new BreederSpeciesEvolution(SpeciesId.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE),
],
[SpeciesId.MANTYKE, new BreederSpeciesEvolution(SpeciesId.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)], [SpeciesId.MANTYKE, new BreederSpeciesEvolution(SpeciesId.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.TOXEL, new BreederSpeciesEvolution(SpeciesId.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)],
];
const POOL_2_POKEMON: (SpeciesId | BreederSpeciesEvolution)[][] = [
[SpeciesId.DITTO],
[
SpeciesId.ELEKID,
new BreederSpeciesEvolution(SpeciesId.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE),
],
[
SpeciesId.MAGBY,
new BreederSpeciesEvolution(SpeciesId.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE),
new BreederSpeciesEvolution(SpeciesId.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE),
],
[SpeciesId.WYNAUT, new BreederSpeciesEvolution(SpeciesId.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.MUNCHLAX, new BreederSpeciesEvolution(SpeciesId.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.RIOLU, new BreederSpeciesEvolution(SpeciesId.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)],
[SpeciesId.AUDINO],
]; ];
/** /**
@ -502,7 +510,7 @@ function getPartyConfig(): EnemyPartyConfig {
shiny: true, shiny: true,
variant: 1, variant: 1,
nature: Nature.MODEST, nature: Nature.MODEST,
moveSet: [MoveId.MOONBLAST, MoveId.MYSTICAL_FIRE, MoveId.ICE_BEAM, MoveId.THUNDERBOLT], moveSet: [MoveId.DAZZLING_GLEAM, MoveId.MYSTICAL_FIRE, MoveId.ICE_BEAM, MoveId.THUNDERBOLT], // Make this one have an item gimmick when we have more items/finish implementations
ivs: [31, 31, 31, 31, 31, 31], ivs: [31, 31, 31, 31, 31, 31],
}, },
{ {
@ -515,7 +523,7 @@ function getPartyConfig(): EnemyPartyConfig {
shiny: true, shiny: true,
variant: 2, variant: 2,
nature: Nature.BOLD, nature: Nature.BOLD,
moveSet: [MoveId.TRI_ATTACK, MoveId.STORED_POWER, MoveId.TAKE_HEART, MoveId.MOONLIGHT], moveSet: [MoveId.TRI_ATTACK, MoveId.STORED_POWER, MoveId.CALM_MIND, MoveId.MOONLIGHT],
ivs: [31, 31, 31, 31, 31, 31], ivs: [31, 31, 31, 31, 31, 31],
}, },
); );

View File

@ -25,7 +25,7 @@ import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter"; import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { PokemonData } from "#system/pokemon-data"; import { PokemonData } from "#system/pokemon-data";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { isNullOrUndefined, randSeedShuffle } from "#utils/common"; import { isNullOrUndefined, randSeedShuffle } from "#utils/common";
import { getEnumValues } from "#utils/enums"; import { getEnumValues } from "#utils/enums";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -14,16 +14,16 @@ import { TrainerItemId } from "#enums/trainer-item-id";
import { assignItemToFirstFreePokemon } from "#items/item-utility"; import { assignItemToFirstFreePokemon } from "#items/item-utility";
import { PokemonMove } from "#moves/pokemon-move"; import { PokemonMove } from "#moves/pokemon-move";
import { showEncounterText } from "#mystery-encounters/encounter-dialogue-utils"; import { showEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
import type { EnemyPartyConfig, EnemyPokemonConfig } from "#mystery-encounters/encounter-phase-utils";
import { import {
type EnemyPartyConfig,
type EnemyPokemonConfig,
initBattleWithEnemyConfig, initBattleWithEnemyConfig,
leaveEncounterWithoutBattle, leaveEncounterWithoutBattle,
loadCustomMovesForEncounter, loadCustomMovesForEncounter,
setEncounterRewards, setEncounterRewards,
transitionMysteryEncounterIntroVisuals, transitionMysteryEncounterIntroVisuals,
} from "#mystery-encounters/encounter-phase-utils"; } from "#mystery-encounters/encounter-phase-utils";
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter"; import { type MysteryEncounter, MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import i18next from "#plugins/i18n"; import i18next from "#plugins/i18n";
import { randSeedInt } from "#utils/common"; import { randSeedInt } from "#utils/common";
@ -167,7 +167,8 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde
const encounter = globalScene.currentBattle.mysteryEncounter!; const encounter = globalScene.currentBattle.mysteryEncounter!;
setEncounterRewards({ setEncounterRewards({
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ROGUE, RarityTier.ULTRA, RarityTier.GREAT], guaranteedRewardSpecs: [HeldItemId.LEFTOVERS],
guaranteedRarityTiers: [RarityTier.ROGUE, RarityTier.ULTRA, RarityTier.GREAT],
fillRemaining: true, fillRemaining: true,
}); });
encounter.startOfBattleEffects.push( encounter.startOfBattleEffects.push(

View File

@ -46,6 +46,7 @@ const namespace = "mysteryEncounters/weirdDream";
/** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */ /** Exclude Ultra Beasts, Paradox, Eternatus, and all legendary/mythical/trio pokemon that are below 570 BST */
const EXCLUDED_TRANSFORMATION_SPECIES = [ const EXCLUDED_TRANSFORMATION_SPECIES = [
SpeciesId.ARCEUS,
SpeciesId.ETERNATUS, SpeciesId.ETERNATUS,
/** UBs */ /** UBs */
SpeciesId.NIHILEGO, SpeciesId.NIHILEGO,
@ -81,20 +82,19 @@ const EXCLUDED_TRANSFORMATION_SPECIES = [
SpeciesId.IRON_BOULDER, SpeciesId.IRON_BOULDER,
SpeciesId.IRON_CROWN, SpeciesId.IRON_CROWN,
/** These are banned so they don't appear in the < 570 BST pool */ /** These are banned so they don't appear in the < 570 BST pool */
SpeciesId.PHIONE,
SpeciesId.TYPE_NULL,
SpeciesId.COSMOG, SpeciesId.COSMOG,
SpeciesId.COSMOEM,
SpeciesId.MELTAN, SpeciesId.MELTAN,
SpeciesId.KUBFU, SpeciesId.KUBFU,
SpeciesId.COSMOEM,
SpeciesId.POIPOLE,
SpeciesId.TERAPAGOS,
SpeciesId.TYPE_NULL,
SpeciesId.CALYREX,
SpeciesId.NAGANADEL,
SpeciesId.URSHIFU, SpeciesId.URSHIFU,
SpeciesId.CALYREX,
SpeciesId.OGERPON, SpeciesId.OGERPON,
SpeciesId.OKIDOGI, SpeciesId.OKIDOGI,
SpeciesId.MUNKIDORI, SpeciesId.MUNKIDORI,
SpeciesId.FEZANDIPITI, SpeciesId.FEZANDIPITI,
SpeciesId.TERAPAGOS,
]; ];
const SUPER_LEGENDARY_BST_THRESHOLD = 600; const SUPER_LEGENDARY_BST_THRESHOLD = 600;
@ -225,6 +225,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit
RewardId.MINT, RewardId.MINT,
RewardId.MINT, RewardId.MINT,
RewardId.MINT, RewardId.MINT,
RewardId.MINT,
], ],
fillRemaining: false, fillRemaining: false,
}); });
@ -638,15 +639,15 @@ function getTransformedSpecies(
} }
function doShowDreamBackground() { function doShowDreamBackground() {
const transformationContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); const transformationContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
transformationContainer.name = "Dream Background"; transformationContainer.name = "Dream Background";
// In case it takes a bit for video to load // In case it takes a bit for video to load
const transformationStaticBg = globalScene.add.rectangle( const transformationStaticBg = globalScene.add.rectangle(
0, 0,
0, 0,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6, globalScene.scaledCanvas.height,
0, 0,
); );
transformationStaticBg.setName("Black Background"); transformationStaticBg.setName("Black Background");

View File

@ -156,7 +156,7 @@ export class MysteryEncounterOption implements IMysteryEncounterOption {
return true; return true;
} }
console.log( console.log(
"Mystery Encounter Edge Case: Requirement not met due to primay pokemon overlapping with support pokemon. There's no valid primary pokemon left.", "Mystery Encounter Edge Case: Requirement not met due to primary pokemon overlapping with support pokemon. There's no valid primary pokemon left.",
); );
return false; return false;
} }

View File

@ -576,7 +576,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
*/ */
/** /**
* @statif Defines the type of encounter which is used as an identifier, should be tied to a unique MysteryEncounterType * @static Defines the type of encounter which is used as an identifier, should be tied to a unique MysteryEncounterType
* NOTE: if new functions are added to {@linkcode MysteryEncounter} class * NOTE: if new functions are added to {@linkcode MysteryEncounter} class
* @param encounterType * @param encounterType
* @returns this * @returns this
@ -605,7 +605,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
} }
/** /**
* Defines an option + phasefor the encounter. * Defines an option + phase for the encounter.
* Use for easy/streamlined options. * Use for easy/streamlined options.
* There should be at least 2 options defined and no more than 4. * There should be at least 2 options defined and no more than 4.
* If complex use {@linkcode MysteryEncounterBuilder.withOption} * If complex use {@linkcode MysteryEncounterBuilder.withOption}
@ -627,7 +627,7 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
} }
/** /**
* Defines an option + phasefor the encounter. * Defines an option + phase for the encounter.
* Use for easy/streamlined options. * Use for easy/streamlined options.
* There should be at least 2 options defined and no more than 4. * There should be at least 2 options defined and no more than 4.
* If complex use {@linkcode MysteryEncounterBuilder.withOption} * If complex use {@linkcode MysteryEncounterBuilder.withOption}

View File

@ -6,7 +6,7 @@ import { isNullOrUndefined } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
/** /**
* Will inject all relevant dialogue tokens that exist in the {@linkcode BattlegScene.currentBattle.mysteryEncounter.dialogueTokens}, into i18n text. * Will inject all relevant dialogue tokens that exist in the {@linkcode globalScene.currentBattle.mysteryEncounter.dialogueTokens}, into i18n text.
* Also adds BBCodeText fragments for colored text, if applicable * Also adds BBCodeText fragments for colored text, if applicable
* @param keyOrString * @param keyOrString
* @param primaryStyle Can define a text style to be applied to the entire string. Must be defined for BBCodeText styles to be applied correctly * @param primaryStyle Can define a text style to be applied to the entire string. Must be defined for BBCodeText styles to be applied correctly

View File

@ -37,7 +37,7 @@ import type { Variant } from "#sprites/variant";
import type { PokemonData } from "#system/pokemon-data"; import type { PokemonData } from "#system/pokemon-data";
import type { TrainerConfig } from "#trainers/trainer-config"; import type { TrainerConfig } from "#trainers/trainer-config";
import { trainerConfigs } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config";
import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import type { PartyOption, PokemonSelectFilter } from "#ui/party-ui-handler"; import type { PartyOption, PokemonSelectFilter } from "#ui/party-ui-handler";
import { PartyUiMode } from "#ui/party-ui-handler"; import { PartyUiMode } from "#ui/party-ui-handler";
import { coerceArray, isNullOrUndefined, randomString, randSeedInt, randSeedItem } from "#utils/common"; import { coerceArray, isNullOrUndefined, randomString, randSeedInt, randSeedItem } from "#utils/common";

View File

@ -13,6 +13,7 @@ import type { PokemonSpecies } from "#data/pokemon-species";
import { getStatusEffectCatchRateMultiplier } from "#data/status-effect"; import { getStatusEffectCatchRateMultiplier } from "#data/status-effect";
import type { AbilityId } from "#enums/ability-id"; import type { AbilityId } from "#enums/ability-id";
import type { HeldItemId } from "#enums/held-item-id"; import type { HeldItemId } from "#enums/held-item-id";
import { ChallengeType } from "#enums/challenge-type";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import type { PokeballType } from "#enums/pokeball"; import type { PokeballType } from "#enums/pokeball";
import type { PokemonType } from "#enums/pokemon-type"; import type { PokemonType } from "#enums/pokemon-type";
@ -31,7 +32,8 @@ import { achvs } from "#system/achv";
import type { PartyOption } from "#ui/party-ui-handler"; import type { PartyOption } from "#ui/party-ui-handler";
import { PartyUiMode } from "#ui/party-ui-handler"; import { PartyUiMode } from "#ui/party-ui-handler";
import { SummaryUiMode } from "#ui/summary-ui-handler"; import { SummaryUiMode } from "#ui/summary-ui-handler";
import { isNullOrUndefined, randSeedInt } from "#utils/common"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, isNullOrUndefined, randSeedInt } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import i18next from "i18next"; import i18next from "i18next";
@ -647,6 +649,25 @@ export async function catchPokemon(
} }
}; };
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => { Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
const addStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
if (!addStatus.value) {
removePokemon();
if (newPokemon) {
newPokemon.loadAssets().then(end);
} else {
end();
}
});
};
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
const addStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
if (!addStatus.value) {
removePokemon();
end();
return;
}
if (globalScene.getPlayerParty().length === 6) { if (globalScene.getPlayerParty().length === 6) {
const promptRelease = () => { const promptRelease = () => {
globalScene.ui.showText( globalScene.ui.showText(

File diff suppressed because it is too large Load Diff

View File

@ -1,624 +1,624 @@
export enum AbilityId { export enum AbilityId {
/**{@link https://bulbapedia.bulbagarden.net/wiki/None_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/None_(ability) | Source} */
NONE, NONE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stench_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Stench_(ability) | Source} */
STENCH, STENCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Drizzle_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Drizzle_(ability) | Source} */
DRIZZLE, DRIZZLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Speed_Boost_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Speed_Boost_(ability) | Source} */
SPEED_BOOST, SPEED_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Battle_Armor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Battle_Armor_(ability) | Source} */
BATTLE_ARMOR, BATTLE_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sturdy_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sturdy_(ability) | Source} */
STURDY, STURDY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Damp_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Damp_(ability) | Source} */
DAMP, DAMP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Limber_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Limber_(ability) | Source} */
LIMBER, LIMBER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Veil_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sand_Veil_(ability) | Source} */
SAND_VEIL, SAND_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Static_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Static_(ability) | Source} */
STATIC, STATIC,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Volt_Absorb_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Volt_Absorb_(ability) | Source} */
VOLT_ABSORB, VOLT_ABSORB,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Absorb_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Water_Absorb_(ability) | Source} */
WATER_ABSORB, WATER_ABSORB,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Oblivious_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Oblivious_(ability) | Source} */
OBLIVIOUS, OBLIVIOUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cloud_Nine_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Cloud_Nine_(ability) | Source} */
CLOUD_NINE, CLOUD_NINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Compound_Eyes_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Compound_Eyes_(ability) | Source} */
COMPOUND_EYES, COMPOUND_EYES,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Insomnia_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Insomnia_(ability) | Source} */
INSOMNIA, INSOMNIA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Color_Change_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Color_Change_(ability) | Source} */
COLOR_CHANGE, COLOR_CHANGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Immunity_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Immunity_(ability) | Source} */
IMMUNITY, IMMUNITY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flash_Fire_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Flash_Fire_(ability) | Source} */
FLASH_FIRE, FLASH_FIRE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shield_Dust_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Shield_Dust_(ability) | Source} */
SHIELD_DUST, SHIELD_DUST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Own_Tempo_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Own_Tempo_(ability) | Source} */
OWN_TEMPO, OWN_TEMPO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Suction_Cups_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Suction_Cups_(ability) | Source} */
SUCTION_CUPS, SUCTION_CUPS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Intimidate_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Intimidate_(ability) | Source} */
INTIMIDATE, INTIMIDATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shadow_Tag_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Shadow_Tag_(ability) | Source} */
SHADOW_TAG, SHADOW_TAG,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rough_Skin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rough_Skin_(ability) | Source} */
ROUGH_SKIN, ROUGH_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wonder_Guard_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Wonder_Guard_(ability) | Source} */
WONDER_GUARD, WONDER_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Levitate_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Levitate_(ability) | Source} */
LEVITATE, LEVITATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Effect_Spore_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Effect_Spore_(ability) | Source} */
EFFECT_SPORE, EFFECT_SPORE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Synchronize_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Synchronize_(ability) | Source} */
SYNCHRONIZE, SYNCHRONIZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Clear_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Clear_Body_(ability) | Source} */
CLEAR_BODY, CLEAR_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Natural_Cure_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Natural_Cure_(ability) | Source} */
NATURAL_CURE, NATURAL_CURE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Lightning_Rod_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Lightning_Rod_(ability) | Source} */
LIGHTNING_ROD, LIGHTNING_ROD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Serene_Grace_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Serene_Grace_(ability) | Source} */
SERENE_GRACE, SERENE_GRACE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Swift_Swim_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Swift_Swim_(ability) | Source} */
SWIFT_SWIM, SWIFT_SWIM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Chlorophyll_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Chlorophyll_(ability) | Source} */
CHLOROPHYLL, CHLOROPHYLL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Illuminate_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Illuminate_(ability) | Source} */
ILLUMINATE, ILLUMINATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Trace_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Trace_(ability) | Source} */
TRACE, TRACE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Huge_Power_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Huge_Power_(ability) | Source} */
HUGE_POWER, HUGE_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Point_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Poison_Point_(ability) | Source} */
POISON_POINT, POISON_POINT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Inner_Focus_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Inner_Focus_(ability) | Source} */
INNER_FOCUS, INNER_FOCUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magma_Armor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Magma_Armor_(ability) | Source} */
MAGMA_ARMOR, MAGMA_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Veil_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Water_Veil_(ability) | Source} */
WATER_VEIL, WATER_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magnet_Pull_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Magnet_Pull_(ability) | Source} */
MAGNET_PULL, MAGNET_PULL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Soundproof_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Soundproof_(ability) | Source} */
SOUNDPROOF, SOUNDPROOF,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rain_Dish_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rain_Dish_(ability) | Source} */
RAIN_DISH, RAIN_DISH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Stream_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sand_Stream_(ability) | Source} */
SAND_STREAM, SAND_STREAM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pressure_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Pressure_(ability) | Source} */
PRESSURE, PRESSURE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Thick_Fat_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Thick_Fat_(ability) | Source} */
THICK_FAT, THICK_FAT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Early_Bird_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Early_Bird_(ability) | Source} */
EARLY_BIRD, EARLY_BIRD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flame_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Flame_Body_(ability) | Source} */
FLAME_BODY, FLAME_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Run_Away_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Run_Away_(ability) | Source} */
RUN_AWAY, RUN_AWAY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Keen_Eye_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Keen_Eye_(ability) | Source} */
KEEN_EYE, KEEN_EYE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hyper_Cutter_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Hyper_Cutter_(ability) | Source} */
HYPER_CUTTER, HYPER_CUTTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pickup_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Pickup_(ability) | Source} */
PICKUP, PICKUP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Truant_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Truant_(ability) | Source} */
TRUANT, TRUANT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hustle_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Hustle_(ability) | Source} */
HUSTLE, HUSTLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cute_Charm_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Cute_Charm_(ability) | Source} */
CUTE_CHARM, CUTE_CHARM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Plus_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Plus_(ability) | Source} */
PLUS, PLUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Minus_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Minus_(ability) | Source} */
MINUS, MINUS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Forecast_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Forecast_(ability) | Source} */
FORECAST, FORECAST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sticky_Hold_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sticky_Hold_(ability) | Source} */
STICKY_HOLD, STICKY_HOLD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shed_Skin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Shed_Skin_(ability) | Source} */
SHED_SKIN, SHED_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Guts_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Guts_(ability) | Source} */
GUTS, GUTS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Marvel_Scale_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Marvel_Scale_(ability) | Source} */
MARVEL_SCALE, MARVEL_SCALE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Liquid_Ooze_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Liquid_Ooze_(ability) | Source} */
LIQUID_OOZE, LIQUID_OOZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Overgrow_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Overgrow_(ability) | Source} */
OVERGROW, OVERGROW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Blaze_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Blaze_(ability) | Source} */
BLAZE, BLAZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Torrent_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Torrent_(ability) | Source} */
TORRENT, TORRENT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Swarm_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Swarm_(ability) | Source} */
SWARM, SWARM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rock_Head_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rock_Head_(ability) | Source} */
ROCK_HEAD, ROCK_HEAD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Drought_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Drought_(ability) | Source} */
DROUGHT, DROUGHT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Arena_Trap_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Arena_Trap_(ability) | Source} */
ARENA_TRAP, ARENA_TRAP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Vital_Spirit_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Vital_Spirit_(ability) | Source} */
VITAL_SPIRIT, VITAL_SPIRIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/White_Smoke_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/White_Smoke_(ability) | Source} */
WHITE_SMOKE, WHITE_SMOKE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pure_Power_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Pure_Power_(ability) | Source} */
PURE_POWER, PURE_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shell_Armor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Shell_Armor_(ability) | Source} */
SHELL_ARMOR, SHELL_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Air_Lock_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Air_Lock_(ability) | Source} */
AIR_LOCK, AIR_LOCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tangled_Feet_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tangled_Feet_(ability) | Source} */
TANGLED_FEET, TANGLED_FEET,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Motor_Drive_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Motor_Drive_(ability) | Source} */
MOTOR_DRIVE, MOTOR_DRIVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rivalry_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rivalry_(ability) | Source} */
RIVALRY, RIVALRY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steadfast_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Steadfast_(ability) | Source} */
STEADFAST, STEADFAST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Snow_Cloak_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Snow_Cloak_(ability) | Source} */
SNOW_CLOAK, SNOW_CLOAK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gluttony_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Gluttony_(ability) | Source} */
GLUTTONY, GLUTTONY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Anger_Point_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Anger_Point_(ability) | Source} */
ANGER_POINT, ANGER_POINT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unburden_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Unburden_(ability) | Source} */
UNBURDEN, UNBURDEN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Heatproof_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Heatproof_(ability) | Source} */
HEATPROOF, HEATPROOF,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Simple_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Simple_(ability) | Source} */
SIMPLE, SIMPLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dry_Skin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Dry_Skin_(ability) | Source} */
DRY_SKIN, DRY_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Download_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Download_(ability) | Source} */
DOWNLOAD, DOWNLOAD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Iron_Fist_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Iron_Fist_(ability) | Source} */
IRON_FIST, IRON_FIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Heal_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Poison_Heal_(ability) | Source} */
POISON_HEAL, POISON_HEAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Adaptability_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Adaptability_(ability) | Source} */
ADAPTABILITY, ADAPTABILITY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Skill_Link_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Skill_Link_(ability) | Source} */
SKILL_LINK, SKILL_LINK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hydration_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Hydration_(ability) | Source} */
HYDRATION, HYDRATION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Solar_Power_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Solar_Power_(ability) | Source} */
SOLAR_POWER, SOLAR_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Quick_Feet_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Quick_Feet_(ability) | Source} */
QUICK_FEET, QUICK_FEET,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Normalize_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Normalize_(ability) | Source} */
NORMALIZE, NORMALIZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sniper_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sniper_(ability) | Source} */
SNIPER, SNIPER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(ability) | Source} */
MAGIC_GUARD, MAGIC_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/No_Guard_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/No_Guard_(ability) | Source} */
NO_GUARD, NO_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stall_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Stall_(ability) | Source} */
STALL, STALL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Technician_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Technician_(ability) | Source} */
TECHNICIAN, TECHNICIAN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Leaf_Guard_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Leaf_Guard_(ability) | Source} */
LEAF_GUARD, LEAF_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Klutz_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Klutz_(ability) | Source} */
KLUTZ, KLUTZ,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mold_Breaker_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Mold_Breaker_(ability) | Source} */
MOLD_BREAKER, MOLD_BREAKER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Super_Luck_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Super_Luck_(ability) | Source} */
SUPER_LUCK, SUPER_LUCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aftermath_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Aftermath_(ability) | Source} */
AFTERMATH, AFTERMATH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Anticipation_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Anticipation_(ability) | Source} */
ANTICIPATION, ANTICIPATION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Forewarn_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Forewarn_(ability) | Source} */
FOREWARN, FOREWARN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unaware_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Unaware_(ability) | Source} */
UNAWARE, UNAWARE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tinted_Lens_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tinted_Lens_(ability) | Source} */
TINTED_LENS, TINTED_LENS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Filter_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Filter_(ability) | Source} */
FILTER, FILTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Slow_Start_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Slow_Start_(ability) | Source} */
SLOW_START, SLOW_START,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Scrappy_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Scrappy_(ability) | Source} */
SCRAPPY, SCRAPPY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Storm_Drain_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Storm_Drain_(ability) | Source} */
STORM_DRAIN, STORM_DRAIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ice_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Ice_Body_(ability) | Source} */
ICE_BODY, ICE_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Solid_Rock_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Solid_Rock_(ability) | Source} */
SOLID_ROCK, SOLID_ROCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Snow_Warning_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Snow_Warning_(ability) | Source} */
SNOW_WARNING, SNOW_WARNING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Honey_Gather_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Honey_Gather_(ability) | Source} */
HONEY_GATHER, HONEY_GATHER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Frisk_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Frisk_(ability) | Source} */
FRISK, FRISK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Reckless_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Reckless_(ability) | Source} */
RECKLESS, RECKLESS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Multitype_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Multitype_(ability) | Source} */
MULTITYPE, MULTITYPE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flower_Gift_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Flower_Gift_(ability) | Source} */
FLOWER_GIFT, FLOWER_GIFT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Bad_Dreams_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Bad_Dreams_(ability) | Source} */
BAD_DREAMS, BAD_DREAMS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pickpocket_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Pickpocket_(ability) | Source} */
PICKPOCKET, PICKPOCKET,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sheer_Force_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sheer_Force_(ability) | Source} */
SHEER_FORCE, SHEER_FORCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Contrary_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Contrary_(ability) | Source} */
CONTRARY, CONTRARY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unnerve_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Unnerve_(ability) | Source} */
UNNERVE, UNNERVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Defiant_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Defiant_(ability) | Source} */
DEFIANT, DEFIANT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Defeatist_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Defeatist_(ability) | Source} */
DEFEATIST, DEFEATIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cursed_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Cursed_Body_(ability) | Source} */
CURSED_BODY, CURSED_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Healer_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Healer_(ability) | Source} */
HEALER, HEALER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Friend_Guard_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Friend_Guard_(ability) | Source} */
FRIEND_GUARD, FRIEND_GUARD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Weak_Armor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Weak_Armor_(ability) | Source} */
WEAK_ARMOR, WEAK_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Heavy_Metal_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Heavy_Metal_(ability) | Source} */
HEAVY_METAL, HEAVY_METAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Light_Metal_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Light_Metal_(ability) | Source} */
LIGHT_METAL, LIGHT_METAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Multiscale_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Multiscale_(ability) | Source} */
MULTISCALE, MULTISCALE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Boost_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Boost_(ability) | Source} */
TOXIC_BOOST, TOXIC_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flare_Boost_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Flare_Boost_(ability) | Source} */
FLARE_BOOST, FLARE_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Harvest_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Harvest_(ability) | Source} */
HARVEST, HARVEST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Telepathy_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Telepathy_(ability) | Source} */
TELEPATHY, TELEPATHY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Moody_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Moody_(ability) | Source} */
MOODY, MOODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Overcoat_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Overcoat_(ability) | Source} */
OVERCOAT, OVERCOAT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Touch_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Poison_Touch_(ability) | Source} */
POISON_TOUCH, POISON_TOUCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Regenerator_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Regenerator_(ability) | Source} */
REGENERATOR, REGENERATOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Big_Pecks_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Big_Pecks_(ability) | Source} */
BIG_PECKS, BIG_PECKS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Rush_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sand_Rush_(ability) | Source} */
SAND_RUSH, SAND_RUSH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wonder_Skin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Wonder_Skin_(ability) | Source} */
WONDER_SKIN, WONDER_SKIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Analytic_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Analytic_(ability) | Source} */
ANALYTIC, ANALYTIC,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Illusion_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Illusion_(ability) | Source} */
ILLUSION, ILLUSION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Imposter_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Imposter_(ability) | Source} */
IMPOSTER, IMPOSTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Infiltrator_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Infiltrator_(ability) | Source} */
INFILTRATOR, INFILTRATOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mummy_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Mummy_(ability) | Source} */
MUMMY, MUMMY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Moxie_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Moxie_(ability) | Source} */
MOXIE, MOXIE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Justified_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Justified_(ability) | Source} */
JUSTIFIED, JUSTIFIED,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rattled_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rattled_(ability) | Source} */
RATTLED, RATTLED,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magic_Bounce_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Magic_Bounce_(ability) | Source} */
MAGIC_BOUNCE, MAGIC_BOUNCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sap_Sipper_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sap_Sipper_(ability) | Source} */
SAP_SIPPER, SAP_SIPPER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Prankster_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Prankster_(ability) | Source} */
PRANKSTER, PRANKSTER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Force_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sand_Force_(ability) | Source} */
SAND_FORCE, SAND_FORCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Iron_Barbs_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Iron_Barbs_(ability) | Source} */
IRON_BARBS, IRON_BARBS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Zen_Mode_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Zen_Mode_(ability) | Source} */
ZEN_MODE, ZEN_MODE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Victory_Star_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Victory_Star_(ability) | Source} */
VICTORY_STAR, VICTORY_STAR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Turboblaze_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Turboblaze_(ability) | Source} */
TURBOBLAZE, TURBOBLAZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Teravolt_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Teravolt_(ability) | Source} */
TERAVOLT, TERAVOLT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aroma_Veil_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Aroma_Veil_(ability) | Source} */
AROMA_VEIL, AROMA_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Flower_Veil_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Flower_Veil_(ability) | Source} */
FLOWER_VEIL, FLOWER_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cheek_Pouch_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Cheek_Pouch_(ability) | Source} */
CHEEK_POUCH, CHEEK_POUCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Protean_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Protean_(ability) | Source} */
PROTEAN, PROTEAN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Fur_Coat_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Fur_Coat_(ability) | Source} */
FUR_COAT, FUR_COAT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Magician_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Magician_(ability) | Source} */
MAGICIAN, MAGICIAN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Bulletproof_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Bulletproof_(ability) | Source} */
BULLETPROOF, BULLETPROOF,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Competitive_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Competitive_(ability) | Source} */
COMPETITIVE, COMPETITIVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Strong_Jaw_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Strong_Jaw_(ability) | Source} */
STRONG_JAW, STRONG_JAW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Refrigerate_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Refrigerate_(ability) | Source} */
REFRIGERATE, REFRIGERATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sweet_Veil_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sweet_Veil_(ability) | Source} */
SWEET_VEIL, SWEET_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stance_Change_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Stance_Change_(ability) | Source} */
STANCE_CHANGE, STANCE_CHANGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gale_Wings_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Gale_Wings_(ability) | Source} */
GALE_WINGS, GALE_WINGS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mega_Launcher_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Mega_Launcher_(ability) | Source} */
MEGA_LAUNCHER, MEGA_LAUNCHER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pelt_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pelt_(ability) | Source} */
GRASS_PELT, GRASS_PELT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Symbiosis_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Symbiosis_(ability) | Source} */
SYMBIOSIS, SYMBIOSIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tough_Claws_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tough_Claws_(ability) | Source} */
TOUGH_CLAWS, TOUGH_CLAWS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pixilate_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Pixilate_(ability) | Source} */
PIXILATE, PIXILATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gooey_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Gooey_(ability) | Source} */
GOOEY, GOOEY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aerilate_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Aerilate_(ability) | Source} */
AERILATE, AERILATE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Parental_Bond_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Parental_Bond_(ability) | Source} */
PARENTAL_BOND, PARENTAL_BOND,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dark_Aura_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Dark_Aura_(ability) | Source} */
DARK_AURA, DARK_AURA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Fairy_Aura_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Fairy_Aura_(ability) | Source} */
FAIRY_AURA, FAIRY_AURA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Aura_Break_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Aura_Break_(ability) | Source} */
AURA_BREAK, AURA_BREAK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Primordial_Sea_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Primordial_Sea_(ability) | Source} */
PRIMORDIAL_SEA, PRIMORDIAL_SEA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Desolate_Land_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Desolate_Land_(ability) | Source} */
DESOLATE_LAND, DESOLATE_LAND,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Delta_Stream_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Delta_Stream_(ability) | Source} */
DELTA_STREAM, DELTA_STREAM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stamina_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Stamina_(ability) | Source} */
STAMINA, STAMINA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wimp_Out_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Wimp_Out_(ability) | Source} */
WIMP_OUT, WIMP_OUT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Emergency_Exit_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Emergency_Exit_(ability) | Source} */
EMERGENCY_EXIT, EMERGENCY_EXIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Compaction_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Water_Compaction_(ability) | Source} */
WATER_COMPACTION, WATER_COMPACTION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Merciless_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Merciless_(ability) | Source} */
MERCILESS, MERCILESS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shields_Down_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Shields_Down_(ability) | Source} */
SHIELDS_DOWN, SHIELDS_DOWN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stakeout_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Stakeout_(ability) | Source} */
STAKEOUT, STAKEOUT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Water_Bubble_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Water_Bubble_(ability) | Source} */
WATER_BUBBLE, WATER_BUBBLE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steelworker_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Steelworker_(ability) | Source} */
STEELWORKER, STEELWORKER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Berserk_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Berserk_(ability) | Source} */
BERSERK, BERSERK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Slush_Rush_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Slush_Rush_(ability) | Source} */
SLUSH_RUSH, SLUSH_RUSH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Long_Reach_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Long_Reach_(ability) | Source} */
LONG_REACH, LONG_REACH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Liquid_Voice_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Liquid_Voice_(ability) | Source} */
LIQUID_VOICE, LIQUID_VOICE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Triage_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Triage_(ability) | Source} */
TRIAGE, TRIAGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Galvanize_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Galvanize_(ability) | Source} */
GALVANIZE, GALVANIZE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Surge_Surfer_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Surge_Surfer_(ability) | Source} */
SURGE_SURFER, SURGE_SURFER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Schooling_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Schooling_(ability) | Source} */
SCHOOLING, SCHOOLING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Disguise_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Disguise_(ability) | Source} */
DISGUISE, DISGUISE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Battle_Bond_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Battle_Bond_(ability) | Source} */
BATTLE_BOND, BATTLE_BOND,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Power_Construct_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Power_Construct_(ability) | Source} */
POWER_CONSTRUCT, POWER_CONSTRUCT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Corrosion_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Corrosion_(ability) | Source} */
CORROSION, CORROSION,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Comatose_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Comatose_(ability) | Source} */
COMATOSE, COMATOSE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Queenly_Majesty_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Queenly_Majesty_(ability) | Source} */
QUEENLY_MAJESTY, QUEENLY_MAJESTY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Innards_Out_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Innards_Out_(ability) | Source} */
INNARDS_OUT, INNARDS_OUT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dancer_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Dancer_(ability) | Source} */
DANCER, DANCER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Battery_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Battery_(ability) | Source} */
BATTERY, BATTERY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Fluffy_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Fluffy_(ability) | Source} */
FLUFFY, FLUFFY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dazzling_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Dazzling_(ability) | Source} */
DAZZLING, DAZZLING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Soul_Heart_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Soul_Heart_(ability) | Source} */
SOUL_HEART, SOUL_HEART,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tangling_Hair_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tangling_Hair_(ability) | Source} */
TANGLING_HAIR, TANGLING_HAIR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Receiver_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Receiver_(ability) | Source} */
RECEIVER, RECEIVER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Power_Of_Alchemy_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Power_Of_Alchemy_(ability) | Source} */
POWER_OF_ALCHEMY, POWER_OF_ALCHEMY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Beast_Boost_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Beast_Boost_(ability) | Source} */
BEAST_BOOST, BEAST_BOOST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rks_System_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rks_System_(ability) | Source} */
RKS_SYSTEM, RKS_SYSTEM,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Electric_Surge_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Electric_Surge_(ability) | Source} */
ELECTRIC_SURGE, ELECTRIC_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Psychic_Surge_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Psychic_Surge_(ability) | Source} */
PSYCHIC_SURGE, PSYCHIC_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Misty_Surge_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Misty_Surge_(ability) | Source} */
MISTY_SURGE, MISTY_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Grassy_Surge_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Grassy_Surge_(ability) | Source} */
GRASSY_SURGE, GRASSY_SURGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Full_Metal_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Full_Metal_Body_(ability) | Source} */
FULL_METAL_BODY, FULL_METAL_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Shadow_Shield_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Shadow_Shield_(ability) | Source} */
SHADOW_SHIELD, SHADOW_SHIELD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Prism_Armor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Prism_Armor_(ability) | Source} */
PRISM_ARMOR, PRISM_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Neuroforce_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Neuroforce_(ability) | Source} */
NEUROFORCE, NEUROFORCE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Intrepid_Sword_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Intrepid_Sword_(ability) | Source} */
INTREPID_SWORD, INTREPID_SWORD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dauntless_Shield_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Dauntless_Shield_(ability) | Source} */
DAUNTLESS_SHIELD, DAUNTLESS_SHIELD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Libero_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Libero_(ability) | Source} */
LIBERO, LIBERO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ball_Fetch_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Ball_Fetch_(ability) | Source} */
BALL_FETCH, BALL_FETCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cotton_Down_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Cotton_Down_(ability) | Source} */
COTTON_DOWN, COTTON_DOWN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Propeller_Tail_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Propeller_Tail_(ability) | Source} */
PROPELLER_TAIL, PROPELLER_TAIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mirror_Armor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Mirror_Armor_(ability) | Source} */
MIRROR_ARMOR, MIRROR_ARMOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gulp_Missile_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Gulp_Missile_(ability) | Source} */
GULP_MISSILE, GULP_MISSILE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Stalwart_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Stalwart_(ability) | Source} */
STALWART, STALWART,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steam_Engine_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Steam_Engine_(ability) | Source} */
STEAM_ENGINE, STEAM_ENGINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Punk_Rock_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Punk_Rock_(ability) | Source} */
PUNK_ROCK, PUNK_ROCK,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sand_Spit_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sand_Spit_(ability) | Source} */
SAND_SPIT, SAND_SPIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ice_Scales_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Ice_Scales_(ability) | Source} */
ICE_SCALES, ICE_SCALES,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ripen_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Ripen_(ability) | Source} */
RIPEN, RIPEN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Ice_Face_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Ice_Face_(ability) | Source} */
ICE_FACE, ICE_FACE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Power_Spot_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Power_Spot_(ability) | Source} */
POWER_SPOT, POWER_SPOT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mimicry_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Mimicry_(ability) | Source} */
MIMICRY, MIMICRY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Screen_Cleaner_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Screen_Cleaner_(ability) | Source} */
SCREEN_CLEANER, SCREEN_CLEANER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Steely_Spirit_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Steely_Spirit_(ability) | Source} */
STEELY_SPIRIT, STEELY_SPIRIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Perish_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Perish_Body_(ability) | Source} */
PERISH_BODY, PERISH_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wandering_Spirit_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Wandering_Spirit_(ability) | Source} */
WANDERING_SPIRIT, WANDERING_SPIRIT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Gorilla_Tactics_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Gorilla_Tactics_(ability) | Source} */
GORILLA_TACTICS, GORILLA_TACTICS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Neutralizing_Gas_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Neutralizing_Gas_(ability) | Source} */
NEUTRALIZING_GAS, NEUTRALIZING_GAS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Pastel_Veil_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Pastel_Veil_(ability) | Source} */
PASTEL_VEIL, PASTEL_VEIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hunger_Switch_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Hunger_Switch_(ability) | Source} */
HUNGER_SWITCH, HUNGER_SWITCH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Quick_Draw_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Quick_Draw_(ability) | Source} */
QUICK_DRAW, QUICK_DRAW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Unseen_Fist_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Unseen_Fist_(ability) | Source} */
UNSEEN_FIST, UNSEEN_FIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Curious_Medicine_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Curious_Medicine_(ability) | Source} */
CURIOUS_MEDICINE, CURIOUS_MEDICINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Transistor_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Transistor_(ability) | Source} */
TRANSISTOR, TRANSISTOR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Dragons_Maw_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Dragons_Maw_(ability) | Source} */
DRAGONS_MAW, DRAGONS_MAW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Chilling_Neigh_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Chilling_Neigh_(ability) | Source} */
CHILLING_NEIGH, CHILLING_NEIGH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Grim_Neigh_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Grim_Neigh_(ability) | Source} */
GRIM_NEIGH, GRIM_NEIGH,
/**{@link https://bulbapedia.bulbagarden.net/wiki/As_One_Glastrier_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/As_One_Glastrier_(ability) | Source} */
AS_ONE_GLASTRIER, AS_ONE_GLASTRIER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/As_One_Spectrier_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/As_One_Spectrier_(ability) | Source} */
AS_ONE_SPECTRIER, AS_ONE_SPECTRIER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Lingering_Aroma_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Lingering_Aroma_(ability) | Source} */
LINGERING_AROMA, LINGERING_AROMA,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Seed_Sower_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Seed_Sower_(ability) | Source} */
SEED_SOWER, SEED_SOWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Thermal_Exchange_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Thermal_Exchange_(ability) | Source} */
THERMAL_EXCHANGE, THERMAL_EXCHANGE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Anger_Shell_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Anger_Shell_(ability) | Source} */
ANGER_SHELL, ANGER_SHELL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Purifying_Salt_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Purifying_Salt_(ability) | Source} */
PURIFYING_SALT, PURIFYING_SALT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Well_Baked_Body_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Well_Baked_Body_(ability) | Source} */
WELL_BAKED_BODY, WELL_BAKED_BODY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wind_Rider_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Wind_Rider_(ability) | Source} */
WIND_RIDER, WIND_RIDER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Guard_Dog_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Guard_Dog_(ability) | Source} */
GUARD_DOG, GUARD_DOG,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Rocky_Payload_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Rocky_Payload_(ability) | Source} */
ROCKY_PAYLOAD, ROCKY_PAYLOAD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Wind_Power_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Wind_Power_(ability) | Source} */
WIND_POWER, WIND_POWER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Zero_To_Hero_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Zero_To_Hero_(ability) | Source} */
ZERO_TO_HERO, ZERO_TO_HERO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Commander_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Commander_(ability) | Source} */
COMMANDER, COMMANDER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Electromorphosis_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Electromorphosis_(ability) | Source} */
ELECTROMORPHOSIS, ELECTROMORPHOSIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Protosynthesis_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Protosynthesis_(ability) | Source} */
PROTOSYNTHESIS, PROTOSYNTHESIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Quark_Drive_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Quark_Drive_(ability) | Source} */
QUARK_DRIVE, QUARK_DRIVE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Good_As_Gold_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Good_As_Gold_(ability) | Source} */
GOOD_AS_GOLD, GOOD_AS_GOLD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Vessel_Of_Ruin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Vessel_Of_Ruin_(ability) | Source} */
VESSEL_OF_RUIN, VESSEL_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sword_Of_Ruin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sword_Of_Ruin_(ability) | Source} */
SWORD_OF_RUIN, SWORD_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tablets_Of_Ruin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tablets_Of_Ruin_(ability) | Source} */
TABLETS_OF_RUIN, TABLETS_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Beads_Of_Ruin_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Beads_Of_Ruin_(ability) | Source} */
BEADS_OF_RUIN, BEADS_OF_RUIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Orichalcum_Pulse_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Orichalcum_Pulse_(ability) | Source} */
ORICHALCUM_PULSE, ORICHALCUM_PULSE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hadron_Engine_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Hadron_Engine_(ability) | Source} */
HADRON_ENGINE, HADRON_ENGINE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Opportunist_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Opportunist_(ability) | Source} */
OPPORTUNIST, OPPORTUNIST,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Cud_Chew_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Cud_Chew_(ability) | Source} */
CUD_CHEW, CUD_CHEW,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Sharpness_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Sharpness_(ability) | Source} */
SHARPNESS, SHARPNESS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Supreme_Overlord_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Supreme_Overlord_(ability) | Source} */
SUPREME_OVERLORD, SUPREME_OVERLORD,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Costar_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Costar_(ability) | Source} */
COSTAR, COSTAR,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Debris_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Debris_(ability) | Source} */
TOXIC_DEBRIS, TOXIC_DEBRIS,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Armor_Tail_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Armor_Tail_(ability) | Source} */
ARMOR_TAIL, ARMOR_TAIL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Earth_Eater_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Earth_Eater_(ability) | Source} */
EARTH_EATER, EARTH_EATER,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Mycelium_Might_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Mycelium_Might_(ability) | Source} */
MYCELIUM_MIGHT, MYCELIUM_MIGHT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Minds_Eye_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Minds_Eye_(ability) | Source} */
MINDS_EYE, MINDS_EYE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Supersweet_Syrup_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Supersweet_Syrup_(ability) | Source} */
SUPERSWEET_SYRUP, SUPERSWEET_SYRUP,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Hospitality_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Hospitality_(ability) | Source} */
HOSPITALITY, HOSPITALITY,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Chain_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Chain_(ability) | Source} */
TOXIC_CHAIN, TOXIC_CHAIN,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Teal_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Teal_(ability) | Source} */
EMBODY_ASPECT_TEAL, EMBODY_ASPECT_TEAL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Wellspring_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Wellspring_(ability) | Source} */
EMBODY_ASPECT_WELLSPRING, EMBODY_ASPECT_WELLSPRING,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Hearthflame_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Hearthflame_(ability) | Source} */
EMBODY_ASPECT_HEARTHFLAME, EMBODY_ASPECT_HEARTHFLAME,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Cornerstone_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Embody_Aspect_Cornerstone_(ability) | Source} */
EMBODY_ASPECT_CORNERSTONE, EMBODY_ASPECT_CORNERSTONE,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shift_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shift_(ability) | Source} */
TERA_SHIFT, TERA_SHIFT,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shell_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Tera_Shell_(ability) | Source} */
TERA_SHELL, TERA_SHELL,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Teraform_Zero_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Teraform_Zero_(ability) | Source} */
TERAFORM_ZERO, TERAFORM_ZERO,
/**{@link https://bulbapedia.bulbagarden.net/wiki/Poison_Puppeteer_(ability) | Source} */ /** {@link https://bulbapedia.bulbagarden.net/wiki/Poison_Puppeteer_(ability) | Source} */
POISON_PUPPETEER, POISON_PUPPETEER,
} }

View File

@ -65,5 +65,45 @@ export enum ChallengeType {
/** /**
* Modifies what the pokemon stats for Flip Stat Mode. * Modifies what the pokemon stats for Flip Stat Mode.
*/ */
FLIP_STAT FLIP_STAT,
/**
* Challenges which conditionally enable or disable automatic party healing during biome transitions
* @see {@linkcode Challenge.applyPartyHealAvailability}
*/
PARTY_HEAL,
/**
* Challenges which conditionally enable or disable the shop
* @see {@linkcode Challenge.applyShopAvailability}
*/
SHOP,
/**
* Challenges which validate whether a pokemon can be added to the player's party or not
* @see {@linkcode Challenge.applyCatchAvailability}
*/
POKEMON_ADD_TO_PARTY,
/**
* Challenges which validate whether a pokemon is allowed to fuse or not
* @see {@linkcode Challenge.applyFusionAvailability}
*/
POKEMON_FUSION,
/**
* Challenges which validate whether particular moves can or cannot be used
* @see {@linkcode Challenge.applyMoveAvailability}
*/
POKEMON_MOVE,
/**
* Challenges which validate whether particular items are or are not sold in the shop
* @see {@linkcode Challenge.applyShopItems}
*/
SHOP_ITEM,
/**
* Challenges which validate whether particular items will be given as a reward after a wave
* @see {@linkcode Challenge.applyWaveRewards}
*/
WAVE_REWARD,
/**
* Challenges which prevent recovery from fainting
* @see {@linkcode Challenge.applyPermanentFaint}
*/
PREVENT_REVIVE,
} }

View File

@ -6,4 +6,7 @@ export enum Challenges {
FRESH_START, FRESH_START,
INVERSE_BATTLE, INVERSE_BATTLE,
FLIP_STAT, FLIP_STAT,
LIMITED_CATCH,
LIMITED_SUPPORT,
HARDCORE,
} }

View File

@ -537,6 +537,7 @@ export class Arena {
case BiomeId.ABYSS: case BiomeId.ABYSS:
case BiomeId.SPACE: case BiomeId.SPACE:
case BiomeId.TEMPLE: case BiomeId.TEMPLE:
case BiomeId.LABORATORY:
return 16; return 16;
default: default:
return 0; return 0;

View File

@ -30,7 +30,7 @@ export class DamageNumberHandler {
const baseScale = target.getSpriteScale() / 6; const baseScale = target.getSpriteScale() / 6;
const damageNumber = addTextObject( const damageNumber = addTextObject(
target.x, target.x,
-(globalScene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, -globalScene.scaledCanvas.height + target.y - target.getSprite().height / 2,
formatStat(amount, true), formatStat(amount, true),
TextStyle.SUMMARY, TextStyle.SUMMARY,
); );

View File

@ -39,7 +39,6 @@ import {
TrappedTag, TrappedTag,
TypeImmuneTag, TypeImmuneTag,
} from "#data/battler-tags"; } from "#data/battler-tags";
import { applyChallenges } from "#data/challenge";
import { allAbilities, allMoves } from "#data/data-lists"; import { allAbilities, allMoves } from "#data/data-lists";
import { getLevelTotalExp } from "#data/exp"; import { getLevelTotalExp } from "#data/exp";
import { import {
@ -134,6 +133,7 @@ import { EnemyBattleInfo } from "#ui/enemy-battle-info";
import type { PartyOption } from "#ui/party-ui-handler"; import type { PartyOption } from "#ui/party-ui-handler";
import { PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler"; import { PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler";
import { PlayerBattleInfo } from "#ui/player-battle-info"; import { PlayerBattleInfo } from "#ui/player-battle-info";
import { applyChallenges } from "#utils/challenge-utils";
import { import {
BooleanHolder, BooleanHolder,
type Constructor, type Constructor,
@ -4033,7 +4033,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
* @param damage integer * @param damage integer
* @param ignoreSegments boolean, not currently used * @param ignoreSegments boolean, not currently used
* @param preventEndure used to update damage if endure or sturdy * @param preventEndure used to update damage if endure or sturdy
* @param ignoreFaintPhas flag on whether to add FaintPhase if pokemon after applying damage faints * @param ignoreFaintPhase flag on whether to add FaintPhase if pokemon after applying damage faints
* @returns integer representing damage dealt * @returns integer representing damage dealt
*/ */
damage(damage: number, _ignoreSegments = false, preventEndure = false, ignoreFaintPhase = false): number { damage(damage: number, _ignoreSegments = false, preventEndure = false, ignoreFaintPhase = false): number {
@ -4546,8 +4546,17 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
} }
const key = this.species.getCryKey(this.formIndex); const key = this.species.getCryKey(this.formIndex);
let rate = 0.85; const crySoundConfig = { rate: 0.85, detune: 0 };
const cry = globalScene.playSound(key, { rate: rate }) as AnySound; if (this.isPlayer()) {
// If fainting is permanent, emphasize impact
const preventRevive = new BooleanHolder(false);
applyChallenges(ChallengeType.PREVENT_REVIVE, preventRevive);
if (preventRevive.value) {
crySoundConfig.detune = -100;
crySoundConfig.rate = 0.7;
}
}
const cry = globalScene.playSound(key, crySoundConfig) as AnySound;
if (!cry || globalScene.fieldVolume === 0) { if (!cry || globalScene.fieldVolume === 0) {
callback(); callback();
return; return;
@ -4566,7 +4575,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
delay: fixedInt(delay), delay: fixedInt(delay),
repeat: -1, repeat: -1,
callback: () => { callback: () => {
frameThreshold = sprite.anims.msPerFrame / rate; frameThreshold = sprite.anims.msPerFrame / crySoundConfig.rate;
frameProgress += delay; frameProgress += delay;
while (frameProgress > frameThreshold) { while (frameProgress > frameThreshold) {
if (sprite.anims.duration) { if (sprite.anims.duration) {
@ -4576,8 +4585,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
frameProgress -= frameThreshold; frameProgress -= frameThreshold;
} }
if (cry && !cry.pendingRemove) { if (cry && !cry.pendingRemove) {
rate *= 0.99; cry.setRate(crySoundConfig.rate * 0.99);
cry.setRate(rate);
} else { } else {
faintCryTimer?.destroy(); faintCryTimer?.destroy();
faintCryTimer = null; faintCryTimer = null;
@ -5186,38 +5194,38 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} }
updateFusionPalette(ignoreOveride?: boolean): void { updateFusionPalette(ignoreOverride?: boolean): void {
if (!this.getFusionSpeciesForm(ignoreOveride)) { if (!this.getFusionSpeciesForm(ignoreOverride)) {
[this.getSprite(), this.getTintSprite()] [this.getSprite(), this.getTintSprite()]
.filter(s => !!s) .filter(s => !!s)
.map(s => { .map(s => {
s.pipelineData[`spriteColors${ignoreOveride && this.summonData.speciesForm ? "Base" : ""}`] = []; s.pipelineData[`spriteColors${ignoreOverride && this.summonData.speciesForm ? "Base" : ""}`] = [];
s.pipelineData[`fusionSpriteColors${ignoreOveride && this.summonData.speciesForm ? "Base" : ""}`] = []; s.pipelineData[`fusionSpriteColors${ignoreOverride && this.summonData.speciesForm ? "Base" : ""}`] = [];
}); });
return; return;
} }
const speciesForm = this.getSpeciesForm(ignoreOveride); const speciesForm = this.getSpeciesForm(ignoreOverride);
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOveride); const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
const spriteKey = speciesForm.getSpriteKey( const spriteKey = speciesForm.getSpriteKey(
this.getGender(ignoreOveride) === Gender.FEMALE, this.getGender(ignoreOverride) === Gender.FEMALE,
speciesForm.formIndex, speciesForm.formIndex,
this.shiny, this.shiny,
this.variant, this.variant,
); );
const backSpriteKey = speciesForm const backSpriteKey = speciesForm
.getSpriteKey(this.getGender(ignoreOveride) === Gender.FEMALE, speciesForm.formIndex, this.shiny, this.variant) .getSpriteKey(this.getGender(ignoreOverride) === Gender.FEMALE, speciesForm.formIndex, this.shiny, this.variant)
.replace("pkmn__", "pkmn__back__"); .replace("pkmn__", "pkmn__back__");
const fusionSpriteKey = fusionSpeciesForm.getSpriteKey( const fusionSpriteKey = fusionSpeciesForm.getSpriteKey(
this.getFusionGender(ignoreOveride) === Gender.FEMALE, this.getFusionGender(ignoreOverride) === Gender.FEMALE,
fusionSpeciesForm.formIndex, fusionSpeciesForm.formIndex,
this.fusionShiny, this.fusionShiny,
this.fusionVariant, this.fusionVariant,
); );
const fusionBackSpriteKey = fusionSpeciesForm const fusionBackSpriteKey = fusionSpeciesForm
.getSpriteKey( .getSpriteKey(
this.getFusionGender(ignoreOveride) === Gender.FEMALE, this.getFusionGender(ignoreOverride) === Gender.FEMALE,
fusionSpeciesForm.formIndex, fusionSpeciesForm.formIndex,
this.fusionShiny, this.fusionShiny,
this.fusionVariant, this.fusionVariant,
@ -5502,8 +5510,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
[this.getSprite(), this.getTintSprite()] [this.getSprite(), this.getTintSprite()]
.filter(s => !!s) .filter(s => !!s)
.map(s => { .map(s => {
s.pipelineData[`spriteColors${ignoreOveride && this.summonData.speciesForm ? "Base" : ""}`] = spriteColors; s.pipelineData[`spriteColors${ignoreOverride && this.summonData.speciesForm ? "Base" : ""}`] = spriteColors;
s.pipelineData[`fusionSpriteColors${ignoreOveride && this.summonData.speciesForm ? "Base" : ""}`] = s.pipelineData[`fusionSpriteColors${ignoreOverride && this.summonData.speciesForm ? "Base" : ""}`] =
fusionSpriteColors; fusionSpriteColors;
}); });

View File

@ -2,8 +2,7 @@ import { FixedBattleConfig } from "#app/battle";
import { CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants"; import { CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import type { Challenge } from "#data/challenge"; import { allChallenges, type Challenge, copyChallenge } from "#data/challenge";
import { allChallenges, applyChallenges, copyChallenge } from "#data/challenge";
import { getDailyStartingBiome } from "#data/daily-run"; import { getDailyStartingBiome } from "#data/daily-run";
import { allSpecies } from "#data/data-lists"; import { allSpecies } from "#data/data-lists";
import type { PokemonSpecies } from "#data/pokemon-species"; import type { PokemonSpecies } from "#data/pokemon-species";
@ -14,7 +13,8 @@ import { GameModes } from "#enums/game-modes";
import { SpeciesId } from "#enums/species-id"; import { SpeciesId } from "#enums/species-id";
import type { Arena } from "#field/arena"; import type { Arena } from "#field/arena";
import { classicFixedBattles, type FixedBattleConfigs } from "#trainers/fixed-battle-configs"; import { classicFixedBattles, type FixedBattleConfigs } from "#trainers/fixed-battle-configs";
import { isNullOrUndefined, randSeedInt, randSeedItem } from "#utils/common"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, isNullOrUndefined, randSeedInt, randSeedItem } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
interface GameModeConfig { interface GameModeConfig {
@ -311,6 +311,16 @@ export class GameMode implements GameModeConfig {
return this.battleConfig[waveIndex]; return this.battleConfig[waveIndex];
} }
/**
* Check if the current game mode has the shop enabled or not
* @returns Whether the shop is available in the current mode
*/
public getShopStatus(): boolean {
const status = new BooleanHolder(!this.hasNoShop);
applyChallenges(ChallengeType.SHOP, status);
return status.value;
}
getClearScoreBonus(): number { getClearScoreBonus(): number {
switch (this.modeId) { switch (this.modeId) {
case GameModes.CLASSIC: case GameModes.CLASSIC:

View File

@ -29,6 +29,7 @@ export class LoadingScene extends SceneBase {
this.loadImage("loading_bg", "arenas"); this.loadImage("loading_bg", "arenas");
this.loadImage("logo", ""); this.loadImage("logo", "");
this.loadImage("logo_fake", "");
// Load menu images // Load menu images
this.loadAtlas("bg", "ui"); this.loadAtlas("bg", "ui");

View File

@ -11,7 +11,7 @@ export abstract class Phase {
/** /**
* The string name of the phase, used to identify the phase type for {@linkcode is} * The string name of the phase, used to identify the phase type for {@linkcode is}
* *
* @privateremarks * @privateRemarks
* *
* When implementing a phase, you must set the `phaseName` property to the name of the phase. * When implementing a phase, you must set the `phaseName` property to the name of the phase.
*/ */

View File

@ -12,6 +12,7 @@ import {
} from "#data/pokeball"; } from "#data/pokeball";
import { getStatusEffectCatchRateMultiplier } from "#data/status-effect"; import { getStatusEffectCatchRateMultiplier } from "#data/status-effect";
import { BattlerIndex } from "#enums/battler-index"; import { BattlerIndex } from "#enums/battler-index";
import { ChallengeType } from "#enums/challenge-type";
import type { PokeballType } from "#enums/pokeball"; import type { PokeballType } from "#enums/pokeball";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
@ -22,6 +23,8 @@ import { achvs } from "#system/achv";
import type { PartyOption } from "#ui/party-ui-handler"; import type { PartyOption } from "#ui/party-ui-handler";
import { PartyUiMode } from "#ui/party-ui-handler"; import { PartyUiMode } from "#ui/party-ui-handler";
import { SummaryUiMode } from "#ui/summary-ui-handler"; import { SummaryUiMode } from "#ui/summary-ui-handler";
import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
// TODO: Refactor and split up to allow for overriding capture chance // TODO: Refactor and split up to allow for overriding capture chance
@ -283,6 +286,13 @@ export class AttemptCapturePhase extends PokemonPhase {
} }
}; };
Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => { Promise.all([pokemon.hideInfo(), globalScene.gameData.setPokemonCaught(pokemon)]).then(() => {
const addStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.POKEMON_ADD_TO_PARTY, pokemon, addStatus);
if (!addStatus.value) {
removePokemon();
end();
return;
}
if (globalScene.getPlayerParty().length === PLAYER_PARTY_MAX_SIZE) { if (globalScene.getPlayerParty().length === PLAYER_PARTY_MAX_SIZE) {
const promptRelease = () => { const promptRelease = () => {
globalScene.ui.showText( globalScene.ui.showText(

View File

@ -9,6 +9,7 @@ import { ArenaTagType } from "#enums/arena-tag-type";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { BiomeId } from "#enums/biome-id"; import { BiomeId } from "#enums/biome-id";
import { ChallengeType } from "#enums/challenge-type";
import { Command } from "#enums/command"; import { Command } from "#enums/command";
import { FieldPosition } from "#enums/field-position"; import { FieldPosition } from "#enums/field-position";
import { MoveId } from "#enums/move-id"; import { MoveId } from "#enums/move-id";
@ -21,6 +22,8 @@ import type { MoveTargetSet } from "#moves/move";
import { getMoveTargets } from "#moves/move-utils"; import { getMoveTargets } from "#moves/move-utils";
import { FieldPhase } from "#phases/field-phase"; import { FieldPhase } from "#phases/field-phase";
import type { TurnMove } from "#types/turn-move"; import type { TurnMove } from "#types/turn-move";
import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
export class CommandPhase extends FieldPhase { export class CommandPhase extends FieldPhase {
@ -109,7 +112,7 @@ export class CommandPhase extends FieldPhase {
* Clear out all unusable moves in front of the currently acting pokemon's move queue. * Clear out all unusable moves in front of the currently acting pokemon's move queue.
*/ */
// TODO: Refactor move queue handling to ensure that this method is not necessary. // TODO: Refactor move queue handling to ensure that this method is not necessary.
private clearUnusuableMoves(): void { private clearUnusableMoves(): void {
const playerPokemon = this.getPokemon(); const playerPokemon = this.getPokemon();
const moveQueue = playerPokemon.getMoveQueue(); const moveQueue = playerPokemon.getMoveQueue();
if (moveQueue.length === 0) { if (moveQueue.length === 0) {
@ -140,7 +143,7 @@ export class CommandPhase extends FieldPhase {
* @returns Whether a queued move was successfully set to be executed. * @returns Whether a queued move was successfully set to be executed.
*/ */
private tryExecuteQueuedMove(): boolean { private tryExecuteQueuedMove(): boolean {
this.clearUnusuableMoves(); this.clearUnusableMoves();
const playerPokemon = globalScene.getPlayerField()[this.fieldIndex]; const playerPokemon = globalScene.getPlayerField()[this.fieldIndex];
const moveQueue = playerPokemon.getMoveQueue(); const moveQueue = playerPokemon.getMoveQueue();
@ -210,16 +213,27 @@ export class CommandPhase extends FieldPhase {
const move = user.getMoveset()[cursor]; const move = user.getMoveset()[cursor];
globalScene.ui.setMode(UiMode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
// Decides between a Disabled, Not Implemented, or No PP translation message // Set the translation key for why the move cannot be selected
const errorMessage = user.isMoveRestricted(move.moveId, user) let cannotSelectKey: string;
? user.getRestrictingTag(move.moveId, user)!.selectionDeniedText(user, move.moveId) const moveStatus = new BooleanHolder(true);
: move.getName().endsWith(" (N)") applyChallenges(ChallengeType.POKEMON_MOVE, move.moveId, moveStatus);
? "battle:moveNotImplemented" if (!moveStatus.value) {
: "battle:moveNoPP"; cannotSelectKey = "battle:moveCannotUseChallenge";
} else if (move.getPpRatio() === 0) {
cannotSelectKey = "battle:moveNoPP";
} else if (move.getName().endsWith(" (N)")) {
cannotSelectKey = "battle:moveNotImplemented";
} else if (user.isMoveRestricted(move.moveId, user)) {
cannotSelectKey = user.getRestrictingTag(move.moveId, user)!.selectionDeniedText(user, move.moveId);
} else {
// TODO: Consider a message that signals a being unusable for an unknown reason
cannotSelectKey = "";
}
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
globalScene.ui.showText( globalScene.ui.showText(
i18next.t(errorMessage, { moveName: moveName }), i18next.t(cannotSelectKey, { moveName: moveName }),
null, null,
() => { () => {
globalScene.ui.clearText(); globalScene.ui.clearText();

View File

@ -148,9 +148,9 @@ export class EggHatchPhase extends Phase {
this.eggHatchOverlay = globalScene.add.rectangle( this.eggHatchOverlay = globalScene.add.rectangle(
0, 0,
-globalScene.game.canvas.height / 6, -globalScene.scaledCanvas.height,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6, globalScene.scaledCanvas.height,
0xffffff, 0xffffff,
); );
this.eggHatchOverlay.setOrigin(0, 0); this.eggHatchOverlay.setOrigin(0, 0);

View File

@ -25,8 +25,8 @@ export class EndCardPhase extends Phase {
globalScene.field.add(this.endCard); globalScene.field.add(this.endCard);
this.text = addTextObject( this.text = addTextObject(
globalScene.game.canvas.width / 12, globalScene.scaledCanvas.width / 2,
globalScene.game.canvas.height / 6 - 16, globalScene.scaledCanvas.height - 16,
i18next.t("battle:congratulations"), i18next.t("battle:congratulations"),
TextStyle.SUMMARY, TextStyle.SUMMARY,
{ fontSize: "128px" }, { fontSize: "128px" },

View File

@ -90,16 +90,16 @@ export class EvolutionPhase extends Phase {
.setVisible(false); .setVisible(false);
this.evolutionBgOverlay = globalScene.add this.evolutionBgOverlay = globalScene.add
.rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6, 0x262626) .rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height, 0x262626)
.setOrigin(0) .setOrigin(0)
.setAlpha(0); .setAlpha(0);
this.evolutionContainer.add([this.evolutionBaseBg, this.evolutionBgOverlay, this.evolutionBg]); this.evolutionContainer.add([this.evolutionBaseBg, this.evolutionBgOverlay, this.evolutionBg]);
this.evolutionOverlay = globalScene.add.rectangle( this.evolutionOverlay = globalScene.add.rectangle(
0, 0,
-globalScene.game.canvas.height / 6, -globalScene.scaledCanvas.height,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6 - 48, globalScene.scaledCanvas.height - 48,
0xffffff, 0xffffff,
); );
this.evolutionOverlay.setOrigin(0).setAlpha(0); this.evolutionOverlay.setOrigin(0).setAlpha(0);

View File

@ -823,6 +823,7 @@ export class MoveEffectPhase extends PokemonPhase {
const substitute = target.getTag(SubstituteTag); const substitute = target.getTag(SubstituteTag);
const isBlockedBySubstitute = substitute && this.move.hitsSubstitute(user, target); const isBlockedBySubstitute = substitute && this.move.hitsSubstitute(user, target);
if (isBlockedBySubstitute) { if (isBlockedBySubstitute) {
user.turnData.totalDamageDealt += Math.min(dmg, substitute.hp);
substitute.hp -= dmg; substitute.hp -= dmg;
} else if (!target.isPlayer() && dmg >= target.hp) { } else if (!target.isPlayer() && dmg >= target.hp) {
globalScene.applyPlayerItems(TrainerItemEffect.ENEMY_ENDURE_CHANCE, { pokemon: target }); globalScene.applyPlayerItems(TrainerItemEffect.ENEMY_ENDURE_CHANCE, { pokemon: target });

View File

@ -1,6 +1,8 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { ChallengeType } from "#enums/challenge-type";
import { BattlePhase } from "#phases/battle-phase"; import { BattlePhase } from "#phases/battle-phase";
import { fixedInt } from "#utils/common"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, fixedInt } from "#utils/common";
export class PartyHealPhase extends BattlePhase { export class PartyHealPhase extends BattlePhase {
public readonly phaseName = "PartyHealPhase"; public readonly phaseName = "PartyHealPhase";
@ -20,7 +22,14 @@ export class PartyHealPhase extends BattlePhase {
globalScene.fadeOutBgm(1000, false); globalScene.fadeOutBgm(1000, false);
} }
globalScene.ui.fadeOut(1000).then(() => { globalScene.ui.fadeOut(1000).then(() => {
const preventRevive = new BooleanHolder(false);
applyChallenges(ChallengeType.PREVENT_REVIVE, preventRevive);
for (const pokemon of globalScene.getPlayerParty()) { for (const pokemon of globalScene.getPlayerParty()) {
// Prevent reviving fainted pokemon during certain challenges
if (pokemon.isFainted() && preventRevive.value) {
continue;
}
pokemon.hp = pokemon.getMaxHp(); pokemon.hp = pokemon.getMaxHp();
pokemon.resetStatus(true, false, false, true); pokemon.resetStatus(true, false, false, true);
for (const move of pokemon.moveset) { for (const move of pokemon.moveset) {

View File

@ -2,10 +2,12 @@ import { globalScene } from "#app/global-scene";
import { biomeLinks, getBiomeName } from "#balance/biomes"; import { biomeLinks, getBiomeName } from "#balance/biomes";
import { BiomeId } from "#enums/biome-id"; import { BiomeId } from "#enums/biome-id";
import { TrainerItemId } from "#enums/trainer-item-id"; import { TrainerItemId } from "#enums/trainer-item-id";
import { ChallengeType } from "#enums/challenge-type";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { BattlePhase } from "#phases/battle-phase"; import { BattlePhase } from "#phases/battle-phase";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { randSeedInt } from "#utils/common"; import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, randSeedInt } from "#utils/common";
export class SelectBiomePhase extends BattlePhase { export class SelectBiomePhase extends BattlePhase {
public readonly phaseName = "SelectBiomePhase"; public readonly phaseName = "SelectBiomePhase";
@ -19,7 +21,11 @@ export class SelectBiomePhase extends BattlePhase {
const setNextBiome = (nextBiome: BiomeId) => { const setNextBiome = (nextBiome: BiomeId) => {
if (nextWaveIndex % 10 === 1) { if (nextWaveIndex % 10 === 1) {
globalScene.phaseManager.unshiftNew("PartyHealPhase", false); const healStatus = new BooleanHolder(true);
applyChallenges(ChallengeType.PARTY_HEAL, healStatus);
if (healStatus.value) {
globalScene.phaseManager.unshiftNew("PartyHealPhase", false);
}
} }
globalScene.phaseManager.unshiftNew("SwitchBiomePhase", nextBiome); globalScene.phaseManager.unshiftNew("SwitchBiomePhase", nextBiome);
this.end(); this.end();

View File

@ -1,7 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { applyChallenges } from "#data/challenge";
import { SpeciesFormChangeMoveLearnedTrigger } from "#data/form-change-triggers"; import { SpeciesFormChangeMoveLearnedTrigger } from "#data/form-change-triggers";
import { Gender } from "#data/gender"; import { Gender } from "#data/gender";
import { ChallengeType } from "#enums/challenge-type"; import { ChallengeType } from "#enums/challenge-type";
@ -10,6 +9,7 @@ import { UiMode } from "#enums/ui-mode";
import { overrideHeldItems, overrideTrainerItems } from "#items/item-overrides"; import { overrideHeldItems, overrideTrainerItems } from "#items/item-overrides";
import { SaveSlotUiMode } from "#ui/save-slot-select-ui-handler"; import { SaveSlotUiMode } from "#ui/save-slot-select-ui-handler";
import type { Starter } from "#ui/starter-select-ui-handler"; import type { Starter } from "#ui/starter-select-ui-handler";
import { applyChallenges } from "#utils/challenge-utils";
import { isNullOrUndefined } from "#utils/common"; import { isNullOrUndefined } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils"; import { getPokemonSpecies } from "#utils/pokemon-utils";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";

View File

@ -14,7 +14,7 @@ import { getBiomeKey } from "#field/arena";
import { assignDailyRunStarterHeldItems } from "#items/held-item-pool"; import { assignDailyRunStarterHeldItems } from "#items/held-item-pool";
import type { SessionSaveData } from "#system/game-data"; import type { SessionSaveData } from "#system/game-data";
import { vouchers } from "#system/voucher"; import { vouchers } from "#system/voucher";
import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { SaveSlotUiMode } from "#ui/save-slot-select-ui-handler"; import { SaveSlotUiMode } from "#ui/save-slot-select-ui-handler";
import { isLocal, isLocalServerConnected, isNullOrUndefined } from "#utils/common"; import { isLocal, isLocalServerConnected, isNullOrUndefined } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -2,12 +2,15 @@ import { timedEventManager } from "#app/global-event-manager";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import type { BattlerIndex } from "#enums/battler-index"; import type { BattlerIndex } from "#enums/battler-index";
import { ChallengeType } from "#enums/challenge-type";
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
import { RewardId } from "#enums/reward-id"; import { RewardId } from "#enums/reward-id";
import { TrainerItemId } from "#enums/trainer-item-id"; import { TrainerItemId } from "#enums/trainer-item-id";
import type { CustomRewardSettings } from "#items/reward-pool-utils"; import type { CustomRewardSettings } from "#items/reward-pool-utils";
import { handleMysteryEncounterVictory } from "#mystery-encounters/encounter-phase-utils"; import { handleMysteryEncounterVictory } from "#mystery-encounters/encounter-phase-utils";
import { PokemonPhase } from "#phases/pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder } from "#utils/common";
export class VictoryPhase extends PokemonPhase { export class VictoryPhase extends PokemonPhase {
public readonly phaseName = "VictoryPhase"; public readonly phaseName = "VictoryPhase";
@ -64,7 +67,9 @@ export class VictoryPhase extends PokemonPhase {
break; break;
} }
} }
if (globalScene.currentBattle.waveIndex % 10) { const healStatus = new BooleanHolder(globalScene.currentBattle.waveIndex % 10 === 0);
applyChallenges(ChallengeType.PARTY_HEAL, healStatus);
if (!healStatus.value) {
globalScene.phaseManager.pushNew( globalScene.phaseManager.pushNew(
"SelectRewardPhase", "SelectRewardPhase",
undefined, undefined,

View File

@ -5,6 +5,7 @@ import {
FlipStatChallenge, FlipStatChallenge,
FreshStartChallenge, FreshStartChallenge,
InverseBattleChallenge, InverseBattleChallenge,
LimitedCatchChallenge,
SingleGenerationChallenge, SingleGenerationChallenge,
SingleTypeChallenge, SingleTypeChallenge,
} from "#data/challenge"; } from "#data/challenge";
@ -922,6 +923,19 @@ export const achvs = {
c.value > 0 && c.value > 0 &&
globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0), globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0),
).setSecret(), ).setSecret(),
// TODO: Decide on icon
NUZLOCKE: new ChallengeAchv(
"NUZLOCKE",
"",
"NUZLOCKE.description",
"leaf_stone",
100,
c =>
c instanceof LimitedCatchChallenge &&
c.value > 0 &&
globalScene.gameMode.challenges.some(c => c.id === Challenges.HARDCORE && c.value > 0) &&
globalScene.gameMode.challenges.some(c => c.id === Challenges.FRESH_START && c.value > 0),
),
BREEDERS_IN_SPACE: new Achv("BREEDERS_IN_SPACE", "", "BREEDERS_IN_SPACE.description", "moon_stone", 50).setSecret(), BREEDERS_IN_SPACE: new Achv("BREEDERS_IN_SPACE", "", "BREEDERS_IN_SPACE.description", "moon_stone", 50).setSecret(),
}; };

View File

@ -11,7 +11,6 @@ import { speciesEggMoves } from "#balance/egg-moves";
import { pokemonPrevolutions } from "#balance/pokemon-evolutions"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions";
import { speciesStarterCosts } from "#balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { ArenaTrapTag } from "#data/arena-tag"; import { ArenaTrapTag } from "#data/arena-tag";
import { applyChallenges } from "#data/challenge";
import { allMoves, allSpecies } from "#data/data-lists"; import { allMoves, allSpecies } from "#data/data-lists";
import type { Egg } from "#data/egg"; import type { Egg } from "#data/egg";
import { pokemonFormChanges } from "#data/pokemon-forms"; import { pokemonFormChanges } from "#data/pokemon-forms";
@ -60,6 +59,7 @@ import { VoucherType, vouchers } from "#system/voucher";
import { trainerConfigs } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config";
import type { DexData, DexEntry } from "#types/dex-data"; import type { DexData, DexEntry } from "#types/dex-data";
import { RUN_HISTORY_LIMIT } from "#ui/run-history-ui-handler"; import { RUN_HISTORY_LIMIT } from "#ui/run-history-ui-handler";
import { applyChallenges } from "#utils/challenge-utils";
import { executeIf, fixedInt, isLocal, NumberHolder, randInt, randSeedItem } from "#utils/common"; import { executeIf, fixedInt, isLocal, NumberHolder, randInt, randSeedItem } from "#utils/common";
import { decrypt, encrypt } from "#utils/data"; import { decrypt, encrypt } from "#utils/data";
import { getEnumKeys } from "#utils/enums"; import { getEnumKeys } from "#utils/enums";

View File

@ -144,7 +144,7 @@ export function setSettingGamepad(setting: SettingGamepad, value: number): boole
handler: () => changeGamepadHandler(g), handler: () => changeGamepadHandler(g),
})), })),
{ {
label: i18next.t("settings:cancelContollerChoice"), label: i18next.t("settings:cancelControllerChoice"),
handler: cancelHandler, handler: cancelHandler,
}, },
], ],

View File

@ -406,6 +406,16 @@ export class TimedEventManager {
return timedEvents.some((te: TimedEvent) => this.isActive(te)); return timedEvents.some((te: TimedEvent) => this.isActive(te));
} }
/**
* Check whether the current event is active and for April Fools.
* @returns Whether the April Fools event is currently active.
*/
isAprilFoolsActive(): boolean {
return timedEvents.some(
te => this.isActive(te) && te.hasOwnProperty("bannerKey") && te.bannerKey!.startsWith("aprf"),
);
}
activeEventHasBanner(): boolean { activeEventHasBanner(): boolean {
const activeEvents = timedEvents.filter(te => this.isActive(te) && te.hasOwnProperty("bannerKey")); const activeEvents = timedEvents.filter(te => this.isActive(te) && te.hasOwnProperty("bannerKey"));
return activeEvents.length > 0; return activeEvents.length > 0;
@ -662,7 +672,7 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
console.log(this.event.bannerKey); console.log(this.event.bannerKey);
const padding = 5; const padding = 5;
const showTimer = this.event.eventType !== EventType.NO_TIMER_DISPLAY; const showTimer = this.event.eventType !== EventType.NO_TIMER_DISPLAY;
const yPosition = globalScene.game.canvas.height / 6 - padding - (showTimer ? 10 : 0) - (this.event.yOffset ?? 0); const yPosition = globalScene.scaledCanvas.height - padding - (showTimer ? 10 : 0) - (this.event.yOffset ?? 0);
this.banner = new Phaser.GameObjects.Image(globalScene, this.availableWidth / 2, yPosition - padding, key); this.banner = new Phaser.GameObjects.Image(globalScene, this.availableWidth / 2, yPosition - padding, key);
this.banner.setName("img-event-banner"); this.banner.setName("img-event-banner");
this.banner.setOrigin(0.5, 1); this.banner.setOrigin(0.5, 1);

View File

@ -66,7 +66,7 @@ export abstract class AbstractOptionSelectUiHandler extends UiHandler {
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
this.optionSelectContainer = globalScene.add.container(globalScene.game.canvas.width / 6 - 1, -48); this.optionSelectContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, -48);
this.optionSelectContainer.setName(`option-select-${this.mode ? UiMode[this.mode] : "UNKNOWN"}`); this.optionSelectContainer.setName(`option-select-${this.mode ? UiMode[this.mode] : "UNKNOWN"}`);
this.optionSelectContainer.setVisible(false); this.optionSelectContainer.setVisible(false);
ui.add(this.optionSelectContainer); ui.add(this.optionSelectContainer);
@ -135,7 +135,7 @@ export abstract class AbstractOptionSelectUiHandler extends UiHandler {
this.optionSelectText.setName("text-option-select"); this.optionSelectText.setName("text-option-select");
this.optionSelectTextContainer.add(this.optionSelectText); this.optionSelectTextContainer.add(this.optionSelectText);
this.optionSelectContainer.setPosition( this.optionSelectContainer.setPosition(
globalScene.game.canvas.width / 6 - 1 - (this.config?.xOffset || 0), globalScene.scaledCanvas.width - 1 - (this.config?.xOffset || 0),
-48 + (this.config?.yOffset || 0), -48 + (this.config?.yOffset || 0),
); );
this.optionSelectBg.width = Math.max(this.optionSelectText.displayWidth + 24, this.getWindowWidth()); this.optionSelectBg.width = Math.max(this.optionSelectText.displayWidth + 24, this.getWindowWidth());

View File

@ -21,7 +21,7 @@ export class AchvBar extends Phaser.GameObjects.Container {
public shown: boolean; public shown: boolean;
constructor() { constructor() {
super(globalScene, globalScene.game.canvas.width / 6, 0); super(globalScene, globalScene.scaledCanvas.width, 0);
this.playerGender = globalScene.gameData.gender; this.playerGender = globalScene.gameData.gender;
} }
@ -118,7 +118,7 @@ export class AchvBar extends Phaser.GameObjects.Container {
globalScene.tweens.add({ globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6 - this.bg.width / 2, x: globalScene.scaledCanvas.width - this.bg.width / 2,
duration: 500, duration: 500,
ease: "Sine.easeOut", ease: "Sine.easeOut",
}); });
@ -136,7 +136,7 @@ export class AchvBar extends Phaser.GameObjects.Container {
globalScene.tweens.add({ globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6, x: globalScene.scaledCanvas.width,
duration: 500, duration: 500,
ease: "Sine.easeIn", ease: "Sine.easeIn",
onComplete: () => { onComplete: () => {

View File

@ -72,9 +72,9 @@ export class AchvsUiHandler extends MessageUiHandler {
const ui = this.getUi(); const ui = this.getUi();
/** Width of the global canvas / 6 */ /** Width of the global canvas / 6 */
const WIDTH = globalScene.game.canvas.width / 6; const WIDTH = globalScene.scaledCanvas.width;
/** Height of the global canvas / 6 */ /** Height of the global canvas / 6 */
const HEIGHT = globalScene.game.canvas.height / 6; const HEIGHT = globalScene.scaledCanvas.height;
this.mainContainer = globalScene.add.container(1, -HEIGHT + 1); this.mainContainer = globalScene.add.container(1, -HEIGHT + 1);

View File

@ -36,7 +36,7 @@ interface ArenaEffectInfo {
/** The enum string representation of the effect */ /** The enum string representation of the effect */
name: string; name: string;
/** {@linkcode ArenaEffectType} type of effect */ /** {@linkcode ArenaEffectType} type of effect */
effecType: ArenaEffectType; effectType: ArenaEffectType;
/** The maximum duration set by the effect */ /** The maximum duration set by the effect */
maxDuration: number; maxDuration: number;
@ -246,7 +246,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
// Creates a proxy object to decide which text object needs to be updated // Creates a proxy object to decide which text object needs to be updated
let textObject: Phaser.GameObjects.Text; let textObject: Phaser.GameObjects.Text;
switch (fieldEffectInfo.effecType) { switch (fieldEffectInfo.effectType) {
case ArenaEffectType.PLAYER: case ArenaEffectType.PLAYER:
textObject = this.flyoutTextPlayer; textObject = this.flyoutTextPlayer;
break; break;
@ -300,7 +300,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
const existingTrapTagIndex = isArenaTrapTag const existingTrapTagIndex = isArenaTrapTag
? this.fieldEffectInfo.findIndex( ? this.fieldEffectInfo.findIndex(
e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effecType, e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effectType,
) )
: -1; : -1;
let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]); let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]);
@ -318,7 +318,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
this.fieldEffectInfo.push({ this.fieldEffectInfo.push({
name, name,
effecType: arenaEffectType, effectType: arenaEffectType,
maxDuration: tagAddedEvent.duration, maxDuration: tagAddedEvent.duration,
duration: tagAddedEvent.duration, duration: tagAddedEvent.duration,
tagType: tagAddedEvent.arenaTagType, tagType: tagAddedEvent.arenaTagType,
@ -353,7 +353,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
? WeatherType[fieldEffectChangedEvent.newWeatherType] ? WeatherType[fieldEffectChangedEvent.newWeatherType]
: TerrainType[fieldEffectChangedEvent.newTerrainType], : TerrainType[fieldEffectChangedEvent.newTerrainType],
), ),
effecType: effectType:
fieldEffectChangedEvent instanceof WeatherChangedEvent ? ArenaEffectType.WEATHER : ArenaEffectType.TERRAIN, fieldEffectChangedEvent instanceof WeatherChangedEvent ? ArenaEffectType.WEATHER : ArenaEffectType.TERRAIN,
maxDuration: fieldEffectChangedEvent.duration, maxDuration: fieldEffectChangedEvent.duration,
duration: fieldEffectChangedEvent.duration, duration: fieldEffectChangedEvent.duration,

View File

@ -1,6 +1,6 @@
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import { AbstractOptionSelectUiHandler } from "#ui/abstact-option-select-ui-handler"; import { AbstractOptionSelectUiHandler } from "#ui/abstract-option-select-ui-handler";
export class AutoCompleteUiHandler extends AbstractOptionSelectUiHandler { export class AutoCompleteUiHandler extends AbstractOptionSelectUiHandler {
modalContainer: Phaser.GameObjects.Container; modalContainer: Phaser.GameObjects.Container;

View File

@ -37,7 +37,7 @@ export class BallUiHandler extends UiHandler {
const optionsText = addTextObject(0, 0, optionsTextContent, TextStyle.WINDOW, { align: "right", maxLines: 6 }); const optionsText = addTextObject(0, 0, optionsTextContent, TextStyle.WINDOW, { align: "right", maxLines: 6 });
const optionsTextWidth = optionsText.displayWidth; const optionsTextWidth = optionsText.displayWidth;
this.pokeballSelectContainer = globalScene.add.container( this.pokeballSelectContainer = globalScene.add.container(
globalScene.game.canvas.width / 6 - 51 - Math.max(64, optionsTextWidth), globalScene.scaledCanvas.width - 51 - Math.max(64, optionsTextWidth),
-49, -49,
); );
this.pokeballSelectContainer.setVisible(false); this.pokeballSelectContainer.setVisible(false);

View File

@ -16,7 +16,6 @@ interface BaseStatsOverlaySettings {
const HEIGHT = 120; const HEIGHT = 120;
const BORDER = 8; const BORDER = 8;
const GLOBAL_SCALE = 6;
const shortStats = ["HP", "ATK", "DEF", "SPATK", "SPDEF", "SPD"]; const shortStats = ["HP", "ATK", "DEF", "SPATK", "SPDEF", "SPD"];
export class BaseStatsOverlay extends Phaser.GameObjects.Container implements InfoToggle { export class BaseStatsOverlay extends Phaser.GameObjects.Container implements InfoToggle {
@ -109,7 +108,7 @@ export class BaseStatsOverlay extends Phaser.GameObjects.Container implements In
// width of this element // width of this element
static getWidth(_scale: number): number { static getWidth(_scale: number): number {
return globalScene.game.canvas.width / GLOBAL_SCALE / 2; return globalScene.scaledCanvas.width / 2;
} }
// height of this element // height of this element

View File

@ -39,7 +39,7 @@ export class PlayerBattleInfo extends BattleInfo {
statOverflow: 1, statOverflow: 1,
}, },
}; };
super(Math.floor(globalScene.game.canvas.width / 6) - 10, -72, true, posParams); super(Math.floor(globalScene.scaledCanvas.width) - 10, -72, true, posParams);
this.hpNumbersContainer = globalScene.add.container(-15, 10).setName("container_hp"); this.hpNumbersContainer = globalScene.add.container(-15, 10).setName("container_hp");
@ -198,11 +198,11 @@ export class PlayerBattleInfo extends BattleInfo {
this.lastLevelCapped = isLevelCapped; this.lastLevelCapped = isLevelCapped;
if (this.lastExp !== pokemon.exp || this.lastLevel !== pokemon.level) { if (this.lastExp !== pokemon.exp || this.lastLevel !== pokemon.level) {
const durationMultipler = Math.max( const durationMultiplier = Math.max(
Phaser.Tweens.Builders.GetEaseFunction("Cubic.easeIn")(1 - Math.min(pokemon.level - this.lastLevel, 10) / 10), Phaser.Tweens.Builders.GetEaseFunction("Cubic.easeIn")(1 - Math.min(pokemon.level - this.lastLevel, 10) / 10),
0.1, 0.1,
); );
await this.updatePokemonExp(pokemon, false, durationMultipler); await this.updatePokemonExp(pokemon, false, durationMultiplier);
} else if (isLevelCapped !== oldLevelCapped) { } else if (isLevelCapped !== oldLevelCapped) {
this.setLevel(pokemon.level); this.setLevel(pokemon.level);
} }

View File

@ -94,7 +94,7 @@ export class BattleMessageUiHandler extends MessageUiHandler {
this.levelUpStatsContainer = levelUpStatsContainer; this.levelUpStatsContainer = levelUpStatsContainer;
const levelUpStatsLabelsContent = addTextObject(globalScene.game.canvas.width / 6 - 73, -94, "", TextStyle.WINDOW, { const levelUpStatsLabelsContent = addTextObject(globalScene.scaledCanvas.width - 73, -94, "", TextStyle.WINDOW, {
maxLines: 6, maxLines: 6,
}); });
let levelUpStatsLabelText = ""; let levelUpStatsLabelText = "";
@ -106,7 +106,7 @@ export class BattleMessageUiHandler extends MessageUiHandler {
levelUpStatsLabelsContent.x -= levelUpStatsLabelsContent.displayWidth; levelUpStatsLabelsContent.x -= levelUpStatsLabelsContent.displayWidth;
const levelUpStatsBg = addWindow( const levelUpStatsBg = addWindow(
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
-100, -100,
80 + levelUpStatsLabelsContent.displayWidth, 80 + levelUpStatsLabelsContent.displayWidth,
100, 100,
@ -117,7 +117,7 @@ export class BattleMessageUiHandler extends MessageUiHandler {
levelUpStatsContainer.add(levelUpStatsLabelsContent); levelUpStatsContainer.add(levelUpStatsLabelsContent);
const levelUpStatsIncrContent = addTextObject( const levelUpStatsIncrContent = addTextObject(
globalScene.game.canvas.width / 6 - 50, globalScene.scaledCanvas.width - 50,
-94, -94,
"+\n+\n+\n+\n+\n+", "+\n+\n+\n+\n+\n+",
TextStyle.WINDOW, TextStyle.WINDOW,
@ -128,7 +128,7 @@ export class BattleMessageUiHandler extends MessageUiHandler {
this.levelUpStatsIncrContent = levelUpStatsIncrContent; this.levelUpStatsIncrContent = levelUpStatsIncrContent;
const levelUpStatsValuesContent = addBBCodeTextObject( const levelUpStatsValuesContent = addBBCodeTextObject(
globalScene.game.canvas.width / 6 - 7, globalScene.scaledCanvas.width - 7,
-94, -94,
"", "",
TextStyle.WINDOW, TextStyle.WINDOW,

View File

@ -19,7 +19,7 @@ export class CandyBar extends Phaser.GameObjects.Container {
public shown: boolean; public shown: boolean;
constructor() { constructor() {
super(globalScene, globalScene.game.canvas.width / 6, -(globalScene.game.canvas.height / 6) + 15); super(globalScene, globalScene.scaledCanvas.width, -globalScene.scaledCanvas.height + 15);
} }
setup(): void { setup(): void {
@ -80,7 +80,7 @@ export class CandyBar extends Phaser.GameObjects.Container {
this.tween = globalScene.tweens.add({ this.tween = globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6 - (this.bg.width - 5), x: globalScene.scaledCanvas.width - (this.bg.width - 5),
duration: 500, duration: 500,
ease: "Sine.easeOut", ease: "Sine.easeOut",
onComplete: () => { onComplete: () => {
@ -111,7 +111,7 @@ export class CandyBar extends Phaser.GameObjects.Container {
this.tween = globalScene.tweens.add({ this.tween = globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6, x: globalScene.scaledCanvas.width,
duration: 500, duration: 500,
ease: "Sine.easeIn", ease: "Sine.easeIn",
onComplete: () => { onComplete: () => {

View File

@ -58,11 +58,11 @@ export class GameChallengesUiHandler extends UiHandler {
this.widestTextBox = 0; this.widestTextBox = 0;
this.challengesContainer = globalScene.add.container(1, -(globalScene.game.canvas.height / 6) + 1); this.challengesContainer = globalScene.add.container(1, -globalScene.scaledCanvas.height + 1);
this.challengesContainer.setName("challenges"); this.challengesContainer.setName("challenges");
this.challengesContainer.setInteractive( this.challengesContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6), new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
@ -79,7 +79,7 @@ export class GameChallengesUiHandler extends UiHandler {
this.challengesContainer.add(bgOverlay); this.challengesContainer.add(bgOverlay);
// TODO: Change this back to /9 when adding in difficulty // TODO: Change this back to /9 when adding in difficulty
const headerBg = addWindow(0, 0, globalScene.game.canvas.width / 6, 24); const headerBg = addWindow(0, 0, globalScene.scaledCanvas.width, 24);
headerBg.setName("window-header-bg"); headerBg.setName("window-header-bg");
headerBg.setOrigin(0, 0); headerBg.setOrigin(0, 0);

View File

@ -10,7 +10,7 @@ export class CharSprite extends Phaser.GameObjects.Container {
public shown: boolean; public shown: boolean;
constructor() { constructor() {
super(globalScene, globalScene.game.canvas.width / 6 + 32, -42); super(globalScene, globalScene.scaledCanvas.width + 32, -42);
} }
setup(): void { setup(): void {
@ -49,7 +49,7 @@ export class CharSprite extends Phaser.GameObjects.Container {
globalScene.tweens.add({ globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6 - 102, x: globalScene.scaledCanvas.width - 102,
duration: 750, duration: 750,
ease: "Cubic.easeOut", ease: "Cubic.easeOut",
onComplete: () => { onComplete: () => {
@ -95,7 +95,7 @@ export class CharSprite extends Phaser.GameObjects.Container {
globalScene.tweens.add({ globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6 + 32, x: globalScene.scaledCanvas.width + 32,
duration: 750, duration: 750,
ease: "Cubic.easeIn", ease: "Cubic.easeIn",
onComplete: () => { onComplete: () => {

View File

@ -42,7 +42,7 @@ export class CommandUiHandler extends UiHandler {
ui.add(this.commandsContainer); ui.add(this.commandsContainer);
this.teraButton = globalScene.add.sprite(-32, 15, "button_tera"); this.teraButton = globalScene.add.sprite(-32, 15, "button_tera");
this.teraButton.setName("terrastallize-button"); this.teraButton.setName("terastallize-button");
this.teraButton.setScale(1.3); this.teraButton.setScale(1.3);
this.teraButton.setFrame("fire"); this.teraButton.setFrame("fire");
this.teraButton.setPipeline(globalScene.spritePipeline, { this.teraButton.setPipeline(globalScene.spritePipeline, {

View File

@ -1,8 +1,8 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { OptionSelectConfig } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig } from "#ui/abstract-option-select-ui-handler";
import { AbstractOptionSelectUiHandler } from "#ui/abstact-option-select-ui-handler"; import { AbstractOptionSelectUiHandler } from "#ui/abstract-option-select-ui-handler";
import i18next from "i18next"; import i18next from "i18next";
export class ConfirmUiHandler extends AbstractOptionSelectUiHandler { export class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
@ -69,7 +69,7 @@ export class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
const xOffset = args.length >= 7 && args[6] !== null ? (args[6] as number) : 0; const xOffset = args.length >= 7 && args[6] !== null ? (args[6] as number) : 0;
const yOffset = args.length >= 8 && args[7] !== null ? (args[7] as number) : 0; const yOffset = args.length >= 8 && args[7] !== null ? (args[7] as number) : 0;
this.optionSelectContainer.setPosition(globalScene.game.canvas.width / 6 - 1 + xOffset, -48 + yOffset); this.optionSelectContainer.setPosition(globalScene.scaledCanvas.width - 1 + xOffset, -48 + yOffset);
this.setCursor(this.switchCheck ? this.switchCheckCursor : 0); this.setCursor(this.switchCheck ? this.switchCheckCursor : 0);
return true; return true;
@ -103,7 +103,7 @@ export class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
const xOffset = args.length >= 4 && args[3] !== null ? (args[3] as number) : 0; const xOffset = args.length >= 4 && args[3] !== null ? (args[3] as number) : 0;
const yOffset = args.length >= 5 && args[4] !== null ? (args[4] as number) : 0; const yOffset = args.length >= 5 && args[4] !== null ? (args[4] as number) : 0;
this.optionSelectContainer.setPosition(globalScene.game.canvas.width / 6 - 1 + xOffset, -48 + yOffset); this.optionSelectContainer.setPosition(globalScene.scaledCanvas.width - 1 + xOffset, -48 + yOffset);
this.setCursor(this.switchCheck ? this.switchCheckCursor : 0); this.setCursor(this.switchCheck ? this.switchCheckCursor : 0);

View File

@ -174,7 +174,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
const ui = this.getUi(); const ui = this.getUi();
this.eggGachaContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6).setVisible(false); this.eggGachaContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height).setVisible(false);
ui.add(this.eggGachaContainer); ui.add(this.eggGachaContainer);
const bg = globalScene.add.nineslice(0, 0, "default_bg", undefined, 320, 180, 0, 0, 16, 0).setOrigin(0); const bg = globalScene.add.nineslice(0, 0, "default_bg", undefined, 320, 180, 0, 0, 16, 0).setOrigin(0);
@ -212,7 +212,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
this.eggGachaOptionSelectBg = addWindow(0, 0, eggGachaOptionSelectWidth, 16 + 576 * this.scale).setOrigin(1); this.eggGachaOptionSelectBg = addWindow(0, 0, eggGachaOptionSelectWidth, 16 + 576 * this.scale).setOrigin(1);
this.eggGachaOptionsContainer = globalScene.add this.eggGachaOptionsContainer = globalScene.add
.container(globalScene.game.canvas.width / 6, 148) .container(globalScene.scaledCanvas.width, 148)
.add(this.eggGachaOptionSelectBg); .add(this.eggGachaOptionSelectBg);
this.eggGachaContainer.add(this.eggGachaOptionsContainer); this.eggGachaContainer.add(this.eggGachaOptionsContainer);
@ -278,7 +278,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
this.eggGachaContainer.add(this.eggGachaOptionsContainer); this.eggGachaContainer.add(this.eggGachaOptionsContainer);
for (const voucher of getEnumValues(VoucherType)) { for (const voucher of getEnumValues(VoucherType)) {
const container = globalScene.add.container(globalScene.game.canvas.width / 6 - 56 * voucher, 0); const container = globalScene.add.container(globalScene.scaledCanvas.width - 56 * voucher, 0);
const bg = addWindow(0, 0, 56, 22).setOrigin(1, 0); const bg = addWindow(0, 0, 56, 22).setOrigin(1, 0);
container.add(bg); container.add(bg);

View File

@ -19,7 +19,7 @@ export class EggHatchSceneHandler extends UiHandler {
} }
setup() { setup() {
this.eggHatchContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.eggHatchContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
globalScene.fieldUI.add(this.eggHatchContainer); globalScene.fieldUI.add(this.eggHatchContainer);
const eggLightraysAnimFrames = globalScene.anims.generateFrameNames("egg_lightrays", { start: 0, end: 3 }); const eggLightraysAnimFrames = globalScene.anims.generateFrameNames("egg_lightrays", { start: 0, end: 3 });

View File

@ -36,11 +36,11 @@ export class EggListUiHandler extends MessageUiHandler {
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
this.eggListContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6).setVisible(false); this.eggListContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height).setVisible(false);
ui.add(this.eggListContainer); ui.add(this.eggListContainer);
const bgColor = globalScene.add const bgColor = globalScene.add
.rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6, 0x006860) .rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height, 0x006860)
.setOrigin(0); .setOrigin(0);
const eggListBg = globalScene.add.image(0, 0, "egg_list_bg").setOrigin(0); const eggListBg = globalScene.add.image(0, 0, "egg_list_bg").setOrigin(0);
@ -69,9 +69,7 @@ export class EggListUiHandler extends MessageUiHandler {
.withUpdateGridCallBack(() => this.updateEggIcons()) .withUpdateGridCallBack(() => this.updateEggIcons())
.withUpdateSingleElementCallback((i: number) => this.setEggDetails(i)); .withUpdateSingleElementCallback((i: number) => this.setEggDetails(i));
this.eggListMessageBoxContainer = globalScene.add this.eggListMessageBoxContainer = globalScene.add.container(0, globalScene.scaledCanvas.height).setVisible(false);
.container(0, globalScene.game.canvas.height / 6)
.setVisible(false);
const eggListMessageBox = addWindow(1, -1, 318, 28).setOrigin(0, 1); const eggListMessageBox = addWindow(1, -1, 318, 28).setOrigin(0, 1);
this.eggListMessageBoxContainer.add(eggListMessageBox); this.eggListMessageBoxContainer.add(eggListMessageBox);

View File

@ -59,11 +59,11 @@ export class EggSummaryUiHandler extends MessageUiHandler {
setup() { setup() {
const ui = this.getUi(); const ui = this.getUi();
this.summaryContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.summaryContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
this.summaryContainer.setVisible(false); this.summaryContainer.setVisible(false);
ui.add(this.summaryContainer); ui.add(this.summaryContainer);
this.eggHatchContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.eggHatchContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
this.eggHatchContainer.setVisible(false); this.eggHatchContainer.setVisible(false);
ui.add(this.eggHatchContainer); ui.add(this.eggHatchContainer);
@ -92,7 +92,7 @@ export class EggSummaryUiHandler extends MessageUiHandler {
iconContainerX + numCols * iconSize, iconContainerX + numCols * iconSize,
iconContainerY + 3, iconContainerY + 3,
4, 4,
globalScene.game.canvas.height / 6 - 20, globalScene.scaledCanvas.height - 20,
numRows, numRows,
); );
this.summaryContainer.add(scrollBar); this.summaryContainer.add(scrollBar);

View File

@ -22,7 +22,7 @@ export class EvolutionSceneHandler extends MessageUiHandler {
const ui = this.getUi(); const ui = this.getUi();
this.evolutionContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.evolutionContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
const messageBg = globalScene.add.sprite(0, 0, "bg", globalScene.windowType).setOrigin(0, 1).setVisible(false); const messageBg = globalScene.add.sprite(0, 0, "bg", globalScene.windowType).setOrigin(0, 1).setVisible(false);

View File

@ -105,15 +105,13 @@ export class FightUiHandler extends UiHandler implements InfoToggle {
]); ]);
// prepare move overlay // prepare move overlay
const overlayScale = 1;
this.moveInfoOverlay = new MoveInfoOverlay({ this.moveInfoOverlay = new MoveInfoOverlay({
delayVisibility: true, delayVisibility: true,
scale: overlayScale,
onSide: true, onSide: true,
right: true, right: true,
x: 0, x: 0,
y: -MoveInfoOverlay.getHeight(overlayScale, true), y: -MoveInfoOverlay.getHeight(true),
width: globalScene.game.canvas.width / 6 + 4, width: globalScene.scaledCanvas.width + 4,
hideEffectBox: true, hideEffectBox: true,
hideBg: true, hideBg: true,
}); });

View File

@ -62,7 +62,7 @@ export class FilterText extends Phaser.GameObjects.Container {
this.dialogueMessageBox = addWindow( this.dialogueMessageBox = addWindow(
-this.textPadding, -this.textPadding,
0, 0,
globalScene.game.canvas.width / 6 + this.textPadding * 2, globalScene.scaledCanvas.width + this.textPadding * 2,
49, 49,
false, false,
false, false,

View File

@ -2,7 +2,7 @@ import { pokerogueApi } from "#api/pokerogue-api";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import type { InputFieldConfig } from "#ui/form-modal-ui-handler"; import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
import { FormModalUiHandler } from "#ui/form-modal-ui-handler"; import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
import type { ModalConfig } from "#ui/modal-ui-handler"; import type { ModalConfig } from "#ui/modal-ui-handler";
@ -49,7 +49,7 @@ export class LoginFormUiHandler extends FormModalUiHandler {
private buildExternalPartyContainer() { private buildExternalPartyContainer() {
this.externalPartyContainer = globalScene.add.container(0, 0); this.externalPartyContainer = globalScene.add.container(0, 0);
this.externalPartyContainer.setInteractive( this.externalPartyContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 12, globalScene.game.canvas.height / 12), new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width / 2, globalScene.scaledCanvas.height / 2),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
this.externalPartyTitle = addTextObject(0, 4, "", TextStyle.SETTINGS_LABEL); this.externalPartyTitle = addTextObject(0, 4, "", TextStyle.SETTINGS_LABEL);

View File

@ -7,7 +7,7 @@ import { Button } from "#enums/buttons";
import { GameDataType } from "#enums/game-data-type"; import { GameDataType } from "#enums/game-data-type";
import { TextStyle } from "#enums/text-style"; import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { AdminMode, getAdminModeName } from "#ui/admin-ui-handler"; import { AdminMode, getAdminModeName } from "#ui/admin-ui-handler";
import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler"; import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
import { BgmBar } from "#ui/bgm-bar"; import { BgmBar } from "#ui/bgm-bar";
@ -96,10 +96,10 @@ export class MenuUiHandler extends MessageUiHandler {
ui.bgmBar = this.bgmBar; ui.bgmBar = this.bgmBar;
this.menuContainer = globalScene.add.container(1, -(globalScene.game.canvas.height / 6) + 1); this.menuContainer = globalScene.add.container(1, -globalScene.scaledCanvas.height + 1);
this.menuContainer.setName("menu"); this.menuContainer.setName("menu");
this.menuContainer.setInteractive( this.menuContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6), new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
@ -146,10 +146,10 @@ export class MenuUiHandler extends MessageUiHandler {
this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale;
this.menuBg = addWindow( this.menuBg = addWindow(
globalScene.game.canvas.width / 6 - (this.optionSelectText.displayWidth + 25), globalScene.scaledCanvas.width - (this.optionSelectText.displayWidth + 25),
0, 0,
this.optionSelectText.displayWidth + 19 + 24 * this.scale, this.optionSelectText.displayWidth + 19 + 24 * this.scale,
globalScene.game.canvas.height / 6 - 2, globalScene.scaledCanvas.height - 2,
); );
this.menuBg.setOrigin(0, 0); this.menuBg.setOrigin(0, 0);
@ -174,7 +174,7 @@ export class MenuUiHandler extends MessageUiHandler {
this.dialogueMessageBox = addWindow( this.dialogueMessageBox = addWindow(
-this.textPadding, -this.textPadding,
0, 0,
globalScene.game.canvas.width / 6 + this.textPadding * 2, globalScene.scaledCanvas.width + this.textPadding * 2,
49, 49,
false, false,
false, false,

View File

@ -46,7 +46,7 @@ export abstract class ModalUiHandler extends UiHandler {
this.modalContainer = globalScene.add.container(0, 0); this.modalContainer = globalScene.add.container(0, 0);
this.modalContainer.setInteractive( this.modalContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6), new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
@ -105,8 +105,8 @@ export abstract class ModalUiHandler extends UiHandler {
const overlay = globalScene.add.rectangle( const overlay = globalScene.add.rectangle(
(this.getWidth() + marginLeft + marginRight) / 2, (this.getWidth() + marginLeft + marginRight) / 2,
(this.getHeight() + marginTop + marginBottom) / 2, (this.getHeight() + marginTop + marginBottom) / 2,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6, globalScene.scaledCanvas.height,
0, 0,
); );
overlay.setOrigin(0.5, 0.5); overlay.setOrigin(0.5, 0.5);
@ -159,8 +159,8 @@ export abstract class ModalUiHandler extends UiHandler {
const width = this.getWidth(config); const width = this.getWidth(config);
const height = this.getHeight(config); const height = this.getHeight(config);
this.modalContainer.setPosition( this.modalContainer.setPosition(
(globalScene.game.canvas.width / 6 - (width + (marginRight - marginLeft))) / 2, (globalScene.scaledCanvas.width - (width + (marginRight - marginLeft))) / 2,
(-globalScene.game.canvas.height / 6 - (height + (marginBottom - marginTop))) / 2, (-globalScene.scaledCanvas.height - (height + (marginBottom - marginTop))) / 2,
); );
this.modalBg.setSize(width, height); this.modalBg.setSize(width, height);

View File

@ -10,17 +10,24 @@ import { fixedInt, getLocalizedSpriteKey } from "#utils/common";
import i18next from "i18next"; import i18next from "i18next";
export interface MoveInfoOverlaySettings { export interface MoveInfoOverlaySettings {
delayVisibility?: boolean; // if true, showing the overlay will only set it to active and populate the fields and the handler using this field has to manually call setVisible later. /**
scale?: number; // scale the box? A scale of 0.5 is recommended * If true, showing the overlay will only set it to active and populate the fields
top?: boolean; // should the effect box be on top? * and the handler using this field has to manually call `setVisible` later.
right?: boolean; // should the effect box be on the right? */
onSide?: boolean; // should the effect be on the side? ignores top argument if true delayVisibility?: boolean;
//location and width of the component; unaffected by scaling /** Whether the effect box should be on top */
top?: boolean;
/** Whether the effect box should be on the right */
right?: boolean;
/** Whether the effect box should be on the side. Overrides the `top` param if `true`. */
onSide?: boolean;
/** `x` position of the component, unaffected by scaling */
x?: number; x?: number;
/** `y` position of the component, unaffected by scaling */
y?: number; y?: number;
/** Default is always half the screen, regardless of scale */ /** Width of the component, unaffected by scaling. Defaults to half the screen width. */
width?: number; width?: number;
/** Determines whether to display the small secondary box */ /** Whether to display the small secondary box */
hideEffectBox?: boolean; hideEffectBox?: boolean;
hideBg?: boolean; hideBg?: boolean;
} }
@ -54,12 +61,11 @@ export class MoveInfoOverlay extends Phaser.GameObjects.Container implements Inf
options.top = false; options.top = false;
} }
super(globalScene, options?.x, options?.y); super(globalScene, options?.x, options?.y);
const scale = options?.scale || 1; // set up the scale this.setScale(1);
this.setScale(scale);
this.options = options || {}; this.options = options || {};
// prepare the description box // prepare the description box
const width = (options?.width || MoveInfoOverlay.getWidth(scale)) / scale; // divide by scale as we always want this to be half a window wide const width = options?.width || MoveInfoOverlay.getWidth(); // we always want this to be half a window wide
this.descBg = addWindow( this.descBg = addWindow(
options?.onSide && !options?.right ? EFF_WIDTH : 0, options?.onSide && !options?.right ? EFF_WIDTH : 0,
options?.top ? EFF_HEIGHT : 0, options?.top ? EFF_HEIGHT : 0,
@ -88,19 +94,19 @@ export class MoveInfoOverlay extends Phaser.GameObjects.Container implements Inf
y: options?.y || 0, y: options?.y || 0,
}; };
if (maskPointOrigin.x < 0) { if (maskPointOrigin.x < 0) {
maskPointOrigin.x += globalScene.game.canvas.width / GLOBAL_SCALE; maskPointOrigin.x += globalScene.scaledCanvas.width;
} }
if (maskPointOrigin.y < 0) { if (maskPointOrigin.y < 0) {
maskPointOrigin.y += globalScene.game.canvas.height / GLOBAL_SCALE; maskPointOrigin.y += globalScene.scaledCanvas.height;
} }
const moveDescriptionTextMaskRect = globalScene.make.graphics(); const moveDescriptionTextMaskRect = globalScene.make.graphics();
moveDescriptionTextMaskRect.fillStyle(0xff0000); moveDescriptionTextMaskRect.fillStyle(0xff0000);
moveDescriptionTextMaskRect.fillRect( moveDescriptionTextMaskRect.fillRect(
maskPointOrigin.x + ((options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER) * scale, maskPointOrigin.x + ((options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER),
maskPointOrigin.y + ((options?.top ? EFF_HEIGHT : 0) + BORDER - 2) * scale, maskPointOrigin.y + ((options?.top ? EFF_HEIGHT : 0) + BORDER - 2),
width - ((options?.onSide ? EFF_WIDTH : 0) - BORDER * 2) * scale, width - ((options?.onSide ? EFF_WIDTH : 0) - BORDER * 2),
(DESC_HEIGHT - (BORDER - 2) * 2) * scale, DESC_HEIGHT - (BORDER - 2) * 2,
); );
moveDescriptionTextMaskRect.setScale(6); moveDescriptionTextMaskRect.setScale(6);
const moveDescriptionTextMask = this.createGeometryMask(moveDescriptionTextMaskRect); const moveDescriptionTextMask = this.createGeometryMask(moveDescriptionTextMaskRect);
@ -233,12 +239,12 @@ export class MoveInfoOverlay extends Phaser.GameObjects.Container implements Inf
} }
// width of this element // width of this element
static getWidth(_scale: number): number { static getWidth(): number {
return globalScene.game.canvas.width / GLOBAL_SCALE / 2; return globalScene.scaledCanvas.width / 2;
} }
// height of this element // height of this element
static getHeight(scale: number, onSide?: boolean): number { static getHeight(onSide?: boolean): number {
return (onSide ? Math.max(EFF_HEIGHT, DESC_HEIGHT) : EFF_HEIGHT + DESC_HEIGHT) * scale; return onSide ? Math.max(EFF_HEIGHT, DESC_HEIGHT) : EFF_HEIGHT + DESC_HEIGHT;
} }
} }

View File

@ -471,7 +471,7 @@ export class MysteryEncounterUiHandler extends UiHandler {
// View Party Button // View Party Button
const viewPartyText = addBBCodeTextObject( const viewPartyText = addBBCodeTextObject(
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
-24, -24,
getBBCodeFrag(i18next.t("mysteryEncounterMessages:view_party_button"), TextStyle.PARTY), getBBCodeFrag(i18next.t("mysteryEncounterMessages:view_party_button"), TextStyle.PARTY),
TextStyle.PARTY, TextStyle.PARTY,

View File

@ -14,7 +14,7 @@ export class PartyExpBar extends Phaser.GameObjects.Container {
public shown: boolean; public shown: boolean;
constructor() { constructor() {
super(globalScene, globalScene.game.canvas.width / 6, -(globalScene.game.canvas.height / 6) + 15); super(globalScene, globalScene.scaledCanvas.width, -globalScene.scaledCanvas.height + 15);
} }
setup(): void { setup(): void {
@ -66,7 +66,7 @@ export class PartyExpBar extends Phaser.GameObjects.Container {
this.tween = globalScene.tweens.add({ this.tween = globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6 - (this.bg.width - 5), x: globalScene.scaledCanvas.width - (this.bg.width - 5),
duration: 500 / Math.pow(2, globalScene.expGainsSpeed), duration: 500 / Math.pow(2, globalScene.expGainsSpeed),
ease: "Sine.easeOut", ease: "Sine.easeOut",
onComplete: () => { onComplete: () => {
@ -92,7 +92,7 @@ export class PartyExpBar extends Phaser.GameObjects.Container {
this.tween = globalScene.tweens.add({ this.tween = globalScene.tweens.add({
targets: this, targets: this,
x: globalScene.game.canvas.width / 6, x: globalScene.scaledCanvas.width,
duration: 500, duration: 500,
ease: "Sine.easeIn", ease: "Sine.easeIn",
onComplete: () => { onComplete: () => {

View File

@ -1,7 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { pokemonEvolutions } from "#balance/pokemon-evolutions"; import { pokemonEvolutions } from "#balance/pokemon-evolutions";
import { applyChallenges } from "#data/challenge";
import { allHeldItems, allMoves } from "#data/data-lists"; import { allHeldItems, allMoves } from "#data/data-lists";
import { SpeciesFormChangeItemTrigger } from "#data/form-change-triggers"; import { SpeciesFormChangeItemTrigger } from "#data/form-change-triggers";
import { Gender, getGenderColor, getGenderSymbol } from "#data/gender"; import { Gender, getGenderColor, getGenderSymbol } from "#data/gender";
@ -27,6 +26,7 @@ import { MoveInfoOverlay } from "#ui/move-info-overlay";
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler"; import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import { applyChallenges } from "#utils/challenge-utils";
import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common"; import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common";
import { toTitleCase } from "#utils/strings"; import { toTitleCase } from "#utils/strings";
import i18next from "i18next"; import i18next from "i18next";
@ -306,7 +306,7 @@ export class PartyUiHandler extends MessageUiHandler {
this.partyCancelButton = partyCancelButton; this.partyCancelButton = partyCancelButton;
this.optionsContainer = globalScene.add.container(globalScene.game.canvas.width / 6 - 1, -1); this.optionsContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, -1);
partyContainer.add(this.optionsContainer); partyContainer.add(this.optionsContainer);
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHandler();
@ -318,14 +318,12 @@ export class PartyUiHandler extends MessageUiHandler {
this.partyDiscardModeButton = partyDiscardModeButton; this.partyDiscardModeButton = partyDiscardModeButton;
// prepare move overlay. in case it appears to be too big, set the overlayScale to .5 // prepare move overlay
const overlayScale = 1;
this.moveInfoOverlay = new MoveInfoOverlay({ this.moveInfoOverlay = new MoveInfoOverlay({
scale: overlayScale,
top: true, top: true,
x: 1, x: 1,
y: -MoveInfoOverlay.getHeight(overlayScale) - 1, y: -MoveInfoOverlay.getHeight() - 1,
width: globalScene.game.canvas.width / 12 - 30, width: globalScene.scaledCanvas.width / 2 - 30,
}); });
ui.add(this.moveInfoOverlay); ui.add(this.moveInfoOverlay);

View File

@ -10,7 +10,7 @@ export class PokeballTray extends Phaser.GameObjects.Container {
public shown: boolean; public shown: boolean;
constructor(player: boolean) { constructor(player: boolean) {
super(globalScene, player ? globalScene.game.canvas.width / 6 : 0, player ? -72 : -144); super(globalScene, player ? globalScene.scaledCanvas.width : 0, player ? -72 : -144);
this.player = player; this.player = player;
} }
@ -36,7 +36,7 @@ export class PokeballTray extends Phaser.GameObjects.Container {
.map((_, i) => .map((_, i) =>
globalScene.add.sprite( globalScene.add.sprite(
(this.player ? -83 : 76) + (this.player ? -83 : 76) +
(globalScene.game.canvas.width / 6) * (this.player ? -1 : 1) + globalScene.scaledCanvas.width * (this.player ? -1 : 1) +
10 * i * (this.player ? 1 : -1), 10 * i * (this.player ? 1 : -1),
-8, -8,
"pb_tray_ball", "pb_tray_ball",
@ -67,7 +67,7 @@ export class PokeballTray extends Phaser.GameObjects.Container {
this.bg.alpha = 1; this.bg.alpha = 1;
this.balls.forEach((ball, b) => { this.balls.forEach((ball, b) => {
ball.x += (globalScene.game.canvas.width / 6 + 104) * (this.player ? 1 : -1); ball.x += (globalScene.scaledCanvas.width + 104) * (this.player ? 1 : -1);
let ballFrame = "ball"; let ballFrame = "ball";
if (b >= party.length) { if (b >= party.length) {
ballFrame = "empty"; ballFrame = "empty";
@ -115,7 +115,7 @@ export class PokeballTray extends Phaser.GameObjects.Container {
this.balls.forEach((ball, b) => { this.balls.forEach((ball, b) => {
globalScene.tweens.add({ globalScene.tweens.add({
targets: ball, targets: ball,
x: `${this.player ? "-" : "+"}=${globalScene.game.canvas.width / 6}`, x: `${this.player ? "-" : "+"}=${globalScene.scaledCanvas.width}`,
duration: 250, duration: 250,
delay: b * 100, delay: b * 100,
ease: "Sine.easeIn", ease: "Sine.easeIn",

View File

@ -7,7 +7,6 @@ import { fixedInt } from "#utils/common";
export interface PokedexInfoOverlaySettings { export interface PokedexInfoOverlaySettings {
delayVisibility?: boolean; // if true, showing the overlay will only set it to active and populate the fields and the handler using this field has to manually call setVisible later. delayVisibility?: boolean; // if true, showing the overlay will only set it to active and populate the fields and the handler using this field has to manually call setVisible later.
scale?: number; // scale the box? A scale of 0.5 is recommended
//location and width of the component; unaffected by scaling //location and width of the component; unaffected by scaling
x?: number; x?: number;
y?: number; y?: number;
@ -36,17 +35,15 @@ export class PokedexInfoOverlay extends Phaser.GameObjects.Container implements
private maskPointOriginX: number; private maskPointOriginX: number;
private maskPointOriginY: number; private maskPointOriginY: number;
public scale: number;
public width: number; public width: number;
constructor(options?: PokedexInfoOverlaySettings) { constructor(options?: PokedexInfoOverlaySettings) {
super(globalScene, options?.x, options?.y); super(globalScene, options?.x, options?.y);
this.scale = options?.scale || 1; // set up the scale this.setScale(1);
this.setScale(this.scale);
this.options = options || {}; this.options = options || {};
// prepare the description box // prepare the description box
this.width = (options?.width || PokedexInfoOverlay.getWidth(this.scale)) / this.scale; // divide by scale as we always want this to be half a window wide this.width = options?.width || PokedexInfoOverlay.getWidth(); // we always want this to be half a window wide
this.descBg = addWindow(0, 0, this.width, DESC_HEIGHT); this.descBg = addWindow(0, 0, this.width, DESC_HEIGHT);
this.descBg.setOrigin(0, 0); this.descBg.setOrigin(0, 0);
this.add(this.descBg); this.add(this.descBg);
@ -61,19 +58,19 @@ export class PokedexInfoOverlay extends Phaser.GameObjects.Container implements
this.maskPointOriginY = options?.y || 0; this.maskPointOriginY = options?.y || 0;
if (this.maskPointOriginX < 0) { if (this.maskPointOriginX < 0) {
this.maskPointOriginX += globalScene.game.canvas.width / GLOBAL_SCALE; this.maskPointOriginX += globalScene.scaledCanvas.width;
} }
if (this.maskPointOriginY < 0) { if (this.maskPointOriginY < 0) {
this.maskPointOriginY += globalScene.game.canvas.height / GLOBAL_SCALE; this.maskPointOriginY += globalScene.scaledCanvas.height;
} }
this.textMaskRect = globalScene.make.graphics(); this.textMaskRect = globalScene.make.graphics();
this.textMaskRect.fillStyle(0xff0000); this.textMaskRect.fillStyle(0xff0000);
this.textMaskRect.fillRect( this.textMaskRect.fillRect(
this.maskPointOriginX + BORDER * this.scale, this.maskPointOriginX + BORDER,
this.maskPointOriginY + (BORDER - 2) * this.scale, this.maskPointOriginY + (BORDER - 2),
this.width - BORDER * 2 * this.scale, this.width - BORDER * 2,
(DESC_HEIGHT - (BORDER - 2) * 2) * this.scale, DESC_HEIGHT - (BORDER - 2) * 2,
); );
this.textMaskRect.setScale(6); this.textMaskRect.setScale(6);
const textMask = this.createGeometryMask(this.textMaskRect); const textMask = this.createGeometryMask(this.textMaskRect);
@ -111,10 +108,10 @@ export class PokedexInfoOverlay extends Phaser.GameObjects.Container implements
this.textMaskRect.clear(); this.textMaskRect.clear();
this.textMaskRect.fillStyle(0xff0000); this.textMaskRect.fillStyle(0xff0000);
this.textMaskRect.fillRect( this.textMaskRect.fillRect(
this.maskPointOriginX + BORDER * this.scale, this.maskPointOriginX + BORDER,
this.maskPointOriginY + (BORDER - 2) * this.scale + (48 - newHeight), this.maskPointOriginY + (BORDER - 2) + (48 - newHeight),
this.width - BORDER * 2 * this.scale, this.width - BORDER * 2,
(newHeight - (BORDER - 2) * 2) * this.scale, newHeight - (BORDER - 2) * 2,
); );
const updatedMask = this.createGeometryMask(this.textMaskRect); const updatedMask = this.createGeometryMask(this.textMaskRect);
this.desc.setMask(updatedMask); this.desc.setMask(updatedMask);
@ -167,12 +164,12 @@ export class PokedexInfoOverlay extends Phaser.GameObjects.Container implements
} }
// width of this element // width of this element
static getWidth(_scale: number): number { static getWidth(): number {
return globalScene.game.canvas.width / GLOBAL_SCALE / 2; return globalScene.scaledCanvas.width / 2;
} }
// height of this element // height of this element
static getHeight(scale: number, _onSide?: boolean): number { static getHeight(): number {
return DESC_HEIGHT * scale; return DESC_HEIGHT;
} }
} }

View File

@ -46,7 +46,7 @@ import { getVariantIcon, getVariantTint } from "#sprites/variant";
import type { StarterAttributes } from "#system/game-data"; import type { StarterAttributes } from "#system/game-data";
import { SettingKeyboard } from "#system/settings-keyboard"; import { SettingKeyboard } from "#system/settings-keyboard";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { BaseStatsOverlay } from "#ui/base-stats-overlay"; import { BaseStatsOverlay } from "#ui/base-stats-overlay";
import { MessageUiHandler } from "#ui/message-ui-handler"; import { MessageUiHandler } from "#ui/message-ui-handler";
import { MoveInfoOverlay } from "#ui/move-info-overlay"; import { MoveInfoOverlay } from "#ui/move-info-overlay";
@ -299,15 +299,15 @@ export class PokedexPageUiHandler extends MessageUiHandler {
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)) ?? "en"; const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)) ?? "en";
const textSettings = languageSettings[langSettingKey]; const textSettings = languageSettings[langSettingKey];
this.starterSelectContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.starterSelectContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
this.starterSelectContainer.setVisible(false); this.starterSelectContainer.setVisible(false);
ui.add(this.starterSelectContainer); ui.add(this.starterSelectContainer);
const bgColor = globalScene.add.rectangle( const bgColor = globalScene.add.rectangle(
0, 0,
0, 0,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6, globalScene.scaledCanvas.height,
0x006860, 0x006860,
); );
bgColor.setOrigin(0, 0); bgColor.setOrigin(0, 0);
@ -602,7 +602,7 @@ export class PokedexPageUiHandler extends MessageUiHandler {
this.filterInstructionsContainer.setVisible(true); this.filterInstructionsContainer.setVisible(true);
this.starterSelectContainer.add(this.filterInstructionsContainer); this.starterSelectContainer.add(this.filterInstructionsContainer);
this.starterSelectMessageBoxContainer = globalScene.add.container(0, globalScene.game.canvas.height / 6); this.starterSelectMessageBoxContainer = globalScene.add.container(0, globalScene.scaledCanvas.height);
this.starterSelectMessageBoxContainer.setVisible(false); this.starterSelectMessageBoxContainer.setVisible(false);
this.starterSelectContainer.add(this.starterSelectMessageBoxContainer); this.starterSelectContainer.add(this.starterSelectMessageBoxContainer);
@ -629,7 +629,7 @@ export class PokedexPageUiHandler extends MessageUiHandler {
this.menuContainer = globalScene.add.container(-130, 0); this.menuContainer = globalScene.add.container(-130, 0);
this.menuContainer.setName("menu"); this.menuContainer.setName("menu");
this.menuContainer.setInteractive( this.menuContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6), new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
@ -659,10 +659,10 @@ export class PokedexPageUiHandler extends MessageUiHandler {
this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale;
this.menuBg = addWindow( this.menuBg = addWindow(
globalScene.game.canvas.width / 6 - 83, globalScene.scaledCanvas.width - 83,
0, 0,
this.optionSelectText.displayWidth + 19 + 24 * this.scale, this.optionSelectText.displayWidth + 19 + 24 * this.scale,
globalScene.game.canvas.height / 6 - 2, globalScene.scaledCanvas.height - 2,
); );
this.menuBg.setOrigin(0, 0); this.menuBg.setOrigin(0, 0);
@ -682,19 +682,16 @@ export class PokedexPageUiHandler extends MessageUiHandler {
this.menuContainer.bringToTop(this.baseStatsOverlay); this.menuContainer.bringToTop(this.baseStatsOverlay);
// add the info overlay last to be the top most ui element and prevent the IVs from overlaying this // add the info overlay last to be the top most ui element and prevent the IVs from overlaying this
const overlayScale = 1;
this.moveInfoOverlay = new MoveInfoOverlay({ this.moveInfoOverlay = new MoveInfoOverlay({
scale: overlayScale,
top: true, top: true,
x: 1, x: 1,
y: globalScene.game.canvas.height / 6 - MoveInfoOverlay.getHeight(overlayScale) - 29, y: globalScene.scaledCanvas.height - MoveInfoOverlay.getHeight() - 29,
}); });
this.starterSelectContainer.add(this.moveInfoOverlay); this.starterSelectContainer.add(this.moveInfoOverlay);
this.infoOverlay = new PokedexInfoOverlay({ this.infoOverlay = new PokedexInfoOverlay({
scale: overlayScale,
x: 1, x: 1,
y: globalScene.game.canvas.height / 6 - PokedexInfoOverlay.getHeight(overlayScale) - 29, y: globalScene.scaledCanvas.height - PokedexInfoOverlay.getHeight() - 29,
}); });
this.starterSelectContainer.add(this.infoOverlay); this.starterSelectContainer.add(this.infoOverlay);
@ -1103,7 +1100,7 @@ export class PokedexPageUiHandler extends MessageUiHandler {
this.starterSelectMessageBoxContainer.setY(0); this.starterSelectMessageBoxContainer.setY(0);
this.message.setY(4); this.message.setY(4);
} else { } else {
this.starterSelectMessageBoxContainer.setY(globalScene.game.canvas.height / 6); this.starterSelectMessageBoxContainer.setY(globalScene.scaledCanvas.height);
this.starterSelectMessageBox.setOrigin(0, 1); this.starterSelectMessageBox.setOrigin(0, 1);
this.message.setY(singleLine ? -22 : -37); this.message.setY(singleLine ? -22 : -37);
} }

View File

@ -1,7 +1,7 @@
import { allAbilities, allMoves, allSpecies } from "#data/data-lists"; import { allAbilities, allMoves, allSpecies } from "#data/data-lists";
import { UiMode } from "#enums/ui-mode"; import { UiMode } from "#enums/ui-mode";
import type { PlayerPokemon } from "#field/pokemon"; import type { PlayerPokemon } from "#field/pokemon";
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler";
import { FilterTextRow } from "#ui/filter-text"; import { FilterTextRow } from "#ui/filter-text";
import type { InputFieldConfig } from "#ui/form-modal-ui-handler"; import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
import { FormModalUiHandler } from "#ui/form-modal-ui-handler"; import { FormModalUiHandler } from "#ui/form-modal-ui-handler";

View File

@ -33,7 +33,7 @@ import { getVariantIcon, getVariantTint } from "#sprites/variant";
import type { DexAttrProps, StarterAttributes } from "#system/game-data"; import type { DexAttrProps, StarterAttributes } from "#system/game-data";
import { SettingKeyboard } from "#system/settings-keyboard"; import { SettingKeyboard } from "#system/settings-keyboard";
import type { DexEntry } from "#types/dex-data"; import type { DexEntry } from "#types/dex-data";
import type { OptionSelectConfig } from "#ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig } from "#ui/abstract-option-select-ui-handler";
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#ui/dropdown"; import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#ui/dropdown";
import { FilterBar } from "#ui/filter-bar"; import { FilterBar } from "#ui/filter-bar";
import { FilterText, FilterTextRow } from "#ui/filter-text"; import { FilterText, FilterTextRow } from "#ui/filter-text";
@ -245,15 +245,15 @@ export class PokedexUiHandler extends MessageUiHandler {
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)) ?? "en"; const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang)) ?? "en";
const textSettings = languageSettings[langSettingKey]; const textSettings = languageSettings[langSettingKey];
this.starterSelectContainer = globalScene.add.container(0, -globalScene.game.canvas.height / 6); this.starterSelectContainer = globalScene.add.container(0, -globalScene.scaledCanvas.height);
this.starterSelectContainer.setVisible(false); this.starterSelectContainer.setVisible(false);
ui.add(this.starterSelectContainer); ui.add(this.starterSelectContainer);
const bgColor = globalScene.add.rectangle( const bgColor = globalScene.add.rectangle(
0, 0,
0, 0,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
globalScene.game.canvas.height / 6, globalScene.scaledCanvas.height,
0x006860, 0x006860,
); );
bgColor.setOrigin(0, 0); bgColor.setOrigin(0, 0);
@ -544,7 +544,7 @@ export class PokedexUiHandler extends MessageUiHandler {
this.type2Icon.setOrigin(0, 0); this.type2Icon.setOrigin(0, 0);
this.starterSelectContainer.add(this.type2Icon); this.starterSelectContainer.add(this.type2Icon);
this.starterSelectMessageBoxContainer = globalScene.add.container(0, globalScene.game.canvas.height / 6); this.starterSelectMessageBoxContainer = globalScene.add.container(0, globalScene.scaledCanvas.height);
this.starterSelectMessageBoxContainer.setVisible(false); this.starterSelectMessageBoxContainer.setVisible(false);
this.starterSelectContainer.add(this.starterSelectMessageBoxContainer); this.starterSelectContainer.add(this.starterSelectMessageBoxContainer);
@ -784,7 +784,7 @@ export class PokedexUiHandler extends MessageUiHandler {
this.starterSelectMessageBoxContainer.setY(0); this.starterSelectMessageBoxContainer.setY(0);
this.message.setY(4); this.message.setY(4);
} else { } else {
this.starterSelectMessageBoxContainer.setY(globalScene.game.canvas.height / 6); this.starterSelectMessageBoxContainer.setY(globalScene.scaledCanvas.height);
this.starterSelectMessageBox.setOrigin(0, 1); this.starterSelectMessageBox.setOrigin(0, 1);
this.message.setY(singleLine ? -22 : -37); this.message.setY(singleLine ? -22 : -37);
} }

View File

@ -89,10 +89,7 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
transferButtonText.setOrigin(1, 0); transferButtonText.setOrigin(1, 0);
this.transferButtonContainer.add(transferButtonText); this.transferButtonContainer.add(transferButtonText);
this.checkButtonContainer = globalScene.add.container( this.checkButtonContainer = globalScene.add.container(globalScene.scaledCanvas.width - 1, OPTION_BUTTON_YPOSITION);
globalScene.game.canvas.width / 6 - 1,
OPTION_BUTTON_YPOSITION,
);
this.checkButtonContainer.setName("use-btn"); this.checkButtonContainer.setName("use-btn");
this.checkButtonContainer.setVisible(false); this.checkButtonContainer.setVisible(false);
ui.add(this.checkButtonContainer); ui.add(this.checkButtonContainer);
@ -127,8 +124,8 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
this.lockRarityButtonContainer.add(this.lockRarityButtonText); this.lockRarityButtonContainer.add(this.lockRarityButtonText);
this.continueButtonContainer = globalScene.add.container( this.continueButtonContainer = globalScene.add.container(
globalScene.game.canvas.width / 12, globalScene.scaledCanvas.width / 2,
-(globalScene.game.canvas.height / 12), -(globalScene.scaledCanvas.height / 2),
); );
this.continueButtonContainer.setVisible(false); this.continueButtonContainer.setVisible(false);
ui.add(this.continueButtonContainer); ui.add(this.continueButtonContainer);
@ -144,15 +141,13 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
this.continueButtonContainer.add(continueButtonText); this.continueButtonContainer.add(continueButtonText);
// prepare move overlay // prepare move overlay
const overlayScale = 1;
this.moveInfoOverlay = new MoveInfoOverlay({ this.moveInfoOverlay = new MoveInfoOverlay({
delayVisibility: true, delayVisibility: true,
scale: overlayScale,
onSide: true, onSide: true,
right: true, right: true,
x: 1, x: 1,
y: -MoveInfoOverlay.getHeight(overlayScale, true) - 1, y: -MoveInfoOverlay.getHeight(true) - 1,
width: globalScene.game.canvas.width / 6 - 2, width: globalScene.scaledCanvas.width - 2,
}); });
ui.add(this.moveInfoOverlay); ui.add(this.moveInfoOverlay);
// register the overlay to receive toggle events // register the overlay to receive toggle events
@ -210,20 +205,20 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
this.updateRerollCostText(); this.updateRerollCostText();
const typeOptions = args[1] as RewardOption[]; const typeOptions = args[1] as RewardOption[];
const removeHealShop = globalScene.gameMode.hasNoShop; const hasShop = globalScene.gameMode.getShopStatus();
const baseShopCost = new NumberHolder(globalScene.getWaveMoneyAmount(1)); const baseShopCost = new NumberHolder(globalScene.getWaveMoneyAmount(1));
globalScene.applyPlayerItems(TrainerItemEffect.HEAL_SHOP_COST, { numberHolder: baseShopCost }); globalScene.applyPlayerItems(TrainerItemEffect.HEAL_SHOP_COST, { numberHolder: baseShopCost });
const shopTypeOptions = !removeHealShop const shopTypeOptions = hasShop
? getPlayerShopRewardOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value) ? getPlayerShopRewardOptionsForWave(globalScene.currentBattle.waveIndex, baseShopCost.value)
: []; : [];
const optionsYOffset = const optionsYOffset =
shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET; shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET;
for (let m = 0; m < typeOptions.length; m++) { for (let m = 0; m < typeOptions.length; m++) {
const sliceWidth = globalScene.game.canvas.width / 6 / (typeOptions.length + 2); const sliceWidth = globalScene.scaledCanvas.width / (typeOptions.length + 2);
const option = new ModifierOption( const option = new ModifierOption(
sliceWidth * (m + 1) + sliceWidth * 0.5, sliceWidth * (m + 1) + sliceWidth * 0.5,
-globalScene.game.canvas.height / 12 + optionsYOffset, -globalScene.scaledCanvas.height / 2 + optionsYOffset,
typeOptions[m], typeOptions[m],
); );
option.setScale(0.5); option.setScale(0.5);
@ -244,10 +239,10 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
row ? SHOP_OPTIONS_ROW_LIMIT : 0, row ? SHOP_OPTIONS_ROW_LIMIT : 0,
row ? undefined : SHOP_OPTIONS_ROW_LIMIT, row ? undefined : SHOP_OPTIONS_ROW_LIMIT,
); );
const sliceWidth = globalScene.game.canvas.width / 6 / (rowOptions.length + 2); const sliceWidth = globalScene.scaledCanvas.width / (rowOptions.length + 2);
const option = new ModifierOption( const option = new ModifierOption(
sliceWidth * (col + 1) + sliceWidth * 0.5, sliceWidth * (col + 1) + sliceWidth * 0.5,
-globalScene.game.canvas.height / 12 - globalScene.game.canvas.height / 32 - (42 - (28 * row - 1)), -globalScene.scaledCanvas.height / 2 - globalScene.game.canvas.height / 32 - (42 - (28 * row - 1)),
shopTypeOptions[m], shopTypeOptions[m],
); );
option.setScale(0.375); option.setScale(0.375);
@ -373,7 +368,7 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) { if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
this.setRowCursor(0); this.setRowCursor(0);
this.setCursor(2); this.setCursor(2);
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && globalScene.gameMode.hasNoShop) { } else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && !hasShop) {
this.setRowCursor(ShopCursorTarget.REWARDS); this.setRowCursor(ShopCursorTarget.REWARDS);
this.setCursor(0); this.setCursor(0);
} else { } else {
@ -561,27 +556,27 @@ export class RewardSelectUiHandler extends AwaitableUiHandler {
// Continue button when no shop items // Continue button when no shop items
this.cursorObj.setScale(1.25); this.cursorObj.setScale(1.25);
this.cursorObj.setPosition( this.cursorObj.setPosition(
globalScene.game.canvas.width / 18 + 23, globalScene.scaledCanvas.width / 3 + 23,
-globalScene.game.canvas.height / 12 - -globalScene.scaledCanvas.height / 2 -
(this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2), (this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2),
); );
ui.showText(i18next.t("rewardSelectUiHandler:continueNextWaveDescription")); ui.showText(i18next.t("rewardSelectUiHandler:continueNextWaveDescription"));
return ret; return ret;
} }
const sliceWidth = globalScene.game.canvas.width / 6 / (options.length + 2); const sliceWidth = globalScene.scaledCanvas.width / (options.length + 2);
if (this.rowCursor < 2) { if (this.rowCursor < 2) {
// Cursor on free items // Cursor on free items
this.cursorObj.setPosition( this.cursorObj.setPosition(
sliceWidth * (cursor + 1) + sliceWidth * 0.5 - 20, sliceWidth * (cursor + 1) + sliceWidth * 0.5 - 20,
-globalScene.game.canvas.height / 12 - -globalScene.scaledCanvas.height / 2 -
(this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2), (this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2),
); );
} else { } else {
// Cursor on paying items // Cursor on paying items
this.cursorObj.setPosition( this.cursorObj.setPosition(
sliceWidth * (cursor + 1) + sliceWidth * 0.5 - 16, sliceWidth * (cursor + 1) + sliceWidth * 0.5 - 16,
-globalScene.game.canvas.height / 12 - -globalScene.scaledCanvas.height / 2 -
globalScene.game.canvas.height / 32 - globalScene.game.canvas.height / 32 -
(-14 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1))), (-14 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1))),
); );

View File

@ -54,14 +54,14 @@ export class RunHistoryUiHandler extends MessageUiHandler {
const loadSessionBg = globalScene.add.rectangle( const loadSessionBg = globalScene.add.rectangle(
0, 0,
0, 0,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
-globalScene.game.canvas.height / 6, -globalScene.scaledCanvas.height,
0x006860, 0x006860,
); );
loadSessionBg.setOrigin(0, 0); loadSessionBg.setOrigin(0, 0);
this.runSelectContainer.add(loadSessionBg); this.runSelectContainer.add(loadSessionBg);
this.runContainerInitialY = -globalScene.game.canvas.height / 6 + 8; this.runContainerInitialY = -globalScene.scaledCanvas.height + 8;
this.runsContainer = globalScene.add.container(8, this.runContainerInitialY); this.runsContainer = globalScene.add.container(8, this.runContainerInitialY);
this.runSelectContainer.add(this.runsContainer); this.runSelectContainer.add(this.runsContainer);

View File

@ -73,7 +73,7 @@ export class RunInfoUiHandler extends UiHandler {
} }
override async setup() { override async setup() {
this.runContainer = globalScene.add.container(1, -(globalScene.game.canvas.height / 6) + 1); this.runContainer = globalScene.add.container(1, -globalScene.scaledCanvas.height + 1);
this.runContainer.setVisible(false); this.runContainer.setVisible(false);
globalScene.loadImage("encounter_exclaim", "mystery-encounters"); globalScene.loadImage("encounter_exclaim", "mystery-encounters");
} }
@ -117,7 +117,7 @@ export class RunInfoUiHandler extends UiHandler {
// Creates Header and adds to this.runContainer // Creates Header and adds to this.runContainer
this.addHeader(); this.addHeader();
this.statsBgWidth = (globalScene.game.canvas.width / 6 - 2) / 3; this.statsBgWidth = (globalScene.scaledCanvas.width - 2) / 3;
// Creates Run Result Container // Creates Run Result Container
this.runResultContainer = globalScene.add.container(0, 24); this.runResultContainer = globalScene.add.container(0, 24);
@ -144,7 +144,7 @@ export class RunInfoUiHandler extends UiHandler {
this.showParty(true); this.showParty(true);
this.runContainer.setInteractive( this.runContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6), new Phaser.Geom.Rectangle(0, 0, globalScene.scaledCanvas.width, globalScene.scaledCanvas.height),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
this.getUi().bringToTop(this.runContainer); this.getUi().bringToTop(this.runContainer);
@ -171,7 +171,7 @@ export class RunInfoUiHandler extends UiHandler {
* It does not check if the run has any PokemonHeldItemModifiers though. * It does not check if the run has any PokemonHeldItemModifiers though.
*/ */
private addHeader() { private addHeader() {
const headerBg = addWindow(0, 0, globalScene.game.canvas.width / 6 - 2, 24); const headerBg = addWindow(0, 0, globalScene.scaledCanvas.width - 2, 24);
headerBg.setOrigin(0, 0); headerBg.setOrigin(0, 0);
this.runContainer.add(headerBg); this.runContainer.add(headerBg);
if (this.runInfo.trainerItems.length !== 0) { if (this.runInfo.trainerItems.length !== 0) {
@ -696,11 +696,11 @@ export class RunInfoUiHandler extends UiHandler {
rules.push(i18next.t("challenges:inverseBattle.shortName")); rules.push(i18next.t("challenges:inverseBattle.shortName"));
break; break;
default: { default: {
const localisationKey = Challenges[this.runInfo.challenges[i].id] const localizationKey = Challenges[this.runInfo.challenges[i].id]
.split("_") .split("_")
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase())) .map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
.join(""); .join("");
rules.push(i18next.t(`challenges:${localisationKey}.name`)); rules.push(i18next.t(`challenges:${localizationKey}.name`));
break; break;
} }
} }
@ -717,7 +717,7 @@ export class RunInfoUiHandler extends UiHandler {
private parsePartyInfo(): void { private parsePartyInfo(): void {
const party = this.runInfo.party; const party = this.runInfo.party;
const currentLanguage = i18next.resolvedLanguage ?? "en"; const currentLanguage = i18next.resolvedLanguage ?? "en";
const windowHeight = (globalScene.game.canvas.height / 6 - 23) / 6; const windowHeight = (globalScene.scaledCanvas.height - 23) / 6;
party.forEach((p: PokemonData, i: number) => { party.forEach((p: PokemonData, i: number) => {
const pokemonInfoWindow = new RoundRectangle(globalScene, 0, 14, this.statsBgWidth * 2 + 10, windowHeight - 2, 3); const pokemonInfoWindow = new RoundRectangle(globalScene, 0, 14, this.statsBgWidth * 2 + 10, windowHeight - 2, 3);
@ -949,8 +949,8 @@ export class RunInfoUiHandler extends UiHandler {
endCard.setOrigin(0); endCard.setOrigin(0);
endCard.setScale(0.5); endCard.setScale(0.5);
const text = addTextObject( const text = addTextObject(
globalScene.game.canvas.width / 12, globalScene.scaledCanvas.width / 2,
globalScene.game.canvas.height / 6 - 16, globalScene.scaledCanvas.height - 16,
i18next.t("battle:congratulations"), i18next.t("battle:congratulations"),
TextStyle.SUMMARY, TextStyle.SUMMARY,
{ fontSize: "128px" }, { fontSize: "128px" },

View File

@ -53,14 +53,14 @@ export class SaveSlotSelectUiHandler extends MessageUiHandler {
const loadSessionBg = globalScene.add.rectangle( const loadSessionBg = globalScene.add.rectangle(
0, 0,
0, 0,
globalScene.game.canvas.width / 6, globalScene.scaledCanvas.width,
-globalScene.game.canvas.height / 6, -globalScene.scaledCanvas.height,
0x006860, 0x006860,
); );
loadSessionBg.setOrigin(0, 0); loadSessionBg.setOrigin(0, 0);
this.saveSlotSelectContainer.add(loadSessionBg); this.saveSlotSelectContainer.add(loadSessionBg);
this.sessionSlotsContainerInitialY = -globalScene.game.canvas.height / 6 + 8; this.sessionSlotsContainerInitialY = -globalScene.scaledCanvas.height + 8;
this.sessionSlotsContainer = globalScene.add.container(8, this.sessionSlotsContainerInitialY); this.sessionSlotsContainer = globalScene.add.container(8, this.sessionSlotsContainerInitialY);
this.saveSlotSelectContainer.add(this.sessionSlotsContainer); this.saveSlotSelectContainer.add(this.sessionSlotsContainer);
@ -400,7 +400,7 @@ class SessionSlot extends Phaser.GameObjects.Container {
const gameModeLabel = addTextObject( const gameModeLabel = addTextObject(
8, 8,
5, 5,
`${GameMode.getModeName(data.gameMode) || i18next.t("gameMode:unkown")} - ${i18next.t("saveSlotSelectUiHandler:wave")} ${data.waveIndex}`, `${GameMode.getModeName(data.gameMode) || i18next.t("gameMode:unknown")} - ${i18next.t("saveSlotSelectUiHandler:wave")} ${data.waveIndex}`,
TextStyle.WINDOW, TextStyle.WINDOW,
); );
this.add(gameModeLabel); this.add(gameModeLabel);

View File

@ -8,7 +8,7 @@ export class SavingIconHandler extends Phaser.GameObjects.Container {
private shown: boolean; private shown: boolean;
constructor() { constructor() {
super(globalScene, globalScene.game.canvas.width / 6 - 4, globalScene.game.canvas.height / 6 - 4); super(globalScene, globalScene.scaledCanvas.width - 4, globalScene.scaledCanvas.height - 4);
} }
setup(): void { setup(): void {

View File

@ -8,7 +8,7 @@ import { UiHandler } from "#ui/ui-handler";
import { addWindow } from "#ui/ui-theme"; import { addWindow } from "#ui/ui-theme";
import i18next from "i18next"; import i18next from "i18next";
type CancelFn = (succes?: boolean) => boolean; type CancelFn = (success?: boolean) => boolean;
/** /**
* Abstract class for handling UI elements related to button bindings. * Abstract class for handling UI elements related to button bindings.
@ -73,8 +73,8 @@ export abstract class AbstractBindingUiHandler extends UiHandler {
// Setup backgrounds and text objects for UI. // Setup backgrounds and text objects for UI.
this.titleBg = addWindow( this.titleBg = addWindow(
globalScene.game.canvas.width / 6 - this.getWindowWidth(), globalScene.scaledCanvas.width - this.getWindowWidth(),
-(globalScene.game.canvas.height / 6) + 28 + 21, -globalScene.scaledCanvas.height + 28 + 21,
this.getWindowWidth(), this.getWindowWidth(),
24, 24,
); );
@ -82,8 +82,8 @@ export abstract class AbstractBindingUiHandler extends UiHandler {
this.optionSelectContainer.add(this.titleBg); this.optionSelectContainer.add(this.titleBg);
this.actionBg = addWindow( this.actionBg = addWindow(
globalScene.game.canvas.width / 6 - this.getWindowWidth(), globalScene.scaledCanvas.width - this.getWindowWidth(),
-(globalScene.game.canvas.height / 6) + this.getWindowHeight() + 28 + 21 + 21, -globalScene.scaledCanvas.height + this.getWindowHeight() + 28 + 21 + 21,
this.getWindowWidth(), this.getWindowWidth(),
24, 24,
); );
@ -102,8 +102,8 @@ export abstract class AbstractBindingUiHandler extends UiHandler {
this.optionSelectContainer.add(this.timerText); this.optionSelectContainer.add(this.timerText);
this.optionSelectBg = addWindow( this.optionSelectBg = addWindow(
globalScene.game.canvas.width / 6 - this.getWindowWidth(), globalScene.scaledCanvas.width - this.getWindowWidth(),
-(globalScene.game.canvas.height / 6) + this.getWindowHeight() + 28, -globalScene.scaledCanvas.height + this.getWindowHeight() + 28,
this.getWindowWidth(), this.getWindowWidth(),
this.getWindowHeight(), this.getWindowHeight(),
); );

Some files were not shown because too many files have changed in this diff Show More