Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ability] Implement Illusion #3273

Open
wants to merge 54 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
9f26ea9
implement illusion ability with unit test and localizations
PyGaVS Jul 31, 2024
34a8e9b
try removing whitespace change on unnecessary files
PyGaVS Jul 31, 2024
34c534f
merge up-to-date
PyGaVS Aug 1, 2024
52c1535
merge and solve conflicts
PyGaVS Aug 2, 2024
699de17
review correction and merge conflicts up-to-date
PyGaVS Aug 4, 2024
41ca2cd
nit corrections
PyGaVS Aug 4, 2024
909d166
nit update src/field/pokemon.ts
PyGaVS Aug 4, 2024
205ee83
nit update src/phases.ts
PyGaVS Aug 4, 2024
889465b
illusion test correction
PyGaVS Aug 5, 2024
b552ced
Merge branch 'pr-illusion' of https://github.com/PyGaVS/pokerogue int…
PyGaVS Aug 5, 2024
9f73316
merge up-to date
PyGaVS Aug 8, 2024
cf41d96
merge up-to-date
PyGaVS Aug 8, 2024
8b4a758
unexpected error correction
PyGaVS Aug 8, 2024
60d442b
Merge branch 'beta' into pr-illusion
PyGaVS Aug 9, 2024
b03cdb6
Merge branch 'beta' into pr-illusion
PyGaVS Aug 12, 2024
5bd06bc
Merge branch 'beta' into pr-illusion
PyGaVS Aug 14, 2024
118c654
Merge branch 'beta' into pr-illusion
PyGaVS Aug 16, 2024
947ee48
update some phases after merge
PyGaVS Aug 19, 2024
7214c70
refactor property pokemon.illusion to pokemon.battleData.illusion
PyGaVS Aug 19, 2024
20295da
nit
PyGaVS Aug 19, 2024
62865ef
nit
PyGaVS Aug 19, 2024
5ed3bcd
merge conflicts
PyGaVS Aug 22, 2024
964692f
merge conflicts
PyGaVS Aug 25, 2024
9c47031
update unit test up-to-date
PyGaVS Aug 26, 2024
c24359c
add docs
PyGaVS Aug 26, 2024
77e9bd7
merge up-to-date
PyGaVS Aug 27, 2024
6a61910
merge up to date
PyGaVS Sep 16, 2024
05ad97f
merge up to date
PyGaVS Sep 16, 2024
b5d8034
bugfix
PyGaVS Oct 10, 2024
df1c789
bugfix
PyGaVS Oct 10, 2024
1a287e7
merge up-to-date
PyGaVS Oct 10, 2024
57bbeb1
merge up to date
PyGaVS Oct 10, 2024
1e9a2a7
refactor field illusion out of battleData
PyGaVS Oct 10, 2024
e1a3c2e
Merge branch 'beta' into pr-illusion
PyGaVS Oct 10, 2024
cf8f778
fix nit
PyGaVS Oct 10, 2024
2557a28
Merge branch 'pr-illusion' of https://github.com/PyGaVS/pokerogue int…
PyGaVS Oct 10, 2024
53fcc10
fix nit
PyGaVS Oct 10, 2024
1535c2f
Merge branch 'beta' into pr-illusion
PyGaVS Oct 10, 2024
d7ed17b
Zoroark change illusion after lastPokemon update
PyGaVS Oct 11, 2024
6396943
Zoroark change illusion after lastPokemon update
PyGaVS Oct 11, 2024
eba3d1d
Merge branch 'beta' into pr-illusion
PyGaVS Oct 11, 2024
c603260
refactor bug fix
PyGaVS Oct 11, 2024
9fd3c3e
Merge branch 'pr-illusion' of https://github.com/PyGaVS/pokerogue int…
PyGaVS Oct 11, 2024
0a9337c
bugfix
PyGaVS Oct 12, 2024
5fbc7e6
Merge branch 'beta' into pr-illusion
PyGaVS Oct 12, 2024
d56e1cf
Merge branch 'beta' into pr-illusion
PyGaVS Oct 13, 2024
d46c3a9
Merge branch 'beta' into pr-illusion
PyGaVS Oct 14, 2024
37e152f
Merge branch 'beta' into pr-illusion
PyGaVS Oct 15, 2024
9544349
Merge branch 'beta' into pr-illusion
PyGaVS Oct 16, 2024
68165c8
Merge branch 'beta' into pr-illusion
PyGaVS Oct 17, 2024
0b21d89
resolve conflicts
PyGaVS Oct 20, 2024
1f95598
merge up to date
PyGaVS Oct 22, 2024
467ebaa
bug fix on tests
PyGaVS Oct 22, 2024
ada362e
merge conflicts
PyGaVS Oct 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/battle-scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ export default class BattleScene extends SceneBase {

container.add(icon);

if (pokemon.isFusion()) {
if (pokemon.isFusion(true)) {
const fusionIcon = this.add.sprite(0, 0, pokemon.getFusionIconAtlasKey(ignoreOverride));
fusionIcon.setName("sprite-fusion-icon");
fusionIcon.setOrigin(0.5, 0);
Expand Down
131 changes: 126 additions & 5 deletions src/data/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,6 @@ export class PostSummonRemoveArenaTagAbAttr extends PostSummonAbAttr {
return true;
}
}

export class PostSummonMessageAbAttr extends PostSummonAbAttr {
private messageFunc: (pokemon: Pokemon) => string;

Expand All @@ -2043,6 +2042,18 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr {
}
}

/**
* Removes illusions when a Pokemon is summoned.
*/
export class PostSummonRemoveIllusionAbAttr extends PostSummonAbAttr {
PyGaVS marked this conversation as resolved.
Show resolved Hide resolved
applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
pokemon.scene.getField(true).map(pokemon => {
pokemon.breakIllusion();
});
return true;
}
}

export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr {
//Attr doesn't force pokemon name on the message
private message: string;
Expand Down Expand Up @@ -2429,13 +2440,16 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
}
const promises: Promise<void>[] = [];

let target: Pokemon;
let target: Pokemon = targets[0];
if (targets.length > 1) {
pokemon.scene.executeWithSeedOffset(() => target = Utils.randSeedItem(targets), pokemon.scene.currentBattle.waveIndex);
} else {
target = targets[0];
}

if (target.battleData.illusion.active) {
return false;
}
target = target!;
pokemon.summonData.speciesForm = target.getSpeciesForm();
pokemon.summonData.fusionSpeciesForm = target.getFusionSpeciesForm();
Expand Down Expand Up @@ -4003,8 +4017,8 @@ export class MaxMultiHitAbAttr extends AbAttr {
}

export class PostBattleAbAttr extends AbAttr {
constructor() {
super(true);
constructor(showAbility: boolean = true) {
super(showAbility);
}

applyPostBattle(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
Expand Down Expand Up @@ -4590,6 +4604,99 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
}
}

/**
* Base class for defining {@linkcode Ability} attributes before summon
* (should use {@linkcode PostSummonAbAttr} for most ability)
PyGaVS marked this conversation as resolved.
Show resolved Hide resolved
* @see {@linkcode applyPreSummon()}
*/
export class PreSummonAbAttr extends AbAttr {
PyGaVS marked this conversation as resolved.
Show resolved Hide resolved
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
PyGaVS marked this conversation as resolved.
Show resolved Hide resolved
* @param {...any} args - N/A
* @returns {boolean} - Whether the illusion was applied.
*/
applyPreSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
let suppressed = false;
console.log("PRESUMMONILLUSION : ", pokemon.name);
pokemon.scene.getField(true).filter(p => p !== pokemon).map(p => {
if ((p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) || (p.getPassiveAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility(true))) {
suppressed = true;
}
});

if (pokemon.battleData.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, simulated: 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();
return true;
}
}

export class IllusionPostBattleAbAttr 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, simulated:boolean, args: any[]): boolean {
pokemon.breakIllusion();
pokemon.battleData.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, simulated: boolean, args: any[]): boolean {
pokemon.battleData.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).
*
Expand Down Expand Up @@ -4804,6 +4911,11 @@ export function applyPostSummonAbAttrs(attrType: Constructor<PostSummonAbAttr>,
return applyAbAttrsInternal<PostSummonAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args), args, false, simulated);
}

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>,
pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PreSwitchOutAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, simulated, args), args, true, simulated);
Expand Down Expand Up @@ -5363,7 +5475,15 @@ export function initAbilities() {
new Ability(Abilities.ILLUSION, 5)
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.unimplemented(),
//The pokemon generate an illusion if it's available
.conditionalAttr((pokemon) => pokemon.battleData.illusion.available, IllusionPreSummonAbAttr, false)
//The pokemon loses his illusion when he is damaged by a move
.conditionalAttr((pokemon) => pokemon.battleData.illusion.active, IllusionBreakAbAttr, true)
//Illusion is available again after a battle
.conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false)
//Illusion is not available after summon
.attr(IllusionDisableAbAttr, false)
.bypassFaint(),
new Ability(Abilities.IMPOSTER, 5)
.attr(PostSummonTransformAbAttr)
.attr(UncopiableAbilityAbAttr),
Expand Down Expand Up @@ -5759,6 +5879,7 @@ export function initAbilities() {
.attr(UnswappableAbilityAbAttr)
.attr(NoTransformAbilityAbAttr)
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
.attr(PostSummonRemoveIllusionAbAttr)
.partial(), // A bunch of weird interactions with other abilities being suppressed then unsuppressed
new Ability(Abilities.PASTEL_VEIL, 8)
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)
Expand Down
14 changes: 8 additions & 6 deletions src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6483,12 +6483,13 @@ export class AbilityChangeAttr extends MoveEffectAttr {
}

const moveTarget = this.selfTarget ? user : target;

moveTarget.summonData.ability = this.ability;
const pokemon: Pokemon = this.selfTarget ? user : target;
pokemon.summonData.ability = this.ability;
user.scene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);

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;
}

Expand Down Expand Up @@ -6644,7 +6645,8 @@ export class SuppressAbilitiesIfActedAttr extends MoveEffectAttr {

export class TransformAttr extends MoveEffectAttr {
async apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): Promise<boolean> {
if (!super.apply(user, target, move, args)) {
if (!super.apply(user, target, move, args) || target.battleData.illusion.active || user.battleData.illusion.active) {
user.scene.queueMessage(i18next.t("battle:attackFailed"));
return false;
}

Expand Down
Loading
Loading