[Balance] Make sure trainers are using fully evolved Pokémon by gym 3 (#3499)
* Make sure trainers are using fully evolved Pokemon by gym 3 * Expand comment info Co-authored-by: Mumble <kimjoanne@protonmail.com> * Implement suggestions * Update `getPokemonSpecies()` to throw an error if passed `undefined` --------- Co-authored-by: Mumble <kimjoanne@protonmail.com>
This commit is contained in:
parent
f5757f0a3a
commit
d234466d61
|
@ -49,7 +49,8 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
|
|||
const costSpecies = Object.keys(speciesStarters)
|
||||
.map(s => parseInt(s) as Species)
|
||||
.filter(s => speciesStarters[s] === cost);
|
||||
const starterSpecies = getPokemonSpecies(getPokemonSpecies(Utils.randSeedItem(costSpecies)).getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER));
|
||||
const randPkmSpecies = getPokemonSpecies(Utils.randSeedItem(costSpecies));
|
||||
const starterSpecies = getPokemonSpecies(randPkmSpecies.getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER));
|
||||
starters.push(getDailyRunStarter(scene, starterSpecies, startingLevel));
|
||||
}
|
||||
}, 0, seed);
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
|
||||
import { Localizable } from "#app/interfaces/locales";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
import i18next from "i18next";
|
||||
import BattleScene, { AnySound } from "../battle-scene";
|
||||
import { Variant, variantColorCache } from "./variant";
|
||||
import { variantData } from "./variant";
|
||||
import { GameMode } from "../game-mode";
|
||||
import { StarterMoveset } from "../system/game-data";
|
||||
import * as Utils from "../utils";
|
||||
import { uncatchableSpecies } from "./biomes";
|
||||
import { speciesEggMoves } from "./egg-moves";
|
||||
import { GrowthRate } from "./exp";
|
||||
import { EvolutionLevel, SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions";
|
||||
import { Type } from "./type";
|
||||
import { LevelMoves, pokemonFormLevelMoves, pokemonFormLevelMoves as pokemonSpeciesFormLevelMoves, pokemonSpeciesLevelMoves } from "./pokemon-level-moves";
|
||||
import { uncatchableSpecies } from "./biomes";
|
||||
import * as Utils from "../utils";
|
||||
import { StarterMoveset } from "../system/game-data";
|
||||
import { speciesEggMoves } from "./egg-moves";
|
||||
import { GameMode } from "../game-mode";
|
||||
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
|
||||
import { VariantSet } from "./variant";
|
||||
import i18next from "i18next";
|
||||
import { Localizable } from "#app/interfaces/locales";
|
||||
import { Stat } from "./pokemon-stat";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||
import { Species } from "#enums/species";
|
||||
import { Variant, VariantSet, variantColorCache, variantData } from "./variant";
|
||||
|
||||
export enum Region {
|
||||
NORMAL,
|
||||
|
@ -28,7 +25,15 @@ export enum Region {
|
|||
PALDEA
|
||||
}
|
||||
|
||||
export function getPokemonSpecies(species: Species | Species[]): PokemonSpecies {
|
||||
/**
|
||||
* Gets the {@linkcode PokemonSpecies} object associated with the {@linkcode Species} enum given
|
||||
* @param species The species to fetch
|
||||
* @returns The associated {@linkcode PokemonSpecies} object
|
||||
*/
|
||||
export function getPokemonSpecies(species: Species | Species[] | undefined): PokemonSpecies {
|
||||
if (!species) {
|
||||
throw new Error("`species` must not be undefined in `getPokemonSpecies()`");
|
||||
}
|
||||
// If a special pool (named trainers) is used here it CAN happen that they have a array as species (which means choose one of those two). So we catch that with this code block
|
||||
if (Array.isArray(species)) {
|
||||
// Pick a random species from the list
|
||||
|
@ -648,8 +653,8 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||
return this.getSpeciesForLevel(level, allowEvolving, false, (isBoss ? PartyMemberStrength.WEAKER : PartyMemberStrength.AVERAGE) + (gameMode?.isEndless ? 1 : 0));
|
||||
}
|
||||
|
||||
getTrainerSpeciesForLevel(level: integer, allowEvolving: boolean = false, strength: PartyMemberStrength): Species {
|
||||
return this.getSpeciesForLevel(level, allowEvolving, true, strength);
|
||||
getTrainerSpeciesForLevel(level: integer, allowEvolving: boolean = false, strength: PartyMemberStrength, currentWave: number = 0): Species {
|
||||
return this.getSpeciesForLevel(level, allowEvolving, true, strength, currentWave);
|
||||
}
|
||||
|
||||
private getStrengthLevelDiff(strength: PartyMemberStrength): integer {
|
||||
|
@ -669,7 +674,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||
}
|
||||
}
|
||||
|
||||
getSpeciesForLevel(level: integer, allowEvolving: boolean = false, forTrainer: boolean = false, strength: PartyMemberStrength = PartyMemberStrength.WEAKER): Species {
|
||||
getSpeciesForLevel(level: integer, allowEvolving: boolean = false, forTrainer: boolean = false, strength: PartyMemberStrength = PartyMemberStrength.WEAKER, currentWave: number = 0): Species {
|
||||
const prevolutionLevels = this.getPrevolutionLevels();
|
||||
|
||||
if (prevolutionLevels.length) {
|
||||
|
@ -730,6 +735,11 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||
evolutionChance = Math.min(0.65 * easeInFunc(Math.min(Math.max(level - evolutionLevel, 0), preferredMinLevel) / preferredMinLevel) + 0.35 * easeOutFunc(Math.min(Math.max(level - evolutionLevel, 0), preferredMinLevel * 2.5) / (preferredMinLevel * 2.5)), 1);
|
||||
}
|
||||
}
|
||||
/* (Most) Trainers shouldn't be using unevolved Pokemon by the third gym leader / wave 80. Exceptions to this include Breeders, whose large teams are balanced by the use of weaker pokemon */
|
||||
if (currentWave >= 80 && forTrainer && strength > PartyMemberStrength.WEAKER) {
|
||||
evolutionChance = 1;
|
||||
noEvolutionChance = 0;
|
||||
}
|
||||
|
||||
if (evolutionChance > 0) {
|
||||
if (isRegionalEvolution) {
|
||||
|
@ -754,7 +764,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
|
|||
|
||||
for (const weight of evolutionPool.keys()) {
|
||||
if (randValue < weight) {
|
||||
return getPokemonSpecies(evolutionPool.get(weight)!).getSpeciesForLevel(level, true, forTrainer, strength); // TODO: is the bang correct?
|
||||
return getPokemonSpecies(evolutionPool.get(weight)).getSpeciesForLevel(level, true, forTrainer, strength, currentWave);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ export const trainerPartyTemplates = {
|
|||
FIVE_WEAK_BALANCED: new TrainerPartyTemplate(5, PartyMemberStrength.WEAK, false, true),
|
||||
SIX_WEAKER: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER),
|
||||
SIX_WEAKER_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true),
|
||||
SIX_WEAK_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAKER, true),
|
||||
SIX_WEAK_SAME: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK, true),
|
||||
SIX_WEAK_BALANCED: new TrainerPartyTemplate(6, PartyMemberStrength.WEAK, false, true),
|
||||
|
||||
GYM_LEADER_1: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, PartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, PartyMemberStrength.STRONG)),
|
||||
|
@ -965,7 +965,7 @@ function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSl
|
|||
return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => {
|
||||
let species = Utils.randSeedItem(speciesPool);
|
||||
if (!ignoreEvolution) {
|
||||
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength);
|
||||
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex);
|
||||
}
|
||||
return scene.addEnemyPokemon(getPokemonSpecies(species), level, trainerSlot, undefined, undefined, postProcess);
|
||||
};
|
||||
|
@ -975,7 +975,7 @@ function getSpeciesFilterRandomPartyMemberFunc(speciesFilter: PokemonSpeciesFilt
|
|||
const originalSpeciesFilter = speciesFilter;
|
||||
speciesFilter = (species: PokemonSpecies) => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden() && originalSpeciesFilter(species);
|
||||
return (scene: BattleScene, level: integer, strength: PartyMemberStrength) => {
|
||||
const ret = scene.addEnemyPokemon(getPokemonSpecies(scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter).getTrainerSpeciesForLevel(level, true, strength)), level, trainerSlot, undefined, undefined, postProcess);
|
||||
const ret = scene.addEnemyPokemon(getPokemonSpecies(scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex)), level, trainerSlot, undefined, undefined, postProcess);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -359,12 +359,12 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
let species = useNewSpeciesPool
|
||||
? getPokemonSpecies(newSpeciesPool[Math.floor(Math.random() * newSpeciesPool.length)])
|
||||
: template.isSameSpecies(index) && index > offset
|
||||
? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset)))
|
||||
? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset), this.scene.currentBattle.waveIndex))
|
||||
: this.genNewPartyMemberSpecies(level, strength);
|
||||
|
||||
// If the species is from newSpeciesPool, we need to adjust it based on the level and strength
|
||||
if (newSpeciesPool) {
|
||||
species = getPokemonSpecies(species.getSpeciesForLevel(level, true, true, strength));
|
||||
species = getPokemonSpecies(species.getSpeciesForLevel(level, true, true, strength, this.scene.currentBattle.waveIndex));
|
||||
}
|
||||
|
||||
ret = this.scene.addEnemyPokemon(species, level, !this.isDouble() || !(index % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER);
|
||||
|
@ -393,7 +393,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
species = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter);
|
||||
}
|
||||
|
||||
let ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength));
|
||||
let ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex));
|
||||
let retry = false;
|
||||
|
||||
console.log(ret.getName());
|
||||
|
@ -412,7 +412,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
|
|||
console.log("Attempting reroll of species evolution to fit specialty type...");
|
||||
let evoAttempt = 0;
|
||||
while (retry && evoAttempt++ < 10) {
|
||||
ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength));
|
||||
ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex));
|
||||
console.log(ret.name);
|
||||
if (this.config.specialtyTypes.find(t => ret.isOfType(t))) {
|
||||
retry = false;
|
||||
|
|
Loading…
Reference in New Issue