From c9ca46daf641633b61988d46cbaff46bcce5ea13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 9 Jan 2025 06:40:06 +0000 Subject: [PATCH 01/17] Refactor details code --- data/abilities.ts | 3 +-- data/mods/gen7pokebilities/scripts.ts | 3 +-- data/mods/gen9ssb/abilities.ts | 3 +-- data/mods/gen9ssb/moves.ts | 6 ++---- data/mods/gen9ssb/scripts.ts | 6 ++---- data/mods/mixandmega/scripts.ts | 6 ++---- data/mods/pokebilities/scripts.ts | 3 +-- sim/battle-actions.ts | 2 +- sim/battle.ts | 3 +-- sim/pokemon.ts | 28 ++++++++++++++------------- 10 files changed, 27 insertions(+), 36 deletions(-) diff --git a/data/abilities.ts b/data/abilities.ts index 8048f5204e6c..4a2d0449a685 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -2030,8 +2030,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.illusion) { this.debug('illusion cleared'); pokemon.illusion = null; - const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + const details = pokemon.getSimpleDetails(); this.add('replace', pokemon, details); this.add('-end', pokemon, 'Illusion'); if (this.ruleTable.has('illusionlevelmod')) { diff --git a/data/mods/gen7pokebilities/scripts.ts b/data/mods/gen7pokebilities/scripts.ts index b0199e4bad6b..b74ad6949f05 100644 --- a/data/mods/gen7pokebilities/scripts.ts +++ b/data/mods/gen7pokebilities/scripts.ts @@ -169,8 +169,7 @@ export const Scripts: ModdedBattleScriptsData = { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getSimpleDetails(); this.battle.add('detailschange', this, (this.illusion || this).details); if (source.effectType === 'Item') { this.canTerastallize = null; // National Dex behavior diff --git a/data/mods/gen9ssb/abilities.ts b/data/mods/gen9ssb/abilities.ts index badd191ed69f..11e74ec300a7 100644 --- a/data/mods/gen9ssb/abilities.ts +++ b/data/mods/gen9ssb/abilities.ts @@ -1755,8 +1755,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa target.clearBoosts(); this.add('-clearboost', target); this.boost({atk: 1, def: -1, spa: 1, spd: -1, spe: 1}); - const details = target.species.name + (target.level === 100 ? '' : ', L' + target.level) + - (target.gender === '' ? '' : ', ' + target.gender) + (target.set.shiny ? ', shiny' : ''); + const details = target.getSimpleDetails(); target.details = details; this.add('replace', target, details); } diff --git a/data/mods/gen9ssb/moves.ts b/data/mods/gen9ssb/moves.ts index 35c1284202f1..fd2d9e278187 100644 --- a/data/mods/gen9ssb/moves.ts +++ b/data/mods/gen9ssb/moves.ts @@ -4236,8 +4236,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { pokemon.cureStatus(); this.boost({def: 1, spd: 1}); (pokemon as any).level += 5; - pokemon.details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getSimpleDetails(); this.add('-anim', pokemon, 'Geomancy', pokemon); this.add('replace', pokemon, pokemon.details); this.add('-message', `${pokemon.name} gained 5 levels!`); @@ -5905,8 +5904,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { this.add(`c:|${getName((source.illusion || source).name)}|lol never do that ever again thanks`); this.add('custom', '-endterastallize', pokemon); delete pokemon.terastallized; - const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + const details = pokemon.getSimpleDetails(); this.add('detailschange', pokemon, details); } }, diff --git a/data/mods/gen9ssb/scripts.ts b/data/mods/gen9ssb/scripts.ts index 3fe0e55a73b8..98f8877ce552 100644 --- a/data/mods/gen9ssb/scripts.ts +++ b/data/mods/gen9ssb/scripts.ts @@ -89,8 +89,7 @@ export function changeSet(context: Battle, pokemon: Pokemon, newSet: SSBSet, cha pokemon.teraType = newSet.teraType === 'Any' ? context.sample(allTypes) : Array.isArray(newSet.teraType) ? context.sample(newSet.teraType) : newSet.teraType; } - const details = pokemon.species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + const details = pokemon.getSimpleDetails(); if (oldShiny !== pokemon.set.shiny || oldGender !== pokemon.gender) context.add('replace', pokemon, details); if (changeAbility) pokemon.setAbility(newSet.ability as string, undefined, true); @@ -386,8 +385,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getSimpleDetails(); // pokemon.setAbility(species.abilities['0'], null, true); // pokemon.baseAbility = pokemon.ability; diff --git a/data/mods/mixandmega/scripts.ts b/data/mods/mixandmega/scripts.ts index a687f445ba51..2bed1943aac2 100644 --- a/data/mods/mixandmega/scripts.ts +++ b/data/mods/mixandmega/scripts.ts @@ -67,8 +67,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getSimpleDetails(); pokemon.ability = this.toID(species.abilities['0']); pokemon.baseAbility = pokemon.ability; } @@ -118,8 +117,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getSimpleDetails(); pokemon.ability = this.toID(species.abilities['0']); pokemon.baseAbility = pokemon.ability; diff --git a/data/mods/pokebilities/scripts.ts b/data/mods/pokebilities/scripts.ts index e9564991a2ac..ecc2cf98647d 100644 --- a/data/mods/pokebilities/scripts.ts +++ b/data/mods/pokebilities/scripts.ts @@ -169,8 +169,7 @@ export const Scripts: ModdedBattleScriptsData = { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getSimpleDetails(); this.battle.add('detailschange', this, (this.illusion || this).details); if (source.effectType === 'Item') { this.canTerastallize = null; // National Dex behavior diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 4128c3f85d54..ad8e9eafd707 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -1959,7 +1959,7 @@ export class BattleActions { } if (pokemon.species.baseSpecies === 'Morpeko') { pokemon.baseSpecies = pokemon.species; - pokemon.details = pokemon.details.replace('Morpeko', pokemon.species.name); + pokemon.details = pokemon.getSimpleDetails(); } this.battle.runEvent('AfterTerastallization', pokemon); } diff --git a/sim/battle.ts b/sim/battle.ts index dba8f006b52c..c640928ae22b 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2494,8 +2494,7 @@ export class Battle { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = species.name + (pokemon.level === 100 ? '' : ', L' + pokemon.level) + - (pokemon.gender === '' ? '' : ', ' + pokemon.gender) + (pokemon.set.shiny ? ', shiny' : ''); + pokemon.details = pokemon.getSimpleDetails(); pokemon.setAbility(species.abilities['0'], null, true); pokemon.baseAbility = pokemon.ability; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index bb954c86b7d5..18199a15b0d2 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -353,8 +353,7 @@ export class Pokemon { this.position = 0; let displayedSpeciesName = this.species.name; if (displayedSpeciesName === 'Greninja-Bond') displayedSpeciesName = 'Greninja'; - this.details = displayedSpeciesName + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getSimpleDetails(displayedSpeciesName); this.status = ''; this.statusState = {}; @@ -509,17 +508,21 @@ export class Pokemon { return this.isActive ? this.getSlot() + fullname.slice(2) : fullname; } + getSimpleDetails(displayedSpeciesName: string | null = null, illusionDetails = false) { + let name = displayedSpeciesName || this.species.name; + let level = this.level; + if (illusionDetails && this.illusion) { + if (this.battle.ruleTable.has('illusionlevelmod')) level = this.illusion.level; + name = this.illusion.species.name; + if (name === 'Greninja-Bond') name = 'Greninja'; + } + return name + (level === 100 ? '' : ', L' + level) + + (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + } + getDetails = () => { const health = this.getHealth(); - let details = this.details; - if (this.illusion) { - const level = this.battle.ruleTable.has('illusionlevelmod') ? this.illusion.level : this.level; - let displayedSpeciesName = this.illusion.species.name; - if (displayedSpeciesName === 'Greninja-Bond') displayedSpeciesName = 'Greninja'; - const illusionDetails = displayedSpeciesName + (level === 100 ? '' : ', L' + level) + - (this.illusion.gender === '' ? '' : ', ' + this.illusion.gender) + (this.illusion.set.shiny ? ', shiny' : ''); - details = illusionDetails; - } + let details = this.getSimpleDetails(null, true); if (this.terastallized) details += `, tera:${this.terastallized}`; return {side: health.side, secret: `${details}|${health.secret}`, shared: `${details}|${health.shared}`}; }; @@ -1387,8 +1390,7 @@ export class Pokemon { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = species.name + (this.level === 100 ? '' : ', L' + this.level) + - (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); + this.details = this.getSimpleDetails(); let details = (this.illusion || this).details; if (this.terastallized) details += `, tera:${this.terastallized}`; this.battle.add('detailschange', this, details); From 375ecc077ba578c747e485f54ba5dc4f50ee158d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 9 Jan 2025 06:58:58 +0000 Subject: [PATCH 02/17] Fainted forme regression --- sim/battle.ts | 11 ++++++ sim/pokemon.ts | 3 +- test/sim/moves/revivalblessing.js | 64 +++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/sim/battle.ts b/sim/battle.ts index c640928ae22b..1b033e3db1db 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2375,6 +2375,17 @@ export class Battle { pokemon.illusion = null; pokemon.isActive = false; pokemon.isStarted = false; + if ( + (pokemon.terastallized && ['Ogerpon', 'Terapagos'].includes(pokemon.baseSpecies.baseSpecies)) || + pokemon.baseSpecies.isMega + ) { + const baseSpecies = this.dex.species.get(pokemon.set.species || pokemon.set.name); + pokemon.setSpecies(baseSpecies); + pokemon.baseSpecies = baseSpecies; + pokemon.baseAbility = pokemon.ability = toID(pokemon.set.ability); + pokemon.details = pokemon.getSimpleDetails(); + this.add('detailschange', pokemon, (pokemon.illusion || pokemon).details, '[silent]'); + } delete pokemon.terastallized; pokemon.side.faintedThisTurn = pokemon; if (this.faintQueue.length >= faintQueueLeft) checkWin = true; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 18199a15b0d2..2d58191e2c00 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -1323,8 +1323,7 @@ export class Pokemon { // Pokemon transformed into Ogerpon cannot Terastallize // restoring their ability to tera after they untransform is handled ELSEWHERE - if (this.species.baseSpecies === 'Ogerpon' && this.canTerastallize) this.canTerastallize = false; - if (this.species.baseSpecies === 'Terapagos' && this.canTerastallize) this.canTerastallize = false; + if (['Ogerpon', 'Terapagos'].includes(this.species.baseSpecies) && this.canTerastallize) this.canTerastallize = false; return true; } diff --git a/test/sim/moves/revivalblessing.js b/test/sim/moves/revivalblessing.js index 20380a11917f..9f00b2d25dab 100644 --- a/test/sim/moves/revivalblessing.js +++ b/test/sim/moves/revivalblessing.js @@ -82,4 +82,68 @@ describe('Revival Blessing', function () { battle.makeChoices('switch 2', ''); assert.equal(battle.p1.active[1].boosts.evasion, 0, "Lycanroc should not have used Double Team"); }); + + it(`should revert Ogerpon-Tera back to Ogerpon after being revived`, () => { + battle = common.createBattle([[ + {species: 'ogerponwellspring', ability: 'waterabsorb', moves: ['memento']}, + {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const ogerpon = battle.p1.pokemon[0]; + battle.makeChoices('move memento terastallize', 'auto'); + battle.makeChoices('switch pawmot', ''); + battle.makeChoices(); + battle.makeChoices('switch 2', ''); + assert.species(ogerpon, 'Ogerpon-Wellspring'); + assert.equal(ogerpon.ability, 'waterabsorb', `Expected ${ogerpon}'ability to be Water Absorb, not ${ogerpon.baseAbility}`); + }); + + it(`shouldn't revert Terapagos-Terastal back to Terapagos after being revived`, () => { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento']}, + {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const terapagos = battle.p1.active[0]; + battle.makeChoices(); + battle.makeChoices('switch pawmot', ''); + battle.makeChoices(); + battle.makeChoices('switch 2', ''); + assert.species(terapagos, 'Terapagos-Terastal'); + assert.equal(terapagos.ability, 'terashell', `Expected ${terapagos}'ability to be Tera Shell, not ${terapagos.ability}`); + }); + + it(`should revert Terapagos-Stellar back to Terapagos after being revived`, () => { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento']}, + {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const terapagos = battle.p1.active[0]; + battle.makeChoices('move memento terastallize', 'auto'); + battle.makeChoices('switch pawmot', ''); + battle.makeChoices(); + battle.makeChoices('switch 2', ''); + assert.species(terapagos, 'Terapagos'); + assert.equal(terapagos.ability, 'terashift', `Expected ${terapagos}'ability to be Tera Shift, not ${terapagos.ability}`); + }); + + it(`should revert Mega Evolutions back to their original form after being revived`, () => { + battle = common.createBattle([[ + {species: 'alakazam', ability: 'synchronize', item: 'alakazite', moves: ['memento']}, + {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const alakazam = battle.p1.pokemon[0]; + battle.makeChoices('move memento mega', 'auto'); + battle.makeChoices('switch pawmot', ''); + battle.makeChoices(); + battle.makeChoices('switch 2', ''); + assert.species(alakazam, 'Alakazam'); + assert.equal(alakazam.ability, 'synchronize', `Expected ${alakazam}'ability to be Synchronize, not ${alakazam.baseAbility}`); + }); }); From 5bee8e73ea68d84a83684e51feda42ff3b06b0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 9 Jan 2025 07:56:31 +0000 Subject: [PATCH 03/17] More logical tests --- test/sim/misc/terapagos.js | 26 +++++++++++++ test/sim/moves/revivalblessing.js | 64 ------------------------------- 2 files changed, 26 insertions(+), 64 deletions(-) diff --git a/test/sim/misc/terapagos.js b/test/sim/misc/terapagos.js index a1276f21a290..23dd92a33895 100644 --- a/test/sim/misc/terapagos.js +++ b/test/sim/misc/terapagos.js @@ -24,6 +24,32 @@ describe(`Terapagos`, function () { assert.false(!!ditto.terastallized); }); + it(`shouldn't revert to Terapagos-Normal if it faints while Terastallized`, function () { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const terapagos = battle.p1.active[0]; + battle.makeChoices(); + assert.species(terapagos, 'Terapagos-Terastal'); + assert.equal(terapagos.ability, 'terashell', `Expected ${terapagos}'ability to be Tera Shell, not ${terapagos.ability}`); + }); + + it(`should revert to Terapagos-Normal if it faints while Terastallized`, function () { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const terapagos = battle.p1.active[0]; + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(terapagos, 'Terapagos'); + assert.equal(terapagos.ability, 'terashift', `Expected ${terapagos}'ability to be Tera Shift, not ${terapagos.ability}`); + }); + it(`[Hackmons] should not cause Terapagos-Terastal to become Terapagos-Stellar if the user is Transformed`, function () { battle = common.createBattle([[ {species: 'terapagos', ability: 'terashift', moves: ['transform'], teraType: 'Stellar'}, diff --git a/test/sim/moves/revivalblessing.js b/test/sim/moves/revivalblessing.js index 9f00b2d25dab..20380a11917f 100644 --- a/test/sim/moves/revivalblessing.js +++ b/test/sim/moves/revivalblessing.js @@ -82,68 +82,4 @@ describe('Revival Blessing', function () { battle.makeChoices('switch 2', ''); assert.equal(battle.p1.active[1].boosts.evasion, 0, "Lycanroc should not have used Double Team"); }); - - it(`should revert Ogerpon-Tera back to Ogerpon after being revived`, () => { - battle = common.createBattle([[ - {species: 'ogerponwellspring', ability: 'waterabsorb', moves: ['memento']}, - {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, - ], [ - {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, - ]]); - const ogerpon = battle.p1.pokemon[0]; - battle.makeChoices('move memento terastallize', 'auto'); - battle.makeChoices('switch pawmot', ''); - battle.makeChoices(); - battle.makeChoices('switch 2', ''); - assert.species(ogerpon, 'Ogerpon-Wellspring'); - assert.equal(ogerpon.ability, 'waterabsorb', `Expected ${ogerpon}'ability to be Water Absorb, not ${ogerpon.baseAbility}`); - }); - - it(`shouldn't revert Terapagos-Terastal back to Terapagos after being revived`, () => { - battle = common.createBattle([[ - {species: 'terapagos', ability: 'terashift', moves: ['memento']}, - {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, - ], [ - {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, - ]]); - const terapagos = battle.p1.active[0]; - battle.makeChoices(); - battle.makeChoices('switch pawmot', ''); - battle.makeChoices(); - battle.makeChoices('switch 2', ''); - assert.species(terapagos, 'Terapagos-Terastal'); - assert.equal(terapagos.ability, 'terashell', `Expected ${terapagos}'ability to be Tera Shell, not ${terapagos.ability}`); - }); - - it(`should revert Terapagos-Stellar back to Terapagos after being revived`, () => { - battle = common.createBattle([[ - {species: 'terapagos', ability: 'terashift', moves: ['memento']}, - {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, - ], [ - {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, - ]]); - const terapagos = battle.p1.active[0]; - battle.makeChoices('move memento terastallize', 'auto'); - battle.makeChoices('switch pawmot', ''); - battle.makeChoices(); - battle.makeChoices('switch 2', ''); - assert.species(terapagos, 'Terapagos'); - assert.equal(terapagos.ability, 'terashift', `Expected ${terapagos}'ability to be Tera Shift, not ${terapagos.ability}`); - }); - - it(`should revert Mega Evolutions back to their original form after being revived`, () => { - battle = common.createBattle([[ - {species: 'alakazam', ability: 'synchronize', item: 'alakazite', moves: ['memento']}, - {species: 'pawmot', ability: 'naturalcure', moves: ['revivalblessing']}, - ], [ - {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, - ]]); - const alakazam = battle.p1.pokemon[0]; - battle.makeChoices('move memento mega', 'auto'); - battle.makeChoices('switch pawmot', ''); - battle.makeChoices(); - battle.makeChoices('switch 2', ''); - assert.species(alakazam, 'Alakazam'); - assert.equal(alakazam.ability, 'synchronize', `Expected ${alakazam}'ability to be Synchronize, not ${alakazam.baseAbility}`); - }); }); From e3aa97b8b67f1e7999bb0e6fff686edc6ee85399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Thu, 9 Jan 2025 08:03:33 +0000 Subject: [PATCH 04/17] Fix test name --- test/sim/misc/terapagos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/sim/misc/terapagos.js b/test/sim/misc/terapagos.js index 23dd92a33895..64815320878f 100644 --- a/test/sim/misc/terapagos.js +++ b/test/sim/misc/terapagos.js @@ -24,7 +24,7 @@ describe(`Terapagos`, function () { assert.false(!!ditto.terastallized); }); - it(`shouldn't revert to Terapagos-Normal if it faints while Terastallized`, function () { + it(`shouldn't revert to Terapagos-Normal if it faints while not Terastallized`, function () { battle = common.createBattle([[ {species: 'terapagos', ability: 'terashift', moves: ['memento']}, {species: 'darkrai', moves: ['darkpulse']}, From f4fbc24022a23b5baf7130e28af28fc58bb0153a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= <80102738+andrebastosdias@users.noreply.github.com> Date: Thu, 9 Jan 2025 10:07:41 +0000 Subject: [PATCH 05/17] Simplify details Co-authored-by: pyuk-bot --- sim/battle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/battle.ts b/sim/battle.ts index 1b033e3db1db..9e9224a7a119 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2384,7 +2384,7 @@ export class Battle { pokemon.baseSpecies = baseSpecies; pokemon.baseAbility = pokemon.ability = toID(pokemon.set.ability); pokemon.details = pokemon.getSimpleDetails(); - this.add('detailschange', pokemon, (pokemon.illusion || pokemon).details, '[silent]'); + this.add('detailschange', pokemon, pokemon.details, '[silent]'); } delete pokemon.terastallized; pokemon.side.faintedThisTurn = pokemon; From f4891c93a620119ca957e79e2016a2a2f8e9ecbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Thu, 9 Jan 2025 10:24:14 +0000 Subject: [PATCH 06/17] Revert Morpeko --- sim/battle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/battle.ts b/sim/battle.ts index 9e9224a7a119..38d2a18cb04c 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2376,7 +2376,7 @@ export class Battle { pokemon.isActive = false; pokemon.isStarted = false; if ( - (pokemon.terastallized && ['Ogerpon', 'Terapagos'].includes(pokemon.baseSpecies.baseSpecies)) || + (pokemon.terastallized && ['Morpeko', 'Ogerpon', 'Terapagos'].includes(pokemon.baseSpecies.baseSpecies)) || pokemon.baseSpecies.isMega ) { const baseSpecies = this.dex.species.get(pokemon.set.species || pokemon.set.name); From bd62d95dc9a56bb2c7271d33782d436b726f0033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Fri, 10 Jan 2025 05:28:13 +0000 Subject: [PATCH 07/17] Add more species --- sim/battle.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sim/battle.ts b/sim/battle.ts index 38d2a18cb04c..28b426ac0dd8 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2377,7 +2377,8 @@ export class Battle { pokemon.isStarted = false; if ( (pokemon.terastallized && ['Morpeko', 'Ogerpon', 'Terapagos'].includes(pokemon.baseSpecies.baseSpecies)) || - pokemon.baseSpecies.isMega + ['Greninja-Bond', 'Necrozma-Ultra', 'Zygarde-Complete'].includes(pokemon.baseSpecies.baseSpecies) || + pokemon.baseSpecies.isMega || pokemon.baseSpecies.isPrimal ) { const baseSpecies = this.dex.species.get(pokemon.set.species || pokemon.set.name); pokemon.setSpecies(baseSpecies); From 72b7af055e6d36fc90829f0754e2f8a1d1b799af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Fri, 10 Jan 2025 12:06:11 +0000 Subject: [PATCH 08/17] Fixed with variable regressionForme --- data/abilities.ts | 2 + data/conditions.ts | 1 + sim/battle-actions.ts | 4 + sim/battle.ts | 19 +-- sim/pokemon.ts | 5 + test/assert.js | 10 ++ test/sim/misc/fainted-forme-regression.js | 150 ++++++++++++++++++++++ test/sim/misc/terapagos.js | 26 ---- 8 files changed, 179 insertions(+), 38 deletions(-) create mode 100644 test/sim/misc/fainted-forme-regression.js diff --git a/data/abilities.ts b/data/abilities.ts index 4a2d0449a685..c7492d2c057a 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -4891,6 +4891,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.species.forme !== 'Terastal') { this.add('-activate', pokemon, 'ability: Tera Shift'); pokemon.formeChange('Terapagos-Terastal', this.effect, true); + pokemon.regressionForme = null; pokemon.baseMaxhp = Math.floor(Math.floor( 2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * pokemon.level / 100 + 10); @@ -5571,6 +5572,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.baseSpecies.baseSpecies !== 'Palafin') return; if (pokemon.species.forme !== 'Hero') { pokemon.formeChange('Palafin-Hero', this.effect, true); + pokemon.regressionForme = null; } }, onSwitchIn() { diff --git a/data/conditions.ts b/data/conditions.ts index 5c0f040ac391..a0a48c341cb7 100644 --- a/data/conditions.ts +++ b/data/conditions.ts @@ -91,6 +91,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = { } if (target.species.name === 'Shaymin-Sky' && target.baseSpecies.baseSpecies === 'Shaymin') { target.formeChange('Shaymin', this.effect, true); + target.regressionForme = null; } }, onBeforeMovePriority: 10, diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index ad8e9eafd707..b48fbc163d01 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -1949,6 +1949,7 @@ export class BattleActions { } if (pokemon.species.name === 'Terapagos-Terastal' && type === 'Stellar') { pokemon.formeChange('Terapagos-Stellar', null, true); + pokemon.regressionForme = {species: this.dex.species.get('Terapagos'), ability: toID('Tera Shift')}; pokemon.baseMaxhp = Math.floor(Math.floor( 2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * pokemon.level / 100 + 10); @@ -1958,6 +1959,9 @@ export class BattleActions { this.battle.add('-heal', pokemon, pokemon.getHealth, '[silent]'); } if (pokemon.species.baseSpecies === 'Morpeko') { + if (pokemon.species.name !== 'Morpeko') { + pokemon.regressionForme = {species: pokemon.baseSpecies, ability: pokemon.baseAbility}; + } pokemon.baseSpecies = pokemon.species; pokemon.details = pokemon.getSimpleDetails(); } diff --git a/sim/battle.ts b/sim/battle.ts index 28b426ac0dd8..43286963e898 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2370,23 +2370,18 @@ export class Battle { if (pokemon.side.totalFainted < 100) pokemon.side.totalFainted++; this.runEvent('Faint', pokemon, faintData.source, faintData.effect); this.singleEvent('End', pokemon.getAbility(), pokemon.abilityState, pokemon); + if (pokemon.regressionForme) { + pokemon.baseSpecies = pokemon.regressionForme.species; + pokemon.baseAbility = pokemon.regressionForme.ability; + pokemon.details = pokemon.getSimpleDetails(pokemon.baseSpecies.name); + pokemon.regressionForme = null; + this.add('detailschange', pokemon, pokemon.details, '[silent]'); + } pokemon.clearVolatile(false); pokemon.fainted = true; pokemon.illusion = null; pokemon.isActive = false; pokemon.isStarted = false; - if ( - (pokemon.terastallized && ['Morpeko', 'Ogerpon', 'Terapagos'].includes(pokemon.baseSpecies.baseSpecies)) || - ['Greninja-Bond', 'Necrozma-Ultra', 'Zygarde-Complete'].includes(pokemon.baseSpecies.baseSpecies) || - pokemon.baseSpecies.isMega || pokemon.baseSpecies.isPrimal - ) { - const baseSpecies = this.dex.species.get(pokemon.set.species || pokemon.set.name); - pokemon.setSpecies(baseSpecies); - pokemon.baseSpecies = baseSpecies; - pokemon.baseAbility = pokemon.ability = toID(pokemon.set.ability); - pokemon.details = pokemon.getSimpleDetails(); - this.add('detailschange', pokemon, pokemon.details, '[silent]'); - } delete pokemon.terastallized; pokemon.side.faintedThisTurn = pokemon; if (this.faintQueue.length >= faintQueueLeft) checkWin = true; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 2d58191e2c00..b9ba0fc4f056 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -131,6 +131,8 @@ export class Pokemon { faintQueued: boolean; subFainted: boolean | null; + regressionForme: {species: Species, ability: ID} | null; + types: string[]; addedType: string; knownType: boolean; @@ -418,6 +420,8 @@ export class Pokemon { this.faintQueued = false; this.subFainted = null; + this.regressionForme = null; + this.types = this.baseSpecies.types; this.baseTypes = this.types; this.addedType = ''; @@ -1388,6 +1392,7 @@ export class Pokemon { const apparentSpecies = this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { + if (!this.regressionForme) this.regressionForme = {species: this.baseSpecies, ability: this.baseAbility}; this.baseSpecies = rawSpecies; this.details = this.getSimpleDetails(); let details = (this.illusion || this).details; diff --git a/test/assert.js b/test/assert.js index 2717be0d3781..ec30d7675700 100644 --- a/test/assert.js +++ b/test/assert.js @@ -81,6 +81,16 @@ assert.fullHP = function (pokemon, message) { }); }; +assert.hasAbility = function (pokemon, ability, message) { + const actual = pokemon.ability; + const expected = toID(ability); + if (actual === expected) return; + throw new AssertionError({ + message: message || `Expected ${pokemon} ability to be ${expected}, not ${actual}.`, + stackStartFunction: assert.hasAbility, + }); +}; + assert.holdsItem = function (pokemon, message) { if (pokemon.item) return; throw new AssertionError({ diff --git a/test/sim/misc/fainted-forme-regression.js b/test/sim/misc/fainted-forme-regression.js new file mode 100644 index 000000000000..1fa2c1967162 --- /dev/null +++ b/test/sim/misc/fainted-forme-regression.js @@ -0,0 +1,150 @@ +'use strict'; + +const assert = require('./../../assert'); +const common = require('./../../common'); + +let battle; + +describe(`Fainted forme regression`, function () { + afterEach(function () { + battle.destroy(); + }); + + it('[Hackmons] should be able to revert between different mega evolutions', function () { + battle = common.createBattle([[ + {species: 'charizardmegay', ability: 'drought', item: 'charizarditex', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento mega', 'auto'); + assert.species(pokemon, 'Charizard-Mega-Y'); + assert.hasAbility(pokemon, 'Drought'); + }); + + it(`should revert Mega Evolutions`, function () { + battle = common.createBattle([[ + {species: 'alakazam', ability: 'synchronize', item: 'alakazite', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento mega', 'auto'); + assert.species(pokemon, 'Alakazam'); + assert.hasAbility(pokemon, 'Synchronize'); + }); + + it(`should revert Rayquaza-Mega`, function () { + battle = common.gen(7).createBattle([[ + {species: 'rayquaza', ability: 'airlock', moves: ['memento', 'dragonascent']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento mega', 'auto'); + assert.species(pokemon, 'Rayquaza'); + assert.hasAbility(pokemon, 'Air Lock'); + }); + + it(`should revert Primal forms`, function () { + battle = common.createBattle([[ + {species: 'kyogre', ability: 'drizzle', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices(); + assert.species(pokemon, 'Kyogre'); + assert.hasAbility(pokemon, 'Drizzle'); + }); + + it(`shouldn't revert Arceus-forms to base Arceus`, function () { + battle = common.createBattle([[ + {species: 'arceusfire', ability: 'multitype', item: 'flameplate', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices(); + assert.species(pokemon, 'Arceus-Fire'); + assert.hasAbility(pokemon, 'Multitype'); + }); + + it("should revert Terastallized Morpeko-Hangry to base Morpeko", function () { + battle = common.createBattle([[ + {species: 'Morpeko', ability: 'hungerswitch', moves: ['memento', 'sleeptalk']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move sleeptalk', 'auto'); + assert.species(pokemon, 'Morpeko-Hangry'); + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(pokemon, 'Morpeko'); + assert.hasAbility(pokemon, 'Hunger Switch'); + }); + + it(`shouldn't revert Palafin-Hero to base Palafin`, function () { + battle = common.createBattle([[ + {species: 'palafin', ability: 'zerotohero', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('switch 2', 'auto'); + battle.makeChoices('switch 2', 'auto'); + assert.species(pokemon, 'Palafin-Hero'); + battle.makeChoices('move memento', 'auto'); + assert.species(pokemon, 'Palafin-Hero'); + assert.hasAbility(pokemon, 'Zero to Hero'); + }); + + it(`should revert Ogerpon-Tera to base Ogerpon`, function () { + battle = common.createBattle([[ + { + species: 'ogerponwellspring', ability: 'waterabsorb', item: 'wellspring mask', + moves: ['memento'], teraType: 'Water', + }, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(pokemon, 'Ogerpon-Wellspring'); + assert.hasAbility(pokemon, 'Water Absorb'); + }); + + it(`shouldn't revert Terapagos-Terastal to base Terapagos`, function () { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento']}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices(); + assert.species(pokemon, 'Terapagos-Terastal'); + assert.hasAbility(pokemon, 'Tera Shell'); + }); + + it(`should revert Terapagos-Stellar to base Terapagos`, function () { + battle = common.createBattle([[ + {species: 'terapagos', ability: 'terashift', moves: ['memento'], teraType: 'Stellar'}, + {species: 'darkrai', moves: ['darkpulse']}, + ], [ + {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, + ]]); + const pokemon = battle.p1.active[0]; + battle.makeChoices('move memento terastallize', 'auto'); + assert.species(pokemon, 'Terapagos'); + assert.hasAbility(pokemon, 'Tera Shift'); + }); +}); diff --git a/test/sim/misc/terapagos.js b/test/sim/misc/terapagos.js index 64815320878f..a1276f21a290 100644 --- a/test/sim/misc/terapagos.js +++ b/test/sim/misc/terapagos.js @@ -24,32 +24,6 @@ describe(`Terapagos`, function () { assert.false(!!ditto.terastallized); }); - it(`shouldn't revert to Terapagos-Normal if it faints while not Terastallized`, function () { - battle = common.createBattle([[ - {species: 'terapagos', ability: 'terashift', moves: ['memento']}, - {species: 'darkrai', moves: ['darkpulse']}, - ], [ - {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, - ]]); - const terapagos = battle.p1.active[0]; - battle.makeChoices(); - assert.species(terapagos, 'Terapagos-Terastal'); - assert.equal(terapagos.ability, 'terashell', `Expected ${terapagos}'ability to be Tera Shell, not ${terapagos.ability}`); - }); - - it(`should revert to Terapagos-Normal if it faints while Terastallized`, function () { - battle = common.createBattle([[ - {species: 'terapagos', ability: 'terashift', moves: ['memento']}, - {species: 'darkrai', moves: ['darkpulse']}, - ], [ - {species: 'mareep', ability: 'static', moves: ['sleeptalk']}, - ]]); - const terapagos = battle.p1.active[0]; - battle.makeChoices('move memento terastallize', 'auto'); - assert.species(terapagos, 'Terapagos'); - assert.equal(terapagos.ability, 'terashift', `Expected ${terapagos}'ability to be Tera Shift, not ${terapagos.ability}`); - }); - it(`[Hackmons] should not cause Terapagos-Terastal to become Terapagos-Stellar if the user is Transformed`, function () { battle = common.createBattle([[ {species: 'terapagos', ability: 'terashift', moves: ['transform'], teraType: 'Stellar'}, From f185f6571db6354d36432fb2949fc3b1a0e1f2f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Fri, 10 Jan 2025 12:08:23 +0000 Subject: [PATCH 09/17] Add comment --- sim/pokemon.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/sim/pokemon.ts b/sim/pokemon.ts index b9ba0fc4f056..09077ac76c62 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -131,6 +131,7 @@ export class Pokemon { faintQueued: boolean; subFainted: boolean | null; + /** If this Pokemon faints will change to this species */ regressionForme: {species: Species, ability: ID} | null; types: string[]; From 3193f8c4d96bf05a7570aca285dc9e909ba81b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Sun, 12 Jan 2025 07:38:38 +0000 Subject: [PATCH 10/17] Transformation should never allow regression --- sim/battle-actions.ts | 2 +- sim/pokemon.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index b48fbc163d01..53ed42952b0f 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -1959,7 +1959,7 @@ export class BattleActions { this.battle.add('-heal', pokemon, pokemon.getHealth, '[silent]'); } if (pokemon.species.baseSpecies === 'Morpeko') { - if (pokemon.species.name !== 'Morpeko') { + if (pokemon.species.name !== 'Morpeko' && !pokemon.transformed) { pokemon.regressionForme = {species: pokemon.baseSpecies, ability: pokemon.baseAbility}; } pokemon.baseSpecies = pokemon.species; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 09077ac76c62..184ebe1ce9c5 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -1393,7 +1393,9 @@ export class Pokemon { const apparentSpecies = this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { - if (!this.regressionForme) this.regressionForme = {species: this.baseSpecies, ability: this.baseAbility}; + if (!this.regressionForme && !this.transformed) { + this.regressionForme = {species: this.baseSpecies, ability: this.baseAbility}; + } this.baseSpecies = rawSpecies; this.details = this.getSimpleDetails(); let details = (this.illusion || this).details; From 568761d079d7aa11c96c51b2f9bcbe261b4ac801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Sun, 12 Jan 2025 08:10:15 +0000 Subject: [PATCH 11/17] Actually use pokemon.details --- sim/pokemon.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 184ebe1ce9c5..335a1c1c8e74 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -354,9 +354,7 @@ export class Pokemon { } this.position = 0; - let displayedSpeciesName = this.species.name; - if (displayedSpeciesName === 'Greninja-Bond') displayedSpeciesName = 'Greninja'; - this.details = this.getSimpleDetails(displayedSpeciesName); + this.details = this.getSimpleDetails(); this.status = ''; this.statusState = {}; @@ -519,15 +517,15 @@ export class Pokemon { if (illusionDetails && this.illusion) { if (this.battle.ruleTable.has('illusionlevelmod')) level = this.illusion.level; name = this.illusion.species.name; - if (name === 'Greninja-Bond') name = 'Greninja'; } + if (name === 'Greninja-Bond') name = 'Greninja'; return name + (level === 100 ? '' : ', L' + level) + (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); } getDetails = () => { const health = this.getHealth(); - let details = this.getSimpleDetails(null, true); + let details = this.illusion ? this.getSimpleDetails(null, true) : this.details; if (this.terastallized) details += `, tera:${this.terastallized}`; return {side: health.side, secret: `${details}|${health.secret}`, shared: `${details}|${health.shared}`}; }; From c09318b6055a3444dd74509bca358921e628a417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Sun, 12 Jan 2025 09:27:21 +0000 Subject: [PATCH 12/17] Rename methods neither updates pokemon.details --- data/abilities.ts | 2 +- data/mods/gen7pokebilities/scripts.ts | 2 +- data/mods/gen9ssb/abilities.ts | 2 +- data/mods/gen9ssb/moves.ts | 4 ++-- data/mods/gen9ssb/scripts.ts | 8 ++++---- data/mods/mixandmega/scripts.ts | 4 ++-- data/mods/pokebilities/scripts.ts | 2 +- sim/battle-actions.ts | 6 +++--- sim/battle.ts | 4 ++-- sim/pokemon.ts | 10 +++++----- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/data/abilities.ts b/data/abilities.ts index c7492d2c057a..29c413374480 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -2030,7 +2030,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.illusion) { this.debug('illusion cleared'); pokemon.illusion = null; - const details = pokemon.getSimpleDetails(); + const details = pokemon.getUpdatedDetails(); this.add('replace', pokemon, details); this.add('-end', pokemon, 'Illusion'); if (this.ruleTable.has('illusionlevelmod')) { diff --git a/data/mods/gen7pokebilities/scripts.ts b/data/mods/gen7pokebilities/scripts.ts index b74ad6949f05..c88b861598cc 100644 --- a/data/mods/gen7pokebilities/scripts.ts +++ b/data/mods/gen7pokebilities/scripts.ts @@ -169,7 +169,7 @@ export const Scripts: ModdedBattleScriptsData = { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = this.getSimpleDetails(); + this.details = this.getUpdatedDetails(); this.battle.add('detailschange', this, (this.illusion || this).details); if (source.effectType === 'Item') { this.canTerastallize = null; // National Dex behavior diff --git a/data/mods/gen9ssb/abilities.ts b/data/mods/gen9ssb/abilities.ts index 11e74ec300a7..c483d3cf34d8 100644 --- a/data/mods/gen9ssb/abilities.ts +++ b/data/mods/gen9ssb/abilities.ts @@ -1755,7 +1755,7 @@ export const Abilities: import('../../../sim/dex-abilities').ModdedAbilityDataTa target.clearBoosts(); this.add('-clearboost', target); this.boost({atk: 1, def: -1, spa: 1, spd: -1, spe: 1}); - const details = target.getSimpleDetails(); + const details = target.getUpdatedDetails(); target.details = details; this.add('replace', target, details); } diff --git a/data/mods/gen9ssb/moves.ts b/data/mods/gen9ssb/moves.ts index fd2d9e278187..230715795ec9 100644 --- a/data/mods/gen9ssb/moves.ts +++ b/data/mods/gen9ssb/moves.ts @@ -4236,7 +4236,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { pokemon.cureStatus(); this.boost({def: 1, spd: 1}); (pokemon as any).level += 5; - pokemon.details = pokemon.getSimpleDetails(); + pokemon.details = pokemon.getUpdatedDetails(); this.add('-anim', pokemon, 'Geomancy', pokemon); this.add('replace', pokemon, pokemon.details); this.add('-message', `${pokemon.name} gained 5 levels!`); @@ -5904,7 +5904,7 @@ export const Moves: import('../../../sim/dex-moves').ModdedMoveDataTable = { this.add(`c:|${getName((source.illusion || source).name)}|lol never do that ever again thanks`); this.add('custom', '-endterastallize', pokemon); delete pokemon.terastallized; - const details = pokemon.getSimpleDetails(); + const details = pokemon.getUpdatedDetails(); this.add('detailschange', pokemon, details); } }, diff --git a/data/mods/gen9ssb/scripts.ts b/data/mods/gen9ssb/scripts.ts index 98f8877ce552..a610ea1453a1 100644 --- a/data/mods/gen9ssb/scripts.ts +++ b/data/mods/gen9ssb/scripts.ts @@ -89,7 +89,7 @@ export function changeSet(context: Battle, pokemon: Pokemon, newSet: SSBSet, cha pokemon.teraType = newSet.teraType === 'Any' ? context.sample(allTypes) : Array.isArray(newSet.teraType) ? context.sample(newSet.teraType) : newSet.teraType; } - const details = pokemon.getSimpleDetails(); + const details = pokemon.getUpdatedDetails(); if (oldShiny !== pokemon.set.shiny || oldGender !== pokemon.gender) context.add('replace', pokemon, details); if (changeAbility) pokemon.setAbility(newSet.ability as string, undefined, true); @@ -385,7 +385,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = pokemon.getSimpleDetails(); + pokemon.details = pokemon.getUpdatedDetails(); // pokemon.setAbility(species.abilities['0'], null, true); // pokemon.baseAbility = pokemon.ability; @@ -914,9 +914,9 @@ export const Scripts: ModdedBattleScriptsData = { } this.battle.runEvent('BeforeSwitchIn', pokemon); if (sourceEffect) { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails, '[from] ' + sourceEffect); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails, '[from] ' + sourceEffect); } else { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails); } pokemon.abilityOrder = this.battle.abilityOrder++; if (isDrag && this.battle.gen === 2) pokemon.draggedIn = this.battle.turn; diff --git a/data/mods/mixandmega/scripts.ts b/data/mods/mixandmega/scripts.ts index 2bed1943aac2..c9c05eaf7d8d 100644 --- a/data/mods/mixandmega/scripts.ts +++ b/data/mods/mixandmega/scripts.ts @@ -67,7 +67,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = pokemon.getSimpleDetails(); + pokemon.details = pokemon.getUpdatedDetails(); pokemon.ability = this.toID(species.abilities['0']); pokemon.baseAbility = pokemon.ability; } @@ -117,7 +117,7 @@ export const Scripts: ModdedBattleScriptsData = { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = pokemon.getSimpleDetails(); + pokemon.details = pokemon.getUpdatedDetails(); pokemon.ability = this.toID(species.abilities['0']); pokemon.baseAbility = pokemon.ability; diff --git a/data/mods/pokebilities/scripts.ts b/data/mods/pokebilities/scripts.ts index ecc2cf98647d..42716a34fbcc 100644 --- a/data/mods/pokebilities/scripts.ts +++ b/data/mods/pokebilities/scripts.ts @@ -169,7 +169,7 @@ export const Scripts: ModdedBattleScriptsData = { this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { this.baseSpecies = rawSpecies; - this.details = this.getSimpleDetails(); + this.details = this.getUpdatedDetails(); this.battle.add('detailschange', this, (this.illusion || this).details); if (source.effectType === 'Item') { this.canTerastallize = null; // National Dex behavior diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 53ed42952b0f..0db42451c866 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -136,9 +136,9 @@ export class BattleActions { } this.battle.runEvent('BeforeSwitchIn', pokemon); if (sourceEffect) { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails, '[from] ' + sourceEffect); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails, '[from] ' + sourceEffect); } else { - this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getDetails); + this.battle.add(isDrag ? 'drag' : 'switch', pokemon, pokemon.getFullDetails); } pokemon.abilityOrder = this.battle.abilityOrder++; if (isDrag && this.battle.gen === 2) pokemon.draggedIn = this.battle.turn; @@ -1963,7 +1963,7 @@ export class BattleActions { pokemon.regressionForme = {species: pokemon.baseSpecies, ability: pokemon.baseAbility}; } pokemon.baseSpecies = pokemon.species; - pokemon.details = pokemon.getSimpleDetails(); + pokemon.details = pokemon.getUpdatedDetails(); } this.battle.runEvent('AfterTerastallization', pokemon); } diff --git a/sim/battle.ts b/sim/battle.ts index 43286963e898..e0ff260c1b7d 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2373,7 +2373,7 @@ export class Battle { if (pokemon.regressionForme) { pokemon.baseSpecies = pokemon.regressionForme.species; pokemon.baseAbility = pokemon.regressionForme.ability; - pokemon.details = pokemon.getSimpleDetails(pokemon.baseSpecies.name); + pokemon.details = pokemon.getUpdatedDetails(pokemon.baseSpecies.name); pokemon.regressionForme = null; this.add('detailschange', pokemon, pokemon.details, '[silent]'); } @@ -2501,7 +2501,7 @@ export class Battle { const species = pokemon.setSpecies(rawSpecies); if (!species) continue; pokemon.baseSpecies = rawSpecies; - pokemon.details = pokemon.getSimpleDetails(); + pokemon.details = pokemon.getUpdatedDetails(); pokemon.setAbility(species.abilities['0'], null, true); pokemon.baseAbility = pokemon.ability; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 335a1c1c8e74..ac2ec5c486ce 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -354,7 +354,7 @@ export class Pokemon { } this.position = 0; - this.details = this.getSimpleDetails(); + this.details = this.getUpdatedDetails(); this.status = ''; this.statusState = {}; @@ -511,7 +511,7 @@ export class Pokemon { return this.isActive ? this.getSlot() + fullname.slice(2) : fullname; } - getSimpleDetails(displayedSpeciesName: string | null = null, illusionDetails = false) { + getUpdatedDetails(displayedSpeciesName: string | null = null, illusionDetails = false) { let name = displayedSpeciesName || this.species.name; let level = this.level; if (illusionDetails && this.illusion) { @@ -523,9 +523,9 @@ export class Pokemon { (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); } - getDetails = () => { + getFullDetails = () => { const health = this.getHealth(); - let details = this.illusion ? this.getSimpleDetails(null, true) : this.details; + let details = this.illusion ? this.getUpdatedDetails(null, true) : this.details; if (this.terastallized) details += `, tera:${this.terastallized}`; return {side: health.side, secret: `${details}|${health.secret}`, shared: `${details}|${health.shared}`}; }; @@ -1395,7 +1395,7 @@ export class Pokemon { this.regressionForme = {species: this.baseSpecies, ability: this.baseAbility}; } this.baseSpecies = rawSpecies; - this.details = this.getSimpleDetails(); + this.details = this.getUpdatedDetails(); let details = (this.illusion || this).details; if (this.terastallized) details += `, tera:${this.terastallized}`; this.battle.add('detailschange', this, details); From a59cb35299b8d9b02fcd93c8d0f7ff33a9253589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Sun, 12 Jan 2025 10:41:43 +0000 Subject: [PATCH 13/17] More refactor pokemon.clearVolatile may be called in OMs and perform some shenanigans. Set the base variables before the call so they are transposed to the main variables, and change the details afterwards. --- sim/battle.ts | 10 +++++++--- sim/pokemon.ts | 15 +++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/sim/battle.ts b/sim/battle.ts index e0ff260c1b7d..ea94615b7f5c 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2371,11 +2371,9 @@ export class Battle { this.runEvent('Faint', pokemon, faintData.source, faintData.effect); this.singleEvent('End', pokemon.getAbility(), pokemon.abilityState, pokemon); if (pokemon.regressionForme) { + // before clearing volatiles pokemon.baseSpecies = pokemon.regressionForme.species; pokemon.baseAbility = pokemon.regressionForme.ability; - pokemon.details = pokemon.getUpdatedDetails(pokemon.baseSpecies.name); - pokemon.regressionForme = null; - this.add('detailschange', pokemon, pokemon.details, '[silent]'); } pokemon.clearVolatile(false); pokemon.fainted = true; @@ -2383,6 +2381,12 @@ export class Battle { pokemon.isActive = false; pokemon.isStarted = false; delete pokemon.terastallized; + if (pokemon.regressionForme) { + // after clearing volatiles + pokemon.details = pokemon.getUpdatedDetails(); + pokemon.regressionForme = null; + this.add('detailschange', pokemon, pokemon.details, '[silent]'); + } pokemon.side.faintedThisTurn = pokemon; if (this.faintQueue.length >= faintQueueLeft) checkWin = true; } diff --git a/sim/pokemon.ts b/sim/pokemon.ts index ac2ec5c486ce..28a492246329 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -511,21 +511,20 @@ export class Pokemon { return this.isActive ? this.getSlot() + fullname.slice(2) : fullname; } - getUpdatedDetails(displayedSpeciesName: string | null = null, illusionDetails = false) { - let name = displayedSpeciesName || this.species.name; - let level = this.level; - if (illusionDetails && this.illusion) { - if (this.battle.ruleTable.has('illusionlevelmod')) level = this.illusion.level; - name = this.illusion.species.name; - } + getUpdatedDetails(illusionLevel?: number) { + let name = this.species.name; if (name === 'Greninja-Bond') name = 'Greninja'; + const level = illusionLevel || this.level; return name + (level === 100 ? '' : ', L' + level) + (this.gender === '' ? '' : ', ' + this.gender) + (this.set.shiny ? ', shiny' : ''); } getFullDetails = () => { const health = this.getHealth(); - let details = this.illusion ? this.getUpdatedDetails(null, true) : this.details; + let details = this.details; + if (this.illusion) { + details = this.illusion.getUpdatedDetails(this.battle.ruleTable.has('illusionlevelmod') ? this.level : undefined); + } if (this.terastallized) details += `, tera:${this.terastallized}`; return {side: health.side, secret: `${details}|${health.secret}`, shared: `${details}|${health.shared}`}; }; From 4ef6789b8ae28156e80b4e4ff7875d7429ecc8d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Sun, 12 Jan 2025 13:38:11 +0000 Subject: [PATCH 14/17] No message to client Neither Zacian-C, Zamazenta-C, nor Tera Morpeko announce their transformations. They are all handled on the client side. It doesn't happen in front of the players. --- sim/battle-actions.ts | 6 ++---- sim/battle.ts | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index 0db42451c866..c7e98a9a3577 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -1958,10 +1958,8 @@ export class BattleActions { pokemon.maxhp = newMaxHP; this.battle.add('-heal', pokemon, pokemon.getHealth, '[silent]'); } - if (pokemon.species.baseSpecies === 'Morpeko') { - if (pokemon.species.name !== 'Morpeko' && !pokemon.transformed) { - pokemon.regressionForme = {species: pokemon.baseSpecies, ability: pokemon.baseAbility}; - } + if (pokemon.species.baseSpecies === 'Morpeko' && !pokemon.transformed) { + pokemon.regressionForme = {species: pokemon.baseSpecies, ability: pokemon.baseAbility}; pokemon.baseSpecies = pokemon.species; pokemon.details = pokemon.getUpdatedDetails(); } diff --git a/sim/battle.ts b/sim/battle.ts index ea94615b7f5c..edfd75789e70 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2385,7 +2385,6 @@ export class Battle { // after clearing volatiles pokemon.details = pokemon.getUpdatedDetails(); pokemon.regressionForme = null; - this.add('detailschange', pokemon, pokemon.details, '[silent]'); } pokemon.side.faintedThisTurn = pokemon; if (this.faintQueue.length >= faintQueueLeft) checkWin = true; From 03f797a9c5c5dfa5c75cfcd47e9005572689bfc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Tue, 14 Jan 2025 06:15:45 +0000 Subject: [PATCH 15/17] Always regress to the set.species --- data/abilities.ts | 4 ++-- data/conditions.ts | 2 +- sim/battle-actions.ts | 8 +++++--- sim/battle.ts | 6 +++--- sim/pokemon.ts | 10 ++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/data/abilities.ts b/data/abilities.ts index 29c413374480..e06c8e3b594d 100644 --- a/data/abilities.ts +++ b/data/abilities.ts @@ -4891,7 +4891,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.species.forme !== 'Terastal') { this.add('-activate', pokemon, 'ability: Tera Shift'); pokemon.formeChange('Terapagos-Terastal', this.effect, true); - pokemon.regressionForme = null; + pokemon.regressionForme = false; pokemon.baseMaxhp = Math.floor(Math.floor( 2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * pokemon.level / 100 + 10); @@ -5572,7 +5572,7 @@ export const Abilities: import('../sim/dex-abilities').AbilityDataTable = { if (pokemon.baseSpecies.baseSpecies !== 'Palafin') return; if (pokemon.species.forme !== 'Hero') { pokemon.formeChange('Palafin-Hero', this.effect, true); - pokemon.regressionForme = null; + pokemon.regressionForme = false; } }, onSwitchIn() { diff --git a/data/conditions.ts b/data/conditions.ts index a0a48c341cb7..5f1302d6afae 100644 --- a/data/conditions.ts +++ b/data/conditions.ts @@ -91,7 +91,7 @@ export const Conditions: import('../sim/dex-conditions').ConditionDataTable = { } if (target.species.name === 'Shaymin-Sky' && target.baseSpecies.baseSpecies === 'Shaymin') { target.formeChange('Shaymin', this.effect, true); - target.regressionForme = null; + target.regressionForme = false; } }, onBeforeMovePriority: 10, diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index c7e98a9a3577..ff02b8c8c054 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -1949,7 +1949,7 @@ export class BattleActions { } if (pokemon.species.name === 'Terapagos-Terastal' && type === 'Stellar') { pokemon.formeChange('Terapagos-Stellar', null, true); - pokemon.regressionForme = {species: this.dex.species.get('Terapagos'), ability: toID('Tera Shift')}; + pokemon.regressionForme = true; pokemon.baseMaxhp = Math.floor(Math.floor( 2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * pokemon.level / 100 + 10); @@ -1958,8 +1958,10 @@ export class BattleActions { pokemon.maxhp = newMaxHP; this.battle.add('-heal', pokemon, pokemon.getHealth, '[silent]'); } - if (pokemon.species.baseSpecies === 'Morpeko' && !pokemon.transformed) { - pokemon.regressionForme = {species: pokemon.baseSpecies, ability: pokemon.baseAbility}; + if (pokemon.species.baseSpecies === 'Morpeko' && !pokemon.transformed && + pokemon.baseSpecies.id !== pokemon.species.id + ) { + pokemon.regressionForme = true; pokemon.baseSpecies = pokemon.species; pokemon.details = pokemon.getUpdatedDetails(); } diff --git a/sim/battle.ts b/sim/battle.ts index edfd75789e70..715e76f4f600 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -2372,8 +2372,8 @@ export class Battle { this.singleEvent('End', pokemon.getAbility(), pokemon.abilityState, pokemon); if (pokemon.regressionForme) { // before clearing volatiles - pokemon.baseSpecies = pokemon.regressionForme.species; - pokemon.baseAbility = pokemon.regressionForme.ability; + pokemon.baseSpecies = this.dex.species.get(pokemon.set.species || pokemon.set.name); + pokemon.baseAbility = toID(pokemon.set.ability); } pokemon.clearVolatile(false); pokemon.fainted = true; @@ -2384,7 +2384,7 @@ export class Battle { if (pokemon.regressionForme) { // after clearing volatiles pokemon.details = pokemon.getUpdatedDetails(); - pokemon.regressionForme = null; + pokemon.regressionForme = false; } pokemon.side.faintedThisTurn = pokemon; if (this.faintQueue.length >= faintQueueLeft) checkWin = true; diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 28a492246329..3484096744c3 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -131,8 +131,8 @@ export class Pokemon { faintQueued: boolean; subFainted: boolean | null; - /** If this Pokemon faints will change to this species */ - regressionForme: {species: Species, ability: ID} | null; + /** If this Pokemon should revert to its set species when it faints */ + regressionForme: boolean; types: string[]; addedType: string; @@ -419,7 +419,7 @@ export class Pokemon { this.faintQueued = false; this.subFainted = null; - this.regressionForme = null; + this.regressionForme = false; this.types = this.baseSpecies.types; this.baseTypes = this.types; @@ -1390,9 +1390,7 @@ export class Pokemon { const apparentSpecies = this.illusion ? this.illusion.species.name : species.baseSpecies; if (isPermanent) { - if (!this.regressionForme && !this.transformed) { - this.regressionForme = {species: this.baseSpecies, ability: this.baseAbility}; - } + if (!this.transformed) this.regressionForme = true; this.baseSpecies = rawSpecies; this.details = this.getUpdatedDetails(); let details = (this.illusion || this).details; From 27b3f2248b73f402cf6bb9ef568ac56aaf62ecbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Wed, 15 Jan 2025 06:28:33 +0000 Subject: [PATCH 16/17] Remove redundant code --- sim/battle-actions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/sim/battle-actions.ts b/sim/battle-actions.ts index ff02b8c8c054..82f6b90f1740 100644 --- a/sim/battle-actions.ts +++ b/sim/battle-actions.ts @@ -1949,7 +1949,6 @@ export class BattleActions { } if (pokemon.species.name === 'Terapagos-Terastal' && type === 'Stellar') { pokemon.formeChange('Terapagos-Stellar', null, true); - pokemon.regressionForme = true; pokemon.baseMaxhp = Math.floor(Math.floor( 2 * pokemon.species.baseStats['hp'] + pokemon.set.ivs['hp'] + Math.floor(pokemon.set.evs['hp'] / 4) + 100 ) * pokemon.level / 100 + 10); From 8a62f2f68d159902b76213a54f042bc272ae197b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bastos=20Dias?= Date: Tue, 21 Jan 2025 18:12:48 +0000 Subject: [PATCH 17/17] Fix function name in comment --- sim/pokemon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/pokemon.ts b/sim/pokemon.ts index 3484096744c3..17f28c84ceb5 100644 --- a/sim/pokemon.ts +++ b/sim/pokemon.ts @@ -1333,7 +1333,7 @@ export class Pokemon { /** * Changes this Pokemon's species to the given speciesId (or species). * This function only handles changes to stats and type. - * Use formChange to handle changes to ability and sending client messages. + * Use formeChange to handle changes to ability and sending client messages. */ setSpecies(rawSpecies: Species, source: Effect | null = this.battle.effect, isTransform = false) { const species = this.battle.runEvent('ModifySpecies', this, null, source, rawSpecies);