Compare commits

..

No commits in common. "8a0b5c52d3e7047d165c4952798afbbefc2f4fad" and "5de0185c0a05be610f1a47a471b292343f0de352" have entirely different histories.

71 changed files with 7424 additions and 8800 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

View File

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 396 B

View File

Before

Width:  |  Height:  |  Size: 411 B

After

Width:  |  Height:  |  Size: 411 B

View File

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 378 B

View File

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 397 B

View File

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

View File

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 391 B

View File

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 390 B

View File

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 381 B

View File

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

View File

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 385 B

View File

Before

Width:  |  Height:  |  Size: 383 B

After

Width:  |  Height:  |  Size: 383 B

View File

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

View File

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 385 B

View File

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 390 B

View File

Before

Width:  |  Height:  |  Size: 383 B

After

Width:  |  Height:  |  Size: 383 B

View File

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 387 B

View File

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

View File

@ -4043,7 +4043,8 @@ export function initAbilities() {
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(UnsuppressableAbilityAbAttr)
.attr(NoFusionAbilityAbAttr),
.attr(NoFusionAbilityAbAttr)
.unimplemented(),
new Ability(Abilities.FLOWER_GIFT, 4)
.conditionalAttr(getWeatherCondition(WeatherType.SUNNY || WeatherType.HARSH_SUN), BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5)
.conditionalAttr(getWeatherCondition(WeatherType.SUNNY || WeatherType.HARSH_SUN), BattleStatMultiplierAbAttr, BattleStat.SPDEF, 1.5)
@ -4395,7 +4396,8 @@ export function initAbilities() {
.attr(UncopiableAbilityAbAttr)
.attr(UnswappableAbilityAbAttr)
.attr(UnsuppressableAbilityAbAttr)
.attr(NoFusionAbilityAbAttr),
.attr(NoFusionAbilityAbAttr)
.unimplemented(),
new Ability(Abilities.ELECTRIC_SURGE, 7)
.attr(PostSummonTerrainChangeAbAttr, TerrainType.ELECTRIC)
.attr(PostBiomeChangeTerrainChangeAbAttr, TerrainType.ELECTRIC),

View File

@ -3328,19 +3328,6 @@ export class VariableMoveTypeAttr extends MoveAttr {
}
}
export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.ARCEUS) || [user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.SILVALLY)) {
const form = user.species.speciesId === Species.ARCEUS || user.species.speciesId === Species.SILVALLY ? user.formIndex : user.fusionSpecies.formIndex;
move.type = Type[Type[form]];
return true;
}
return false;
}
}
export class TechnoBlastTypeAttr extends VariableMoveTypeAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.GENESECT)) {
@ -6625,7 +6612,7 @@ export function initMoves() {
.attr(ConfuseAttr)
.soundBased(),
new AttackMove(Moves.JUDGMENT, Type.NORMAL, MoveCategory.SPECIAL, 100, 100, 10, -1, 0, 4)
.attr(FormChangeItemTypeAttr),
.partial(),
new AttackMove(Moves.BUG_BITE, Type.BUG, MoveCategory.PHYSICAL, 60, 100, 20, -1, 0, 4)
.attr(StealEatBerryAttr),
new AttackMove(Moves.CHARGE_BEAM, Type.ELECTRIC, MoveCategory.SPECIAL, 50, 90, 10, 70, 0, 4)
@ -7395,7 +7382,7 @@ export function initMoves() {
new AttackMove(Moves.NATURES_MADNESS, Type.FAIRY, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 7)
.attr(TargetHalfHpDamageAttr),
new AttackMove(Moves.MULTI_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 120, 100, 10, -1, 0, 7)
.attr(FormChangeItemTypeAttr),
.partial(),
/* Unused */
new AttackMove(Moves.TEN_MILLION_VOLT_THUNDERBOLT, Type.ELECTRIC, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7)
.partial()

View File

@ -86,45 +86,7 @@ export enum FormChangeItem {
SHOCK_DRIVE,
BURN_DRIVE,
CHILL_DRIVE,
DOUSE_DRIVE,
FIST_PLATE = 100,
SKY_PLATE,
TOXIC_PLATE,
EARTH_PLATE,
STONE_PLATE,
INSECT_PLATE,
SPOOKY_PLATE,
IRON_PLATE,
FLAME_PLATE,
SPLASH_PLATE,
MEADOW_PLATE,
ZAP_PLATE,
MIND_PLATE,
ICICLE_PLATE,
DRACO_PLATE,
DREAD_PLATE,
PIXIE_PLATE,
BLANK_PLATE, // TODO: Find a potential use for this
LEGEND_PLATE, // TODO: Find a potential use for this
FIGHTING_MEMORY,
FLYING_MEMORY,
POISON_MEMORY,
GROUND_MEMORY,
ROCK_MEMORY,
BUG_MEMORY,
GHOST_MEMORY,
STEEL_MEMORY,
FIRE_MEMORY,
WATER_MEMORY,
GRASS_MEMORY,
ELECTRIC_MEMORY,
PSYCHIC_MEMORY,
ICE_MEMORY,
DRAGON_MEMORY,
DARK_MEMORY,
FAIRY_MEMORY,
BLANK_MEMORY // TODO: Find a potential use for this
DOUSE_DRIVE
}
export type SpeciesFormChangeConditionPredicate = (p: Pokemon) => boolean;
@ -571,25 +533,6 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.SHAYMIN, "sky", "land", new SpeciesFormChangeTimeOfDayTrigger(TimeOfDay.DAWN, TimeOfDay.NIGHT)),
new SpeciesFormChange(Species.SHAYMIN, "sky", "land", new SpeciesFormChangeStatusEffectTrigger(StatusEffect.FREEZE))
],
[Species.ARCEUS]: [
new SpeciesFormChange(Species.ARCEUS, "normal", "fighting", new SpeciesFormChangeItemTrigger(FormChangeItem.FIST_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "flying", new SpeciesFormChangeItemTrigger(FormChangeItem.SKY_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "poison", new SpeciesFormChangeItemTrigger(FormChangeItem.TOXIC_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "ground", new SpeciesFormChangeItemTrigger(FormChangeItem.EARTH_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "rock", new SpeciesFormChangeItemTrigger(FormChangeItem.STONE_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "bug", new SpeciesFormChangeItemTrigger(FormChangeItem.INSECT_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "ghost", new SpeciesFormChangeItemTrigger(FormChangeItem.SPOOKY_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "steel", new SpeciesFormChangeItemTrigger(FormChangeItem.IRON_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "fire", new SpeciesFormChangeItemTrigger(FormChangeItem.FLAME_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "water", new SpeciesFormChangeItemTrigger(FormChangeItem.SPLASH_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "grass", new SpeciesFormChangeItemTrigger(FormChangeItem.MEADOW_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "electric", new SpeciesFormChangeItemTrigger(FormChangeItem.ZAP_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "psychic", new SpeciesFormChangeItemTrigger(FormChangeItem.MIND_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "ice", new SpeciesFormChangeItemTrigger(FormChangeItem.ICICLE_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "dragon", new SpeciesFormChangeItemTrigger(FormChangeItem.DRACO_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "dark", new SpeciesFormChangeItemTrigger(FormChangeItem.DREAD_PLATE)),
new SpeciesFormChange(Species.ARCEUS, "normal", "fairy", new SpeciesFormChangeItemTrigger(FormChangeItem.PIXIE_PLATE))
],
[Species.DARMANITAN]: [
new SpeciesFormChange(Species.DARMANITAN, "", "zen", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.DARMANITAN, "zen", "", new SpeciesFormChangeManualTrigger(), true)
@ -654,25 +597,6 @@ export const pokemonFormChanges: PokemonFormChanges = {
new SpeciesFormChange(Species.WISHIWASHI, "", "school", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.WISHIWASHI, "school", "", new SpeciesFormChangeManualTrigger(), true)
],
[Species.SILVALLY]: [
new SpeciesFormChange(Species.SILVALLY, "normal", "fighting", new SpeciesFormChangeItemTrigger(FormChangeItem.FIGHTING_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "flying", new SpeciesFormChangeItemTrigger(FormChangeItem.FLYING_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "poison", new SpeciesFormChangeItemTrigger(FormChangeItem.POISON_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "ground", new SpeciesFormChangeItemTrigger(FormChangeItem.GROUND_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "rock", new SpeciesFormChangeItemTrigger(FormChangeItem.ROCK_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "bug", new SpeciesFormChangeItemTrigger(FormChangeItem.BUG_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "ghost", new SpeciesFormChangeItemTrigger(FormChangeItem.GHOST_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "steel", new SpeciesFormChangeItemTrigger(FormChangeItem.STEEL_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "fire", new SpeciesFormChangeItemTrigger(FormChangeItem.FIRE_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "water", new SpeciesFormChangeItemTrigger(FormChangeItem.WATER_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "grass", new SpeciesFormChangeItemTrigger(FormChangeItem.GRASS_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "electric", new SpeciesFormChangeItemTrigger(FormChangeItem.ELECTRIC_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "psychic", new SpeciesFormChangeItemTrigger(FormChangeItem.PSYCHIC_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "ice", new SpeciesFormChangeItemTrigger(FormChangeItem.ICE_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "dragon", new SpeciesFormChangeItemTrigger(FormChangeItem.DRAGON_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "dark", new SpeciesFormChangeItemTrigger(FormChangeItem.DARK_MEMORY)),
new SpeciesFormChange(Species.SILVALLY, "normal", "fairy", new SpeciesFormChangeItemTrigger(FormChangeItem.FAIRY_MEMORY))
],
[Species.MINIOR]: [
new SpeciesFormChange(Species.MINIOR, "red-meteor", "red", new SpeciesFormChangeManualTrigger(), true),
new SpeciesFormChange(Species.MINIOR, "red", "red-meteor", new SpeciesFormChangeManualTrigger(), true),

View File

@ -1445,21 +1445,21 @@ export const trainerConfigs: TrainerConfigs = {
p.generateAndPopulateMoveset();
})),
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)
[TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL)
.setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL], TrainerSlot.TRAINER, true)),
[TrainerType.RIVAL_2]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL_2)
[TrainerType.RIVAL_2]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL_2)
.setModifierRewardFuncs(() => modifierTypes.EXP_SHARE)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT, Species.QUILLADIN, Species.BRAIXEN, Species.FROGADIER, Species.DARTRIX, Species.TORRACAT, Species.BRIONNE, Species.THWACKEY, Species.RABOOT, Species.DRIZZILE, Species.FLORAGATO, Species.CROCALOR, Species.QUAXWELL], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOTTO, Species.HOOTHOOT, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL, Species.FLETCHINDER, Species.TRUMBEAK, Species.CORVISQUIRE, Species.WATTREL], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)),
[TrainerType.RIVAL_3]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL_3)
[TrainerType.RIVAL_3]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL_3)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
.setSpeciesFilter(species => species.baseTotal >= 540),
[TrainerType.RIVAL_4]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_2").setMixedBattleBgm("battle_rival_2").setPartyTemplates(trainerPartyTemplates.RIVAL_4)
[TrainerType.RIVAL_4]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_2").setPartyTemplates(trainerPartyTemplates.RIVAL_4)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true))
.setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450))
@ -1468,7 +1468,7 @@ export const trainerConfigs: TrainerConfigs = {
const starter = party[0];
return [modifierTypes.TERA_SHARD().generateType(null, [starter.species.type1]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier];
}),
[TrainerType.RIVAL_5]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_3").setMixedBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_5)
[TrainerType.RIVAL_5]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_5)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true,
p => p.setBoss(true, 2)))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true))
@ -1484,7 +1484,7 @@ export const trainerConfigs: TrainerConfigs = {
const starter = party[0];
return [modifierTypes.TERA_SHARD().generateType(null, [starter.species.type1]).withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier];
}),
[TrainerType.RIVAL_6]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm("final").setBattleBgm("battle_rival_3").setMixedBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_6)
[TrainerType.RIVAL_6]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm("final").setBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_6)
.setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true,
p => {
p.setBoss(true, 3);

View File

@ -1070,10 +1070,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
/**
* Calculates the effectiveness of a move against the Pokémon.
*
* @param source - The Pokémon using the move.
* @param move - The move being used.
* @returns The type damage multiplier or undefined if it's a status move
*/
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier | undefined {
@ -1081,27 +1077,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return undefined;
}
return this.getAttackMoveEffectiveness(source, move, true);
return this.getAttackMoveEffectiveness(source, move);
}
/**
* Calculates the effectiveness of an attack move against the Pokémon.
*
* @param source - 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.
* @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): TypeDamageMultiplier {
const move = pokemonMove.getMove();
const typeless = move.hasAttr(TypelessAttr);
const typeMultiplier = new Utils.NumberHolder(this.getAttackTypeEffectiveness(move.type, source));
const cancelled = new Utils.BooleanHolder(false);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
if (!typeless && !ignoreAbility) {
if (!typeless) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true);
}
if (!cancelled.value && !ignoreAbility) {
if (!cancelled.value) {
applyPreDefendAbAttrs(MoveImmunityAbAttr, this, source, move, cancelled, typeMultiplier, true);
}
return (!cancelled.value ? typeMultiplier.value : 0) as TypeDamageMultiplier;

View File

@ -389,43 +389,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "Flammenmodul",
"CHILL_DRIVE": "Gefriermodul",
"DOUSE_DRIVE": "Aquamodul",
"FIST_PLATE": "Fausttafel",
"SKY_PLATE": "Wolkentafel",
"TOXIC_PLATE": "Gifttafel",
"EARTH_PLATE": "Erdtafel",
"STONE_PLATE": "Steintafel",
"INSECT_PLATE": "Käfertafel",
"SPOOKY_PLATE": "Spuktafel",
"IRON_PLATE": "Eisentafel",
"FLAME_PLATE": "Feuertafel",
"SPLASH_PLATE": "Wassertafel",
"MEADOW_PLATE": "Wiesentafel",
"ZAP_PLATE": "Blitztafel",
"MIND_PLATE": "Hirntafel",
"ICICLE_PLATE": "Frosttafel",
"DRACO_PLATE": "Dracotafel",
"DREAD_PLATE": "Furchttafel",
"PIXIE_PLATE": "Feentafel",
"BLANK_PLATE": "Neutraltafel",
"LEGEND_PLATE": "Legendentafel",
"FIGHTING_MEMORY": "Kampf-Disc",
"FLYING_MEMORY": "Flug-Disc",
"POISON_MEMORY": "Gift-Disc",
"GROUND_MEMORY": "Boden-Disc",
"ROCK_MEMORY": "Gesteins-Disc",
"BUG_MEMORY": "Käfer-Disc",
"GHOST_MEMORY": "Geister-Disc",
"STEEL_MEMORY": "Stahl-Disc",
"FIRE_MEMORY": "Feuer-Disc",
"WATER_MEMORY": "Wasser-Disc",
"GRASS_MEMORY": "Pflanzen-Disc",
"ELECTRIC_MEMORY": "Elektro-Disc",
"PSYCHIC_MEMORY": "Psycho-Disc",
"ICE_MEMORY": "Eis-Disc",
"DRAGON_MEMORY": "Drachen-Disc",
"DARK_MEMORY": "Unlicht-Disc",
"FAIRY_MEMORY": "Feen-Disc",
"BLANK_MEMORY": "Leere-Disc",
},
} as const;

View File

@ -388,43 +388,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "Burn Drive",
"CHILL_DRIVE": "Chill Drive",
"DOUSE_DRIVE": "Douse Drive",
"FIST_PLATE": "Fist Plate",
"SKY_PLATE": "Sky Plate",
"TOXIC_PLATE": "Toxic Plate",
"EARTH_PLATE": "Earth Plate",
"STONE_PLATE": "Stone Plate",
"INSECT_PLATE": "Insect Plate",
"SPOOKY_PLATE": "Spooky Plate",
"IRON_PLATE": "Iron Plate",
"FLAME_PLATE": "Flame Plate",
"SPLASH_PLATE": "Splash Plate",
"MEADOW_PLATE": "Meadow Plate",
"ZAP_PLATE": "Zap Plate",
"MIND_PLATE": "Mind Plate",
"ICICLE_PLATE": "Icicle Plate",
"DRACO_PLATE": "Draco Plate",
"DREAD_PLATE": "Dread Plate",
"PIXIE_PLATE": "Pixie Plate",
"BLANK_PLATE": "Blank Plate",
"LEGEND_PLATE": "Legend Plate",
"FIGHTING_MEMORY": "Fighting Memory",
"FLYING_MEMORY": "Flying Memory",
"POISON_MEMORY": "Poison Memory",
"GROUND_MEMORY": "Ground Memory",
"ROCK_MEMORY": "Rock Memory",
"BUG_MEMORY": "Bug Memory",
"GHOST_MEMORY": "Ghost Memory",
"STEEL_MEMORY": "Steel Memory",
"FIRE_MEMORY": "Fire Memory",
"WATER_MEMORY": "Water Memory",
"GRASS_MEMORY": "Grass Memory",
"ELECTRIC_MEMORY": "Electric Memory",
"PSYCHIC_MEMORY": "Psychic Memory",
"ICE_MEMORY": "Ice Memory",
"DRAGON_MEMORY": "Dragon Memory",
"DARK_MEMORY": "Dark Memory",
"FAIRY_MEMORY": "Fairy Memory",
"BLANK_MEMORY": "Blank Memory",
},
} as const;

View File

@ -388,43 +388,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "PiroROM",
"CHILL_DRIVE": "CrioROM",
"DOUSE_DRIVE": "HidroROM",
"FIST_PLATE": "Tabla Fuerte",
"SKY_PLATE": "Tabla Cielo",
"TOXIC_PLATE": "Tabla Tóxica",
"EARTH_PLATE": "Tabla Terrax",
"STONE_PLATE": "Tabla Pétrea",
"INSECT_PLATE": "Tabla Bicho",
"SPOOKY_PLATE": "Tabla Terror",
"IRON_PLATE": "Tabla Acero",
"FLAME_PLATE": "Tabla Llama",
"SPLASH_PLATE": "Tabla Linfa",
"MEADOW_PLATE": "Tabla Pradal",
"ZAP_PLATE": "Tabla Trueno",
"MIND_PLATE": "Tabla Mental",
"ICICLE_PLATE": "Tabla Helada",
"DRACO_PLATE": "Tabla Draco",
"DREAD_PLATE": "Tabla Oscura",
"PIXIE_PLATE": "Tabla Duende",
"BLANK_PLATE": "Tabla Neutra",
"LEGEND_PLATE": "Tabla Legendaria",
"FIGHTING_MEMORY": "Disco Lucha",
"FLYING_MEMORY": "Disco Volador",
"POISON_MEMORY": "Disco Veneno",
"GROUND_MEMORY": "Disco Tierra",
"ROCK_MEMORY": "Disco Roca",
"BUG_MEMORY": "Disco Bicho",
"GHOST_MEMORY": "Disco Fantasma",
"STEEL_MEMORY": "Disco Acero",
"FIRE_MEMORY": "Disco Fuego",
"WATER_MEMORY": "Disco Agua",
"GRASS_MEMORY": "Disco Planta",
"ELECTRIC_MEMORY": "Disco Eléctrico",
"PSYCHIC_MEMORY": "Disco Psíquico",
"ICE_MEMORY": "Disco Hielo",
"DRAGON_MEMORY": "Disco Dragón",
"DARK_MEMORY": "Disco Siniestro",
"FAIRY_MEMORY": "Disco Hada",
"BLANK_MEMORY": "Disco Blanco",
},
} as const;

View File

@ -388,43 +388,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "Module Pyro",
"CHILL_DRIVE": "Module Cryo",
"DOUSE_DRIVE": "Module Aqua",
"FIST_PLATE": "Plaque Poing",
"SKY_PLATE": "Plaque Ciel",
"TOXIC_PLATE": "Plaque Toxicité",
"EARTH_PLATE": "Plaque Terre",
"STONE_PLATE": "Plaque Roc",
"INSECT_PLATE": "Plaque Insecte",
"SPOOKY_PLATE": "Plaque Fantôme",
"IRON_PLATE": "Plaque Fer",
"FLAME_PLATE": "Plaque Flamme",
"SPLASH_PLATE": "Plaque Hydro",
"MEADOW_PLATE": "Plaque Herbe",
"ZAP_PLATE": "Plaque Volt",
"MIND_PLATE": "Plaque Esprit",
"ICICLE_PLATE": "Plaque Glace",
"DRACO_PLATE": "Plaque Draco",
"DREAD_PLATE": "Plaque Ombre",
"PIXIE_PLATE": "Plaque Pixie",
"BLANK_PLATE": "Plaque Renouveau",
"LEGEND_PLATE": "Plaque Légende",
"FIGHTING_MEMORY": "ROM Combat",
"FLYING_MEMORY": "ROM Vol",
"POISON_MEMORY": "ROM Poison",
"GROUND_MEMORY": "ROM Sol",
"ROCK_MEMORY": "ROM Roche",
"BUG_MEMORY": "ROM Insecte",
"GHOST_MEMORY": "ROM Spectre",
"STEEL_MEMORY": "ROM Acier",
"FIRE_MEMORY": "ROM Feu",
"WATER_MEMORY": "ROM Eau",
"GRASS_MEMORY": "ROM Plante",
"ELECTRIC_MEMORY": "ROM Électrik",
"PSYCHIC_MEMORY": "ROM Psy",
"ICE_MEMORY": "ROM Glace",
"DRAGON_MEMORY": "ROM Dragon",
"DARK_MEMORY": "ROM Ténèbres",
"FAIRY_MEMORY": "ROM Fée",
"BLANK_MEMORY": "ROM Vierge",
},
} as const;

View File

@ -388,43 +388,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "Piromodulo",
"CHILL_DRIVE": "Gelomodulo",
"DOUSE_DRIVE": "Idromodulo",
"FIST_PLATE": "Lastrapugno",
"SKY_PLATE": "Lastracielo",
"TOXIC_PLATE": "Lastrafiele",
"EARTH_PLATE": "Lastrageo",
"STONE_PLATE": "Lastrapietra",
"INSECT_PLATE": "Lastrabaco",
"SPOOKY_PLATE": "Lastratetra",
"IRON_PLATE": "Lastraferro",
"FLAME_PLATE": "Lastrarogo",
"SPLASH_PLATE": "Lastraidro",
"MEADOW_PLATE": "Lastraprato",
"ZAP_PLATE": "Lastrasaetta",
"MIND_PLATE": "Lastramente",
"ICICLE_PLATE": "Lastragelo",
"DRACO_PLATE": "Lastradrakon",
"DREAD_PLATE": "Lastratimore",
"PIXIE_PLATE": "Lastraspiritello",
"BLANK_PLATE": "Lastraripristino",
"LEGEND_PLATE": "Lastraleggenda",
"FIGHTING_MEMORY": "ROM Lotta",
"FLYING_MEMORY": "ROM Volante",
"POISON_MEMORY": "ROM Veleno",
"GROUND_MEMORY": "ROM Terra",
"ROCK_MEMORY": "ROM Roccia",
"BUG_MEMORY": "ROM Coleottero",
"GHOST_MEMORY": "ROM Spettro",
"STEEL_MEMORY": "ROM Acciaio",
"FIRE_MEMORY": "ROM Fuoco",
"WATER_MEMORY": "ROM Acqua",
"GRASS_MEMORY": "ROM Erba",
"ELECTRIC_MEMORY": "ROM Elettro",
"PSYCHIC_MEMORY": "ROM Psico",
"ICE_MEMORY": "ROM Ghiaccio",
"DRAGON_MEMORY": "ROM Drago",
"DARK_MEMORY": "ROM Buio",
"FAIRY_MEMORY": "ROM Folletto",
"BLANK_MEMORY": "ROM Vuota",
},
} as const;

View File

@ -425,6 +425,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"DRAGON_MEMORY": "드래곤메모리",
"DARK_MEMORY": "다크메모리",
"FAIRY_MEMORY": "페어리메모리",
"BLANK_MEMORY": "빈메모리",
},
} as const;

View File

@ -388,43 +388,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "IgneDisco",
"CHILL_DRIVE": "CrioDisco",
"DOUSE_DRIVE": "HidroDisco",
"FIST_PLATE": "Placa de Punho",
"SKY_PLATE": "Placa do Céu",
"TOXIC_PLATE": "Placa Tóxica",
"EARTH_PLATE": "Placa Terrestre",
"STONE_PLATE": "Placa de Pedra",
"INSECT_PLATE": "Placa de Insetos",
"SPOOKY_PLATE": "Placa Assustadora",
"IRON_PLATE": "Placa de Ferro",
"FLAME_PLATE": "Placa da Chama",
"SPLASH_PLATE": "Placa de Respingo",
"MEADOW_PLATE": "Placa de Prado",
"ZAP_PLATE": "Placa Elétrica",
"MIND_PLATE": "Placa Mental",
"ICICLE_PLATE": "Placa de Gelo",
"DRACO_PLATE": "Placa de Draco",
"DREAD_PLATE": "Placa do Pavor",
"PIXIE_PLATE": "Placa Duende",
"BLANK_PLATE": "Placa em Branco",
"LEGEND_PLATE": "Placa de Legenda",
"FIGHTING_MEMORY": "Memória de Lutador",
"FLYING_MEMORY": "Memória Voadora",
"POISON_MEMORY": "Memória Venenosa",
"GROUND_MEMORY": "Memória Terrestre",
"ROCK_MEMORY": "Memória da Rocha",
"BUG_MEMORY": "Memória de Insetos",
"GHOST_MEMORY": "Memória Fantasma",
"STEEL_MEMORY": "Memória de Aço",
"FIRE_MEMORY": "Memória de Fogo",
"WATER_MEMORY": "Memória da Água",
"GRASS_MEMORY": "Memória de Planta",
"ELECTRIC_MEMORY": "Memória Elétrica",
"PSYCHIC_MEMORY": "Memória Psíquica",
"ICE_MEMORY": "Memória de Gelo",
"DRAGON_MEMORY": "Memória do Dragão",
"DARK_MEMORY": "Memória Negra",
"FAIRY_MEMORY": "Memória de Fada",
"BLANK_MEMORY": "Memória Vazia",
},
} as const;

View File

@ -388,43 +388,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
"BURN_DRIVE": "火焰卡带",
"CHILL_DRIVE": "冰冻卡带",
"DOUSE_DRIVE": "水流卡带",
"FIST_PLATE": "拳頭石板",
"SKY_PLATE": "藍天石板",
"TOXIC_PLATE": "劇毒石板",
"EARTH_PLATE": "大地石板",
"STONE_PLATE": "岩石石板",
"INSECT_PLATE": "玉蟲石板",
"SPOOKY_PLATE": "妖怪石板",
"IRON_PLATE": "鋼鐵石板",
"FLAME_PLATE": "火球石板",
"SPLASH_PLATE": "水滴石板",
"MEADOW_PLATE": "碧綠石板",
"ZAP_PLATE": "雷電石板",
"MIND_PLATE": "神奇石板",
"ICICLE_PLATE": "冰柱石板",
"DRACO_PLATE": "龍之石板",
"DREAD_PLATE": "惡顏石板",
"PIXIE_PLATE": "妖精石板",
"BLANK_PLATE": "淨空石板",
"LEGEND_PLATE": "傳說石板",
"FIGHTING_MEMORY": "戰鬥記憶碟",
"FLYING_MEMORY": "飛翔記憶碟",
"POISON_MEMORY": "毒記憶碟",
"GROUND_MEMORY": "大地記憶碟",
"ROCK_MEMORY": "岩石記憶碟",
"BUG_MEMORY": "蟲子記憶碟",
"GHOST_MEMORY": "幽靈記憶碟",
"STEEL_MEMORY": "鋼鐵記憶碟",
"FIRE_MEMORY": "火焰記憶碟",
"WATER_MEMORY": "清水記憶碟",
"GRASS_MEMORY": "青草記憶碟",
"ELECTRIC_MEMORY": "電子記憶碟",
"PSYCHIC_MEMORY": "精神記憶碟",
"ICE_MEMORY": "冰雪記憶碟",
"DRAGON_MEMORY": "龍記憶碟",
"DARK_MEMORY": "黑暗記憶碟",
"FAIRY_MEMORY": "妖精記憶碟",
"BLANK_MEMORY": "空白記憶碟",
},
} as const;

View File

@ -442,43 +442,5 @@ export const modifierType: ModifierTypeTranslationEntries = {
BURN_DRIVE: "火焰卡帶",
CHILL_DRIVE: "冰凍卡帶",
DOUSE_DRIVE: "水流卡帶",
"FIST_PLATE": "拳頭石板",
"SKY_PLATE": "藍天石板",
"TOXIC_PLATE": "劇毒石板",
"EARTH_PLATE": "大地石板",
"STONE_PLATE": "岩石石板",
"INSECT_PLATE": "玉蟲石板",
"SPOOKY_PLATE": "妖怪石板",
"IRON_PLATE": "鋼鐵石板",
"FLAME_PLATE": "火球石板",
"SPLASH_PLATE": "水滴石板",
"MEADOW_PLATE": "碧綠石板",
"ZAP_PLATE": "雷電石板",
"MIND_PLATE": "神奇石板",
"ICICLE_PLATE": "冰柱石板",
"DRACO_PLATE": "龍之石板",
"DREAD_PLATE": "惡顏石板",
"PIXIE_PLATE": "妖精石板",
"BLANK_PLATE": "淨空石板",
"LEGEND_PLATE": "傳說石板",
"FIGHTING_MEMORY": "戰鬥記憶碟",
"FLYING_MEMORY": "飛翔記憶碟",
"POISON_MEMORY": "毒記憶碟",
"GROUND_MEMORY": "大地記憶碟",
"ROCK_MEMORY": "岩石記憶碟",
"BUG_MEMORY": "蟲子記憶碟",
"GHOST_MEMORY": "幽靈記憶碟",
"STEEL_MEMORY": "鋼鐵記憶碟",
"FIRE_MEMORY": "火焰記憶碟",
"WATER_MEMORY": "清水記憶碟",
"GRASS_MEMORY": "青草記憶碟",
"ELECTRIC_MEMORY": "電子記憶碟",
"PSYCHIC_MEMORY": "精神記憶碟",
"ICE_MEMORY": "冰雪記憶碟",
"DRAGON_MEMORY": "龍記憶碟",
"DARK_MEMORY": "黑暗記憶碟",
"FAIRY_MEMORY": "妖精記憶碟",
"BLANK_MEMORY": "空白記憶碟",
},
} as const;

View File

@ -1079,10 +1079,6 @@ export class NextEncounterPhase extends EncounterPhase {
super(scene);
}
start() {
super.start();
}
doEncounter(): void {
this.scene.playBgm(undefined, true);
@ -1162,9 +1158,6 @@ export class PostSummonPhase extends PokemonPhase {
const pokemon = this.getPokemon();
if (pokemon.status?.effect === StatusEffect.TOXIC) {
pokemon.status.turnCount = 0;
}
this.scene.arena.applyTags(ArenaTrapTag, pokemon);
applyPostSummonAbAttrs(PostSummonAbAttr, pokemon).then(() => this.end());
}
@ -1504,10 +1497,6 @@ export class SwitchSummonPhase extends SummonPhase {
this.batonPass = batonPass;
}
start(): void {
super.start();
}
preSummon(): void {
if (!this.player) {
if (this.slotIndex === -1) {

View File

@ -1,142 +0,0 @@
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
import Phaser from "phaser";
import GameManager from "#app/test/utils/gameManager";
import * as overrides from "#app/overrides";
import {Abilities} from "#app/data/enums/abilities";
import {Species} from "#app/data/enums/species";
import {
CommandPhase,
DamagePhase,
EnemyCommandPhase,
MessagePhase,
PostSummonPhase,
SwitchPhase,
SwitchSummonPhase,
TurnEndPhase, TurnInitPhase,
TurnStartPhase,
} from "#app/phases";
import {Mode} from "#app/ui/ui";
import {Stat} from "#app/data/pokemon-stat";
import {Moves} from "#app/data/enums/moves";
import {getMovePosition} from "#app/test/utils/gameManagerUtils";
import {Command} from "#app/ui/command-ui-handler";
import {QuietFormChangePhase} from "#app/form-change-phase";
describe("Abilities - Zen mode", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
const moveToUse = Moves.SPLASH;
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
});
it("ZEN MODE - not enough damage to change form", async() => {
const moveToUse = Moves.SPLASH;
await game.startBattle([
Species.DARMANITAN,
]);
game.scene.getParty()[0].stats[Stat.SPD] = 1;
game.scene.getParty()[0].stats[Stat.HP] = 100;
game.scene.getParty()[0].hp = 100;
expect(game.scene.getParty()[0].formIndex).toBe(0);
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
});
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
const movePosition = getMovePosition(game.scene, 0, moveToUse);
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(DamagePhase, false);
// await game.phaseInterceptor.runFrom(DamagePhase).to(DamagePhase, false);
const damagePhase = game.scene.getCurrentPhase() as DamagePhase;
damagePhase.updateAmount(40);
await game.phaseInterceptor.runFrom(DamagePhase).to(TurnEndPhase, false);
expect(game.scene.getParty()[0].hp).toBeLessThan(100);
expect(game.scene.getParty()[0].formIndex).toBe(0);
}, 20000);
it("ZEN MODE - enough damage to change form", async() => {
const moveToUse = Moves.SPLASH;
await game.startBattle([
Species.DARMANITAN,
]);
game.scene.getParty()[0].stats[Stat.SPD] = 1;
game.scene.getParty()[0].stats[Stat.HP] = 1000;
game.scene.getParty()[0].hp = 100;
expect(game.scene.getParty()[0].formIndex).toBe(0);
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
});
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
const movePosition = getMovePosition(game.scene, 0, moveToUse);
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(QuietFormChangePhase);
await game.phaseInterceptor.to(TurnInitPhase, false);
expect(game.scene.getParty()[0].hp).not.toBe(100);
expect(game.scene.getParty()[0].formIndex).not.toBe(0);
}, 20000);
it("ZEN MODE - kill pokemon while on zen mode", async() => {
const moveToUse = Moves.SPLASH;
await game.startBattle([
Species.DARMANITAN,
Species.CHARIZARD,
]);
game.scene.getParty()[0].stats[Stat.SPD] = 1;
game.scene.getParty()[0].stats[Stat.HP] = 1000;
game.scene.getParty()[0].hp = 100;
expect(game.scene.getParty()[0].formIndex).toBe(0);
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
});
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
const movePosition = getMovePosition(game.scene, 0, moveToUse);
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(DamagePhase, false);
// await game.phaseInterceptor.runFrom(DamagePhase).to(DamagePhase, false);
const damagePhase = game.scene.getCurrentPhase() as DamagePhase;
damagePhase.updateAmount(80);
await game.phaseInterceptor.runFrom(DamagePhase).to(QuietFormChangePhase);
expect(game.scene.getParty()[0].hp).not.toBe(100);
expect(game.scene.getParty()[0].formIndex).not.toBe(0);
await game.killPokemon(game.scene.getParty()[0]);
expect(game.scene.getParty()[0].isFainted()).toBe(true);
await game.phaseInterceptor.run(MessagePhase);
await game.phaseInterceptor.run(EnemyCommandPhase);
await game.phaseInterceptor.run(TurnStartPhase);
game.onNextPrompt("SwitchPhase", Mode.PARTY, () => {
game.scene.unshiftPhase(new SwitchSummonPhase(game.scene, 0, 1, false, false));
game.scene.ui.setMode(Mode.MESSAGE);
});
game.onNextPrompt("SwitchPhase", Mode.MESSAGE, () => {
game.endPhase();
});
await game.phaseInterceptor.run(SwitchPhase);
await game.phaseInterceptor.to(PostSummonPhase);
expect(game.scene.getParty()[1].formIndex).toBe(1);
}, 20000);
});

View File

@ -6,7 +6,7 @@ import {Species} from "#app/data/enums/species";
import * as overrides from "../../overrides";
import {Command} from "#app/ui/command-ui-handler";
import {
CommandPhase, DamagePhase,
CommandPhase,
EncounterPhase,
EnemyCommandPhase,
LoginPhase,
@ -15,7 +15,7 @@ import {
SelectStarterPhase,
SummonPhase,
TitlePhase,
TurnInitPhase, VictoryPhase,
TurnInitPhase,
} from "#app/phases";
import {Moves} from "#app/data/enums/moves";
import GameManager from "#app/test/utils/gameManager";
@ -106,7 +106,9 @@ describe("Test Battle Phase", () => {
const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE);
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase, false);
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase);
expect(game.scene.ui?.getMode()).toBe(Mode.MODIFIER_SELECT);
expect(game.scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
}, 20000);
it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async() => {
@ -126,7 +128,7 @@ describe("Test Battle Phase", () => {
const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE);
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false);
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase);
}, 20000);
it("load 100% data file", async() => {
@ -257,71 +259,5 @@ describe("Test Battle Phase", () => {
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("kill opponent pokemon", async() => {
const moveToUse = Moves.SPLASH;
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
await game.startBattle([
Species.DARMANITAN,
Species.CHARIZARD,
]);
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
});
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
const movePosition = getMovePosition(game.scene, 0, moveToUse);
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
await game.phaseInterceptor.to(DamagePhase, false);
await game.killPokemon(game.scene.currentBattle.enemyParty[0]);
expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true);
await game.phaseInterceptor.to(VictoryPhase, false);
}, 200000);
it("to next turn", async() => {
const moveToUse = Moves.SPLASH;
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
await game.startBattle();
const turn = game.scene.currentBattle.turn;
game.doAttack(0);
await game.toNextTurn();
expect(game.scene.currentBattle.turn).toBeGreaterThan(turn);
}, 20000);
it("to next wave with pokemon killed, single", async() => {
const moveToUse = Moves.SPLASH;
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
await game.startBattle();
const waveIndex = game.scene.currentBattle.waveIndex;
game.doAttack(0);
await game.doKillOpponents();
await game.toNextWave();
expect(game.scene.currentBattle.waveIndex).toBeGreaterThan(waveIndex);
}, 20000);
});

View File

@ -1,4 +1,4 @@
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
import {afterEach, beforeAll, beforeEach, describe, it, vi} from "vitest";
import GameManager from "#app/test/utils/gameManager";
import Phaser from "phaser";
import * as overrides from "#app/overrides";
@ -22,24 +22,18 @@ describe("Test Battle Phase", () => {
beforeEach(() => {
game = new GameManager(phaserGame);
const moveToUse = Moves.SPLASH;
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
});
it.skip("to next turn", async() => {
it("should start phase", async() => {
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
await game.startBattle();
const turn = game.scene.currentBattle.turn;
game.doAttack(0);
await game.toNextTurn();
expect(game.scene.currentBattle.turn).toBeGreaterThan(turn);
}, 20000);
}, 100000);
});

View File

@ -1,137 +0,0 @@
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
import {Mode} from "#app/ui/ui";
import {Species} from "#app/data/enums/species";
import * as overrides from "../../overrides";
import {
CommandPhase,
} from "#app/phases";
import {Moves} from "#app/data/enums/moves";
import GameManager from "#app/test/utils/gameManager";
import Phaser from "phaser";
import {Abilities} from "#app/data/enums/abilities";
describe("Test Battle Phase", () => {
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, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]);
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
});
it("startBattle 2vs1 boss", async() => {
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 2vs2 boss", async() => {
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 2vs2 trainer", async() => {
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 2vs1 trainer", async() => {
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 2vs1 rival", async() => {
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 2vs2 rival", async() => {
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 1vs1 trainer", async() => {
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
await game.startBattle([
Species.BLASTOISE,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 2vs2 trainer", async() => {
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
it("startBattle 4vs2 trainer", async() => {
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
await game.startBattle([
Species.BLASTOISE,
Species.CHARIZARD,
Species.DARKRAI,
Species.GABITE,
]);
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
}, 20000);
});

View File

@ -11,6 +11,6 @@ export default class TextInterceptor {
}
getLatestMessage(): string {
return this.logs.pop();
return this.logs[this.logs.length - 1];
}
}

View File

@ -4,18 +4,18 @@ import {generateStarter, waitUntil} from "#app/test/utils/gameManagerUtils";
import {
CommandPhase,
EncounterPhase,
FaintPhase,
LoginPhase, NewBattlePhase,
LoginPhase,
PostSummonPhase,
SelectGenderPhase,
SelectStarterPhase,
TitlePhase, TurnInitPhase,
TitlePhase,
} from "#app/phases";
import BattleScene from "#app/battle-scene.js";
import PhaseInterceptor from "#app/test/utils/phaseInterceptor";
import TextInterceptor from "#app/test/utils/TextInterceptor";
import {GameModes, getGameMode} from "#app/game-mode";
import fs from "fs";
import {AES, enc} from "crypto-js";
import { AES, enc } from "crypto-js";
import {updateUserInfo} from "#app/account";
import {Species} from "#app/data/enums/species";
import {PlayerGender} from "#app/data/enums/player-gender";
@ -23,11 +23,6 @@ import {GameDataType} from "#app/data/enums/game-data-type";
import InputsHandler from "#app/test/utils/inputsHandler";
import {ExpNotification} from "#app/enums/exp-notification";
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
import {EnemyPokemon, PlayerPokemon} from "#app/field/pokemon";
import {MockClock} from "#app/test/utils/mocks/mockClock";
import {Command} from "#app/ui/command-ui-handler";
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
import {Button} from "#app/enums/buttons";
/**
* Class to manage the game state and transitions between phases.
@ -89,31 +84,31 @@ export default class GameManager {
* @param callback - The callback to execute.
* @param expireFn - Optional function to determine if the prompt has expired.
*/
onNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn?: () => void, awaitingActionInput: boolean = false) {
this.phaseInterceptor.addToNextPrompt(phaseTarget, mode, callback, expireFn, awaitingActionInput);
onNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn?: () => void) {
this.phaseInterceptor.addToNextPrompt(phaseTarget, mode, callback, expireFn);
}
/**
* Runs the game to the title phase.
* @returns A promise that resolves when the title phase is reached.
*/
async runToTitle(): Promise<void> {
await this.phaseInterceptor.run(LoginPhase);
this.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => {
this.scene.gameData.gender = PlayerGender.MALE;
this.endPhase();
}, () => this.isCurrentPhase(TitlePhase));
await this.phaseInterceptor.run(SelectGenderPhase, () => this.isCurrentPhase(TitlePhase));
await this.phaseInterceptor.run(TitlePhase);
this.scene.gameSpeed = 5;
this.scene.moveAnimations = false;
this.scene.showLevelUpStats = false;
this.scene.expGainsSpeed = 3;
this.scene.expParty = ExpNotification.SKIP;
this.scene.hpBarSpeed = 3;
runToTitle(): Promise<void> {
return new Promise(async(resolve, reject) => {
await this.phaseInterceptor.run(LoginPhase).catch((e) => reject(e));
this.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => {
this.scene.gameData.gender = PlayerGender.MALE;
this.endPhase();
}, () => this.isCurrentPhase(TitlePhase));
await this.phaseInterceptor.run(SelectGenderPhase, () => this.isCurrentPhase(TitlePhase)).catch((e) => reject(e));
await this.phaseInterceptor.run(TitlePhase).catch((e) => reject(e));
this.scene.gameSpeed = 5;
this.scene.moveAnimations = false;
this.scene.showLevelUpStats = false;
this.scene.expGainsSpeed = 3;
this.scene.expParty = ExpNotification.SKIP;
this.scene.hpBarSpeed = 3;
resolve();
});
}
/**
@ -121,91 +116,41 @@ export default class GameManager {
* @param species - Optional array of species to summon.
* @returns A promise that resolves when the summon phase is reached.
*/
async runToSummon(species?: Species[]) {
await this.runToTitle();
this.onNextPrompt("TitlePhase", Mode.TITLE, () => {
this.scene.gameMode = getGameMode(GameModes.CLASSIC);
const starters = generateStarter(this.scene, species);
const selectStarterPhase = new SelectStarterPhase(this.scene);
this.scene.pushPhase(new EncounterPhase(this.scene, false));
selectStarterPhase.initBattle(starters);
runToSummon(species?: Species[]): Promise<void> {
return new Promise(async(resolve, reject) => {
await this.runToTitle().catch((e) => reject(e));
this.onNextPrompt("TitlePhase", Mode.TITLE, () => {
this.scene.gameMode = getGameMode(GameModes.CLASSIC);
const starters = generateStarter(this.scene, species);
const selectStarterPhase = new SelectStarterPhase(this.scene);
this.scene.pushPhase(new EncounterPhase(this.scene, false));
selectStarterPhase.initBattle(starters);
});
await this.phaseInterceptor.run(EncounterPhase).catch((e) => reject(e));
resolve();
});
await this.phaseInterceptor.run(EncounterPhase);
}
/**
* Transitions to the start of a battle.
* Starts a battle.
* @param species - Optional array of species to start the battle with.
* @returns A promise that resolves when the battle is started.
*/
async startBattle(species?: Species[]) {
await this.runToSummon(species);
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
this.setMode(Mode.MESSAGE);
this.endPhase();
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnInitPhase));
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
this.setMode(Mode.MESSAGE);
this.endPhase();
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnInitPhase));
await this.phaseInterceptor.to(CommandPhase);
console.log("==================[New Turn]==================");
}
/**
* Emulate a player attack
* @param movePosition the index of the move in the pokemon's moveset array
*/
doAttack(movePosition: integer) {
this.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
this.scene.ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
startBattle(species?: Species[]): Promise<void> {
return new Promise(async(resolve, reject) => {
await this.runToSummon(species).catch((e) => reject(e));
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
this.setMode(Mode.MESSAGE);
this.endPhase();
}, () => this.isCurrentPhase(CommandPhase));
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
this.setMode(Mode.MESSAGE);
this.endPhase();
}, () => this.isCurrentPhase(CommandPhase));
await this.phaseInterceptor.runFrom(PostSummonPhase).to(CommandPhase).catch((e) => reject(e));
console.log("==================[New Turn]==================");
return resolve();
});
this.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
});
}
/** Faint all opponents currently on the field */
async doKillOpponents() {
await this.killPokemon(this.scene.currentBattle.enemyParty[0]);
if (this.scene.currentBattle.double) {
await this.killPokemon(this.scene.currentBattle.enemyParty[1]);
}
}
/** Emulate selecting a modifier (item) */
doSelectModifier() {
this.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => {
const handler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
handler.processInput(Button.CANCEL);
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(NewBattlePhase), true);
this.onNextPrompt("SelectModifierPhase", Mode.CONFIRM, () => {
const handler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
handler.processInput(Button.ACTION);
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(NewBattlePhase));
}
/** Transition to the next upcoming {@linkcode CommandPhase} */
async toNextTurn() {
await this.phaseInterceptor.to(CommandPhase);
}
/** Emulate selecting a modifier (item) and transition to the next upcoming {@linkcode CommandPhase} */
async toNextWave() {
this.doSelectModifier();
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
this.setMode(Mode.MESSAGE);
this.endPhase();
}, () => this.isCurrentPhase(TurnInitPhase));
await this.toNextTurn();
}
/**
@ -268,15 +213,4 @@ export default class GameManager {
}
return updateUserInfo();
}
async killPokemon(pokemon: PlayerPokemon | EnemyPokemon) {
(this.scene.time as MockClock).overrideDelay = 0.01;
return new Promise<void>(async(resolve, reject) => {
pokemon.hp = 0;
this.scene.pushPhase(new FaintPhase(this.scene, pokemon.getBattlerIndex(), true));
await this.phaseInterceptor.to(FaintPhase).catch((e) => reject(e));
(this.scene.time as MockClock).overrideDelay = undefined;
resolve();
});
}
}

View File

@ -120,7 +120,7 @@ export default class GameWrapper {
pause: () => null,
setRate: () => null,
add: () => this.scene.sound,
get: () => ({...this.scene.sound, totalDuration: 0}),
get: () => this.scene.sound,
getAllPlaying: () => [],
manager: {
game: this.game,
@ -131,13 +131,6 @@ export default class GameWrapper {
key: "",
};
this.scene.cameras = {
main: {
setPostPipeline: () => null,
removePostPipeline: () => null,
},
}
this.scene.tweens = {
add: (data) => {
if (data.onComplete) {

View File

@ -2,10 +2,8 @@ import Clock = Phaser.Time.Clock;
export class MockClock extends Clock {
public overrideDelay: number;
constructor(scene) {
super(scene);
this.overrideDelay = undefined;
setInterval(() => {
/*
To simulate frame update
@ -16,9 +14,4 @@ export class MockClock extends Clock {
this.update(this.systems.game.loop.time, 100);
}, 100);
}
addEvent(config: Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig): Phaser.Time.TimerEvent {
const cfg = { ...config, delay: this.overrideDelay || config.delay};
return super.addEvent(cfg);
}
}

View File

@ -143,7 +143,6 @@ export default class MockSprite {
play() {
// return this.phaserSprite.play();
return this;
}
setPipelineData(key, value) {

View File

@ -8,7 +8,6 @@ export default class MockText {
private textureManager;
public list = [];
public style;
constructor(textureManager, x, y, content, styleOptions) {
this.scene = textureManager.scene;
this.textureManager = textureManager;
@ -139,15 +138,6 @@ export default class MockText {
// return this.phaserText.setX(x);
}
/**
* Sets the position of this Game Object.
* @param x The x position of this Game Object. Default 0.
* @param y The y position of this Game Object. If not set it will use the `x` value. Default x.
* @param z The z position of this Game Object. Default 0.
* @param w The w position of this Game Object. Default 0.
*/
setPosition(x?: number, y?: number, z?: number, w?: number) { }
setText(text) {
// Sets the text this Game Object will display.
// return this.phaserText.setText(text);

View File

@ -1,43 +1,17 @@
import {
BattleEndPhase,
BerryPhase,
CheckSwitchPhase,
CommandPhase,
DamagePhase,
EggLapsePhase,
EncounterPhase,
EnemyCommandPhase,
FaintPhase,
LoginPhase,
MessagePhase,
MoveEffectPhase,
MoveEndPhase,
MovePhase,
NewBattlePhase,
NextEncounterPhase,
CheckSwitchPhase, CommandPhase, DamagePhase, EggLapsePhase,
EncounterPhase, EnemyCommandPhase, FaintPhase,
LoginPhase, MessagePhase, MoveEffectPhase, MoveEndPhase, MovePhase, NewBattlePhase, NextEncounterPhase,
PostSummonPhase,
SelectGenderPhase,
SelectModifierPhase,
SelectStarterPhase,
SelectTargetPhase,
ShinySparklePhase,
ShowAbilityPhase,
StatChangePhase,
SummonPhase,
SwitchPhase,
SwitchSummonPhase,
TitlePhase,
ToggleDoublePositionPhase,
TurnEndPhase,
TurnInitPhase,
TurnStartPhase,
UnavailablePhase,
VictoryPhase
SelectGenderPhase, SelectModifierPhase,
SelectStarterPhase, SelectTargetPhase, ShinySparklePhase, ShowAbilityPhase, StatChangePhase, SummonPhase,
TitlePhase, ToggleDoublePositionPhase, TurnEndPhase, TurnInitPhase, TurnStartPhase, UnavailablePhase, VictoryPhase
} from "#app/phases";
import UI, {Mode} from "#app/ui/ui";
import {Phase} from "#app/phase";
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
import {QuietFormChangePhase} from "#app/form-change-phase";
export default class PhaseInterceptor {
public scene;
@ -89,13 +63,10 @@ export default class PhaseInterceptor {
[ShinySparklePhase, this.startPhase],
[SelectTargetPhase, this.startPhase],
[UnavailablePhase, this.startPhase],
[QuietFormChangePhase, this.startPhase],
[SwitchPhase, this.startPhase],
[SwitchSummonPhase, this.startPhase],
];
private endBySetMode = [
TitlePhase, SelectGenderPhase, CommandPhase
TitlePhase, SelectGenderPhase, CommandPhase, SelectModifierPhase
];
/**
@ -107,8 +78,8 @@ export default class PhaseInterceptor {
this.log = [];
this.onHold = [];
this.prompts = [];
this.startPromptHandler();
this.initPhases();
this.startPromptHander();
}
rejectAll(error) {
@ -138,10 +109,8 @@ export default class PhaseInterceptor {
async to(phaseTo, runTarget: boolean = true): Promise<void> {
return new Promise(async (resolve, reject) => {
ErrorInterceptor.getInstance().add(this);
if (this.phaseFrom) {
await this.run(this.phaseFrom).catch((e) => reject(e));
this.phaseFrom = null;
}
await this.run(this.phaseFrom).catch((e) => reject(e));
this.phaseFrom = null;
const targetName = typeof phaseTo === "string" ? phaseTo : phaseTo.name;
this.intervalRun = setInterval(async() => {
const currentPhase = this.onHold?.length && this.onHold[0];
@ -269,6 +238,7 @@ export default class PhaseInterceptor {
*/
superEndPhase() {
const instance = this.scene.getCurrentPhase();
console.log(`%c INTERCEPTED Super End Phase ${instance.constructor.name}`, "color:red;");
this.originalSuperEnd.apply(instance);
this.inProgress?.callback();
this.inProgress = undefined;
@ -283,9 +253,6 @@ export default class PhaseInterceptor {
const instance = this.scene.ui;
console.log("setMode", mode, args);
const ret = this.originalSetMode.apply(instance, [mode, ...args]);
if (!this.phases[currentPhase.constructor.name]) {
throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptior PHASES list`);
}
if (this.phases[currentPhase.constructor.name].endBySetMode) {
this.inProgress?.callback();
this.inProgress = undefined;
@ -296,17 +263,16 @@ export default class PhaseInterceptor {
/**
* Method to start the prompt handler.
*/
startPromptHandler() {
startPromptHander() {
this.promptInterval = setInterval(() => {
if (this.prompts.length) {
const actionForNextPrompt = this.prompts[0];
const expireFn = actionForNextPrompt.expireFn && actionForNextPrompt.expireFn();
const currentMode = this.scene.ui.getMode();
const currentPhase = this.scene.getCurrentPhase().constructor.name;
const currentHandler = this.scene.ui.getHandler();
if (expireFn) {
this.prompts.shift();
} else if (currentMode === actionForNextPrompt.mode && currentPhase === actionForNextPrompt.phaseTarget && currentHandler.active && (!actionForNextPrompt.awaitingActionInput || (actionForNextPrompt.awaitingActionInput && currentHandler.awaitingActionInput))) {
} else if (currentMode === actionForNextPrompt.mode && currentPhase === actionForNextPrompt.phaseTarget) {
this.prompts.shift().callback();
}
}
@ -320,13 +286,12 @@ export default class PhaseInterceptor {
* @param callback - The callback function to execute.
* @param expireFn - The function to determine if the prompt has expired.
*/
addToNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn: () => void, awaitingActionInput: boolean = false) {
addToNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn: () => void) {
this.prompts.push({
phaseTarget,
mode,
callback,
expireFn,
awaitingActionInput
expireFn
});
}

View File

@ -179,25 +179,21 @@ export default class FightUiHandler extends UiHandler {
const pp = maxPP - pokemonMove.ppUsed;
this.ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`);
const ppPercentLeft = pp / maxPP;
let ppColor = "white";
if (ppPercentLeft <= 0.5) {
ppColor = "yellow";
}
if (ppPercentLeft <= 0.25) {
ppColor = "orange";
}
if (pp === 0) {
ppColor = "red";
}
this.ppText.setColor(ppColor);
this.powerText.setText(`${power >= 0 ? power : "---"}`);
this.accuracyText.setText(`${accuracy >= 0 ? accuracy : "---"}`);
const ppPercentLeft = pp / maxPP;
//** Determines TextStyle according to percentage of PP remaining */
let ppColorStyle = TextStyle.MOVE_PP_FULL;
if (ppPercentLeft > 0.25 && ppPercentLeft <= 0.5) {
ppColorStyle = TextStyle.MOVE_PP_HALF_FULL;
} else if (ppPercentLeft > 0 && ppPercentLeft <= 0.25) {
ppColorStyle = TextStyle.MOVE_PP_NEAR_EMPTY;
} else if (ppPercentLeft === 0) {
ppColorStyle = TextStyle.MOVE_PP_EMPTY;
}
//** Changes the text color and shadow according to the determined TextStyle */
this.ppText.setColor(this.getTextColor(ppColorStyle, false));
this.ppText.setShadowColor(this.getTextColor(ppColorStyle, true));
pokemon.getOpponents().forEach((opponent) => {
opponent.updateEffectiveness(this.getEffectivenessText(pokemon, opponent, pokemonMove));
});

View File

@ -1,4 +1,3 @@
import i18next from "i18next";
import BattleScene from "../battle-scene";
import { ModalUiHandler } from "./modal-ui-handler";
import { addTextObject, TextStyle } from "./text";
@ -32,7 +31,7 @@ export default class LoadingModalUiHandler extends ModalUiHandler {
setup(): void {
super.setup();
const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, i18next.t("menu:loading"), TextStyle.WINDOW);
const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, "Loading…", TextStyle.WINDOW);
label.setOrigin(0.5, 0.5);
this.modalContainer.add(label);

View File

@ -6,12 +6,12 @@ import { getNatureName } from "../data/nature";
import { Type } from "../data/type";
import Pokemon from "../field/pokemon";
import i18next from "../plugins/i18n";
import { DexAttr } from "../system/game-data";
import * as Utils from "../utils";
import ConfirmUiHandler from "./confirm-ui-handler";
import { StatsContainer } from "./stats-container";
import { TextStyle, addBBCodeTextObject, addTextObject, getTextColor } from "./text";
import { addWindow } from "./ui-theme";
import { DexAttr } from "../system/game-data";
interface LanguageSetting {
infoContainerTextSize: string;
@ -40,7 +40,7 @@ const languageSettings: { [key: string]: LanguageSetting } = {
},
"pt": {
infoContainerTextSize: "60px",
infoContainerLabelXPos: -15,
infoContainerLabelXPos: -16,
infoContainerTextXPos: -12,
},
};

View File

@ -193,21 +193,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private pokemonHatchedIcon : Phaser.GameObjects.Sprite;
private pokemonHatchedCountText: Phaser.GameObjects.Text;
private genOptionsText: Phaser.GameObjects.Text;
private instructionsContainer: Phaser.GameObjects.Container;
private shinyIconElement: Phaser.GameObjects.Sprite;
private formIconElement: Phaser.GameObjects.Sprite;
private abilityIconElement: Phaser.GameObjects.Sprite;
private genderIconElement: Phaser.GameObjects.Sprite;
private natureIconElement: Phaser.GameObjects.Sprite;
private variantIconElement: Phaser.GameObjects.Sprite;
private shinyLabel: Phaser.GameObjects.Text;
private formLabel: Phaser.GameObjects.Text;
private genderLabel: Phaser.GameObjects.Text;
private abilityLabel: Phaser.GameObjects.Text;
private natureLabel: Phaser.GameObjects.Text;
private variantLabel: Phaser.GameObjects.Text;
private instructionsText: Phaser.GameObjects.Text;
private starterSelectMessageBox: Phaser.GameObjects.NineSlice;
private starterSelectMessageBoxContainer: Phaser.GameObjects.Container;
private statsContainer: StatsContainer;
@ -669,45 +656,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.starterSelectContainer.add(this.pokemonEggMovesContainer);
// The font size should be set per language
const instructionTextSize = textSettings.instructionTextSize;
this.instructionsContainer = this.scene.add.container(4, 156);
this.instructionsContainer.setVisible(true);
this.starterSelectContainer.add(this.instructionsContainer);
// instruction rows that will be pushed into the container dynamically based on need
this.shinyIconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, "keyboard", "R.png");
this.shinyIconElement.setScale(0.675);
this.shinyIconElement.setOrigin(0.0, 0.0);
this.shinyLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleShiny"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.formIconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, "keyboard", "F.png");
this.formIconElement.setScale(0.675);
this.formIconElement.setOrigin(0.0, 0.0);
this.formLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleForm"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.genderIconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, "keyboard", "G.png");
this.genderIconElement.setScale(0.675);
this.genderIconElement.setOrigin(0.0, 0.0);
this.genderLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleGender"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.abilityIconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, "keyboard", "E.png");
this.abilityIconElement.setScale(0.675);
this.abilityIconElement.setOrigin(0.0, 0.0);
this.abilityLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleAbility"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.natureIconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, "keyboard", "N.png");
this.natureIconElement.setScale(0.675);
this.natureIconElement.setOrigin(0.0, 0.0);
this.natureLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleNature"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.variantIconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, "keyboard", "V.png");
this.variantIconElement.setScale(0.675);
this.variantIconElement.setOrigin(0.0, 0.0);
this.variantLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleVariant"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.hideInstructions();
this.starterSelectMessageBoxContainer = this.scene.add.container(0, this.scene.game.canvas.height / 6);
this.starterSelectMessageBoxContainer.setVisible(false);
this.starterSelectContainer.add(this.starterSelectMessageBoxContainer);
@ -1542,7 +1494,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, undefined, false);
}
updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void {
createButtonFromIconText(iconSetting, gamepadType, translatedText, instructionTextSize): void {
let iconPath;
// touch controls cannot be rebound as is, and are just emulating a keyboard event.
// Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls
@ -1573,11 +1525,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} else {
iconPath = this.scene.inputController?.getIconForLatestInputRecorded(iconSetting);
}
iconElement.setTexture(gamepadType, iconPath);
iconElement.setPosition(this.instructionRowX, this.instructionRowY);
controlLabel.setPosition(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY);
iconElement.setVisible(true);
controlLabel.setVisible(true);
const iconElement = this.scene.add.sprite(this.instructionRowX, this.instructionRowY, gamepadType, iconPath);
iconElement.setScale(0.675);
iconElement.setOrigin(0.0, 0.0);
const controlLabel = addTextObject(this.scene, this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, translatedText, TextStyle.PARTY, { fontSize: instructionTextSize });
this.instructionsContainer.add([iconElement, controlLabel]);
this.instructionRowY += 8;
if (this.instructionRowY >= 24) {
@ -1587,9 +1538,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
}
updateInstructions(): void {
const currentLanguage = i18next.resolvedLanguage;
const langSettingKey = Object.keys(languageSettings).find(lang => currentLanguage.includes(lang));
const textSettings = languageSettings[langSettingKey];
const instructionTextSize = textSettings.instructionTextSize;
this.instructionRowX = 0;
this.instructionRowY = 0;
this.hideInstructions();
this.instructionsContainer.removeAll();
let gamepadType;
if (this.scene.inputMethod === "gamepad") {
@ -1600,22 +1554,22 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (this.speciesStarterDexEntry?.caughtAttr) {
if (this.canCycleShiny) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Shiny, gamepadType, this.shinyIconElement, this.shinyLabel);
this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Shiny, gamepadType, i18next.t("starterSelectUiHandler:cycleShiny"), instructionTextSize);
}
if (this.canCycleForm) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Form, gamepadType, this.formIconElement, this.formLabel);
this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Form, gamepadType, i18next.t("starterSelectUiHandler:cycleForm"), instructionTextSize);
}
if (this.canCycleGender) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Gender, gamepadType, this.genderIconElement, this.genderLabel);
this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Gender, gamepadType, i18next.t("starterSelectUiHandler:cycleGender"), instructionTextSize);
}
if (this.canCycleAbility) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Ability, gamepadType, this.abilityIconElement, this.abilityLabel);
this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Ability, gamepadType, i18next.t("starterSelectUiHandler:cycleAbility"), instructionTextSize);
}
if (this.canCycleNature) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Nature, gamepadType, this.natureIconElement, this.natureLabel);
this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Nature, gamepadType, i18next.t("starterSelectUiHandler:cycleNature"), instructionTextSize);
}
if (this.canCycleVariant) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Variant, gamepadType, this.variantIconElement, this.variantLabel);
this.createButtonFromIconText(SettingKeyboard.Button_Cycle_Variant, gamepadType, i18next.t("starterSelectUiHandler:cycleVariant"), instructionTextSize);
}
}
}
@ -2387,25 +2341,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
super.clearText();
}
hideInstructions(): void {
this.shinyIconElement.setVisible(false);
this.shinyLabel.setVisible(false);
this.formIconElement.setVisible(false);
this.formLabel.setVisible(false);
this.genderIconElement.setVisible(false);
this.genderLabel.setVisible(false);
this.abilityIconElement.setVisible(false);
this.abilityLabel.setVisible(false);
this.natureIconElement.setVisible(false);
this.natureLabel.setVisible(false);
this.variantIconElement.setVisible(false);
this.variantLabel.setVisible(false);
}
clear(): void {
super.clear();
this.cursor = -1;
this.hideInstructions();
this.starterSelectContainer.setVisible(false);
this.blockInput = false;

View File

@ -29,11 +29,7 @@ export enum TextStyle {
SETTINGS_LOCKED,
TOOLTIP_TITLE,
TOOLTIP_CONTENT,
MOVE_INFO_CONTENT,
MOVE_PP_FULL,
MOVE_PP_HALF_FULL,
MOVE_PP_NEAR_EMPTY,
MOVE_PP_EMPTY
MOVE_INFO_CONTENT
}
interface LanguageSetting {
@ -208,27 +204,11 @@ export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: Ui
return !shadow ? "#f8f8f8" : "#6b5a73";
case TextStyle.WINDOW:
case TextStyle.MOVE_INFO_CONTENT:
case TextStyle.MOVE_PP_FULL:
case TextStyle.TOOLTIP_CONTENT:
if (uiTheme) {
return !shadow ? "#484848" : "#d0d0c8";
}
return !shadow ? "#f8f8f8" : "#6b5a73";
case TextStyle.MOVE_PP_HALF_FULL:
if (uiTheme) {
return !shadow ? "#a68e17" : "#ebd773";
}
return !shadow ? "#ccbe00" : "#6e672c";
case TextStyle.MOVE_PP_NEAR_EMPTY:
if (uiTheme) {
return !shadow ? "#d64b00" : "#f7b18b";
}
return !shadow ? "#d64b00" : "#69402a";
case TextStyle.MOVE_PP_EMPTY:
if (uiTheme) {
return !shadow ? "#e13d3d" : "#fca2a2";
}
return !shadow ? "#e13d3d" : "#632929";
case TextStyle.WINDOW_ALT:
return !shadow ? "#484848" : "#d0d0c8";
case TextStyle.BATTLE_INFO: