Merge branch 'beta' into waveData

This commit is contained in:
Bertie690 2025-04-29 18:14:30 -04:00 committed by GitHub
commit efb079c58e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 831 additions and 459 deletions

View File

@ -9,7 +9,7 @@
"build": "vite build", "build": "vite build",
"build:beta": "vite build --mode beta", "build:beta": "vite build --mode beta",
"preview": "vite preview", "preview": "vite preview",
"test": "vitest run", "test": "vitest run --no-isolate",
"test:cov": "vitest run --coverage --no-isolate", "test:cov": "vitest run --coverage --no-isolate",
"test:watch": "vitest watch --coverage --no-isolate", "test:watch": "vitest watch --coverage --no-isolate",
"test:silent": "vitest run --silent --no-isolate", "test:silent": "vitest run --silent --no-isolate",

View File

@ -19383,6 +19383,44 @@ export const pokemonFormLevelMoves: PokemonSpeciesFormLevelMoves = {
[ 100, Moves.SEED_FLARE ], [ 100, Moves.SEED_FLARE ],
] ]
}, },
[Species.BASCULIN]: {
1: [
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.WATER_GUN ],
[ 4, Moves.TACKLE ],
[ 8, Moves.FLAIL ],
[ 12, Moves.AQUA_JET ],
[ 16, Moves.BITE ],
[ 20, Moves.SCARY_FACE ],
[ 24, Moves.HEADBUTT ],
[ 28, Moves.SOAK ],
[ 32, Moves.CRUNCH ],
[ 36, Moves.TAKE_DOWN ],
[ 40, Moves.FINAL_GAMBIT ],
[ 44, Moves.WAVE_CRASH ],
[ 48, Moves.THRASH ],
[ 52, Moves.DOUBLE_EDGE ],
[ 56, Moves.HEAD_SMASH ],
],
2: [
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.WATER_GUN ],
[ 4, Moves.TACKLE ],
[ 8, Moves.FLAIL ],
[ 12, Moves.AQUA_JET ],
[ 16, Moves.BITE ],
[ 20, Moves.SCARY_FACE ],
[ 24, Moves.HEADBUTT ],
[ 28, Moves.SOAK ],
[ 32, Moves.CRUNCH ],
[ 36, Moves.TAKE_DOWN ],
[ 40, Moves.UPROAR ],
[ 44, Moves.WAVE_CRASH ],
[ 48, Moves.THRASH ],
[ 52, Moves.DOUBLE_EDGE ],
[ 56, Moves.HEAD_SMASH ],
]
},
[Species.KYUREM]: { [Species.KYUREM]: {
1: [ 1: [
[ 1, Moves.DRAGON_BREATH ], [ 1, Moves.DRAGON_BREATH ],

View File

@ -4,12 +4,19 @@ export type SignatureSpecies = {
[key in string]: (Species | Species[])[]; [key in string]: (Species | Species[])[];
}; };
/* /**
* The signature species for each Gym Leader, Elite Four member, and Champion. * The signature species for each Gym Leader, Elite Four member, and Champion.
* The key is the trainer type, and the value is an array of Species or Species arrays. * The key is the trainer type, and the value is an array of Species or Species arrays.
* This is in a separate const so it can be accessed from other places and not just the trainerConfigs * This is in a separate const so it can be accessed from other places and not just the trainerConfigs
*
* @remarks
* The `Proxy` object allows us to define a handler that will intercept
* the property access and return an empty array if the property does not exist in the object.
*
* This means that accessing `signatureSpecies` will not throw an error if the property does not exist,
* but instead default to an empty array.
*/ */
export const signatureSpecies: SignatureSpecies = { export const signatureSpecies: SignatureSpecies = new Proxy({
// Gym Leaders- Kanto // Gym Leaders- Kanto
BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL], BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL],
MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS], MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS],
@ -92,71 +99,8 @@ export const signatureSpecies: SignatureSpecies = {
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu
}, {
// Elite Four- Kanto get(target, prop: string) {
LORELEI: [ return target[prop as keyof SignatureSpecies] ?? [];
Species.JYNX, }
[Species.SLOWBRO, Species.GALAR_SLOWBRO], });
Species.LAPRAS,
[Species.CLOYSTER, Species.ALOLA_SANDSLASH],
],
BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]],
AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK],
LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR],
// Elite Four- Johto (Bruno included)
WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR],
KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL],
KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE],
// Elite Four- Hoenn
SIDNEY: [
[Species.SHIFTRY, Species.CACTURNE],
[Species.SHARPEDO, Species.CRAWDAUNT],
Species.ABSOL,
Species.MIGHTYENA,
],
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]],
GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW],
DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA],
// Elite Four- Sinnoh
AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION],
BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR],
FLINT: [
[Species.RAPIDASH, Species.FLAREON],
Species.MAGMORTAR,
[Species.STEELIX, Species.LOPUNNY],
Species.INFERNAPE,
], // Tera Fire Steelix or Lopunny
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]],
// Elite Four- Unova
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT],
MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK],
GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE],
CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS],
// Elite Four- Kalos
MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME],
SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE],
WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH],
DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN],
// Elite Four- Alola
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]],
MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO],
OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC],
ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND],
KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
// Elite Four- Galar
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL],
NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW],
BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP],
ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR],
RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON],
// Elite Four- Paldea
RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire
POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton
LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio
HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur
// Elite Four- BBL
CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom
AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross
LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill
DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon
};

