From 1cf19b49f26d0b82c102d304d7585fe5bacea785 Mon Sep 17 00:00:00 2001 From: AJ Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Tue, 20 May 2025 22:59:39 -0400 Subject: [PATCH] [Balance] Moveset generation adjustments (#5801) * Moveset generation adjustments * Remove shiny explosion check, prevent 2 self-KO moves --- src/field/pokemon.ts | 74 +++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index fcca0c5614a..74ccb0c7f49 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3500,11 +3500,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } let weight = levelMove[0]; // Evolution Moves - if (weight === 0) { + if (weight === EVOLVE_MOVE) { weight = 50; } - // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight - if (weight === 1 && allMoves[levelMove[1]].power >= 80) { + // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight. Trainers use actual relearn moves. + if (weight === 1 && allMoves[levelMove[1]].power >= 80 || weight === RELEARN_MOVE && this.hasTrainer()) { weight = 40; } if ( @@ -3609,9 +3609,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Bosses never get self ko moves or Pain Split if (this.isBoss()) { - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr)); - movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(HpSplitAttr)); + movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr) && !allMoves[m[0]].hasAttr(HpSplitAttr)); } + // No one gets Memento or Final Gambit movePool = movePool.filter( m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit), ); @@ -3623,10 +3623,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { m[0], m[1] * (allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1), ]); - movePool = movePool.map(m => [ - m[0], - m[1] * (allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1), - ]); // Trainers get a weight bump to stat buffing moves movePool = movePool.map(m => [ m[0], @@ -3687,10 +3683,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { ]); /** The higher this is the more the game weights towards higher level moves. At `0` all moves are equal weight. */ - let weightMultiplier = 0.9; - if (this.hasTrainer()) { - weightMultiplier += 0.7; - } + let weightMultiplier = 1.6; if (this.isBoss()) { weightMultiplier += 0.4; } @@ -3699,37 +3692,21 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { Math.ceil(Math.pow(m[1], weightMultiplier) * 100), ]); - // Trainers and bosses always force a stab move - if (this.hasTrainer() || this.isBoss()) { - const stabMovePool = baseWeights.filter( - m => - allMoves[m[0]].category !== MoveCategory.STATUS && - this.isOfType(allMoves[m[0]].type), - ); + // All Pokemon force a STAB move first + const stabMovePool = baseWeights.filter( + m => + allMoves[m[0]].category !== MoveCategory.STATUS && + this.isOfType(allMoves[m[0]].type), + ); - if (stabMovePool.length) { - const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); - let rand = randSeedInt(totalWeight); - let index = 0; - while (rand > stabMovePool[index][1]) { - rand -= stabMovePool[index++][1]; - } - this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); - } - } else { - // Normal wild pokemon just force a random damaging move - const attackMovePool = baseWeights.filter( - m => allMoves[m[0]].category !== MoveCategory.STATUS, - ); - if (attackMovePool.length) { - const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); - let rand = randSeedInt(totalWeight); - let index = 0; - while (rand > attackMovePool[index][1]) { - rand -= attackMovePool[index++][1]; - } - this.moveset.push(new PokemonMove(attackMovePool[index][0], 0, 0)); + if (stabMovePool.length) { + const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); + let rand = randSeedInt(totalWeight); + let index = 0; + while (rand > stabMovePool[index][1]) { + rand -= stabMovePool[index++][1]; } + this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); } while ( @@ -3741,7 +3718,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Other damaging moves 2x weight if 0-1 damaging moves, 0.5x if 2, 0.125x if 3. These weights get 20x if STAB. // Status moves remain unchanged on weight, this encourages 1-2 movePool = baseWeights - .filter(m => !this.moveset.some(mo => m[0] === mo.moveId)) + .filter(m => !this.moveset.some( + mo => + m[0] === mo.moveId || + (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)) // Only one self-KO move allowed + )) .map(m => { let ret: number; if ( @@ -3772,7 +3753,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }); } else { // Non-trainer pokemon just use normal weights - movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo.moveId)); + movePool = baseWeights.filter(m => !this.moveset.some( + mo => + m[0] === mo.moveId || + (allMoves[m[0]].hasAttr(SacrificialAttr) && mo.getMove().hasAttr(SacrificialAttr)) // Only one self-KO move allowed + )); } const totalWeight = movePool.reduce((v, m) => v + m[1], 0); let rand = randSeedInt(totalWeight); @@ -7104,7 +7089,6 @@ export class EnemyPokemon extends Pokemon { if (!dataSource) { this.generateAndPopulateMoveset(); - if (shinyLock || Overrides.OPP_SHINY_OVERRIDE === false) { this.shiny = false; } else {