mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-03 23:12:20 +02:00
Merge branch 'beta' into hebrew-pr
This commit is contained in:
commit
f213747500
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1,2 +1,3 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
# Auto detect text files and perform LF normalization
|
||||||
* text=auto
|
* text=auto
|
||||||
|
* -crlf
|
||||||
|
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,6 +1,7 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
description: Create a report to help us improve
|
description: Create a report to help us improve
|
||||||
title: "[Bug] "
|
title: "[Bug] "
|
||||||
|
type: bug
|
||||||
labels: ["Bug", "Triage"]
|
labels: ["Bug", "Triage"]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
|
1
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
1
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -1,6 +1,7 @@
|
|||||||
name: Feature Request
|
name: Feature Request
|
||||||
description: Suggest an idea for this project
|
description: Suggest an idea for this project
|
||||||
title: "[Feature] "
|
title: "[Feature] "
|
||||||
|
type: 'feature'
|
||||||
labels: ["Enhancement", "Triage"]
|
labels: ["Enhancement", "Triage"]
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
"1005",
|
"1005",
|
||||||
"1006",
|
"1006",
|
||||||
"1006",
|
"1006",
|
||||||
"1007-apex",
|
"1007-apex-build-Disabled",
|
||||||
"1007-apex",
|
"1007-apex-build-Disabled",
|
||||||
"1008-ultimate",
|
"1008-ultimate-mode-Disabled",
|
||||||
"1008-ultimate",
|
"1008-ultimate-mode-Disabled",
|
||||||
"115-mega",
|
"115-mega",
|
||||||
"115-mega",
|
"115-mega",
|
||||||
"127-mega",
|
"127-mega",
|
||||||
@ -185,9 +185,9 @@
|
|||||||
"531-mega",
|
"531-mega",
|
||||||
"569-gigantamax",
|
"569-gigantamax",
|
||||||
"569-gigantamax",
|
"569-gigantamax",
|
||||||
"6-mega",
|
|
||||||
"6-mega",
|
|
||||||
"6-mega-x",
|
"6-mega-x",
|
||||||
|
"6-mega-x",
|
||||||
|
"6-mega-y",
|
||||||
"6-mega-y",
|
"6-mega-y",
|
||||||
"6058",
|
"6058",
|
||||||
"6058",
|
"6058",
|
||||||
@ -825,8 +825,8 @@
|
|||||||
"873",
|
"873",
|
||||||
"874",
|
"874",
|
||||||
"874",
|
"874",
|
||||||
"875-no",
|
"875-no-ice",
|
||||||
"875-no",
|
"875-no-ice",
|
||||||
"875",
|
"875",
|
||||||
"875",
|
"875",
|
||||||
"876-female",
|
"876-female",
|
||||||
@ -963,26 +963,26 @@
|
|||||||
"929",
|
"929",
|
||||||
"930",
|
"930",
|
||||||
"930",
|
"930",
|
||||||
"931-blue",
|
"931-blue-plumage-Disabled",
|
||||||
"931-blue",
|
"931-blue-plumage-Disabled",
|
||||||
"931-green",
|
"931-green-plumage-Disabled",
|
||||||
"931-green",
|
"931-green-plumage-Disabled",
|
||||||
"931-white",
|
"931-white-plumage-Disabled",
|
||||||
"931-white",
|
"931-white-plumage-Disabled",
|
||||||
"931-yellow",
|
"931-yellow-plumage-Disabled",
|
||||||
"931-yellow",
|
"931-yellow-plumage-Disabled",
|
||||||
"932",
|
"932",
|
||||||
"932",
|
"932",
|
||||||
"933",
|
"933",
|
||||||
"933",
|
"933",
|
||||||
"934",
|
"934",
|
||||||
"934",
|
"934",
|
||||||
"935",
|
"935-Disabled",
|
||||||
"935",
|
"935-Disabled",
|
||||||
"936",
|
"936-Disabled",
|
||||||
"936",
|
"936-Disabled",
|
||||||
"937",
|
"937-Disabled",
|
||||||
"937",
|
"937-Disabled",
|
||||||
"938",
|
"938",
|
||||||
"938",
|
"938",
|
||||||
"939",
|
"939",
|
||||||
@ -1073,6 +1073,8 @@
|
|||||||
"978-droopy",
|
"978-droopy",
|
||||||
"978-stretchy",
|
"978-stretchy",
|
||||||
"978-stretchy",
|
"978-stretchy",
|
||||||
|
"979-Disabled",
|
||||||
|
"979-Disabled",
|
||||||
"980",
|
"980",
|
||||||
"980",
|
"980",
|
||||||
"981",
|
"981",
|
||||||
@ -1131,10 +1133,10 @@
|
|||||||
"1005b",
|
"1005b",
|
||||||
"1006b",
|
"1006b",
|
||||||
"1006b",
|
"1006b",
|
||||||
"1007b-apex",
|
"1007b-apex-build-Disabled",
|
||||||
"1007b-apex",
|
"1007b-apex-build-Disabled",
|
||||||
"1008b-ultimate",
|
"1008b-ultimate-mode-Disabled",
|
||||||
"1008b-ultimate",
|
"1008b-ultimate-mode-Disabled",
|
||||||
"115b-mega",
|
"115b-mega",
|
||||||
"115b-mega",
|
"115b-mega",
|
||||||
"127b-mega",
|
"127b-mega",
|
||||||
@ -1303,9 +1305,9 @@
|
|||||||
"531b-mega",
|
"531b-mega",
|
||||||
"569b-gigantamax",
|
"569b-gigantamax",
|
||||||
"569b-gigantamax",
|
"569b-gigantamax",
|
||||||
"6b-mega",
|
|
||||||
"6b-mega",
|
|
||||||
"6b-mega-x",
|
"6b-mega-x",
|
||||||
|
"6b-mega-x",
|
||||||
|
"6b-mega-y",
|
||||||
"6b-mega-y",
|
"6b-mega-y",
|
||||||
"6058b",
|
"6058b",
|
||||||
"6058b",
|
"6058b",
|
||||||
@ -1943,8 +1945,8 @@
|
|||||||
"873b",
|
"873b",
|
||||||
"874b",
|
"874b",
|
||||||
"874b",
|
"874b",
|
||||||
"875b-no",
|
"875b-no-ice",
|
||||||
"875b-no",
|
"875b-no-ice",
|
||||||
"875b",
|
"875b",
|
||||||
"875b",
|
"875b",
|
||||||
"876b-female",
|
"876b-female",
|
||||||
@ -2083,26 +2085,26 @@
|
|||||||
"929b",
|
"929b",
|
||||||
"930b",
|
"930b",
|
||||||
"930b",
|
"930b",
|
||||||
"931b-blue",
|
"931b-blue-plumage-Disabled",
|
||||||
"931b-blue",
|
"931b-blue-plumage-Disabled",
|
||||||
"931b-green",
|
"931b-green-plumage-Disabled",
|
||||||
"931b-green",
|
"931b-green-plumage-Disabled",
|
||||||
"931b-white",
|
"931b-white-plumage-Disabled",
|
||||||
"931b-white",
|
"931b-white-plumage-Disabled",
|
||||||
"931b-yellow",
|
"931b-yellow-plumage-Disabled",
|
||||||
"931b-yellow",
|
"931b-yellow-plumage-Disabled",
|
||||||
"932b",
|
"932b",
|
||||||
"932b",
|
"932b",
|
||||||
"933b",
|
"933b",
|
||||||
"933b",
|
"933b",
|
||||||
"934b",
|
"934b",
|
||||||
"934b",
|
"934b",
|
||||||
"935b",
|
"935b-Disabled",
|
||||||
"935b",
|
"935b-Disabled",
|
||||||
"936b",
|
"936b-Disabled",
|
||||||
"936b",
|
"936b-Disabled",
|
||||||
"937b",
|
"937b-Disabled",
|
||||||
"937b",
|
"937b-Disabled",
|
||||||
"938b",
|
"938b",
|
||||||
"938b",
|
"938b",
|
||||||
"939b",
|
"939b",
|
||||||
@ -2251,10 +2253,10 @@
|
|||||||
"1005sb",
|
"1005sb",
|
||||||
"1006sb",
|
"1006sb",
|
||||||
"1006sb",
|
"1006sb",
|
||||||
"1007sb-apex",
|
"1007sb-apex-build-Disabled",
|
||||||
"1007sb-apex",
|
"1007sb-apex-build-Disabled",
|
||||||
"1008sb-ultimate",
|
"1008sb-ultimate-mode-Disabled",
|
||||||
"1008sb-ultimate",
|
"1008sb-ultimate-mode-Disabled",
|
||||||
"115sb-mega",
|
"115sb-mega",
|
||||||
"115sb-mega",
|
"115sb-mega",
|
||||||
"127sb-mega",
|
"127sb-mega",
|
||||||
@ -3063,8 +3065,8 @@
|
|||||||
"873sb",
|
"873sb",
|
||||||
"874sb",
|
"874sb",
|
||||||
"874sb",
|
"874sb",
|
||||||
"875sb-no",
|
"875sb-no-ice",
|
||||||
"875sb-no",
|
"875sb-no-ice",
|
||||||
"875sb",
|
"875sb",
|
||||||
"875sb",
|
"875sb",
|
||||||
"876sb-female",
|
"876sb-female",
|
||||||
@ -3203,26 +3205,26 @@
|
|||||||
"929sb",
|
"929sb",
|
||||||
"930sb",
|
"930sb",
|
||||||
"930sb",
|
"930sb",
|
||||||
"931sb-blue",
|
"931sb-blue-plumage-Disabled",
|
||||||
"931sb-blue",
|
"931sb-blue-plumage-Disabled",
|
||||||
"931sb-green",
|
"931sb-green-plumage-Disabled",
|
||||||
"931sb-green",
|
"931sb-green-plumage-Disabled",
|
||||||
"931sb-white",
|
"931sb-white-plumage-Disabled",
|
||||||
"931sb-white",
|
"931sb-white-plumage-Disabled",
|
||||||
"931sb-yellow",
|
"931sb-yellow-plumage-Disabled",
|
||||||
"931sb-yellow",
|
"931sb-yellow-plumage-Disabled",
|
||||||
"932sb",
|
"932sb",
|
||||||
"932sb",
|
"932sb",
|
||||||
"933sb",
|
"933sb",
|
||||||
"933sb",
|
"933sb",
|
||||||
"934sb",
|
"934sb",
|
||||||
"934sb",
|
"934sb",
|
||||||
"935sb",
|
"935sb-Disabled",
|
||||||
"935sb",
|
"935sb-Disabled",
|
||||||
"936sb",
|
"936sb-Disabled",
|
||||||
"936sb",
|
"936sb-Disabled",
|
||||||
"937sb",
|
"937sb-Disabled",
|
||||||
"937sb",
|
"937sb-Disabled",
|
||||||
"938sb",
|
"938sb",
|
||||||
"938sb",
|
"938sb",
|
||||||
"939sb",
|
"939sb",
|
||||||
@ -3376,10 +3378,10 @@
|
|||||||
"1005s",
|
"1005s",
|
||||||
"1006s",
|
"1006s",
|
||||||
"1006s",
|
"1006s",
|
||||||
"1007s-apex",
|
"1007s-apex-build-Disabled",
|
||||||
"1007s-apex",
|
"1007s-apex-build-Disabled",
|
||||||
"1008s-ultimate",
|
"1008s-ultimate-mode-Disabled",
|
||||||
"1008s-ultimate",
|
"1008s-ultimate-mode-Disabled",
|
||||||
"115s-mega",
|
"115s-mega",
|
||||||
"115s-mega",
|
"115s-mega",
|
||||||
"127s-mega",
|
"127s-mega",
|
||||||
@ -4188,8 +4190,8 @@
|
|||||||
"873s",
|
"873s",
|
||||||
"874s",
|
"874s",
|
||||||
"874s",
|
"874s",
|
||||||
"875s-no",
|
"875s-no-ice",
|
||||||
"875s-no",
|
"875s-no-ice",
|
||||||
"875s",
|
"875s",
|
||||||
"875s",
|
"875s",
|
||||||
"876s-female",
|
"876s-female",
|
||||||
@ -4328,26 +4330,26 @@
|
|||||||
"929s",
|
"929s",
|
||||||
"930s",
|
"930s",
|
||||||
"930s",
|
"930s",
|
||||||
"931s-blue",
|
"931s-blue-plumage-Disabled",
|
||||||
"931s-blue",
|
"931s-blue-plumage-Disabled",
|
||||||
"931s-green",
|
"931s-green-plumage-Disabled",
|
||||||
"931s-green",
|
"931s-green-plumage-Disabled",
|
||||||
"931s-white",
|
"931s-white-plumage-Disabled",
|
||||||
"931s-white",
|
"931s-white-plumage-Disabled",
|
||||||
"931s-yellow",
|
"931s-yellow-plumage-Disabled",
|
||||||
"931s-yellow",
|
"931s-yellow-plumage-Disabled",
|
||||||
"932s",
|
"932s",
|
||||||
"932s",
|
"932s",
|
||||||
"933s",
|
"933s",
|
||||||
"933s",
|
"933s",
|
||||||
"934s",
|
"934s",
|
||||||
"934s",
|
"934s",
|
||||||
"935s",
|
"935s-Disabled",
|
||||||
"935s",
|
"935s-Disabled",
|
||||||
"936s",
|
"936s-Disabled",
|
||||||
"936s",
|
"936s-Disabled",
|
||||||
"937s",
|
"937s-Disabled",
|
||||||
"937s",
|
"937s-Disabled",
|
||||||
"938s",
|
"938s",
|
||||||
"938s",
|
"938s",
|
||||||
"939s",
|
"939s",
|
||||||
@ -4438,6 +4440,8 @@
|
|||||||
"978s-droopy",
|
"978s-droopy",
|
||||||
"978s-stretchy",
|
"978s-stretchy",
|
||||||
"978s-stretchy",
|
"978s-stretchy",
|
||||||
|
"979s-Disabled",
|
||||||
|
"979s-Disabled",
|
||||||
"980s",
|
"980s",
|
||||||
"980s",
|
"980s",
|
||||||
"981s",
|
"981s",
|
||||||
@ -4485,11 +4489,10 @@
|
|||||||
"1000",
|
"1000",
|
||||||
"1001",
|
"1001",
|
||||||
"1004",
|
"1004",
|
||||||
"1007-apex",
|
"1007-apex-build-Disabled",
|
||||||
"1007-apex",
|
"1007-apex-build-Disabled",
|
||||||
"1007-apex",
|
"1008-ultimate-mode-Disabled",
|
||||||
"1007-apex",
|
"1008-ultimate-mode-Disabled",
|
||||||
"1008-ultimate",
|
|
||||||
"127-mega",
|
"127-mega",
|
||||||
"142-mega",
|
"142-mega",
|
||||||
"150-mega",
|
"150-mega",
|
||||||
@ -4698,21 +4701,21 @@
|
|||||||
"933_3",
|
"933_3",
|
||||||
"933_3",
|
"933_3",
|
||||||
"934",
|
"934",
|
||||||
"935",
|
"935-Disabled",
|
||||||
"935_3",
|
"935_3-Disabled",
|
||||||
"935_3",
|
"935_3-Disabled",
|
||||||
"936_1",
|
"936_1-Disabled",
|
||||||
"936_1",
|
"936_1-Disabled",
|
||||||
"936_2",
|
"936_2-Disabled",
|
||||||
"936_2",
|
"936_2-Disabled",
|
||||||
"936_3",
|
"936_3-Disabled",
|
||||||
"936_3",
|
"936_3-Disabled",
|
||||||
"937_1",
|
"937_1-Disabled",
|
||||||
"937_1",
|
"937_1-Disabled",
|
||||||
"937_2",
|
"937_2-Disabled",
|
||||||
"937_2",
|
"937_2-Disabled",
|
||||||
"937_3",
|
"937_3-Disabled",
|
||||||
"937_3",
|
"937_3-Disabled",
|
||||||
"94-mega_1",
|
"94-mega_1",
|
||||||
"94-mega_1",
|
"94-mega_1",
|
||||||
"94-mega_2",
|
"94-mega_2",
|
||||||
@ -4755,11 +4758,10 @@
|
|||||||
"1000b",
|
"1000b",
|
||||||
"1001b",
|
"1001b",
|
||||||
"1004b",
|
"1004b",
|
||||||
"1007b-apex",
|
"1007b-apex-build-Disabled",
|
||||||
"1007b-apex",
|
"1007b-apex-build-Disabled",
|
||||||
"1007b-apex",
|
"1008b-ultimate-mode-Disabled",
|
||||||
"1007b-apex",
|
"1008b-ultimate-mode-Disabled",
|
||||||
"1008b-ultimate",
|
|
||||||
"127b-mega",
|
"127b-mega",
|
||||||
"142b-mega",
|
"142b-mega",
|
||||||
"150b-mega",
|
"150b-mega",
|
||||||
@ -4920,24 +4922,24 @@
|
|||||||
"932b",
|
"932b",
|
||||||
"933b",
|
"933b",
|
||||||
"934b",
|
"934b",
|
||||||
"935_1b",
|
"935_1b-Disabled",
|
||||||
"935_1b",
|
"935_1b-Disabled",
|
||||||
"935_2b",
|
"935_2b-Disabled",
|
||||||
"935_2b",
|
"935_2b-Disabled",
|
||||||
"935_3b",
|
"935_3b-Disabled",
|
||||||
"935_3b",
|
"935_3b-Disabled",
|
||||||
"936_1b",
|
"936_1b-Disabled",
|
||||||
"936_1b",
|
"936_1b-Disabled",
|
||||||
"936_2b",
|
"936_2b-Disabled",
|
||||||
"936_2b",
|
"936_2b-Disabled",
|
||||||
"936_3b",
|
"936_3b-Disabled",
|
||||||
"936_3b",
|
"936_3b-Disabled",
|
||||||
"937_1b",
|
"937_1b-Disabled",
|
||||||
"937_1b",
|
"937_1b-Disabled",
|
||||||
"937_2b",
|
"937_2b-Disabled",
|
||||||
"937_2b",
|
"937_2b-Disabled",
|
||||||
"937_3b",
|
"937_3b-Disabled",
|
||||||
"937_3b",
|
"937_3b-Disabled",
|
||||||
"94b-mega",
|
"94b-mega",
|
||||||
"948b",
|
"948b",
|
||||||
"949b",
|
"949b",
|
||||||
|
BIN
public/images/types_de.png
Normal file → Executable file
BIN
public/images/types_de.png
Normal file → Executable file
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.6 KiB |
@ -168,6 +168,8 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
|||||||
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import { initGlobalScene } from "#app/global-scene";
|
import { initGlobalScene } from "#app/global-scene";
|
||||||
|
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
|
||||||
|
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
||||||
|
|
||||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||||
|
|
||||||
@ -2904,6 +2906,21 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues an ability bar flyout phase
|
||||||
|
* @param pokemon The pokemon who has the ability
|
||||||
|
* @param passive Whether the ability is a passive
|
||||||
|
* @param show Whether to show or hide the bar
|
||||||
|
*/
|
||||||
|
public queueAbilityDisplay(pokemon: Pokemon, passive: boolean, show: boolean): void {
|
||||||
|
this.unshiftPhase(
|
||||||
|
show
|
||||||
|
? new ShowAbilityPhase(pokemon.getBattlerIndex(), passive)
|
||||||
|
: new HideAbilityPhase(pokemon.getBattlerIndex(), passive),
|
||||||
|
);
|
||||||
|
this.clearPhaseQueueSplice();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
* Moves everything from nextCommandPhaseQueue to phaseQueue (keeping order)
|
||||||
*/
|
*/
|
||||||
@ -3133,6 +3150,41 @@ export default class BattleScene extends SceneBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, transferQuantity = 1): boolean {
|
||||||
|
const mod = itemModifier.clone() as PokemonHeldItemModifier;
|
||||||
|
const source = mod.pokemonId ? mod.getPokemon() : null;
|
||||||
|
const cancelled = new Utils.BooleanHolder(false);
|
||||||
|
|
||||||
|
if (source && source.isPlayer() !== target.isPlayer()) {
|
||||||
|
applyAbAttrs(BlockItemTheftAbAttr, source, cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancelled.value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchingModifier = this.findModifier(
|
||||||
|
m => m instanceof PokemonHeldItemModifier && m.matchType(mod) && m.pokemonId === target.id,
|
||||||
|
target.isPlayer(),
|
||||||
|
) as PokemonHeldItemModifier;
|
||||||
|
|
||||||
|
if (matchingModifier) {
|
||||||
|
const maxStackCount = matchingModifier.getMaxStackCount();
|
||||||
|
if (matchingModifier.stackCount >= maxStackCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const countTaken = Math.min(transferQuantity, mod.stackCount, maxStackCount - matchingModifier.stackCount);
|
||||||
|
mod.stackCount -= countTaken;
|
||||||
|
} else {
|
||||||
|
const countTaken = Math.min(transferQuantity, mod.stackCount);
|
||||||
|
mod.stackCount -= countTaken;
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeOld = mod.stackCount === 0;
|
||||||
|
|
||||||
|
return !removeOld || !source || this.hasModifier(itemModifier, !source.isPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
removePartyMemberModifiers(partyMemberIndex: number): Promise<void> {
|
removePartyMemberModifiers(partyMemberIndex: number): Promise<void> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const pokemonId = this.getPlayerParty()[partyMemberIndex].id;
|
const pokemonId = this.getPlayerParty()[partyMemberIndex].id;
|
||||||
@ -3290,6 +3342,11 @@ export default class BattleScene extends SceneBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasModifier(modifier: PersistentModifier, enemy = false): boolean {
|
||||||
|
const modifiers = !enemy ? this.modifiers : this.enemyModifiers;
|
||||||
|
return modifiers.indexOf(modifier) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a currently owned item. If the item is stacked, the entire item stack
|
* Removes a currently owned item. If the item is stacked, the entire item stack
|
||||||
* gets removed. This function does NOT apply in-battle effects, such as Unburden.
|
* gets removed. This function does NOT apply in-battle effects, such as Unburden.
|
||||||
|
3014
src/data/ability.ts
3014
src/data/ability.ts
File diff suppressed because it is too large
Load Diff
@ -64,7 +64,7 @@ export abstract class ArenaTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onOverlap(_arena: Arena): void {}
|
onOverlap(_arena: Arena, _source: Pokemon | null): void {}
|
||||||
|
|
||||||
lapse(_arena: Arena): boolean {
|
lapse(_arena: Arena): boolean {
|
||||||
return this.turnCount < 1 || !!--this.turnCount;
|
return this.turnCount < 1 || !!--this.turnCount;
|
||||||
@ -706,7 +706,7 @@ export class ArenaTrapTag extends ArenaTag {
|
|||||||
this.maxLayers = maxLayers;
|
this.maxLayers = maxLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
onOverlap(arena: Arena): void {
|
onOverlap(arena: Arena, _source: Pokemon | null): void {
|
||||||
if (this.layers < this.maxLayers) {
|
if (this.layers < this.maxLayers) {
|
||||||
this.layers++;
|
this.layers++;
|
||||||
|
|
||||||
@ -1427,13 +1427,9 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
public override onAdd(_arena: Arena): void {
|
public override onAdd(_arena: Arena): void {
|
||||||
const pokemon = this.getSourcePokemon();
|
const pokemon = this.getSourcePokemon();
|
||||||
if (pokemon) {
|
if (pokemon) {
|
||||||
globalScene.queueMessage(
|
this.playActivationMessage(pokemon);
|
||||||
i18next.t("arenaTag:neutralizingGasOnAdd", {
|
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const fieldPokemon of globalScene.getField()) {
|
for (const fieldPokemon of globalScene.getField(true)) {
|
||||||
if (fieldPokemon && fieldPokemon.id !== pokemon.id) {
|
if (fieldPokemon && fieldPokemon.id !== pokemon.id) {
|
||||||
[true, false].forEach(passive => applyOnLoseAbAttrs(fieldPokemon, passive));
|
[true, false].forEach(passive => applyOnLoseAbAttrs(fieldPokemon, passive));
|
||||||
}
|
}
|
||||||
@ -1441,8 +1437,9 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override onOverlap(_arena: Arena): void {
|
public override onOverlap(_arena: Arena, source: Pokemon | null): void {
|
||||||
this.sourceCount++;
|
this.sourceCount++;
|
||||||
|
this.playActivationMessage(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onSourceLeave(arena: Arena): void {
|
public onSourceLeave(arena: Arena): void {
|
||||||
@ -1466,7 +1463,7 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
globalScene.queueMessage(i18next.t("arenaTag:neutralizingGasOnRemove"));
|
globalScene.queueMessage(i18next.t("arenaTag:neutralizingGasOnRemove"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const pokemon of globalScene.getField()) {
|
for (const pokemon of globalScene.getField(true)) {
|
||||||
// There is only one pokemon with this attr on the field on removal, so its abilities are already active
|
// There is only one pokemon with this attr on the field on removal, so its abilities are already active
|
||||||
if (pokemon && !pokemon.hasAbilityWithAttr(PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr, false)) {
|
if (pokemon && !pokemon.hasAbilityWithAttr(PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr, false)) {
|
||||||
[true, false].forEach(passive => applyOnGainAbAttrs(pokemon, passive));
|
[true, false].forEach(passive => applyOnGainAbAttrs(pokemon, passive));
|
||||||
@ -1481,6 +1478,16 @@ export class SuppressAbilitiesTag extends ArenaTag {
|
|||||||
public isBeingRemoved() {
|
public isBeingRemoved() {
|
||||||
return this.beingRemoved;
|
return this.beingRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private playActivationMessage(pokemon: Pokemon | null) {
|
||||||
|
if (pokemon) {
|
||||||
|
globalScene.queueMessage(
|
||||||
|
i18next.t("arenaTag:neutralizingGasOnAdd", {
|
||||||
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter
|
// TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter
|
||||||
|
@ -1680,7 +1680,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||||
},
|
},
|
||||||
[Biome.METROPOLIS]: {
|
[Biome.METROPOLIS]: {
|
||||||
[BiomePoolTier.COMMON]: [ TrainerType.CLERK, TrainerType.CYCLIST, TrainerType.OFFICER, TrainerType.WAITER ],
|
[BiomePoolTier.COMMON]: [ TrainerType.CLERK, TrainerType.CYCLIST, TrainerType.OFFICER, TrainerType.WAITER, TrainerType.BEAUTY ],
|
||||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.BREEDER, TrainerType.DEPOT_AGENT, TrainerType.GUITARIST ],
|
[BiomePoolTier.UNCOMMON]: [ TrainerType.BREEDER, TrainerType.DEPOT_AGENT, TrainerType.GUITARIST ],
|
||||||
[BiomePoolTier.RARE]: [ TrainerType.ARTIST ],
|
[BiomePoolTier.RARE]: [ TrainerType.ARTIST ],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
@ -1713,7 +1713,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||||
},
|
},
|
||||||
[Biome.SWAMP]: {
|
[Biome.SWAMP]: {
|
||||||
[BiomePoolTier.COMMON]: [],
|
[BiomePoolTier.COMMON]: [ TrainerType.PARASOL_LADY ],
|
||||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER ],
|
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER ],
|
||||||
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
@ -1724,7 +1724,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||||
},
|
},
|
||||||
[Biome.BEACH]: {
|
[Biome.BEACH]: {
|
||||||
[BiomePoolTier.COMMON]: [ TrainerType.FISHERMAN, TrainerType.PARASOL_LADY, TrainerType.SAILOR ],
|
[BiomePoolTier.COMMON]: [ TrainerType.FISHERMAN, TrainerType.SAILOR ],
|
||||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BREEDER ],
|
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BREEDER ],
|
||||||
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
@ -1735,7 +1735,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||||
},
|
},
|
||||||
[Biome.LAKE]: {
|
[Biome.LAKE]: {
|
||||||
[BiomePoolTier.COMMON]: [ TrainerType.BREEDER, TrainerType.FISHERMAN ],
|
[BiomePoolTier.COMMON]: [ TrainerType.BREEDER, TrainerType.FISHERMAN, TrainerType.PARASOL_LADY ],
|
||||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER ],
|
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER ],
|
||||||
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
[BiomePoolTier.RARE]: [ TrainerType.BLACK_BELT ],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
@ -1790,7 +1790,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||||
},
|
},
|
||||||
[Biome.DESERT]: {
|
[Biome.DESERT]: {
|
||||||
[BiomePoolTier.COMMON]: [ TrainerType.SCIENTIST ],
|
[BiomePoolTier.COMMON]: [ TrainerType.SCIENTIST, TrainerType.BACKPACKER ],
|
||||||
[BiomePoolTier.UNCOMMON]: [],
|
[BiomePoolTier.UNCOMMON]: [],
|
||||||
[BiomePoolTier.RARE]: [],
|
[BiomePoolTier.RARE]: [],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
@ -1812,8 +1812,8 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
[BiomePoolTier.BOSS_ULTRA_RARE]: []
|
||||||
},
|
},
|
||||||
[Biome.MEADOW]: {
|
[Biome.MEADOW]: {
|
||||||
[BiomePoolTier.COMMON]: [ TrainerType.PARASOL_LADY ],
|
[BiomePoolTier.COMMON]: [ TrainerType.PARASOL_LADY, TrainerType.BEAUTY ],
|
||||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BREEDER ],
|
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BREEDER, TrainerType.BAKER ],
|
||||||
[BiomePoolTier.RARE]: [],
|
[BiomePoolTier.RARE]: [],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
[BiomePoolTier.ULTRA_RARE]: [],
|
[BiomePoolTier.ULTRA_RARE]: [],
|
||||||
@ -1879,7 +1879,7 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
|||||||
},
|
},
|
||||||
[Biome.RUINS]: {
|
[Biome.RUINS]: {
|
||||||
[BiomePoolTier.COMMON]: [ TrainerType.PSYCHIC, TrainerType.SCIENTIST ],
|
[BiomePoolTier.COMMON]: [ TrainerType.PSYCHIC, TrainerType.SCIENTIST ],
|
||||||
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BLACK_BELT ],
|
[BiomePoolTier.UNCOMMON]: [ TrainerType.ACE_TRAINER, TrainerType.BLACK_BELT, TrainerType.HEX_MANIAC ],
|
||||||
[BiomePoolTier.RARE]: [],
|
[BiomePoolTier.RARE]: [],
|
||||||
[BiomePoolTier.SUPER_RARE]: [],
|
[BiomePoolTier.SUPER_RARE]: [],
|
||||||
[BiomePoolTier.ULTRA_RARE]: [],
|
[BiomePoolTier.ULTRA_RARE]: [],
|
||||||
@ -7165,14 +7165,18 @@ export function initBiomes() {
|
|||||||
[ Biome.MOUNTAIN, BiomePoolTier.COMMON ],
|
[ Biome.MOUNTAIN, BiomePoolTier.COMMON ],
|
||||||
[ Biome.CAVE, BiomePoolTier.COMMON ],
|
[ Biome.CAVE, BiomePoolTier.COMMON ],
|
||||||
[ Biome.BADLANDS, BiomePoolTier.COMMON ],
|
[ Biome.BADLANDS, BiomePoolTier.COMMON ],
|
||||||
[ Biome.JUNGLE, BiomePoolTier.COMMON ]
|
[ Biome.JUNGLE, BiomePoolTier.COMMON ],
|
||||||
|
[ Biome.DESERT, BiomePoolTier.COMMON ]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
[ TrainerType.BAKER, [
|
[ TrainerType.BAKER, [
|
||||||
[ Biome.SLUM, BiomePoolTier.UNCOMMON ]
|
[ Biome.SLUM, BiomePoolTier.UNCOMMON ],
|
||||||
|
[ Biome.MEADOW, BiomePoolTier.UNCOMMON ]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
[ TrainerType.BEAUTY, [
|
[ TrainerType.BEAUTY, [
|
||||||
|
[ Biome.METROPOLIS, BiomePoolTier.COMMON ],
|
||||||
|
[ Biome.MEADOW, BiomePoolTier.COMMON ],
|
||||||
[ Biome.FAIRY_CAVE, BiomePoolTier.COMMON ]
|
[ Biome.FAIRY_CAVE, BiomePoolTier.COMMON ]
|
||||||
]],
|
]],
|
||||||
[ TrainerType.BIKER, [
|
[ TrainerType.BIKER, [
|
||||||
@ -7247,7 +7251,8 @@ export function initBiomes() {
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
[ TrainerType.PARASOL_LADY, [
|
[ TrainerType.PARASOL_LADY, [
|
||||||
[ Biome.BEACH, BiomePoolTier.COMMON ],
|
[ Biome.SWAMP, BiomePoolTier.COMMON ],
|
||||||
|
[ Biome.LAKE, BiomePoolTier.COMMON ],
|
||||||
[ Biome.MEADOW, BiomePoolTier.COMMON ]
|
[ Biome.MEADOW, BiomePoolTier.COMMON ]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
@ -7313,6 +7318,7 @@ export function initBiomes() {
|
|||||||
]
|
]
|
||||||
],
|
],
|
||||||
[ TrainerType.HEX_MANIAC, [
|
[ TrainerType.HEX_MANIAC, [
|
||||||
|
[ Biome.RUINS, BiomePoolTier.UNCOMMON ],
|
||||||
[ Biome.GRAVEYARD, BiomePoolTier.UNCOMMON ]
|
[ Biome.GRAVEYARD, BiomePoolTier.UNCOMMON ]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
162
src/data/balance/signature-species.ts
Normal file
162
src/data/balance/signature-species.ts
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import { Species } from "#enums/species";
|
||||||
|
|
||||||
|
export type SignatureSpecies = {
|
||||||
|
[key in string]: (Species | Species[])[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The signature species for each Gym Leader, Elite Four member, and Champion.
|
||||||
|
* The key is the trainer type, and the value is an array of Species or Species arrays.
|
||||||
|
* This is in a separate const so it can be accessed from other places and not just the trainerConfigs
|
||||||
|
*/
|
||||||
|
export const signatureSpecies: SignatureSpecies = {
|
||||||
|
// Gym Leaders- Kanto
|
||||||
|
BROCK: [Species.GEODUDE, Species.ONIX],
|
||||||
|
MISTY: [Species.STARYU, Species.PSYDUCK],
|
||||||
|
LT_SURGE: [Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ],
|
||||||
|
ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP],
|
||||||
|
JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT],
|
||||||
|
SABRINA: [Species.ABRA, Species.MR_MIME, Species.ESPEON],
|
||||||
|
BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGMAR],
|
||||||
|
GIOVANNI: [Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F],
|
||||||
|
// Gym Leaders- Johto
|
||||||
|
FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.DODUO],
|
||||||
|
BUGSY: [Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR],
|
||||||
|
WHITNEY: [Species.JIGGLYPUFF, Species.MILTANK, Species.AIPOM, Species.GIRAFARIG],
|
||||||
|
MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE],
|
||||||
|
CHUCK: [Species.POLIWRATH, Species.MANKEY],
|
||||||
|
JASMINE: [Species.MAGNEMITE, Species.STEELIX],
|
||||||
|
PRYCE: [Species.SEEL, Species.SWINUB],
|
||||||
|
CLAIR: [Species.DRATINI, Species.HORSEA, Species.GYARADOS],
|
||||||
|
// Gym Leaders- Hoenn
|
||||||
|
ROXANNE: [Species.GEODUDE, Species.NOSEPASS],
|
||||||
|
BRAWLY: [Species.MACHOP, Species.MAKUHITA],
|
||||||
|
WATTSON: [Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE],
|
||||||
|
FLANNERY: [Species.SLUGMA, Species.TORKOAL, Species.NUMEL],
|
||||||
|
NORMAN: [Species.SLAKOTH, Species.SPINDA, Species.ZIGZAGOON, Species.KECLEON],
|
||||||
|
WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY],
|
||||||
|
TATE: [Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE],
|
||||||
|
LIZA: [Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR],
|
||||||
|
JUAN: [Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH],
|
||||||
|
// Gym Leaders- Sinnoh
|
||||||
|
ROARK: [Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE],
|
||||||
|
GARDENIA: [Species.ROSELIA, Species.TANGELA, Species.TURTWIG],
|
||||||
|
MAYLENE: [Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR],
|
||||||
|
CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP],
|
||||||
|
FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB],
|
||||||
|
BYRON: [Species.SHIELDON, Species.BRONZOR, Species.AGGRON],
|
||||||
|
CANDICE: [Species.SNEASEL, Species.SNOVER, Species.SNORUNT],
|
||||||
|
VOLKNER: [Species.SHINX, Species.CHINCHOU, Species.ROTOM],
|
||||||
|
// Gym Leaders- Unova
|
||||||
|
CILAN: [Species.PANSAGE, Species.FOONGUS, Species.PETILIL],
|
||||||
|
CHILI: [Species.PANSEAR, Species.DARUMAKA, Species.NUMEL],
|
||||||
|
CRESS: [Species.PANPOUR, Species.TYMPOLE, Species.SLOWPOKE],
|
||||||
|
CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE],
|
||||||
|
LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO],
|
||||||
|
ROXIE: [Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI],
|
||||||
|
BURGH: [Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST],
|
||||||
|
ELESA: [Species.EMOLGA, Species.BLITZLE, Species.JOLTIK],
|
||||||
|
CLAY: [Species.DRILBUR, Species.SANDILE, Species.GOLETT],
|
||||||
|
SKYLA: [Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET],
|
||||||
|
BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO],
|
||||||
|
DRAYDEN: [Species.DRUDDIGON, Species.AXEW, Species.DEINO],
|
||||||
|
MARLON: [Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA],
|
||||||
|
// Gym Leaders- Kalos
|
||||||
|
VIOLA: [Species.SURSKIT, Species.SCATTERBUG],
|
||||||
|
GRANT: [Species.AMAURA, Species.TYRUNT],
|
||||||
|
KORRINA: [Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO],
|
||||||
|
RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT],
|
||||||
|
CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA],
|
||||||
|
VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME],
|
||||||
|
OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.SLOWKING],
|
||||||
|
WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL],
|
||||||
|
// Gym Leaders- Galar
|
||||||
|
MILO: [Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET],
|
||||||
|
NESSA: [Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD],
|
||||||
|
KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL],
|
||||||
|
BEA: [Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS],
|
||||||
|
ALLISTER: [Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY],
|
||||||
|
OPAL: [Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING],
|
||||||
|
BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR],
|
||||||
|
GORDIE: [Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE],
|
||||||
|
MELONY: [Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME],
|
||||||
|
PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY],
|
||||||
|
MARNIE: [Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO],
|
||||||
|
RAIHAN: [Species.DURALUDON, Species.TURTONATOR, Species.GOOMY],
|
||||||
|
// Gym Leaders- Paldea; First slot is Tera
|
||||||
|
KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA], // Tera Bug Teddiursa
|
||||||
|
BRASSIUS: [Species.SUDOWOODO, Species.BRAMBLIN, Species.SMOLIV], // Tera Grass Sudowoodo
|
||||||
|
IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL], // Tera Ghost Misdreavus
|
||||||
|
KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler
|
||||||
|
LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly
|
||||||
|
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
|
||||||
|
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
|
||||||
|
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.CUBCHOO, Species.ALOLA_VULPIX], // Tera Ice Swablu
|
||||||
|
|
||||||
|
// Elite Four- Kanto
|
||||||
|
LORELEI: [
|
||||||
|
Species.JYNX,
|
||||||
|
[Species.SLOWBRO, Species.GALAR_SLOWBRO],
|
||||||
|
Species.LAPRAS,
|
||||||
|
[Species.CLOYSTER, Species.ALOLA_SANDSLASH],
|
||||||
|
],
|
||||||
|
BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]],
|
||||||
|
AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK],
|
||||||
|
LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR],
|
||||||
|
// Elite Four- Johto (Bruno included)
|
||||||
|
WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR],
|
||||||
|
KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL],
|
||||||
|
KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE],
|
||||||
|
// Elite Four- Hoenn
|
||||||
|
SIDNEY: [
|
||||||
|
[Species.SHIFTRY, Species.CACTURNE],
|
||||||
|
[Species.SHARPEDO, Species.CRAWDAUNT],
|
||||||
|
Species.ABSOL,
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
],
|
||||||
|
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]],
|
||||||
|
GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW],
|
||||||
|
DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA],
|
||||||
|
// Elite Four- Sinnoh
|
||||||
|
AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION],
|
||||||
|
BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR],
|
||||||
|
FLINT: [
|
||||||
|
[Species.RAPIDASH, Species.FLAREON],
|
||||||
|
Species.MAGMORTAR,
|
||||||
|
[Species.STEELIX, Species.LOPUNNY],
|
||||||
|
Species.INFERNAPE,
|
||||||
|
], // Tera Fire Steelix or Lopunny
|
||||||
|
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]],
|
||||||
|
// Elite Four- Unova
|
||||||
|
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT],
|
||||||
|
MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK],
|
||||||
|
GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE],
|
||||||
|
CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS],
|
||||||
|
// Elite Four- Kalos
|
||||||
|
MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME],
|
||||||
|
SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE],
|
||||||
|
WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH],
|
||||||
|
DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN],
|
||||||
|
// Elite Four- Alola
|
||||||
|
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]],
|
||||||
|
MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO],
|
||||||
|
OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC],
|
||||||
|
ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND],
|
||||||
|
KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
|
||||||
|
// Elite Four- Galar
|
||||||
|
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL],
|
||||||
|
NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW],
|
||||||
|
BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP],
|
||||||
|
ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR],
|
||||||
|
RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON],
|
||||||
|
// Elite Four- Paldea
|
||||||
|
RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire
|
||||||
|
POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton
|
||||||
|
LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio
|
||||||
|
HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur
|
||||||
|
// Elite Four- BBL
|
||||||
|
CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom
|
||||||
|
AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross
|
||||||
|
LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill
|
||||||
|
DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon
|
||||||
|
};
|
@ -1922,10 +1922,6 @@ export class SlowStartTag extends AbilityBattlerTag {
|
|||||||
i18next.t("battlerTags:slowStartOnAdd", {
|
i18next.t("battlerTags:slowStartOnAdd", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
}),
|
}),
|
||||||
null,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5542,6 +5542,31 @@ export class LeechSeedAttr extends AddBattlerTagAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the appropriate battler tag for Smack Down and Thousand arrows
|
||||||
|
* @extends AddBattlerTagAttr
|
||||||
|
*/
|
||||||
|
export class FallDownAttr extends AddBattlerTagAttr {
|
||||||
|
constructor() {
|
||||||
|
super(BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds Grounded Tag to the target and checks if fallDown message should be displayed
|
||||||
|
* @param user the {@linkcode Pokemon} using the move
|
||||||
|
* @param target the {@linkcode Pokemon} targeted by the move
|
||||||
|
* @param move the {@linkcode Move} invoking this effect
|
||||||
|
* @param args n/a
|
||||||
|
* @returns `true` if the effect successfully applies; `false` otherwise
|
||||||
|
*/
|
||||||
|
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
|
||||||
|
if (!target.isGrounded()) {
|
||||||
|
globalScene.queueMessage(i18next.t("moveTriggers:fallDown", { targetPokemonName: getPokemonNameWithAffix(target) }));
|
||||||
|
}
|
||||||
|
return super.apply(user, target, move, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the appropriate battler tag for Gulp Missile when Surf or Dive is used.
|
* Adds the appropriate battler tag for Gulp Missile when Surf or Dive is used.
|
||||||
* @extends MoveEffectAttr
|
* @extends MoveEffectAttr
|
||||||
@ -9646,7 +9671,7 @@ export function initMoves() {
|
|||||||
.target(MoveTarget.BOTH_SIDES)
|
.target(MoveTarget.BOTH_SIDES)
|
||||||
.unimplemented(),
|
.unimplemented(),
|
||||||
new AttackMove(Moves.SMACK_DOWN, PokemonType.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5)
|
new AttackMove(Moves.SMACK_DOWN, PokemonType.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
.attr(FallDownAttr)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
||||||
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ])
|
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ])
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||||
@ -10097,7 +10122,7 @@ export function initMoves() {
|
|||||||
.triageMove(),
|
.triageMove(),
|
||||||
new AttackMove(Moves.THOUSAND_ARROWS, PokemonType.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
new AttackMove(Moves.THOUSAND_ARROWS, PokemonType.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6)
|
||||||
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
.attr(NeutralDamageAgainstFlyingTypeMultiplierAttr)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true)
|
.attr(FallDownAttr)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
.attr(HitsTagAttr, BattlerTagType.FLYING)
|
||||||
.attr(HitsTagAttr, BattlerTagType.FLOATING)
|
.attr(HitsTagAttr, BattlerTagType.FLOATING)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
|
||||||
|
@ -2987,11 +2987,11 @@ export function initSpecies() {
|
|||||||
new PokemonSpecies(Species.VAROOM, 9, false, false, false, "Single-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1, 35, Abilities.OVERCOAT, Abilities.NONE, Abilities.SLOW_START, 300, 45, 70, 63, 30, 45, 47, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
|
new PokemonSpecies(Species.VAROOM, 9, false, false, false, "Single-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1, 35, Abilities.OVERCOAT, Abilities.NONE, Abilities.SLOW_START, 300, 45, 70, 63, 30, 45, 47, 190, 50, 60, GrowthRate.MEDIUM_FAST, 50, false),
|
||||||
new PokemonSpecies(Species.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, false,
|
new PokemonSpecies(Species.REVAVROOM, 9, false, false, false, "Multi-Cyl Pokémon", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, false,
|
||||||
new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, false, null, true),
|
new PokemonForm("Normal", "", PokemonType.STEEL, PokemonType.POISON, 1.8, 120, Abilities.OVERCOAT, Abilities.NONE, Abilities.FILTER, 500, 80, 119, 90, 54, 67, 90, 75, 50, 175, false, null, true),
|
||||||
new PokemonForm("Segin Starmobile", "segin-starmobile", PokemonType.STEEL, PokemonType.DARK, 1.8, 240, Abilities.INTIMIDATE, Abilities.NONE, Abilities.INTIMIDATE, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175),
|
new PokemonForm("Segin Starmobile", "segin-starmobile", PokemonType.STEEL, PokemonType.DARK, 1.8, 240, Abilities.INTIMIDATE, Abilities.NONE, Abilities.INTIMIDATE, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
|
||||||
new PokemonForm("Schedar Starmobile", "schedar-starmobile", PokemonType.STEEL, PokemonType.FIRE, 1.8, 240, Abilities.SPEED_BOOST, Abilities.NONE, Abilities.SPEED_BOOST, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175),
|
new PokemonForm("Schedar Starmobile", "schedar-starmobile", PokemonType.STEEL, PokemonType.FIRE, 1.8, 240, Abilities.SPEED_BOOST, Abilities.NONE, Abilities.SPEED_BOOST, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
|
||||||
new PokemonForm("Navi Starmobile", "navi-starmobile", PokemonType.STEEL, PokemonType.POISON, 1.8, 240, Abilities.TOXIC_DEBRIS, Abilities.NONE, Abilities.TOXIC_DEBRIS, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175),
|
new PokemonForm("Navi Starmobile", "navi-starmobile", PokemonType.STEEL, PokemonType.POISON, 1.8, 240, Abilities.TOXIC_DEBRIS, Abilities.NONE, Abilities.TOXIC_DEBRIS, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
|
||||||
new PokemonForm("Ruchbah Starmobile", "ruchbah-starmobile", PokemonType.STEEL, PokemonType.FAIRY, 1.8, 240, Abilities.MISTY_SURGE, Abilities.NONE, Abilities.MISTY_SURGE, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175),
|
new PokemonForm("Ruchbah Starmobile", "ruchbah-starmobile", PokemonType.STEEL, PokemonType.FAIRY, 1.8, 240, Abilities.MISTY_SURGE, Abilities.NONE, Abilities.MISTY_SURGE, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
|
||||||
new PokemonForm("Caph Starmobile", "caph-starmobile", PokemonType.STEEL, PokemonType.FIGHTING, 1.8, 240, Abilities.STAMINA, Abilities.NONE, Abilities.STAMINA, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175),
|
new PokemonForm("Caph Starmobile", "caph-starmobile", PokemonType.STEEL, PokemonType.FIGHTING, 1.8, 240, Abilities.STAMINA, Abilities.NONE, Abilities.STAMINA, 600, 110, 129, 100, 77, 79, 105, 75, 50, 175, false, null, false, true),
|
||||||
),
|
),
|
||||||
new PokemonSpecies(Species.CYCLIZAR, 9, false, false, false, "Mount Pokémon", PokemonType.DRAGON, PokemonType.NORMAL, 1.6, 63, Abilities.SHED_SKIN, Abilities.NONE, Abilities.REGENERATOR, 501, 70, 95, 65, 85, 65, 121, 190, 50, 175, GrowthRate.MEDIUM_SLOW, 50, false),
|
new PokemonSpecies(Species.CYCLIZAR, 9, false, false, false, "Mount Pokémon", PokemonType.DRAGON, PokemonType.NORMAL, 1.6, 63, Abilities.SHED_SKIN, Abilities.NONE, Abilities.REGENERATOR, 501, 70, 95, 65, 85, 65, 121, 190, 50, 175, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||||
new PokemonSpecies(Species.ORTHWORM, 9, false, false, false, "Earthworm Pokémon", PokemonType.STEEL, null, 2.5, 310, Abilities.EARTH_EATER, Abilities.NONE, Abilities.SAND_VEIL, 480, 70, 85, 145, 60, 55, 65, 25, 50, 240, GrowthRate.SLOW, 50, false),
|
new PokemonSpecies(Species.ORTHWORM, 9, false, false, false, "Earthworm Pokémon", PokemonType.STEEL, null, 2.5, 310, Abilities.EARTH_EATER, Abilities.NONE, Abilities.SAND_VEIL, 480, 70, 85, 145, 60, 55, 65, 25, 50, 240, GrowthRate.SLOW, 50, false),
|
||||||
|
@ -22,6 +22,8 @@ import { PartyMemberStrength } from "#enums/party-member-strength";
|
|||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
|
import { signatureSpecies } from "./balance/signature-species";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
|
||||||
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
||||||
const ELITE_FOUR_MINIMUM_BST = 460;
|
const ELITE_FOUR_MINIMUM_BST = 460;
|
||||||
@ -1744,148 +1746,6 @@ function getSpeciesFilterRandomPartyMemberFunc(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type SignatureSpecies = {
|
|
||||||
[key in string]: (Species | Species[])[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The signature species for each Gym Leader, Elite Four member, and Champion.
|
|
||||||
* The key is the trainer type, and the value is an array of Species or Species arrays.
|
|
||||||
* This is in a separate const so it can be accessed from other places and not just the trainerConfigs
|
|
||||||
*/
|
|
||||||
export const signatureSpecies: SignatureSpecies = {
|
|
||||||
BROCK: [Species.GEODUDE, Species.ONIX],
|
|
||||||
MISTY: [Species.STARYU, Species.PSYDUCK],
|
|
||||||
LT_SURGE: [Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ],
|
|
||||||
ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP],
|
|
||||||
JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT],
|
|
||||||
SABRINA: [Species.ABRA, Species.MR_MIME, Species.ESPEON],
|
|
||||||
BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGMAR],
|
|
||||||
GIOVANNI: [Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F],
|
|
||||||
FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.DODUO],
|
|
||||||
BUGSY: [Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR],
|
|
||||||
WHITNEY: [Species.JIGGLYPUFF, Species.MILTANK, Species.AIPOM, Species.GIRAFARIG],
|
|
||||||
MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE],
|
|
||||||
CHUCK: [Species.POLIWRATH, Species.MANKEY],
|
|
||||||
JASMINE: [Species.MAGNEMITE, Species.STEELIX],
|
|
||||||
PRYCE: [Species.SEEL, Species.SWINUB],
|
|
||||||
CLAIR: [Species.DRATINI, Species.HORSEA, Species.GYARADOS],
|
|
||||||
ROXANNE: [Species.GEODUDE, Species.NOSEPASS],
|
|
||||||
BRAWLY: [Species.MACHOP, Species.MAKUHITA],
|
|
||||||
WATTSON: [Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE],
|
|
||||||
FLANNERY: [Species.SLUGMA, Species.TORKOAL, Species.NUMEL],
|
|
||||||
NORMAN: [Species.SLAKOTH, Species.SPINDA, Species.ZIGZAGOON, Species.KECLEON],
|
|
||||||
WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY],
|
|
||||||
TATE: [Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE],
|
|
||||||
LIZA: [Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR],
|
|
||||||
JUAN: [Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH],
|
|
||||||
ROARK: [Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE],
|
|
||||||
GARDENIA: [Species.ROSELIA, Species.TANGELA, Species.TURTWIG],
|
|
||||||
MAYLENE: [Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR],
|
|
||||||
CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP],
|
|
||||||
FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB],
|
|
||||||
BYRON: [Species.SHIELDON, Species.BRONZOR, Species.AGGRON],
|
|
||||||
CANDICE: [Species.SNEASEL, Species.SNOVER, Species.SNORUNT],
|
|
||||||
VOLKNER: [Species.SHINX, Species.CHINCHOU, Species.ROTOM],
|
|
||||||
CILAN: [Species.PANSAGE, Species.FOONGUS, Species.PETILIL],
|
|
||||||
CHILI: [Species.PANSEAR, Species.DARUMAKA, Species.NUMEL],
|
|
||||||
CRESS: [Species.PANPOUR, Species.TYMPOLE, Species.SLOWPOKE],
|
|
||||||
CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE],
|
|
||||||
LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO],
|
|
||||||
ROXIE: [Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI],
|
|
||||||
BURGH: [Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST],
|
|
||||||
ELESA: [Species.EMOLGA, Species.BLITZLE, Species.JOLTIK],
|
|
||||||
CLAY: [Species.DRILBUR, Species.SANDILE, Species.GOLETT],
|
|
||||||
SKYLA: [Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET],
|
|
||||||
BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO],
|
|
||||||
DRAYDEN: [Species.DRUDDIGON, Species.AXEW, Species.DEINO],
|
|
||||||
MARLON: [Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA],
|
|
||||||
VIOLA: [Species.SURSKIT, Species.SCATTERBUG],
|
|
||||||
GRANT: [Species.AMAURA, Species.TYRUNT],
|
|
||||||
KORRINA: [Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO],
|
|
||||||
RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT],
|
|
||||||
CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA],
|
|
||||||
VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME],
|
|
||||||
OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.SLOWKING],
|
|
||||||
WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL],
|
|
||||||
MILO: [Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET],
|
|
||||||
NESSA: [Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD],
|
|
||||||
KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL],
|
|
||||||
BEA: [Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS],
|
|
||||||
ALLISTER: [Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY],
|
|
||||||
OPAL: [Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING],
|
|
||||||
BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR],
|
|
||||||
GORDIE: [Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE],
|
|
||||||
MELONY: [Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME],
|
|
||||||
PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY],
|
|
||||||
MARNIE: [Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO],
|
|
||||||
RAIHAN: [Species.DURALUDON, Species.TURTONATOR, Species.GOOMY],
|
|
||||||
KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA], // Tera Bug Teddiursa
|
|
||||||
BRASSIUS: [Species.SUDOWOODO, Species.BRAMBLIN, Species.SMOLIV], // Tera Grass Sudowoodo
|
|
||||||
IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL], // Tera Ghost Misdreavus
|
|
||||||
KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler
|
|
||||||
LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly
|
|
||||||
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
|
|
||||||
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
|
|
||||||
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.CUBCHOO, Species.ALOLA_VULPIX], // Tera Ice Swablu
|
|
||||||
LORELEI: [
|
|
||||||
Species.JYNX,
|
|
||||||
[Species.SLOWBRO, Species.GALAR_SLOWBRO],
|
|
||||||
Species.LAPRAS,
|
|
||||||
[Species.CLOYSTER, Species.ALOLA_SANDSLASH],
|
|
||||||
],
|
|
||||||
BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]],
|
|
||||||
AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK],
|
|
||||||
LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR],
|
|
||||||
WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR],
|
|
||||||
KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL],
|
|
||||||
KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE],
|
|
||||||
SIDNEY: [
|
|
||||||
[Species.SHIFTRY, Species.CACTURNE],
|
|
||||||
[Species.SHARPEDO, Species.CRAWDAUNT],
|
|
||||||
Species.ABSOL,
|
|
||||||
Species.MIGHTYENA,
|
|
||||||
],
|
|
||||||
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]],
|
|
||||||
GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW],
|
|
||||||
DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA],
|
|
||||||
AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION],
|
|
||||||
BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR],
|
|
||||||
FLINT: [
|
|
||||||
[Species.RAPIDASH, Species.FLAREON],
|
|
||||||
Species.MAGMORTAR,
|
|
||||||
[Species.STEELIX, Species.LOPUNNY],
|
|
||||||
Species.INFERNAPE,
|
|
||||||
], // Tera Fire Steelix or Lopunny
|
|
||||||
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]],
|
|
||||||
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT],
|
|
||||||
MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK],
|
|
||||||
GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE],
|
|
||||||
CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS],
|
|
||||||
MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME],
|
|
||||||
SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE],
|
|
||||||
WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH],
|
|
||||||
DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN],
|
|
||||||
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]],
|
|
||||||
MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO],
|
|
||||||
OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC],
|
|
||||||
ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND],
|
|
||||||
KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
|
|
||||||
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL],
|
|
||||||
NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW],
|
|
||||||
BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP],
|
|
||||||
ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR],
|
|
||||||
RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON],
|
|
||||||
RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire
|
|
||||||
POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton
|
|
||||||
LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio
|
|
||||||
HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur
|
|
||||||
CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom
|
|
||||||
AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross
|
|
||||||
LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill
|
|
||||||
DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon
|
|
||||||
};
|
|
||||||
|
|
||||||
export const trainerConfigs: TrainerConfigs = {
|
export const trainerConfigs: TrainerConfigs = {
|
||||||
[TrainerType.UNKNOWN]: new TrainerConfig(0).setHasGenders(),
|
[TrainerType.UNKNOWN]: new TrainerConfig(0).setHasGenders(),
|
||||||
[TrainerType.ACE_TRAINER]: new TrainerConfig(++t)
|
[TrainerType.ACE_TRAINER]: new TrainerConfig(++t)
|
||||||
@ -1952,12 +1812,92 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
[TrainerType.BAKER]: new TrainerConfig(++t)
|
[TrainerType.BAKER]: new TrainerConfig(++t)
|
||||||
.setEncounterBgm(TrainerType.CLERK)
|
.setEncounterBgm(TrainerType.CLERK)
|
||||||
.setMoneyMultiplier(1.35)
|
.setMoneyMultiplier(1.35)
|
||||||
.setSpeciesFilter(s => s.isOfType(PokemonType.GRASS) || s.isOfType(PokemonType.FIRE)),
|
.setSpeciesFilter(
|
||||||
[TrainerType.BEAUTY]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.PARASOL_LADY),
|
s =>
|
||||||
|
[s.ability1, s.ability2, s.abilityHidden].some(
|
||||||
|
a =>
|
||||||
|
!!a &&
|
||||||
|
[
|
||||||
|
Abilities.WHITE_SMOKE,
|
||||||
|
Abilities.GLUTTONY,
|
||||||
|
Abilities.HONEY_GATHER,
|
||||||
|
Abilities.HARVEST,
|
||||||
|
Abilities.CHEEK_POUCH,
|
||||||
|
Abilities.SWEET_VEIL,
|
||||||
|
Abilities.RIPEN,
|
||||||
|
Abilities.PURIFYING_SALT,
|
||||||
|
Abilities.WELL_BAKED_BODY,
|
||||||
|
Abilities.SUPERSWEET_SYRUP,
|
||||||
|
Abilities.HOSPITALITY,
|
||||||
|
].includes(a),
|
||||||
|
) ||
|
||||||
|
s
|
||||||
|
.getLevelMoves()
|
||||||
|
.some(plm =>
|
||||||
|
[Moves.SOFT_BOILED, Moves.SPORE, Moves.MILK_DRINK, Moves.OVERHEAT, Moves.TEATIME].includes(plm[1]),
|
||||||
|
),
|
||||||
|
), // Mons with baking related abilities or who learn Overheat, Teatime, Milk Drink, Spore, or Soft-Boiled by level
|
||||||
|
[TrainerType.BEAUTY]: new TrainerConfig(++t)
|
||||||
|
.setMoneyMultiplier(1.55)
|
||||||
|
.setEncounterBgm(TrainerType.PARASOL_LADY)
|
||||||
|
.setPartyTemplates(
|
||||||
|
trainerPartyTemplates.TWO_AVG_SAME_ONE_AVG,
|
||||||
|
trainerPartyTemplates.TWO_AVG_SAME_ONE_STRONG,
|
||||||
|
trainerPartyTemplates.THREE_AVG_SAME,
|
||||||
|
trainerPartyTemplates.THREE_AVG,
|
||||||
|
trainerPartyTemplates.FOUR_WEAK,
|
||||||
|
trainerPartyTemplates.ONE_STRONG,
|
||||||
|
)
|
||||||
|
.setSpeciesPools({
|
||||||
|
[TrainerPoolTier.COMMON]: [
|
||||||
|
Species.MEOWTH,
|
||||||
|
Species.GOLDEEN,
|
||||||
|
Species.MAREEP,
|
||||||
|
Species.MARILL,
|
||||||
|
Species.SKITTY,
|
||||||
|
Species.GLAMEOW,
|
||||||
|
Species.PURRLOIN,
|
||||||
|
],
|
||||||
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
|
Species.SMOOCHUM,
|
||||||
|
Species.ROSELIA,
|
||||||
|
Species.LUVDISC,
|
||||||
|
Species.BLITZLE,
|
||||||
|
Species.SEWADDLE,
|
||||||
|
Species.PETILIL,
|
||||||
|
Species.MINCCINO,
|
||||||
|
Species.GOTHITA,
|
||||||
|
Species.SPRITZEE,
|
||||||
|
Species.FLITTLE,
|
||||||
|
],
|
||||||
|
[TrainerPoolTier.RARE]: [
|
||||||
|
Species.FEEBAS,
|
||||||
|
Species.FURFROU,
|
||||||
|
Species.SALANDIT,
|
||||||
|
Species.BRUXISH,
|
||||||
|
Species.HATENNA,
|
||||||
|
Species.SNOM,
|
||||||
|
Species.ALOLA_VULPIX,
|
||||||
|
],
|
||||||
|
[TrainerPoolTier.SUPER_RARE]: [Species.CLAMPERL, Species.AMAURA, Species.SYLVEON, Species.GOOMY, Species.POPPLIO],
|
||||||
|
}),
|
||||||
[TrainerType.BIKER]: new TrainerConfig(++t)
|
[TrainerType.BIKER]: new TrainerConfig(++t)
|
||||||
.setMoneyMultiplier(1.4)
|
.setMoneyMultiplier(1.4)
|
||||||
.setEncounterBgm(TrainerType.ROUGHNECK)
|
.setEncounterBgm(TrainerType.ROUGHNECK)
|
||||||
.setSpeciesFilter(s => s.isOfType(PokemonType.POISON)),
|
.setSpeciesPools({
|
||||||
|
[TrainerPoolTier.COMMON]: [Species.EKANS, Species.KOFFING, Species.CROAGUNK, Species.VENIPEDE, Species.SCRAGGY],
|
||||||
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
|
Species.GRIMER,
|
||||||
|
Species.VOLTORB,
|
||||||
|
Species.TEDDIURSA,
|
||||||
|
Species.MAGBY,
|
||||||
|
Species.SKORUPI,
|
||||||
|
Species.SANDILE,
|
||||||
|
Species.PAWNIARD,
|
||||||
|
Species.SHROODLE,
|
||||||
|
],
|
||||||
|
[TrainerPoolTier.RARE]: [Species.VAROOM, Species.CYCLIZAR],
|
||||||
|
}),
|
||||||
[TrainerType.BLACK_BELT]: new TrainerConfig(++t)
|
[TrainerType.BLACK_BELT]: new TrainerConfig(++t)
|
||||||
.setHasGenders("Battle Girl", TrainerType.PSYCHIC)
|
.setHasGenders("Battle Girl", TrainerType.PSYCHIC)
|
||||||
.setHasDouble("Crush Kin")
|
.setHasDouble("Crush Kin")
|
||||||
@ -2059,9 +1999,15 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
.setEncounterBgm(TrainerType.CYCLIST)
|
.setEncounterBgm(TrainerType.CYCLIST)
|
||||||
.setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG)
|
.setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG)
|
||||||
.setSpeciesPools({
|
.setSpeciesPools({
|
||||||
[TrainerPoolTier.COMMON]: [Species.PICHU, Species.STARLY, Species.TAILLOW, Species.BOLTUND],
|
[TrainerPoolTier.COMMON]: [Species.DODUO, Species.PICHU, Species.TAILLOW, Species.STARLY, Species.PONYTA],
|
||||||
[TrainerPoolTier.UNCOMMON]: [Species.DODUO, Species.ELECTRIKE, Species.BLITZLE, Species.WATTREL],
|
[TrainerPoolTier.UNCOMMON]: [
|
||||||
[TrainerPoolTier.RARE]: [Species.YANMA, Species.NINJASK, Species.WHIRLIPEDE, Species.EMOLGA],
|
Species.ELECTRIKE,
|
||||||
|
Species.SHINX,
|
||||||
|
Species.BLITZLE,
|
||||||
|
Species.DUCKLETT,
|
||||||
|
Species.WATTREL,
|
||||||
|
],
|
||||||
|
[TrainerPoolTier.RARE]: [Species.YANMA, Species.NINJASK, Species.WHIRLIPEDE, Species.EMOLGA, Species.SKIDDO],
|
||||||
[TrainerPoolTier.SUPER_RARE]: [Species.ACCELGOR, Species.DREEPY],
|
[TrainerPoolTier.SUPER_RARE]: [Species.ACCELGOR, Species.DREEPY],
|
||||||
}),
|
}),
|
||||||
[TrainerType.DANCER]: new TrainerConfig(++t)
|
[TrainerType.DANCER]: new TrainerConfig(++t)
|
||||||
@ -2077,7 +2023,7 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
[TrainerPoolTier.COMMON]: [Species.RALTS, Species.SPOINK, Species.LOTAD, Species.BUDEW],
|
[TrainerPoolTier.COMMON]: [Species.RALTS, Species.SPOINK, Species.LOTAD, Species.BUDEW],
|
||||||
[TrainerPoolTier.UNCOMMON]: [Species.SPINDA, Species.SWABLU, Species.MARACTUS],
|
[TrainerPoolTier.UNCOMMON]: [Species.SPINDA, Species.SWABLU, Species.MARACTUS],
|
||||||
[TrainerPoolTier.RARE]: [Species.BELLOSSOM, Species.HITMONTOP, Species.MIME_JR, Species.ORICORIO],
|
[TrainerPoolTier.RARE]: [Species.BELLOSSOM, Species.HITMONTOP, Species.MIME_JR, Species.ORICORIO],
|
||||||
[TrainerPoolTier.SUPER_RARE]: [Species.POPPLIO],
|
[TrainerPoolTier.SUPER_RARE]: [Species.QUAXLY, Species.JANGMO_O],
|
||||||
}),
|
}),
|
||||||
[TrainerType.DEPOT_AGENT]: new TrainerConfig(++t).setMoneyMultiplier(1.45).setEncounterBgm(TrainerType.CLERK),
|
[TrainerType.DEPOT_AGENT]: new TrainerConfig(++t).setMoneyMultiplier(1.45).setEncounterBgm(TrainerType.CLERK),
|
||||||
[TrainerType.DOCTOR]: new TrainerConfig(++t)
|
[TrainerType.DOCTOR]: new TrainerConfig(++t)
|
||||||
@ -2215,7 +2161,7 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
trainerPartyTemplates.THREE_AVG,
|
trainerPartyTemplates.THREE_AVG,
|
||||||
trainerPartyTemplates.TWO_STRONG,
|
trainerPartyTemplates.TWO_STRONG,
|
||||||
)
|
)
|
||||||
.setSpeciesFilter(s => s.isOfType(PokemonType.GHOST)),
|
.setSpeciesFilter(s => s.isOfType(PokemonType.GHOST) || s.isOfType(PokemonType.PSYCHIC)),
|
||||||
[TrainerType.NURSERY_AIDE]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm("lass"),
|
[TrainerType.NURSERY_AIDE]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm("lass"),
|
||||||
[TrainerType.OFFICER]: new TrainerConfig(++t)
|
[TrainerType.OFFICER]: new TrainerConfig(++t)
|
||||||
.setMoneyMultiplier(1.55)
|
.setMoneyMultiplier(1.55)
|
||||||
@ -2245,7 +2191,28 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
[TrainerType.PARASOL_LADY]: new TrainerConfig(++t)
|
[TrainerType.PARASOL_LADY]: new TrainerConfig(++t)
|
||||||
.setMoneyMultiplier(1.55)
|
.setMoneyMultiplier(1.55)
|
||||||
.setEncounterBgm(TrainerType.PARASOL_LADY)
|
.setEncounterBgm(TrainerType.PARASOL_LADY)
|
||||||
.setSpeciesFilter(s => s.isOfType(PokemonType.WATER)),
|
.setPartyTemplates(
|
||||||
|
trainerPartyTemplates.TWO_AVG_SAME_ONE_AVG,
|
||||||
|
trainerPartyTemplates.TWO_AVG_SAME_ONE_STRONG,
|
||||||
|
trainerPartyTemplates.TWO_AVG,
|
||||||
|
trainerPartyTemplates.FOUR_WEAK,
|
||||||
|
trainerPartyTemplates.ONE_STRONG,
|
||||||
|
)
|
||||||
|
.setSpeciesFilter(
|
||||||
|
s =>
|
||||||
|
[s.ability1, s.ability2, s.abilityHidden].some(
|
||||||
|
a =>
|
||||||
|
!!a &&
|
||||||
|
[
|
||||||
|
Abilities.DRIZZLE,
|
||||||
|
Abilities.SWIFT_SWIM,
|
||||||
|
Abilities.HYDRATION,
|
||||||
|
Abilities.RAIN_DISH,
|
||||||
|
Abilities.DRY_SKIN,
|
||||||
|
Abilities.WIND_POWER,
|
||||||
|
].includes(a),
|
||||||
|
) || s.getLevelMoves().some(plm => plm[1] === Moves.RAIN_DANCE),
|
||||||
|
), // Mons with rain abilities or who learn Rain Dance by level
|
||||||
[TrainerType.PILOT]: new TrainerConfig(++t)
|
[TrainerType.PILOT]: new TrainerConfig(++t)
|
||||||
.setEncounterBgm(TrainerType.CLERK)
|
.setEncounterBgm(TrainerType.CLERK)
|
||||||
.setSpeciesFilter(s => tmSpecies[Moves.FLY].indexOf(s.speciesId) > -1),
|
.setSpeciesFilter(s => tmSpecies[Moves.FLY].indexOf(s.speciesId) > -1),
|
||||||
|
@ -303,6 +303,11 @@ export class Arena {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns weather or not the weather can be changed to {@linkcode weather} */
|
||||||
|
canSetWeather(weather: WeatherType): boolean {
|
||||||
|
return !(this.weather?.weatherType === (weather || undefined));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to set a new weather to the battle
|
* Attempts to set a new weather to the battle
|
||||||
* @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set
|
* @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set
|
||||||
@ -314,7 +319,7 @@ export class Arena {
|
|||||||
return this.trySetWeatherOverride(Overrides.WEATHER_OVERRIDE);
|
return this.trySetWeatherOverride(Overrides.WEATHER_OVERRIDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.weather?.weatherType === (weather || undefined)) {
|
if (!this.canSetWeather(weather)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,8 +393,13 @@ export class Arena {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether or not the terrain can be set to {@linkcode terrain} */
|
||||||
|
canSetTerrain(terrain: TerrainType): boolean {
|
||||||
|
return !(this.terrain?.terrainType === (terrain || undefined));
|
||||||
|
}
|
||||||
|
|
||||||
trySetTerrain(terrain: TerrainType, hasPokemonSource: boolean, ignoreAnim = false): boolean {
|
trySetTerrain(terrain: TerrainType, hasPokemonSource: boolean, ignoreAnim = false): boolean {
|
||||||
if (this.terrain?.terrainType === (terrain || undefined)) {
|
if (!this.canSetTerrain(terrain)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,7 +673,7 @@ export class Arena {
|
|||||||
): boolean {
|
): boolean {
|
||||||
const existingTag = this.getTagOnSide(tagType, side);
|
const existingTag = this.getTagOnSide(tagType, side);
|
||||||
if (existingTag) {
|
if (existingTag) {
|
||||||
existingTag.onOverlap(this);
|
existingTag.onOverlap(this, globalScene.getPokemonById(sourceId));
|
||||||
|
|
||||||
if (existingTag instanceof ArenaTrapTag) {
|
if (existingTag instanceof ArenaTrapTag) {
|
||||||
const { tagType, side, turnCount, layers, maxLayers } = existingTag as ArenaTrapTag;
|
const { tagType, side, turnCount, layers, maxLayers } = existingTag as ArenaTrapTag;
|
||||||
|
@ -6916,10 +6916,10 @@ export class EnemyPokemon extends Pokemon {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
speciesId in Overrides.OPP_FORM_OVERRIDES &&
|
speciesId in Overrides.OPP_FORM_OVERRIDES &&
|
||||||
Overrides.OPP_FORM_OVERRIDES[speciesId] &&
|
!isNullOrUndefined(Overrides.OPP_FORM_OVERRIDES[speciesId]) &&
|
||||||
this.species.forms[Overrides.OPP_FORM_OVERRIDES[speciesId]]
|
this.species.forms[Overrides.OPP_FORM_OVERRIDES[speciesId]]
|
||||||
) {
|
) {
|
||||||
this.formIndex = Overrides.OPP_FORM_OVERRIDES[speciesId] ?? 0;
|
this.formIndex = Overrides.OPP_FORM_OVERRIDES[speciesId];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dataSource) {
|
if (!dataSource) {
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
TrainerSlot,
|
TrainerSlot,
|
||||||
trainerConfigs,
|
trainerConfigs,
|
||||||
trainerPartyTemplates,
|
trainerPartyTemplates,
|
||||||
signatureSpecies,
|
|
||||||
TeraAIMode,
|
TeraAIMode,
|
||||||
} from "#app/data/trainer-config";
|
} from "#app/data/trainer-config";
|
||||||
import type { EnemyPokemon } from "#app/field/pokemon";
|
import type { EnemyPokemon } from "#app/field/pokemon";
|
||||||
@ -22,6 +21,7 @@ import i18next from "i18next";
|
|||||||
import { PartyMemberStrength } from "#enums/party-member-strength";
|
import { PartyMemberStrength } from "#enums/party-member-strength";
|
||||||
import { Species } from "#enums/species";
|
import { Species } from "#enums/species";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
|
import { signatureSpecies } from "#app/data/balance/signature-species";
|
||||||
|
|
||||||
export enum TrainerVariant {
|
export enum TrainerVariant {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
|
@ -79,6 +79,7 @@ export class LoadingScene extends SceneBase {
|
|||||||
this.loadImage("icon_owned", "ui");
|
this.loadImage("icon_owned", "ui");
|
||||||
this.loadImage("icon_egg_move", "ui");
|
this.loadImage("icon_egg_move", "ui");
|
||||||
this.loadImage("ability_bar_left", "ui");
|
this.loadImage("ability_bar_left", "ui");
|
||||||
|
this.loadImage("ability_bar_right", "ui");
|
||||||
this.loadImage("bgm_bar", "ui");
|
this.loadImage("bgm_bar", "ui");
|
||||||
this.loadImage("party_exp_bar", "ui");
|
this.loadImage("party_exp_bar", "ui");
|
||||||
this.loadImage("achv_bar", "ui");
|
this.loadImage("achv_bar", "ui");
|
||||||
|
@ -3566,10 +3566,10 @@ function getNewModifierTypeOption(
|
|||||||
} else if (upgradeCount === undefined && player) {
|
} else if (upgradeCount === undefined && player) {
|
||||||
upgradeCount = 0;
|
upgradeCount = 0;
|
||||||
if (tier < ModifierTier.MASTER && allowLuckUpgrades) {
|
if (tier < ModifierTier.MASTER && allowLuckUpgrades) {
|
||||||
const partyShinyCount = party.filter(p => p.isShiny() && !p.isFainted()).length;
|
const partyLuckValue = getPartyLuckValue(party);
|
||||||
const upgradeOdds = Math.floor(32 / ((partyShinyCount + 2) / 2));
|
const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4));
|
||||||
while (modifierPool.hasOwnProperty(tier + upgradeCount + 1) && modifierPool[tier + upgradeCount + 1].length) {
|
while (modifierPool.hasOwnProperty(tier + upgradeCount + 1) && modifierPool[tier + upgradeCount + 1].length) {
|
||||||
if (!randSeedInt(upgradeOdds)) {
|
if (randSeedInt(upgradeOdds) < 4) {
|
||||||
upgradeCount++;
|
upgradeCount++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
||||||
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
|
||||||
import { type PokeballCounts } from "#app/battle-scene";
|
import { type PokeballCounts } from "#app/battle-scene";
|
||||||
import { EvolutionItem } from "#app/data/balance/pokemon-evolutions";
|
import { EvolutionItem } from "#app/data/balance/pokemon-evolutions";
|
||||||
import { Gender } from "#app/data/gender";
|
import { Gender } from "#app/data/gender";
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
|
||||||
export class Phase {
|
export class Phase {
|
||||||
start() {
|
start() {}
|
||||||
if (globalScene.abilityBar.shown) {
|
|
||||||
globalScene.abilityBar.resetAutoHideTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end() {
|
end() {
|
||||||
globalScene.shiftPhase();
|
globalScene.shiftPhase();
|
||||||
|
27
src/phases/hide-ability-phase.ts
Normal file
27
src/phases/hide-ability-phase.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import type { BattlerIndex } from "#app/battle";
|
||||||
|
import { PokemonPhase } from "./pokemon-phase";
|
||||||
|
|
||||||
|
export class HideAbilityPhase extends PokemonPhase {
|
||||||
|
private passive: boolean;
|
||||||
|
|
||||||
|
constructor(battlerIndex: BattlerIndex, passive = false) {
|
||||||
|
super(battlerIndex);
|
||||||
|
|
||||||
|
this.passive = passive;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
const pokemon = this.getPokemon();
|
||||||
|
|
||||||
|
if (pokemon) {
|
||||||
|
globalScene.abilityBar.hide().then(() => {
|
||||||
|
this.end();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,17 +28,28 @@ export class MessagePhase extends Phase {
|
|||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
if (this.text.indexOf("$") > -1) {
|
if (this.text.indexOf("$") > -1) {
|
||||||
|
const pokename: string[] = [];
|
||||||
|
const repname = [ "#POKEMON1", "#POKEMON2" ];
|
||||||
|
for (let p = 0; p < globalScene.getPlayerField().length; p++) {
|
||||||
|
pokename.push(globalScene.getPlayerField()[p].getNameToRender());
|
||||||
|
this.text = this.text.split(pokename[p]).join(repname[p]);
|
||||||
|
}
|
||||||
const pageIndex = this.text.indexOf("$");
|
const pageIndex = this.text.indexOf("$");
|
||||||
globalScene.unshiftPhase(
|
for (let p = 0; p < globalScene.getPlayerField().length; p++) {
|
||||||
new MessagePhase(
|
this.text = this.text.split(repname[p]).join(pokename[p]);
|
||||||
this.text.slice(pageIndex + 1),
|
}
|
||||||
this.callbackDelay,
|
if (pageIndex !== -1) {
|
||||||
this.prompt,
|
globalScene.unshiftPhase(
|
||||||
this.promptDelay,
|
new MessagePhase(
|
||||||
this.speaker,
|
this.text.slice(pageIndex + 1),
|
||||||
),
|
this.callbackDelay,
|
||||||
);
|
this.prompt,
|
||||||
this.text = this.text.slice(0, pageIndex).trim();
|
this.promptDelay,
|
||||||
|
this.speaker,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
this.text = this.text.slice(0, pageIndex).trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.speaker) {
|
if (this.speaker) {
|
||||||
@ -61,12 +72,4 @@ export class MessagePhase extends Phase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end() {
|
|
||||||
if (globalScene.abilityBar.shown) {
|
|
||||||
globalScene.abilityBar.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
super.end();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -504,7 +504,7 @@ export class MovePhase extends BattlePhase {
|
|||||||
globalScene
|
globalScene
|
||||||
.getField(true)
|
.getField(true)
|
||||||
.filter(p => p !== this.pokemon)
|
.filter(p => p !== this.pokemon)
|
||||||
.forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, redirectTarget));
|
.forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, redirectTarget, this.pokemon));
|
||||||
|
|
||||||
/** `true` if an Ability is responsible for redirecting the move to another target; `false` otherwise */
|
/** `true` if an Ability is responsible for redirecting the move to another target; `false` otherwise */
|
||||||
let redirectedByAbility = currentTarget !== redirectTarget.value;
|
let redirectedByAbility = currentTarget !== redirectTarget.value;
|
||||||
|
@ -5,6 +5,8 @@ import { EFFECTIVE_STATS, BATTLE_STATS } from "#enums/stat";
|
|||||||
import { PokemonMove } from "#app/field/pokemon";
|
import { PokemonMove } from "#app/field/pokemon";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { PokemonPhase } from "./pokemon-phase";
|
import { PokemonPhase } from "./pokemon-phase";
|
||||||
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms a Pokemon into another Pokemon on the field.
|
* Transforms a Pokemon into another Pokemon on the field.
|
||||||
@ -62,6 +64,13 @@ export class PokemonTransformPhase extends PokemonPhase {
|
|||||||
globalScene.playSound("battle_anims/PRSFX- Transform");
|
globalScene.playSound("battle_anims/PRSFX- Transform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalScene.queueMessage(
|
||||||
|
i18next.t("abilityTriggers:postSummonTransform", {
|
||||||
|
pokemonNameWithAffix: getPokemonNameWithAffix(user),
|
||||||
|
targetName: target.name,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
promises.push(
|
promises.push(
|
||||||
user.loadAssets(false).then(() => {
|
user.loadAssets(false).then(() => {
|
||||||
user.playAnim();
|
user.playAnim();
|
||||||
|
@ -53,6 +53,7 @@ export class SelectStarterPhase extends Phase {
|
|||||||
let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0));
|
let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0));
|
||||||
if (
|
if (
|
||||||
starter.species.speciesId in Overrides.STARTER_FORM_OVERRIDES &&
|
starter.species.speciesId in Overrides.STARTER_FORM_OVERRIDES &&
|
||||||
|
!Utils.isNullOrUndefined(Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]) &&
|
||||||
starter.species.forms[Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]!]
|
starter.species.forms[Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]!]
|
||||||
) {
|
) {
|
||||||
starterFormIndex = Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]!;
|
starterFormIndex = Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]!;
|
||||||
|
@ -1,36 +1,60 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { BattlerIndex } from "#app/battle";
|
import type { BattlerIndex } from "#app/battle";
|
||||||
import { PokemonPhase } from "./pokemon-phase";
|
import { PokemonPhase } from "./pokemon-phase";
|
||||||
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
|
import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
|
||||||
|
|
||||||
export class ShowAbilityPhase extends PokemonPhase {
|
export class ShowAbilityPhase extends PokemonPhase {
|
||||||
private passive: boolean;
|
private passive: boolean;
|
||||||
|
private pokemonName: string;
|
||||||
|
private abilityName: string;
|
||||||
|
private pokemonOnField: boolean;
|
||||||
|
|
||||||
constructor(battlerIndex: BattlerIndex, passive = false) {
|
constructor(battlerIndex: BattlerIndex, passive = false) {
|
||||||
super(battlerIndex);
|
super(battlerIndex);
|
||||||
|
|
||||||
this.passive = passive;
|
this.passive = passive;
|
||||||
|
|
||||||
|
const pokemon = this.getPokemon();
|
||||||
|
if (pokemon) {
|
||||||
|
// Set these now as the pokemon object may change before the queued phase is run
|
||||||
|
this.pokemonName = getPokemonNameWithAffix(pokemon);
|
||||||
|
this.abilityName = (passive ? this.getPokemon().getPassiveAbility() : this.getPokemon().getAbility()).name;
|
||||||
|
this.pokemonOnField = true;
|
||||||
|
} else {
|
||||||
|
this.pokemonOnField = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
|
if (!this.pokemonOnField || !this.getPokemon()) {
|
||||||
|
return this.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the bar is already out, hide it before showing the new one
|
||||||
|
if (globalScene.abilityBar.isVisible()) {
|
||||||
|
globalScene.unshiftPhase(new HideAbilityPhase(this.battlerIndex, this.passive));
|
||||||
|
globalScene.unshiftPhase(new ShowAbilityPhase(this.battlerIndex, this.passive));
|
||||||
|
return this.end();
|
||||||
|
}
|
||||||
|
|
||||||
const pokemon = this.getPokemon();
|
const pokemon = this.getPokemon();
|
||||||
|
|
||||||
if (pokemon) {
|
if (!pokemon.isPlayer()) {
|
||||||
if (!pokemon.isPlayer()) {
|
/** If its an enemy pokemon, list it as last enemy to use ability or move */
|
||||||
/** If its an enemy pokemon, list it as last enemy to use ability or move */
|
globalScene.currentBattle.lastEnemyInvolved = pokemon.getBattlerIndex() % 2;
|
||||||
globalScene.currentBattle.lastEnemyInvolved = pokemon.getBattlerIndex() % 2;
|
} else {
|
||||||
} else {
|
globalScene.currentBattle.lastPlayerInvolved = pokemon.getBattlerIndex() % 2;
|
||||||
globalScene.currentBattle.lastPlayerInvolved = pokemon.getBattlerIndex() % 2;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
globalScene.abilityBar.showAbility(pokemon, this.passive);
|
|
||||||
|
|
||||||
|
globalScene.abilityBar.showAbility(this.pokemonName, this.abilityName, this.passive, this.player).then(() => {
|
||||||
if (pokemon?.battleData) {
|
if (pokemon?.battleData) {
|
||||||
pokemon.battleData.abilityRevealed = true;
|
pokemon.battleData.abilityRevealed = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.end();
|
this.end();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type Pokemon from "../field/pokemon";
|
|
||||||
import { TextStyle, addTextObject } from "./text";
|
import { TextStyle, addTextObject } from "./text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
const hiddenX = -118;
|
const barWidth = 118;
|
||||||
const shownX = 0;
|
const screenLeft = 0;
|
||||||
const baseY = -116;
|
const baseY = -116;
|
||||||
|
|
||||||
export default class AbilityBar extends Phaser.GameObjects.Container {
|
export default class AbilityBar extends Phaser.GameObjects.Container {
|
||||||
private bg: Phaser.GameObjects.Image;
|
private abilityBars: Phaser.GameObjects.Image[];
|
||||||
private abilityBarText: Phaser.GameObjects.Text;
|
private abilityBarText: Phaser.GameObjects.Text;
|
||||||
|
private player: boolean;
|
||||||
private tween: Phaser.Tweens.Tween | null;
|
private screenRight: number; // hold screenRight in case size changes between show and hide
|
||||||
private autoHideTimer: NodeJS.Timeout | null;
|
private shown: boolean;
|
||||||
|
|
||||||
public shown: boolean;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(globalScene, hiddenX, baseY);
|
super(globalScene, barWidth, baseY);
|
||||||
|
this.abilityBars = [];
|
||||||
|
this.player = true;
|
||||||
|
this.shown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(): void {
|
setup(): void {
|
||||||
this.bg = globalScene.add.image(0, 0, "ability_bar_left");
|
for (const key of ["ability_bar_right", "ability_bar_left"]) {
|
||||||
this.bg.setOrigin(0, 0);
|
const bar = globalScene.add.image(0, 0, key);
|
||||||
|
bar.setOrigin(0, 0);
|
||||||
this.add(this.bg);
|
bar.setVisible(false);
|
||||||
|
this.add(bar);
|
||||||
|
this.abilityBars.push(bar);
|
||||||
|
}
|
||||||
|
|
||||||
this.abilityBarText = addTextObject(15, 3, "", TextStyle.MESSAGE, {
|
this.abilityBarText = addTextObject(15, 3, "", TextStyle.MESSAGE, {
|
||||||
fontSize: "72px",
|
fontSize: "72px",
|
||||||
@ -33,72 +35,80 @@ export default class AbilityBar extends Phaser.GameObjects.Container {
|
|||||||
this.abilityBarText.setOrigin(0, 0);
|
this.abilityBarText.setOrigin(0, 0);
|
||||||
this.abilityBarText.setWordWrapWidth(600, true);
|
this.abilityBarText.setWordWrapWidth(600, true);
|
||||||
this.add(this.abilityBarText);
|
this.add(this.abilityBarText);
|
||||||
|
this.bringToTop(this.abilityBarText);
|
||||||
|
|
||||||
this.setVisible(false);
|
this.setVisible(false);
|
||||||
this.shown = false;
|
this.setX(-barWidth); // start hidden (right edge of bar at x=0)
|
||||||
}
|
}
|
||||||
|
|
||||||
showAbility(pokemon: Pokemon, passive = false): void {
|
public override setVisible(value: boolean): this {
|
||||||
this.abilityBarText.setText(
|
this.abilityBars[+this.player].setVisible(value);
|
||||||
`${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: getPokemonNameWithAffix(pokemon), passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: !passive ? pokemon.getAbility().name : pokemon.getPassiveAbility().name })}`,
|
this.shown = value;
|
||||||
);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.shown) {
|
public async startTween(config: any, text?: string): Promise<void> {
|
||||||
return;
|
this.setVisible(true);
|
||||||
|
if (text) {
|
||||||
|
this.abilityBarText.setText(text);
|
||||||
}
|
}
|
||||||
|
return new Promise(resolve => {
|
||||||
|
globalScene.tweens.add({
|
||||||
|
...config,
|
||||||
|
onComplete: () => {
|
||||||
|
if (config.onComplete) {
|
||||||
|
config.onComplete();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async showAbility(pokemonName: string, abilityName: string, passive = false, player = true): Promise<void> {
|
||||||
|
const text = `${i18next.t("fightUiHandler:abilityFlyInText", { pokemonName: pokemonName, passive: passive ? i18next.t("fightUiHandler:passive") : "", abilityName: abilityName })}`;
|
||||||
|
this.screenRight = globalScene.scaledCanvas.width;
|
||||||
|
if (player !== this.player) {
|
||||||
|
// Move the bar if it has changed from the player to enemy side (or vice versa)
|
||||||
|
this.setX(player ? -barWidth : this.screenRight);
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
globalScene.fieldUI.bringToTop(this);
|
globalScene.fieldUI.bringToTop(this);
|
||||||
|
|
||||||
this.y = baseY + (globalScene.currentBattle.double ? 14 : 0);
|
let y = baseY;
|
||||||
this.tween = globalScene.tweens.add({
|
if (this.player) {
|
||||||
targets: this,
|
y += globalScene.currentBattle.double ? 14 : 0;
|
||||||
x: shownX,
|
} else {
|
||||||
duration: 500,
|
y -= globalScene.currentBattle.double ? 28 : 14;
|
||||||
ease: "Sine.easeOut",
|
}
|
||||||
onComplete: () => {
|
|
||||||
this.tween = null;
|
|
||||||
this.resetAutoHideTimer();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setVisible(true);
|
this.setY(y);
|
||||||
this.shown = true;
|
|
||||||
|
return this.startTween(
|
||||||
|
{
|
||||||
|
targets: this,
|
||||||
|
x: this.player ? screenLeft : this.screenRight - barWidth,
|
||||||
|
duration: 500,
|
||||||
|
ease: "Sine.easeOut",
|
||||||
|
hold: 1000,
|
||||||
|
},
|
||||||
|
text,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
hide(): void {
|
public async hide(): Promise<void> {
|
||||||
if (!this.shown) {
|
return this.startTween({
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.autoHideTimer) {
|
|
||||||
clearInterval(this.autoHideTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.tween) {
|
|
||||||
this.tween.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tween = globalScene.tweens.add({
|
|
||||||
targets: this,
|
targets: this,
|
||||||
x: -91,
|
x: this.player ? -barWidth : this.screenRight,
|
||||||
duration: 500,
|
duration: 200,
|
||||||
ease: "Sine.easeIn",
|
ease: "Sine.easeIn",
|
||||||
onComplete: () => {
|
onComplete: () => {
|
||||||
this.tween = null;
|
|
||||||
this.setVisible(false);
|
this.setVisible(false);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.shown = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetAutoHideTimer(): void {
|
public isVisible(): boolean {
|
||||||
if (this.autoHideTimer) {
|
return this.shown;
|
||||||
clearInterval(this.autoHideTimer);
|
|
||||||
}
|
|
||||||
this.autoHideTimer = setTimeout(() => {
|
|
||||||
this.hide();
|
|
||||||
this.autoHideTimer = null;
|
|
||||||
}, 2500);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,12 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
|
|||||||
const fadeMap = new Map<number, number>();
|
const fadeMap = new Map<number, number>();
|
||||||
const actionPattern = /@(c|d|s|f)\{(.*?)\}/;
|
const actionPattern = /@(c|d|s|f)\{(.*?)\}/;
|
||||||
let actionMatch: RegExpExecArray | null;
|
let actionMatch: RegExpExecArray | null;
|
||||||
|
const pokename: string[] = [];
|
||||||
|
const repname = [ "#POKEMON1", "#POKEMON2" ];
|
||||||
|
for (let p = 0; p < globalScene.getPlayerField().length; p++) {
|
||||||
|
pokename.push(globalScene.getPlayerField()[p].getNameToRender());
|
||||||
|
text = text.split(pokename[p]).join(repname[p]);
|
||||||
|
}
|
||||||
while ((actionMatch = actionPattern.exec(text))) {
|
while ((actionMatch = actionPattern.exec(text))) {
|
||||||
switch (actionMatch[1]) {
|
switch (actionMatch[1]) {
|
||||||
case "c":
|
case "c":
|
||||||
@ -94,6 +100,9 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
|
|||||||
text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4);
|
text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let p = 0; p < globalScene.getPlayerField().length; p++) {
|
||||||
|
text = text.split(repname[p]).join(pokename[p]);
|
||||||
|
}
|
||||||
if (text) {
|
if (text) {
|
||||||
// Predetermine overflow line breaks to avoid words breaking while displaying
|
// Predetermine overflow line breaks to avoid words breaking while displaying
|
||||||
const textWords = text.split(" ");
|
const textWords = text.split(" ");
|
||||||
|
@ -1742,36 +1742,26 @@ export default class PokedexUiHandler extends MessageUiHandler {
|
|||||||
container.icon.setTint(0);
|
container.icon.setTint(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.eggMove1) {
|
const pairs: [boolean | undefined, Phaser.GameObjects.Image][] = [
|
||||||
container.eggMove1Icon.setVisible(true);
|
[data.eggMove1, container.eggMove1Icon],
|
||||||
} else {
|
[data.eggMove2, container.eggMove2Icon],
|
||||||
container.eggMove1Icon.setVisible(false);
|
[data.tmMove1, container.tmMove1Icon],
|
||||||
}
|
[data.tmMove2, container.tmMove2Icon],
|
||||||
if (data.eggMove2) {
|
[data.passive1, container.passive1Icon],
|
||||||
container.eggMove2Icon.setVisible(true);
|
[data.passive2, container.passive2Icon],
|
||||||
} else {
|
];
|
||||||
container.eggMove2Icon.setVisible(false);
|
|
||||||
}
|
pairs.forEach(([unlocked, icon]) => {
|
||||||
if (data.tmMove1) {
|
if (unlocked) {
|
||||||
container.tmMove1Icon.setVisible(true);
|
icon.setVisible(true);
|
||||||
} else {
|
icon.clearTint();
|
||||||
container.tmMove1Icon.setVisible(false);
|
} else if (unlocked === false) {
|
||||||
}
|
icon.setVisible(true);
|
||||||
if (data.tmMove2) {
|
icon.setTint(0x808080);
|
||||||
container.tmMove2Icon.setVisible(true);
|
} else {
|
||||||
} else {
|
icon.setVisible(false);
|
||||||
container.tmMove2Icon.setVisible(false);
|
}
|
||||||
}
|
});
|
||||||
if (data.passive1) {
|
|
||||||
container.passive1Icon.setVisible(true);
|
|
||||||
} else {
|
|
||||||
container.passive1Icon.setVisible(false);
|
|
||||||
}
|
|
||||||
if (data.passive2) {
|
|
||||||
container.passive2Icon.setVisible(true);
|
|
||||||
} else {
|
|
||||||
container.passive2Icon.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.showDecorations) {
|
if (this.showDecorations) {
|
||||||
if (this.pokerusSpecies.includes(data.species)) {
|
if (this.pokerusSpecies.includes(data.species)) {
|
||||||
|
11
src/ui/ui.ts
11
src/ui/ui.ts
@ -328,17 +328,28 @@ export default class UI extends Phaser.GameObjects.Container {
|
|||||||
prompt?: boolean | null,
|
prompt?: boolean | null,
|
||||||
promptDelay?: number | null,
|
promptDelay?: number | null,
|
||||||
): void {
|
): void {
|
||||||
|
const pokename: string[] = [];
|
||||||
|
const repname = [ "#POKEMON1", "#POKEMON2" ];
|
||||||
|
for (let p = 0; p < globalScene.getPlayerField().length; p++) {
|
||||||
|
pokename.push(globalScene.getPlayerField()[p].getNameToRender());
|
||||||
|
text = text.split(pokename[p]).join(repname[p]);
|
||||||
|
}
|
||||||
if (prompt && text.indexOf("$") > -1) {
|
if (prompt && text.indexOf("$") > -1) {
|
||||||
const messagePages = text.split(/\$/g).map(m => m.trim());
|
const messagePages = text.split(/\$/g).map(m => m.trim());
|
||||||
// biome-ignore lint/complexity/useOptionalChain: optional chain would change this to be null instead of undefined.
|
// biome-ignore lint/complexity/useOptionalChain: optional chain would change this to be null instead of undefined.
|
||||||
let showMessageAndCallback = () => callback && callback();
|
let showMessageAndCallback = () => callback && callback();
|
||||||
for (let p = messagePages.length - 1; p >= 0; p--) {
|
for (let p = messagePages.length - 1; p >= 0; p--) {
|
||||||
const originalFunc = showMessageAndCallback;
|
const originalFunc = showMessageAndCallback;
|
||||||
|
messagePages[p] = messagePages[p].split(repname[0]).join(pokename[0]);
|
||||||
|
messagePages[p] = messagePages[p].split(repname[1]).join(pokename[1]);
|
||||||
showMessageAndCallback = () => this.showText(messagePages[p], null, originalFunc, null, true);
|
showMessageAndCallback = () => this.showText(messagePages[p], null, originalFunc, null, true);
|
||||||
}
|
}
|
||||||
showMessageAndCallback();
|
showMessageAndCallback();
|
||||||
} else {
|
} else {
|
||||||
const handler = this.getHandler();
|
const handler = this.getHandler();
|
||||||
|
for (let p = 0; p < globalScene.getPlayerField().length; p++) {
|
||||||
|
text = text.split(repname[p]).join(pokename[p]);
|
||||||
|
}
|
||||||
if (handler instanceof MessageUiHandler) {
|
if (handler instanceof MessageUiHandler) {
|
||||||
(handler as MessageUiHandler).showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
(handler as MessageUiHandler).showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||||
} else {
|
} else {
|
||||||
|
115
test/abilities/lightningrod.test.ts
Normal file
115
test/abilities/lightningrod.test.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { Stat } from "#enums/stat";
|
||||||
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("Abilities - Lightningrod", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.moveset([ Moves.SPLASH, Moves.SHOCK_WAVE ])
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.battleType("double")
|
||||||
|
.disableCrits()
|
||||||
|
.enemySpecies(Species.MAGIKARP)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset(Moves.SPLASH);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should redirect electric type moves", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.LIGHTNING_ROD;
|
||||||
|
|
||||||
|
game.move.select(Moves.SHOCK_WAVE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not redirect non-electric type moves", async () => {
|
||||||
|
game.override.moveset([ Moves.SPLASH, Moves.AERIAL_ACE ]);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.LIGHTNING_ROD;
|
||||||
|
|
||||||
|
game.move.select(Moves.AERIAL_ACE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should boost the user's spatk without damaging", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.LIGHTNING_ROD;
|
||||||
|
|
||||||
|
game.move.select(Moves.SHOCK_WAVE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy2.isFullHp()).toBe(true);
|
||||||
|
expect(enemy2.getStatStage(Stat.SPATK)).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not redirect moves changed from electric type via ability", async () => {
|
||||||
|
game.override.ability(Abilities.NORMALIZE);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.LIGHTNING_ROD;
|
||||||
|
|
||||||
|
game.move.select(Moves.SHOCK_WAVE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should redirect moves changed to electric type via ability", async () => {
|
||||||
|
game.override.ability(Abilities.GALVANIZE)
|
||||||
|
.moveset(Moves.TACKLE);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.LIGHTNING_ROD;
|
||||||
|
|
||||||
|
game.move.select(Moves.TACKLE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(true);
|
||||||
|
expect(enemy2.getStatStage(Stat.SPATK)).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
@ -1,4 +1,5 @@
|
|||||||
import { BattlerIndex } from "#app/battle";
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import { PostSummonWeatherChangeAbAttr } from "#app/data/ability";
|
||||||
import { Abilities } from "#enums/abilities";
|
import { Abilities } from "#enums/abilities";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
import { Moves } from "#enums/moves";
|
import { Moves } from "#enums/moves";
|
||||||
@ -7,7 +8,7 @@ import { Species } from "#enums/species";
|
|||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/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("Abilities - Neutralizing Gas", () => {
|
describe("Abilities - Neutralizing Gas", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -155,4 +156,25 @@ describe("Abilities - Neutralizing Gas", () => {
|
|||||||
|
|
||||||
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeUndefined();
|
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not activate abilities of pokemon no longer on the field", async () => {
|
||||||
|
game.override
|
||||||
|
.battleType("single")
|
||||||
|
.ability(Abilities.NEUTRALIZING_GAS)
|
||||||
|
.enemyAbility(Abilities.DELTA_STREAM);
|
||||||
|
await game.classicMode.startBattle([ Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
|
const weatherChangeAttr = enemy.getAbilityAttrs(PostSummonWeatherChangeAbAttr, false)[0];
|
||||||
|
vi.spyOn(weatherChangeAttr, "applyPostSummon");
|
||||||
|
|
||||||
|
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined();
|
||||||
|
|
||||||
|
game.move.select(Moves.SPLASH);
|
||||||
|
await game.killPokemon(enemy);
|
||||||
|
await game.killPokemon(game.scene.getPlayerPokemon()!);
|
||||||
|
|
||||||
|
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeUndefined();
|
||||||
|
expect(weatherChangeAttr.applyPostSummon).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
115
test/abilities/storm_drain.test.ts
Normal file
115
test/abilities/storm_drain.test.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { BattlerIndex } from "#app/battle";
|
||||||
|
import { Abilities } from "#enums/abilities";
|
||||||
|
import { Moves } from "#enums/moves";
|
||||||
|
import { Species } from "#enums/species";
|
||||||
|
import { Stat } from "#enums/stat";
|
||||||
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("Abilities - Storm Drain", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
game.override
|
||||||
|
.moveset([ Moves.SPLASH, Moves.WATER_GUN ])
|
||||||
|
.ability(Abilities.BALL_FETCH)
|
||||||
|
.battleType("double")
|
||||||
|
.disableCrits()
|
||||||
|
.enemySpecies(Species.MAGIKARP)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.enemyMoveset(Moves.SPLASH);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should redirect water type moves", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.STORM_DRAIN;
|
||||||
|
|
||||||
|
game.move.select(Moves.WATER_GUN, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not redirect non-water type moves", async () => {
|
||||||
|
game.override.moveset([ Moves.SPLASH, Moves.AERIAL_ACE ]);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.STORM_DRAIN;
|
||||||
|
|
||||||
|
game.move.select(Moves.AERIAL_ACE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should boost the user's spatk without damaging", async () => {
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.STORM_DRAIN;
|
||||||
|
|
||||||
|
game.move.select(Moves.WATER_GUN, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy2.isFullHp()).toBe(true);
|
||||||
|
expect(enemy2.getStatStage(Stat.SPATK)).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not redirect moves changed from water type via ability", async () => {
|
||||||
|
game.override.ability(Abilities.NORMALIZE);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.STORM_DRAIN;
|
||||||
|
|
||||||
|
game.move.select(Moves.WATER_GUN, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should redirect moves changed to water type via ability", async () => {
|
||||||
|
game.override.ability(Abilities.LIQUID_VOICE)
|
||||||
|
.moveset(Moves.PSYCHIC_NOISE);
|
||||||
|
await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]);
|
||||||
|
|
||||||
|
const enemy1 = game.scene.getEnemyField()[0];
|
||||||
|
const enemy2 = game.scene.getEnemyField()[1];
|
||||||
|
|
||||||
|
enemy2.summonData.ability = Abilities.STORM_DRAIN;
|
||||||
|
|
||||||
|
game.move.select(Moves.PSYCHIC_NOISE, BattlerIndex.PLAYER, BattlerIndex.ENEMY);
|
||||||
|
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER_2);
|
||||||
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
|
expect(enemy1.isFullHp()).toBe(true);
|
||||||
|
expect(enemy2.getStatStage(Stat.SPATK)).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
@ -27,8 +27,8 @@ describe("Moves - Chilly Reception", () => {
|
|||||||
.battleType("single")
|
.battleType("single")
|
||||||
.moveset([Moves.CHILLY_RECEPTION, Moves.SNOWSCAPE])
|
.moveset([Moves.CHILLY_RECEPTION, Moves.SNOWSCAPE])
|
||||||
.enemyMoveset(Array(4).fill(Moves.SPLASH))
|
.enemyMoveset(Array(4).fill(Moves.SPLASH))
|
||||||
.enemyAbility(Abilities.NONE)
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
.ability(Abilities.NONE);
|
.ability(Abilities.BALL_FETCH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should still change the weather if user can't switch out", async () => {
|
it("should still change the weather if user can't switch out", async () => {
|
||||||
@ -72,7 +72,6 @@ describe("Moves - Chilly Reception", () => {
|
|||||||
game.override
|
game.override
|
||||||
.battleType("single")
|
.battleType("single")
|
||||||
.enemyMoveset([Moves.CHILLY_RECEPTION, Moves.TACKLE])
|
.enemyMoveset([Moves.CHILLY_RECEPTION, Moves.TACKLE])
|
||||||
.enemyAbility(Abilities.NONE)
|
|
||||||
.moveset(Array(4).fill(Moves.SPLASH));
|
.moveset(Array(4).fill(Moves.SPLASH));
|
||||||
|
|
||||||
await game.classicMode.startBattle([Species.SLOWKING, Species.MEOWTH]);
|
await game.classicMode.startBattle([Species.SLOWKING, Species.MEOWTH]);
|
||||||
@ -89,7 +88,6 @@ describe("Moves - Chilly Reception", () => {
|
|||||||
.battleType("single")
|
.battleType("single")
|
||||||
.startingWave(8)
|
.startingWave(8)
|
||||||
.enemyMoveset(Array(4).fill(Moves.CHILLY_RECEPTION))
|
.enemyMoveset(Array(4).fill(Moves.CHILLY_RECEPTION))
|
||||||
.enemyAbility(Abilities.NONE)
|
|
||||||
.enemySpecies(Species.MAGIKARP)
|
.enemySpecies(Species.MAGIKARP)
|
||||||
.moveset([Moves.SPLASH, Moves.THUNDERBOLT]);
|
.moveset([Moves.SPLASH, Moves.THUNDERBOLT]);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ describe("Moves - Secret Power", () => {
|
|||||||
await game.classicMode.startBattle([Species.BLASTOISE, Species.CHARIZARD]);
|
await game.classicMode.startBattle([Species.BLASTOISE, Species.CHARIZARD]);
|
||||||
|
|
||||||
const sereneGraceAttr = allAbilities[Abilities.SERENE_GRACE].getAttrs(MoveEffectChanceMultiplierAbAttr)[0];
|
const sereneGraceAttr = allAbilities[Abilities.SERENE_GRACE].getAttrs(MoveEffectChanceMultiplierAbAttr)[0];
|
||||||
vi.spyOn(sereneGraceAttr, "apply");
|
vi.spyOn(sereneGraceAttr, "canApply");
|
||||||
|
|
||||||
game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY);
|
game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY);
|
||||||
game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2);
|
game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2);
|
||||||
@ -86,8 +86,8 @@ describe("Moves - Secret Power", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
await game.phaseInterceptor.to("BerryPhase", false);
|
||||||
|
|
||||||
expect(sereneGraceAttr.apply).toHaveBeenCalledOnce();
|
expect(sereneGraceAttr.canApply).toHaveBeenCalledOnce();
|
||||||
expect(sereneGraceAttr.apply).toHaveLastReturnedWith(true);
|
expect(sereneGraceAttr.canApply).toHaveLastReturnedWith(true);
|
||||||
|
|
||||||
expect(rainbowEffect.apply).toHaveBeenCalledTimes(0);
|
expect(rainbowEffect.apply).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Stat } from "#enums/stat";
|
|
||||||
import { ArenaTagSide } from "#app/data/arena-tag";
|
import { ArenaTagSide } from "#app/data/arena-tag";
|
||||||
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
import { ArenaTagType } from "#app/enums/arena-tag-type";
|
||||||
import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
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 { Stat } from "#enums/stat";
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/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";
|
||||||
@ -24,13 +24,16 @@ describe("Moves - Tailwind", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleType("double");
|
game.override
|
||||||
game.override.moveset([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]);
|
.battleType("double")
|
||||||
game.override.enemyMoveset(Moves.SPLASH);
|
.moveset([Moves.TAILWIND, Moves.SPLASH])
|
||||||
|
.enemyMoveset(Moves.SPLASH)
|
||||||
|
.enemyAbility(Abilities.BALL_FETCH)
|
||||||
|
.ability(Abilities.BALL_FETCH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("doubles the Speed stat of the Pokemons on its side", async () => {
|
it("doubles the Speed stat of the Pokemons on its side", async () => {
|
||||||
await game.startBattle([Species.MAGIKARP, Species.MEOWTH]);
|
await game.classicMode.startBattle([Species.MAGIKARP, Species.MEOWTH]);
|
||||||
const magikarp = game.scene.getPlayerField()[0];
|
const magikarp = game.scene.getPlayerField()[0];
|
||||||
const meowth = game.scene.getPlayerField()[1];
|
const meowth = game.scene.getPlayerField()[1];
|
||||||
|
|
||||||
@ -43,7 +46,7 @@ describe("Moves - Tailwind", () => {
|
|||||||
game.move.select(Moves.TAILWIND);
|
game.move.select(Moves.TAILWIND);
|
||||||
game.move.select(Moves.SPLASH, 1);
|
game.move.select(Moves.SPLASH, 1);
|
||||||
|
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
|
||||||
expect(magikarp.getEffectiveStat(Stat.SPD)).toBe(magikarpSpd * 2);
|
expect(magikarp.getEffectiveStat(Stat.SPD)).toBe(magikarpSpd * 2);
|
||||||
expect(meowth.getEffectiveStat(Stat.SPD)).toBe(meowthSpd * 2);
|
expect(meowth.getEffectiveStat(Stat.SPD)).toBe(meowthSpd * 2);
|
||||||
@ -53,7 +56,7 @@ describe("Moves - Tailwind", () => {
|
|||||||
it("lasts for 4 turns", async () => {
|
it("lasts for 4 turns", async () => {
|
||||||
game.override.battleType("single");
|
game.override.battleType("single");
|
||||||
|
|
||||||
await game.startBattle([Species.MAGIKARP]);
|
await game.classicMode.startBattle([Species.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(Moves.TAILWIND);
|
game.move.select(Moves.TAILWIND);
|
||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
@ -76,7 +79,7 @@ describe("Moves - Tailwind", () => {
|
|||||||
it("does not affect the opposing side", async () => {
|
it("does not affect the opposing side", async () => {
|
||||||
game.override.battleType("single");
|
game.override.battleType("single");
|
||||||
|
|
||||||
await game.startBattle([Species.MAGIKARP]);
|
await game.classicMode.startBattle([Species.MAGIKARP]);
|
||||||
|
|
||||||
const ally = game.scene.getPlayerPokemon()!;
|
const ally = game.scene.getPlayerPokemon()!;
|
||||||
const enemy = game.scene.getEnemyPokemon()!;
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
@ -91,7 +94,7 @@ describe("Moves - Tailwind", () => {
|
|||||||
|
|
||||||
game.move.select(Moves.TAILWIND);
|
game.move.select(Moves.TAILWIND);
|
||||||
|
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
|
||||||
expect(ally.getEffectiveStat(Stat.SPD)).toBe(allySpd * 2);
|
expect(ally.getEffectiveStat(Stat.SPD)).toBe(allySpd * 2);
|
||||||
expect(enemy.getEffectiveStat(Stat.SPD)).equal(enemySpd);
|
expect(enemy.getEffectiveStat(Stat.SPD)).equal(enemySpd);
|
||||||
|
Loading…
Reference in New Issue
Block a user