Merge branch 'beta' into gitlocalize-30798

This commit is contained in:
José Ricardo 2024-09-01 19:30:17 -03:00 committed by GitHub
commit 85a16850b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 462 additions and 390 deletions

View File

@ -30,7 +30,7 @@
- [ ] The PR is self-contained and cannot be split into smaller PRs? - [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes? - [ ] Have I provided a clear explanation of the changes?
- [ ] Have I considered writing automated tests for the issue? - [ ] Have I considered writing automated tests for the issue?
- [ ] If I have text, did I add make it translatable and added a key in the English language? - [ ] If I have text, did I make it translatable and add a key in the English locale file(s)?
- [ ] Have I tested the changes (manually)? - [ ] Have I tested the changes (manually)?
- [ ] Are all unit tests still passing? (`npm run test`) - [ ] Are all unit tests still passing? (`npm run test`)
- [ ] Are the changes visual? - [ ] Are the changes visual?

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -5025,7 +5025,7 @@ export function initAbilities() {
.attr(AlwaysHitAbAttr) .attr(AlwaysHitAbAttr)
.attr(DoubleBattleChanceAbAttr), .attr(DoubleBattleChanceAbAttr),
new Ability(Abilities.STALL, 4) new Ability(Abilities.STALL, 4)
.attr(ChangeMovePriorityAbAttr, (pokemon, move: Move) => true, -0.5), .attr(ChangeMovePriorityAbAttr, (pokemon, move: Move) => true, -0.2),
new Ability(Abilities.TECHNICIAN, 4) new Ability(Abilities.TECHNICIAN, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => { .attr(MovePowerBoostAbAttr, (user, target, move) => {
const power = new Utils.NumberHolder(move.power); const power = new Utils.NumberHolder(move.power);
@ -5713,7 +5713,7 @@ export function initAbilities() {
.partial() // Healing not blocked by Heal Block .partial() // Healing not blocked by Heal Block
.ignorable(), .ignorable(),
new Ability(Abilities.MYCELIUM_MIGHT, 9) new Ability(Abilities.MYCELIUM_MIGHT, 9)
.attr(ChangeMovePriorityAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS, -0.5) .attr(ChangeMovePriorityAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS, -0.2)
.attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS) .attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS)
.attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS), .attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS),
new Ability(Abilities.MINDS_EYE, 9) new Ability(Abilities.MINDS_EYE, 9)

View File

@ -35,18 +35,18 @@ interface BiomeDepths {
export const biomeLinks: BiomeLinks = { export const biomeLinks: BiomeLinks = {
[Biome.TOWN]: Biome.PLAINS, [Biome.TOWN]: Biome.PLAINS,
[Biome.PLAINS]: [ Biome.GRASS, Biome.METROPOLIS, Biome.LAKE ], [Biome.PLAINS]: [ Biome.GRASS, Biome.METROPOLIS, Biome.LAKE ],
[Biome.GRASS]: [ Biome.TALL_GRASS, [ Biome.CONSTRUCTION_SITE, 2 ] ], [Biome.GRASS]: Biome.TALL_GRASS,
[Biome.TALL_GRASS]: [ Biome.FOREST, Biome.CAVE ], [Biome.TALL_GRASS]: [ Biome.FOREST, Biome.CAVE ],
[Biome.SLUM]: Biome.CONSTRUCTION_SITE, [Biome.SLUM]: [ Biome.CONSTRUCTION_SITE, [ Biome.SWAMP, 2 ] ],
[Biome.FOREST]: [ Biome.JUNGLE, Biome.MEADOW ], [Biome.FOREST]: [ Biome.JUNGLE, Biome.MEADOW ],
[Biome.SEA]: [ Biome.SEABED, Biome.ICE_CAVE ], [Biome.SEA]: [ Biome.SEABED, Biome.ICE_CAVE ],
[Biome.SWAMP]: [ Biome.GRAVEYARD, Biome.TALL_GRASS ], [Biome.SWAMP]: [ Biome.GRAVEYARD, Biome.TALL_GRASS ],
[Biome.BEACH]: [ Biome.SEA, [ Biome.ISLAND, 3 ] ], [Biome.BEACH]: [ Biome.SEA, [ Biome.ISLAND, 2 ] ],
[Biome.LAKE]: [ Biome.BEACH, Biome.SWAMP, Biome.CONSTRUCTION_SITE ], [Biome.LAKE]: [ Biome.BEACH, Biome.SWAMP, Biome.CONSTRUCTION_SITE ],
[Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 3 ] ], [Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 3 ] ],
[Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.DOJO, 2] [ Biome.WASTELAND, 2 ] ], [Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 2 ], [ Biome.SPACE, 3 ] ],
[Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ], [Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ],
[Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE ], [Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE [ Biome.LABORATORY, 2 ] ],
[Biome.DESERT]: [ Biome.RUINS, [ Biome.CONSTRUCTION_SITE, 2 ] ], [Biome.DESERT]: [ Biome.RUINS, [ Biome.CONSTRUCTION_SITE, 2 ] ],
[Biome.ICE_CAVE]: Biome.SNOWY_FOREST, [Biome.ICE_CAVE]: Biome.SNOWY_FOREST,
[Biome.MEADOW]: [ Biome.PLAINS, Biome.FAIRY_CAVE ], [Biome.MEADOW]: [ Biome.PLAINS, Biome.FAIRY_CAVE ],
@ -54,17 +54,17 @@ export const biomeLinks: BiomeLinks = {
[Biome.VOLCANO]: [ Biome.BEACH, [ Biome.ICE_CAVE, 3 ] ], [Biome.VOLCANO]: [ Biome.BEACH, [ Biome.ICE_CAVE, 3 ] ],
[Biome.GRAVEYARD]: Biome.ABYSS, [Biome.GRAVEYARD]: Biome.ABYSS,
[Biome.DOJO]: [ Biome.PLAINS, [ Biome.JUNGLE, 2], [ Biome.TEMPLE, 2 ] ], [Biome.DOJO]: [ Biome.PLAINS, [ Biome.JUNGLE, 2], [ Biome.TEMPLE, 2 ] ],
[Biome.FACTORY]: [ Biome.TALL_GRASS, [ Biome.LABORATORY, 3 ] ], [Biome.FACTORY]: [ Biome.PLAINS, [ Biome.LABORATORY, 2 ] ],
[Biome.RUINS]: [ Biome.FOREST ], [Biome.RUINS]: [ Biome.MOUNTAIN, [ Biome.FOREST, 2 ] ],
[Biome.WASTELAND]: Biome.BADLANDS, [Biome.WASTELAND]: Biome.BADLANDS,
[Biome.ABYSS]: [ Biome.CAVE, [ Biome.SPACE, 3 ], [ Biome.WASTELAND, 3 ] ], [Biome.ABYSS]: [ Biome.CAVE, [ Biome.SPACE, 2 ], [ Biome.WASTELAND, 2 ] ],
[Biome.SPACE]: Biome.RUINS, [Biome.SPACE]: Biome.RUINS,
[Biome.CONSTRUCTION_SITE]: [ Biome.POWER_PLANT, [ Biome.DOJO, 2 ] ], [Biome.CONSTRUCTION_SITE]: [ Biome.POWER_PLANT, [ Biome.DOJO, 2 ] ],
[Biome.JUNGLE]: [ Biome.TEMPLE ], [Biome.JUNGLE]: [ Biome.TEMPLE ],
[Biome.FAIRY_CAVE]: [ Biome.ICE_CAVE, [ Biome.SPACE, 2 ] ], [Biome.FAIRY_CAVE]: [ Biome.ICE_CAVE, [ Biome.SPACE, 2 ] ],
[Biome.TEMPLE]: [ Biome.DESERT, [ Biome.SWAMP, 2 ], [ Biome.RUINS, 2 ] ], [Biome.TEMPLE]: [ Biome.DESERT, [ Biome.SWAMP, 2 ], [ Biome.RUINS, 2 ] ],
[Biome.METROPOLIS]: Biome.SLUM, [Biome.METROPOLIS]: Biome.SLUM,
[Biome.SNOWY_FOREST]: [ Biome.FOREST, Biome.MOUNTAIN, [ Biome.LAKE, 2 ] ], [Biome.SNOWY_FOREST]: [ Biome.FOREST, [ Biome.MOUNTAIN, 2 ], [ Biome.LAKE, 2 ] ],
[Biome.ISLAND]: Biome.SEA, [Biome.ISLAND]: Biome.SEA,
[Biome.LABORATORY]: Biome.CONSTRUCTION_SITE [Biome.LABORATORY]: Biome.CONSTRUCTION_SITE
}; };
@ -7666,7 +7666,7 @@ export function initBiomes() {
if (biome === Biome.END) { if (biome === Biome.END) {
const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key))); const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key)));
biomeList.pop(); // Removes Biome.END from the list biomeList.pop(); // Removes Biome.END from the list
const randIndex = Utils.randInt(biomeList.length, 2); // Will never be Biome.TOWN or Biome.PLAINS const randIndex = Utils.randInt(biomeList.length, 1); // Will never be Biome.TOWN
biome = Biome[biomeList[randIndex]]; biome = Biome[biomeList[randIndex]];
} }
const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome]) const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome])

View File

