[UI][Enhancement] Allow tera type choice on starter select (#5366)

* Allow tera type choice on starter select

* Make tera type actually apply in run

* Remove logging statement

* Add support for alternate forms
This commit is contained in:
Xavion3 2025-02-21 07:23:08 +11:00 committed by GitHub
parent 3a4c8eb92e
commit 2d067ec7ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 121 additions and 49 deletions

View File

@ -170,7 +170,7 @@ input:-internal-autofill-selected {
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleNature, #touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT']) #apadCycleNature,
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX_PAGE'], [data-ui-mode='RUN_INFO']) #apadCycleAbility, #touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX_PAGE'], [data-ui-mode='RUN_INFO']) #apadCycleAbility,
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX_PAGE']) #apadCycleGender, #touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX_PAGE']) #apadCycleGender,
#touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX']) #apadCycleVariant { #touchControls:not(.config-mode):not([data-ui-mode='STARTER_SELECT'], [data-ui-mode='POKEDEX']) #apadCycleTera {
display: none; display: none;
} }

View File

@ -129,7 +129,7 @@
<div id="apadCycleNature" class="apad-button apad-square apad-small" data-key="CYCLE_NATURE"> <div id="apadCycleNature" class="apad-button apad-square apad-small" data-key="CYCLE_NATURE">
<span class="apad-label">N</span> <span class="apad-label">N</span>
</div> </div>
<div id="apadCycleVariant" class="apad-button apad-square apad-small" data-key="V"> <div id="apadCycleTera" class="apad-button apad-square apad-small" data-key="CYCLE_TERA">
<span class="apad-label">V</span> <span class="apad-label">V</span>
</div> </div>
<!-- buttons to display battle-specific information --> <!-- buttons to display battle-specific information -->

View File