View File

@ -5724,7 +5724,6 @@ export const tmSpecies: TmSpecies = {
Species.SCOLIPEDE, Species.SCOLIPEDE,
Species.WHIMSICOTT, Species.WHIMSICOTT,
Species.LILLIGANT, Species.LILLIGANT,
Species.BASCULIN,
Species.KROOKODILE, Species.KROOKODILE,
Species.DARMANITAN, Species.DARMANITAN,
Species.CRUSTLE, Species.CRUSTLE,
@ -6023,6 +6022,11 @@ export const tmSpecies: TmSpecies = {
Species.HISUI_DECIDUEYE, Species.HISUI_DECIDUEYE,
Species.PALDEA_TAUROS, Species.PALDEA_TAUROS,
Species.BLOODMOON_URSALUNA, Species.BLOODMOON_URSALUNA,
[
Species.BASCULIN,
"blue-striped",
"red-striped",
]
], ],
[Moves.LOW_KICK]: [ [Moves.LOW_KICK]: [
Species.SANDSHREW, Species.SANDSHREW,
@ -19335,7 +19339,6 @@ export const tmSpecies: TmSpecies = {
Species.CONKELDURR, Species.CONKELDURR,
Species.THROH, Species.THROH,
Species.SAWK, Species.SAWK,
Species.BASCULIN,
Species.DARMANITAN, Species.DARMANITAN,
Species.SCRAFTY, Species.SCRAFTY,
Species.ESCAVALIER, Species.ESCAVALIER,
@ -19449,6 +19452,11 @@ export const tmSpecies: TmSpecies = {
Species.HISUI_BRAVIARY, Species.HISUI_BRAVIARY,
Species.HISUI_DECIDUEYE, Species.HISUI_DECIDUEYE,
Species.PALDEA_TAUROS, Species.PALDEA_TAUROS,
[
Species.BASCULIN,
"blue-striped",
"red-striped",
],
], ],
[Moves.SPITE]: [ [Moves.SPITE]: [
Species.EKANS, Species.EKANS,
@ -51341,7 +51349,6 @@ export const tmSpecies: TmSpecies = {
Species.SCOLIPEDE, Species.SCOLIPEDE,
Species.WHIMSICOTT, Species.WHIMSICOTT,
Species.LILLIGANT, Species.LILLIGANT,
Species.BASCULIN,
Species.KROOKODILE, Species.KROOKODILE,
Species.DARMANITAN, Species.DARMANITAN,
Species.CRUSTLE, Species.CRUSTLE,
@ -51655,6 +51662,11 @@ export const tmSpecies: TmSpecies = {
Species.HISUI_DECIDUEYE, Species.HISUI_DECIDUEYE,
Species.PALDEA_TAUROS, Species.PALDEA_TAUROS,
Species.BLOODMOON_URSALUNA, Species.BLOODMOON_URSALUNA,
[
Species.BASCULIN,
"blue-striped",
"red-striped",
],
], ],
[Moves.NASTY_PLOT]: [ [Moves.NASTY_PLOT]: [
Species.PIKACHU, Species.PIKACHU,

View File

@ -2463,7 +2463,7 @@ export class StatusEffectAttr extends MoveEffectAttr {
return false; return false;
} }
if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0)) if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0))
&& pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus)) { && pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus, false)) {
applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect); applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect);
return true; return true;
} }

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@ import BattleInfo, {
import type Move from "#app/data/moves/move"; import type Move from "#app/data/moves/move";
import { import {
HighCritAttr, HighCritAttr,
StatChangeBeforeDmgCalcAttr,
HitsTagAttr, HitsTagAttr,
applyMoveAttrs, applyMoveAttrs,
FixedDamageAttr, FixedDamageAttr,
@ -70,10 +69,8 @@ import {
EFFECTIVE_STATS, EFFECTIVE_STATS,
} from "#enums/stat"; } from "#enums/stat";
import { import {
DamageMoneyRewardModifier,
EnemyDamageBoosterModifier, EnemyDamageBoosterModifier,
EnemyDamageReducerModifier, EnemyDamageReducerModifier,
EnemyEndureChanceModifier,
EnemyFusionChanceModifier, EnemyFusionChanceModifier,
HiddenAbilityRateBoosterModifier, HiddenAbilityRateBoosterModifier,
BaseStatModifier, BaseStatModifier,
@ -119,7 +116,6 @@ import {
TypeImmuneTag, TypeImmuneTag,
getBattlerTag, getBattlerTag,
SemiInvulnerableTag, SemiInvulnerableTag,
TypeBoostTag,
MoveRestrictionBattlerTag, MoveRestrictionBattlerTag,
ExposedTag, ExposedTag,
DragonCheerTag, DragonCheerTag,
@ -189,7 +185,7 @@ import {
PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr, PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr,
applyAllyStatMultiplierAbAttrs, applyAllyStatMultiplierAbAttrs,
AllyStatMultiplierAbAttr, AllyStatMultiplierAbAttr,
MoveAbilityBypassAbAttr MoveAbilityBypassAbAttr,
} from "#app/data/abilities/ability"; } from "#app/data/abilities/ability";
import { allAbilities } from "#app/data/data-lists"; import { allAbilities } from "#app/data/data-lists";
import type PokemonData from "#app/system/pokemon-data"; import type PokemonData from "#app/system/pokemon-data";
@ -203,7 +199,7 @@ import {
EVOLVE_MOVE, EVOLVE_MOVE,
RELEARN_MOVE, RELEARN_MOVE,
} from "#app/data/balance/pokemon-level-moves"; } from "#app/data/balance/pokemon-level-moves";
import { DamageAchv, achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data"; import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data";
import { DexAttr } from "#app/system/game-data"; import { DexAttr } from "#app/system/game-data";
import { import {
@ -249,7 +245,7 @@ import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";
import { SwitchType } from "#enums/switch-type"; import { SwitchType } from "#enums/switch-type";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
import {getStatusEffectOverlapText } from "#app/data/status-effect"; import { getStatusEffectOverlapText } from "#app/data/status-effect";
import { import {
BASE_HIDDEN_ABILITY_CHANCE, BASE_HIDDEN_ABILITY_CHANCE,
BASE_SHINY_CHANCE, BASE_SHINY_CHANCE,
@ -5551,9 +5547,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
sourcePokemon: Pokemon | null = null, sourcePokemon: Pokemon | null = null,
turnsRemaining = 0, turnsRemaining = 0,
sourceText: string | null = null, sourceText: string | null = null,
overrideStatus?: boolean overrideStatus?: boolean,
quiet = true,
): boolean { ): boolean {
if (!this.canSetStatus(effect, false, overrideStatus, sourcePokemon)) { if (!this.canSetStatus(effect, quiet, overrideStatus, sourcePokemon)) {
return false; return false;
} }
if (this.isFainted() && effect !== StatusEffect.FAINT) { if (this.isFainted() && effect !== StatusEffect.FAINT) {
@ -7059,6 +7056,15 @@ export class EnemyPokemon extends Pokemon {
} }
speciesId = prevolution; speciesId = prevolution;
} }
if (this.hasTrainer() && globalScene.currentBattle) {
const { waveIndex } = globalScene.currentBattle;
const ivs: number[] = [];
while (ivs.length < 6) {
ivs.push(this.randSeedIntRange(Math.floor(waveIndex / 10), 31));
}
this.ivs = ivs;
}
} }
this.aiType = this.aiType =

View File

@ -23,18 +23,18 @@ describe("Abilities - Illusion", () => {
beforeEach(() => { beforeEach(() => {
game = new GameManager(phaserGame); game = new GameManager(phaserGame);
game.override.battleStyle("single"); game.override
game.override.enemySpecies(Species.ZORUA); .battleStyle("single")
game.override.enemyAbility(Abilities.ILLUSION); .enemySpecies(Species.ZORUA)
game.override.enemyMoveset(Moves.TACKLE); .enemyAbility(Abilities.ILLUSION)
game.override.enemyHeldItems([{ name: "WIDE_LENS", count: 3 }]); .enemyMoveset(Moves.TACKLE)
.enemyHeldItems([{ name: "WIDE_LENS", count: 3 }])
game.override.moveset([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE]); .moveset([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE])
game.override.startingHeldItems([{ name: "WIDE_LENS", count: 3 }]); .startingHeldItems([{ name: "WIDE_LENS", count: 3 }]);
}); });
it("creates illusion at the start", async () => { it("creates illusion at the start", async () => {
await game.classicMode.startBattle([Species.ZOROARK, Species.AXEW]); await game.classicMode.startBattle([Species.ZOROARK, Species.FEEBAS]);
const zoroark = game.scene.getPlayerPokemon()!; const zoroark = game.scene.getPlayerPokemon()!;
const zorua = game.scene.getEnemyPokemon()!; const zorua = game.scene.getEnemyPokemon()!;
@ -43,7 +43,7 @@ describe("Abilities - Illusion", () => {
}); });
it("break after receiving damaging move", async () => { it("break after receiving damaging move", async () => {
await game.classicMode.startBattle([Species.AXEW]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -55,7 +55,7 @@ describe("Abilities - Illusion", () => {
}); });
it("break after getting ability changed", async () => { it("break after getting ability changed", async () => {
await game.classicMode.startBattle([Species.AXEW]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.WORRY_SEED); game.move.select(Moves.WORRY_SEED);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -76,7 +76,7 @@ describe("Abilities - Illusion", () => {
it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => { it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => {
game.override.enemyMoveset([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE]); game.override.enemyMoveset([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE]);
await game.classicMode.startBattle([Species.ZOROARK, Species.AXEW]); await game.classicMode.startBattle([Species.ZOROARK, Species.FEEBAS]);
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
const zoroark = game.scene.getPlayerPokemon()!; const zoroark = game.scene.getPlayerPokemon()!;

View File

@ -209,4 +209,19 @@ describe("Spec - Pokemon", () => {
expect(types[1]).toBe(PokemonType.DARK); expect(types[1]).toBe(PokemonType.DARK);
}); });
}); });
it.each([5, 25, 55, 95, 145, 195])(
"should set minimum IVs for enemy trainer pokemon based on wave (%i)",
async wave => {
game.override.startingWave(wave);
await game.classicMode.startBattle([Species.FEEBAS]);
const { waveIndex } = game.scene.currentBattle;
for (const pokemon of game.scene.getEnemyParty()) {
for (const index in pokemon.ivs) {
expect(pokemon.ivs[index]).toBeGreaterThanOrEqual(Math.floor(waveIndex / 10));
}
}
},
);
}); });