@ -1132,7 +1132,7 @@ export function initSpecies() {
), ),
new PokemonSpecies(Species.SNORLAX, 1, false, false, false, "Sleeping Pokémon", Type.NORMAL, null, 2.1, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 540, 160, 110, 65, 65, 110, 30, 25, 50, 189, GrowthRate.SLOW, 87.5, false, true, new PokemonSpecies(Species.SNORLAX, 1, false, false, false, "Sleeping Pokémon", Type.NORMAL, null, 2.1, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 540, 160, 110, 65, 65, 110, 30, 25, 50, 189, GrowthRate.SLOW, 87.5, false, true,
new PokemonForm("Normal", "", Type.NORMAL, null, 2.1, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 540, 160, 110, 65, 65, 110, 30, 25, 50, 189, false, null, true), new PokemonForm("Normal", "", Type.NORMAL, null, 2.1, 460, Abilities.IMMUNITY, Abilities.THICK_FAT, Abilities.GLUTTONY, 540, 160, 110, 65, 65, 110, 30, 25, 50, 189, false, null, true),
new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 35, 460, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 640, 200, 135, 85, 80, 125, 15, 25, 50, 189), new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.NORMAL, null, 35, 460, Abilities.HARVEST, Abilities.HARVEST, Abilities.HARVEST, 640, 200, 135, 80, 80, 125, 20, 25, 50, 189),
), ),
new PokemonSpecies(Species.ARTICUNO, 1, true, false, false, "Freeze Pokémon", Type.ICE, Type.FLYING, 1.7, 55.4, Abilities.PRESSURE, Abilities.NONE, Abilities.SNOW_CLOAK, 580, 90, 85, 100, 95, 125, 85, 3, 35, 290, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.ARTICUNO, 1, true, false, false, "Freeze Pokémon", Type.ICE, Type.FLYING, 1.7, 55.4, Abilities.PRESSURE, Abilities.NONE, Abilities.SNOW_CLOAK, 580, 90, 85, 100, 95, 125, 85, 3, 35, 290, GrowthRate.SLOW, null, false),
new PokemonSpecies(Species.ZAPDOS, 1, true, false, false, "Electric Pokémon", Type.ELECTRIC, Type.FLYING, 1.6, 52.6, Abilities.PRESSURE, Abilities.NONE, Abilities.STATIC, 580, 90, 90, 85, 125, 90, 100, 3, 35, 290, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.ZAPDOS, 1, true, false, false, "Electric Pokémon", Type.ELECTRIC, Type.FLYING, 1.6, 52.6, Abilities.PRESSURE, Abilities.NONE, Abilities.STATIC, 580, 90, 90, 85, 125, 90, 100, 3, 35, 290, GrowthRate.SLOW, null, false),
@ -3573,7 +3573,7 @@ export const starterPassiveAbilities = {
[Species.CHATOT]: Abilities.PUNK_ROCK, [Species.CHATOT]: Abilities.PUNK_ROCK,
[Species.SPIRITOMB]: Abilities.VESSEL_OF_RUIN, [Species.SPIRITOMB]: Abilities.VESSEL_OF_RUIN,
[Species.GIBLE]: Abilities.SAND_STREAM, [Species.GIBLE]: Abilities.SAND_STREAM,
[Species.MUNCHLAX]: Abilities.HARVEST, [Species.MUNCHLAX]: Abilities.RIPEN,
[Species.RIOLU]: Abilities.MINDS_EYE, [Species.RIOLU]: Abilities.MINDS_EYE,
[Species.HIPPOPOTAS]: Abilities.UNAWARE, [Species.HIPPOPOTAS]: Abilities.UNAWARE,
[Species.SKORUPI]: Abilities.SUPER_LUCK, [Species.SKORUPI]: Abilities.SUPER_LUCK,

View File

@ -41,8 +41,6 @@ export class LoadingScene extends SceneBase {
this.loadImage("loading_bg", "arenas"); this.loadImage("loading_bg", "arenas");
this.loadImage("logo", ""); this.loadImage("logo", "");
// this.loadImage("pride-update", "events");
this.loadImage("august-variant-update", "events");
// Load menu images // Load menu images
this.loadAtlas("bg", "ui"); this.loadAtlas("bg", "ui");
@ -246,7 +244,12 @@ export class LoadingScene extends SceneBase {
} else { } else {
this.loadAtlas("types", ""); this.loadAtlas("types", "");
} }
const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt_BR", "zh_CN"];
if (lang && availableLangs.includes(lang)) {
this.loadImage("september-update-"+lang, "events");
} else {
this.loadImage("september-update-en", "events");
}
this.loadAtlas("statuses", ""); this.loadAtlas("statuses", "");
this.loadAtlas("categories", ""); this.loadAtlas("categories", "");

View File

@ -10,19 +10,19 @@
}, },
"10K_MONEY": { "10K_MONEY": {
"name": "Money Haver", "name": "Money Haver",
"name_female": null "name_female": "Money Haver"
}, },
"100K_MONEY": { "100K_MONEY": {
"name": "Rich", "name": "Rich",
"name_female": null "name_female": "Rich"
}, },
"1M_MONEY": { "1M_MONEY": {
"name": "Millionaire", "name": "Millionaire",
"name_female": null "name_female": "Millionaire"
}, },
"10M_MONEY": { "10M_MONEY": {
"name": "One Percenter", "name": "One Percenter",
"name_female": null "name_female": "One Percenter"
}, },
"DamageAchv": { "DamageAchv": {
"description": "Inflict {{damageAmount}} damage in one hit" "description": "Inflict {{damageAmount}} damage in one hit"
@ -32,11 +32,11 @@
}, },
"1000_DMG": { "1000_DMG": {
"name": "Harder Hitter", "name": "Harder Hitter",
"name_female": null "name_female": "Harder Hitter"
}, },
"2500_DMG": { "2500_DMG": {
"name": "That's a Lotta Damage!", "name": "That's a Lotta Damage!",
"name_female": null "name_female": "That's a Lotta Damage!"
}, },
"10000_DMG": { "10000_DMG": {
"name": "One Punch Man", "name": "One Punch Man",
@ -47,19 +47,19 @@
}, },
"250_HEAL": { "250_HEAL": {
"name": "Novice Healer", "name": "Novice Healer",
"name_female": null "name_female": "Novice Healer"
}, },
"1000_HEAL": { "1000_HEAL": {
"name": "Big Healer", "name": "Big Healer",
"name_female": null "name_female": "Big Healer"
}, },
"2500_HEAL": { "2500_HEAL": {
"name": "Cleric", "name": "Cleric",
"name_female": null "name_female": "Cleric"
}, },
"10000_HEAL": { "10000_HEAL": {
"name": "Recovery Master", "name": "Recovery Master",
"name_female": null "name_female": "Recovery Master"
}, },
"LevelAchv": { "LevelAchv": {
"description": "Level up a Pokémon to Lv{{level}}" "description": "Level up a Pokémon to Lv{{level}}"
@ -69,7 +69,7 @@
}, },
"LV_250": { "LV_250": {
"name": "Elite", "name": "Elite",
"name_female": null "name_female": "Elite"
}, },
"LV_1000": { "LV_1000": {
"name": "To Go Even Further Beyond" "name": "To Go Even Further Beyond"
@ -79,23 +79,23 @@
}, },
"10_RIBBONS": { "10_RIBBONS": {
"name": "Pokémon League Champion", "name": "Pokémon League Champion",
"name_female": null "name_female": "Pokémon League Champion"
}, },
"25_RIBBONS": { "25_RIBBONS": {
"name": "Great League Champion", "name": "Great League Champion",
"name_female": null "name_female": "Great League Champion"
}, },
"50_RIBBONS": { "50_RIBBONS": {
"name": "Ultra League Champion", "name": "Ultra League Champion",
"name_female": null "name_female": "Ultra League Champion"
}, },
"75_RIBBONS": { "75_RIBBONS": {
"name": "Rogue League Champion", "name": "Rogue League Champion",
"name_female": null "name_female": "Rogue League Champion"
}, },
"100_RIBBONS": { "100_RIBBONS": {
"name": "Master League Champion", "name": "Master League Champion",
"name_female": null "name_female": "Master League Champion"
}, },
"TRANSFER_MAX_BATTLE_STAT": { "TRANSFER_MAX_BATTLE_STAT": {
"name": "Teamwork", "name": "Teamwork",
@ -147,7 +147,7 @@
}, },
"SHINY_PARTY": { "SHINY_PARTY": {
"name": "That's Dedication", "name": "That's Dedication",
"name_female": null, "name_female": "That's Dedication",
"description": "Have a full party of shiny Pokémon" "description": "Have a full party of shiny Pokémon"
}, },
"HATCH_MYTHICAL": { "HATCH_MYTHICAL": {
@ -176,7 +176,7 @@
}, },
"CLASSIC_VICTORY": { "CLASSIC_VICTORY": {
"name": "Undefeated", "name": "Undefeated",
"name_female": null, "name_female": "Undefeated",
"description": "Beat the game in classic mode" "description": "Beat the game in classic mode"
}, },
"UNEVOLVED_CLASSIC_VICTORY": { "UNEVOLVED_CLASSIC_VICTORY": {

View File

@ -58,7 +58,7 @@
"iris_alder_double": { "iris_alder_double": {
"encounter": { "encounter": {
"1": "Iris: Welcome Challenger! I am THE Unova Champion!\n$Alder: Iris, aren't you a bit too excited?", "1": "Iris: Welcome Challenger! I am THE Unova Champion!\n$Alder: Iris, aren't you a bit too excited?",
"1_female": null "1_female": "Iris: Welcome Challenger! I am THE Unova Champion!\n$Alder: Iris, aren't you a bit too excited?"
}, },
"victory": { "victory": {
"1": "Iris: A loss like this is not easy to take...\n$Alder: But we will only get stronger with every loss!" "1": "Iris: A loss like this is not easy to take...\n$Alder: But we will only get stronger with every loss!"
@ -75,7 +75,7 @@
"marnie_piers_double": { "marnie_piers_double": {
"encounter": { "encounter": {
"1": "Piers: Ready for a concert?\n$Marnie: Brother... They are here to fight, not to sing...", "1": "Piers: Ready for a concert?\n$Marnie: Brother... They are here to fight, not to sing...",
"1_female": null "1_female": "Piers: Ready for a concert?\n$Marnie: Brother... They are here to fight, not to sing..."
}, },
"victory": { "victory": {
"1": "Piers: Now that was a great concert!\n$Marnie: Brother..." "1": "Piers: Now that was a great concert!\n$Marnie: Brother..."

View File

@ -1,6 +1,6 @@
{ {
"encounter": "It appears the time has finally come once again.\nYou know why you have come here, do you not?\n$You were drawn here, because you have been here before.\nCountless times.\n$Though, perhaps it can be counted.\nTo be precise, this is in fact your {{cycleCount}} cycle.\n$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.\n$Until now you have yet to succeed, but I sense a different presence in you this time.\n\n$You are the only one here, though it is as if there is… another.\n$Will you finally prove a formidable challenge to me?\nThe challenge I have longed after for millennia?\n$We begin.", "encounter": "It appears the time has finally come once again.\nYou know why you have come here, do you not?\n$You were drawn here, because you have been here before.\nCountless times.\n$Though, perhaps it can be counted.\nTo be precise, this is in fact your {{cycleCount}} cycle.\n$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.\n$Until now you have yet to succeed, but I sense a different presence in you this time.\n\n$You are the only one here, though it is as if there is… another.\n$Will you finally prove a formidable challenge to me?\nThe challenge I have longed after for millennia?\n$We begin.",
"encounter_female": null, "encounter_female": "It appears the time has finally come once again.\nYou know why you have come here, do you not?\n$You were drawn here, because you have been here before.\nCountless times.\n$Though, perhaps it can be counted.\nTo be precise, this is in fact your {{cycleCount}} cycle.\n$Each cycle your mind reverts to its former state.\nEven so, somehow, remnants of your former selves remain.\n$Until now you have yet to succeed, but I sense a different presence in you this time.\n\n$You are the only one here, though it is as if there is… another.\n$Will you finally prove a formidable challenge to me?\nThe challenge I have longed after for millennia?\n$We begin.",
"firstStageWin": "I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back.\n$Do not disappoint me.", "firstStageWin": "I see. The presence I felt was indeed real.\nIt appears I no longer need to hold back.\n$Do not disappoint me.",
"secondStageWin": "…Magnificent.", "secondStageWin": "…Magnificent.",
"key_ordinal_one": "st", "key_ordinal_one": "st",

View File

@ -3,31 +3,31 @@
"encounter": { "encounter": {
"1": "Hey, wanna battle?", "1": "Hey, wanna battle?",
"2": "Are you a new trainer too?", "2": "Are you a new trainer too?",
"2_female": null, "2_female": "Are you a new trainer too?",
"3": "Hey, I haven't seen you before. Let's battle!", "3": "Hey, I haven't seen you before. Let's battle!",
"4": "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!", "4": "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!",
"4_female": null, "4_female": "I just lost, so I'm trying to find more Pokémon.\nWait! You look weak! Come on, let's battle!",
"5": "Have we met or not? I don't really remember. Well, I guess it's nice to meet you anyway!", "5": "Have we met or not? I don't really remember. Well, I guess it's nice to meet you anyway!",
"6": "All right! Let's go!", "6": "All right! Let's go!",
"7": "All right! Here I come! I'll show you my power!", "7": "All right! Here I come! I'll show you my power!",
"8": "Haw haw haw... I'll show you how hawesome my Pokémon are!", "8": "Haw haw haw... I'll show you how hawesome my Pokémon are!",
"9": "No need to waste time saying hello. Bring it on whenever you're ready!", "9": "No need to waste time saying hello. Bring it on whenever you're ready!",
"9_female": null, "9_female": "No need to waste time saying hello. Bring it on whenever you're ready!",
"10": "Don't let your guard down, or you may be crying when a kid beats you.", "10": "Don't let your guard down, or you may be crying when a kid beats you.",
"11": "I've raised my Pokémon with great care. You're not allowed to hurt them!", "11": "I've raised my Pokémon with great care. You're not allowed to hurt them!",
"12": "Glad you made it! It won't be an easy job from here.", "12": "Glad you made it! It won't be an easy job from here.",
"12_female": null, "12_female": "Glad you made it! It won't be an easy job from here.",
"13": "The battles continue forever! Welcome to the world with no end!", "13": "The battles continue forever! Welcome to the world with no end!",
"13_female": null "13_female": "The battles continue forever! Welcome to the world with no end!"
}, },
"victory": { "victory": {
"1": "Wow! You're strong!", "1": "Wow! You're strong!",
"1_female": null, "1_female": "Wow! You're strong!",
"2": "I didn't stand a chance, huh?", "2": "I didn't stand a chance, huh?",
"3": "I'll find you again when I'm older and beat you!", "3": "I'll find you again when I'm older and beat you!",
"4": "Ugh. I don't have any more Pokémon.", "4": "Ugh. I don't have any more Pokémon.",
"5": "No way… NO WAY! How could I lose again…", "5": "No way… NO WAY! How could I lose again…",
"5_female": null, "5_female": "No way… NO WAY! How could I lose again…",
"6": "No! I lost!", "6": "No! I lost!",
"7": "Whoa! You are incredible! I'm amazed and surprised!", "7": "Whoa! You are incredible! I'm amazed and surprised!",
"8": "Could it be… How… My Pokémon and I are the strongest, though…", "8": "Could it be… How… My Pokémon and I are the strongest, though…",
@ -42,12 +42,12 @@
"encounter": { "encounter": {
"1": "Let's have a battle, shall we?", "1": "Let's have a battle, shall we?",
"2": "You look like a new trainer. Let's have a battle!", "2": "You look like a new trainer. Let's have a battle!",
"2_female": null, "2_female": "You look like a new trainer. Let's have a battle!",
"3": "I don't recognize you. How about a battle?", "3": "I don't recognize you. How about a battle?",
"4": "Let's have a fun Pokémon battle!", "4": "Let's have a fun Pokémon battle!",
"5": "I'll show you the ropes of how to really use Pokémon!", "5": "I'll show you the ropes of how to really use Pokémon!",
"6": "A serious battle starts from a serious beginning! Are you sure you're ready?", "6": "A serious battle starts from a serious beginning! Are you sure you're ready?",
"6_female": null, "6_female": "A serious battle starts from a serious beginning! Are you sure you're ready?",
"7": "You're only young once. And you only get one shot at a given battle. Soon, you'll be nothing but a memory.", "7": "You're only young once. And you only get one shot at a given battle. Soon, you'll be nothing but a memory.",
"8": "You'd better go easy on me, OK? Though I'll be seriously fighting!", "8": "You'd better go easy on me, OK? Though I'll be seriously fighting!",
"9": "School is boring. I've got nothing to do. Yawn. I'm only battling to kill the time." "9": "School is boring. I've got nothing to do. Yawn. I'm only battling to kill the time."
@ -55,15 +55,15 @@
"victory": { "victory": {
"1": "That was impressive! I've got a lot to learn.", "1": "That was impressive! I've got a lot to learn.",
"2": "I didn't think you'd beat me that bad…", "2": "I didn't think you'd beat me that bad…",
"2_female": null, "2_female": "I didn't think you'd beat me that bad…",
"3": "I hope we get to have a rematch some day.", "3": "I hope we get to have a rematch some day.",
"4": "That was pretty amazingly fun! You've totally exhausted me…", "4": "That was pretty amazingly fun! You've totally exhausted me…",
"5": "You actually taught me a lesson! You're pretty amazing!", "5": "You actually taught me a lesson! You're pretty amazing!",
"6": "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.", "6": "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.",
"6_female": null, "6_female": "Seriously, I lost. That is, like, seriously depressing, but you were seriously cool.",
"7": "I don't need memories like this. Deleting memory…", "7": "I don't need memories like this. Deleting memory…",
"8": "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.", "8": "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.",
"8_female": null, "8_female": "Hey! I told you to go easy on me! Still, you're pretty cool when you're serious.",
"9": "I'm actually getting tired of battling… There's gotta be something new to do…" "9": "I'm actually getting tired of battling… There's gotta be something new to do…"
} }
}, },
@ -154,7 +154,7 @@
"ace_trainer": { "ace_trainer": {
"encounter": { "encounter": {
"1": "You seem quite confident.", "1": "You seem quite confident.",
"1_female": null, "1_female": "You seem quite confident.",
"2": "Your Pokémon… Show them to me…", "2": "Your Pokémon… Show them to me…",
"3": "Because I'm an Ace Trainer, people think I'm strong.", "3": "Because I'm an Ace Trainer, people think I'm strong.",
"4": "Are you aware of what it takes to be an Ace Trainer?" "4": "Are you aware of what it takes to be an Ace Trainer?"
@ -163,9 +163,9 @@
"1": "Yes… You have good Pokémon…", "1": "Yes… You have good Pokémon…",
"2": "What?! But I'm a battling genius!", "2": "What?! But I'm a battling genius!",
"3": "Of course, you are the main character!", "3": "Of course, you are the main character!",
"3_female": null, "3_female": "Of course, you are the main character!",
"4": "OK! OK! You could be an Ace Trainer!", "4": "OK! OK! You could be an Ace Trainer!",
"4_female": null "4_female": "OK! OK! You could be an Ace Trainer!"
}, },
"defeat": { "defeat": {
"1": "I am devoting my body and soul to Pokémon battles!", "1": "I am devoting my body and soul to Pokémon battles!",
@ -187,7 +187,7 @@
"1": "Get ready, because when we team up, it's double the trouble!", "1": "Get ready, because when we team up, it's double the trouble!",
"2": "Two hearts, one strategy let's see if you can keep up with our twin power!", "2": "Two hearts, one strategy let's see if you can keep up with our twin power!",
"3": "Hope you're ready for double trouble, because we're about to bring the heat!", "3": "Hope you're ready for double trouble, because we're about to bring the heat!",
"3_female": null "3_female": "Hope you're ready for double trouble, because we're about to bring the heat!"
}, },
"victory": { "victory": {
"1": "We may have lost this round, but our bond remains unbreakable!", "1": "We may have lost this round, but our bond remains unbreakable!",
@ -216,7 +216,7 @@
"encounter": { "encounter": {
"1": "I praise your courage in challenging me! For I am the one with the strongest kick!", "1": "I praise your courage in challenging me! For I am the one with the strongest kick!",
"2": "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?", "2": "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?",
"2_female": null "2_female": "Oh, I see. Would you like to be cut to pieces? Or do you prefer the role of punching bag?"
}, },
"victory": { "victory": {
"1": "Oh. The Pokémon did the fighting. My strong kick didn't help a bit.", "1": "Oh. The Pokémon did the fighting. My strong kick didn't help a bit.",
@ -328,7 +328,7 @@
"defeat": { "defeat": {
"1": "New age simply refers to twentieth century classical composers, right?", "1": "New age simply refers to twentieth century classical composers, right?",
"2": "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself.", "2": "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself.",
"2_female": null "2_female": "Don't get hung up on sadness or frustration. You can use your grudges to motivate yourself."
} }
}, },
"psychic": { "psychic": {
@ -360,7 +360,7 @@
"baker": { "baker": {
"encounter": { "encounter": {
"1": "Hope you're ready to taste defeat!", "1": "Hope you're ready to taste defeat!",
"1_female": null "1_female": "Hope you're ready to taste defeat!"
}, },
"victory": { "victory": {
"1": "I'll bake a comeback." "1": "I'll bake a comeback."
@ -391,7 +391,7 @@
"1": "Matey, you're walking the plank if you lose!", "1": "Matey, you're walking the plank if you lose!",
"2": "Come on then! My sailor's pride is at stake!", "2": "Come on then! My sailor's pride is at stake!",
"3": "Ahoy there! Are you seasick?", "3": "Ahoy there! Are you seasick?",
"3_female": null "3_female": "Ahoy there! Are you seasick?"
}, },
"victory": { "victory": {
"1": "Argh! Beaten by a kid!", "1": "Argh! Beaten by a kid!",
@ -419,7 +419,7 @@
}, },
"victory": { "victory": {
"1": "Tch, you really are strong. It's too bad.\n$If you were to join Team Rocket, you could become an Executive.", "1": "Tch, you really are strong. It's too bad.\n$If you were to join Team Rocket, you could become an Executive.",
"1_female": null, "1_female": "Tch, you really are strong. It's too bad.\n$If you were to join Team Rocket, you could become an Executive.",
"2": "I... I'm shattered...", "2": "I... I'm shattered...",
"3": "Aaaieeeee! This can't be happening! I fought hard, but I still lost…" "3": "Aaaieeeee! This can't be happening! I fought hard, but I still lost…"
} }
@ -458,7 +458,7 @@
"1": "Hehehe! You might have beaten me, but you don't stand a chance against the boss!\n$If you get lost now, you won't have to face a sound whipping!", "1": "Hehehe! You might have beaten me, but you don't stand a chance against the boss!\n$If you get lost now, you won't have to face a sound whipping!",
"2": "Hehehe... So, I lost, too...", "2": "Hehehe... So, I lost, too...",
"3": "Ahya! How could this be? For an Admin like me to lose to some random trainer...", "3": "Ahya! How could this be? For an Admin like me to lose to some random trainer...",
"3_female": null "3_female": "Ahya! How could this be? For an Admin like me to lose to some random trainer..."
} }
}, },
"courtney": { "courtney": {
@ -478,13 +478,13 @@
"1": "Ahahahaha! You're going to meddle in Team Aqua's affairs?\n$You're either absolutely fearless, simply ignorant, or both!\n$You're so cute, you're disgusting! I'll put you down", "1": "Ahahahaha! You're going to meddle in Team Aqua's affairs?\n$You're either absolutely fearless, simply ignorant, or both!\n$You're so cute, you're disgusting! I'll put you down",
"2": "What's this? Who's this spoiled brat?", "2": "What's this? Who's this spoiled brat?",
"3": "Cool your jets. Be patient. I'll crush you shortly.", "3": "Cool your jets. Be patient. I'll crush you shortly.",
"3_female": null "3_female": "Cool your jets. Be patient. I'll crush you shortly."
}, },
"victory": { "victory": {
"1": "Ahahahaha! We got meddled with unexpectedly! We're out of options.\n$We'll have to pull out. But this isn't the last you'll see of Team Aqua!\n$We have other plans! Don't you forget it!", "1": "Ahahahaha! We got meddled with unexpectedly! We're out of options.\n$We'll have to pull out. But this isn't the last you'll see of Team Aqua!\n$We have other plans! Don't you forget it!",
"2": "Ahhh?! Did I go too easy on you?!", "2": "Ahhh?! Did I go too easy on you?!",
"3": "Uh. Are you telling me you've upped your game even more during the fight?\n$You're a brat with a bright future… My Pokémon and I don't have any strength left to fight…\n$Go on… Go and be destroyed by Archie.", "3": "Uh. Are you telling me you've upped your game even more during the fight?\n$You're a brat with a bright future… My Pokémon and I don't have any strength left to fight…\n$Go on… Go and be destroyed by Archie.",
"3_female": null "3_female": "Uh. Are you telling me you've upped your game even more during the fight?\n$You're a brat with a bright future… My Pokémon and I don't have any strength left to fight…\n$Go on… Go and be destroyed by Archie."
} }
}, },
"matt": { "matt": {
@ -497,7 +497,7 @@
"1": "Muwuhahaha! That battle was fun even though I lost!", "1": "Muwuhahaha! That battle was fun even though I lost!",
"2": "I can feel it! I can feel it, all right! The strength coming offa you!\n$More! I still want more! But looks like we're outta time...", "2": "I can feel it! I can feel it, all right! The strength coming offa you!\n$More! I still want more! But looks like we're outta time...",
"3": "Oho! That's a loss I can be proud of!", "3": "Oho! That's a loss I can be proud of!",
"3_female": null "3_female": "Oho! That's a loss I can be proud of!"
} }
}, },
"mars": { "mars": {
@ -505,7 +505,7 @@
"1": "I'm Mars, one of Team Galactic's top Commanders.", "1": "I'm Mars, one of Team Galactic's top Commanders.",
"2": "Team Galactic's vision for the future is unwavering. Opposition will be crushed without mercy!", "2": "Team Galactic's vision for the future is unwavering. Opposition will be crushed without mercy!",
"3": "Feeling nervous? You should be!", "3": "Feeling nervous? You should be!",
"3_female": null "3_female": "Feeling nervous? You should be!"
}, },
"victory": { "victory": {
"1": "This can't be happening! How did I lose?!", "1": "This can't be happening! How did I lose?!",
@ -540,25 +540,25 @@
"zinzolin": { "zinzolin": {
"encounter": { "encounter": {
"1": "You could become a threat to Team Plasma, so we will eliminate you here and now!", "1": "You could become a threat to Team Plasma, so we will eliminate you here and now!",
"1_female": null, "1_female": "You could become a threat to Team Plasma, so we will eliminate you here and now!",
"2": "You don't have the sense to know when to quit, it seems. It's an act of mercy on my part to bring an end to this now!", "2": "You don't have the sense to know when to quit, it seems. It's an act of mercy on my part to bring an end to this now!",
"3": "You're an impressive Trainer to have made it this far. But it ends here.", "3": "You're an impressive Trainer to have made it this far. But it ends here.",
"3_female": null "3_female": "You're an impressive Trainer to have made it this far. But it ends here."
}, },
"victory": { "victory": {
"1": "Ghetsis... I have failed you...", "1": "Ghetsis... I have failed you...",
"2": "It's bitter cold. I'm shivering. I'm suffering. Yet, we will stand victorious.", "2": "It's bitter cold. I'm shivering. I'm suffering. Yet, we will stand victorious.",
"3": "Hmph. You're a smarter Trainer than I expected, but not smart enough.", "3": "Hmph. You're a smarter Trainer than I expected, but not smart enough.",
"3_female": null "3_female": "Hmph. You're a smarter Trainer than I expected, but not smart enough."
} }
}, },
"rood": { "rood": {
"encounter": { "encounter": {
"1": "You are a threat to Team Plasma. We cannot let you walk away from here and now!", "1": "You are a threat to Team Plasma. We cannot let you walk away from here and now!",
"1_female": null, "1_female": "You are a threat to Team Plasma. We cannot let you walk away from here and now!",
"2": "It seems you don't know when to give up. I'll make sure no one interferes with our plans!", "2": "It seems you don't know when to give up. I'll make sure no one interferes with our plans!",
"3": "You are a remarkable Trainer to have made it this far. But this is where it ends.", "3": "You are a remarkable Trainer to have made it this far. But this is where it ends.",
"3_female": null "3_female": "You are a remarkable Trainer to have made it this far. But this is where it ends."
}, },
"victory": { "victory": {
"1": "Ghetsis... I have failed my mission...", "1": "Ghetsis... I have failed my mission...",
@ -569,15 +569,15 @@
"xerosic": { "xerosic": {
"encounter": { "encounter": {
"1": "Ah ha ha! It would be my pleasure. Come on, little Trainer! Let's see what you've got!", "1": "Ah ha ha! It would be my pleasure. Come on, little Trainer! Let's see what you've got!",
"1_female": null, "1_female": "Ah ha ha! It would be my pleasure. Come on, little Trainer! Let's see what you've got!",
"2": "Hmm... You're more powerful than you look. I wonder how much energy there is inside you.", "2": "Hmm... You're more powerful than you look. I wonder how much energy there is inside you.",
"2_female": null, "2_female": "Hmm... You're more powerful than you look. I wonder how much energy there is inside you.",
"3": "I've been waiting for you! I need to do a little research on you! Come, let us begin!" "3": "I've been waiting for you! I need to do a little research on you! Come, let us begin!"
}, },
"victory": { "victory": {
"1": "Ah, you're quite strong. Oh yes—very strong, indeed.", "1": "Ah, you're quite strong. Oh yes—very strong, indeed.",
"2": "Ding-ding-ding! You did it! To the victor go the spoils!", "2": "Ding-ding-ding! You did it! To the victor go the spoils!",
"2_female": null, "2_female": "Ding-ding-ding! You did it! To the victor go the spoils!",
"3": "Wonderful! Amazing! You have tremendous skill and bravery!" "3": "Wonderful! Amazing! You have tremendous skill and bravery!"
} }
}, },
@ -585,7 +585,7 @@
"encounter": { "encounter": {
"1": "I am Bryony, and it would be my pleasure to battle you. Show me what you've got.", "1": "I am Bryony, and it would be my pleasure to battle you. Show me what you've got.",
"2": "Impressive... You're more powerful than you appear. Let's see the true extent of your energy.", "2": "Impressive... You're more powerful than you appear. Let's see the true extent of your energy.",
"2_female": null, "2_female": "Impressive... You're more powerful than you appear. Let's see the true extent of your energy.",
"3": "I've anticipated your arrival. It's time for a little test. Shall we begin?" "3": "I've anticipated your arrival. It's time for a little test. Shall we begin?"
}, },
"victory": { "victory": {
@ -598,11 +598,11 @@
"encounter": { "encounter": {
"1": "Prepare for trouble!", "1": "Prepare for trouble!",
"2": "We're pulling a big job here! Get lost, kid!", "2": "We're pulling a big job here! Get lost, kid!",
"2_female": null, "2_female": "We're pulling a big job here! Get lost, kid!",
"3": "Hand over your Pokémon, or face the wrath of Team Rocket!", "3": "Hand over your Pokémon, or face the wrath of Team Rocket!",
"4": "You're about to experience the true terror of Team Rocket!", "4": "You're about to experience the true terror of Team Rocket!",
"5": "Hey, kid! Me am a Team Rocket member kind of guy!", "5": "Hey, kid! Me am a Team Rocket member kind of guy!",
"5_female": null "5_female": "Hey, kid! Me am a Team Rocket member kind of guy!"
}, },
"victory": { "victory": {
"1": "Team Rocket blasting off again!", "1": "Team Rocket blasting off again!",
@ -624,7 +624,7 @@
"1": "Huh? I lost?!", "1": "Huh? I lost?!",
"2": "I can't believe I lost! I even skipped lunch for this", "2": "I can't believe I lost! I even skipped lunch for this",
"3": "No way! You're just a kid!", "3": "No way! You're just a kid!",
"3_female": null, "3_female": "No way! You're just a kid!",
"4": "Urrrgh... I should've ducked into our hideout right away...", "4": "Urrrgh... I should've ducked into our hideout right away...",
"5": "You beat me... Do you think the boss will dock my pay for this?" "5": "You beat me... Do you think the boss will dock my pay for this?"
} }
@ -652,7 +652,7 @@
"3": "In the name of Team Galactic, I'll eliminate anyone who stands in our way!", "3": "In the name of Team Galactic, I'll eliminate anyone who stands in our way!",
"4": "Get ready to lose!", "4": "Get ready to lose!",
"5": "Hope you're ready for a cosmic beatdown!", "5": "Hope you're ready for a cosmic beatdown!",
"5_female": null "5_female": "Hope you're ready for a cosmic beatdown!"
}, },
"victory": { "victory": {
"1": "Shut down...", "1": "Shut down...",
@ -682,7 +682,7 @@
"encounter": { "encounter": {
"1": "Your Pokémon are no match for the elegance of Team Flare.", "1": "Your Pokémon are no match for the elegance of Team Flare.",
"2": "Hope you brought your sunglasses, because things are about to get bright!", "2": "Hope you brought your sunglasses, because things are about to get bright!",
"2_female": null, "2_female": "Hope you brought your sunglasses, because things are about to get bright!",
"3": "Team Flare will cleanse the world of imperfection!", "3": "Team Flare will cleanse the world of imperfection!",
"4": "Prepare to face the brilliance of Team Flare!", "4": "Prepare to face the brilliance of Team Flare!",
"5": "Fashion is most important to us!" "5": "Fashion is most important to us!"
@ -784,7 +784,7 @@
}, },
"defeat": { "defeat": {
"1": "Mark my words. Not being able to measure your own strength shows that you are still a child.", "1": "Mark my words. Not being able to measure your own strength shows that you are still a child.",
"1_female": null "1_female": "Mark my words. Not being able to measure your own strength shows that you are still a child."
} }
}, },
"rocket_boss_giovanni_2": { "rocket_boss_giovanni_2": {
@ -845,7 +845,7 @@
"galactic_boss_cyrus_1": { "galactic_boss_cyrus_1": {
"encounter": { "encounter": {
"1": "You were compelled to come here by such vacuous sentimentality.\n$I will make you regret paying heed to your heart!", "1": "You were compelled to come here by such vacuous sentimentality.\n$I will make you regret paying heed to your heart!",
"1_female": null "1_female": "You were compelled to come here by such vacuous sentimentality.\n$I will make you regret paying heed to your heart!"
}, },
"victory": { "victory": {
"1": "Interesting. And quite curious." "1": "Interesting. And quite curious."
@ -995,7 +995,7 @@
"misty": { "misty": {
"encounter": { "encounter": {
"1": "My policy is an all out offensive with Water-type Pokémon!", "1": "My policy is an all out offensive with Water-type Pokémon!",
"1_female": null, "1_female": "My policy is an all out offensive with Water-type Pokémon!",
"2": "Hiya, I'll show you the strength of my aquatic Pokémon!", "2": "Hiya, I'll show you the strength of my aquatic Pokémon!",
"3": "My dream was to go on a journey and battle powerful trainers…\nWill you be a sufficient challenge?" "3": "My dream was to go on a journey and battle powerful trainers…\nWill you be a sufficient challenge?"
}, },
@ -1013,14 +1013,14 @@
"lt_surge": { "lt_surge": {
"encounter": { "encounter": {
"1": "My Electric Pokémon saved me during the war! I'll show you how!", "1": "My Electric Pokémon saved me during the war! I'll show you how!",
"1_female": null, "1_female": "My Electric Pokémon saved me during the war! I'll show you how!",
"2": "Ten-hut! I'll shock you into surrender!", "2": "Ten-hut! I'll shock you into surrender!",
"3": "I'll zap you just like I do to all my enemies in battle!" "3": "I'll zap you just like I do to all my enemies in battle!"
}, },
"victory": { "victory": {
"1": "Whoa! Your team's the real deal, kid!", "1": "Whoa! Your team's the real deal, kid!",
"2": "Aaargh, you're strong! Even my electric tricks lost against you.", "2": "Aaargh, you're strong! Even my electric tricks lost against you.",
"2_female": null, "2_female": "Aaargh, you're strong! Even my electric tricks lost against you.",
"3": "That was an absolutely shocking loss!" "3": "That was an absolutely shocking loss!"
}, },
"defeat": { "defeat": {
@ -1045,7 +1045,7 @@
"defeat": { "defeat": {
"1": "I was afraid I would doze off…", "1": "I was afraid I would doze off…",
"2": "Oh my, it seems my Grass Pokémon overwhelmed you.", "2": "Oh my, it seems my Grass Pokémon overwhelmed you.",
"2_female": null, "2_female": "Oh my, it seems my Grass Pokémon overwhelmed you.",
"3": "That battle was such a soothing experience.", "3": "That battle was such a soothing experience.",
"4": "Oh… Is that all?" "4": "Oh… Is that all?"
} }
@ -1106,7 +1106,7 @@
"1": "I, the leader of Team Rocket, will make you feel a world of pain!", "1": "I, the leader of Team Rocket, will make you feel a world of pain!",
"2": "My training here will be vital before I am to face my old associates again.", "2": "My training here will be vital before I am to face my old associates again.",
"3": "I do not think you are prepared for the level of failure you are about to experience!", "3": "I do not think you are prepared for the level of failure you are about to experience!",
"3_female": null "3_female": "I do not think you are prepared for the level of failure you are about to experience!"
}, },
"victory": { "victory": {
"1": "WHAT! Me, lose?! There is nothing I wish to say to you!", "1": "WHAT! Me, lose?! There is nothing I wish to say to you!",
@ -1139,7 +1139,7 @@
"brawly": { "brawly": {
"encounter": { "encounter": {
"1": "Oh man, a challenger!\nLet's see what you can do!", "1": "Oh man, a challenger!\nLet's see what you can do!",
"1_female": null, "1_female": "Oh man, a challenger!\nLet's see what you can do!",
"2": "You seem like a big splash.\nLet's battle!", "2": "You seem like a big splash.\nLet's battle!",
"3": "Time to create a storm!\nLet's go!" "3": "Time to create a storm!\nLet's go!"
}, },
@ -1167,7 +1167,7 @@
}, },
"defeat": { "defeat": {
"1": "Recharge your batteries and challenge me again sometime!\nWahahahaha!", "1": "Recharge your batteries and challenge me again sometime!\nWahahahaha!",
"1_female": null, "1_female": "Recharge your batteries and challenge me again sometime!\nWahahahaha!",
"2": "I hope you found our battle electrifying!\nWahahahaha!", "2": "I hope you found our battle electrifying!\nWahahahaha!",
"3": "Aren't you shocked I won?\nWahahahaha!" "3": "Aren't you shocked I won?\nWahahahaha!"
} }
@ -1214,7 +1214,7 @@
}, },
"victory": { "victory": {
"1": "You're the first Trainer I've seen with more grace than I.\nExcellently played.", "1": "You're the first Trainer I've seen with more grace than I.\nExcellently played.",
"1_female": null, "1_female": "You're the first Trainer I've seen with more grace than I.\nExcellently played.",
"2": "Oh, my Flying Pokémon have plummeted!\nVery well.", "2": "Oh, my Flying Pokémon have plummeted!\nVery well.",
"3": "Though I may have fallen, my Pokémon will continue to fly!" "3": "Though I may have fallen, my Pokémon will continue to fly!"
}, },
@ -1227,7 +1227,7 @@
"tate": { "tate": {
"encounter": { "encounter": {
"1": "Hehehe…\nWere you surprised to see me without my sister?", "1": "Hehehe…\nWere you surprised to see me without my sister?",
"1_female": null, "1_female": "Hehehe…\nWere you surprised to see me without my sister?",
"2": "I can see what you're thinking…\nYou want to battle!", "2": "I can see what you're thinking…\nYou want to battle!",
"3": "How can you defeat someone…\nWho knows your every move?" "3": "How can you defeat someone…\nWho knows your every move?"
}, },
@ -1245,7 +1245,7 @@
"liza": { "liza": {
"encounter": { "encounter": {
"1": "Fufufu…\nWere you surprised to see me without my brother?", "1": "Fufufu…\nWere you surprised to see me without my brother?",
"1_female": null, "1_female": "Fufufu…\nWere you surprised to see me without my brother?",
"2": "I can determine what you desire…\nYou want to battle, don't you?", "2": "I can determine what you desire…\nYou want to battle, don't you?",
"3": "How can you defeat someone…\nWho's one with their Pokémon?" "3": "How can you defeat someone…\nWho's one with their Pokémon?"
}, },
@ -1317,10 +1317,10 @@
"nessa": { "nessa": {
"encounter": { "encounter": {
"1": "No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.", "1": "No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.",
"1_female": null, "1_female": "No matter what kind of plan your refined mind may be plotting, my partner and I will be sure to sink it.",
"2": "I'm not here to chat. I'm here to win!", "2": "I'm not here to chat. I'm here to win!",
"3": "This is a little gift from my Pokémon… I hope you can take it!", "3": "This is a little gift from my Pokémon… I hope you can take it!",
"3_female": null "3_female": "This is a little gift from my Pokémon… I hope you can take it!"
}, },
"victory": { "victory": {
"1": "You and your Pokémon are just too much…", "1": "You and your Pokémon are just too much…",
@ -1341,7 +1341,7 @@
}, },
"victory": { "victory": {
"1": "You… You're pretty good, huh?", "1": "You… You're pretty good, huh?",
"1_female": null, "1_female": "You… You're pretty good, huh?",
"2": "If you find Gordie around, be sure to give him a right trashing, would you?", "2": "If you find Gordie around, be sure to give him a right trashing, would you?",
"3": "I think you took breaking the ice a little too literally…" "3": "I think you took breaking the ice a little too literally…"
}, },
@ -1355,12 +1355,12 @@
"encounter": { "encounter": {
"1": "You look strong! Shoots! Let's start!", "1": "You look strong! Shoots! Let's start!",
"2": "I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.", "2": "I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.",
"2_female": null, "2_female": "I'm strong like the ocean's wide. You're gonna get swept away, fo' sho'.",
"3": "Oh ho, so I'm facing you! That's off the wall." "3": "Oh ho, so I'm facing you! That's off the wall."
}, },
"victory": { "victory": {
"1": "You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!", "1": "You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!",
"1_female": null, "1_female": "You totally rocked that! You're raising some wicked Pokémon. You got this Trainer thing down!",
"2": "You don't just look strong, you're strong fo' reals! Eh, I was swept away, too!", "2": "You don't just look strong, you're strong fo' reals! Eh, I was swept away, too!",
"3": "You're strong as a gnarly wave!" "3": "You're strong as a gnarly wave!"
}, },
@ -1373,7 +1373,7 @@
"shauntal": { "shauntal": {
"encounter": { "encounter": {
"1": "Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.", "1": "Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.",
"1_female": null, "1_female": "Excuse me. You're a challenger, right?\nI'm the Elite Four's Ghost-type Pokémon user, Shauntal, and I shall be your opponent.",
"2": "I absolutely love writing about Trainers who come here and the Pokémon they train.\nCould I use you and your Pokémon as a subject?", "2": "I absolutely love writing about Trainers who come here and the Pokémon they train.\nCould I use you and your Pokémon as a subject?",
"3": "Every person who works with Pokémon has a story to tell.\nWhat story is about to be told?" "3": "Every person who works with Pokémon has a story to tell.\nWhat story is about to be told?"
}, },
@ -1391,7 +1391,7 @@
"marshal": { "marshal": {
"encounter": { "encounter": {
"1": "My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!", "1": "My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!",
"1_female": null, "1_female": "My mentor, Alder, sees your potential as a Trainer and is taking an interest in you.\nIt is my intention to test you--to take you to the limits of your strength. Kiai!",
"2": "Victory, decisive victory, is my intention! Challenger, here I come!", "2": "Victory, decisive victory, is my intention! Challenger, here I come!",
"3": "In myself, I seek to develop the strength of a fighter and shatter any weakness in myself!\nPrevailing with the force of my convictions!" "3": "In myself, I seek to develop the strength of a fighter and shatter any weakness in myself!\nPrevailing with the force of my convictions!"
}, },
@ -1411,7 +1411,7 @@
"1": "You remind me of an old friend. That makes me excited about this Pokémon battle!", "1": "You remind me of an old friend. That makes me excited about this Pokémon battle!",
"2": "Pokémon battles have no meaning if you don't think why you battle.\n$Or better said, it makes battling together with Pokémon meaningless.", "2": "Pokémon battles have no meaning if you don't think why you battle.\n$Or better said, it makes battling together with Pokémon meaningless.",
"3": "My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you.", "3": "My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you.",
"3_female": null "3_female": "My name's Cheren! I'm a Gym Leader and a teacher! Pleasure to meet you."
}, },
"victory": { "victory": {
"1": "Thank you! I saw what was missing in me.", "1": "Thank you! I saw what was missing in me.",
@ -1427,65 +1427,65 @@
"chili": { "chili": {
"encounter": { "encounter": {
"1": "Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!", "1": "Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!",
"1_female": null, "1_female": "Yeeeeooow! Time to play with FIRE!! I'm the strongest of us brothers!",
"2": "Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!", "2": "Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!",
"2_female": null, "2_female": "Ta-da! The Fire-type scorcher Chili--that's me--will be your opponent!",
"3": "I'm going to show you what me and my blazing Fire types can do!", "3": "I'm going to show you what me and my blazing Fire types can do!",
"3_female": null "3_female": "I'm going to show you what me and my blazing Fire types can do!"
}, },
"victory": { "victory": {
"1": "You got me. I am… burned… out…", "1": "You got me. I am… burned… out…",
"1_female": null, "1_female": "You got me. I am… burned… out…",
"2": "Whoa ho! You're on fire!", "2": "Whoa ho! You're on fire!",
"2_female": null, "2_female": "Whoa ho! You're on fire!",
"3": "Augh! You got me!" "3": "Augh! You got me!"
}, },
"defeat": { "defeat": {
"1": "I'm on fire! Play with me, and you'll get burned!", "1": "I'm on fire! Play with me, and you'll get burned!",
"1_female": null, "1_female": "I'm on fire! Play with me, and you'll get burned!",
"2": "When you play with fire, you get burned!", "2": "When you play with fire, you get burned!",
"3": "I mean, c'mon, your opponent was me! You didn't have a chance!", "3": "I mean, c'mon, your opponent was me! You didn't have a chance!",
"3_female": null "3_female": "I mean, c'mon, your opponent was me! You didn't have a chance!"
} }
}, },
"cilan": { "cilan": {
"encounter": { "encounter": {
"1": "Nothing personal... No hard feelings... Me and my Grass-type Pokémon will...\n$Um... We're gonna battle come what may.", "1": "Nothing personal... No hard feelings... Me and my Grass-type Pokémon will...\n$Um... We're gonna battle come what may.",
"1_female": null, "1_female": "Nothing personal... No hard feelings... Me and my Grass-type Pokémon will...\n$Um... We're gonna battle come what may.",
"2": "So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.", "2": "So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.",
"2_female": null, "2_female": "So, um, if you're OK with me, I'll, um, put everything I've got into being, er, you know, your opponent.",
"3": "OK… So, um, I'm Cilan, I like Grass-type Pokémon.", "3": "OK… So, um, I'm Cilan, I like Grass-type Pokémon.",
"3_female": null "3_female": "OK… So, um, I'm Cilan, I like Grass-type Pokémon."
}, },
"victory": { "victory": {
"1": "Er… Is it over now?", "1": "Er… Is it over now?",
"1_female": null, "1_female": "Er… Is it over now?",
"2": "…What a surprise. You are very strong, aren't you? \n$I guess my brothers wouldn't have been able to defeat you either…", "2": "…What a surprise. You are very strong, aren't you? \n$I guess my brothers wouldn't have been able to defeat you either…",
"2_female": null, "2_female": "…What a surprise. You are very strong, aren't you? \n$I guess my brothers wouldn't have been able to defeat you either…",
"3": "…Huh. Looks like my timing was, um, off?" "3": "…Huh. Looks like my timing was, um, off?"
}, },
"defeat": { "defeat": {
"1": "Huh? Did I win?", "1": "Huh? Did I win?",
"1_female": null, "1_female": "Huh? Did I win?",
"2": "I guess… \n$I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.", "2": "I guess… \n$I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.",
"2_female": null, "2_female": "I guess… \n$I suppose I won, because I've been competing with my brothers Chili and Cress, and we all were able to get tougher.",
"3": "It…it was quite a thrilling experience…", "3": "It…it was quite a thrilling experience…",
"3_female": null "3_female": "It…it was quite a thrilling experience…"
} }
}, },
"roark": { "roark": {
"encounter": { "encounter": {
"1": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!", "1": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!",
"1_female": null, "1_female": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!",
"2": "Here goes! These are my rocking Pokémon, my pride and joy!", "2": "Here goes! These are my rocking Pokémon, my pride and joy!",
"3": "Rock-type Pokémon are simply the best!", "3": "Rock-type Pokémon are simply the best!",
"4": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!", "4": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!",
"4_female": null "4_female": "I need to see your potential as a Trainer. And, I'll need to see the toughness of the Pokémon that battle with you!"
}, },
"victory": { "victory": {
"1": "W-what? That can't be! My buffed-up Pokémon!", "1": "W-what? That can't be! My buffed-up Pokémon!",
"2": "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.", "2": "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.",
"2_female": null, "2_female": "…We lost control there. Next time I'd like to challenge you to a Fossil-digging race underground.",
"3": "With skill like yours, it's natural for you to win.", "3": "With skill like yours, it's natural for you to win.",
"4": "Wh-what?! It can't be! Even that wasn't enough?", "4": "Wh-what?! It can't be! Even that wasn't enough?",
"5": "I blew it." "5": "I blew it."
@ -1508,7 +1508,7 @@
"victory": { "victory": {
"1": "I'm not good enough yet…", "1": "I'm not good enough yet…",
"2": "I see… Your journey has taken you to far-away places and you have witnessed much more than I.\n$I envy you for that…", "2": "I see… Your journey has taken you to far-away places and you have witnessed much more than I.\n$I envy you for that…",
"2_female": null, "2_female": "I see… Your journey has taken you to far-away places and you have witnessed much more than I.\n$I envy you for that…",
"3": "How is this possible…", "3": "How is this possible…",
"4": "I don't think our potentials are so different.\n$But you seem to have something more than that… So be it.", "4": "I don't think our potentials are so different.\n$But you seem to have something more than that… So be it.",
"5": "Guess I need more training.", "5": "Guess I need more training.",
@ -1568,13 +1568,13 @@
}, },
"defeat": { "defeat": {
"1": "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?", "1": "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?",
"1_female": null "1_female": "Heh heh! Don't mind me, just scooping up a W over here. I get it if you're upset, but don't go full Kieran on me, OK?"
} }
}, },
"ramos": { "ramos": {
"encounter": { "encounter": {
"1": "Did yeh enjoy the garden playground I made with all these sturdy plants o' mine?\n$Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?", "1": "Did yeh enjoy the garden playground I made with all these sturdy plants o' mine?\n$Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?",
"1_female": null "1_female": "Did yeh enjoy the garden playground I made with all these sturdy plants o' mine?\n$Their strength is a sign o' my strength as a gardener and a Gym Leader! Yeh sure yer up to facing all that?"
}, },
"victory": { "victory": {
"1": "Yeh believe in yer Pokémon… And they believe in yeh, too… It was a fine battle, sprout." "1": "Yeh believe in yer Pokémon… And they believe in yeh, too… It was a fine battle, sprout."
@ -1605,7 +1605,7 @@
"victory": { "victory": {
"1": "I must say, I'm warmed up to you! I might even admire you a little.", "1": "I must say, I'm warmed up to you! I might even admire you a little.",
"2": "Wow! You're great! You've earned my respect! \n$I think your focus and will bowled us over totally. ", "2": "Wow! You're great! You've earned my respect! \n$I think your focus and will bowled us over totally. ",
"2_female": null "2_female": "Wow! You're great! You've earned my respect! \n$I think your focus and will bowled us over totally. "
}, },
"defeat": { "defeat": {
"1": "I sensed your will to win, but I don't lose!", "1": "I sensed your will to win, but I don't lose!",
@ -1618,7 +1618,7 @@
}, },
"victory": { "victory": {
"1": "Amazing! You're very good, aren't you?", "1": "Amazing! You're very good, aren't you?",
"1_female": null "1_female": "Amazing! You're very good, aren't you?"
}, },
"defeat": { "defeat": {
"1": "Yes! My Pokémon and I are perfectly good!" "1": "Yes! My Pokémon and I are perfectly good!"
@ -1660,7 +1660,7 @@
"clay": { "clay": {
"encounter": { "encounter": {
"1": "Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!", "1": "Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!",
"1_female": null "1_female": "Harrumph! Kept me waitin', didn't ya, kid? All right, time to see what ya can do!"
}, },
"victory": { "victory": {
"1": "Man oh man… It feels good to go all out and still be defeated!" "1": "Man oh man… It feels good to go all out and still be defeated!"
@ -1675,7 +1675,7 @@
}, },
"victory": { "victory": {
"1": "Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!", "1": "Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!",
"1_female": null "1_female": "Vaultin' Veluza! Yer a lively one, aren't ya! A little TOO lively, if I do say so myself!"
}, },
"defeat": { "defeat": {
"1": "You come back to see me again now, ya hear?" "1": "You come back to see me again now, ya hear?"
@ -1742,7 +1742,7 @@
}, },
"victory": { "victory": {
"1": "Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. \n$I find much joy in having met you and your Pokémon. You have proven yourself worthy.", "1": "Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. \n$I find much joy in having met you and your Pokémon. You have proven yourself worthy.",
"1_female": null "1_female": "Bravo. I realize now your authenticity and magnificence as a Pokémon Trainer. \n$I find much joy in having met you and your Pokémon. You have proven yourself worthy."
}, },
"defeat": { "defeat": {
"1": "A grand illusion!" "1": "A grand illusion!"
@ -1751,14 +1751,14 @@
"lorelei": { "lorelei": {
"encounter": { "encounter": {
"1": "No one can best me when it comes to icy Pokémon! Freezing moves are powerful!\n$Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?", "1": "No one can best me when it comes to icy Pokémon! Freezing moves are powerful!\n$Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?",
"1_female": null "1_female": "No one can best me when it comes to icy Pokémon! Freezing moves are powerful!\n$Your Pokémon will be at my mercy when they are frozen solid! Hahaha! Are you ready?"
}, },
"victory": { "victory": {
"1": "How dare you!" "1": "How dare you!"
}, },
"defeat": { "defeat": {
"1": "There's nothing you can do once you're frozen.", "1": "There's nothing you can do once you're frozen.",
"1_female": null "1_female": "There's nothing you can do once you're frozen."
} }
}, },
"will": { "will": {
@ -1775,11 +1775,11 @@
"malva": { "malva": {
"encounter": { "encounter": {
"1": "I feel like my heart might just burst into flames. \n$I'm burning up with my hatred for you, runt!", "1": "I feel like my heart might just burst into flames. \n$I'm burning up with my hatred for you, runt!",
"1_female": null "1_female": "I feel like my heart might just burst into flames. \n$I'm burning up with my hatred for you, runt!"
}, },
"victory": { "victory": {
"1": "What news… So a new challenger has defeated Malva!", "1": "What news… So a new challenger has defeated Malva!",
"1_female": null "1_female": "What news… So a new challenger has defeated Malva!"
}, },
"defeat": { "defeat": {
"1": "I am delighted! Yes, delighted that I could squash you beneath my heel." "1": "I am delighted! Yes, delighted that I could squash you beneath my heel."
@ -1802,7 +1802,7 @@
}, },
"victory": { "victory": {
"1": "I certainly found an interesting Trainer to face!", "1": "I certainly found an interesting Trainer to face!",
"1_female": null "1_female": "I certainly found an interesting Trainer to face!"
}, },
"defeat": { "defeat": {
"1": "Ahaha. What an interesting battle." "1": "Ahaha. What an interesting battle."
@ -1814,11 +1814,11 @@
}, },
"victory": { "victory": {
"1": "Not bad, kiddo.", "1": "Not bad, kiddo.",
"1_female": null "1_female": "Not bad, kiddo."
}, },
"defeat": { "defeat": {
"1": "Nahahaha! You really are something else, kiddo!", "1": "Nahahaha! You really are something else, kiddo!",
"1_female": null "1_female": "Nahahaha! You really are something else, kiddo!"
} }
}, },
"bruno": { "bruno": {
@ -1838,7 +1838,7 @@
}, },
"victory": { "victory": {
"1": "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win.", "1": "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win.",
"1_female": null "1_female": "Whoa, amazing! You're an expert on Pokémon!\nMy research isn't complete yet. OK, you win."
}, },
"defeat": { "defeat": {
"1": "Thanks! Thanks to our battle, I was also able to make progress in my research!" "1": "Thanks! Thanks to our battle, I was also able to make progress in my research!"
@ -1869,11 +1869,11 @@
"lenora": { "lenora": {
"encounter": { "encounter": {
"1": "Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!", "1": "Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!",
"1_female": null "1_female": "Well then, challenger, I'm going to research how you battle with the Pokémon you've so lovingly raised!"
}, },
"victory": { "victory": {
"1": "My theory about you was correct. You're more than just talented… You're motivated! I salute you!", "1": "My theory about you was correct. You're more than just talented… You're motivated! I salute you!",
"1_female": null "1_female": "My theory about you was correct. You're more than just talented… You're motivated! I salute you!"
}, },
"defeat": { "defeat": {
"1": "Ah ha ha! If you lose, make sure to analyze why, and use that knowledge in your next battle!" "1": "Ah ha ha! If you lose, make sure to analyze why, and use that knowledge in your next battle!"
@ -1899,7 +1899,7 @@
}, },
"defeat": { "defeat": {
"1": "Hey, c'mon! Get serious! You gotta put more out there!", "1": "Hey, c'mon! Get serious! You gotta put more out there!",
"1_female": null "1_female": "Hey, c'mon! Get serious! You gotta put more out there!"
} }
}, },
"olivia": { "olivia": {
@ -1938,7 +1938,7 @@
"flint": { "flint": {
"encounter": { "encounter": {
"1": "Hope you're warmed up, cause here comes the Big Bang!", "1": "Hope you're warmed up, cause here comes the Big Bang!",
"1_female": null "1_female": "Hope you're warmed up, cause here comes the Big Bang!"
}, },
"victory": { "victory": {
"1": "Incredible! Your moves are so hot, they make mine look lukewarm!" "1": "Incredible! Your moves are so hot, they make mine look lukewarm!"
@ -1961,7 +1961,7 @@
"caitlin": { "caitlin": {
"encounter": { "encounter": {
"1": "It's me who appeared when the flower opened up. You who have been waiting…\n$You look like a Pokémon Trainer with refined strength and deepened kindness. \n$What I look for in my opponent is superb strength… \n$Please unleash your power to the fullest!", "1": "It's me who appeared when the flower opened up. You who have been waiting…\n$You look like a Pokémon Trainer with refined strength and deepened kindness. \n$What I look for in my opponent is superb strength… \n$Please unleash your power to the fullest!",
"1_female": null "1_female": "It's me who appeared when the flower opened up. You who have been waiting…\n$You look like a Pokémon Trainer with refined strength and deepened kindness. \n$What I look for in my opponent is superb strength… \n$Please unleash your power to the fullest!"
}, },
"victory": { "victory": {
"1": "My Pokémon and I learned so much! I offer you my thanks." "1": "My Pokémon and I learned so much! I offer you my thanks."
@ -1984,15 +1984,15 @@
"wikstrom": { "wikstrom": {
"encounter": { "encounter": {
"1": "Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! \n$Let the battle begin! En garde!", "1": "Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! \n$Let the battle begin! En garde!",
"1_female": null "1_female": "Well met, young challenger! Verily am I the famed blade of hardened steel, Duke Wikstrom! \n$Let the battle begin! En garde!"
}, },
"victory": { "victory": {
"1": "Glorious! The trust that you share with your honorable Pokémon surpasses even mine!", "1": "Glorious! The trust that you share with your honorable Pokémon surpasses even mine!",
"1_female": null "1_female": "Glorious! The trust that you share with your honorable Pokémon surpasses even mine!"
}, },
"defeat": { "defeat": {
"1": "What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! \n$Winning against such a worthy opponent doth give my soul wings--thus do I soar!", "1": "What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! \n$Winning against such a worthy opponent doth give my soul wings--thus do I soar!",
"1_female": null "1_female": "What manner of magic is this? My heart, it doth hammer ceaselessly in my breast! \n$Winning against such a worthy opponent doth give my soul wings--thus do I soar!"
} }
}, },
"acerola": { "acerola": {
@ -2024,14 +2024,14 @@
}, },
"victory": { "victory": {
"1": "You got me. You are magnificent!", "1": "You got me. You are magnificent!",
"1_female": null, "1_female": "You got me. You are magnificent!",
"2": "I never expected another trainer to beat me… I'm surprised.", "2": "I never expected another trainer to beat me… I'm surprised.",
"2_female": null "2_female": "I never expected another trainer to beat me… I'm surprised."
}, },
"defeat": { "defeat": {
"1": "That was close. Want to try again?", "1": "That was close. Want to try again?",
"2": "It's not that you are weak. Don't let it bother you.", "2": "It's not that you are weak. Don't let it bother you.",
"2_female": null "2_female": "It's not that you are weak. Don't let it bother you."
} }
}, },
"karen": { "karen": {
@ -2057,7 +2057,7 @@
}, },
"victory": { "victory": {
"1": "The power of Grass has wilted… What an incredible Challenger!", "1": "The power of Grass has wilted… What an incredible Challenger!",
"1_female": null "1_female": "The power of Grass has wilted… What an incredible Challenger!"
}, },
"defeat": { "defeat": {
"1": "This'll really leave you in shock and awe." "1": "This'll really leave you in shock and awe."
@ -2077,7 +2077,7 @@
"drasna": { "drasna": {
"encounter": { "encounter": {
"1": "You must be a strong Trainer. Yes, quite strong indeed…\n$That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!", "1": "You must be a strong Trainer. Yes, quite strong indeed…\n$That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!",
"1_female": null "1_female": "You must be a strong Trainer. Yes, quite strong indeed…\n$That's just wonderful news! Facing opponents like you and your team will make my Pokémon grow like weeds!"
}, },
"victory": { "victory": {
"1": "Oh, dear me. That sure was a quick battle… I do hope you'll come back again sometime!" "1": "Oh, dear me. That sure was a quick battle… I do hope you'll come back again sometime!"
@ -2111,7 +2111,7 @@
"blue": { "blue": {
"encounter": { "encounter": {
"1": "You must be pretty good to get this far.", "1": "You must be pretty good to get this far.",
"1_female": null "1_female": "You must be pretty good to get this far."
}, },
"victory": { "victory": {
"1": "I've only lost to him and now to you… Him? Hee, hee…" "1": "I've only lost to him and now to you… Him? Hee, hee…"
@ -2159,7 +2159,7 @@
}, },
"victory": { "victory": {
"1": "This is the emergence of a new Champion.", "1": "This is the emergence of a new Champion.",
"1_female": null "1_female": "This is the emergence of a new Champion."
}, },
"defeat": { "defeat": {
"1": "I successfully defended my Championship." "1": "I successfully defended my Championship."
@ -2248,7 +2248,7 @@
}, },
"victory": { "victory": {
"1": "Waaah! Waaah! You're so mean!", "1": "Waaah! Waaah! You're so mean!",
"1_female": null "1_female": "Waaah! Waaah! You're so mean!"
}, },
"defeat": { "defeat": {
"1": "And that's that!" "1": "And that's that!"
@ -2257,7 +2257,7 @@
"chuck": { "chuck": {
"encounter": { "encounter": {
"1": "Hah! You want to challenge me? Are you brave or just ignorant?", "1": "Hah! You want to challenge me? Are you brave or just ignorant?",
"1_female": null "1_female": "Hah! You want to challenge me? Are you brave or just ignorant?"
}, },
"victory": { "victory": {
"1": "You're strong! Would you please make me your apprentice?" "1": "You're strong! Would you please make me your apprentice?"
@ -2269,7 +2269,7 @@
"katy": { "katy": {
"encounter": { "encounter": {
"1": "Don't let your guard down unless you would like to find yourself knocked off your feet!", "1": "Don't let your guard down unless you would like to find yourself knocked off your feet!",
"1_female": null "1_female": "Don't let your guard down unless you would like to find yourself knocked off your feet!"
}, },
"victory": { "victory": {
"1": "All of my sweet little Pokémon dropped like flies!" "1": "All of my sweet little Pokémon dropped like flies!"
@ -2303,7 +2303,7 @@
"maylene": { "maylene": {
"encounter": { "encounter": {
"1": "I've come to challenge you now, and I won't hold anything back. \n$Please prepare yourself for battle!", "1": "I've come to challenge you now, and I won't hold anything back. \n$Please prepare yourself for battle!",
"1_female": null "1_female": "I've come to challenge you now, and I won't hold anything back. \n$Please prepare yourself for battle!"
}, },
"victory": { "victory": {
"1": "I admit defeat…" "1": "I admit defeat…"
@ -2326,7 +2326,7 @@
"byron": { "byron": {
"encounter": { "encounter": {
"1": "Trainer! You're young, just like my son, Roark. \n$With more young Trainers taking charge, the future of Pokémon is bright! \n$So, as a wall for young people, I'll take your challenge!", "1": "Trainer! You're young, just like my son, Roark. \n$With more young Trainers taking charge, the future of Pokémon is bright! \n$So, as a wall for young people, I'll take your challenge!",
"1_female": null "1_female": "Trainer! You're young, just like my son, Roark. \n$With more young Trainers taking charge, the future of Pokémon is bright! \n$So, as a wall for young people, I'll take your challenge!"
}, },
"victory": { "victory": {
"1": "Hmm! My sturdy Pokémon--defeated!" "1": "Hmm! My sturdy Pokémon--defeated!"
@ -2349,7 +2349,7 @@
"volkner": { "volkner": {
"encounter": { "encounter": {
"1": "Since you've come this far, you must be quite strong…\n$I hope you're the Trainer who'll make me remember how fun it is to battle!", "1": "Since you've come this far, you must be quite strong…\n$I hope you're the Trainer who'll make me remember how fun it is to battle!",
"1_female": null "1_female": "Since you've come this far, you must be quite strong…\n$I hope you're the Trainer who'll make me remember how fun it is to battle!"
}, },
"victory": { "victory": {
"1": "You've got me beat…\n$Your desire and the noble way your Pokémon battled for you… \n$I even felt thrilled during our match. That was a very good battle." "1": "You've got me beat…\n$Your desire and the noble way your Pokémon battled for you… \n$I even felt thrilled during our match. That was a very good battle."
@ -2452,7 +2452,7 @@
"valerie": { "valerie": {
"encounter": { "encounter": {
"1": "Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. \n$Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. \n$The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong.", "1": "Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. \n$Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. \n$The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong.",
"1_female": null "1_female": "Oh, if it isn't a young Trainer… It is lovely to get to meet you like this. \n$Then I suppose you have earned yourself the right to a battle, as a reward for your efforts. \n$The elusive Fairy may appear frail as the breeze and delicate as a bloom, but it is strong."
}, },
"victory": { "victory": {
"1": "I hope that you will find things worth smiling about tomorrow…" "1": "I hope that you will find things worth smiling about tomorrow…"
@ -2500,7 +2500,7 @@
}, },
"victory": { "victory": {
"1": "Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon.", "1": "Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon.",
"1_female": null "1_female": "Your pink is still lacking, but you're an excellent Trainer with excellent Pokémon."
}, },
"defeat": { "defeat": {
"1": "Too bad for you, I guess." "1": "Too bad for you, I guess."
@ -2509,7 +2509,7 @@
"bede": { "bede": {
"encounter": { "encounter": {
"1": "I suppose I should prove beyond doubt just how pathetic you are and how strong I am.", "1": "I suppose I should prove beyond doubt just how pathetic you are and how strong I am.",
"1_female": null "1_female": "I suppose I should prove beyond doubt just how pathetic you are and how strong I am."
}, },
"victory": { "victory": {
"1": "I see… Well, that's fine. I wasn't really trying all that hard anyway." "1": "I see… Well, that's fine. I wasn't really trying all that hard anyway."
@ -2554,7 +2554,7 @@
"brassius": { "brassius": {
"encounter": { "encounter": {
"1": "I assume you are ready? Let our collaborative work of art begin!", "1": "I assume you are ready? Let our collaborative work of art begin!",
"1_female": null "1_female": "I assume you are ready? Let our collaborative work of art begin!"
}, },
"victory": { "victory": {
"1": "Ahhh…vant-garde!" "1": "Ahhh…vant-garde!"
@ -2566,11 +2566,11 @@
"iono": { "iono": {
"encounter": { "encounter": {
"1": "How're ya feelin' about this battle?\n$...\n$Let's get this show on the road! How strong is our challenger? \n$I 'unno! Let's find out together!", "1": "How're ya feelin' about this battle?\n$...\n$Let's get this show on the road! How strong is our challenger? \n$I 'unno! Let's find out together!",
"1_female": null "1_female": "How're ya feelin' about this battle?\n$...\n$Let's get this show on the road! How strong is our challenger? \n$I 'unno! Let's find out together!"
}, },
"victory": { "victory": {
"1": "You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!", "1": "You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!",
"1_female": null "1_female": "You're as flashy and bright as a 10,000,000-volt Thunderbolt, friendo!"
}, },
"defeat": { "defeat": {
"1": "Your eyeballs are MINE!" "1": "Your eyeballs are MINE!"
@ -2593,7 +2593,7 @@
}, },
"victory": { "victory": {
"1": "You're cool, my friend—you move my SOUL!", "1": "You're cool, my friend—you move my SOUL!",
"1_female": null "1_female": "You're cool, my friend—you move my SOUL!"
}, },
"defeat": { "defeat": {
"1": "Later, baby!" "1": "Later, baby!"
@ -2627,9 +2627,9 @@
"nessa_elite": { "nessa_elite": {
"encounter": { "encounter": {
"1": "The tides are turning in my favor. Ready to get swept away?", "1": "The tides are turning in my favor. Ready to get swept away?",
"1_female": null, "1_female": "The tides are turning in my favor. Ready to get swept away?",
"2": "Let's make some waves with this battle! I hope you're prepared!", "2": "Let's make some waves with this battle! I hope you're prepared!",
"2_female": null "2_female": "Let's make some waves with this battle! I hope you're prepared!"
}, },
"victory": { "victory": {
"1": "You navigated those waters perfectly... Well done!", "1": "You navigated those waters perfectly... Well done!",
@ -2657,7 +2657,7 @@
"allister_elite": { "allister_elite": {
"encounter": { "encounter": {
"1": "Shadows fall... Are you ready to face your fears?", "1": "Shadows fall... Are you ready to face your fears?",
"1_female": null, "1_female": "Shadows fall... Are you ready to face your fears?",
"2": "Let's see if you can handle the darkness that I command." "2": "Let's see if you can handle the darkness that I command."
}, },
"victory": { "victory": {
@ -2681,7 +2681,7 @@
"defeat": { "defeat": {
"1": "Another storm weathered, another victory claimed! Well fought!", "1": "Another storm weathered, another victory claimed! Well fought!",
"2": "You got caught in my storm! Better luck next time!", "2": "You got caught in my storm! Better luck next time!",
"2_female": null "2_female": "You got caught in my storm! Better luck next time!"
} }
}, },
"alder": { "alder": {

View File

@ -1,42 +1,9 @@
import { BattlerIndex } from "#app/battle.js";
import { TrickRoomTag } from "#app/data/arena-tag.js";
import { Stat } from "#app/enums/stat.js";
import Pokemon from "#app/field/pokemon.js";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "./battle-phase";
import * as Utils from "#app/utils.js"; import Pokemon from "#app/field/pokemon";
type PokemonFunc = (pokemon: Pokemon) => void; type PokemonFunc = (pokemon: Pokemon) => void;
export abstract class FieldPhase extends BattlePhase { export abstract class FieldPhase extends BattlePhase {
getOrder(): BattlerIndex[] {
const playerField = this.scene.getPlayerField().filter(p => p.isActive()) as Pokemon[];
const enemyField = this.scene.getEnemyField().filter(p => p.isActive()) as Pokemon[];
// We shuffle the list before sorting so speed ties produce random results
let orderedTargets: Pokemon[] = playerField.concat(enemyField);
// We seed it with the current turn to prevent an inconsistency where it
// was varying based on how long since you last reloaded
this.scene.executeWithSeedOffset(() => {
orderedTargets = Utils.randSeedShuffle(orderedTargets);
}, this.scene.currentBattle.turn, this.scene.waveSeed);
orderedTargets.sort((a: Pokemon, b: Pokemon) => {
const aSpeed = a?.getBattleStat(Stat.SPD) || 0;
const bSpeed = b?.getBattleStat(Stat.SPD) || 0;
return bSpeed - aSpeed;
});
const speedReversed = new Utils.BooleanHolder(false);
this.scene.arena.applyTags(TrickRoomTag, speedReversed);
if (speedReversed.value) {
orderedTargets = orderedTargets.reverse();
}
return orderedTargets.map(t => t.getFieldIndex() + (!t.isPlayer() ? BattlerIndex.ENEMY : 0));
}
executeForAll(func: PokemonFunc): void { executeForAll(func: PokemonFunc): void {
const field = this.scene.getField(true).filter(p => p.summonData); const field = this.scene.getField(true).filter(p => p.summonData);
field.forEach(pokemon => func(pokemon)); field.forEach(pokemon => func(pokemon));

View File

@ -1,12 +1,12 @@
import BattleScene from "#app/battle-scene.js"; import BattleScene from "#app/battle-scene";
import { applyAbAttrs, BypassSpeedChanceAbAttr, PreventBypassSpeedChanceAbAttr, ChangeMovePriorityAbAttr } from "#app/data/ability.js"; import { applyAbAttrs, BypassSpeedChanceAbAttr, PreventBypassSpeedChanceAbAttr, ChangeMovePriorityAbAttr } from "#app/data/ability";
import { allMoves, applyMoveAttrs, IncrementMovePriorityAttr, MoveHeaderAttr } from "#app/data/move.js"; import { allMoves, applyMoveAttrs, IncrementMovePriorityAttr, MoveHeaderAttr } from "#app/data/move";
import { Abilities } from "#app/enums/abilities.js"; import { Abilities } from "#app/enums/abilities";
import { Stat } from "#app/enums/stat.js"; import { Stat } from "#app/enums/stat";
import { PokemonMove } from "#app/field/pokemon.js"; import Pokemon, { PokemonMove } from "#app/field/pokemon";
import { BypassSpeedChanceModifier } from "#app/modifier/modifier.js"; import { BypassSpeedChanceModifier } from "#app/modifier/modifier";
import { Command } from "#app/ui/command-ui-handler.js"; import { Command } from "#app/ui/command-ui-handler";
import * as Utils from "#app/utils.js"; import * as Utils from "#app/utils";
import { AttemptCapturePhase } from "./attempt-capture-phase"; import { AttemptCapturePhase } from "./attempt-capture-phase";
import { AttemptRunPhase } from "./attempt-run-phase"; import { AttemptRunPhase } from "./attempt-run-phase";
import { BerryPhase } from "./berry-phase"; import { BerryPhase } from "./berry-phase";
@ -17,18 +17,59 @@ import { PostTurnStatusEffectPhase } from "./post-turn-status-effect-phase";
import { SwitchSummonPhase } from "./switch-summon-phase"; import { SwitchSummonPhase } from "./switch-summon-phase";
import { TurnEndPhase } from "./turn-end-phase"; import { TurnEndPhase } from "./turn-end-phase";
import { WeatherEffectPhase } from "./weather-effect-phase"; import { WeatherEffectPhase } from "./weather-effect-phase";
import { BattlerIndex } from "#app/battle";
import { TrickRoomTag } from "#app/data/arena-tag";
export class TurnStartPhase extends FieldPhase { export class TurnStartPhase extends FieldPhase {
constructor(scene: BattleScene) { constructor(scene: BattleScene) {
super(scene); super(scene);
} }
start() { /**
super.start(); * This orders the active Pokemon on the field by speed into an BattlerIndex array and returns that array.
* It also checks for Trick Room and reverses the array if it is present.
* @returns {@linkcode BattlerIndex[]} the battle indices of all pokemon on the field ordered by speed
*/
getSpeedOrder(): BattlerIndex[] {
const playerField = this.scene.getPlayerField().filter(p => p.isActive()) as Pokemon[];
const enemyField = this.scene.getEnemyField().filter(p => p.isActive()) as Pokemon[];
const field = this.scene.getField(); // We shuffle the list before sorting so speed ties produce random results
const order = this.getOrder(); let orderedTargets: Pokemon[] = playerField.concat(enemyField);
// We seed it with the current turn to prevent an inconsistency where it
// was varying based on how long since you last reloaded
this.scene.executeWithSeedOffset(() => {
orderedTargets = Utils.randSeedShuffle(orderedTargets);
}, this.scene.currentBattle.turn, this.scene.waveSeed);
orderedTargets.sort((a: Pokemon, b: Pokemon) => {
const aSpeed = a?.getBattleStat(Stat.SPD) || 0;
const bSpeed = b?.getBattleStat(Stat.SPD) || 0;
return bSpeed - aSpeed;
});
// Next, a check for Trick Room is applied. If Trick Room is present, the order is reversed.
const speedReversed = new Utils.BooleanHolder(false);
this.scene.arena.applyTags(TrickRoomTag, speedReversed);
if (speedReversed.value) {
orderedTargets = orderedTargets.reverse();
}
return orderedTargets.map(t => t.getFieldIndex() + (!t.isPlayer() ? BattlerIndex.ENEMY : BattlerIndex.PLAYER));
}
/**
* This takes the result of getSpeedOrder and applies priority / bypass speed attributes to it.
* This also considers the priority levels of various commands and changes the result of getSpeedOrder based on such.
* @returns {@linkcode BattlerIndex[]} the final sequence of commands for this turn
*/
getCommandOrder(): BattlerIndex[] {
let moveOrder = this.getSpeedOrder();
// The creation of the battlerBypassSpeed object contains checks for the ability Quick Draw and the held item Quick Claw
// The ability Mycelium Might disables Quick Claw's activation when using a status move
// This occurs before the main loop because of battles with more than two Pokemon
const battlerBypassSpeed = {}; const battlerBypassSpeed = {};
this.scene.getField(true).filter(p => p.summonData).map(p => { this.scene.getField(true).filter(p => p.summonData).map(p => {
@ -42,8 +83,9 @@ export class TurnStartPhase extends FieldPhase {
battlerBypassSpeed[p.getBattlerIndex()] = bypassSpeed; battlerBypassSpeed[p.getBattlerIndex()] = bypassSpeed;
}); });
const moveOrder = order.slice(0); // The function begins sorting orderedTargets based on command priority, move priority, and possible speed bypasses.
// Non-FIGHT commands (SWITCH, BALL, RUN) have a higher command priority and will always occur before any FIGHT commands.
moveOrder = moveOrder.slice(0);
moveOrder.sort((a, b) => { moveOrder.sort((a, b) => {
const aCommand = this.scene.currentBattle.turnCommands[a]; const aCommand = this.scene.currentBattle.turnCommands[a];
const bCommand = this.scene.currentBattle.turnCommands[b]; const bCommand = this.scene.currentBattle.turnCommands[b];
@ -55,37 +97,50 @@ export class TurnStartPhase extends FieldPhase {
return -1; return -1;
} }
} else if (aCommand?.command === Command.FIGHT) { } else if (aCommand?.command === Command.FIGHT) {
const aMove = allMoves[aCommand.move!.move];//TODO: is the bang correct here? const aMove = allMoves[aCommand.move!.move];
const bMove = allMoves[bCommand!.move!.move];//TODO: is the bang correct here? const bMove = allMoves[bCommand!.move!.move];
// The game now considers priority and applies the relevant move and ability attributes
const aPriority = new Utils.IntegerHolder(aMove.priority); const aPriority = new Utils.IntegerHolder(aMove.priority);
const bPriority = new Utils.IntegerHolder(bMove.priority); const bPriority = new Utils.IntegerHolder(bMove.priority);
applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority); //TODO: is the bang correct here? applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, aMove, aPriority);
applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority); //TODO: is the bang correct here? applyMoveAttrs(IncrementMovePriorityAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, bMove, bPriority);
applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, false, aMove, aPriority); //TODO: is the bang correct here? applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === a)!, null, false, aMove, aPriority);
applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, false, bMove, bPriority); //TODO: is the bang correct here? applyAbAttrs(ChangeMovePriorityAbAttr, this.scene.getField().find(p => p?.isActive() && p.getBattlerIndex() === b)!, null, false, bMove, bPriority);
// The game now checks for differences in priority levels.
// If the moves share the same original priority bracket, it can check for differences in battlerBypassSpeed and return the result.
// This conditional is used to ensure that Quick Claw can still activate with abilities like Stall and Mycelium Might (attack moves only)
// Otherwise, the game returns the user of the move with the highest priority.
const isSameBracket = Math.ceil(aPriority.value) - Math.ceil(bPriority.value) === 0;
if (aPriority.value !== bPriority.value) { if (aPriority.value !== bPriority.value) {
const bracketDifference = Math.ceil(aPriority.value) - Math.ceil(bPriority.value); if (isSameBracket && battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value) {
const hasSpeedDifference = battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value;
if (bracketDifference === 0 && hasSpeedDifference) {
return battlerBypassSpeed[a].value ? -1 : 1; return battlerBypassSpeed[a].value ? -1 : 1;
} }
return aPriority.value < bPriority.value ? 1 : -1; return aPriority.value < bPriority.value ? 1 : -1;
} }
} }
// If there is no difference between the move's calculated priorities, the game checks for differences in battlerBypassSpeed and returns the result.
if (battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value) { if (battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value) {
return battlerBypassSpeed[a].value ? -1 : 1; return battlerBypassSpeed[a].value ? -1 : 1;
} }
const aIndex = order.indexOf(a); const aIndex = moveOrder.indexOf(a);
const bIndex = order.indexOf(b); const bIndex = moveOrder.indexOf(b);
return aIndex < bIndex ? -1 : aIndex > bIndex ? 1 : 0; return aIndex < bIndex ? -1 : aIndex > bIndex ? 1 : 0;
}); });
return moveOrder;
}
start() {
super.start();
const field = this.scene.getField();
const moveOrder = this.getCommandOrder();
let orderIndex = 0; let orderIndex = 0;
@ -150,10 +205,9 @@ export class TurnStartPhase extends FieldPhase {
} }
} }
this.scene.pushPhase(new WeatherEffectPhase(this.scene)); this.scene.pushPhase(new WeatherEffectPhase(this.scene));
for (const o of order) { for (const o of moveOrder) {
if (field[o].status && field[o].status.isPostTurn()) { if (field[o].status && field[o].status.isPostTurn()) {
this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, o)); this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, o));
} }

View File

@ -1,6 +1,6 @@
import { BattleStat } from "#app/data/battle-stat"; import { BattleStat } from "#app/data/battle-stat";
import { MovePhase } from "#app/phases/move-phase";
import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { TurnEndPhase } from "#app/phases/turn-end-phase";
import { TurnStartPhase } from "#app/phases/turn-start-phase";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
@ -8,7 +8,6 @@ import GameManager from "#test/utils/gameManager";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
describe("Abilities - Mycelium Might", () => { describe("Abilities - Mycelium Might", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
let game: GameManager; let game: GameManager;
@ -35,7 +34,7 @@ describe("Abilities - Mycelium Might", () => {
}); });
/** /**
* Bulbapedia References: * References:
* https://bulbapedia.bulbagarden.net/wiki/Mycelium_Might_(Ability) * https://bulbapedia.bulbagarden.net/wiki/Mycelium_Might_(Ability)
* https://bulbapedia.bulbagarden.net/wiki/Priority * https://bulbapedia.bulbagarden.net/wiki/Priority
* https://www.smogon.com/forums/threads/scarlet-violet-battle-mechanics-research.3709545/page-24 * https://www.smogon.com/forums/threads/scarlet-violet-battle-mechanics-research.3709545/page-24
@ -44,22 +43,22 @@ describe("Abilities - Mycelium Might", () => {
it("will move last in its priority bracket and ignore protective abilities", async () => { it("will move last in its priority bracket and ignore protective abilities", async () => {
await game.startBattle([Species.REGIELEKI]); await game.startBattle([Species.REGIELEKI]);
const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyPokemon = game.scene.getEnemyPokemon(); const enemyPokemon = game.scene.getEnemyPokemon();
const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex();
const enemyIndex = enemyPokemon?.getBattlerIndex(); const enemyIndex = enemyPokemon?.getBattlerIndex();
game.move.select(Moves.BABY_DOLL_EYES); game.move.select(Moves.BABY_DOLL_EYES);
await game.phaseInterceptor.to(MovePhase, false); await game.phaseInterceptor.to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const speedOrder = phase.getSpeedOrder();
const commandOrder = phase.getCommandOrder();
// The opponent Pokemon (without Mycelium Might) goes first despite having lower speed than the player Pokemon. // The opponent Pokemon (without Mycelium Might) goes first despite having lower speed than the player Pokemon.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
await game.phaseInterceptor.run(MovePhase);
await game.phaseInterceptor.to(MovePhase, false);
// The player Pokemon (with Mycelium Might) goes last despite having higher speed than the opponent. // The player Pokemon (with Mycelium Might) goes last despite having higher speed than the opponent.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex); expect(speedOrder).toEqual([playerIndex, enemyIndex]);
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
// Despite the opponent's ability (Clear Body), its attack stat is still reduced.
expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1); expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1);
}, 20000); }, 20000);
@ -67,39 +66,41 @@ describe("Abilities - Mycelium Might", () => {
game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
await game.startBattle([Species.REGIELEKI]); await game.startBattle([Species.REGIELEKI]);
const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyPokemon = game.scene.getEnemyPokemon(); const enemyPokemon = game.scene.getEnemyPokemon();
const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex();
const enemyIndex = enemyPokemon?.getBattlerIndex(); const enemyIndex = enemyPokemon?.getBattlerIndex();
game.move.select(Moves.BABY_DOLL_EYES); game.move.select(Moves.BABY_DOLL_EYES);
await game.phaseInterceptor.to(MovePhase, false); await game.phaseInterceptor.to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const speedOrder = phase.getSpeedOrder();
const commandOrder = phase.getCommandOrder();
// The player Pokemon (with M.M.) goes first because its move is still within a higher priority bracket than its opponent. // The player Pokemon (with M.M.) goes first because its move is still within a higher priority bracket than its opponent.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
await game.phaseInterceptor.run(MovePhase);
await game.phaseInterceptor.to(MovePhase, false);
// The enemy Pokemon goes second because its move is in a lower priority bracket. // The enemy Pokemon goes second because its move is in a lower priority bracket.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex); expect(speedOrder).toEqual([playerIndex, enemyIndex]);
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
// Despite the opponent's ability (Clear Body), its attack stat is still reduced.
expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1); expect(enemyPokemon?.summonData.battleStats[BattleStat.ATK]).toBe(-1);
}, 20000); }, 20000);
it("will not affect non-status moves", async () => { it("will not affect non-status moves", async () => {
await game.startBattle([Species.REGIELEKI]); await game.startBattle([Species.REGIELEKI]);
const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
game.move.select(Moves.QUICK_ATTACK); game.move.select(Moves.QUICK_ATTACK);
await game.phaseInterceptor.to(MovePhase, false); await game.phaseInterceptor.to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const speedOrder = phase.getSpeedOrder();
const commandOrder = phase.getCommandOrder();
// The player Pokemon (with M.M.) goes first because it has a higher speed and did not use a status move. // The player Pokemon (with M.M.) goes first because it has a higher speed and did not use a status move.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
await game.phaseInterceptor.run(MovePhase);
await game.phaseInterceptor.to(MovePhase, false);
// The enemy Pokemon (without M.M.) goes second because its speed is lower. // The enemy Pokemon (without M.M.) goes second because its speed is lower.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex); // This means that the commandOrder should be identical to the speedOrder
expect(speedOrder).toEqual([playerIndex, enemyIndex]);
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
}, 20000); }, 20000);
}); });

View File

@ -1,11 +1,10 @@
import { MovePhase } from "#app/phases/move-phase";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager"; import GameManager from "#test/utils/gameManager";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
import { TurnStartPhase } from "#app/phases/turn-start-phase";
describe("Abilities - Stall", () => { describe("Abilities - Stall", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
@ -32,7 +31,7 @@ describe("Abilities - Stall", () => {
}); });
/** /**
* Bulbapedia References: * References:
* https://bulbapedia.bulbagarden.net/wiki/Stall_(Ability) * https://bulbapedia.bulbagarden.net/wiki/Stall_(Ability)
* https://bulbapedia.bulbagarden.net/wiki/Priority * https://bulbapedia.bulbagarden.net/wiki/Priority
**/ **/
@ -40,55 +39,56 @@ describe("Abilities - Stall", () => {
it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => { it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => {
await game.startBattle([Species.SHUCKLE]); await game.startBattle([Species.SHUCKLE]);
const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
game.move.select(Moves.QUICK_ATTACK); game.move.select(Moves.QUICK_ATTACK);
await game.phaseInterceptor.to(MovePhase, false); await game.phaseInterceptor.to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const speedOrder = phase.getSpeedOrder();
const commandOrder = phase.getCommandOrder();
// The player Pokemon (without Stall) goes first despite having lower speed than the opponent. // The player Pokemon (without Stall) goes first despite having lower speed than the opponent.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex);
await game.phaseInterceptor.run(MovePhase);
await game.phaseInterceptor.to(MovePhase, false);
// The opponent Pokemon (with Stall) goes last despite having higher speed than the player Pokemon. // The opponent Pokemon (with Stall) goes last despite having higher speed than the player Pokemon.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex); expect(speedOrder).toEqual([enemyIndex, playerIndex]);
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
}, 20000); }, 20000);
it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => { it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => {
await game.startBattle([Species.SHUCKLE]); await game.startBattle([Species.SHUCKLE]);
const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to(MovePhase, false); await game.phaseInterceptor.to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const speedOrder = phase.getSpeedOrder();
const commandOrder = phase.getCommandOrder();
// The opponent Pokemon (with Stall) goes first because its move is still within a higher priority bracket than its opponent. // The opponent Pokemon (with Stall) goes first because its move is still within a higher priority bracket than its opponent.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex);
await game.phaseInterceptor.run(MovePhase);
await game.phaseInterceptor.to(MovePhase, false);
// The player Pokemon goes second because its move is in a lower priority bracket. // The player Pokemon goes second because its move is in a lower priority bracket.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex); expect(speedOrder).toEqual([enemyIndex, playerIndex]);
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
}, 20000); }, 20000);
it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => { it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => {
game.override.ability(Abilities.STALL); game.override.ability(Abilities.STALL);
await game.startBattle([Species.SHUCKLE]); await game.startBattle([Species.SHUCKLE]);
const leadIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex();
const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex();
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to(MovePhase, false); await game.phaseInterceptor.to(TurnStartPhase, false);
// The opponent Pokemon (with Stall) goes first because it has a higher speed. const phase = game.scene.getCurrentPhase() as TurnStartPhase;
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(enemyIndex); const speedOrder = phase.getSpeedOrder();
const commandOrder = phase.getCommandOrder();
await game.phaseInterceptor.run(MovePhase); // The opponent Pokemon (with Stall) goes first because it has a higher speed.
await game.phaseInterceptor.to(MovePhase, false);
// The player Pokemon (with Stall) goes second because its speed is lower. // The player Pokemon (with Stall) goes second because its speed is lower.
expect((game.scene.getCurrentPhase() as MovePhase).pokemon.getBattlerIndex()).toBe(leadIndex); expect(speedOrder).toEqual([enemyIndex, playerIndex]);
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
}, 20000); }, 20000);
}); });

View File

@ -1,4 +1,3 @@
import { Stat } from "#app/data/pokemon-stat";
import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
import { SelectTargetPhase } from "#app/phases/select-target-phase"; import { SelectTargetPhase } from "#app/phases/select-target-phase";
import { TurnStartPhase } from "#app/phases/turn-start-phase"; import { TurnStartPhase } from "#app/phases/turn-start-phase";
@ -7,8 +6,7 @@ import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager"; import GameManager from "#test/utils/gameManager";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
describe("Battle order", () => { describe("Battle order", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
@ -37,30 +35,42 @@ describe("Battle order", () => {
await game.startBattle([ await game.startBattle([
Species.BULBASAUR, Species.BULBASAUR,
]); ]);
game.scene.getParty()[0].stats[Stat.SPD] = 50;
game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 150; const playerPokemon = game.scene.getPlayerPokemon()!;
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50]); // set playerPokemon's speed to 50
vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set enemyPokemon's speed to 150
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.run(EnemyCommandPhase); await game.phaseInterceptor.run(EnemyCommandPhase);
const playerPokemonIndex = playerPokemon.getBattlerIndex();
const enemyPokemonIndex = enemyPokemon.getBattlerIndex();
const phase = game.scene.getCurrentPhase() as TurnStartPhase; const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const order = phase.getOrder(); const order = phase.getCommandOrder();
expect(order[0]).toBe(2); expect(order[0]).toBe(enemyPokemonIndex);
expect(order[1]).toBe(0); expect(order[1]).toBe(playerPokemonIndex);
}, 20000); }, 20000);
it("Player faster than opponent 150 vs 50", async () => { it("Player faster than opponent 150 vs 50", async () => {
await game.startBattle([ await game.startBattle([
Species.BULBASAUR, Species.BULBASAUR,
]); ]);
game.scene.getParty()[0].stats[Stat.SPD] = 150;
game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 50; const playerPokemon = game.scene.getPlayerPokemon()!;
const enemyPokemon = game.scene.getEnemyPokemon()!;
vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set playerPokemon's speed to 150
vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50]); // set enemyPokemon's speed to 50
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.run(EnemyCommandPhase); await game.phaseInterceptor.run(EnemyCommandPhase);
const playerPokemonIndex = playerPokemon.getBattlerIndex();
const enemyPokemonIndex = enemyPokemon.getBattlerIndex();
const phase = game.scene.getCurrentPhase() as TurnStartPhase; const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const order = phase.getOrder(); const order = phase.getCommandOrder();
expect(order[0]).toBe(0); expect(order[0]).toBe(playerPokemonIndex);
expect(order[1]).toBe(2); expect(order[1]).toBe(enemyPokemonIndex);
}, 20000); }, 20000);
it("double - both opponents faster than player 50/50 vs 150/150", async () => { it("double - both opponents faster than player 50/50 vs 150/150", async () => {
@ -69,20 +79,25 @@ describe("Battle order", () => {
Species.BULBASAUR, Species.BULBASAUR,
Species.BLASTOISE, Species.BLASTOISE,
]); ]);
game.scene.getParty()[0].stats[Stat.SPD] = 50;
game.scene.getParty()[1].stats[Stat.SPD] = 50; const playerPokemon = game.scene.getPlayerField();
game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 150; const enemyPokemon = game.scene.getEnemyField();
game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150;
playerPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50])); // set both playerPokemons' speed to 50
enemyPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150])); // set both enemyPokemons' speed to 150
const playerIndices = playerPokemon.map(p => p?.getBattlerIndex());
const enemyIndices = enemyPokemon.map(p => p?.getBattlerIndex());
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
game.move.select(Moves.TACKLE, 1); game.move.select(Moves.TACKLE, 1);
await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase; const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const order = phase.getOrder(); const order = phase.getCommandOrder();
expect(order.indexOf(0)).toBeGreaterThan(order.indexOf(2)); expect(order.slice(0, 2).includes(enemyIndices[0])).toBe(true);
expect(order.indexOf(0)).toBeGreaterThan(order.indexOf(3)); expect(order.slice(0, 2).includes(enemyIndices[1])).toBe(true);
expect(order.indexOf(1)).toBeGreaterThan(order.indexOf(2)); expect(order.slice(2, 4).includes(playerIndices[0])).toBe(true);
expect(order.indexOf(1)).toBeGreaterThan(order.indexOf(3)); expect(order.slice(2, 4).includes(playerIndices[1])).toBe(true);
}, 20000); }, 20000);
it("double - speed tie except 1 - 100/100 vs 100/150", async () => { it("double - speed tie except 1 - 100/100 vs 100/150", async () => {
@ -91,19 +106,25 @@ describe("Battle order", () => {
Species.BULBASAUR, Species.BULBASAUR,
Species.BLASTOISE, Species.BLASTOISE,
]); ]);
game.scene.getParty()[0].stats[Stat.SPD] = 100;
game.scene.getParty()[1].stats[Stat.SPD] = 100; const playerPokemon = game.scene.getPlayerField();
game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 100; const enemyPokemon = game.scene.getEnemyField();
game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; playerPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100])); //set both playerPokemons' speed to 100
vi.spyOn(enemyPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100]); // set enemyPokemon's speed to 100
vi.spyOn(enemyPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set enemyPokemon's speed to 150
const playerIndices = playerPokemon.map(p => p?.getBattlerIndex());
const enemyIndices = enemyPokemon.map(p => p?.getBattlerIndex());
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
game.move.select(Moves.TACKLE, 1); game.move.select(Moves.TACKLE, 1);
await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase; const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const order = phase.getOrder(); const order = phase.getCommandOrder();
expect(order.indexOf(3)).toBeLessThan(order.indexOf(0)); expect(order[0]).toBe(enemyIndices[1]);
expect(order.indexOf(3)).toBeLessThan(order.indexOf(1)); expect(order.slice(1, 4).includes(enemyIndices[0])).toBe(true);
expect(order.indexOf(3)).toBeLessThan(order.indexOf(2)); expect(order.slice(1, 4).includes(playerIndices[0])).toBe(true);
expect(order.slice(1, 4).includes(playerIndices[1])).toBe(true);
}, 20000); }, 20000);
it("double - speed tie 100/150 vs 100/150", async () => { it("double - speed tie 100/150 vs 100/150", async () => {
@ -112,19 +133,25 @@ describe("Battle order", () => {
Species.BULBASAUR, Species.BULBASAUR,
Species.BLASTOISE, Species.BLASTOISE,
]); ]);
game.scene.getParty()[0].stats[Stat.SPD] = 100;
game.scene.getParty()[1].stats[Stat.SPD] = 150; const playerPokemon = game.scene.getPlayerField();
game.scene.currentBattle.enemyParty[0].stats[Stat.SPD] = 100; const enemyPokemon = game.scene.getEnemyField();
game.scene.currentBattle.enemyParty[1].stats[Stat.SPD] = 150; vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100]); // set one playerPokemon's speed to 100
vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set other playerPokemon's speed to 150
vi.spyOn(enemyPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100]); // set one enemyPokemon's speed to 100
vi.spyOn(enemyPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set other enemyPokemon's speed to 150
const playerIndices = playerPokemon.map(p => p?.getBattlerIndex());
const enemyIndices = enemyPokemon.map(p => p?.getBattlerIndex());
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
game.move.select(Moves.TACKLE, 1); game.move.select(Moves.TACKLE, 1);
await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false);
const phase = game.scene.getCurrentPhase() as TurnStartPhase; const phase = game.scene.getCurrentPhase() as TurnStartPhase;
const order = phase.getOrder(); const order = phase.getCommandOrder();
expect(order.indexOf(1)).toBeLessThan(order.indexOf(0)); expect(order.slice(0, 2).includes(playerIndices[1])).toBe(true);
expect(order.indexOf(1)).toBeLessThan(order.indexOf(2)); expect(order.slice(0, 2).includes(enemyIndices[1])).toBe(true);
expect(order.indexOf(3)).toBeLessThan(order.indexOf(0)); expect(order.slice(2, 4).includes(playerIndices[0])).toBe(true);
expect(order.indexOf(3)).toBeLessThan(order.indexOf(2)); expect(order.slice(2, 4).includes(enemyIndices[0])).toBe(true);
}, 20000); }, 20000);
}); });

View File

@ -381,7 +381,7 @@ export default class GameManager {
} }
/** /**
* Intercepts `TurnStartPhase` and mocks the getOrder's return value {@linkcode TurnStartPhase.getOrder} * Intercepts `TurnStartPhase` and mocks the getSpeedOrder's return value {@linkcode TurnStartPhase.getSpeedOrder}
* Used to modify the turn order. * Used to modify the turn order.
* @param {BattlerIndex[]} order The turn order to set * @param {BattlerIndex[]} order The turn order to set
* @example * @example
@ -392,7 +392,7 @@ export default class GameManager {
async setTurnOrder(order: BattlerIndex[]): Promise<void> { async setTurnOrder(order: BattlerIndex[]): Promise<void> {
await this.phaseInterceptor.to(TurnStartPhase, false); await this.phaseInterceptor.to(TurnStartPhase, false);
vi.spyOn(this.scene.getCurrentPhase() as TurnStartPhase, "getOrder").mockReturnValue(order); vi.spyOn(this.scene.getCurrentPhase() as TurnStartPhase, "getSpeedOrder").mockReturnValue(order);
} }
/** /**

View File

@ -1,35 +1,39 @@
import BattleScene from "#app/battle-scene.js"; import BattleScene from "#app/battle-scene";
import { TextStyle, addTextObject } from "#app/ui/text.js"; import { TextStyle, addTextObject } from "#app/ui/text";
import i18next from "i18next";
export enum EventType { export enum EventType {
SHINY SHINY,
GENERIC
} }
interface TimedEvent { interface EventBanner {
name: string; bannerKey?: string;
eventType: EventType; xPosition?: number;
shinyMultiplier?: number; yPosition?: number;
startDate: Date; scale?: number;
endDate: Date; availableLangs?: string[];
bannerFilename?: string }
interface TimedEvent extends EventBanner {
name: string;
eventType: EventType;
shinyMultiplier?: number;
startDate: Date;
endDate: Date;
} }
const timedEvents: TimedEvent[] = [ const timedEvents: TimedEvent[] = [
{ {
name: "Pride Update", name: "September Update",
eventType: EventType.SHINY, eventType: EventType.GENERIC,
shinyMultiplier: 2, startDate: new Date(Date.UTC(2024, 7, 28, 0)),
startDate: new Date(Date.UTC(2024, 5, 14, 0)), endDate: new Date(Date.UTC(2024, 8, 15, 0)),
endDate: new Date(Date.UTC(2024, 5, 23, 0)), bannerKey: "september-update",
bannerFilename: "pride-update" xPosition: 19,
}, yPosition: 115,
{ scale: 0.30,
name: "August Variant Update", availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es", "pt_BR", "zh_CN"]
eventType: EventType.SHINY,
shinyMultiplier: 2,
startDate: new Date(Date.UTC(2024, 7, 16, 0)),
endDate: new Date(Date.UTC(2024, 7, 22, 0)),
bannerFilename: "august-variant-update"
} }
]; ];
@ -67,7 +71,7 @@ export class TimedEventManager {
} }
getEventBannerFilename(): string { getEventBannerFilename(): string {
return timedEvents.find((te: TimedEvent) => this.isActive(te))?.bannerFilename!; // TODO: is this bang correct? return timedEvents.find((te: TimedEvent) => this.isActive(te))?.bannerKey!; // TODO: is this bang correct?
} }
} }
@ -85,38 +89,37 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
} }
setup() { setup() {
console.log(this.event?.bannerFilename); const lang = i18next.resolvedLanguage;
this.banner = new Phaser.GameObjects.Image(this.scene, 29, 64, this.event!.bannerFilename!); // TODO: are the bangs correct here? if (this.event && this.event.bannerKey) {
this.banner.setName("img-event-banner"); let key = this.event.bannerKey;
this.banner.setOrigin(0.08, -0.35); if (lang && this.event.availableLangs && this.event.availableLangs.length > 0) {
this.banner.setScale(0.18); if (this.event.availableLangs.includes(lang)) {
// this.bannerShadow = new Phaser.GameObjects.Rectangle( key += "-"+lang;
// this.scene, } else {
// this.banner.x - 2, key += "-en";
// this.banner.y + 2, }
// this.banner.width, }
// this.banner.height, console.log(this.event.bannerKey);
// 0x484848 this.banner = new Phaser.GameObjects.Image(this.scene, this.event.xPosition ?? 29, this.event.yPosition ?? 64, key);
// ); this.banner.setName("img-event-banner");
// this.bannerShadow.setName("rect-event-banner-shadow"); this.banner.setOrigin(0.08, -0.35);
// this.bannerShadow.setScale(0.07); this.banner.setScale(this.event.scale ?? 0.18);
// this.bannerShadow.setAlpha(0.5); if (this.event.eventType !== EventType.GENERIC) {
// this.bannerShadow.setOrigin(0,0); this.eventTimerText = addTextObject(
this.eventTimerText = addTextObject( this.scene,
this.scene, this.banner.x + 8,
this.banner.x + 8, this.banner.y + 100,
this.banner.y + 100, this.timeToGo(this.event.endDate),
this.timeToGo(this.event!.endDate), // TODO: is the bang correct here? TextStyle.WINDOW
TextStyle.WINDOW );
); this.eventTimerText.setName("text-event-timer");
this.eventTimerText.setName("text-event-timer"); this.eventTimerText.setScale(0.15);
this.eventTimerText.setScale(0.15); this.eventTimerText.setOrigin(0, 0);
this.eventTimerText.setOrigin(0, 0);
this.add([ this.add(this.eventTimerText);
this.eventTimerText, }
// this.bannerShadow, this.add(this.banner);
this.banner]); }
} }
show() { show() {
@ -157,6 +160,8 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
} }
updateCountdown() { updateCountdown() {
this.eventTimerText.setText(this.timeToGo(this.event!.endDate)); // TODO: is the bang correct here? if (this.event && this.event.eventType !== EventType.GENERIC) {
this.eventTimerText.setText(this.timeToGo(this.event.endDate));
}
} }
} }

View File

@ -23,6 +23,14 @@ export enum SortDirection {
DESC = 1 DESC = 1
} }
export enum SortCriteria {
NUMBER = 0,
COST = 1,
CANDY = 2,
IV = 3,
NAME = 4
}
export class DropDownLabel { export class DropDownLabel {
public state: DropDownState; public state: DropDownState;
public text: string; public text: string;

View File

@ -166,6 +166,8 @@ export default class PartyUiHandler extends MessageUiHandler {
private iconAnimHandler: PokemonIconAnimHandler; private iconAnimHandler: PokemonIconAnimHandler;
private blockInput: boolean;
private static FilterAll = (_pokemon: PlayerPokemon) => null; private static FilterAll = (_pokemon: PlayerPokemon) => null;
public static FilterNonFainted = (pokemon: PlayerPokemon) => { public static FilterNonFainted = (pokemon: PlayerPokemon) => {
@ -317,7 +319,7 @@ export default class PartyUiHandler extends MessageUiHandler {
processInput(button: Button): boolean { processInput(button: Button): boolean {
const ui = this.getUi(); const ui = this.getUi();
if (this.pendingPrompt) { if (this.pendingPrompt || this.blockInput) {
return false; return false;
} }
@ -485,7 +487,9 @@ export default class PartyUiHandler extends MessageUiHandler {
this.clearOptions(); this.clearOptions();
ui.playSelect(); ui.playSelect();
if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) { if (this.cursor >= this.scene.currentBattle.getBattlerCount() || !pokemon.isAllowedInBattle()) {
this.blockInput = true;
this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => { this.showText(i18next.t("partyUiHandler:releaseConfirmation", { pokemonName: getPokemonNameWithAffix(pokemon) }), null, () => {
this.blockInput = false;
ui.setModeWithoutClear(Mode.CONFIRM, () => { ui.setModeWithoutClear(Mode.CONFIRM, () => {
ui.setMode(Mode.PARTY); ui.setMode(Mode.PARTY);
this.doRelease(this.cursor); this.doRelease(this.cursor);

View File

@ -39,12 +39,13 @@ import { Species } from "#enums/species";
import {Button} from "#enums/buttons"; import {Button} from "#enums/buttons";
import { EggSourceType } from "#app/enums/egg-source-types.js"; import { EggSourceType } from "#app/enums/egg-source-types.js";
import AwaitableUiHandler from "./awaitable-ui-handler"; import AwaitableUiHandler from "./awaitable-ui-handler";
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType } from "./dropdown"; import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "./dropdown";
import { StarterContainer } from "./starter-container"; import { StarterContainer } from "./starter-container";
import { DropDownColumn, FilterBar } from "./filter-bar"; import { DropDownColumn, FilterBar } from "./filter-bar";
import { ScrollBar } from "./scroll-bar"; import { ScrollBar } from "./scroll-bar";
import { SelectChallengePhase } from "#app/phases/select-challenge-phase.js"; import { SelectChallengePhase } from "#app/phases/select-challenge-phase.js";
import { TitlePhase } from "#app/phases/title-phase.js"; import { TitlePhase } from "#app/phases/title-phase.js";
import { Abilities } from "#app/enums/abilities";
export type StarterSelectCallback = (starters: Starter[]) => void; export type StarterSelectCallback = (starters: Starter[]) => void;
@ -501,11 +502,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
// sort filter // sort filter
const sortOptions = [ const sortOptions = [
new DropDownOption(this.scene, 0, new DropDownLabel(i18next.t("filterBar:sortByNumber"), undefined, DropDownState.ON)), new DropDownOption(this.scene, SortCriteria.NUMBER, new DropDownLabel(i18next.t("filterBar:sortByNumber"), undefined, DropDownState.ON)),
new DropDownOption(this.scene, 1, new DropDownLabel(i18next.t("filterBar:sortByCost"))), new DropDownOption(this.scene, SortCriteria.COST, new DropDownLabel(i18next.t("filterBar:sortByCost"))),
new DropDownOption(this.scene, 2, new DropDownLabel(i18next.t("filterBar:sortByCandies"))), new DropDownOption(this.scene, SortCriteria.CANDY, new DropDownLabel(i18next.t("filterBar:sortByCandies"))),
new DropDownOption(this.scene, 3, new DropDownLabel(i18next.t("filterBar:sortByIVs"))), new DropDownOption(this.scene, SortCriteria.IV, new DropDownLabel(i18next.t("filterBar:sortByIVs"))),
new DropDownOption(this.scene, 4, new DropDownLabel(i18next.t("filterBar:sortByName"))) new DropDownOption(this.scene, SortCriteria.NAME, new DropDownLabel(i18next.t("filterBar:sortByName")))
]; ];
this.filterBar.addFilter(DropDownColumn.SORT, i18next.t("filterBar:sortFilter"), new DropDown(this.scene, 0, 0, sortOptions, this.updateStarters, DropDownType.SINGLE)); this.filterBar.addFilter(DropDownColumn.SORT, i18next.t("filterBar:sortFilter"), new DropDown(this.scene, 0, 0, sortOptions, this.updateStarters, DropDownType.SINGLE));
this.filterBarContainer.add(this.filterBar); this.filterBarContainer.add(this.filterBar);
@ -2363,6 +2364,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
// First, ensure you have the caught attributes for the species else default to bigint 0 // First, ensure you have the caught attributes for the species else default to bigint 0
const caughtAttr = this.scene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0); const caughtAttr = this.scene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0);
const starterData = this.scene.gameData.starterData[container.species.speciesId]; const starterData = this.scene.gameData.starterData[container.species.speciesId];
const isStarterProgressable = speciesEggMoves.hasOwnProperty(container.species.speciesId);
// Gen filter // Gen filter
const fitsGen = this.filterBar.getVals(DropDownColumn.GEN).includes(container.species.generation); const fitsGen = this.filterBar.getVals(DropDownColumn.GEN).includes(container.species.generation);
@ -2398,7 +2400,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.ON) { if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.ON) {
return isPassiveUnlocked; return isPassiveUnlocked;
} else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.EXCLUDE) { } else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.EXCLUDE) {
return !isPassiveUnlocked; return isStarterProgressable && !isPassiveUnlocked;
} else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.UNLOCKABLE) { } else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.UNLOCKABLE) {
return isPassiveUnlockable; return isPassiveUnlockable;
} else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.OFF) { } else if (unlocks.val === "PASSIVE" && unlocks.state === DropDownState.OFF) {
@ -2413,7 +2415,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.ON) { if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.ON) {
return isCostReduced; return isCostReduced;
} else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.EXCLUDE) { } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.EXCLUDE) {
return !isCostReduced; return isStarterProgressable && !isCostReduced;
} else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.UNLOCKABLE) { } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.UNLOCKABLE) {
return isCostReductionUnlockable; return isCostReductionUnlockable;
} else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.OFF) { } else if (unlocks.val === "COST_REDUCTION" && unlocks.state === DropDownState.OFF) {
@ -2450,12 +2452,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
}); });
// HA Filter // HA Filter
const speciesHasHiddenAbility = container.species.abilityHidden !== container.species.ability1 && container.species.abilityHidden !== Abilities.NONE;
const hasHA = starterData.abilityAttr & AbilityAttr.ABILITY_HIDDEN; const hasHA = starterData.abilityAttr & AbilityAttr.ABILITY_HIDDEN;
const fitsHA = this.filterBar.getVals(DropDownColumn.MISC).some(misc => { const fitsHA = this.filterBar.getVals(DropDownColumn.MISC).some(misc => {
if (misc.val === "HIDDEN_ABILITY" && misc.state === DropDownState.ON) { if (misc.val === "HIDDEN_ABILITY" && misc.state === DropDownState.ON) {
return hasHA; return hasHA;
} else if (misc.val === "HIDDEN_ABILITY" && misc.state === DropDownState.EXCLUDE) { } else if (misc.val === "HIDDEN_ABILITY" && misc.state === DropDownState.EXCLUDE) {
return !hasHA; return speciesHasHiddenAbility && !hasHA;
} else if (misc.val === "HIDDEN_ABILITY" && misc.state === DropDownState.OFF) { } else if (misc.val === "HIDDEN_ABILITY" && misc.state === DropDownState.OFF) {
return true; return true;
} }
@ -2467,7 +2470,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (misc.val === "EGG" && misc.state === DropDownState.ON) { if (misc.val === "EGG" && misc.state === DropDownState.ON) {
return isEggPurchasable; return isEggPurchasable;
} else if (misc.val === "EGG" && misc.state === DropDownState.EXCLUDE) { } else if (misc.val === "EGG" && misc.state === DropDownState.EXCLUDE) {
return !isEggPurchasable; return isStarterProgressable && !isEggPurchasable;
} else if (misc.val === "EGG" && misc.state === DropDownState.OFF) { } else if (misc.val === "EGG" && misc.state === DropDownState.OFF) {
return true; return true;
} }
@ -2498,19 +2501,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
switch (sort.val) { switch (sort.val) {
default: default:
break; break;
case 0: case SortCriteria.NUMBER:
return (a.species.speciesId - b.species.speciesId) * -sort.dir; return (a.species.speciesId - b.species.speciesId) * -sort.dir;
case 1: case SortCriteria.COST:
return (a.cost - b.cost) * -sort.dir; return (a.cost - b.cost) * -sort.dir;
case 2: case SortCriteria.CANDY:
const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount; const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount;
const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount; const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount;
return (candyCountA - candyCountB) * -sort.dir; return (candyCountA - candyCountB) * -sort.dir;
case 3: case SortCriteria.IV:
const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length; const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length;
const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length; const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length;
return (avgIVsA - avgIVsB) * -sort.dir; return (avgIVsA - avgIVsB) * -sort.dir;
case 4: case SortCriteria.NAME:
return a.species.name.localeCompare(b.species.name) * -sort.dir; return a.species.name.localeCompare(b.species.name) * -sort.dir;
} }
return 0; return 0;