mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-02-25 05:28:27 +00:00
implement illusion ability with unit test and localizations
This commit is contained in:
parent
bfc44ea35e
commit
9f26ea983b
@ -851,7 +851,7 @@ export default class BattleScene extends SceneBase {
|
|||||||
|
|
||||||
container.add(icon);
|
container.add(icon);
|
||||||
|
|
||||||
if (pokemon.isFusion()) {
|
if (pokemon.isFusion(true)) {
|
||||||
const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride));
|
const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride));
|
||||||
fusionIcon.setName("sprite-fusion-icon");
|
fusionIcon.setName("sprite-fusion-icon");
|
||||||
fusionIcon.setOrigin(0.5, 0);
|
fusionIcon.setOrigin(0.5, 0);
|
||||||
|
120
src/data/ability.ts
Normal file → Executable file
120
src/data/ability.ts
Normal file → Executable file
@ -1885,7 +1885,6 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PostSummonMessageAbAttr extends PostSummonAbAttr {
|
export class PostSummonMessageAbAttr extends PostSummonAbAttr {
|
||||||
private messageFunc: (pokemon: Pokemon) => string;
|
private messageFunc: (pokemon: Pokemon) => string;
|
||||||
|
|
||||||
@ -1898,6 +1897,11 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr {
|
|||||||
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
pokemon.scene.queueMessage(this.messageFunc(pokemon));
|
pokemon.scene.queueMessage(this.messageFunc(pokemon));
|
||||||
|
|
||||||
|
pokemon.scene.getField(true).map(pokemon => {
|
||||||
|
if (pokemon.breakIllusion()) {
|
||||||
|
pokemon.scene.queueMessage(i18next.t("abilityTriggers:illusionBreak", { pokemonName: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2262,6 +2266,10 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
|
|||||||
target = targets[0];
|
target = targets[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target.illusion.active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pokemon.summonData.speciesForm = target.getSpeciesForm();
|
pokemon.summonData.speciesForm = target.getSpeciesForm();
|
||||||
pokemon.summonData.fusionSpeciesForm = target.getFusionSpeciesForm();
|
pokemon.summonData.fusionSpeciesForm = target.getFusionSpeciesForm();
|
||||||
pokemon.summonData.ability = target.getAbility().id;
|
pokemon.summonData.ability = target.getAbility().id;
|
||||||
@ -3554,8 +3562,8 @@ export class MaxMultiHitAbAttr extends AbAttr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PostBattleAbAttr extends AbAttr {
|
export class PostBattleAbAttr extends AbAttr {
|
||||||
constructor() {
|
constructor(showAbility: boolean = true) {
|
||||||
super(true);
|
super(showAbility);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
@ -4041,6 +4049,97 @@ export class IceFaceBlockPhysicalAbAttr extends ReceivedMoveDamageMultiplierAbAt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class PreSummonAbAttr extends AbAttr {
|
||||||
|
applyPreSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IllusionPreSummonAbAttr extends PreSummonAbAttr {
|
||||||
|
/**
|
||||||
|
* Apply a new illusion when summoning Zoroark if the illusion is available
|
||||||
|
*
|
||||||
|
* @param {Pokemon} pokemon - The Pokémon with the Illusion ability.
|
||||||
|
* @param {boolean} passive - N/A
|
||||||
|
* @param {...any} args - N/A
|
||||||
|
* @returns {boolean} - Whether the illusion was applied.
|
||||||
|
*/
|
||||||
|
applyPreSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
|
let suppressed = false;
|
||||||
|
pokemon.scene.getField(true).filter(p => p !== pokemon).map(p => {
|
||||||
|
if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) {
|
||||||
|
suppressed = true;
|
||||||
|
}
|
||||||
|
if (p.getPassiveAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility(true)) {
|
||||||
|
suppressed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pokemon.illusion.available && !suppressed) {
|
||||||
|
return pokemon.generateIllusion();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IllusionBreakAbAttr extends PostDefendAbAttr {
|
||||||
|
/**
|
||||||
|
* Destroy illusion if attack move deals damage to zoroark
|
||||||
|
*
|
||||||
|
* @param {Pokemon} pokemon - The Pokémon with the Illusion ability.
|
||||||
|
* @param {boolean} passive - N/A
|
||||||
|
* @param {Pokemon} attacker - The attacking Pokémon.
|
||||||
|
* @param {PokemonMove} move - The move being used.
|
||||||
|
* @param {PokemonMove} hitResult - The type of hitResult the pokemon got
|
||||||
|
* @param {...any} args - N/A
|
||||||
|
* @returns {boolean} - Whether the illusion was destroyed.
|
||||||
|
*/
|
||||||
|
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean {
|
||||||
|
|
||||||
|
const breakIllusion: HitResult[] = [HitResult.EFFECTIVE, HitResult.SUPER_EFFECTIVE, HitResult.NOT_VERY_EFFECTIVE, HitResult.ONE_HIT_KO];
|
||||||
|
if (!breakIllusion.includes(hitResult)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pokemon.breakIllusion();
|
||||||
|
pokemon.scene.queueMessage(i18next.t("abilityTriggers:illusionBreak", { pokemonName: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IllusionAfterBattle extends PostBattleAbAttr {
|
||||||
|
/**
|
||||||
|
* Illusion will be available again after a battle and apply the illusion of the pokemon is already on field
|
||||||
|
*
|
||||||
|
* @param {Pokemon} pokemon - The Pokémon with the Illusion ability.
|
||||||
|
* @param {boolean} passive - N/A
|
||||||
|
* @param {...any} args - N/A
|
||||||
|
* @returns {boolean} - Whether the illusion was applied.
|
||||||
|
*/
|
||||||
|
applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
|
pokemon.breakIllusion();
|
||||||
|
pokemon.illusion.available = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IllusionDisableAbAttr extends PostSummonAbAttr {
|
||||||
|
/**
|
||||||
|
* Illusion will be disabled if the pokemon is summoned with an illusion.
|
||||||
|
* So the pokemon can use 1 illusion per battle.
|
||||||
|
*
|
||||||
|
* @param {Pokemon} pokemon - The Pokémon with the Illusion ability.
|
||||||
|
* @param {boolean} passive - N/A
|
||||||
|
* @param {...any} args - N/A
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
|
||||||
|
pokemon.illusion.available = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a Pokémon with this Ability selects a damaging move, it has a 30% chance of going first in its priority bracket. If the Ability activates, this is announced at the start of the turn (after move selection).
|
* If a Pokémon with this Ability selects a damaging move, it has a 30% chance of going first in its priority bracket. If the Ability activates, this is announced at the start of the turn (after move selection).
|
||||||
*
|
*
|
||||||
@ -4216,6 +4315,11 @@ export function applyPostSummonAbAttrs(attrType: Constructor<PostSummonAbAttr>,
|
|||||||
return applyAbAttrsInternal<PostSummonAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, args), args);
|
return applyAbAttrsInternal<PostSummonAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, args), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function applyPreSummonAbAttrs(attrType: Constructor<PreSummonAbAttr>,
|
||||||
|
pokemon: Pokemon, ...args: any[]) {
|
||||||
|
return applyAbAttrsInternal<PreSummonAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreSummon(pokemon, passive, args), args);
|
||||||
|
}
|
||||||
|
|
||||||
export function applyPreSwitchOutAbAttrs(attrType: Constructor<PreSwitchOutAbAttr>,
|
export function applyPreSwitchOutAbAttrs(attrType: Constructor<PreSwitchOutAbAttr>,
|
||||||
pokemon: Pokemon, ...args: any[]): Promise<void> {
|
pokemon: Pokemon, ...args: any[]): Promise<void> {
|
||||||
return applyAbAttrsInternal<PreSwitchOutAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, args), args, true);
|
return applyAbAttrsInternal<PreSwitchOutAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, args), args, true);
|
||||||
@ -4759,7 +4863,15 @@ export function initAbilities() {
|
|||||||
new Ability(Abilities.ILLUSION, 5)
|
new Ability(Abilities.ILLUSION, 5)
|
||||||
.attr(UncopiableAbilityAbAttr)
|
.attr(UncopiableAbilityAbAttr)
|
||||||
.attr(UnswappableAbilityAbAttr)
|
.attr(UnswappableAbilityAbAttr)
|
||||||
.unimplemented(),
|
//The pokemon generate an illusion if it's available
|
||||||
|
.conditionalAttr((pokemon) => pokemon.illusion.available, IllusionPreSummonAbAttr, false)
|
||||||
|
//The pokemon loses his illusion when he is damaged by a move
|
||||||
|
.conditionalAttr((pokemon) => pokemon.illusion.active, IllusionBreakAbAttr, true)
|
||||||
|
//Illusion is available again after a battle
|
||||||
|
.conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionAfterBattle, false)
|
||||||
|
//Illusion is not available after summon
|
||||||
|
.attr(IllusionDisableAbAttr, false)
|
||||||
|
.bypassFaint(),
|
||||||
new Ability(Abilities.IMPOSTER, 5)
|
new Ability(Abilities.IMPOSTER, 5)
|
||||||
.attr(PostSummonTransformAbAttr)
|
.attr(PostSummonTransformAbAttr)
|
||||||
.attr(UncopiableAbilityAbAttr),
|
.attr(UncopiableAbilityAbAttr),
|
||||||
|
@ -5486,10 +5486,12 @@ export class AbilityChangeAttr extends MoveEffectAttr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
(this.selfTarget ? user : target).summonData.ability = this.ability;
|
const pokemon: Pokemon = this.selfTarget ? user : target;
|
||||||
|
pokemon.summonData.ability = this.ability;
|
||||||
user.scene.queueMessage(i18next.t("moveTriggers:acquiredAbility", {pokemonName: getPokemonNameWithAffix((this.selfTarget ? user : target)), abilityName: allAbilities[this.ability].name}));
|
if (pokemon.breakIllusion()) {
|
||||||
|
pokemon.scene.queueMessage(i18next.t("abilityTriggers:illusionBreak", { pokemonName: getPokemonNameWithAffix(pokemon) }));
|
||||||
|
}
|
||||||
|
user.scene.queueMessage(i18next.t("moveTriggers:acquiredAbility", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: allAbilities[this.ability].name}));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5641,7 +5643,8 @@ export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr {
|
|||||||
export class TransformAttr extends MoveEffectAttr {
|
export class TransformAttr extends MoveEffectAttr {
|
||||||
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (!super.apply(user, target, move, args)) {
|
if (!super.apply(user, target, move, args) || target.illusion.active || user.illusion.active) {
|
||||||
|
user.scene.queueMessage(i18next.t("battle:attackFailed"));
|
||||||
return resolve(false);
|
return resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
public name: string;
|
public name: string;
|
||||||
public nickname: string;
|
public nickname: string;
|
||||||
public species: PokemonSpecies;
|
public species: PokemonSpecies;
|
||||||
|
public illusion: Illusion;
|
||||||
public formIndex: integer;
|
public formIndex: integer;
|
||||||
public abilityIndex: integer;
|
public abilityIndex: integer;
|
||||||
public passive: boolean;
|
public passive: boolean;
|
||||||
@ -126,6 +127,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
const randAbilityIndex = Utils.randSeedInt(2);
|
const randAbilityIndex = Utils.randSeedInt(2);
|
||||||
|
|
||||||
this.species = species;
|
this.species = species;
|
||||||
|
this.illusion = {active: false, available: true};
|
||||||
|
|
||||||
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
|
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
// Determine the ability index
|
// Determine the ability index
|
||||||
@ -240,15 +243,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getNameToRender() {
|
getNameToRender(useIllusion: boolean = true) {
|
||||||
|
const name: string = (!useIllusion && this.illusion.active) ? this.illusion.name : this.name;
|
||||||
|
const nickname: string = (!useIllusion && this.illusion.active) ? this.illusion.nickname : this.nickname;
|
||||||
try {
|
try {
|
||||||
if (this.nickname) {
|
if (nickname) {
|
||||||
return decodeURIComponent(escape(atob(this.nickname)));
|
return decodeURIComponent(escape(atob(nickname)));
|
||||||
}
|
}
|
||||||
return this.name;
|
return name;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Failed to decode nickname for ${this.name}`, err);
|
console.error(`Failed to decode nickname for ${name}`, err);
|
||||||
return this.name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +281,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
this.addAt(sprite, 0);
|
this.addAt(sprite, 0);
|
||||||
this.addAt(tintSprite, 1);
|
this.addAt(tintSprite, 1);
|
||||||
|
|
||||||
if (this.isShiny() && !this.shinySparkle) {
|
if (this.isShiny(true) && !this.shinySparkle) {
|
||||||
this.initShinySparkle();
|
this.initShinySparkle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -337,6 +342,113 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an illusion of the last pokemon in the party, as other wild pokemon in the area.
|
||||||
|
*
|
||||||
|
* @param {Pokemon} pokemon - The Pokemon that will create an illusion.
|
||||||
|
* @param {Pokemon[]} party - The party of the trainer's pokemon.
|
||||||
|
*/
|
||||||
|
generateIllusion(): boolean {
|
||||||
|
if (this.hasTrainer()) {
|
||||||
|
const party: Pokemon[] = (this.isPlayer() ? this.scene.getParty() : this.scene.getEnemyParty()).filter(p => p.isAllowedInBattle());
|
||||||
|
const lastPokemon: Pokemon = party.at(-1);
|
||||||
|
const speciesId = lastPokemon.species.speciesId;
|
||||||
|
|
||||||
|
if ( lastPokemon === this || this.illusion.active ||
|
||||||
|
((speciesId === Species.OGERPON || speciesId === Species.TERAPAGOS) && (lastPokemon.isTerastallized() || this.isTerastallized()))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.illusion = {
|
||||||
|
active: true,
|
||||||
|
available: true,
|
||||||
|
name: this.name,
|
||||||
|
nickname: this.nickname,
|
||||||
|
species: getPokemonSpecies(speciesId),
|
||||||
|
formIndex: lastPokemon.formIndex,
|
||||||
|
shiny: this.shiny,
|
||||||
|
variant: this.variant,
|
||||||
|
shinySparkle: this.shinySparkle,
|
||||||
|
gender: lastPokemon.gender,
|
||||||
|
pokeball: lastPokemon.pokeball,
|
||||||
|
fusionFormIndex: lastPokemon.fusionFormIndex,
|
||||||
|
fusionSpecies: lastPokemon.fusionSpecies,
|
||||||
|
fusionVariant: this.fusionVariant,
|
||||||
|
fusionShiny: this.fusionShiny,
|
||||||
|
fusionGender: lastPokemon.fusionGender
|
||||||
|
};
|
||||||
|
|
||||||
|
this.name = lastPokemon.name;
|
||||||
|
this.nickname = lastPokemon.nickname;
|
||||||
|
this.shiny = lastPokemon.shiny;
|
||||||
|
this.variant = lastPokemon.variant;
|
||||||
|
this.fusionVariant = lastPokemon.fusionVariant;
|
||||||
|
this.fusionShiny = lastPokemon.fusionShiny;
|
||||||
|
if (this.shiny) {
|
||||||
|
this.initShinySparkle();
|
||||||
|
}
|
||||||
|
this.loadAssets(false, true).then(() => this.playAnim());
|
||||||
|
} else {
|
||||||
|
let availables: Species[] = [];
|
||||||
|
if (this.isBoss()) {
|
||||||
|
availables = [Species.ENTEI, Species.RAIKOU, Species.SUICUNE];
|
||||||
|
} else {
|
||||||
|
const area: Species[] = [
|
||||||
|
Species.HOUNDOUR, Species.SABLEYE, Species.PURRLOIN, Species.PAWNIARD, Species.NICKIT,
|
||||||
|
Species.IMPIDIMP, Species.MASCHIFF, Species.ABSOL, Species.SPIRITOMB, Species.DEINO,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let species of area) {
|
||||||
|
for (const evolutionLevel of getPokemonSpecies(species).getEvolutionLevels()) {
|
||||||
|
if (evolutionLevel[1] && evolutionLevel[1] <= this.level) {
|
||||||
|
species = evolutionLevel[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
availables.push(species);
|
||||||
|
}
|
||||||
|
availables.push(this.species.name === getPokemonSpecies(Species.ZORUA).name ? Species.MURKROW : Species.HONCHKROW);
|
||||||
|
}
|
||||||
|
const randomIllusion: PokemonSpecies = getPokemonSpecies(availables[this.randSeedInt(availables.length)]);
|
||||||
|
|
||||||
|
this.illusion = {
|
||||||
|
active: true,
|
||||||
|
available: true,
|
||||||
|
species: randomIllusion,
|
||||||
|
name: this.name,
|
||||||
|
shiny: this.shiny,
|
||||||
|
variant: this.variant,
|
||||||
|
shinySparkle: this.shinySparkle,
|
||||||
|
gender: this.gender
|
||||||
|
};
|
||||||
|
this.name = randomIllusion.name;
|
||||||
|
this.loadAssets(false, true).then(() => this.playAnim());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
breakIllusion(): boolean {
|
||||||
|
if (!this.illusion.active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = this.illusion.name;
|
||||||
|
this.nickname = this.illusion.nickname;
|
||||||
|
this.shiny = this.illusion.shiny;
|
||||||
|
this.variant = this.illusion.variant;
|
||||||
|
this.fusionVariant = this.illusion.fusionVariant;
|
||||||
|
this.fusionShiny = this.illusion.fusionShiny;
|
||||||
|
this.illusion = {active: false, available: false};
|
||||||
|
if (this.isOnField) {
|
||||||
|
this.scene.playSound("PRSFX- Transform");
|
||||||
|
}
|
||||||
|
if (this.shiny) {
|
||||||
|
this.initShinySparkle();
|
||||||
|
}
|
||||||
|
this.loadAssets(false).then(() => this.playAnim());
|
||||||
|
this.updateInfo(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
abstract isPlayer(): boolean;
|
abstract isPlayer(): boolean;
|
||||||
|
|
||||||
abstract hasTrainer(): boolean;
|
abstract hasTrainer(): boolean;
|
||||||
@ -345,18 +457,25 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
abstract getBattlerIndex(): BattlerIndex;
|
abstract getBattlerIndex(): BattlerIndex;
|
||||||
|
|
||||||
loadAssets(ignoreOverride: boolean = true): Promise<void> {
|
/**
|
||||||
|
* @param {boolean} useIllusion - Whether we want the illusion or not.
|
||||||
|
*/
|
||||||
|
loadAssets(ignoreOverride: boolean = true, useIllusion: boolean = false): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const moveIds = this.getMoveset().map(m => m.getMove().id);
|
const moveIds = this.getMoveset().map(m => m.getMove().id);
|
||||||
Promise.allSettled(moveIds.map(m => initMoveAnim(this.scene, m)))
|
Promise.allSettled(moveIds.map(m => initMoveAnim(this.scene, m)))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
loadMoveAnimAssets(this.scene, moveIds);
|
loadMoveAnimAssets(this.scene, moveIds);
|
||||||
this.getSpeciesForm().loadAssets(this.scene, this.getGender() === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
const formIndex = this.illusion.active && useIllusion ? this.illusion.formIndex : this.formIndex;
|
||||||
if (this.isPlayer() || this.getFusionSpeciesForm()) {
|
this.getSpeciesForm(false, useIllusion).loadAssets(this.scene, this.getGender(useIllusion) === Gender.FEMALE, formIndex, this.isShiny(useIllusion), this.getVariant(useIllusion));
|
||||||
|
if (this.isPlayer() || this.getFusionSpeciesForm(false, useIllusion)) {
|
||||||
this.scene.loadPokemonAtlas(this.getBattleSpriteKey(true, ignoreOverride), this.getBattleSpriteAtlasPath(true, ignoreOverride));
|
this.scene.loadPokemonAtlas(this.getBattleSpriteKey(true, ignoreOverride), this.getBattleSpriteAtlasPath(true, ignoreOverride));
|
||||||
}
|
}
|
||||||
if (this.getFusionSpeciesForm()) {
|
if (this.getFusionSpeciesForm(false, useIllusion)) {
|
||||||
this.getFusionSpeciesForm().loadAssets(this.scene, this.getFusionGender() === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
const fusionFormIndex = this.illusion.active && useIllusion ? this.illusion.fusionFormIndex : this.fusionFormIndex;
|
||||||
|
const fusionShiny = this.illusion.active && !useIllusion ? this.illusion.fusionShiny : this.fusionShiny;
|
||||||
|
const fusionVariant = this.illusion.active && !useIllusion ? this.illusion.fusionVariant : this.fusionVariant;
|
||||||
|
this.getFusionSpeciesForm(false, useIllusion).loadAssets(this.scene, this.getFusionGender(false, useIllusion) === Gender.FEMALE, fusionFormIndex, fusionShiny, fusionVariant);
|
||||||
this.scene.loadPokemonAtlas(this.getFusionBattleSpriteKey(true, ignoreOverride), this.getFusionBattleSpriteAtlasPath(true, ignoreOverride));
|
this.scene.loadPokemonAtlas(this.getFusionBattleSpriteKey(true, ignoreOverride), this.getFusionBattleSpriteAtlasPath(true, ignoreOverride));
|
||||||
}
|
}
|
||||||
this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
|
this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
|
||||||
@ -456,18 +575,27 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSpriteId(ignoreOverride?: boolean): string {
|
getSpriteId(ignoreOverride?: boolean): string {
|
||||||
return this.getSpeciesForm(ignoreOverride).getSpriteId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
const formIndex: integer = this.illusion.active ? this.illusion.formIndex : this.formIndex;
|
||||||
|
return this.getSpeciesForm(ignoreOverride, true).getSpriteId(this.getGender(ignoreOverride, true) === Gender.FEMALE, formIndex, this.shiny, this.variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
|
getBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
|
||||||
if (back === undefined) {
|
if (back === undefined) {
|
||||||
back = this.isPlayer();
|
back = this.isPlayer();
|
||||||
}
|
}
|
||||||
return this.getSpeciesForm(ignoreOverride).getSpriteId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant, back);
|
|
||||||
|
const formIndex: integer = this.illusion.active ? this.illusion.formIndex : this.formIndex;
|
||||||
|
|
||||||
|
return this.getSpeciesForm(ignoreOverride, true).getSpriteId(this.getGender(ignoreOverride, true) === Gender.FEMALE, formIndex, this.shiny, this.variant, back);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSpriteKey(ignoreOverride?: boolean): string {
|
getSpriteKey(ignoreOverride?: boolean): string {
|
||||||
return this.getSpeciesForm(ignoreOverride).getSpriteKey(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
return this.getSpeciesForm(ignoreOverride, false).getSpriteKey(
|
||||||
|
this.getGender(ignoreOverride) === Gender.FEMALE,
|
||||||
|
this.formIndex,
|
||||||
|
this.illusion.shiny ?? this.shiny,
|
||||||
|
this.illusion.variant ?? this.variant
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBattleSpriteKey(back?: boolean, ignoreOverride?: boolean): string {
|
getBattleSpriteKey(back?: boolean, ignoreOverride?: boolean): string {
|
||||||
@ -475,14 +603,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFusionSpriteId(ignoreOverride?: boolean): string {
|
getFusionSpriteId(ignoreOverride?: boolean): string {
|
||||||
return this.getFusionSpeciesForm(ignoreOverride).getSpriteId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
const fusionFormIndex: integer = this.illusion.active ? this.illusion.fusionFormIndex : this.fusionFormIndex;
|
||||||
|
return this.getFusionSpeciesForm(ignoreOverride, true).getSpriteId(this.getFusionGender(ignoreOverride, true) === Gender.FEMALE, fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFusionBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
|
getFusionBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
|
||||||
if (back === undefined) {
|
if (back === undefined) {
|
||||||
back = this.isPlayer();
|
back = this.isPlayer();
|
||||||
}
|
}
|
||||||
return this.getFusionSpeciesForm(ignoreOverride).getSpriteId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant, back);
|
|
||||||
|
const fusionFormIndex: integer = this.illusion.active ? this.illusion.fusionFormIndex : this.fusionFormIndex;
|
||||||
|
|
||||||
|
return this.getFusionSpeciesForm(ignoreOverride, true).getSpriteId(this.getFusionGender(ignoreOverride, true) === Gender.FEMALE, fusionFormIndex, this.fusionShiny, this.fusionVariant, back);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFusionBattleSpriteKey(back?: boolean, ignoreOverride?: boolean): string {
|
getFusionBattleSpriteKey(back?: boolean, ignoreOverride?: boolean): string {
|
||||||
@ -494,39 +626,56 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getIconAtlasKey(ignoreOverride?: boolean): string {
|
getIconAtlasKey(ignoreOverride?: boolean): string {
|
||||||
return this.getSpeciesForm(ignoreOverride).getIconAtlasKey(this.formIndex, this.shiny, this.variant);
|
const formIndex: integer = this.illusion.active ? this.illusion.formIndex : this.formIndex;
|
||||||
|
return this.getSpeciesForm(ignoreOverride, true).getIconAtlasKey(formIndex, this.shiny, this.variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFusionIconAtlasKey(ignoreOverride?: boolean): string {
|
getFusionIconAtlasKey(ignoreOverride?: boolean): string {
|
||||||
return this.getFusionSpeciesForm(ignoreOverride).getIconAtlasKey(this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
return this.getFusionSpeciesForm(ignoreOverride, true).getIconAtlasKey(this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIconId(ignoreOverride?: boolean): string {
|
getIconId(ignoreOverride?: boolean): string {
|
||||||
return this.getSpeciesForm(ignoreOverride).getIconId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
|
const formIndex: integer = this.illusion.active ? this.illusion.formIndex : this.formIndex;
|
||||||
|
return this.getSpeciesForm(ignoreOverride, true).getIconId(this.getGender(ignoreOverride, true) === Gender.FEMALE, formIndex, this.shiny, this.variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFusionIconId(ignoreOverride?: boolean): string {
|
getFusionIconId(ignoreOverride?: boolean): string {
|
||||||
return this.getFusionSpeciesForm(ignoreOverride).getIconId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
const fusionFormIndex: integer = this.illusion.active ? this.illusion.fusionFormIndex : this.fusionFormIndex;
|
||||||
|
return this.getFusionSpeciesForm(ignoreOverride, true).getIconId(this.getFusionGender(ignoreOverride, true) === Gender.FEMALE, fusionFormIndex, this.fusionShiny, this.fusionVariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSpeciesForm(ignoreOverride?: boolean): PokemonSpeciesForm {
|
/**
|
||||||
|
* @param {boolean} useIllusion - Whether we want the speciesForm of the illusion or not.
|
||||||
|
*/
|
||||||
|
getSpeciesForm(ignoreOverride?: boolean, useIllusion: boolean = false): PokemonSpeciesForm {
|
||||||
|
const species: PokemonSpecies = useIllusion && this.illusion.active ? this.illusion.species : this.species;
|
||||||
|
const formIndex: integer = useIllusion && this.illusion.active ? this.illusion.formIndex : this.formIndex;
|
||||||
|
|
||||||
if (!ignoreOverride && this.summonData?.speciesForm) {
|
if (!ignoreOverride && this.summonData?.speciesForm) {
|
||||||
return this.summonData.speciesForm;
|
return this.summonData.speciesForm;
|
||||||
}
|
}
|
||||||
if (!this.species.forms?.length) {
|
|
||||||
return this.species;
|
if (!species.forms?.length || formIndex === undefined) {
|
||||||
}
|
return species;
|
||||||
return this.species.forms[this.formIndex];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFusionSpeciesForm(ignoreOverride?: boolean): PokemonSpeciesForm {
|
return species.forms[formIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} useIllusion - Whether we want the fusionSpeciesForm of the illusion or not.
|
||||||
|
*/
|
||||||
|
getFusionSpeciesForm(ignoreOverride?: boolean, useIllusion: boolean = false): PokemonSpeciesForm {
|
||||||
|
const fusionSpecies: PokemonSpecies = useIllusion && this.illusion.active ? this.illusion.fusionSpecies : this.fusionSpecies;
|
||||||
|
const fusionFormIndex: integer = useIllusion && this.illusion.active ? this.illusion.fusionFormIndex : this.fusionFormIndex;
|
||||||
|
|
||||||
if (!ignoreOverride && this.summonData?.speciesForm) {
|
if (!ignoreOverride && this.summonData?.speciesForm) {
|
||||||
return this.summonData.fusionSpeciesForm;
|
return this.summonData.fusionSpeciesForm;
|
||||||
}
|
}
|
||||||
if (!this.fusionSpecies?.forms?.length || this.fusionFormIndex >= this.fusionSpecies?.forms.length) {
|
if (!fusionSpecies?.forms?.length || fusionFormIndex >= fusionSpecies?.forms.length) {
|
||||||
return this.fusionSpecies;
|
return fusionSpecies;
|
||||||
}
|
}
|
||||||
return this.fusionSpecies?.forms[this.fusionFormIndex];
|
return fusionSpecies?.forms[fusionFormIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
getSprite(): Phaser.GameObjects.Sprite {
|
getSprite(): Phaser.GameObjects.Sprite {
|
||||||
@ -835,35 +984,78 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getGender(ignoreOverride?: boolean): Gender {
|
/**
|
||||||
if (!ignoreOverride && this.summonData?.gender !== undefined) {
|
* @param {boolean} useIllusion - Whether we want the gender of the illusion or not.
|
||||||
|
*/
|
||||||
|
getGender(ignoreOverride?: boolean, useIllusion: boolean = false): Gender {
|
||||||
|
if (useIllusion && this.illusion.active) {
|
||||||
|
return this.illusion.gender;
|
||||||
|
} else if (!ignoreOverride && this.summonData?.gender !== undefined) {
|
||||||
return this.summonData.gender;
|
return this.summonData.gender;
|
||||||
}
|
}
|
||||||
return this.gender;
|
return this.gender;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFusionGender(ignoreOverride?: boolean): Gender {
|
/**
|
||||||
if (!ignoreOverride && this.summonData?.fusionGender !== undefined) {
|
* @param {boolean} useIllusion - Whether we want the fusionGender of the illusion or not.
|
||||||
|
*/
|
||||||
|
getFusionGender(ignoreOverride?: boolean, useIllusion: boolean = false): Gender {
|
||||||
|
if (useIllusion && this.illusion.active) {
|
||||||
|
return this.illusion.fusionGender;
|
||||||
|
} else if (!ignoreOverride && this.summonData?.fusionGender !== undefined) {
|
||||||
return this.summonData.fusionGender;
|
return this.summonData.fusionGender;
|
||||||
}
|
}
|
||||||
return this.fusionGender;
|
return this.fusionGender;
|
||||||
}
|
}
|
||||||
|
|
||||||
isShiny(): boolean {
|
isShiny(useIllusion: boolean = false): boolean {
|
||||||
return this.shiny || (this.isFusion() && this.fusionShiny);
|
if (!useIllusion && this.illusion.active) {
|
||||||
|
return this.illusion.shiny || (!!this.illusion.fusionSpecies && this.illusion.fusionShiny);
|
||||||
|
} else {
|
||||||
|
return this.shiny || (this.isFusion(useIllusion) && this.fusionShiny);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getVariant(): Variant {
|
isDoubleShiny(useIllusion: boolean = false): boolean {
|
||||||
return !this.isFusion() ? this.variant : Math.max(this.variant, this.fusionVariant) as Variant;
|
if (!useIllusion && this.illusion.active) {
|
||||||
|
return this.isFusion(false) && this.illusion.shiny && this.illusion.fusionShiny;
|
||||||
|
} else {
|
||||||
|
return this.isFusion(useIllusion) && this.shiny && this.fusionShiny;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getVariant(useIllusion: boolean = false): Variant {
|
||||||
|
if (!useIllusion && this.illusion.active) {
|
||||||
|
return !this.isFusion(false) ? this.illusion.variant : Math.max(this.variant, this.fusionVariant) as Variant;
|
||||||
|
} else {
|
||||||
|
return !this.isFusion(true) ? this.variant : Math.max(this.variant, this.fusionVariant) as Variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getBaseVariant(doubleShiny: boolean): Variant {
|
||||||
|
if (doubleShiny) {
|
||||||
|
return this.illusion.active ? this.illusion.variant : this.variant;
|
||||||
|
} else {
|
||||||
|
return this.getVariant();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getLuck(): integer {
|
getLuck(): integer {
|
||||||
return this.luck + (this.isFusion() ? this.fusionLuck : 0);
|
return this.luck + (this.isFusion() ? this.fusionLuck : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
isFusion(): boolean {
|
isFusion(useIllusion: boolean = false): boolean {
|
||||||
|
if (useIllusion && this.illusion.active) {
|
||||||
|
return !!this.illusion.fusionSpecies;
|
||||||
|
} else {
|
||||||
return !!this.fusionSpecies;
|
return !!this.fusionSpecies;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getName(illusion: boolean = false): string {
|
||||||
|
return (!illusion && this.illusion.active) ? this.illusion.name : this.name;
|
||||||
|
}
|
||||||
|
|
||||||
abstract isBoss(): boolean;
|
abstract isBoss(): boolean;
|
||||||
|
|
||||||
@ -894,30 +1086,29 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the types of a pokemon
|
* Gets the types of a pokemon
|
||||||
* @param includeTeraType boolean to include tera-formed type, default false
|
* @param {boolean} includeTeraType to include tera-formed type, default false
|
||||||
* @param forDefend boolean if the pokemon is defending from an attack
|
* @param {boolean} forDefend if the pokemon is defending from an attack
|
||||||
* @param ignoreOverride boolean if true, ignore ability changing effects
|
* @param {boolean} ignoreOverride if true, ignore ability changing effects
|
||||||
|
* @param {boolean} useIllusion whether we want he types of the illusion or not
|
||||||
* @returns array of {@linkcode Type}
|
* @returns array of {@linkcode Type}
|
||||||
*/
|
*/
|
||||||
getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride?: boolean): Type[] {
|
getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride?: boolean, useIllusion: boolean | "AUTO" = "AUTO"): Type[] {
|
||||||
const types = [];
|
const types: Type[] = [];
|
||||||
|
|
||||||
if (includeTeraType) {
|
if (includeTeraType) {
|
||||||
const teraType = this.getTeraType();
|
const teraType = this.getTeraType();
|
||||||
if (teraType !== Type.UNKNOWN) {
|
if (teraType !== Type.UNKNOWN) {
|
||||||
types.push(teraType);
|
types.push(teraType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!types.length || !includeTeraType) {
|
if (!types.length || !includeTeraType) {
|
||||||
if (!ignoreOverride && this.summonData?.types) {
|
const doIllusion: boolean = useIllusion === "AUTO" ? !forDefend : useIllusion;
|
||||||
|
if (!ignoreOverride && this.summonData?.types && (!this.illusion.active || !doIllusion)) {
|
||||||
this.summonData.types.forEach(t => types.push(t));
|
this.summonData.types.forEach(t => types.push(t));
|
||||||
} else {
|
} else {
|
||||||
const speciesForm = this.getSpeciesForm(ignoreOverride);
|
const speciesForm = this.getSpeciesForm(ignoreOverride, doIllusion);
|
||||||
|
|
||||||
types.push(speciesForm.type1);
|
types.push(speciesForm.type1);
|
||||||
|
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride, doIllusion);
|
||||||
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
|
|
||||||
if (fusionSpeciesForm) {
|
if (fusionSpeciesForm) {
|
||||||
if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) {
|
if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) {
|
||||||
types.push(fusionSpeciesForm.type2);
|
types.push(fusionSpeciesForm.type2);
|
||||||
@ -925,7 +1116,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
types.push(fusionSpeciesForm.type1);
|
types.push(fusionSpeciesForm.type1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types.length === 1 && speciesForm.type2 !== null) {
|
if (types.length === 1 && speciesForm.type2 !== null) {
|
||||||
types.push(speciesForm.type2);
|
types.push(speciesForm.type2);
|
||||||
}
|
}
|
||||||
@ -951,7 +1141,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
types.splice(index, 1);
|
types.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1179,12 +1368,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @param source - The attacking Pokémon.
|
* @param source - The attacking Pokémon.
|
||||||
* @param pokemonMove - The move being used by the attacking Pokémon.
|
* @param pokemonMove - The move being used by the attacking Pokémon.
|
||||||
* @param ignoreAbility - Whether to check for abilities that might affect type effectiveness or immunity.
|
* @param ignoreAbility - Whether to check for abilities that might affect type effectiveness or immunity.
|
||||||
|
* @param {boolean} useIllusion - Whether we want the attack move effectiveness on the illusion or not
|
||||||
* @returns The type damage multiplier, indicating the effectiveness of the move
|
* @returns The type damage multiplier, indicating the effectiveness of the move
|
||||||
*/
|
*/
|
||||||
getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove, ignoreAbility: boolean = false): TypeDamageMultiplier {
|
getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove, ignoreAbility: boolean = false, useIllusion: boolean = false): TypeDamageMultiplier {
|
||||||
const move = pokemonMove.getMove();
|
const move = pokemonMove.getMove();
|
||||||
const typeless = move.hasAttr(TypelessAttr);
|
const typeless = move.hasAttr(TypelessAttr);
|
||||||
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move, source));
|
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move, source, undefined, undefined, useIllusion));
|
||||||
const cancelled = new Utils.BooleanHolder(false);
|
const cancelled = new Utils.BooleanHolder(false);
|
||||||
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
|
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
|
||||||
if (!typeless && !ignoreAbility) {
|
if (!typeless && !ignoreAbility) {
|
||||||
@ -1203,9 +1393,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @param source the Pokemon using the move
|
* @param source the Pokemon using the move
|
||||||
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
|
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
|
||||||
* @param simulated tag to only apply the strong winds effect message when the move is used
|
* @param simulated tag to only apply the strong winds effect message when the move is used
|
||||||
|
* @param {boolean} useIllusion - Whether we want the attack type effectiveness on the illusion or not
|
||||||
* @returns a multiplier for the type effectiveness
|
* @returns a multiplier for the type effectiveness
|
||||||
*/
|
*/
|
||||||
getAttackTypeEffectiveness(moveOrType: Move | Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
|
getAttackTypeEffectiveness(moveOrType: Move | Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true, useIllusion: boolean = false): TypeDamageMultiplier {
|
||||||
const move = (moveOrType instanceof Move)
|
const move = (moveOrType instanceof Move)
|
||||||
? moveOrType
|
? moveOrType
|
||||||
: undefined;
|
: undefined;
|
||||||
@ -1216,7 +1407,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
if (moveType === Type.STELLAR) {
|
if (moveType === Type.STELLAR) {
|
||||||
return this.isTerastallized() ? 2 : 1;
|
return this.isTerastallized() ? 2 : 1;
|
||||||
}
|
}
|
||||||
const types = this.getTypes(true, true);
|
const types = this.getTypes(true, true, undefined, useIllusion);
|
||||||
|
|
||||||
let multiplier = types.map(defType => {
|
let multiplier = types.map(defType => {
|
||||||
if (source) {
|
if (source) {
|
||||||
@ -1253,12 +1444,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
getMatchupScore(pokemon: Pokemon): number {
|
getMatchupScore(pokemon: Pokemon): number {
|
||||||
const types = this.getTypes(true);
|
const types = this.getTypes(true);
|
||||||
const enemyTypes = pokemon.getTypes(true, true);
|
const enemyTypes = pokemon.getTypes(true, true, false, true);
|
||||||
const outspeed = (this.isActive(true) ? this.getBattleStat(Stat.SPD, pokemon) : this.getStat(Stat.SPD)) <= pokemon.getBattleStat(Stat.SPD, this);
|
const outspeed = (this.isActive(true) ? this.getBattleStat(Stat.SPD, pokemon) : this.getStat(Stat.SPD)) <= pokemon.getBattleStat(Stat.SPD, this);
|
||||||
let atkScore = pokemon.getAttackTypeEffectiveness(types[0], this) * (outspeed ? 1.25 : 1);
|
let atkScore = pokemon.getAttackTypeEffectiveness(types[0], this, false, false, true) * (outspeed ? 1.25 : 1);
|
||||||
let defScore = 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[0], pokemon), 0.25);
|
let defScore = 1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[0], pokemon), 0.25);
|
||||||
if (types.length > 1) {
|
if (types.length > 1) {
|
||||||
atkScore *= pokemon.getAttackTypeEffectiveness(types[1], this);
|
atkScore *= pokemon.getAttackTypeEffectiveness(types[1], this, false, false, true);
|
||||||
}
|
}
|
||||||
if (enemyTypes.length > 1) {
|
if (enemyTypes.length > 1) {
|
||||||
defScore *= (1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1], pokemon), 0.25));
|
defScore *= (1 / Math.max(this.getAttackTypeEffectiveness(enemyTypes[1], pokemon), 0.25));
|
||||||
@ -3720,7 +3911,7 @@ export class EnemyPokemon extends Pokemon {
|
|||||||
if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) {
|
if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) {
|
||||||
targetScore = -20;
|
targetScore = -20;
|
||||||
} else if (move instanceof AttackMove) {
|
} else if (move instanceof AttackMove) {
|
||||||
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove);
|
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove, false, true);
|
||||||
if (target.isPlayer() !== this.isPlayer()) {
|
if (target.isPlayer() !== this.isPlayer()) {
|
||||||
targetScore *= effectiveness;
|
targetScore *= effectiveness;
|
||||||
if (this.isOfType(move.type)) {
|
if (this.isOfType(move.type)) {
|
||||||
@ -4017,6 +4208,91 @@ export class EnemyPokemon extends Pokemon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Illusion property
|
||||||
|
*/
|
||||||
|
interface Illusion {
|
||||||
|
/**
|
||||||
|
* Whether the illusion is active or not.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
active: boolean;
|
||||||
|
/**
|
||||||
|
* Whether the pokemon can generate an illusion or not.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
available: boolean;
|
||||||
|
/**
|
||||||
|
* The stored name of the pokemon.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
/**
|
||||||
|
* The stored nickname of the pokemon.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
nickname?: string;
|
||||||
|
/**
|
||||||
|
* The species of the illusion.
|
||||||
|
* @type {PokemonSpecies}
|
||||||
|
*/
|
||||||
|
species?: PokemonSpecies;
|
||||||
|
/**
|
||||||
|
* The formIndex of the illusion
|
||||||
|
* @type {integer}
|
||||||
|
*/
|
||||||
|
formIndex?: integer;
|
||||||
|
/**
|
||||||
|
* Store whether the base pokemon is shiny or not.
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
shiny?: boolean;
|
||||||
|
/**
|
||||||
|
* The shiny variant of the base pokemon.
|
||||||
|
* @type {Variant}
|
||||||
|
*/
|
||||||
|
variant?: Variant;
|
||||||
|
/**
|
||||||
|
* The shinysparkles of the base pokemon.
|
||||||
|
* @type {Phaser.GameObjects.Sprite}
|
||||||
|
*/
|
||||||
|
shinySparkle?: Phaser.GameObjects.Sprite;
|
||||||
|
/**
|
||||||
|
* The gender of the illusion
|
||||||
|
* @type {Gender}
|
||||||
|
*/
|
||||||
|
gender?: Gender;
|
||||||
|
/**
|
||||||
|
* The pokeball of the illusion.
|
||||||
|
*/
|
||||||
|
pokeball?: PokeballType;
|
||||||
|
/**
|
||||||
|
* The fusionned species of the illusion if it's a fusion.
|
||||||
|
* @type {PokemonSpecies}
|
||||||
|
*/
|
||||||
|
fusionSpecies?: PokemonSpecies;
|
||||||
|
/**
|
||||||
|
* The fusionFormIndex of the illusion
|
||||||
|
* @type {integer}
|
||||||
|
*/
|
||||||
|
fusionFormIndex?: integer;
|
||||||
|
/**
|
||||||
|
* Whether the fusionned species of the base pokemon is shiny or not.
|
||||||
|
* @type {PokemonSpecies}
|
||||||
|
*/
|
||||||
|
fusionShiny?: boolean;
|
||||||
|
/**
|
||||||
|
* The variant of the fusionned species of the base pokemon.
|
||||||
|
* @type {Variant}
|
||||||
|
*/
|
||||||
|
fusionVariant?: Variant;
|
||||||
|
/**
|
||||||
|
* The fusionGender of the illusion if it's a fusion
|
||||||
|
* @type {Gender}
|
||||||
|
*/
|
||||||
|
fusionGender?: Gender;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TurnMove {
|
export interface TurnMove {
|
||||||
move: Moves;
|
move: Moves;
|
||||||
targets?: BattlerIndex[];
|
targets?: BattlerIndex[];
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "{{pokemonName}} kopiert {{abilityName}} von {{targetName}}!",
|
"trace": "{{pokemonName}} kopiert {{abilityName}} von {{targetName}}!",
|
||||||
"windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!",
|
"windPowerCharged": "Der Treffer durch {{moveName}} läd die Stärke von {{pokemonName}} auf!",
|
||||||
"quickDraw": "Durch Schnellschuss kann {{pokemonName}} schneller handeln als sonst!",
|
"quickDraw": "Durch Schnellschuss kann {{pokemonName}} schneller handeln als sonst!",
|
||||||
|
"illusionBreak": "Das Trugbild von {{pokemonName}} verschwindet!",
|
||||||
"blockItemTheft": "{{abilityName}} von {{pokemonNameWithAffix}} verhindert Item-Diebstahl!",
|
"blockItemTheft": "{{abilityName}} von {{pokemonNameWithAffix}} verhindert Item-Diebstahl!",
|
||||||
"typeImmunityHeal": "{{abilityName}} von {{pokemonNameWithAffix}} füllte einige KP auf!",
|
"typeImmunityHeal": "{{abilityName}} von {{pokemonNameWithAffix}} füllte einige KP auf!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} vermeidet Schaden mit {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} vermeidet Schaden mit {{abilityName}}!",
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!",
|
"trace": "{{pokemonName}} copied {{targetName}}'s\n{{abilityName}}!",
|
||||||
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
"windPowerCharged": "Being hit by {{moveName}} charged {{pokemonName}} with power!",
|
||||||
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
||||||
|
"illusionBreak": "{{pokemonName}}'s illusion wore off!",
|
||||||
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
||||||
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
||||||
|
@ -11,6 +11,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
|
"windPowerCharged": "¡{{pokemonName}} se ha cargado de electricidad gracias a {{moveName}}!",
|
||||||
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
"quickDraw": "{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
||||||
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
||||||
|
"illusionBreak": "¡La ilusión de {{pokemonName}} se ha desvanecido!",
|
||||||
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
||||||
"postDefendDisguise": "{{pokemonNameWithAffix}}'s disguise was busted!",
|
"postDefendDisguise": "{{pokemonNameWithAffix}}'s disguise was busted!",
|
||||||
|
@ -9,6 +9,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"poisonHeal": "{{abilityName}} de {{pokemonName}}\nrestaure un peu ses PV !",
|
"poisonHeal": "{{abilityName}} de {{pokemonName}}\nrestaure un peu ses PV !",
|
||||||
"trace": "{{pokemonName}} copie le talent {{abilityName}}\nde {{targetName}} !",
|
"trace": "{{pokemonName}} copie le talent {{abilityName}}\nde {{targetName}} !",
|
||||||
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !",
|
"windPowerCharged": "{{pokemonName}} a été touché par la capacité {{moveName}} et se charge en électricité !",
|
||||||
|
"illusionBreak": "L’illusion de {{pokemonName}} se brise !",
|
||||||
"quickDraw": "Tir Vif permet à {{pokemonName}}\nd’agir plus vite que d’habitude !",
|
"quickDraw": "Tir Vif permet à {{pokemonName}}\nd’agir plus vite que d’habitude !",
|
||||||
"blockItemTheft": "{{abilityName}} de {{pokemonNameWithAffix}}\nempêche son objet d’être volé !",
|
"blockItemTheft": "{{abilityName}} de {{pokemonNameWithAffix}}\nempêche son objet d’être volé !",
|
||||||
"typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
|
"typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaure un peu ses PV !",
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "L'abilità {{abilityName}} di {{targetName}}\nviene copiata da {{pokemonName}} con Traccia!",
|
"trace": "L'abilità {{abilityName}} di {{targetName}}\nviene copiata da {{pokemonName}} con Traccia!",
|
||||||
"windPowerCharged": "Venire colpito da {{moveName}} ha caricato {{pokemonName}}!",
|
"windPowerCharged": "Venire colpito da {{moveName}} ha caricato {{pokemonName}}!",
|
||||||
"quickDraw":"{{pokemonName}} agisce più rapidamente del normale grazie a Colpolesto!",
|
"quickDraw":"{{pokemonName}} agisce più rapidamente del normale grazie a Colpolesto!",
|
||||||
|
"illusionBreak": "L'illusione di {{pokemonName}} si dissolve!",
|
||||||
"blockItemTheft": "{{abilityName}} di {{pokemonNameWithAffix}}\nlo rende immune ai furti!",
|
"blockItemTheft": "{{abilityName}} di {{pokemonNameWithAffix}}\nlo rende immune ai furti!",
|
||||||
"typeImmunityHeal": "{{pokemonName}} recupera alcuni PS\ncon {{abilityName}}!",
|
"typeImmunityHeal": "{{pokemonName}} recupera alcuni PS\ncon {{abilityName}}!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} evita il colpo\ncon {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} evita il colpo\ncon {{abilityName}}!",
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "{{pokemonName}}[[는]] 상대 {{targetName}}의 \n{{abilityName}}[[를]] 트레이스했다!",
|
"trace": "{{pokemonName}}[[는]] 상대 {{targetName}}의 \n{{abilityName}}[[를]] 트레이스했다!",
|
||||||
"windPowerCharged": "{{pokemonName}}[[는]]\n{{moveName}}에 맞아 충전되었다!",
|
"windPowerCharged": "{{pokemonName}}[[는]]\n{{moveName}}에 맞아 충전되었다!",
|
||||||
"quickDraw": "{{pokemonName}}[[는]]\n퀵드로에 의해 행동이 빨라졌다!",
|
"quickDraw": "{{pokemonName}}[[는]]\n퀵드로에 의해 행동이 빨라졌다!",
|
||||||
|
"illusionBreak": "{{pokemonName}}의\n일루전이 풀렸다!",
|
||||||
"blockItemTheft": "{{pokemonNameWithAffix}}의 {{abilityName}}에 의해\n도구를 빼앗기지 않는다!",
|
"blockItemTheft": "{{pokemonNameWithAffix}}의 {{abilityName}}에 의해\n도구를 빼앗기지 않는다!",
|
||||||
"typeImmunityHeal": "{{pokemonNameWithAffix}}[[는]]\n{{abilityName}}[[로]] 체력이 회복되었다!",
|
"typeImmunityHeal": "{{pokemonNameWithAffix}}[[는]]\n{{abilityName}}[[로]] 체력이 회복되었다!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}}[[는]] {{abilityName}} 때문에\n데미지를 입지 않는다!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}}[[는]] {{abilityName}} 때문에\n데미지를 입지 않는다!",
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "{{pokemonName}} copiou {{abilityName}}\nde {{targetName}}!",
|
"trace": "{{pokemonName}} copiou {{abilityName}}\nde {{targetName}}!",
|
||||||
"windPowerCharged": "Ser atingido por {{moveName}} carregou {{pokemonName}} com poder!",
|
"windPowerCharged": "Ser atingido por {{moveName}} carregou {{pokemonName}} com poder!",
|
||||||
"quickDraw": "{{pokemonName}} pode agir mais rápido que o normal\ngraças ao seu Quick Draw!",
|
"quickDraw": "{{pokemonName}} pode agir mais rápido que o normal\ngraças ao seu Quick Draw!",
|
||||||
|
"illusionBreak": "A ilusão de {{pokemonName}} acabou!",
|
||||||
"blockItemTheft": "{{abilityName}} de {{pokemonNameWithAffix}}\nprevine o roubo de itens!",
|
"blockItemTheft": "{{abilityName}} de {{pokemonNameWithAffix}}\nprevine o roubo de itens!",
|
||||||
"typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaurou um pouco de PS!",
|
"typeImmunityHeal": "{{abilityName}} de {{pokemonNameWithAffix}}\nrestaurou um pouco de PS!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} evitou dano\ncom {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} evitou dano\ncom {{abilityName}}!",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ability } from "./ability";
|
import { ability } from "./ability";
|
||||||
import { abilityTriggers } from "./ability-trigger";
|
import { abilityTriggers } from "./ability-trigger";
|
||||||
|
import { arenaFlyout } from "./arena-flyout";
|
||||||
import { PGFachv, PGMachv } from "./achv";
|
import { PGFachv, PGMachv } from "./achv";
|
||||||
import { arenaFlyout } from "./arena-flyout";
|
import { arenaFlyout } from "./arena-flyout";
|
||||||
import { arenaTag } from "./arena-tag";
|
import { arenaTag } from "./arena-tag";
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "{{pokemonName}}复制了{{targetName}}的\n{{abilityName}}!",
|
"trace": "{{pokemonName}}复制了{{targetName}}的\n{{abilityName}}!",
|
||||||
"windPowerCharged": "受{{moveName}}的影响,{{pokemonName}}提升了能力!",
|
"windPowerCharged": "受{{moveName}}的影响,{{pokemonName}}提升了能力!",
|
||||||
"quickDraw":"因为速击效果发动,\n{{pokemonName}}比平常出招更快了!",
|
"quickDraw":"因为速击效果发动,\n{{pokemonName}}比平常出招更快了!",
|
||||||
|
"illusionBreak": "{{pokemonName}}造成的\n幻觉被解除了!",
|
||||||
"blockItemTheft": "{{pokemonNameWithAffix}}的{{abilityName}}\n阻止了对方夺取道具!",
|
"blockItemTheft": "{{pokemonNameWithAffix}}的{{abilityName}}\n阻止了对方夺取道具!",
|
||||||
"typeImmunityHeal": "{{pokemonNameWithAffix}}因{{abilityName}}\n回复了少许HP!",
|
"typeImmunityHeal": "{{pokemonNameWithAffix}}因{{abilityName}}\n回复了少许HP!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}}因{{abilityName}}\n避免了伤害!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}}因{{abilityName}}\n避免了伤害!",
|
||||||
|
@ -10,6 +10,7 @@ export const abilityTriggers: SimpleTranslationEntries = {
|
|||||||
"trace": "{{pokemonName}} 複製了 {{targetName}} 的\n{{abilityName}}!",
|
"trace": "{{pokemonName}} 複製了 {{targetName}} 的\n{{abilityName}}!",
|
||||||
"windPowerCharged": "受 {{moveName}} 的影響, {{pokemonName}} 提升了能力!",
|
"windPowerCharged": "受 {{moveName}} 的影響, {{pokemonName}} 提升了能力!",
|
||||||
"quickDraw":"{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
"quickDraw":"{{pokemonName}} can act faster than normal, thanks to its Quick Draw!",
|
||||||
|
"illusionBreak": "{{pokemonName}}造成的\n幻覺解除了!",
|
||||||
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
"blockItemTheft": "{{pokemonNameWithAffix}}'s {{abilityName}}\nprevents item theft!",
|
||||||
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
"typeImmunityHeal": "{{pokemonNameWithAffix}}'s {{abilityName}}\nrestored its HP a little!",
|
||||||
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
"nonSuperEffectiveImmunity": "{{pokemonNameWithAffix}} avoided damage\nwith {{abilityName}}!",
|
||||||
|
@ -18,23 +18,23 @@ export function getPokemonMessage(pokemon: Pokemon, content: string): string {
|
|||||||
* @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance
|
* @param pokemon {@linkcode Pokemon} name and battle context will be retrieved from this instance
|
||||||
* @returns {string} ex: "Wild Gengar", "Ectoplasma sauvage"
|
* @returns {string} ex: "Wild Gengar", "Ectoplasma sauvage"
|
||||||
*/
|
*/
|
||||||
export function getPokemonNameWithAffix(pokemon: Pokemon): string {
|
export function getPokemonNameWithAffix(pokemon: Pokemon, useIllusion: boolean = true): string {
|
||||||
switch (pokemon.scene.currentBattle.battleSpec) {
|
switch (pokemon.scene.currentBattle.battleSpec) {
|
||||||
case BattleSpec.DEFAULT:
|
case BattleSpec.DEFAULT:
|
||||||
return !pokemon.isPlayer()
|
return !pokemon.isPlayer()
|
||||||
? pokemon.hasTrainer()
|
? pokemon.hasTrainer()
|
||||||
? i18next.t("battle:foePokemonWithAffix", {
|
? i18next.t("battle:foePokemonWithAffix", {
|
||||||
pokemonName: pokemon.getNameToRender(),
|
pokemonName: pokemon.getNameToRender(useIllusion),
|
||||||
})
|
})
|
||||||
: i18next.t("battle:wildPokemonWithAffix", {
|
: i18next.t("battle:wildPokemonWithAffix", {
|
||||||
pokemonName: pokemon.getNameToRender(),
|
pokemonName: pokemon.getNameToRender(useIllusion),
|
||||||
})
|
})
|
||||||
: pokemon.getNameToRender();
|
: pokemon.getNameToRender(useIllusion);
|
||||||
case BattleSpec.FINAL_BOSS:
|
case BattleSpec.FINAL_BOSS:
|
||||||
return !pokemon.isPlayer()
|
return !pokemon.isPlayer()
|
||||||
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() })
|
? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender(useIllusion) })
|
||||||
: pokemon.getNameToRender();
|
: pokemon.getNameToRender(useIllusion);
|
||||||
default:
|
default:
|
||||||
return pokemon.getNameToRender();
|
return pokemon.getNameToRender(useIllusion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,10 @@ import { Starter } from "./ui/starter-select-ui-handler";
|
|||||||
import { Gender } from "./data/gender";
|
import { Gender } from "./data/gender";
|
||||||
import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather";
|
import { Weather, WeatherType, getRandomWeatherType, getTerrainBlockMessage, getWeatherDamageMessage, getWeatherLapseMessage } from "./data/weather";
|
||||||
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
|
import { ArenaTagSide, ArenaTrapTag, MistTag, TrickRoomTag } from "./data/arena-tag";
|
||||||
import { CheckTrappedAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr, applyAbAttrs, applyCheckTrappedAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr } from "./data/ability";
|
import {
|
||||||
|
CheckTrappedAbAttr, PreSummonAbAttr, PostAttackAbAttr, PostBattleAbAttr, PostDefendAbAttr, PostSummonAbAttr, PostTurnAbAttr, PostWeatherLapseAbAttr, PreSwitchOutAbAttr, PreWeatherDamageAbAttr, ProtectStatAbAttr, RedirectMoveAbAttr, BlockRedirectAbAttr, RunSuccessAbAttr, StatChangeMultiplierAbAttr, SuppressWeatherEffectAbAttr, SyncEncounterNatureAbAttr,
|
||||||
|
applyAbAttrs, applyCheckTrappedAbAttrs, applyPreSummonAbAttrs, applyPostAttackAbAttrs, applyPostBattleAbAttrs, applyPostDefendAbAttrs, applyPostSummonAbAttrs, applyPostTurnAbAttrs, applyPostWeatherLapseAbAttrs, applyPreStatChangeAbAttrs, applyPreSwitchOutAbAttrs, applyPreWeatherEffectAbAttrs, IncrementMovePriorityAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr, BlockNonDirectDamageAbAttr as BlockNonDirectDamageAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, PostBiomeChangeAbAttr, applyPostFaintAbAttrs, PostFaintAbAttr, IncreasePpAbAttr, PostStatChangeAbAttr, applyPostStatChangeAbAttrs, AlwaysHitAbAttr, PreventBerryUseAbAttr, StatChangeCopyAbAttr, PokemonTypeChangeAbAttr, applyPreAttackAbAttrs, applyPostMoveUsedAbAttrs, PostMoveUsedAbAttr, MaxMultiHitAbAttr, HealFromBerryUseAbAttr, IgnoreMoveEffectsAbAttr, BlockStatusDamageAbAttr, BypassSpeedChanceAbAttr, AddSecondStrikeAbAttr
|
||||||
|
} from "./data/ability";
|
||||||
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
import { Unlockables, getUnlockableName } from "./system/unlockables";
|
||||||
import { getBiomeKey } from "./field/arena";
|
import { getBiomeKey } from "./field/arena";
|
||||||
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
import { BattleType, BattlerIndex, TurnCommand } from "./battle";
|
||||||
@ -842,6 +845,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const enemyPokemon = this.scene.getEnemyParty()[e];
|
const enemyPokemon = this.scene.getEnemyParty()[e];
|
||||||
if (e < (battle.double ? 2 : 1)) {
|
if (e < (battle.double ? 2 : 1)) {
|
||||||
enemyPokemon.setX(-66 + enemyPokemon.getFieldPositionOffset()[0]);
|
enemyPokemon.setX(-66 + enemyPokemon.getFieldPositionOffset()[0]);
|
||||||
@ -895,6 +899,8 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
battle.enemyParty.forEach((enemyPokemon, e) => {
|
battle.enemyParty.forEach((enemyPokemon, e) => {
|
||||||
if (e < (battle.double ? 2 : 1)) {
|
if (e < (battle.double ? 2 : 1)) {
|
||||||
if (battle.battleType === BattleType.WILD) {
|
if (battle.battleType === BattleType.WILD) {
|
||||||
|
|
||||||
|
applyPreSummonAbAttrs(PreSummonAbAttr, enemyPokemon, []);
|
||||||
this.scene.field.add(enemyPokemon);
|
this.scene.field.add(enemyPokemon);
|
||||||
battle.seenEnemyPartyMemberIds.add(enemyPokemon.id);
|
battle.seenEnemyPartyMemberIds.add(enemyPokemon.id);
|
||||||
const playerPokemon = this.scene.getPlayerPokemon();
|
const playerPokemon = this.scene.getPlayerPokemon();
|
||||||
@ -1058,7 +1064,7 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
const enemyField = this.scene.getEnemyField();
|
const enemyField = this.scene.getEnemyField();
|
||||||
|
|
||||||
enemyField.forEach((enemyPokemon, e) => {
|
enemyField.forEach((enemyPokemon, e) => {
|
||||||
if (enemyPokemon.isShiny()) {
|
if (enemyPokemon.isShiny(true)) {
|
||||||
this.scene.unshiftPhase(new ShinySparklePhase(this.scene, BattlerIndex.ENEMY + e));
|
this.scene.unshiftPhase(new ShinySparklePhase(this.scene, BattlerIndex.ENEMY + e));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1378,7 +1384,8 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
this.preSummon();
|
const pokemon = this.getPokemon();
|
||||||
|
applyPreSummonAbAttrs(PreSummonAbAttr, pokemon).then(() => this.preSummon());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1447,8 +1454,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
|
|
||||||
summon(): void {
|
summon(): void {
|
||||||
const pokemon = this.getPokemon();
|
const pokemon = this.getPokemon();
|
||||||
|
const pokeball = this.scene.addFieldSprite(this.player ? 36 : 248, this.player ? 80 : 44, "pb", getPokeballAtlasKey(pokemon.illusion.pokeball ?? pokemon.pokeball));
|
||||||
const pokeball = this.scene.addFieldSprite(this.player ? 36 : 248, this.player ? 80 : 44, "pb", getPokeballAtlasKey(pokemon.pokeball));
|
|
||||||
pokeball.setVisible(false);
|
pokeball.setVisible(false);
|
||||||
pokeball.setOrigin(0.5, 0.625);
|
pokeball.setOrigin(0.5, 0.625);
|
||||||
this.scene.field.add(pokeball);
|
this.scene.field.add(pokeball);
|
||||||
@ -1494,7 +1500,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
}
|
}
|
||||||
this.scene.currentBattle.seenEnemyPartyMemberIds.add(pokemon.id);
|
this.scene.currentBattle.seenEnemyPartyMemberIds.add(pokemon.id);
|
||||||
}
|
}
|
||||||
addPokeballOpenParticles(this.scene, pokemon.x, pokemon.y - 16, pokemon.pokeball);
|
addPokeballOpenParticles(this.scene, pokemon.x, pokemon.y - 16, pokemon.illusion.pokeball ?? pokemon.pokeball);
|
||||||
this.scene.updateModifiers(this.player);
|
this.scene.updateModifiers(this.player);
|
||||||
this.scene.updateFieldScale();
|
this.scene.updateFieldScale();
|
||||||
pokemon.showInfo();
|
pokemon.showInfo();
|
||||||
@ -1502,7 +1508,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
pokemon.setVisible(true);
|
pokemon.setVisible(true);
|
||||||
pokemon.getSprite().setVisible(true);
|
pokemon.getSprite().setVisible(true);
|
||||||
pokemon.setScale(0.5);
|
pokemon.setScale(0.5);
|
||||||
pokemon.tint(getPokeballTintColor(pokemon.pokeball));
|
pokemon.tint(getPokeballTintColor(pokemon.illusion.pokeball ?? pokemon.pokeball));
|
||||||
pokemon.untint(250, "Sine.easeIn");
|
pokemon.untint(250, "Sine.easeIn");
|
||||||
this.scene.updateFieldScale();
|
this.scene.updateFieldScale();
|
||||||
this.scene.tweens.add({
|
this.scene.tweens.add({
|
||||||
@ -1526,7 +1532,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
|
|||||||
onEnd(): void {
|
onEnd(): void {
|
||||||
const pokemon = this.getPokemon();
|
const pokemon = this.getPokemon();
|
||||||
|
|
||||||
if (pokemon.isShiny()) {
|
if (pokemon.isShiny(true)) {
|
||||||
this.scene.unshiftPhase(new ShinySparklePhase(this.scene, pokemon.getBattlerIndex()));
|
this.scene.unshiftPhase(new ShinySparklePhase(this.scene, pokemon.getBattlerIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1587,7 +1593,10 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||||||
this.scene.pbTrayEnemy.showPbTray(this.scene.getEnemyParty());
|
this.scene.pbTrayEnemy.showPbTray(this.scene.getEnemyParty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const pokemon: Pokemon = this.getPokemon();
|
||||||
|
|
||||||
|
// if doReturn === False OR slotIndex !== -1 (slotIndex is valid) and the pokemon doesn't exist/is false
|
||||||
|
// then switchAndSummon(), manually pick pokemon to switch into
|
||||||
if (!this.doReturn || (this.slotIndex !== -1 && !(this.player ? this.scene.getParty() : this.scene.getEnemyParty())[this.slotIndex])) {
|
if (!this.doReturn || (this.slotIndex !== -1 && !(this.player ? this.scene.getParty() : this.scene.getEnemyParty())[this.slotIndex])) {
|
||||||
if (this.player) {
|
if (this.player) {
|
||||||
return this.switchAndSummon();
|
return this.switchAndSummon();
|
||||||
@ -1597,8 +1606,6 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pokemon = this.getPokemon();
|
|
||||||
|
|
||||||
if (!this.batonPass) {
|
if (!this.batonPass) {
|
||||||
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.removeTagsBySourceId(pokemon.id));
|
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.removeTagsBySourceId(pokemon.id));
|
||||||
}
|
}
|
||||||
@ -1612,7 +1619,7 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||||||
);
|
);
|
||||||
this.scene.playSound("pb_rel");
|
this.scene.playSound("pb_rel");
|
||||||
pokemon.hideInfo();
|
pokemon.hideInfo();
|
||||||
pokemon.tint(getPokeballTintColor(pokemon.pokeball), 1, 250, "Sine.easeIn");
|
pokemon.tint(getPokeballTintColor(pokemon.illusion.pokeball ?? pokemon.pokeball), 1, 250, "Sine.easeIn");
|
||||||
this.scene.tweens.add({
|
this.scene.tweens.add({
|
||||||
targets: pokemon,
|
targets: pokemon,
|
||||||
duration: 250,
|
duration: 250,
|
||||||
@ -1631,6 +1638,8 @@ export class SwitchSummonPhase extends SummonPhase {
|
|||||||
const party = this.player ? this.getParty() : this.scene.getEnemyParty();
|
const party = this.player ? this.getParty() : this.scene.getEnemyParty();
|
||||||
const switchedPokemon = party[this.slotIndex];
|
const switchedPokemon = party[this.slotIndex];
|
||||||
this.lastPokemon = this.getPokemon();
|
this.lastPokemon = this.getPokemon();
|
||||||
|
|
||||||
|
applyPreSummonAbAttrs(PreSummonAbAttr, switchedPokemon);
|
||||||
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon);
|
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon);
|
||||||
if (this.batonPass && switchedPokemon) {
|
if (this.batonPass && switchedPokemon) {
|
||||||
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id));
|
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id));
|
||||||
@ -4470,6 +4479,7 @@ export class SwitchPhase extends BattlePhase {
|
|||||||
}
|
}
|
||||||
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
|
this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
|
||||||
}, PartyUiHandler.FilterNonFainted);
|
}, PartyUiHandler.FilterNonFainted);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
127
src/test/abilities/illusion.test.ts
Normal file
127
src/test/abilities/illusion.test.ts
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
|
import overrides from "#app/overrides";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { Gender } from "../../data/gender";
|
||||||
|
import { PokeballType } from "../../data/pokeball";
|
||||||
|
import {
|
||||||
|
TurnEndPhase,
|
||||||
|
} from "#app/phases";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
|
||||||
|
describe("Abilities - Illusion", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
vi.spyOn(overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue("single");
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.ZORUA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ILLUSION);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||||
|
vi.spyOn(overrides, "OPP_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "WIDE_LENS", count: 3}]);
|
||||||
|
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE, Moves.TACKLE]);
|
||||||
|
vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{name: "WIDE_LENS", count: 3}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("create illusion at the start", async () => {
|
||||||
|
await game.startBattle([Species.ZOROARK, Species.AXEW]);
|
||||||
|
|
||||||
|
const zoroark = game.scene.getPlayerPokemon();
|
||||||
|
const zorua = game.scene.getEnemyPokemon();
|
||||||
|
|
||||||
|
expect(zoroark.illusion.active).equals(true);
|
||||||
|
expect(zorua.illusion.active).equals(true);
|
||||||
|
expect(zoroark.illusion.available).equals(false);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disappear after receiving damaging move and changing ability move", async () => {
|
||||||
|
await game.startBattle([Species.ZOROARK, Species.AXEW]);
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.WORRY_SEED));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
const zoroark = game.scene.getPlayerPokemon();
|
||||||
|
const zorua = game.scene.getEnemyPokemon();
|
||||||
|
|
||||||
|
expect(zorua.illusion.active).equals(false);
|
||||||
|
expect(zoroark.illusion.active).equals(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disappear if the ability is suppressed", async () => {
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NEUTRALIZING_GAS);
|
||||||
|
await game.startBattle([Species.KOFFING]);
|
||||||
|
|
||||||
|
const zorua = game.scene.getEnemyPokemon();
|
||||||
|
|
||||||
|
expect(zorua.illusion.active).equals(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("trick the enemy AI", async () => {
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE, Moves.TACKLE]);
|
||||||
|
await game.startBattle([Species.ZOROARK, Species.AXEW]);
|
||||||
|
|
||||||
|
const enemy = game.scene.getEnemyPokemon();
|
||||||
|
const zoroark = game.scene.getPlayerPokemon();
|
||||||
|
|
||||||
|
const flameThwowerEffectiveness = zoroark.getAttackMoveEffectiveness(enemy, enemy.getMoveset()[0], false, true);
|
||||||
|
const psychicEffectiveness = zoroark.getAttackMoveEffectiveness(enemy, enemy.getMoveset()[1], false, true);
|
||||||
|
|
||||||
|
expect(psychicEffectiveness).above(flameThwowerEffectiveness);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("do not disappear if the pokemon takes indirect damages", async () => {
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.GIGALITH);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SAND_STREAM);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.WILL_O_WISP, Moves.WILL_O_WISP, Moves.WILL_O_WISP, Moves.WILL_O_WISP]);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.FLARE_BLITZ]);
|
||||||
|
|
||||||
|
await game.startBattle([Species.ZOROARK, Species.AZUMARILL]);
|
||||||
|
|
||||||
|
game.doAttack(getMovePosition(game.scene, 0, Moves.FLARE_BLITZ));
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
const zoroark = game.scene.getPlayerPokemon();
|
||||||
|
|
||||||
|
expect(zoroark.illusion.active).equals(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("copy the the name, the nickname, the gender, the shininess and the pokeball of the pokemon", async () => {
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SCARY_FACE, Moves.SCARY_FACE, Moves.SCARY_FACE, Moves.SCARY_FACE]);
|
||||||
|
|
||||||
|
await game.startBattle([Species.ABRA, Species.ZOROARK, Species.AXEW]);
|
||||||
|
|
||||||
|
const axew = game.scene.getParty().at(2);
|
||||||
|
axew.shiny = true;
|
||||||
|
axew.nickname = btoa(unescape(encodeURIComponent("axew nickname")));
|
||||||
|
axew.gender = Gender.FEMALE;
|
||||||
|
axew.pokeball = PokeballType.GREAT_BALL;
|
||||||
|
|
||||||
|
game.doSwitchPokemon(1);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
|
const zoroark = game.scene.getPlayerPokemon();
|
||||||
|
expect(zoroark.name).equals("Axew");
|
||||||
|
expect(zoroark.getNameToRender()).equals("axew nickname");
|
||||||
|
expect(zoroark.getGender(false, true)).equals(Gender.FEMALE);
|
||||||
|
expect(zoroark.isShiny(true)).equals(true);
|
||||||
|
expect(zoroark.illusion.pokeball).equals(PokeballType.GREAT_BALL);
|
||||||
|
});
|
||||||
|
});
|
@ -298,7 +298,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
});
|
});
|
||||||
this.teraIcon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip());
|
this.teraIcon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip());
|
||||||
|
|
||||||
const isFusion = pokemon.isFusion();
|
const isFusion = pokemon.isFusion(true);
|
||||||
|
|
||||||
this.splicedIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0), 2.5);
|
this.splicedIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0), 2.5);
|
||||||
this.splicedIcon.setVisible(isFusion);
|
this.splicedIcon.setVisible(isFusion);
|
||||||
@ -308,7 +308,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
|
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
|
||||||
const baseVariant = !doubleShiny ? pokemon.getVariant() : pokemon.variant;
|
const baseVariant = !doubleShiny ? pokemon.getVariant(true) : pokemon.variant;
|
||||||
|
|
||||||
this.shinyIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0), 2.5);
|
this.shinyIcon.setPositionRelative(this.nameText, nameTextWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0) + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0), 2.5);
|
||||||
this.shinyIcon.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`);
|
this.shinyIcon.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`);
|
||||||
@ -510,6 +510,11 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const gender: Gender = pokemon.illusion.active ? pokemon.illusion.gender : pokemon.gender;
|
||||||
|
|
||||||
|
this.genderText.setText(getGenderSymbol(gender));
|
||||||
|
this.genderText.setColor(getGenderColor(gender));
|
||||||
|
|
||||||
const nameUpdated = this.lastName !== pokemon.getNameToRender();
|
const nameUpdated = this.lastName !== pokemon.getNameToRender();
|
||||||
|
|
||||||
if (nameUpdated) {
|
if (nameUpdated) {
|
||||||
@ -527,8 +532,10 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
this.lastTeraType = teraType;
|
this.lastTeraType = teraType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isFusion = pokemon.isFusion(true);
|
||||||
|
|
||||||
if (nameUpdated || teraTypeUpdated) {
|
if (nameUpdated || teraTypeUpdated) {
|
||||||
this.splicedIcon.setVisible(!!pokemon.fusionSpecies);
|
this.splicedIcon.setVisible(isFusion);
|
||||||
|
|
||||||
this.teraIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + this.genderText.displayWidth + 1, 2);
|
this.teraIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + this.genderText.displayWidth + 1, 2);
|
||||||
this.splicedIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0), 1.5);
|
this.splicedIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + this.genderText.displayWidth + 1 + (this.teraIcon.visible ? this.teraIcon.displayWidth + 1 : 0), 1.5);
|
||||||
@ -630,7 +637,17 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
this.lastBattleStats = battleStatsStr;
|
this.lastBattleStats = battleStatsStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shinyIcon.setVisible(pokemon.isShiny());
|
this.shinyIcon.setVisible(pokemon.isShiny(true));
|
||||||
|
|
||||||
|
const doubleShiny = isFusion && pokemon.shiny && pokemon.fusionShiny;
|
||||||
|
const baseVariant = !doubleShiny ? pokemon.getVariant(true) : pokemon.variant;
|
||||||
|
this.shinyIcon.setTint(getVariantTint(baseVariant));
|
||||||
|
|
||||||
|
this.fusionShinyIcon.setVisible(doubleShiny);
|
||||||
|
if (isFusion) {
|
||||||
|
this.fusionShinyIcon.setTint(getVariantTint(pokemon.fusionVariant));
|
||||||
|
}
|
||||||
|
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
@ -643,7 +660,8 @@ export default class BattleInfo extends Phaser.GameObjects.Container {
|
|||||||
const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.BATTLE_INFO);
|
const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.BATTLE_INFO);
|
||||||
nameTextWidth = nameSizeTest.displayWidth;
|
nameTextWidth = nameSizeTest.displayWidth;
|
||||||
|
|
||||||
while (nameTextWidth > (this.player || !this.boss ? 60 : 98) - ((pokemon.gender !== Gender.GENDERLESS ? 6 : 0) + (pokemon.fusionSpecies ? 8 : 0) + (pokemon.isShiny() ? 8 : 0) + (Math.min(pokemon.level.toString().length, 3) - 3) * 8)) {
|
const gender: Gender = pokemon.illusion.active ? pokemon.illusion.gender : pokemon.gender;
|
||||||
|
while (nameTextWidth > (this.player || !this.boss ? 60 : 98) - ((gender !== Gender.GENDERLESS ? 6 : 0) + (pokemon.fusionSpecies ? 8 : 0) + (pokemon.isShiny() ? 8 : 0) + (Math.min(pokemon.level.toString().length, 3) - 3) * 8)) {
|
||||||
displayName = `${displayName.slice(0, displayName.endsWith(".") ? -2 : -1).trimEnd()}.`;
|
displayName = `${displayName.slice(0, displayName.endsWith(".") ? -2 : -1).trimEnd()}.`;
|
||||||
nameSizeTest.setText(displayName);
|
nameSizeTest.setText(displayName);
|
||||||
nameTextWidth = nameSizeTest.displayWidth;
|
nameTextWidth = nameSizeTest.displayWidth;
|
||||||
|
@ -117,14 +117,14 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
public static FilterNonFainted = (pokemon: PlayerPokemon) => {
|
public static FilterNonFainted = (pokemon: PlayerPokemon) => {
|
||||||
if (pokemon.isFainted()) {
|
if (pokemon.isFainted()) {
|
||||||
return i18next.t("partyUiHandler:noEnergy", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
return i18next.t("partyUiHandler:noEnergy", { pokemonName: getPokemonNameWithAffix(pokemon, false) });
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
public static FilterFainted = (pokemon: PlayerPokemon) => {
|
public static FilterFainted = (pokemon: PlayerPokemon) => {
|
||||||
if (!pokemon.isFainted()) {
|
if (!pokemon.isFainted()) {
|
||||||
return i18next.t("partyUiHandler:hasEnergy", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
return i18next.t("partyUiHandler:hasEnergy", { pokemonName: getPokemonNameWithAffix(pokemon, false) });
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
@ -138,7 +138,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
const challengeAllowed = new Utils.BooleanHolder(true);
|
const challengeAllowed = new Utils.BooleanHolder(true);
|
||||||
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, pokemon, challengeAllowed);
|
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, pokemon, challengeAllowed);
|
||||||
if (!challengeAllowed.value) {
|
if (!challengeAllowed.value) {
|
||||||
return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
return i18next.t("partyUiHandler:cantBeUsed", { pokemonName: getPokemonNameWithAffix(pokemon, false) });
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
@ -148,7 +148,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => {
|
public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => {
|
||||||
const matchingModifier = pokemon.scene.findModifier(m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(modifier)) as PokemonHeldItemModifier;
|
const matchingModifier = pokemon.scene.findModifier(m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(modifier)) as PokemonHeldItemModifier;
|
||||||
if (matchingModifier && matchingModifier.stackCount === matchingModifier.getMaxStackCount(pokemon.scene)) {
|
if (matchingModifier && matchingModifier.stackCount === matchingModifier.getMaxStackCount(pokemon.scene)) {
|
||||||
return i18next.t("partyUiHandler:tooManyItems", { pokemonName: getPokemonNameWithAffix(pokemon) });
|
return i18next.t("partyUiHandler:tooManyItems", { pokemonName: getPokemonNameWithAffix(pokemon, false) });
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
@ -380,18 +380,18 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
this.clearOptions();
|
this.clearOptions();
|
||||||
ui.playSelect();
|
ui.playSelect();
|
||||||
pokemon.pauseEvolutions = false;
|
pokemon.pauseEvolutions = false;
|
||||||
this.showText(i18next.t("partyUiHandler:unpausedEvolutions", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => this.showText(null, 0), null, true);
|
this.showText(i18next.t("partyUiHandler:unpausedEvolutions", { pokemonName: getPokemonNameWithAffix(pokemon, false) }), null, () => this.showText(null, 0), null, true);
|
||||||
} else if (option === PartyOption.UNSPLICE) {
|
} else if (option === PartyOption.UNSPLICE) {
|
||||||
this.clearOptions();
|
this.clearOptions();
|
||||||
ui.playSelect();
|
ui.playSelect();
|
||||||
this.showText(i18next.t("partyUiHandler:unspliceConfirmation", { fusionName: pokemon.fusionSpecies.name, pokemonName: pokemon.name }), null, () => {
|
this.showText(i18next.t("partyUiHandler:unspliceConfirmation", { fusionName: pokemon.fusionSpecies.name, pokemonName: pokemon.getName() }), null, () => {
|
||||||
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||||
const fusionName = pokemon.name;
|
const fusionName = pokemon.getName(false);
|
||||||
pokemon.unfuse().then(() => {
|
pokemon.unfuse().then(() => {
|
||||||
this.clearPartySlots();
|
this.clearPartySlots();
|
||||||
this.populatePartySlots();
|
this.populatePartySlots();
|
||||||
ui.setMode(Mode.PARTY);
|
ui.setMode(Mode.PARTY);
|
||||||
this.showText(i18next.t("partyUiHandler:wasReverted", { fusionName: fusionName, pokemonName: pokemon.name }), null, () => {
|
this.showText(i18next.t("partyUiHandler:wasReverted", { fusionName: fusionName, pokemonName: pokemon.getName() }), null, () => {
|
||||||
ui.setMode(Mode.PARTY);
|
ui.setMode(Mode.PARTY);
|
||||||
this.showText(null, 0);
|
this.showText(null, 0);
|
||||||
}, null, true);
|
}, null, true);
|
||||||
@ -405,7 +405,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
this.clearOptions();
|
this.clearOptions();
|
||||||
ui.playSelect();
|
ui.playSelect();
|
||||||
if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) {
|
if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) {
|
||||||
this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => {
|
this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: getPokemonNameWithAffix(pokemon, false) }), null, () => {
|
||||||
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||||
ui.setMode(Mode.PARTY);
|
ui.setMode(Mode.PARTY);
|
||||||
this.doRelease(this.cursor);
|
this.doRelease(this.cursor);
|
||||||
@ -950,7 +950,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doRelease(slotIndex: integer): void {
|
doRelease(slotIndex: integer): void {
|
||||||
this.showText(this.getReleaseMessage(getPokemonNameWithAffix(this.scene.getParty()[slotIndex])), null, () => {
|
this.showText(this.getReleaseMessage(getPokemonNameWithAffix(this.scene.getParty()[slotIndex], false)), null, () => {
|
||||||
this.clearPartySlots();
|
this.clearPartySlots();
|
||||||
this.scene.removePartyMemberModifiers(slotIndex);
|
this.scene.removePartyMemberModifiers(slotIndex);
|
||||||
const releasedPokemon = this.scene.getParty().splice(slotIndex, 1)[0];
|
const releasedPokemon = this.scene.getParty().splice(slotIndex, 1)[0];
|
||||||
@ -1081,7 +1081,7 @@ class PartySlot extends Phaser.GameObjects.Container {
|
|||||||
const slotInfoContainer = this.scene.add.container(0, 0);
|
const slotInfoContainer = this.scene.add.container(0, 0);
|
||||||
this.add(slotInfoContainer);
|
this.add(slotInfoContainer);
|
||||||
|
|
||||||
let displayName = this.pokemon.getNameToRender();
|
let displayName = this.pokemon.getNameToRender(false);
|
||||||
let nameTextWidth: number;
|
let nameTextWidth: number;
|
||||||
|
|
||||||
const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.PARTY);
|
const nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.PARTY);
|
||||||
@ -1148,12 +1148,12 @@ class PartySlot extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.pokemon.isShiny()) {
|
if (this.pokemon.isShiny()) {
|
||||||
const doubleShiny = this.pokemon.isFusion() && this.pokemon.shiny && this.pokemon.fusionShiny;
|
const doubleShiny = this.pokemon.isDoubleShiny(false);
|
||||||
|
|
||||||
const shinyStar = this.scene.add.image(0, 0, `shiny_star_small${doubleShiny ? "_1" : ""}`);
|
const shinyStar = this.scene.add.image(0, 0, `shiny_star_small${doubleShiny ? "_1" : ""}`);
|
||||||
shinyStar.setOrigin(0, 0);
|
shinyStar.setOrigin(0, 0);
|
||||||
shinyStar.setPositionRelative(slotName, -9, 3);
|
shinyStar.setPositionRelative(slotName, -9, 3);
|
||||||
shinyStar.setTint(getVariantTint(!doubleShiny ? this.pokemon.getVariant() : this.pokemon.variant));
|
shinyStar.setTint(getVariantTint(this.pokemon.getBaseVariant(doubleShiny)));
|
||||||
|
|
||||||
slotInfoContainer.add(shinyStar);
|
slotInfoContainer.add(shinyStar);
|
||||||
|
|
||||||
@ -1161,7 +1161,7 @@ class PartySlot extends Phaser.GameObjects.Container {
|
|||||||
const fusionShinyStar = this.scene.add.image(0, 0, "shiny_star_small_2");
|
const fusionShinyStar = this.scene.add.image(0, 0, "shiny_star_small_2");
|
||||||
fusionShinyStar.setOrigin(0, 0);
|
fusionShinyStar.setOrigin(0, 0);
|
||||||
fusionShinyStar.setPosition(shinyStar.x, shinyStar.y);
|
fusionShinyStar.setPosition(shinyStar.x, shinyStar.y);
|
||||||
fusionShinyStar.setTint(getVariantTint(this.pokemon.fusionVariant));
|
fusionShinyStar.setTint(getVariantTint(this.pokemon.illusion.fusionVariant ?? this.pokemon.fusionVariant));
|
||||||
|
|
||||||
slotInfoContainer.add(fusionShinyStar);
|
slotInfoContainer.add(fusionShinyStar);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ export default class RenameFormUiHandler extends FormModalUiHandler {
|
|||||||
show(args: any[]): boolean {
|
show(args: any[]): boolean {
|
||||||
if (super.show(args)) {
|
if (super.show(args)) {
|
||||||
const config = args[0] as ModalConfig;
|
const config = args[0] as ModalConfig;
|
||||||
this.inputs[0].text = (args[1] as PlayerPokemon).getNameToRender();
|
this.inputs[0].text = (args[1] as PlayerPokemon).getNameToRender(false);
|
||||||
|
|
||||||
this.submitAction = (_) => {
|
this.submitAction = (_) => {
|
||||||
this.sanitizeInputs();
|
this.sanitizeInputs();
|
||||||
|
@ -301,8 +301,8 @@ export default class SummaryUiHandler extends UiHandler {
|
|||||||
this.pokemonSprite.setPipelineData("teraColor", getTypeRgb(this.pokemon.getTeraType()));
|
this.pokemonSprite.setPipelineData("teraColor", getTypeRgb(this.pokemon.getTeraType()));
|
||||||
this.pokemonSprite.setPipelineData("ignoreTimeTint", true);
|
this.pokemonSprite.setPipelineData("ignoreTimeTint", true);
|
||||||
this.pokemonSprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
this.pokemonSprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
||||||
this.pokemonSprite.setPipelineData("shiny", this.pokemon.shiny);
|
this.pokemonSprite.setPipelineData("shiny", this.pokemon.illusion.shiny ?? this.pokemon.shiny);
|
||||||
this.pokemonSprite.setPipelineData("variant", this.pokemon.variant);
|
this.pokemonSprite.setPipelineData("variant", this.pokemon.illusion.variant ?? this.pokemon.variant);
|
||||||
[ "spriteColors", "fusionSpriteColors" ].map(k => {
|
[ "spriteColors", "fusionSpriteColors" ].map(k => {
|
||||||
delete this.pokemonSprite.pipelineData[`${k}Base`];
|
delete this.pokemonSprite.pipelineData[`${k}Base`];
|
||||||
if (this.pokemon.summonData?.speciesForm) {
|
if (this.pokemon.summonData?.speciesForm) {
|
||||||
@ -312,7 +312,7 @@ export default class SummaryUiHandler extends UiHandler {
|
|||||||
});
|
});
|
||||||
this.pokemon.cry();
|
this.pokemon.cry();
|
||||||
|
|
||||||
this.nameText.setText(this.pokemon.getNameToRender());
|
this.nameText.setText(this.pokemon.getNameToRender(false));
|
||||||
|
|
||||||
const isFusion = this.pokemon.isFusion();
|
const isFusion = this.pokemon.isFusion();
|
||||||
|
|
||||||
@ -346,12 +346,12 @@ export default class SummaryUiHandler extends UiHandler {
|
|||||||
|
|
||||||
this.candyShadow.setCrop(0,0,16, candyCropY);
|
this.candyShadow.setCrop(0,0,16, candyCropY);
|
||||||
|
|
||||||
const doubleShiny = isFusion && this.pokemon.shiny && this.pokemon.fusionShiny;
|
const doubleShiny = this.pokemon.isDoubleShiny(false);
|
||||||
const baseVariant = !doubleShiny ? this.pokemon.getVariant() : this.pokemon.variant;
|
const baseVariant = this.pokemon.getBaseVariant(doubleShiny);
|
||||||
|
|
||||||
this.shinyIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0) + 1, 3);
|
this.shinyIcon.setPositionRelative(this.nameText, this.nameText.displayWidth + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0) + 1, 3);
|
||||||
this.shinyIcon.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`);
|
this.shinyIcon.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`);
|
||||||
this.shinyIcon.setVisible(this.pokemon.isShiny());
|
this.shinyIcon.setVisible(this.pokemon.isShiny(false));
|
||||||
this.shinyIcon.setTint(getVariantTint(baseVariant));
|
this.shinyIcon.setTint(getVariantTint(baseVariant));
|
||||||
if (this.shinyIcon.visible) {
|
if (this.shinyIcon.visible) {
|
||||||
const shinyDescriptor = doubleShiny || baseVariant ?
|
const shinyDescriptor = doubleShiny || baseVariant ?
|
||||||
@ -364,7 +364,7 @@ export default class SummaryUiHandler extends UiHandler {
|
|||||||
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
|
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
|
||||||
this.fusionShinyIcon.setVisible(doubleShiny);
|
this.fusionShinyIcon.setVisible(doubleShiny);
|
||||||
if (isFusion) {
|
if (isFusion) {
|
||||||
this.fusionShinyIcon.setTint(getVariantTint(this.pokemon.fusionVariant));
|
this.fusionShinyIcon.setTint(getVariantTint(this.pokemon.illusion.fusionVariant ?? this.pokemon.fusionVariant));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pokeball.setFrame(getPokeballAtlasKey(this.pokemon.pokeball));
|
this.pokeball.setFrame(getPokeballAtlasKey(this.pokemon.pokeball));
|
||||||
@ -727,7 +727,7 @@ export default class SummaryUiHandler extends UiHandler {
|
|||||||
return typeIcon;
|
return typeIcon;
|
||||||
};
|
};
|
||||||
|
|
||||||
const types = this.pokemon.getTypes(false, false, true);
|
const types = this.pokemon.getTypes(false, false, true, false);
|
||||||
profileContainer.add(getTypeIcon(0, types[0]));
|
profileContainer.add(getTypeIcon(0, types[0]));
|
||||||
if (types.length > 1) {
|
if (types.length > 1) {
|
||||||
profileContainer.add(getTypeIcon(1, types[1]));
|
profileContainer.add(getTypeIcon(1, types[1]));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user