Skip to content

Commit 068c935

Browse files
committed
illusion working entirely
1 parent dc2bf95 commit 068c935

File tree

5 files changed

+119
-100
lines changed

5 files changed

+119
-100
lines changed

src/data/ability.ts

+46-47
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { Command } from "../ui/command-ui-handler";
2323
import { BerryModifierType } from "#app/modifier/modifier-type";
2424
import { getPokeballName } from "./pokeball";
2525
import { Species } from "./enums/species";
26-
import PokemonSpecies, { getPokemonSpecies } from "./pokemon-species";
2726
import { BattlerIndex } from "#app/battle";
2827

2928
export class Ability implements Localizable {
@@ -2471,7 +2470,7 @@ function getTerrainCondition(...terrainTypes: TerrainType[]): AbAttrCondition {
24712470
}
24722471

24732472
export class PostTurnAbAttr extends AbAttr {
2474-
applyPostTurn(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
2473+
applyPostTurn(pokemon: Pokemon, passive: boolean, party: Pokemon[], args: any[]): boolean | Promise<boolean> {
24752474
return false;
24762475
}
24772476
}
@@ -2996,11 +2995,11 @@ export class MaxMultiHitAbAttr extends AbAttr {
29962995
}
29972996

29982997
export class PostBattleAbAttr extends AbAttr {
2999-
constructor() {
3000-
super(true);
2998+
constructor(showAbility: boolean = true) {
2999+
super(showAbility);
30013000
}
30023001

3003-
applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
3002+
applyPostBattle(pokemon: Pokemon, passive: boolean, party: Pokemon[], args: any[]): boolean {
30043003
return false;
30053004
}
30063005
}
@@ -3475,61 +3474,57 @@ export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr {
34753474
}
34763475
}
34773476

3478-
export class IllusionAbAttr extends PreSummonAbAttr {
3479-
3480-
public trueName: string;
3481-
3482-
applyPreSummon(pokemon: Pokemon, passive: boolean, party: Pokemon[]) {
3483-
3484-
//Case when Zoroark already used illusion one someone
3485-
if (!!pokemon.illusion.name) {
3477+
export class IllusionPreSummonAbAttr extends PreSummonAbAttr {
3478+
applyPreSummon(pokemon: Pokemon, passive: boolean, party: Pokemon[], args: any[]): boolean | Promise<boolean> {
3479+
if (pokemon.illusion.available) {
3480+
pokemon.generateIllusion(pokemon, party);
3481+
return true;
3482+
} else {
34863483
return false;
34873484
}
3485+
}
3486+
}
34883487

3489-
if (pokemon.hasTrainer()) {
3490-
const aliveParty: Pokemon[] = [];
3491-
for (const pkmn of party) {
3492-
if (pkmn.isAllowedInBattle()) {
3493-
aliveParty.push(pkmn);
3494-
}
3495-
}
3496-
const lastPokemon: Pokemon = aliveParty.slice(-1)[0];
3497-
3498-
pokemon.illusion = {active: true, species: lastPokemon.species, name: pokemon.name};
3499-
pokemon.name = lastPokemon.name;
3488+
export class IllusionPostTurnAbAttr extends PostTurnAbAttr {
3489+
applyPostTurn(pokemon: Pokemon, passive: boolean, party: Pokemon[]) {
3490+
if (pokemon.hasTrainer() && !pokemon.isOnField() && pokemon.illusion.available) {
3491+
pokemon.generateIllusion(pokemon, party);
35003492
return true;
35013493
} else {
3502-
console.log("ALLO");
3503-
const availables = [Species.ENTEI, Species.RAIKOU, Species.SUICUNE];
3504-
const randomIllusion: PokemonSpecies = getPokemonSpecies(availables[Math.floor(Math.random()*3)]);
3505-
pokemon.illusion = {active: true, species: randomIllusion, name: pokemon.name};
3506-
pokemon.name = randomIllusion.name;
3494+
return false;
35073495
}
35083496
}
35093497
}
35103498

35113499
export class IllusionBreakAbAttr extends PostDefendAbAttr {
3512-
35133500
applyPostDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean | Promise<boolean> {
35143501
if (hitResult > 4) {
35153502
return false;
35163503
}
35173504
pokemon.illusion.active = false;
3518-
//pokemon.summonData.speciesForm = pokemon.getSpeciesForm();
3519-
pokemon.name = pokemon.species.name;
3505+
pokemon.name = pokemon.illusion.name;
35203506
pokemon.scene.playSound("PRSFX- Transform");
3521-
35223507
pokemon.loadAssets(false).then(() => pokemon.playAnim());
3523-
3524-
//pokemon.scene.queueMessage(getPokemonMessage(pokemon, ` transformed\ninto ${target.name}!`));
3508+
pokemon.scene.queueMessage(getPokemonMessage(pokemon, "'s illusion wore off!"));
35253509
return true;
35263510
}
35273511
}
35283512

35293513
export class IllusionAfterBattle extends PostBattleAbAttr {
3530-
applyPostBattle(pokemon: Pokemon, passive: boolean, args: any[]): boolean {
3531-
//Reset illusion
3532-
pokemon.illusion = {active: false};
3514+
applyPostBattle(pokemon: Pokemon, passive: boolean, party: Pokemon[], args: any[]): boolean {
3515+
pokemon.generateIllusion(pokemon, party);
3516+
if (pokemon.isOnField()) {
3517+
pokemon.scene.playSound("PRSFX- Transform");
3518+
pokemon.illusion.available = false;
3519+
}
3520+
pokemon.loadAssets(false).then(() => pokemon.playAnim());
3521+
return true;
3522+
}
3523+
}
3524+
3525+
export class IllusionDisableAbAttr extends PostSummonAbAttr {
3526+
applyPostSummon(pokemon: Pokemon, passive: boolean, args: any[]): boolean | Promise<boolean> {
3527+
pokemon.illusion.available = false;
35333528
return true;
35343529
}
35353530
}
@@ -3701,8 +3696,8 @@ export function applyPreWeatherEffectAbAttrs(attrType: { new(...args: any[]): Pr
37013696
}
37023697

37033698
export function applyPostTurnAbAttrs(attrType: { new(...args: any[]): PostTurnAbAttr },
3704-
pokemon: Pokemon, ...args: any[]): Promise<void> {
3705-
return applyAbAttrsInternal<PostTurnAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, args), args);
3699+
pokemon: Pokemon, party: Pokemon[], ...args: any[]): Promise<void> {
3700+
return applyAbAttrsInternal<PostTurnAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostTurn(pokemon, passive, party, args), args);
37063701
}
37073702

37083703
export function applyPostWeatherChangeAbAttrs(attrType: { new(...args: any[]): PostWeatherChangeAbAttr },
@@ -3726,8 +3721,8 @@ export function applyCheckTrappedAbAttrs(attrType: { new(...args: any[]): CheckT
37263721
}
37273722

37283723
export function applyPostBattleAbAttrs(attrType: { new(...args: any[]): PostBattleAbAttr },
3729-
pokemon: Pokemon, ...args: any[]): Promise<void> {
3730-
return applyAbAttrsInternal<PostBattleAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, args), args);
3724+
pokemon: Pokemon, party: Pokemon[], ...args: any[]): Promise<void> {
3725+
return applyAbAttrsInternal<PostBattleAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostBattle(pokemon, passive, party, args), args);
37313726
}
37323727

37333728
export function applyPostFaintAbAttrs(attrType: { new(...args: any[]): PostFaintAbAttr },
@@ -4200,12 +4195,16 @@ export function initAbilities() {
42004195
new Ability(Abilities.ILLUSION, 5)
42014196
.attr(UncopiableAbilityAbAttr)
42024197
.attr(UnswappableAbilityAbAttr)
4203-
//The pokemon get the illusion when summon
4204-
.attr(IllusionAbAttr, false)
4198+
//The pokemon genrate an illusion if it's available
4199+
.conditionalAttr((pokemon) => pokemon.illusion.available, IllusionPostTurnAbAttr, false)
4200+
.conditionalAttr((pokemon) => pokemon.illusion.available, IllusionPreSummonAbAttr, false)
4201+
//Illusion is not available after summon
4202+
.attr(IllusionDisableAbAttr, false)
42054203
//The pokemon loses his illusion when he is damaged by a move
4206-
.conditionalAttr((pokemon) => pokemon.illusion.active, IllusionBreakAbAttr)
4207-
//Zoroark can do illusion again after a battle
4208-
.attr(IllusionAfterBattle),
4204+
.conditionalAttr((pokemon) => pokemon.illusion.active, IllusionBreakAbAttr, true)
4205+
//Illusion is available again after a battle again after a battle
4206+
.conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionAfterBattle, false)
4207+
.bypassFaint(),
42094208
new Ability(Abilities.IMPOSTER, 5)
42104209
.attr(PostSummonTransformAbAttr)
42114210
.attr(UncopiableAbilityAbAttr),

src/data/enums/battler-tag-type.ts

-1
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,4 @@ export enum BattlerTagType {
5959
MINIMIZED = "MINIMIZED",
6060
DESTINY_BOND = "DESTINY_BOND",
6161
ICE_FACE = "ICE_FACE",
62-
ILLUSIONED = "ILLUSIONED"
6362
}

src/field/pokemon.ts

+50-31
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
6060
public id: integer;
6161
public name: string;
6262
public species: PokemonSpecies;
63-
public illusion: {active: boolean, species?: PokemonSpecies, name?: string};
63+
public illusion: {active: boolean, available: boolean, species?: PokemonSpecies, name?: string, fusionSpecies?: PokemonSpecies};
6464
public formIndex: integer;
6565
public abilityIndex: integer;
6666
public passive: boolean;
@@ -124,7 +124,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
124124
const randAbilityIndex = Utils.randSeedInt(2);
125125

126126
this.species = species;
127-
this.illusion = {active: false};
127+
this.illusion = {active: false, available: true};
128128

129129
this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL;
130130
this.level = level;
@@ -308,6 +308,29 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
308308
}
309309
}
310310

311+
generateIllusion(pokemon: Pokemon, party: Pokemon[]): void {
312+
if (pokemon.hasTrainer()) {
313+
const lastPokemon: Pokemon = party.slice(-1)[0];
314+
const speciesId = lastPokemon.species.speciesId;
315+
pokemon.illusion = {
316+
active: true,
317+
available: true,
318+
species: getPokemonSpecies(speciesId),
319+
fusionSpecies: lastPokemon.fusionSpecies,
320+
name: pokemon.name
321+
};
322+
pokemon.name = lastPokemon.name;
323+
pokemon.loadAssets(false).then(() => pokemon.playAnim());
324+
} else {
325+
const availables = [Species.ENTEI, Species.RAIKOU, Species.SUICUNE];
326+
const randomIllusion: PokemonSpecies = getPokemonSpecies(availables[Math.floor(Math.random()*3)]);
327+
pokemon.illusion = {active: true, available: true, species: randomIllusion, name: pokemon.name};
328+
pokemon.name = randomIllusion.name;
329+
pokemon.loadAssets(false).then(() => pokemon.playAnim());
330+
}
331+
332+
}
333+
311334
abstract isPlayer(): boolean;
312335

313336
abstract hasTrainer(): boolean;
@@ -322,7 +345,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
322345
Promise.allSettled(moveIds.map(m => initMoveAnim(this.scene, m)))
323346
.then(() => {
324347
loadMoveAnimAssets(this.scene, moveIds);
325-
this.getSpeciesForm().loadAssets(this.scene, this.getGender() === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
348+
this.getSpeciesForm(false, true).loadAssets(this.scene, this.getGender() === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
326349
if (this.isPlayer() || this.getFusionSpeciesForm()) {
327350
this.scene.loadPokemonAtlas(this.getBattleSpriteKey(true, ignoreOverride), this.getBattleSpriteAtlasPath(true, ignoreOverride));
328351
}
@@ -427,7 +450,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
427450
}
428451

429452
getSpriteId(ignoreOverride?: boolean): string {
430-
return this.getSpeciesForm(ignoreOverride).getSpriteId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
453+
return this.getSpeciesForm(ignoreOverride, true).getSpriteId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
431454
}
432455

433456
getBattleSpriteId(back?: boolean, ignoreOverride?: boolean): string {
@@ -438,7 +461,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
438461
}
439462

440463
getSpriteKey(ignoreOverride?: boolean): string {
441-
return this.getSpeciesForm(ignoreOverride).getSpriteKey(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
464+
return this.getSpeciesForm(ignoreOverride, false).getSpriteKey(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
442465
}
443466

444467
getBattleSpriteKey(back?: boolean, ignoreOverride?: boolean): string {
@@ -465,42 +488,42 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
465488
}
466489

467490
getIconAtlasKey(ignoreOverride?: boolean): string {
468-
return this.getSpeciesForm(ignoreOverride).getIconAtlasKey(this.formIndex, this.shiny, this.variant);
491+
return this.getSpeciesForm(ignoreOverride, true).getIconAtlasKey(this.formIndex, this.shiny, this.variant);
469492
}
470493

471494
getFusionIconAtlasKey(ignoreOverride?: boolean): string {
472-
return this.getFusionSpeciesForm(ignoreOverride).getIconAtlasKey(this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
495+
return this.getFusionSpeciesForm(ignoreOverride, true).getIconAtlasKey(this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
473496
}
474497

475498
getIconId(ignoreOverride?: boolean): string {
476-
return this.getSpeciesForm(ignoreOverride).getIconId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
499+
return this.getSpeciesForm(ignoreOverride, true).getIconId(this.getGender(ignoreOverride) === Gender.FEMALE, this.formIndex, this.shiny, this.variant);
477500
}
478501

479502
getFusionIconId(ignoreOverride?: boolean): string {
480-
return this.getFusionSpeciesForm(ignoreOverride).getIconId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
503+
return this.getFusionSpeciesForm(ignoreOverride, true).getIconId(this.getFusionGender(ignoreOverride) === Gender.FEMALE, this.fusionFormIndex, this.fusionShiny, this.fusionVariant);
481504
}
482505

483-
getSpeciesForm(ignoreOverride?: boolean, illusion?: boolean): PokemonSpeciesForm {
484-
//ICITO
506+
getSpeciesForm(ignoreOverride?: boolean, illusion: boolean = false): PokemonSpeciesForm {
485507
const species: PokemonSpecies = illusion && this.illusion.active ? this.illusion.species : this.species;
486-
487508
if (!ignoreOverride && this.summonData?.speciesForm) {
488509
return this.summonData.speciesForm;
489510
}
511+
490512
if (!species.forms?.length) {
491513
return species;
492514
}
493515
return species.forms[this.formIndex];
494516
}
495517

496-
getFusionSpeciesForm(ignoreOverride?: boolean): PokemonSpeciesForm {
518+
getFusionSpeciesForm(ignoreOverride?: boolean, illusion: boolean = false): PokemonSpeciesForm {
519+
const fusionSpecies: PokemonSpecies = illusion && this.illusion.active ? (this.illusion.fusionSpecies ?? this.illusion.species) : this.fusionSpecies;
497520
if (!ignoreOverride && this.summonData?.speciesForm) {
498521
return this.summonData.fusionSpeciesForm;
499522
}
500-
if (!this.fusionSpecies?.forms?.length || this.fusionFormIndex >= this.fusionSpecies?.forms.length) {
501-
return this.fusionSpecies;
523+
if (!fusionSpecies?.forms?.length || this.fusionFormIndex >= fusionSpecies?.forms.length) {
524+
return fusionSpecies;
502525
}
503-
return this.fusionSpecies?.forms[this.fusionFormIndex];
526+
return fusionSpecies?.forms[this.fusionFormIndex];
504527
}
505528

506529
getSprite(): Phaser.GameObjects.Sprite {
@@ -849,34 +872,31 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
849872
return this.getLevelMoves(1, true).map(lm => lm[1]).filter(lm => !this.moveset.filter(m => m.moveId === lm).length).filter((move: Moves, i: integer, array: Moves[]) => array.indexOf(move) === i);
850873
}
851874

852-
getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride?: boolean, illusion: boolean = true): Type[] {
853-
const types = [];
854-
875+
getTypes(includeTeraType = false, forDefend: boolean = false, ignoreOverride?: boolean, illusion: boolean | "AUTO" = "AUTO"): Type[] {
876+
const types: Type[] = [];
855877
if (includeTeraType) {
856878
const teraType = this.getTeraType();
857879
if (teraType !== Type.UNKNOWN) {
858880
types.push(teraType);
859881
}
860882
}
861-
862883
if (!types.length || !includeTeraType) {
863884
if (!ignoreOverride && this.summonData?.types) {
864885
this.summonData.types.forEach(t => types.push(t));
865886
} else {
866-
//ILLUSION /!\
867-
const speciesForm = this.getSpeciesForm(ignoreOverride, !forDefend && illusion);
887+
const doIllusion: boolean = illusion === "AUTO" ? !forDefend : illusion;
868888

869-
types.push(speciesForm.type1);
889+
const speciesForm = this.getSpeciesForm(ignoreOverride, doIllusion);
870890

871-
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride);
891+
types.push(speciesForm.type1);
892+
const fusionSpeciesForm = this.getFusionSpeciesForm(ignoreOverride, doIllusion);
872893
if (fusionSpeciesForm) {
873894
if (fusionSpeciesForm.type2 !== null && fusionSpeciesForm.type2 !== speciesForm.type1) {
874895
types.push(fusionSpeciesForm.type2);
875896
} else if (fusionSpeciesForm.type1 !== speciesForm.type1) {
876897
types.push(fusionSpeciesForm.type1);
877898
}
878899
}
879-
880900
if (types.length === 1 && speciesForm.type2 !== null) {
881901
types.push(speciesForm.type2);
882902
}
@@ -900,7 +920,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
900920
types.splice(index, 1);
901921
}
902922
}
903-
904923
return types;
905924
}
906925

@@ -1087,10 +1106,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
10871106
return this.getAttackMoveEffectiveness(source, move);
10881107
}
10891108

1090-
getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove): TypeDamageMultiplier {
1109+
getAttackMoveEffectiveness(source: Pokemon, pokemonMove: PokemonMove, illusion: boolean = false): TypeDamageMultiplier {
10911110
const move = pokemonMove.getMove();
10921111
const typeless = move.hasAttr(TypelessAttr);
1093-
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.type, source));
1112+
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.type, source, undefined, illusion));
10941113
const cancelled = new Utils.BooleanHolder(false);
10951114
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
10961115
if (!typeless) {
@@ -1102,11 +1121,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
11021121
return (!cancelled.value ? typeMultiplier.value : 0) as TypeDamageMultiplier;
11031122
}
11041123

1105-
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false): TypeDamageMultiplier {
1124+
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, illusion: boolean = false): TypeDamageMultiplier {
11061125
if (moveType === Type.STELLAR) {
11071126
return this.isTerastallized() ? 2 : 1;
11081127
}
1109-
const types = this.getTypes(true, true);
1128+
const types = this.getTypes(true, true, undefined, illusion);
11101129

11111130
let multiplier = types.map(defType => {
11121131
if (source) {
@@ -3434,7 +3453,7 @@ export class EnemyPokemon extends Pokemon {
34343453
if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) {
34353454
targetScore = -20;
34363455
} else if (move instanceof AttackMove) {
3437-
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove);
3456+
const effectiveness = target.getAttackMoveEffectiveness(this, pokemonMove, true);
34383457
if (target.isPlayer() !== this.isPlayer()) {
34393458
targetScore *= effectiveness;
34403459
if (this.isOfType(move.type)) {

0 commit comments

Comments
 (0)