[Bug] Starter UI challenge form fix (#3373)
* First issue with soft attribute on challenges as well as incorrect sprites appearing on the starter select ui * Updated logic to fix starter party icons, forms and shinies in starter selection area * Fixed issue where some pokemon were being shown in challenges originally if the default form didn't meet the criteria * Updated docs and tests to account for new behaviour * Removed some debugging comments * Fixed rotom form not counting as valid party * Fixed a bug where the cursor's last known position would be used when pokemon forms were being changed when other forms were available when updated from your party directly * Fixed issue with starter party icons' forms updating incorrectly when removing pokemon from party * Fixed docs * Updated code to allow for starter icons to remember their previous state after a reload
This commit is contained in:
parent
aaad2241ae
commit
49bb681554
|
@ -273,11 +273,9 @@ export abstract class Challenge {
|
||||||
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
|
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
|
||||||
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
|
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
|
||||||
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
||||||
* @param checkEvolutions {@link boolean} If true, check the pokemon's future evolutions
|
|
||||||
* @param checkForms {@link boolean} If true, check the pokemon's alternative forms
|
|
||||||
* @returns {@link boolean} Whether this function did anything.
|
* @returns {@link boolean} Whether this function did anything.
|
||||||
*/
|
*/
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean, checkForms?: boolean): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,14 +403,13 @@ export class SingleGenerationChallenge extends Challenge {
|
||||||
super(Challenges.SINGLE_GENERATION, 9);
|
super(Challenges.SINGLE_GENERATION, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||||
const generations = [pokemon.generation];
|
const generations = [pokemon.generation];
|
||||||
const checkPokemonEvolutions = checkEvolutions ?? true as boolean;
|
|
||||||
if (soft) {
|
if (soft) {
|
||||||
const speciesToCheck = [pokemon.speciesId];
|
const speciesToCheck = [pokemon.speciesId];
|
||||||
while (speciesToCheck.length) {
|
while (speciesToCheck.length) {
|
||||||
const checking = speciesToCheck.pop();
|
const checking = speciesToCheck.pop();
|
||||||
if (checking && pokemonEvolutions.hasOwnProperty(checking) && checkPokemonEvolutions) {
|
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||||
pokemonEvolutions[checking].forEach(e => {
|
pokemonEvolutions[checking].forEach(e => {
|
||||||
speciesToCheck.push(e.speciesId);
|
speciesToCheck.push(e.speciesId);
|
||||||
generations.push(getPokemonSpecies(e.speciesId).generation);
|
generations.push(getPokemonSpecies(e.speciesId).generation);
|
||||||
|
@ -533,22 +530,20 @@ export class SingleTypeChallenge extends Challenge {
|
||||||
super(Challenges.SINGLE_TYPE, 18);
|
super(Challenges.SINGLE_TYPE, 18);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false, checkEvolutions?: boolean, checkForms?: boolean): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
|
||||||
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
|
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
|
||||||
const types = [speciesForm.type1, speciesForm.type2];
|
const types = [speciesForm.type1, speciesForm.type2];
|
||||||
const checkPokemonEvolutions = checkEvolutions ?? true as boolean;
|
|
||||||
const checkPokemonForms = checkForms ?? true as boolean;
|
|
||||||
if (soft) {
|
if (soft) {
|
||||||
const speciesToCheck = [pokemon.speciesId];
|
const speciesToCheck = [pokemon.speciesId];
|
||||||
while (speciesToCheck.length) {
|
while (speciesToCheck.length) {
|
||||||
const checking = speciesToCheck.pop();
|
const checking = speciesToCheck.pop();
|
||||||
if (checking && pokemonEvolutions.hasOwnProperty(checking) && checkPokemonEvolutions) {
|
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
|
||||||
pokemonEvolutions[checking].forEach(e => {
|
pokemonEvolutions[checking].forEach(e => {
|
||||||
speciesToCheck.push(e.speciesId);
|
speciesToCheck.push(e.speciesId);
|
||||||
types.push(getPokemonSpecies(e.speciesId).type1, getPokemonSpecies(e.speciesId).type2);
|
types.push(getPokemonSpecies(e.speciesId).type1, getPokemonSpecies(e.speciesId).type2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (checking && pokemonFormChanges.hasOwnProperty(checking) && checkPokemonForms) {
|
if (checking && pokemonFormChanges.hasOwnProperty(checking)) {
|
||||||
pokemonFormChanges[checking].forEach(f1 => {
|
pokemonFormChanges[checking].forEach(f1 => {
|
||||||
getPokemonSpecies(checking).forms.forEach(f2 => {
|
getPokemonSpecies(checking).forms.forEach(f2 => {
|
||||||
if (f1.formKey === f2.formKey) {
|
if (f1.formKey === f2.formKey) {
|
||||||
|
@ -746,7 +741,7 @@ export class LowerStarterPointsChallenge extends Challenge {
|
||||||
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
|
||||||
* @returns True if any challenge was successfully applied.
|
* @returns True if any challenge was successfully applied.
|
||||||
*/
|
*/
|
||||||
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean, checkEvolutions?: boolean, checkForms?: boolean): boolean;
|
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean): boolean;
|
||||||
/**
|
/**
|
||||||
* Apply all challenges that modify available total starter points.
|
* Apply all challenges that modify available total starter points.
|
||||||
* @param gameMode {@link GameMode} The current gameMode
|
* @param gameMode {@link GameMode} The current gameMode
|
||||||
|
@ -854,7 +849,7 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
|
||||||
if (c.value !== 0) {
|
if (c.value !== 0) {
|
||||||
switch (challengeType) {
|
switch (challengeType) {
|
||||||
case ChallengeType.STARTER_CHOICE:
|
case ChallengeType.STARTER_CHOICE:
|
||||||
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3], args[4], args[5]);
|
ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]);
|
||||||
break;
|
break;
|
||||||
case ChallengeType.STARTER_POINTS:
|
case ChallengeType.STARTER_POINTS:
|
||||||
ret ||= c.applyStarterPoints(args[0]);
|
ret ||= c.applyStarterPoints(args[0]);
|
||||||
|
|
|
@ -197,6 +197,7 @@ export interface StarterAttributes {
|
||||||
variant?: integer;
|
variant?: integer;
|
||||||
form?: integer;
|
form?: integer;
|
||||||
female?: boolean;
|
female?: boolean;
|
||||||
|
shiny?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StarterPreferences {
|
export interface StarterPreferences {
|
||||||
|
|
|
@ -51,6 +51,9 @@ describe("UI - Starter select", () => {
|
||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
|
@ -112,6 +115,9 @@ describe("UI - Starter select", () => {
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.CYCLE_GENDER);
|
handler.processInput(Button.CYCLE_GENDER);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
|
@ -176,6 +182,9 @@ describe("UI - Starter select", () => {
|
||||||
handler.processInput(Button.CYCLE_GENDER);
|
handler.processInput(Button.CYCLE_GENDER);
|
||||||
handler.processInput(Button.CYCLE_NATURE);
|
handler.processInput(Button.CYCLE_NATURE);
|
||||||
handler.processInput(Button.CYCLE_ABILITY);
|
handler.processInput(Button.CYCLE_ABILITY);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
|
@ -238,6 +247,9 @@ describe("UI - Starter select", () => {
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.CYCLE_GENDER);
|
handler.processInput(Button.CYCLE_GENDER);
|
||||||
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
|
handler.processInput(Button.V);
|
||||||
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
|
@ -298,7 +310,6 @@ describe("UI - Starter select", () => {
|
||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.CYCLE_SHINY);
|
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
});
|
});
|
||||||
|
@ -358,7 +369,7 @@ describe("UI - Starter select", () => {
|
||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
game.phaseInterceptor.unlock();
|
game.phaseInterceptor.unlock();
|
||||||
|
@ -419,7 +430,7 @@ describe("UI - Starter select", () => {
|
||||||
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
const handler = game.scene.ui.getHandler() as StarterSelectUiHandler;
|
||||||
handler.processInput(Button.RIGHT);
|
handler.processInput(Button.RIGHT);
|
||||||
handler.processInput(Button.LEFT);
|
handler.processInput(Button.LEFT);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.CYCLE_SHINY);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.V);
|
handler.processInput(Button.V);
|
||||||
handler.processInput(Button.ACTION);
|
handler.processInput(Button.ACTION);
|
||||||
|
|
|
@ -1303,11 +1303,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
|
|
||||||
const isPartyValid = this.isPartyValid();
|
const isPartyValid = this.isPartyValid();
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
if (isPartyValid) {
|
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), this.starterSpecies.length !== 0);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), isPartyValid);
|
||||||
} else {
|
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), this.starterSpecies.length !== 0, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentPartyValue = this.starterSpecies.map(s => s.generation).reduce((total: number, gen: number, i: number) => total += this.scene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0);
|
const currentPartyValue = this.starterSpecies.map(s => s.generation).reduce((total: number, gen: number, i: number) => total += this.scene.gameData.getSpeciesStarterValue(this.starterSpecies[i].speciesId), 0);
|
||||||
const newCost = this.scene.gameData.getSpeciesStarterValue(species.speciesId);
|
const newCost = this.scene.gameData.getSpeciesStarterValue(species.speciesId);
|
||||||
|
@ -1661,7 +1658,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor);
|
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId));
|
||||||
// prepare persistent starter data to store changes
|
// prepare persistent starter data to store changes
|
||||||
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
|
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
|
||||||
if (!starterAttributes) {
|
if (!starterAttributes) {
|
||||||
|
@ -1671,8 +1668,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
case Button.CYCLE_SHINY:
|
case Button.CYCLE_SHINY:
|
||||||
if (this.canCycleShiny) {
|
if (this.canCycleShiny) {
|
||||||
const newVariant = props.variant;
|
const newVariant = props.variant;
|
||||||
|
starterAttributes.shiny = starterAttributes.shiny ? !starterAttributes.shiny : true;
|
||||||
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined);
|
this.setSpeciesDetails(this.lastSpecies, !props.shiny, undefined, undefined, props.shiny ? 0 : undefined, undefined, undefined);
|
||||||
if (this.dexAttrCursor & DexAttr.SHINY) {
|
if (starterAttributes.shiny) {
|
||||||
this.scene.playSound("sparkle");
|
this.scene.playSound("sparkle");
|
||||||
// Set the variant label to the shiny tint
|
// Set the variant label to the shiny tint
|
||||||
const tint = getVariantTint(newVariant);
|
const tint = getVariantTint(newVariant);
|
||||||
|
@ -1680,6 +1678,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.pokemonShinyIcon.setTint(tint);
|
this.pokemonShinyIcon.setTint(tint);
|
||||||
this.pokemonShinyIcon.setVisible(true);
|
this.pokemonShinyIcon.setVisible(true);
|
||||||
} else {
|
} else {
|
||||||
|
// starterAttributes.variant = 0;
|
||||||
|
if (starterAttributes?.variant) {
|
||||||
|
delete starterAttributes.variant;
|
||||||
|
}
|
||||||
this.pokemonShinyIcon.setVisible(false);
|
this.pokemonShinyIcon.setVisible(false);
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
@ -1948,6 +1950,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.updateInstructions();
|
this.updateInstructions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePartyIcon(species: PokemonSpecies, index: number) {
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
|
||||||
|
this.starterIcons[index].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
||||||
|
this.starterIcons[index].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
||||||
|
this.checkIconId(this.starterIcons[index], species, props.female, props.formIndex, props.shiny, props.variant);
|
||||||
|
}
|
||||||
|
|
||||||
switchMoveHandler(i: number, newMove: Moves, move: Moves) {
|
switchMoveHandler(i: number, newMove: Moves, move: Moves) {
|
||||||
const speciesId = this.lastSpecies.speciesId;
|
const speciesId = this.lastSpecies.speciesId;
|
||||||
const existingMoveIndex = this.starterMoveset?.indexOf(newMove)!; // TODO: is this bang correct?
|
const existingMoveIndex = this.starterMoveset?.indexOf(newMove)!; // TODO: is this bang correct?
|
||||||
|
@ -2099,9 +2108,24 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
// pre filter for challenges
|
// pre filter for challenges
|
||||||
if (this.scene.gameMode.modeId === GameModes.CHALLENGE) {
|
if (this.scene.gameMode.modeId === GameModes.CHALLENGE) {
|
||||||
this.starterContainers.forEach(container => {
|
this.starterContainers.forEach(container => {
|
||||||
|
const species = container.species;
|
||||||
|
let allFormsValid = false;
|
||||||
|
if (species.forms?.length > 0) {
|
||||||
|
for (let i = 0; i < species.forms.length; i++) {
|
||||||
|
/* Here we are making a fake form index dex props for challenges
|
||||||
|
* Since some pokemon rely on forms to be valid (i.e. blaze tauros for fire challenges), we make a fake form and dex props to use in the challenge
|
||||||
|
*/
|
||||||
|
const tempFormProps = BigInt(Math.pow(2, i)) * DexAttr.DEFAULT_FORM;
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(container.species, this.scene.gameData.getSpeciesDefaultDexAttr(container.species, false, true)), true);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, tempFormProps), true);
|
||||||
if (isValidForChallenge.value) {
|
allFormsValid = allFormsValid || isValidForChallenge.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, container.species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(container.species, false, true)), true);
|
||||||
|
allFormsValid = isValidForChallenge.value;
|
||||||
|
}
|
||||||
|
if (allFormsValid) {
|
||||||
this.validStarterContainers.push(container);
|
this.validStarterContainers.push(container);
|
||||||
} else {
|
} else {
|
||||||
container.setVisible(false);
|
container.setVisible(false);
|
||||||
|
@ -2111,6 +2135,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.validStarterContainers = this.starterContainers;
|
this.validStarterContainers = this.starterContainers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this updates icons for previously saved pokemon
|
||||||
|
for (let i = 0; i < this.validStarterContainers.length; i++) {
|
||||||
|
const currentFilteredContainer = this.validStarterContainers[i];
|
||||||
|
const starterSprite = currentFilteredContainer.icon as Phaser.GameObjects.Sprite;
|
||||||
|
|
||||||
|
const currentDexAttr = this.getCurrentDexProps(currentFilteredContainer.species.speciesId);
|
||||||
|
const props = this.scene.gameData.getSpeciesDexAttrProps(currentFilteredContainer.species, currentDexAttr);
|
||||||
|
|
||||||
|
starterSprite.setTexture(currentFilteredContainer.species.getIconAtlasKey(props.formIndex, props.shiny, props.variant), currentFilteredContainer.species.getIconId(props.female!, props.formIndex, props.shiny, props.variant));
|
||||||
|
currentFilteredContainer.checkIconId(props.female, props.formIndex, props.shiny, props.variant);
|
||||||
|
}
|
||||||
|
|
||||||
// filter
|
// filter
|
||||||
this.validStarterContainers.forEach(container => {
|
this.validStarterContainers.forEach(container => {
|
||||||
container.setVisible(false);
|
container.setVisible(false);
|
||||||
|
@ -2336,9 +2372,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
const species = this.filteredStarterContainers[cursor]?.species;
|
const species = this.filteredStarterContainers[cursor]?.species;
|
||||||
|
|
||||||
if (species) {
|
if (species) {
|
||||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
const variant = defaultProps.variant;
|
const variant = this.starterPreferences[species.speciesId]?.variant ? this.starterPreferences[species.speciesId].variant as Variant : defaultProps.variant;
|
||||||
const tint = getVariantTint(variant);
|
const tint = getVariantTint(variant);
|
||||||
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
this.pokemonShinyIcon.setFrame(getVariantIcon(variant));
|
||||||
this.pokemonShinyIcon.setTint(tint);
|
this.pokemonShinyIcon.setTint(tint);
|
||||||
|
@ -2384,7 +2420,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
|
|
||||||
setSpecies(species: PokemonSpecies | null) {
|
setSpecies(species: PokemonSpecies | null) {
|
||||||
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
|
this.speciesStarterDexEntry = species ? this.scene.gameData.dexData[species.speciesId] : null;
|
||||||
this.dexAttrCursor = species ? this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true) : 0n;
|
this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n;
|
||||||
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
|
this.abilityCursor = species ? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
|
||||||
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0;
|
this.natureCursor = species ? this.scene.gameData.getSpeciesDefaultNature(species) : 0;
|
||||||
|
|
||||||
|
@ -2454,7 +2490,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastSpecies) {
|
if (this.lastSpecies) {
|
||||||
const dexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(this.lastSpecies, false, true);
|
const dexAttr = this.getCurrentDexProps(this.lastSpecies.speciesId);
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr);
|
const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, dexAttr);
|
||||||
const speciesIndex = this.allSpecies.indexOf(this.lastSpecies);
|
const speciesIndex = this.allSpecies.indexOf(this.lastSpecies);
|
||||||
const lastSpeciesIcon = this.starterContainers[speciesIndex].icon;
|
const lastSpeciesIcon = this.starterContainers[speciesIndex].icon;
|
||||||
|
@ -2480,7 +2516,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.pokemonLuckText.setText(luck.toString());
|
this.pokemonLuckText.setText(luck.toString());
|
||||||
this.pokemonLuckText.setTint(getVariantTint(Math.min(luck - 1, 2) as Variant));
|
this.pokemonLuckText.setTint(getVariantTint(Math.min(luck - 1, 2) as Variant));
|
||||||
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
||||||
this.pokemonShinyIcon.setVisible(this.pokemonLuckText.visible);
|
this.pokemonShinyIcon.setVisible(this.starterPreferences[species.speciesId]?.shiny ?? false);
|
||||||
|
|
||||||
//Growth translate
|
//Growth translate
|
||||||
let growthReadable = Utils.toReadableString(GrowthRate[species.growthRate]);
|
let growthReadable = Utils.toReadableString(GrowthRate[species.growthRate]);
|
||||||
|
@ -2504,7 +2540,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species));
|
this.pokemonHatchedIcon.setFrame(getEggTierForSpecies(species));
|
||||||
}
|
}
|
||||||
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`);
|
this.pokemonHatchedCountText.setText(`${this.speciesStarterDexEntry.hatchedCount}`);
|
||||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
const defaultProps = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
const variant = defaultProps.variant;
|
const variant = defaultProps.variant;
|
||||||
const tint = getVariantTint(variant);
|
const tint = getVariantTint(variant);
|
||||||
|
@ -2578,13 +2614,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
props = this.scene.gameData.getSpeciesDexAttrProps(species, this.starterAttr[starterIndex]);
|
props = this.scene.gameData.getSpeciesDexAttrProps(species, this.starterAttr[starterIndex]);
|
||||||
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]);
|
this.setSpeciesDetails(species, props.shiny, props.formIndex, props.female, props.variant, this.starterAbilityIndexes[starterIndex], this.starterNatures[starterIndex]);
|
||||||
} else {
|
} else {
|
||||||
const defaultDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
const defaultAbilityIndex = starterAttributes?.ability ?? this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||||
// load default nature from stater save data, if set
|
// load default nature from stater save data, if set
|
||||||
const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species);
|
const defaultNature = starterAttributes?.nature || this.scene.gameData.getSpeciesDefaultNature(species);
|
||||||
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
props = this.scene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr);
|
||||||
if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) {
|
if (starterAttributes?.variant && !isNaN(starterAttributes.variant)) {
|
||||||
if (props.shiny = (starterAttributes.variant >= 0)) {
|
if (props.shiny) {
|
||||||
props.variant = starterAttributes.variant as Variant;
|
props.variant = starterAttributes.variant as Variant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2679,6 +2715,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct?
|
this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct?
|
||||||
this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex);
|
this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex);
|
||||||
this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex);
|
this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex);
|
||||||
|
const [isInParty, partyIndex]: [boolean, number] = this.isInParty(species); // we use this to firstly check if the pokemon is in the party, and if so, to get the party index in order to update the icon image
|
||||||
|
if (isInParty) {
|
||||||
|
this.updatePartyIcon(species, partyIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pokemonSprite.setVisible(false);
|
this.pokemonSprite.setVisible(false);
|
||||||
|
@ -2695,7 +2735,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
const dexEntry = this.scene.gameData.dexData[species.speciesId];
|
||||||
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr;
|
const abilityAttr = this.scene.gameData.starterData[species.speciesId].abilityAttr;
|
||||||
if (!dexEntry.caughtAttr) {
|
if (!dexEntry.caughtAttr) {
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, forSeen, !forSeen));
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
|
||||||
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
const defaultAbilityIndex = this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
|
||||||
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
const defaultNature = this.scene.gameData.getSpeciesDefaultNature(species);
|
||||||
if (shiny === undefined || shiny !== props.shiny) {
|
if (shiny === undefined || shiny !== props.shiny) {
|
||||||
|
@ -2750,9 +2790,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
|
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), !!this.starterSpecies.length);
|
||||||
const starterSprite = this.filteredStarterContainers[this.cursor].icon as Phaser.GameObjects.Sprite;
|
const currentFilteredContainer = this.filteredStarterContainers.find(p => p.species.speciesId === species.speciesId)!;
|
||||||
starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female!, formIndex, shiny, variant)); // TODO: is this bang correct?
|
const starterSprite = currentFilteredContainer.icon as Phaser.GameObjects.Sprite;
|
||||||
this.filteredStarterContainers[this.cursor].checkIconId(female, formIndex, shiny, variant);
|
starterSprite.setTexture(species.getIconAtlasKey(formIndex, shiny, variant), species.getIconId(female!, formIndex, shiny, variant));
|
||||||
|
currentFilteredContainer.checkIconId(female, formIndex, shiny, variant);
|
||||||
this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY);
|
this.canCycleShiny = !!(dexEntry.caughtAttr & DexAttr.NON_SHINY && dexEntry.caughtAttr & DexAttr.SHINY);
|
||||||
this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE);
|
this.canCycleGender = !!(dexEntry.caughtAttr & DexAttr.MALE && dexEntry.caughtAttr & DexAttr.FEMALE);
|
||||||
this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, (abilityAttr & AbilityAttr.ABILITY_2) && species.ability2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
this.canCycleAbility = [ abilityAttr & AbilityAttr.ABILITY_1, (abilityAttr & AbilityAttr.ABILITY_2) && species.ability2, abilityAttr & AbilityAttr.ABILITY_HIDDEN ].filter(a => a).length > 1;
|
||||||
|
@ -2876,6 +2917,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
this.pokemonAdditionalMoveCountLabel.setText(`(+${Math.max(this.speciesStarterMoves.length - 4, 0)})`);
|
this.pokemonAdditionalMoveCountLabel.setText(`(+${Math.max(this.speciesStarterMoves.length - 4, 0)})`);
|
||||||
this.pokemonAdditionalMoveCountLabel.setVisible(this.speciesStarterMoves.length > 4);
|
this.pokemonAdditionalMoveCountLabel.setVisible(this.speciesStarterMoves.length > 4);
|
||||||
|
|
||||||
|
this.tryUpdateValue();
|
||||||
|
|
||||||
this.updateInstructions();
|
this.updateInstructions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2903,7 +2946,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
|
|
||||||
for (let s = 0; s < this.starterSpecies.length; s++) {
|
for (let s = 0; s < this.starterSpecies.length; s++) {
|
||||||
const species = this.starterSpecies[s];
|
const species = this.starterSpecies[s];
|
||||||
const currentDexAttr = this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true);
|
const currentDexAttr = this.getCurrentDexProps(species.speciesId);
|
||||||
const props = this.scene.gameData.getSpeciesDexAttrProps(species, currentDexAttr);
|
const props = this.scene.gameData.getSpeciesDexAttrProps(species, currentDexAttr);
|
||||||
this.starterIcons[s].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
this.starterIcons[s].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
|
||||||
this.starterIcons[s].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
this.starterIcons[s].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
|
||||||
|
@ -2984,7 +3027,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
if (addingToParty) { // this does a check to see if the pokemon being added is valid; if so, it will update the isPartyValid boolean
|
if (addingToParty) { // this does a check to see if the pokemon being added is valid; if so, it will update the isPartyValid boolean
|
||||||
const isNewPokemonValid = new Utils.BooleanHolder(true);
|
const isNewPokemonValid = new Utils.BooleanHolder(true);
|
||||||
const species = this.filteredStarterContainers[this.cursor].species;
|
const species = this.filteredStarterContainers[this.cursor].species;
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isNewPokemonValid, this.scene.gameData.getSpeciesDexAttrProps(species, this.scene.gameData.getSpeciesDefaultDexAttr(species, false, true)), !!(this.starterSpecies.length), false, false);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isNewPokemonValid, this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), false);
|
||||||
isPartyValid = isPartyValid || isNewPokemonValid.value;
|
isPartyValid = isPartyValid || isNewPokemonValid.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3013,11 +3056,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
* we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too.
|
* we change to can AddParty value to true since the user has enough cost to choose this pokemon and this pokemon registered too.
|
||||||
*/
|
*/
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
if (isPartyValid) { // we have two checks here - one for the party being valid and one for not. This comes from mono type challenges - if the party is valid it will check pokemon's evolutions and forms, and if it's not valid it won't check their evolutions and forms
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.getCurrentDexProps(this.allSpecies[s].speciesId)), isPartyValid);
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.scene.gameData.getSpeciesDefaultDexAttr(this.allSpecies[s], false, true)), !!(this.starterSpecies.length + (add ? 1 : 0)));
|
|
||||||
} else {
|
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, this.allSpecies[s], isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(this.allSpecies[s], this.scene.gameData.getSpeciesDefaultDexAttr(this.allSpecies[s], false, true)), !!(this.starterSpecies.length + (add ? 1 : 0)), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value;
|
const canBeChosen = remainValue >= speciesStarterValue && isValidForChallenge.value;
|
||||||
|
|
||||||
|
@ -3132,12 +3171,50 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||||
for (let s = 0; s < this.starterSpecies.length; s++) {
|
for (let s = 0; s < this.starterSpecies.length; s++) {
|
||||||
const isValidForChallenge = new Utils.BooleanHolder(true);
|
const isValidForChallenge = new Utils.BooleanHolder(true);
|
||||||
const species = this.starterSpecies[s];
|
const species = this.starterSpecies[s];
|
||||||
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor), this.starterSpecies.length !== 0, false, false);
|
Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_CHOICE, species, isValidForChallenge, this.scene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), false);
|
||||||
canStart = canStart || isValidForChallenge.value;
|
canStart = canStart || isValidForChallenge.value;
|
||||||
}
|
}
|
||||||
return canStart;
|
return canStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this creates a temporary dex attr props that we use to check whether a pokemon is valid for a challenge.
|
||||||
|
* when checking for certain challenges (i.e. mono type), we need to check for form changes AND evolutions
|
||||||
|
* However, since some pokemon can evolve based on their intial gender/form, we need a way to look for that
|
||||||
|
* This temporary dex attr will therefore ONLY look at gender and form, since there's no cases of shinies/variants
|
||||||
|
* having different evolutions to their non shiny/variant part, and so those can be ignored
|
||||||
|
* Since the current form and gender is stored in the starter preferences, this is where we get the values from
|
||||||
|
*/
|
||||||
|
getCurrentDexProps(speciesId: number): bigint {
|
||||||
|
let props = 0n;
|
||||||
|
|
||||||
|
if (this.starterPreferences[speciesId]?.female) { // this checks the gender of the pokemon
|
||||||
|
props += DexAttr.FEMALE;
|
||||||
|
} else {
|
||||||
|
props += DexAttr.MALE;
|
||||||
|
}
|
||||||
|
if (this.starterPreferences[speciesId]?.shiny) {
|
||||||
|
props += DexAttr.SHINY;
|
||||||
|
if (this.starterPreferences[speciesId]?.variant) {
|
||||||
|
props += BigInt(Math.pow(2, this.starterPreferences[speciesId]?.variant)) * DexAttr.DEFAULT_VARIANT;
|
||||||
|
} else {
|
||||||
|
props += DexAttr.DEFAULT_VARIANT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
props += DexAttr.NON_SHINY;
|
||||||
|
if (this.starterPreferences[speciesId]?.variant) {
|
||||||
|
delete this.starterPreferences[speciesId].variant;
|
||||||
|
}
|
||||||
|
props += DexAttr.DEFAULT_VARIANT; // we add the default variant here because non shiny versions are listed as default variant
|
||||||
|
}
|
||||||
|
if (this.starterPreferences[speciesId]?.form) { // this checks for the form of the pokemon
|
||||||
|
props += BigInt(Math.pow(2, this.starterPreferences[speciesId]?.form)) * DexAttr.DEFAULT_FORM;
|
||||||
|
} else {
|
||||||
|
props += DexAttr.DEFAULT_FORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
toggleStatsMode(on?: boolean): void {
|
toggleStatsMode(on?: boolean): void {
|
||||||
if (on === undefined) {
|
if (on === undefined) {
|
||||||
on = !this.statsMode;
|
on = !this.statsMode;
|
||||||
|
|
Loading…
Reference in New Issue