@ -180,9 +180,9 @@ const cfg_keyboard_qwerty = {
[SettingKeyboard.Button_Cycle_Gender]: Button.CYCLE_GENDER, [SettingKeyboard.Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingKeyboard.Button_Cycle_Ability]: Button.CYCLE_ABILITY, [SettingKeyboard.Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingKeyboard.Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingKeyboard.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingKeyboard.Button_Cycle_Variant]: Button.V,
[SettingKeyboard.Button_Speed_Up]: Button.SPEED_UP, [SettingKeyboard.Button_Speed_Up]: Button.SPEED_UP,
[SettingKeyboard.Button_Slow_Down]: Button.SLOW_DOWN, [SettingKeyboard.Button_Slow_Down]: Button.SLOW_DOWN,
[SettingKeyboard.Button_Cycle_Tera]: Button.CYCLE_TERA,
[SettingKeyboard.Alt_Button_Up]: Button.UP, [SettingKeyboard.Alt_Button_Up]: Button.UP,
[SettingKeyboard.Alt_Button_Down]: Button.DOWN, [SettingKeyboard.Alt_Button_Down]: Button.DOWN,
[SettingKeyboard.Alt_Button_Left]: Button.LEFT, [SettingKeyboard.Alt_Button_Left]: Button.LEFT,
@ -197,9 +197,9 @@ const cfg_keyboard_qwerty = {
[SettingKeyboard.Alt_Button_Cycle_Gender]: Button.CYCLE_GENDER, [SettingKeyboard.Alt_Button_Cycle_Gender]: Button.CYCLE_GENDER,
[SettingKeyboard.Alt_Button_Cycle_Ability]: Button.CYCLE_ABILITY, [SettingKeyboard.Alt_Button_Cycle_Ability]: Button.CYCLE_ABILITY,
[SettingKeyboard.Alt_Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingKeyboard.Alt_Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingKeyboard.Alt_Button_Cycle_Variant]: Button.V,
[SettingKeyboard.Alt_Button_Speed_Up]: Button.SPEED_UP, [SettingKeyboard.Alt_Button_Speed_Up]: Button.SPEED_UP,
[SettingKeyboard.Alt_Button_Slow_Down]: Button.SLOW_DOWN, [SettingKeyboard.Alt_Button_Slow_Down]: Button.SLOW_DOWN,
[SettingKeyboard.Alt_Button_Cycle_Tera]: Button.CYCLE_TERA,
}, },
default: { default: {
KEY_ARROW_UP: SettingKeyboard.Button_Up, KEY_ARROW_UP: SettingKeyboard.Button_Up,
@ -216,7 +216,7 @@ const cfg_keyboard_qwerty = {
KEY_G: SettingKeyboard.Button_Cycle_Gender, KEY_G: SettingKeyboard.Button_Cycle_Gender,
KEY_E: SettingKeyboard.Button_Cycle_Ability, KEY_E: SettingKeyboard.Button_Cycle_Ability,
KEY_N: SettingKeyboard.Button_Cycle_Nature, KEY_N: SettingKeyboard.Button_Cycle_Nature,
KEY_V: SettingKeyboard.Button_Cycle_Variant, KEY_V: SettingKeyboard.Button_Cycle_Tera,
KEY_PLUS: -1, KEY_PLUS: -1,
KEY_MINUS: -1, KEY_MINUS: -1,
KEY_A: SettingKeyboard.Alt_Button_Left, KEY_A: SettingKeyboard.Alt_Button_Left,

View File

@ -53,7 +53,7 @@ const pad_dualshock = {
[SettingGamepad.Button_Action]: Button.ACTION, [SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL, [SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.V, [SettingGamepad.Button_Cycle_Tera]: Button.CYCLE_TERA,
[SettingGamepad.Button_Menu]: Button.MENU, [SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS, [SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM, [SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
@ -72,7 +72,7 @@ const pad_dualshock = {
RC_S: SettingGamepad.Button_Action, RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel, RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature, RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant, RC_N: SettingGamepad.Button_Cycle_Tera,
START: SettingGamepad.Button_Menu, START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats, SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form, LB: SettingGamepad.Button_Cycle_Form,

View File

@ -51,7 +51,7 @@ const pad_generic = {
[SettingGamepad.Button_Action]: Button.ACTION, [SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL, [SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.V, [SettingGamepad.Button_Cycle_Tera]: Button.CYCLE_TERA,
[SettingGamepad.Button_Menu]: Button.MENU, [SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS, [SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM, [SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
@ -69,7 +69,7 @@ const pad_generic = {
RC_S: SettingGamepad.Button_Action, RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel, RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature, RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant, RC_N: SettingGamepad.Button_Cycle_Tera,
START: SettingGamepad.Button_Menu, START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats, SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form, LB: SettingGamepad.Button_Cycle_Form,

View File

@ -52,7 +52,7 @@ const pad_procon = {
[SettingGamepad.Button_Action]: Button.ACTION, [SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL, [SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.V, [SettingGamepad.Button_Cycle_Tera]: Button.CYCLE_TERA,
[SettingGamepad.Button_Menu]: Button.MENU, [SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS, [SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM, [SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
@ -70,7 +70,7 @@ const pad_procon = {
RC_S: SettingGamepad.Button_Action, RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel, RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature, RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant, RC_N: SettingGamepad.Button_Cycle_Tera,
START: SettingGamepad.Button_Menu, START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats, SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form, LB: SettingGamepad.Button_Cycle_Form,

View File

@ -43,7 +43,7 @@ const pad_unlicensedSNES = {
[SettingGamepad.Button_Action]: Button.ACTION, [SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL, [SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.V, [SettingGamepad.Button_Cycle_Tera]: Button.CYCLE_TERA,
[SettingGamepad.Button_Menu]: Button.MENU, [SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS, [SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM, [SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
@ -61,7 +61,7 @@ const pad_unlicensedSNES = {
RC_S: SettingGamepad.Button_Action, RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel, RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature, RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant, RC_N: SettingGamepad.Button_Cycle_Tera,
START: SettingGamepad.Button_Menu, START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats, SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form, LB: SettingGamepad.Button_Cycle_Form,

View File

@ -51,7 +51,7 @@ const pad_xbox360 = {
[SettingGamepad.Button_Action]: Button.ACTION, [SettingGamepad.Button_Action]: Button.ACTION,
[SettingGamepad.Button_Cancel]: Button.CANCEL, [SettingGamepad.Button_Cancel]: Button.CANCEL,
[SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE, [SettingGamepad.Button_Cycle_Nature]: Button.CYCLE_NATURE,
[SettingGamepad.Button_Cycle_Variant]: Button.V, [SettingGamepad.Button_Cycle_Tera]: Button.CYCLE_TERA,
[SettingGamepad.Button_Menu]: Button.MENU, [SettingGamepad.Button_Menu]: Button.MENU,
[SettingGamepad.Button_Stats]: Button.STATS, [SettingGamepad.Button_Stats]: Button.STATS,
[SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM, [SettingGamepad.Button_Cycle_Form]: Button.CYCLE_FORM,
@ -69,7 +69,7 @@ const pad_xbox360 = {
RC_S: SettingGamepad.Button_Action, RC_S: SettingGamepad.Button_Action,
RC_E: SettingGamepad.Button_Cancel, RC_E: SettingGamepad.Button_Cancel,
RC_W: SettingGamepad.Button_Cycle_Nature, RC_W: SettingGamepad.Button_Cycle_Nature,
RC_N: SettingGamepad.Button_Cycle_Variant, RC_N: SettingGamepad.Button_Cycle_Tera,
START: SettingGamepad.Button_Menu, START: SettingGamepad.Button_Menu,
SELECT: SettingGamepad.Button_Stats, SELECT: SettingGamepad.Button_Stats,
LB: SettingGamepad.Button_Cycle_Form, LB: SettingGamepad.Button_Cycle_Form,

View File

@ -708,6 +708,7 @@ export class FreshStartChallenge extends Challenge {
pokemon.variant = 0; // Not shiny pokemon.variant = 0; // Not shiny
pokemon.formIndex = 0; // Froakie should be base form pokemon.formIndex = 0; // Froakie should be base form
pokemon.ivs = [ 15, 15, 15, 15, 15, 15 ]; // Default IVs of 15 for all stats (Updated to 15 from 10 in 1.2.0) pokemon.ivs = [ 15, 15, 15, 15, 15, 15 ]; // Default IVs of 15 for all stats (Updated to 15 from 10 in 1.2.0)
pokemon.teraType = pokemon.species.type1; // Always primary tera type
return true; return true;
} }

View File

@ -13,7 +13,7 @@ export enum Button {
CYCLE_GENDER, CYCLE_GENDER,
CYCLE_ABILITY, CYCLE_ABILITY,
CYCLE_NATURE, CYCLE_NATURE,
V, CYCLE_TERA,
SPEED_UP, SPEED_UP,
SLOW_DOWN SLOW_DOWN,
} }

View File

@ -12,6 +12,7 @@ import type { Starter } from "#app/ui/starter-select-ui-handler";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import type { Species } from "#enums/species"; import type { Species } from "#enums/species";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import * as Utils from "../utils";
export class SelectStarterPhase extends Phase { export class SelectStarterPhase extends Phase {
@ -79,6 +80,12 @@ export class SelectStarterPhase extends Phase {
starterPokemon.nickname = starter.nickname; starterPokemon.nickname = starter.nickname;
} }
if (!Utils.isNullOrUndefined(starter.teraType)) {
starterPokemon.teraType = starter.teraType;
} else {
starterPokemon.teraType = starterPokemon.species.type1;
}
if (globalScene.gameMode.isSplicedOnly || Overrides.STARTER_FUSION_OVERRIDE) { if (globalScene.gameMode.isSplicedOnly || Overrides.STARTER_FUSION_OVERRIDE) {
starterPokemon.generateFusionSpecies(true); starterPokemon.generateFusionSpecies(true);
} }

View File

@ -55,6 +55,7 @@ import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-e
import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import { ArenaTrapTag } from "#app/data/arena-tag"; import { ArenaTrapTag } from "#app/data/arena-tag";
import type { Type } from "#enums/type";
export const defaultStarterSpecies: Species[] = [ export const defaultStarterSpecies: Species[] = [
Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE,
@ -229,6 +230,7 @@ export interface StarterAttributes {
shiny?: boolean; shiny?: boolean;
favorite?: boolean; favorite?: boolean;
nickname?: string; nickname?: string;
tera?: Type;
} }
export interface StarterPreferences { export interface StarterPreferences {

View File

@ -21,7 +21,7 @@ export enum SettingGamepad {
Button_Cycle_Gender = "BUTTON_CYCLE_GENDER", Button_Cycle_Gender = "BUTTON_CYCLE_GENDER",
Button_Cycle_Ability = "BUTTON_CYCLE_ABILITY", Button_Cycle_Ability = "BUTTON_CYCLE_ABILITY",
Button_Cycle_Nature = "BUTTON_CYCLE_NATURE", Button_Cycle_Nature = "BUTTON_CYCLE_NATURE",
Button_Cycle_Variant = "BUTTON_CYCLE_VARIANT", Button_Cycle_Tera = "BUTTON_CYCLE_TERA",
Button_Speed_Up = "BUTTON_SPEED_UP", Button_Speed_Up = "BUTTON_SPEED_UP",
Button_Slow_Down = "BUTTON_SLOW_DOWN", Button_Slow_Down = "BUTTON_SLOW_DOWN",
Button_Submit = "BUTTON_SUBMIT", Button_Submit = "BUTTON_SUBMIT",
@ -45,7 +45,7 @@ export const settingGamepadOptions = {
[SettingGamepad.Button_Cycle_Gender]: [ `KEY ${Button.CYCLE_GENDER.toString()}`, pressAction ], [SettingGamepad.Button_Cycle_Gender]: [ `KEY ${Button.CYCLE_GENDER.toString()}`, pressAction ],
[SettingGamepad.Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ], [SettingGamepad.Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ],
[SettingGamepad.Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ], [SettingGamepad.Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ],
[SettingGamepad.Button_Cycle_Variant]: [ `KEY ${Button.V.toString()}`, pressAction ], [SettingGamepad.Button_Cycle_Tera]: [ `KEY ${Button.CYCLE_TERA.toString()}`, pressAction ],
[SettingGamepad.Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ], [SettingGamepad.Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ],
[SettingGamepad.Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ], [SettingGamepad.Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ],
[SettingGamepad.Button_Submit]: [ `KEY ${Button.SUBMIT.toString()}`, pressAction ], [SettingGamepad.Button_Submit]: [ `KEY ${Button.SUBMIT.toString()}`, pressAction ],
@ -67,7 +67,7 @@ export const settingGamepadDefaults = {
[SettingGamepad.Button_Cycle_Gender]: 0, [SettingGamepad.Button_Cycle_Gender]: 0,
[SettingGamepad.Button_Cycle_Ability]: 0, [SettingGamepad.Button_Cycle_Ability]: 0,
[SettingGamepad.Button_Cycle_Nature]: 0, [SettingGamepad.Button_Cycle_Nature]: 0,
[SettingGamepad.Button_Cycle_Variant]: 0, [SettingGamepad.Button_Cycle_Tera]: 0,
[SettingGamepad.Button_Speed_Up]: 0, [SettingGamepad.Button_Speed_Up]: 0,
[SettingGamepad.Button_Slow_Down]: 0, [SettingGamepad.Button_Slow_Down]: 0,
[SettingGamepad.Button_Submit]: 0, [SettingGamepad.Button_Submit]: 0,
@ -96,7 +96,7 @@ export function setSettingGamepad(setting: SettingGamepad, value: number): boole
case SettingGamepad.Button_Cycle_Gender: case SettingGamepad.Button_Cycle_Gender:
case SettingGamepad.Button_Cycle_Ability: case SettingGamepad.Button_Cycle_Ability:
case SettingGamepad.Button_Cycle_Nature: case SettingGamepad.Button_Cycle_Nature:
case SettingGamepad.Button_Cycle_Variant: case SettingGamepad.Button_Cycle_Tera:
case SettingGamepad.Button_Speed_Up: case SettingGamepad.Button_Speed_Up:
case SettingGamepad.Button_Slow_Down: case SettingGamepad.Button_Slow_Down:
case SettingGamepad.Button_Submit: case SettingGamepad.Button_Submit:

View File

@ -32,8 +32,8 @@ export enum SettingKeyboard {
Alt_Button_Cycle_Ability = "ALT_BUTTON_CYCLE_ABILITY", Alt_Button_Cycle_Ability = "ALT_BUTTON_CYCLE_ABILITY",
Button_Cycle_Nature = "BUTTON_CYCLE_NATURE", Button_Cycle_Nature = "BUTTON_CYCLE_NATURE",
Alt_Button_Cycle_Nature = "ALT_BUTTON_CYCLE_NATURE", Alt_Button_Cycle_Nature = "ALT_BUTTON_CYCLE_NATURE",
Button_Cycle_Variant = "BUTTON_CYCLE_VARIANT", Button_Cycle_Tera = "BUTTON_CYCLE_TERA",
Alt_Button_Cycle_Variant = "ALT_BUTTON_CYCLE_VARIANT", Alt_Button_Cycle_Tera = "ALT_BUTTON_CYCLE_TERA",
Button_Speed_Up = "BUTTON_SPEED_UP", Button_Speed_Up = "BUTTON_SPEED_UP",
Alt_Button_Speed_Up = "ALT_BUTTON_SPEED_UP", Alt_Button_Speed_Up = "ALT_BUTTON_SPEED_UP",
Button_Slow_Down = "BUTTON_SLOW_DOWN", Button_Slow_Down = "BUTTON_SLOW_DOWN",
@ -73,8 +73,8 @@ export const settingKeyboardOptions = {
[SettingKeyboard.Alt_Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ], [SettingKeyboard.Alt_Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ],
[SettingKeyboard.Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ], [SettingKeyboard.Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ],
[SettingKeyboard.Alt_Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ], [SettingKeyboard.Alt_Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ],
[SettingKeyboard.Button_Cycle_Variant]: [ `KEY ${Button.V.toString()}`, pressAction ], [SettingKeyboard.Button_Cycle_Tera]: [ `KEY ${Button.CYCLE_TERA.toString()}`, pressAction ],
[SettingKeyboard.Alt_Button_Cycle_Variant]: [ `KEY ${Button.V.toString()}`, pressAction ], [SettingKeyboard.Alt_Button_Cycle_Tera]: [ `KEY ${Button.CYCLE_TERA.toString()}`, pressAction ],
[SettingKeyboard.Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ], [SettingKeyboard.Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ],
[SettingKeyboard.Alt_Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ], [SettingKeyboard.Alt_Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ],
[SettingKeyboard.Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ], [SettingKeyboard.Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ],
@ -112,8 +112,8 @@ export const settingKeyboardDefaults = {
[SettingKeyboard.Alt_Button_Cycle_Ability]: 0, [SettingKeyboard.Alt_Button_Cycle_Ability]: 0,
[SettingKeyboard.Button_Cycle_Nature]: 0, [SettingKeyboard.Button_Cycle_Nature]: 0,
[SettingKeyboard.Alt_Button_Cycle_Nature]: 0, [SettingKeyboard.Alt_Button_Cycle_Nature]: 0,
[SettingKeyboard.Button_Cycle_Variant]: 0, [SettingKeyboard.Button_Cycle_Tera]: 0,
[SettingKeyboard.Alt_Button_Cycle_Variant]: 0, [SettingKeyboard.Alt_Button_Cycle_Tera]: 0,
[SettingKeyboard.Button_Speed_Up]: 0, [SettingKeyboard.Button_Speed_Up]: 0,
[SettingKeyboard.Alt_Button_Speed_Up]: 0, [SettingKeyboard.Alt_Button_Speed_Up]: 0,
[SettingKeyboard.Button_Slow_Down]: 0, [SettingKeyboard.Button_Slow_Down]: 0,
@ -148,7 +148,7 @@ export function setSettingKeyboard(setting: SettingKeyboard, value: number): boo
case SettingKeyboard.Button_Cycle_Gender: case SettingKeyboard.Button_Cycle_Gender:
case SettingKeyboard.Button_Cycle_Ability: case SettingKeyboard.Button_Cycle_Ability:
case SettingKeyboard.Button_Cycle_Nature: case SettingKeyboard.Button_Cycle_Nature:
case SettingKeyboard.Button_Cycle_Variant: case SettingKeyboard.Button_Cycle_Tera:
case SettingKeyboard.Button_Speed_Up: case SettingKeyboard.Button_Speed_Up:
case SettingKeyboard.Button_Slow_Down: case SettingKeyboard.Button_Slow_Down:
case SettingKeyboard.Alt_Button_Up: case SettingKeyboard.Alt_Button_Up:
@ -164,7 +164,7 @@ export function setSettingKeyboard(setting: SettingKeyboard, value: number): boo
case SettingKeyboard.Alt_Button_Cycle_Gender: case SettingKeyboard.Alt_Button_Cycle_Gender:
case SettingKeyboard.Alt_Button_Cycle_Ability: case SettingKeyboard.Alt_Button_Cycle_Ability:
case SettingKeyboard.Alt_Button_Cycle_Nature: case SettingKeyboard.Alt_Button_Cycle_Nature:
case SettingKeyboard.Alt_Button_Cycle_Variant: case SettingKeyboard.Alt_Button_Cycle_Tera:
case SettingKeyboard.Alt_Button_Speed_Up: case SettingKeyboard.Alt_Button_Speed_Up:
case SettingKeyboard.Alt_Button_Slow_Down: case SettingKeyboard.Alt_Button_Slow_Down:
case SettingKeyboard.Alt_Button_Submit: case SettingKeyboard.Alt_Button_Submit:

View File

@ -406,9 +406,9 @@ describe("Test Rebinding", () => {
}); });
it("check to delete all the binds of an action", () => { it("check to delete all the binds of an action", () => {
inGame.whenWePressOnKeyboard("V").weShouldTriggerTheButton("Button_Cycle_Variant"); inGame.whenWePressOnKeyboard("V").weShouldTriggerTheButton("Button_Cycle_Tera");
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Cycle_Variant").thereShouldBeNoIcon().weWantThisBindInstead("K").confirm(); inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Cycle_Tera").thereShouldBeNoIcon().weWantThisBindInstead("K").confirm();
inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Cycle_Variant").iconDisplayedIs("KEY_K").whenWeDelete().thereShouldBeNoIconAnymore(); inTheSettingMenu.whenCursorIsOnSetting("Alt_Button_Cycle_Tera").iconDisplayedIs("KEY_K").whenWeDelete().thereShouldBeNoIconAnymore();
inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Variant").iconDisplayedIs("KEY_V").whenWeDelete().thereShouldBeNoIconAnymore(); inTheSettingMenu.whenCursorIsOnSetting("Button_Cycle_Tera").iconDisplayedIs("KEY_V").whenWeDelete().thereShouldBeNoIconAnymore();
}); });
}); });

View File

@ -35,7 +35,7 @@
<div id="apadCycleShiny" class="apad-button apad-square apad-small" data-key="CYCLE_SHINY"> <div id="apadCycleShiny" class="apad-button apad-square apad-small" data-key="CYCLE_SHINY">
<span class="apad-label">R</span> <span class="apad-label">R</span>
</div> </div>
<div id="apadCycleVariant" class="apad-button apad-square apad-small" data-key="V"> <div id="apadCycleTera" class="apad-button apad-square apad-small" data-key="CYCLE_TERA">
<span class="apad-label">V</span> <span class="apad-label">V</span>
</div> </div>
<div id="apadStats" class="apad-button apad-rectangle apad-small" data-key="STATS"> <div id="apadStats" class="apad-button apad-rectangle apad-small" data-key="STATS">
@ -59,7 +59,7 @@
<div id="apadCycleNature" class="apad-button apad-square apad-small" data-key="CYCLE_NATURE"> <div id="apadCycleNature" class="apad-button apad-square apad-small" data-key="CYCLE_NATURE">
<span class="apad-label">N</span> <span class="apad-label">N</span>
</div> </div>
<div id="apadInfo" class="apad-button apad-rectangle apad-small" data-key="V"> <div id="apadInfo" class="apad-button apad-rectangle apad-small" data-key="CYCLE_TERA">
<span class="apad-label">V</span> <span class="apad-label">V</span>
</div> </div>
</div> </div>

View File

@ -86,7 +86,7 @@ export class UiInputs {
[Button.CYCLE_GENDER]: () => this.buttonCycleOption(Button.CYCLE_GENDER), [Button.CYCLE_GENDER]: () => this.buttonCycleOption(Button.CYCLE_GENDER),
[Button.CYCLE_ABILITY]: () => this.buttonCycleOption(Button.CYCLE_ABILITY), [Button.CYCLE_ABILITY]: () => this.buttonCycleOption(Button.CYCLE_ABILITY),
[Button.CYCLE_NATURE]: () => this.buttonCycleOption(Button.CYCLE_NATURE), [Button.CYCLE_NATURE]: () => this.buttonCycleOption(Button.CYCLE_NATURE),
[Button.V]: () => this.buttonCycleOption(Button.V), [Button.CYCLE_TERA]: () => this.buttonCycleOption(Button.CYCLE_TERA),
[Button.SPEED_UP]: () => this.buttonSpeedChange(), [Button.SPEED_UP]: () => this.buttonSpeedChange(),
[Button.SLOW_DOWN]: () => this.buttonSpeedChange(false), [Button.SLOW_DOWN]: () => this.buttonSpeedChange(false),
}; };
@ -109,7 +109,7 @@ export class UiInputs {
[Button.CYCLE_GENDER]: () => undefined, [Button.CYCLE_GENDER]: () => undefined,
[Button.CYCLE_ABILITY]: () => undefined, [Button.CYCLE_ABILITY]: () => undefined,
[Button.CYCLE_NATURE]: () => undefined, [Button.CYCLE_NATURE]: () => undefined,
[Button.V]: () => this.buttonInfo(false), [Button.CYCLE_TERA]: () => undefined,
[Button.SPEED_UP]: () => undefined, [Button.SPEED_UP]: () => undefined,
[Button.SLOW_DOWN]: () => undefined, [Button.SLOW_DOWN]: () => undefined,
}; };
@ -197,7 +197,7 @@ export class UiInputs {
const uiHandler = globalScene.ui?.getHandler(); const uiHandler = globalScene.ui?.getHandler();
if (whitelist.some(handler => uiHandler instanceof handler)) { if (whitelist.some(handler => uiHandler instanceof handler)) {
globalScene.ui.processInput(button); globalScene.ui.processInput(button);
} else if (button === Button.V) { } else if (button === Button.CYCLE_TERA) {
this.buttonInfo(true); this.buttonInfo(true);
} }
} }

View File

@ -919,7 +919,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
} else { } else {
error = true; error = true;
} }
} else if (button === Button.V) { } else if (button === Button.CYCLE_TERA) {
if (!this.filterTextMode && !this.showingTray) { if (!this.filterTextMode && !this.showingTray) {
this.cursorObj.setVisible(false); this.cursorObj.setVisible(false);
this.setSpecies(null); this.setSpecies(null);
@ -1170,9 +1170,6 @@ export default class PokedexUiHandler extends MessageUiHandler {
case SettingKeyboard.Button_Cycle_Shiny: case SettingKeyboard.Button_Cycle_Shiny:
iconPath = "R.png"; iconPath = "R.png";
break; break;
case SettingKeyboard.Button_Cycle_Variant:
iconPath = "V.png";
break;
case SettingKeyboard.Button_Cycle_Form: case SettingKeyboard.Button_Cycle_Form:
iconPath = "F.png"; iconPath = "F.png";
break; break;

View File

@ -56,6 +56,8 @@ import { getPassiveCandyCount, getValueReductionCandyCounts, getSameSpeciesEggCa
import { BooleanHolder, fixedInt, getLocalizedSpriteKey, isNullOrUndefined, NumberHolder, padInt, randIntRange, rgbHexToRgba, toReadableString } from "#app/utils"; import { BooleanHolder, fixedInt, getLocalizedSpriteKey, isNullOrUndefined, NumberHolder, padInt, randIntRange, rgbHexToRgba, toReadableString } from "#app/utils";
import type { Nature } from "#enums/nature"; import type { Nature } from "#enums/nature";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { achvs } from "#app/system/achv";
import * as Utils from "../utils";
export type StarterSelectCallback = (starters: Starter[]) => void; export type StarterSelectCallback = (starters: Starter[]) => void;
@ -68,6 +70,7 @@ export interface Starter {
moveset?: StarterMoveset; moveset?: StarterMoveset;
pokerus: boolean; pokerus: boolean;
nickname?: string; nickname?: string;
teraType?: Type;
} }
interface LanguageSetting { interface LanguageSetting {
@ -212,6 +215,7 @@ interface SpeciesDetails {
abilityIndex?: number, abilityIndex?: number,
natureIndex?: number, natureIndex?: number,
forSeen?: boolean, // default = false forSeen?: boolean, // default = false
teraType?: Type,
} }
export default class StarterSelectUiHandler extends MessageUiHandler { export default class StarterSelectUiHandler extends MessageUiHandler {
@ -262,6 +266,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private pokemonShinyIcon: Phaser.GameObjects.Sprite; private pokemonShinyIcon: Phaser.GameObjects.Sprite;
private pokemonPassiveDisabledIcon: Phaser.GameObjects.Sprite; private pokemonPassiveDisabledIcon: Phaser.GameObjects.Sprite;
private pokemonPassiveLockedIcon: Phaser.GameObjects.Sprite; private pokemonPassiveLockedIcon: Phaser.GameObjects.Sprite;
private teraIcon: Phaser.GameObjects.Sprite;
private activeTooltip: "ABILITY" | "PASSIVE" | "CANDY" | undefined; private activeTooltip: "ABILITY" | "PASSIVE" | "CANDY" | undefined;
private instructionsContainer: Phaser.GameObjects.Container; private instructionsContainer: Phaser.GameObjects.Container;
@ -271,12 +276,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private abilityIconElement: Phaser.GameObjects.Sprite; private abilityIconElement: Phaser.GameObjects.Sprite;
private genderIconElement: Phaser.GameObjects.Sprite; private genderIconElement: Phaser.GameObjects.Sprite;
private natureIconElement: Phaser.GameObjects.Sprite; private natureIconElement: Phaser.GameObjects.Sprite;
private teraIconElement: Phaser.GameObjects.Sprite;
private goFilterIconElement: Phaser.GameObjects.Sprite; private goFilterIconElement: Phaser.GameObjects.Sprite;
private shinyLabel: Phaser.GameObjects.Text; private shinyLabel: Phaser.GameObjects.Text;
private formLabel: Phaser.GameObjects.Text; private formLabel: Phaser.GameObjects.Text;
private genderLabel: Phaser.GameObjects.Text; private genderLabel: Phaser.GameObjects.Text;
private abilityLabel: Phaser.GameObjects.Text; private abilityLabel: Phaser.GameObjects.Text;
private natureLabel: Phaser.GameObjects.Text; private natureLabel: Phaser.GameObjects.Text;
private teraLabel: Phaser.GameObjects.Text;
private goFilterLabel: Phaser.GameObjects.Text; private goFilterLabel: Phaser.GameObjects.Text;
private starterSelectMessageBox: Phaser.GameObjects.NineSlice; private starterSelectMessageBox: Phaser.GameObjects.NineSlice;
@ -292,6 +299,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private dexAttrCursor: bigint = 0n; private dexAttrCursor: bigint = 0n;
private abilityCursor: number = -1; private abilityCursor: number = -1;
private natureCursor: number = -1; private natureCursor: number = -1;
private teraCursor: Type = Type.UNKNOWN;
private filterBarCursor: number = 0; private filterBarCursor: number = 0;
private starterMoveset: StarterMoveset | null; private starterMoveset: StarterMoveset | null;
private scrollCursor: number; private scrollCursor: number;
@ -304,6 +312,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private starterAttr: bigint[] = []; private starterAttr: bigint[] = [];
private starterAbilityIndexes: number[] = []; private starterAbilityIndexes: number[] = [];
private starterNatures: Nature[] = []; private starterNatures: Nature[] = [];
private starterTeras: Type[] = [];
private starterMovesets: StarterMoveset[] = []; private starterMovesets: StarterMoveset[] = [];
private speciesStarterDexEntry: DexEntry | null; private speciesStarterDexEntry: DexEntry | null;
private speciesStarterMoves: Moves[]; private speciesStarterMoves: Moves[];
@ -312,6 +321,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
private canCycleGender: boolean; private canCycleGender: boolean;
private canCycleAbility: boolean; private canCycleAbility: boolean;
private canCycleNature: boolean; private canCycleNature: boolean;
private canCycleTera: boolean;
private assetLoadCancelled: BooleanHolder | null; private assetLoadCancelled: BooleanHolder | null;
public cursorObj: Phaser.GameObjects.Image; public cursorObj: Phaser.GameObjects.Image;
@ -823,6 +833,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.starterSelectContainer.add(this.pokemonEggMovesContainer); this.starterSelectContainer.add(this.pokemonEggMovesContainer);
this.teraIcon = globalScene.add.sprite(85, 63, "button_tera");
this.teraIcon.setName("terrastallize-icon");
this.teraIcon.setFrame("fire");
this.starterSelectContainer.add(this.teraIcon);
// The font size should be set per language // The font size should be set per language
const instructionTextSize = textSettings.instructionTextSize; const instructionTextSize = textSettings.instructionTextSize;
@ -867,6 +882,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.natureLabel = addTextObject(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleNature"), TextStyle.PARTY, { fontSize: instructionTextSize }); this.natureLabel = addTextObject(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleNature"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.natureLabel.setName("text-nature-label"); this.natureLabel.setName("text-nature-label");
this.teraIconElement = new Phaser.GameObjects.Sprite(globalScene, this.instructionRowX, this.instructionRowY, "keyboard", "V.png");
this.teraIconElement.setName("sprite-tera-icon-element");
this.teraIconElement.setScale(0.675);
this.teraIconElement.setOrigin(0.0, 0.0);
this.teraLabel = addTextObject(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY, i18next.t("starterSelectUiHandler:cycleTera"), TextStyle.PARTY, { fontSize: instructionTextSize });
this.teraLabel.setName("text-tera-label");
this.goFilterIconElement = new Phaser.GameObjects.Sprite(globalScene, this.filterInstructionRowX, this.filterInstructionRowY, "keyboard", "C.png"); this.goFilterIconElement = new Phaser.GameObjects.Sprite(globalScene, this.filterInstructionRowX, this.filterInstructionRowY, "keyboard", "C.png");
this.goFilterIconElement.setName("sprite-goFilter-icon-element"); this.goFilterIconElement.setName("sprite-goFilter-icon-element");
this.goFilterIconElement.setScale(0.675); this.goFilterIconElement.setScale(0.675);
@ -1497,6 +1519,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const props = globalScene.gameData.getSpeciesDexAttrProps(randomSpecies, dexAttr); const props = globalScene.gameData.getSpeciesDexAttrProps(randomSpecies, dexAttr);
const abilityIndex = this.abilityCursor; const abilityIndex = this.abilityCursor;
const nature = this.natureCursor as unknown as Nature; const nature = this.natureCursor as unknown as Nature;
const teraType = this.teraCursor;
const moveset = this.starterMoveset?.slice(0) as StarterMoveset; const moveset = this.starterMoveset?.slice(0) as StarterMoveset;
const starterCost = globalScene.gameData.getSpeciesStarterValue(randomSpecies.speciesId); const starterCost = globalScene.gameData.getSpeciesStarterValue(randomSpecies.speciesId);
const speciesForm = getPokemonSpeciesForm(randomSpecies.speciesId, props.formIndex); const speciesForm = getPokemonSpeciesForm(randomSpecies.speciesId, props.formIndex);
@ -1505,7 +1528,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
.loadAssets(props.female, props.formIndex, props.shiny, props.variant, true) .loadAssets(props.female, props.formIndex, props.shiny, props.variant, true)
.then(() => { .then(() => {
if (this.tryUpdateValue(starterCost, true)) { if (this.tryUpdateValue(starterCost, true)) {
this.addToParty(randomSpecies, dexAttr, abilityIndex, nature, moveset, true); this.addToParty(randomSpecies, dexAttr, abilityIndex, nature, moveset, teraType, true);
ui.playSelect(); ui.playSelect();
} }
}); });
@ -1585,7 +1608,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const cursorObj = this.starterCursorObjs[this.starterSpecies.length]; const cursorObj = this.starterCursorObjs[this.starterSpecies.length];
cursorObj.setVisible(true); cursorObj.setVisible(true);
cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y); cursorObj.setPosition(this.cursorObj.x, this.cursorObj.y);
this.addToParty(this.lastSpecies, this.dexAttrCursor, this.abilityCursor, this.natureCursor as unknown as Nature, this.starterMoveset?.slice(0) as StarterMoveset); this.addToParty(this.lastSpecies, this.dexAttrCursor, this.abilityCursor, this.natureCursor as unknown as Nature, this.starterMoveset?.slice(0) as StarterMoveset, this.teraCursor);
ui.playSelect(); ui.playSelect();
} else { } else {
ui.playError(); // this should be redundant as there is now a trigger for when a pokemon can't be added to party ui.playError(); // this should be redundant as there is now a trigger for when a pokemon can't be added to party
@ -2066,7 +2089,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
} while (newFormIndex !== props.formIndex); } while (newFormIndex !== props.formIndex);
starterAttributes.form = newFormIndex; // store the selected form starterAttributes.form = newFormIndex; // store the selected form
this.setSpeciesDetails(this.lastSpecies, { formIndex: newFormIndex }); starterAttributes.tera = this.lastSpecies.forms[newFormIndex].type1;
this.setSpeciesDetails(this.lastSpecies, { formIndex: newFormIndex, teraType: starterAttributes.tera });
success = true; success = true;
} }
break; break;
@ -2125,6 +2149,19 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
success = true; success = true;
} }
break; break;
case Button.CYCLE_TERA:
if (this.canCycleTera) {
const speciesForm = getPokemonSpeciesForm(this.lastSpecies.speciesId, starterAttributes.form ?? 0);
if (speciesForm.type1 === this.teraCursor && !Utils.isNullOrUndefined(speciesForm.type2)) {
starterAttributes.tera = speciesForm.type2!;
this.setSpeciesDetails(this.lastSpecies, { teraType: speciesForm.type2! });
} else {
starterAttributes.tera = speciesForm.type1;
this.setSpeciesDetails(this.lastSpecies, { teraType: speciesForm.type1 });
}
success = true;
}
break;
case Button.UP: case Button.UP:
if (!this.starterIconsCursorObj.visible) { if (!this.starterIconsCursorObj.visible) {
if (currentRow > 0) { if (currentRow > 0) {
@ -2289,7 +2326,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
return [ isDupe, removeIndex ]; return [ isDupe, removeIndex ];
} }
addToParty(species: PokemonSpecies, dexAttr: bigint, abilityIndex: number, nature: Nature, moveset: StarterMoveset, randomSelection: boolean = false) { addToParty(species: PokemonSpecies, dexAttr: bigint, abilityIndex: number, nature: Nature, moveset: StarterMoveset, teraType: Type, randomSelection: boolean = false) {
const props = globalScene.gameData.getSpeciesDexAttrProps(species, dexAttr); const props = globalScene.gameData.getSpeciesDexAttrProps(species, dexAttr);
this.starterIcons[this.starterSpecies.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant)); this.starterIcons[this.starterSpecies.length].setTexture(species.getIconAtlasKey(props.formIndex, props.shiny, props.variant));
this.starterIcons[this.starterSpecies.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant)); this.starterIcons[this.starterSpecies.length].setFrame(species.getIconId(props.female, props.formIndex, props.shiny, props.variant));
@ -2299,6 +2336,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.starterAttr.push(dexAttr); this.starterAttr.push(dexAttr);
this.starterAbilityIndexes.push(abilityIndex); this.starterAbilityIndexes.push(abilityIndex);
this.starterNatures.push(nature); this.starterNatures.push(nature);
this.starterTeras.push(teraType);
this.starterMovesets.push(moveset); this.starterMovesets.push(moveset);
if (this.speciesLoaded.get(species.speciesId) || randomSelection ) { if (this.speciesLoaded.get(species.speciesId) || randomSelection ) {
getPokemonSpeciesForm(species.speciesId, props.formIndex).cry(); getPokemonSpeciesForm(species.speciesId, props.formIndex).cry();
@ -2379,6 +2417,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
case SettingKeyboard.Button_Cycle_Nature: case SettingKeyboard.Button_Cycle_Nature:
iconPath = "N.png"; iconPath = "N.png";
break; break;
case SettingKeyboard.Button_Cycle_Tera:
iconPath = "V.png";
break;
case SettingKeyboard.Button_Stats: case SettingKeyboard.Button_Stats:
iconPath = "C.png"; iconPath = "C.png";
break; break;
@ -2459,6 +2500,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
if (this.canCycleNature) { if (this.canCycleNature) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Nature, gamepadType, this.natureIconElement, this.natureLabel); this.updateButtonIcon(SettingKeyboard.Button_Cycle_Nature, gamepadType, this.natureIconElement, this.natureLabel);
} }
if (this.canCycleTera) {
this.updateButtonIcon(SettingKeyboard.Button_Cycle_Tera, gamepadType, this.teraIconElement, this.teraLabel);
}
} }
// if filter mode is inactivated and gamepadType is not undefined, update the button icons // if filter mode is inactivated and gamepadType is not undefined, update the button icons
@ -2876,6 +2920,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n; this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n;
this.abilityCursor = species ? globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0; this.abilityCursor = species ? globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0;
this.natureCursor = species ? globalScene.gameData.getSpeciesDefaultNature(species) : 0; this.natureCursor = species ? globalScene.gameData.getSpeciesDefaultNature(species) : 0;
this.teraCursor = species ? species.type1 : Type.UNKNOWN;
if (!species && globalScene.ui.getTooltip().visible) { if (!species && globalScene.ui.getTooltip().visible) {
globalScene.ui.hideTooltip(); globalScene.ui.hideTooltip();
@ -2894,6 +2939,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
// load default ability from stater save data, if set // load default ability from stater save data, if set
this.abilityCursor = starterAttributes.ability; this.abilityCursor = starterAttributes.ability;
} }
if (starterAttributes?.tera) {
// load default tera from starter save data, if set
this.teraCursor = starterAttributes.tera;
}
if (this.statsMode) { if (this.statsMode) {
if (this.speciesStarterDexEntry?.caughtAttr) { if (this.speciesStarterDexEntry?.caughtAttr) {
@ -3035,7 +3084,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
female: props.female, female: props.female,
variant: props.variant, variant: props.variant,
abilityIndex: this.starterAbilityIndexes[starterIndex], abilityIndex: this.starterAbilityIndexes[starterIndex],
natureIndex: this.starterNatures[starterIndex] natureIndex: this.starterNatures[starterIndex],
teraType: this.starterTeras[starterIndex]
}); });
} else { } else {
const defaultDexAttr = this.getCurrentDexProps(species.speciesId); const defaultDexAttr = this.getCurrentDexProps(species.speciesId);
@ -3083,6 +3133,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonCaughtHatchedContainer.setVisible(false); this.pokemonCaughtHatchedContainer.setVisible(false);
this.pokemonCandyContainer.setVisible(false); this.pokemonCandyContainer.setVisible(false);
this.pokemonFormText.setVisible(false); this.pokemonFormText.setVisible(false);
this.teraIcon.setVisible(false);
const defaultDexAttr = globalScene.gameData.getSpeciesDefaultDexAttr(species, true, true); const defaultDexAttr = globalScene.gameData.getSpeciesDefaultDexAttr(species, true, true);
const defaultAbilityIndex = globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); const defaultAbilityIndex = globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
@ -3117,6 +3168,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonCaughtHatchedContainer.setVisible(false); this.pokemonCaughtHatchedContainer.setVisible(false);
this.pokemonCandyContainer.setVisible(false); this.pokemonCandyContainer.setVisible(false);
this.pokemonFormText.setVisible(false); this.pokemonFormText.setVisible(false);
this.teraIcon.setVisible(false);
this.setSpeciesDetails(species!, { // TODO: is this bang correct? this.setSpeciesDetails(species!, { // TODO: is this bang correct?
shiny: false, shiny: false,
@ -3131,7 +3183,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}): void { setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}): void {
let { shiny, formIndex, female, variant, abilityIndex, natureIndex } = options; let { shiny, formIndex, female, variant, abilityIndex, natureIndex, teraType } = options;
const forSeen: boolean = options.forSeen ?? false; const forSeen: boolean = options.forSeen ?? false;
const oldProps = species ? globalScene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null; const oldProps = species ? globalScene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null;
const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species);
@ -3139,6 +3191,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.dexAttrCursor = 0n; this.dexAttrCursor = 0n;
this.abilityCursor = -1; this.abilityCursor = -1;
this.natureCursor = -1; this.natureCursor = -1;
this.teraCursor = Type.UNKNOWN;
// We will only update the sprite if there is a change to form, shiny/variant // We will only update the sprite if there is a change to form, shiny/variant
// or gender for species with gender sprite differences // or gender for species with gender sprite differences
const shouldUpdateSprite = (species?.genderDiffs && !isNullOrUndefined(female)) const shouldUpdateSprite = (species?.genderDiffs && !isNullOrUndefined(female))
@ -3168,6 +3221,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.dexAttrCursor |= globalScene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct? this.dexAttrCursor |= globalScene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct?
this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex); this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex);
this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex); this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex);
this.teraCursor = !Utils.isNullOrUndefined(teraType) ? teraType : (teraType = species.type1);
const [ isInParty, partyIndex ]: [boolean, number] = this.isInParty(species); // we use this to firstly check if the pokemon is in the party, and if so, to get the party index in order to update the icon image const [ isInParty, partyIndex ]: [boolean, number] = this.isInParty(species); // we use this to firstly check if the pokemon is in the party, and if so, to get the party index in order to update the icon image
if (isInParty) { if (isInParty) {
this.updatePartyIcon(species, partyIndex); this.updatePartyIcon(species, partyIndex);
@ -3179,6 +3233,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonPassiveText.setVisible(false); this.pokemonPassiveText.setVisible(false);
this.pokemonPassiveDisabledIcon.setVisible(false); this.pokemonPassiveDisabledIcon.setVisible(false);
this.pokemonPassiveLockedIcon.setVisible(false); this.pokemonPassiveLockedIcon.setVisible(false);
this.teraIcon.setVisible(false);
if (this.assetLoadCancelled) { if (this.assetLoadCancelled) {
this.assetLoadCancelled.value = true; this.assetLoadCancelled.value = true;
@ -3230,6 +3285,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.starterAttr[starterIndex] = this.dexAttrCursor; this.starterAttr[starterIndex] = this.dexAttrCursor;
this.starterAbilityIndexes[starterIndex] = this.abilityCursor; this.starterAbilityIndexes[starterIndex] = this.abilityCursor;
this.starterNatures[starterIndex] = this.natureCursor; this.starterNatures[starterIndex] = this.natureCursor;
this.starterTeras[starterIndex] = this.teraCursor;
} }
const assetLoadCancelled = new BooleanHolder(false); const assetLoadCancelled = new BooleanHolder(false);
@ -3288,7 +3344,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.canCycleForm = species.forms.filter(f => f.isStarterSelectable || !pokemonFormChanges[species.speciesId]?.find(fc => fc.formKey)) this.canCycleForm = species.forms.filter(f => f.isStarterSelectable || !pokemonFormChanges[species.speciesId]?.find(fc => fc.formKey))
.map((_, f) => dexEntry.caughtAttr & globalScene.gameData.getFormAttr(f)).filter(f => f).length > 1; .map((_, f) => dexEntry.caughtAttr & globalScene.gameData.getFormAttr(f)).filter(f => f).length > 1;
this.canCycleNature = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr).length > 1; this.canCycleNature = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr).length > 1;
this.canCycleTera = globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) && !Utils.isNullOrUndefined(getPokemonSpeciesForm(species.speciesId, formIndex ?? 0).type2);
} }
if (dexEntry.caughtAttr && species.malePercent !== null) { if (dexEntry.caughtAttr && species.malePercent !== null) {
@ -3412,10 +3468,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonFormText.setText(formText); this.pokemonFormText.setText(formText);
this.setTypeIcons(speciesForm.type1, speciesForm.type2); this.setTypeIcons(speciesForm.type1, speciesForm.type2);
this.teraIcon.setFrame(Type[this.teraCursor].toLowerCase());
this.teraIcon.setVisible(!this.statsMode && globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id));
} else { } else {
this.pokemonAbilityText.setText(""); this.pokemonAbilityText.setText("");
this.pokemonPassiveText.setText(""); this.pokemonPassiveText.setText("");
this.pokemonNatureText.setText(""); this.pokemonNatureText.setText("");
this.teraIcon.setVisible(false);
this.setTypeIcons(null, null); this.setTypeIcons(null, null);
} }
} else { } else {
@ -3426,6 +3486,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonAbilityText.setText(""); this.pokemonAbilityText.setText("");
this.pokemonPassiveText.setText(""); this.pokemonPassiveText.setText("");
this.pokemonNatureText.setText(""); this.pokemonNatureText.setText("");
this.teraIcon.setVisible(false);
this.setTypeIcons(null, null); this.setTypeIcons(null, null);
} }
@ -3479,6 +3540,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.starterAttr.splice(index, 1); this.starterAttr.splice(index, 1);
this.starterAbilityIndexes.splice(index, 1); this.starterAbilityIndexes.splice(index, 1);
this.starterNatures.splice(index, 1); this.starterNatures.splice(index, 1);
this.starterTeras.splice(index, 1);
this.starterMovesets.splice(index, 1); this.starterMovesets.splice(index, 1);
for (let s = 0; s < this.starterSpecies.length; s++) { for (let s = 0; s < this.starterSpecies.length; s++) {
@ -3690,6 +3752,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
abilityIndex: thisObj.starterAbilityIndexes[i], abilityIndex: thisObj.starterAbilityIndexes[i],
passive: !(globalScene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)), passive: !(globalScene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)),
nature: thisObj.starterNatures[i] as Nature, nature: thisObj.starterNatures[i] as Nature,
teraType: thisObj.starterTeras[i] as Type,
moveset: thisObj.starterMovesets[i], moveset: thisObj.starterMovesets[i],
pokerus: thisObj.pokerusSpecies.includes(starterSpecies), pokerus: thisObj.pokerusSpecies.includes(starterSpecies),
nickname: thisObj.starterPreferences[starterSpecies.speciesId]?.nickname, nickname: thisObj.starterPreferences[starterSpecies.speciesId]?.nickname,
@ -3816,6 +3879,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.abilityLabel.setVisible(false); this.abilityLabel.setVisible(false);
this.natureIconElement.setVisible(false); this.natureIconElement.setVisible(false);
this.natureLabel.setVisible(false); this.natureLabel.setVisible(false);
this.teraIconElement.setVisible(false);
this.teraLabel.setVisible(false);
this.goFilterIconElement.setVisible(false); this.goFilterIconElement.setVisible(false);
this.goFilterLabel.setVisible(false); this.goFilterLabel.setVisible(false);
} }