[Balance] Moveset generation adjustments (#5801)

* Moveset generation adjustments

* Remove shiny explosion check, prevent 2 self-KO moves
This commit is contained in:
AJ Fontaine 2025-05-20 22:59:39 -04:00 committed by GitHub
parent f01e7599ac
commit 1cf19b49f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -3500,11 +3500,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
let weight = levelMove[0]; let weight = levelMove[0];
// Evolution Moves // Evolution Moves
if (weight === 0) { if (weight === EVOLVE_MOVE) {
weight = 50; weight = 50;
} }
// Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight // 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) { if (weight === 1 && allMoves[levelMove[1]].power >= 80 || weight === RELEARN_MOVE && this.hasTrainer()) {
weight = 40; weight = 40;
} }
if ( if (
@ -3609,9 +3609,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
// Bosses never get self ko moves or Pain Split // Bosses never get self ko moves or Pain Split
if (this.isBoss()) { if (this.isBoss()) {
movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr)); movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(SacrificialAttr) && !allMoves[m[0]].hasAttr(HpSplitAttr));
movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(HpSplitAttr));
} }
// No one gets Memento or Final Gambit
movePool = movePool.filter( movePool = movePool.filter(
m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit), m => !allMoves[m[0]].hasAttr(SacrificialAttrOnHit),
); );
@ -3623,10 +3623,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
m[0], m[0],
m[1] * (allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1), 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 // Trainers get a weight bump to stat buffing moves
movePool = movePool.map(m => [ movePool = movePool.map(m => [
m[0], 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. */ /** The higher this is the more the game weights towards higher level moves. At `0` all moves are equal weight. */
let weightMultiplier = 0.9; let weightMultiplier = 1.6;
if (this.hasTrainer()) {
weightMultiplier += 0.7;
}
if (this.isBoss()) { if (this.isBoss()) {
weightMultiplier += 0.4; weightMultiplier += 0.4;
} }
@ -3699,8 +3692,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
Math.ceil(Math.pow(m[1], weightMultiplier) * 100), Math.ceil(Math.pow(m[1], weightMultiplier) * 100),
]); ]);
// Trainers and bosses always force a stab move // All Pokemon force a STAB move first
if (this.hasTrainer() || this.isBoss()) {
const stabMovePool = baseWeights.filter( const stabMovePool = baseWeights.filter(
m => m =>
allMoves[m[0]].category !== MoveCategory.STATUS && allMoves[m[0]].category !== MoveCategory.STATUS &&
@ -3716,21 +3708,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
this.moveset.push(new PokemonMove(stabMovePool[index][0], 0, 0)); 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));
}
}
while ( while (
baseWeights.length > this.moveset.length && baseWeights.length > this.moveset.length &&
@ -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. // 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 // Status moves remain unchanged on weight, this encourages 1-2
movePool = baseWeights 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 => { .map(m => {
let ret: number; let ret: number;
if ( if (
@ -3772,7 +3753,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}); });
} else { } else {
// Non-trainer pokemon just use normal weights // 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); const totalWeight = movePool.reduce((v, m) => v + m[1], 0);
let rand = randSeedInt(totalWeight); let rand = randSeedInt(totalWeight);
@ -7104,7 +7089,6 @@ export class EnemyPokemon extends Pokemon {
if (!dataSource) { if (!dataSource) {
this.generateAndPopulateMoveset(); this.generateAndPopulateMoveset();
if (shinyLock || Overrides.OPP_SHINY_OVERRIDE === false) { if (shinyLock || Overrides.OPP_SHINY_OVERRIDE === false) {
this.shiny = false; this.shiny = false;
} else { } else {