[Feature] Add possibility to override whole user party (#1643)

* Add possibility to override whole user party

* Update species overriding

* Replace SPARTER_SPECIES_OVERRIDE with array

* Replace SPARTER_SPECIES_OVERRIDE with array

* Add possibility to override species forms

* Add possibility to override species forms

* Fix eslint styling

* Add possibility to override Abilities for party

* Override status, gender, moveset

* Add possibility to override shinies

* Fix CI
This commit is contained in:
hayuna 2024-06-04 17:29:38 +02:00 committed by GitHub
parent 7ac7c2b63b
commit ef8b6aa4f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 123 additions and 40 deletions

View File

@ -686,8 +686,8 @@ export default class BattleScene extends SceneBase {
return findInParty(this.getParty()) || findInParty(this.getEnemyParty()); return findInParty(this.getParty()) || findInParty(this.getEnemyParty());
} }
addPlayerPokemon(species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void): PlayerPokemon { addPlayerPokemon(species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, postProcess?: (playerPokemon: PlayerPokemon) => void, indexInParty?: number): PlayerPokemon {
const pokemon = new PlayerPokemon(this, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource); const pokemon = new PlayerPokemon(this, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource, indexInParty);
if (postProcess) { if (postProcess) {
postProcess(pokemon); postProcess(pokemon);
} }

View File

@ -61,7 +61,7 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
function getDailyRunStarter(scene: BattleScene, starterSpeciesForm: PokemonSpeciesForm, startingLevel: integer): Starter { function getDailyRunStarter(scene: BattleScene, starterSpeciesForm: PokemonSpeciesForm, startingLevel: integer): Starter {
const starterSpecies = starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId); const starterSpecies = starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId);
const formIndex = starterSpeciesForm instanceof PokemonSpecies ? undefined : starterSpeciesForm.formIndex; const formIndex = starterSpeciesForm instanceof PokemonSpecies ? undefined : starterSpeciesForm.formIndex;
const pokemon = new PlayerPokemon(scene, starterSpecies, startingLevel, undefined, formIndex, undefined, undefined, undefined, undefined, undefined, undefined); const pokemon = new PlayerPokemon(scene, starterSpecies, startingLevel, undefined, formIndex, undefined, undefined, undefined, undefined, undefined, undefined, undefined);
const starter: Starter = { const starter: Starter = {
species: starterSpecies, species: starterSpecies,
dexAttr: pokemon.getDexAttr(), dexAttr: pokemon.getDexAttr(),

View File

@ -98,6 +98,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
public battleData: PokemonBattleData; public battleData: PokemonBattleData;
public battleSummonData: PokemonBattleSummonData; public battleSummonData: PokemonBattleSummonData;
public turnData: PokemonTurnData; public turnData: PokemonTurnData;
public indexInParty: number;
public fieldPosition: FieldPosition; public fieldPosition: FieldPosition;
@ -106,7 +107,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
private shinySparkle: Phaser.GameObjects.Sprite; private shinySparkle: Phaser.GameObjects.Sprite;
constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData) { constructor(scene: BattleScene, x: number, y: number, species: PokemonSpecies, level: integer, abilityIndex?: integer, formIndex?: integer, gender?: Gender, shiny?: boolean, variant?: Variant, ivs?: integer[], nature?: Nature, dataSource?: Pokemon | PokemonData, indexInParty?: number) {
super(scene, x, y); super(scene, x, y);
if (!species.isObtainable() && this.isPlayer()) { if (!species.isObtainable() && this.isPlayer()) {
@ -139,6 +140,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (variant !== undefined) { if (variant !== undefined) {
this.variant = variant; this.variant = variant;
} }
if (indexInParty !== undefined) {
this.indexInParty = indexInParty;
}
this.exp = dataSource?.exp || getLevelTotalExp(this.level, species.growthRate); this.exp = dataSource?.exp || getLevelTotalExp(this.level, species.growthRate);
this.levelExp = dataSource?.levelExp || 0; this.levelExp = dataSource?.levelExp || 0;
if (dataSource) { if (dataSource) {
@ -816,7 +820,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
: this.moveset; : this.moveset;
// Overrides moveset based on arrays specified in overrides.ts // Overrides moveset based on arrays specified in overrides.ts
const overrideArray: Array<Moves> = this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.OPP_MOVESET_OVERRIDE; const overrideArray: Array<Moves> = this.isPlayer() ? Overrides.STARTER_OVERRIDE[this.indexInParty]?.moveset : Overrides.OPP_MOVESET_OVERRIDE;
if (overrideArray.length > 0) { if (overrideArray.length > 0) {
overrideArray.forEach((move: Moves, index: number) => { overrideArray.forEach((move: Moves, index: number) => {
const ppUsed = this.moveset[index]?.ppUsed || 0; const ppUsed = this.moveset[index]?.ppUsed || 0;
@ -901,9 +905,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (!ignoreOverride && this.summonData?.ability) { if (!ignoreOverride && this.summonData?.ability) {
return allAbilities[this.summonData.ability]; return allAbilities[this.summonData.ability];
} }
if (Overrides.ABILITY_OVERRIDE && this.isPlayer()) {
return allAbilities[Overrides.ABILITY_OVERRIDE];
}
if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) { if (Overrides.OPP_ABILITY_OVERRIDE && !this.isPlayer()) {
return allAbilities[Overrides.OPP_ABILITY_OVERRIDE]; return allAbilities[Overrides.OPP_ABILITY_OVERRIDE];
} }
@ -911,6 +912,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)]; return allAbilities[this.getFusionSpeciesForm(ignoreOverride).getAbility(this.fusionAbilityIndex)];
} }
let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex); let abilityId = this.getSpeciesForm(ignoreOverride).getAbility(this.abilityIndex);
if (Overrides.STARTER_OVERRIDE[this.indexInParty]?.ability) {
abilityId = Overrides.STARTER_OVERRIDE[this.indexInParty].ability;
}
if (abilityId === Abilities.NONE) { if (abilityId === Abilities.NONE) {
abilityId = this.species.ability1; abilityId = this.species.ability1;
} }
@ -925,8 +930,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns {Ability} The passive ability of the pokemon * @returns {Ability} The passive ability of the pokemon
*/ */
getPassiveAbility(): Ability { getPassiveAbility(): Ability {
if (Overrides.PASSIVE_ABILITY_OVERRIDE && this.isPlayer()) { if (Overrides.STARTER_OVERRIDE[this.indexInParty]?.passiveAbility && this.isPlayer()) {
return allAbilities[Overrides.PASSIVE_ABILITY_OVERRIDE]; return allAbilities[Overrides.STARTER_OVERRIDE[this.indexInParty].passiveAbility];
} }
if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) { if (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE && !this.isPlayer()) {
return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE]; return allAbilities[Overrides.OPP_PASSIVE_ABILITY_OVERRIDE];
@ -948,7 +953,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
*/ */
hasPassive(): boolean { hasPassive(): boolean {
// returns override if valid for current case // returns override if valid for current case
if ((Overrides.PASSIVE_ABILITY_OVERRIDE !== Abilities.NONE && this.isPlayer()) || if ((Overrides.STARTER_OVERRIDE[this.indexInParty]?.passiveAbility !== Abilities.NONE && this.isPlayer()) ||
(Overrides.OPP_PASSIVE_ABILITY_OVERRIDE !== Abilities.NONE && !this.isPlayer())) { (Overrides.OPP_PASSIVE_ABILITY_OVERRIDE !== Abilities.NONE && !this.isPlayer())) {
return true; return true;
} }
@ -2822,19 +2827,21 @@ export default interface Pokemon {
export class PlayerPokemon extends Pokemon { export class PlayerPokemon extends Pokemon {
public compatibleTms: Moves[]; public compatibleTms: Moves[];
public indexInParty: number;
constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender: Gender, shiny: boolean, variant: Variant, ivs: integer[], nature: Nature, dataSource: Pokemon | PokemonData) { constructor(scene: BattleScene, species: PokemonSpecies, level: integer, abilityIndex: integer, formIndex: integer, gender: Gender, shiny: boolean, variant: Variant, ivs: integer[], nature: Nature, dataSource: Pokemon | PokemonData, indexInParty: number) {
super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource); super(scene, 106, 148, species, level, abilityIndex, formIndex, gender, shiny, variant, ivs, nature, dataSource);
if (Overrides.STATUS_OVERRIDE) { if (Overrides.STARTER_OVERRIDE[indexInParty]?.status) {
this.status = new Status(Overrides.STATUS_OVERRIDE); this.status = new Status(Overrides.STARTER_OVERRIDE[indexInParty].status);
} }
this.indexInParty = indexInParty;
if (Overrides.SHINY_OVERRIDE) { if (Overrides.STARTER_OVERRIDE[this.indexInParty]?.shiny) {
this.shiny = true; this.shiny = true;
this.initShinySparkle(); this.initShinySparkle();
if (Overrides.VARIANT_OVERRIDE) { if (Overrides.STARTER_OVERRIDE[this.indexInParty]?.shinyVariant) {
this.variant = Overrides.VARIANT_OVERRIDE; this.variant = Overrides.STARTER_OVERRIDE[this.indexInParty].shinyVariant;
} }
} }

View File

@ -52,24 +52,95 @@ export const POKEBALL_OVERRIDE: { active: boolean, pokeballs: PokeballCounts } =
* PLAYER OVERRIDES * PLAYER OVERRIDES
*/ */
// forms can be found in pokemon-species.ts
export const STARTER_FORM_OVERRIDE: integer = 0;
// default 5 or 20 for Daily // default 5 or 20 for Daily
export const STARTING_LEVEL_OVERRIDE: integer = 0; export const STARTING_LEVEL_OVERRIDE: integer = 0;
/** interface StarterOverride {
* SPECIES OVERRIDE /**
* will only apply to the first starter in your party or each enemy pokemon * SPECIES OVERRIDE
* default is 0 to not override * will apply to each starter in your party
* @example SPECIES_OVERRIDE = Species.Bulbasaur; * default is 0 to not override
*/ * @example STARTER_OVERRIDE.species = Species.Bulbasaur;
export const STARTER_SPECIES_OVERRIDE: Species | integer = 0; */
export const ABILITY_OVERRIDE: Abilities = Abilities.NONE;
export const PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE; species: Species | integer;
export const STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE; // forms can be found in pokemon-species.ts
export const GENDER_OVERRIDE: Gender = null; form: integer;
export const MOVESET_OVERRIDE: Array<Moves> = []; ability: Abilities;
export const SHINY_OVERRIDE: boolean = false; passiveAbility: Abilities;
export const VARIANT_OVERRIDE: Variant = 0; status: StatusEffect;
gender: Gender;
moveset: Moves[];
shiny: boolean;
shinyVariant: Variant;
}
export const STARTER_OVERRIDE: StarterOverride[] = [
{
species: 0,
form: 0,
ability: Abilities.NONE,
passiveAbility: Abilities.NONE,
status: StatusEffect.NONE,
gender: null,
moveset: [],
shiny: false,
shinyVariant: 0,
},
{
species: 0,
form: 0,
ability: Abilities.NONE,
passiveAbility: Abilities.NONE,
status: StatusEffect.NONE,
gender: null,
moveset: [],
shiny: false,
shinyVariant: 0,
},
{
species: 0,
form: 0,
ability: Abilities.NONE,
passiveAbility: Abilities.NONE,
status: StatusEffect.NONE,
gender: null,
moveset: [],
shiny: false,
shinyVariant: 0,
},
{
species: 0,
form: 0,
ability: Abilities.NONE,
passiveAbility: Abilities.NONE,
status: StatusEffect.NONE,
gender: null,
moveset: [],
shiny: false,
shinyVariant: 0,
},
{
species: 0,
form: 0,
ability: Abilities.NONE,
passiveAbility: Abilities.NONE,
status: StatusEffect.NONE,
gender: null,
moveset: [],
shiny: false,
shinyVariant: 0,
},
{
species: 0,
form: 0,
ability: Abilities.NONE,
passiveAbility: Abilities.NONE,
status: StatusEffect.NONE,
gender: null,
moveset: [],
shiny: false,
shinyVariant: 0,
}
];
/** /**
* OPPONENT / ENEMY OVERRIDES * OPPONENT / ENEMY OVERRIDES

View File

@ -529,22 +529,27 @@ export class SelectStarterPhase extends Phase {
const party = this.scene.getParty(); const party = this.scene.getParty();
const loadPokemonAssets: Promise<void>[] = []; const loadPokemonAssets: Promise<void>[] = [];
starters.forEach((starter: Starter, i: integer) => { starters.forEach((starter: Starter, i: integer) => {
if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { if (Overrides.STARTER_OVERRIDE[i]?.species) {
starter.species = getPokemonSpecies(Overrides.STARTER_SPECIES_OVERRIDE as Species); starter.species = getPokemonSpecies(Overrides.STARTER_OVERRIDE[i].species as Species);
} }
const starterProps = this.scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr); const starterProps = this.scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr);
let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0)); let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0));
if (!i && Overrides.STARTER_SPECIES_OVERRIDE) { if (Overrides.STARTER_OVERRIDE[i]?.form) {
starterFormIndex = Overrides.STARTER_FORM_OVERRIDE; starterFormIndex = Overrides.STARTER_OVERRIDE[i].form;
const availableForms = starter.species.forms.length;
// prevent use forms which does not exist for species
if (Overrides.STARTER_OVERRIDE[i].form >= availableForms) {
starterFormIndex = 0;
}
} }
let starterGender = starter.species.malePercent !== null let starterGender = starter.species.malePercent !== null
? !starterProps.female ? Gender.MALE : Gender.FEMALE ? !starterProps.female ? Gender.MALE : Gender.FEMALE
: Gender.GENDERLESS; : Gender.GENDERLESS;
if (Overrides.GENDER_OVERRIDE !== null) { if (Overrides.STARTER_OVERRIDE[i]?.gender !== null) {
starterGender = Overrides.GENDER_OVERRIDE; starterGender = Overrides.STARTER_OVERRIDE[i].gender;
} }
const starterIvs = this.scene.gameData.dexData[starter.species.speciesId].ivs.slice(0); const starterIvs = this.scene.gameData.dexData[starter.species.speciesId].ivs.slice(0);
const starterPokemon = this.scene.addPlayerPokemon(starter.species, this.scene.gameMode.getStartingLevel(), starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, starterIvs, starter.nature); const starterPokemon = this.scene.addPlayerPokemon(starter.species, this.scene.gameMode.getStartingLevel(), starter.abilityIndex, starterFormIndex, starterGender, starterProps.shiny, starterProps.variant, starterIvs, starter.nature, null, null, i);
starterPokemon.tryPopulateMoveset(starter.moveset); starterPokemon.tryPopulateMoveset(starter.moveset);
if (starter.passive) { if (starter.passive) {
starterPokemon.passive = true; starterPokemon.passive = true;