mirror of https://github.com/pret/pokeemerald.git
Page:
Multipage Options Menu
Pages
Ability Switcher via special
Add A PokeVial Item
Add Ability to Avoid Battle Damage in Debug Menu
Add Ability to Swap Bikes Whenever
Add Choice Specs Scarf hold item effects
Add Description Submenu
Add Difficulty Mode
Add In‐Cart Rumble
Add Nuzlocke Challenge
Add PC Access in PokeNav
Add Physical Special Split
Add Sleep Mode
Add Thief Ball
Add a EV IV Stat Editor UI
Add a debug menu
Adding Multi region Support
Adding Support for Connectivity with Other Hacks Whilst Maintaining Connectivity with Vanilla
Adding Time Based Encounters
Adding Walking Animations to All NPCs
Adding a New Trainer Class
Adding a New Trainer Front Picture
Adding a Pokémon Type & Disabling the Mystery Type
Adding new event object or overworld sprites
All Trees Permanently Get Cut
Allow All Pokemon to Evolve Without Trading
Allow Both Latios and Latias Appear.
Allow Feebas to be caught on any Valid Fishing Spot in Route 119 rather than only Three
Allow Jumping Over Ledges with Acro Bike
Allow Move Relearner to Teach Moves that Pre Evolutions Know
Allow Running From Trainer Battles
Allow running indoors
Amulet Coin Effects If Anyone In Party is Holding It
Automatically make the keyboard switch to lowercase after the first character
Better White Out Money Calculation
Button Press to Skip Copyright Screen
Chain Fishing
Change Enemy Trainer Parties Depending on Difficulty
Change Someone's PC to Lanette's PC from the Start of the Game
Change Starter Pokémon
Change Time Based Evolution Times
Change initial PC items
Changing the Battle Music Depending on the Opponent
Colored stats by nature in summary screen
Converting to FR Tilesets
Custom Battle Mugshots
Custom Border Dimensions
Debugging using gdb (Windows, WSL2, Visual Studio Code mGBA)
Debugging using printf
Disable Bag Use In Battle
Disable Catching Pokemon
Disable Pokémon animation on Birch's intro Pokémon
Disabling Union Room check when entering Pokémon Centers
Dynamic Trade Names
Dynamic overworld palette system
Enable the Reset RTC Feature
Enable trade with FRLG without beating the game
Expanding The Metatile Count
Extra save space with three lines of code
Faster HP Drain
Feature Branches
Fish Will Now Always Get on Hook
Fix AI's Switch In Battle
Fix Snow Weather
Fixing the aspect ratio of the Pokémon logo on the title screen
Forcing Battle Animations for Major Battles
Full Screen Start Menu by Archie and Mudskip
Gen 6 Exp Share
Gen 6 style Exp. Share Alternative Option
Get Match Calls Only If Caller Wants a Rematch
Get Rid of Battery Run Dry Error Message
Get Rid of Pokemon Disobeying You
Holding Select Allows For A Second Register Item
Home
How the Game Works
How to Support Savefile Backwards Compatibility
How to add a new Pokémon species
How to add a new ability
How to add a new region map
How to create a new regular trainer battle
How to delete a map
Implement Missing Text Function RESET_FONT
Implementing Catch EXP
Implementing ipatix's High Quality Audio Mixer
Implementing the “textcolor” script command from FRLG and give object events their own text colour
Improve Partner Battle Code
Improve the Loading of Battle Terrain
Improving the WaitForVBlank function
Increase money limit
Infinite TM usage
Instead of Asking to Stop learning a New Move, You'll be Asked to Continue Learning
Item Automatically Goes to PC if Bag is Full
Keep the Camera from Making Waves
LGPE Style Bonus Premier Balls
Learn moves upon evolution
List Menu Text Coloring
Make Cleanse Tag Avoid All Wild Encounters and Usable If Held By Anyone in Your Party; Make PokeDoll Do the Same for Trainers Seeing You
Make Daycare Faster at Leveling Pokémon
Make Key Items That Cannot Be Used In The Field Not Show A Use or Register Option
Make L Button Be Turbo A When L=A Option Is Set
Make Ledge Jumps Check Collision
Make Move Relearner Teach Egg Moves With A Flag
Make Multiple Secret Bases
Make Norman's Slaking Have Ability Intimidate
Make Pokemon Not Heal When Going into PC
Make Pokemon that Require a Fateful Encounter to be Legal to Always Be Set to Legal
Make space for EWRAM Data for Summary screen
Make the Bag Able to Hold 120 Items Instead of 30
Make the Person in the Intro Match the the Save File
Map Based Trainer Battle Music
Move Item
Multipage Options Menu
Name Rater Allows Traded Pokemon to be Renamed
New Birch's Briefcase With Fully Custom Starters by Archie and Mudskip
New Custom Menu Border Themes (Basic)
New Main Menu UI With Mugshot by Archie and Mudskip
New Options Plus ‐ Multipage Options Menu with Faster Text, HP‐EXP Bar Speeds and Metric
Nickname your Pokémon from the party menu
Not showing dex entries until getting the Pokédex
Omnidirectional Jump
Optimization ‐ Remove Expensive and Redundant `BuildColorMaps()` Function
Option to Skip Copyright and Intro
Overview: Items and their Effects
Overview: The Party Menu
Overview∶ The Game Loop
Overview∶ The Task System
Per Shop\Mart Item Prices
Plural Giveitem
Pokecenters Disregard Eggs
Prompt for reusing Repels
Push B in wild battle moves to Run
Push B to Toggle Running Shoes
Pushing B When Asked To Stop Learning Move Will Cancel Teaching The Move
Quickly Run from a Battle by Holding Right While the Wild Pokémon's Name Appears
Raise Odds of Catching a Pokemon by Pressing B When the Ball Shakes
Random Info, Tips, and Tricks
Reflections
Remove 'Select' Sound From Specific Map Events
Remove Warp Fadescreen
Remove badge boosts
Remove the backup save file
Remove the extra save confirmation
Remove the functionally redundant move grammar tables
Repeated Field Medicine Use
Reuse filler save space for Variables and Flags
Revert Brendan May Sprites to Ruby Sapphire
Set Metatile IDs From Another Map
Set Up Item Balls on a Map Without Needing New Scripts
Shifting to Pokémon Already in Battle Exits the Shift Menu
Shiny Creation With a Flag
Shop Items By Badge Count
Show IVs EVs in Summary Screen
Show Species That You're Switching For in the Party Menu
Show Type Effectiveness In Battle Using Pre Existing Function and Disable in Option Menu
Show a throbber animation while the game is saving
Shuckle makes Berry Juice
Something doesn't work I need help etc.
Spawn Invisible Player
Speedy Nurse Joy
Spinda Second Frame Spot Addition
Stair Warps
Supplementary Scripting Macros
Surfing Dismount Ground Effects
Temporarily Replace Player or Enemy Party Pokemon
The Basics of Scripting
Toggle Trainer Sight
Trainer Backsprite Editing
Trainer Class Based Poké Balls
Trainer Scripts
Trainers No Longer Spin to Face You Right As You Pass Them
Trigger Map Scripts By Flag
Triple layer metatiles
Tutorials
Tweaking the count of health beeps
Uniquely Shuffle Array
Update Sitrus Berry's effect to Gen 4 standard
Use HMs Without Any Pokemon in your Party Knowing Them
Useful Modding Tools
Useful Scripting Specials
Why You Should (Almost) Always Be Using 32‐Bit Variables in Your Code
Why should I use this over binary hacking
3
Multipage Options Menu
voloved edited this page 2023-05-09 06:55:04 -04:00
Table of Contents
By devolov
Goal: Add in more pages to the options menu.
This tutorial will be adding in a new page that inserts one a new page with the following:
- The ability to turn set and clear a flag called
FLAG_FOLLOWERS
. - The ability to switch between Easy/Normal/Hard on a difficulty setting in a var called
VAR_DIFFICULTY
.
Those two were chosen to show a way to add in a two option, and three option settings. You can use them as a template for adding in more options.
The data for each of these options is held in the gTask[].data
, which there are 16 data variables in that array. The zeroth variable holds the currently selected row and there are 6 default options, so there are nine more options that can be added before some kind of bit-packing is needed.
Defining the new text that will be used
-------------------------------- src/strings.c --------------------------------
index 31275fabd..65c6412bf 100644
@@ -1501,14 +1501,20 @@ const u8 gText_MoveCloserToLinkPartner[] = _("Move closer to your link partner(s
const u8 gText_ABtnRegistrationCounter[] = _("A Button: Registration Counter");
const u8 gText_ABtnTitleScreen[] = _("A Button: Title Screen");
const u8 gText_Option[] = _("OPTION");
+const u8 gText_SmallDot[] = _("·");
+const u8 gText_LargeDot[] = _("{EMOJI_CIRCLE}");
+const u8 gText_PageNav[] = _("{L_BUTTON}{R_BUTTON} PAGE");
const u8 gText_TextSpeed[] = _("TEXT SPEED");
const u8 gText_BattleScene[] = _("BATTLE SCENE");
const u8 gText_BattleStyle[] = _("BATTLE STYLE");
const u8 gText_Sound[] = _("SOUND");
const u8 gText_Frame[] = _("FRAME");
const u8 gText_OptionMenuCancel[] = _("CANCEL");
const u8 gText_ButtonMode[] = _("BUTTON MODE");
+const u8 gText_Follower[] = _("FOLLOWERS");
+const u8 gText_Difficulty[] = _("DIFFICULTY");
const u8 gText_TextSpeedSlow[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}SLOW");
const u8 gText_TextSpeedMid[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}MID");
const u8 gText_TextSpeedFast[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}FAST");
@@ -1525,6 +1529,18 @@ const u8 gText_FrameTypeNumber[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}");
const u8 gText_ButtonTypeNormal[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}NORMAL");
const u8 gText_ButtonTypeLR[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}LR");
const u8 gText_ButtonTypeLEqualsA[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}L=A");
+const u8 gText_FollowerOff[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}HIDE");
+const u8 gText_FollowerOn[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}SHOW");
+const u8 gText_DifficultyEasy[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}EASY");
+const u8 gText_DifficultyNormal[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}NORMAL");
+const u8 gText_DifficultyHard[] = _("{COLOR GREEN}{SHADOW LIGHT_GREEN}HARD");
const u8 gText_NumPlayerLink[] = _("{STR_VAR_1}P LINK");
const u8 gText_BronzeCard[] = _("BRONZE");
const u8 gText_CopperCard[] = _("COPPER");
Declaring the new text used
------------------------------ include/strings.h ------------------------------
index 11ce0b860..c1604ddc1 100644
@@ -318,16 +316,34 @@ extern const u8 gText_FrameType[];
extern const u8 gText_ButtonTypeNormal[];
extern const u8 gText_ButtonTypeLR[];
extern const u8 gText_ButtonTypeLEqualsA[];
+extern const u8 gText_FollowerOff[];
+extern const u8 gText_FollowerOn[];
+extern const u8 gText_DifficultyEasy[];
+extern const u8 gText_DifficultyNormal[];
+extern const u8 gText_DifficultyHard[];
extern const u8 gText_Option[];
extern const u8 gText_OptionMenu[];
+extern const u8 gText_SmallDot[];
+extern const u8 gText_LargeDot[];
+extern const u8 gText_PageNav[];
extern const u8 gText_TextSpeed[];
extern const u8 gText_BattleScene[];
extern const u8 gText_BattleStyle[];
extern const u8 gText_Sound[];
extern const u8 gText_Frame[];
extern const u8 gText_OptionMenuCancel[];
extern const u8 gText_ButtonMode[];
+extern const u8 gText_Follower[];
+extern const u8 gText_Difficulty[];
extern const u8 gText_MaleSymbol[];
extern const u8 gText_FemaleSymbol[];
------------------------------ src/option_menu.c ------------------------------
index 12c073045..c67bfe173 100644
@@ -15,8 +15,9 @@
#include "gba/m4a_internal.h"
#include "constants/rgb.h"
#include "event_data.h"
+#include "string_util.h"
// Task data
enum
{
TD_MENUSELECTION,
TD_TEXTSPEED,
TD_BATTLESCENE,
TD_BATTLESTYLE,
TD_SOUND,
TD_BUTTONMODE,
TD_FRAMETYPE,
+ TD_FOLLOWER,
+ TD_DIFFICULTY,
};
-// Menu items
+// Menu items Pg1
enum
{
MENUITEM_TEXTSPEED,
MENUITEM_BATTLESCENE,
MENUITEM_BATTLESTYLE,
MENUITEM_SOUND,
MENUITEM_BUTTONMODE,
MENUITEM_FRAMETYPE,
@@ -44,6 +47,18 @@ enum
MENUITEM_COUNT,
};
+// Menu items Pg2
+enum
+{
+ MENUITEM_FOLLOWER,
+ MENUITEM_DIFFICULTY,
+ MENUITEM_CANCEL_PG2,
+ MENUITEM_COUNT_PG2,
+};
+
// Window Ids
enum
{
@@ -51,17 +66,28 @@ enum
WIN_OPTIONS
};
+//Pg 1
#define YPOS_TEXTSPEED (MENUITEM_TEXTSPEED * 16)
#define YPOS_BATTLESCENE (MENUITEM_BATTLESCENE * 16)
#define YPOS_BATTLESTYLE (MENUITEM_BATTLESTYLE * 16)
#define YPOS_SOUND (MENUITEM_SOUND * 16)
#define YPOS_BUTTONMODE (MENUITEM_BUTTONMODE * 16)
#define YPOS_FRAMETYPE (MENUITEM_FRAMETYPE * 16)
+
+//Pg2
+#define YPOS_FOLLOWER (MENUITEM_FOLLOWER * 16)
+#define YPOS_DIFFICULTY (MENUITEM_DIFFICULTY * 16)
+
+#define PAGE_COUNT 2
// this file's functions
static void Task_OptionMenuFadeIn(u8 taskId);
static void Task_OptionMenuProcessInput(u8 taskId);
+static void Task_OptionMenuFadeIn_Pg2(u8 taskId);
+static void Task_OptionMenuProcessInput_Pg2(u8 taskId);
static void Task_OptionMenuSave(u8 taskId);
static void Task_OptionMenuFadeOut(u8 taskId);
static void HighlightOptionMenuItem(u8 selection);
@@ -71,8 +97,16 @@ static u8 BattleScene_ProcessInput(u8 selection);
static void BattleScene_DrawChoices(u8 selection);
static u8 BattleStyle_ProcessInput(u8 selection);
static void BattleStyle_DrawChoices(u8 selection);
+static u8 Follower_ProcessInput(u8 selection);
+static void Follower_DrawChoices(u8 selection);
+static u8 Difficulty_ProcessInput(u8 selection);
+static void Difficulty_DrawChoices(u8 selection);
static u8 Sound_ProcessInput(u8 selection);
static void Sound_DrawChoices(u8 selection);
static u8 FrameType_ProcessInput(u8 selection);
@@ -82,8 +116,11 @@ static void ButtonMode_DrawChoices(u8 selection);
static void DrawTextOption(void);
static void DrawOptionMenuTexts(void);
static void DrawBgWindowFrames(void);
EWRAM_DATA static bool8 sArrowPressed = FALSE;
+EWRAM_DATA static u8 sCurrPage = 0;
static const u16 sOptionMenuText_Pal[] = INCBIN_U16("graphics/interface/option_menu_text.gbapal");
// note: this is only used in the Japanese release
@@ -94,13 +131,22 @@ static const u8 *const sOptionMenuItemsNames[MENUITEM_COUNT] =
[MENUITEM_TEXTSPEED] = gText_TextSpeed,
[MENUITEM_BATTLESCENE] = gText_BattleScene,
[MENUITEM_BATTLESTYLE] = gText_BattleStyle,
[MENUITEM_SOUND] = gText_Sound,
[MENUITEM_BUTTONMODE] = gText_ButtonMode,
[MENUITEM_FRAMETYPE] = gText_Frame,
[MENUITEM_CANCEL] = gText_OptionMenuCancel,
};
+static const u8 *const sOptionMenuItemsNames_Pg2[MENUITEM_COUNT_PG2] =
+{
+ [MENUITEM_FOLLOWER] = gText_Follower,
+ [MENUITEM_DIFFICULTY] = gText_Difficulty,
+ [MENUITEM_CANCEL_PG2] = gText_OptionMenuCancel,
+};
+
static const struct WindowTemplate sOptionMenuWinTemplates[] =
{
{
@@ -164,8 +210,50 @@ static void VBlankCB(void)
TransferPlttBuffer();
}
+static void ReadAllCurrentSettings(u8 taskId)
+{
+ gTasks[taskId].data[TD_MENUSELECTION] = 0;
+ gTasks[taskId].data[TD_TEXTSPEED] = gSaveBlock2Ptr->optionsTextSpeed;
+ gTasks[taskId].data[TD_BATTLESCENE] = gSaveBlock2Ptr->optionsBattleSceneOff;
+ gTasks[taskId].data[TD_BATTLESTYLE] = gSaveBlock2Ptr->optionsBattleStyle;
+ gTasks[taskId].data[TD_SOUND] = gSaveBlock2Ptr->optionsSound;
+ gTasks[taskId].data[TD_BUTTONMODE] = gSaveBlock2Ptr->optionsButtonMode;
+ gTasks[taskId].data[TD_FRAMETYPE] = gSaveBlock2Ptr->optionsWindowFrameType;
+ gTasks[taskId].data[TD_FOLLOWER] = FlagGet(FLAG_POKEMON_FOLLOWERS);
+ gTasks[taskId].data[TD_DIFFICULTY] = VarGet(VAR_DIFFICULTY);
+}
+
+static void DrawOptionsPg1(u8 taskId)
+{
+ ReadAllCurrentSettings(taskId);
+ TextSpeed_DrawChoices(gTasks[taskId].data[TD_TEXTSPEED]);
+ BattleScene_DrawChoices(gTasks[taskId].data[TD_BATTLESCENE]);
+ BattleStyle_DrawChoices(gTasks[taskId].data[TD_BATTLESTYLE]);
+ Sound_DrawChoices(gTasks[taskId].data[TD_SOUND]);
+ ButtonMode_DrawChoices(gTasks[taskId].data[TD_BUTTONMODE]);
+ FrameType_DrawChoices(gTasks[taskId].data[TD_FRAMETYPE]);
+ HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]);
+ CopyWindowToVram(WIN_OPTIONS, COPYWIN_FULL);
+}
+
+static void DrawOptionsPg2(u8 taskId)
+{
+ ReadAllCurrentSettings(taskId);
+ Follower_DrawChoices(gTasks[taskId].data[TD_FOLLOWER]);
+ Difficulty_DrawChoices(gTasks[taskId].data[TD_DIFFICULTY]);
+ HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]);
+ CopyWindowToVram(WIN_OPTIONS, COPYWIN_FULL);
+}
+
void CB2_InitOptionMenu(void)
{
+ u8 taskId;
switch (gMain.state)
{
default:
@@ -240,27 +328,17 @@ void CB2_InitOptionMenu(void)
break;
case 10:
{
- u8 taskId = CreateTask(Task_OptionMenuFadeIn, 0);
-
- gTasks[taskId].data[TD_MENUSELECTION] = 0;
- gTasks[taskId].data[TD_TEXTSPEED] = gSaveBlock2Ptr->optionsTextSpeed;
- gTasks[taskId].data[TD_BATTLESCENE] = gSaveBlock2Ptr->optionsBattleSceneOff;
- gTasks[taskId].data[TD_BATTLESTYLE] = gSaveBlock2Ptr->optionsBattleStyle;
- gTasks[taskId].data[TD_SOUND] = gSaveBlock2Ptr->optionsSound;
- gTasks[taskId].data[TD_BUTTONMODE] = gSaveBlock2Ptr->optionsButtonMode;
- gTasks[taskId].data[TD_FRAMETYPE] = gSaveBlock2Ptr->optionsWindowFrameType;
-
- TextSpeed_DrawChoices(gTasks[taskId].data[TD_TEXTSPEED]);
- BattleScene_DrawChoices(gTasks[taskId].data[TD_BATTLESCENE]);
- BattleStyle_DrawChoices(gTasks[taskId].data[TD_BATTLESTYLE]);
- Sound_DrawChoices(gTasks[taskId].data[TD_SOUND]);
- ButtonMode_DrawChoices(gTasks[taskId].data[TD_BUTTONMODE]);
- FrameType_DrawChoices(gTasks[taskId].data[TD_FRAMETYPE]);
- HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]);
-
- CopyWindowToVram(WIN_OPTIONS, COPYWIN_FULL);
+ switch(sCurrPage)
+ {
+ case 0:
+ taskId = CreateTask(Task_OptionMenuFadeIn, 0);
+ DrawOptionsPg1(taskId);
+ break;
+ case 1:
+ taskId = CreateTask(Task_OptionMenuFadeIn_Pg2, 0);
+ DrawOptionsPg2(taskId);
+ break;
+ }
gMain.state++;
break;
}
@@ -268,7 +346,44 @@ void CB2_InitOptionMenu(void)
BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, RGB_BLACK);
SetVBlankCallback(VBlankCB);
SetMainCallback2(MainCB2);
return;
}
}
+static u8 Process_ChangePage(u8 CurrentPage)
+{
+ if (JOY_NEW(R_BUTTON))
+ {
+ if (CurrentPage < PAGE_COUNT - 1)
+ CurrentPage++;
+ else
+ CurrentPage = 0;
+ }
+ if (JOY_NEW(L_BUTTON))
+ {
+ if (CurrentPage != 0)
+ CurrentPage--;
+ else
+ CurrentPage = PAGE_COUNT - 1;
+ }
+ return CurrentPage;
+}
+
+static void Task_ChangePage(u8 taskId)
+{
+ DrawTextOption();
+ PutWindowTilemap(1);
+ DrawOptionMenuTexts();
+ switch(sCurrPage)
+ {
+ case 0:
+ DrawOptionsPg1(taskId);
+ gTasks[taskId].func = Task_OptionMenuFadeIn;
+ break;
+ case 1:
+ DrawOptionsPg2(taskId);
+ gTasks[taskId].func = Task_OptionMenuFadeIn_Pg2;
+ break;
+ }
+}
+
@@ -280,12 +395,19 @@ static void Task_OptionMenuFadeIn(u8 taskId)
static void Task_OptionMenuProcessInput(u8 taskId)
{
- if (JOY_NEW(A_BUTTON))
+ if (JOY_NEW(L_BUTTON) || JOY_NEW(R_BUTTON))
+ {
+ FillWindowPixelBuffer(WIN_OPTIONS, PIXEL_FILL(1));
+ ClearStdWindowAndFrame(WIN_OPTIONS, FALSE);
+ sCurrPage = Process_ChangePage(sCurrPage);
+ gTasks[taskId].func = Task_ChangePage;
+ }
+ else if (JOY_NEW(A_BUTTON))
{
if (gTasks[taskId].data[TD_MENUSELECTION] == MENUITEM_CANCEL)
gTasks[taskId].func = Task_OptionMenuSave;
}
else if (JOY_NEW(B_BUTTON))
{
gTasks[taskId].func = Task_OptionMenuSave;
}
@@ -372,6 +487,100 @@ static void Task_OptionMenuProcessInput(u8 taskId)
}
}
+static void Task_OptionMenuFadeIn_Pg2(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ gTasks[taskId].func = Task_OptionMenuProcessInput_Pg2;
+}
+
+static void Task_OptionMenuProcessInput_Pg2(u8 taskId)
+{
+ if (JOY_NEW(L_BUTTON) || JOY_NEW(R_BUTTON))
+ {
+ FillWindowPixelBuffer(WIN_OPTIONS, PIXEL_FILL(1));
+ ClearStdWindowAndFrame(WIN_OPTIONS, FALSE);
+ sCurrPage = Process_ChangePage(sCurrPage);
+ gTasks[taskId].func = Task_ChangePage;
+ }
+ else if (JOY_NEW(A_BUTTON))
+ {
+ if (gTasks[taskId].data[TD_MENUSELECTION] == MENUITEM_CANCEL_PG2)
+ gTasks[taskId].func = Task_OptionMenuSave;
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ gTasks[taskId].func = Task_OptionMenuSave;
+ }
+ else if (JOY_NEW(DPAD_UP))
+ {
+ if (gTasks[taskId].data[TD_MENUSELECTION] > 0)
+ gTasks[taskId].data[TD_MENUSELECTION]--;
+ else
+ gTasks[taskId].data[TD_MENUSELECTION] = MENUITEM_CANCEL_PG2;
+ HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]);
+ }
+ else if (JOY_NEW(DPAD_DOWN))
+ {
+ if (gTasks[taskId].data[TD_MENUSELECTION] < MENUITEM_CANCEL_PG2)
+ gTasks[taskId].data[TD_MENUSELECTION]++;
+ else
+ gTasks[taskId].data[TD_MENUSELECTION] = 0;
+ HighlightOptionMenuItem(gTasks[taskId].data[TD_MENUSELECTION]);
+ }
+ else
+ {
+ u8 previousOption;
+
+ switch (gTasks[taskId].data[TD_MENUSELECTION])
+ {
+ case MENUITEM_FOLLOWER:
+ previousOption = gTasks[taskId].data[TD_FOLLOWER];
+ gTasks[taskId].data[TD_FOLLOWER] = Follower_ProcessInput(gTasks[taskId].data[TD_FOLLOWER]);
+
+ if (previousOption != gTasks[taskId].data[TD_FOLLOWER])
+ Follower_DrawChoices(gTasks[taskId].data[TD_FOLLOWER]);
+ break;
+ case MENUITEM_DIFFICULTY:
+ previousOption = gTasks[taskId].data[TD_DIFFICULTY];
+ gTasks[taskId].data[TD_DIFFICULTY] = Difficulty_ProcessInput(gTasks[taskId].data[TD_DIFFICULTY]);
+
+ if (previousOption != gTasks[taskId].data[TD_DIFFICULTY])
+ Difficulty_DrawChoices(gTasks[taskId].data[TD_DIFFICULTY]);
+ break;
+ default:
+ return;
+ }
+
+ if (sArrowPressed)
+ {
+ sArrowPressed = FALSE;
+ CopyWindowToVram(WIN_OPTIONS, COPYWIN_GFX);
+ }
+ }
+}
+
static void Task_OptionMenuSave(u8 taskId)
{
gSaveBlock2Ptr->optionsTextSpeed = gTasks[taskId].data[TD_TEXTSPEED];
@@ -381,6 +590,35 @@ static void Task_OptionMenuSave(u8 taskId)
gSaveBlock2Ptr->optionsButtonMode = gTasks[taskId].data[TD_BUTTONMODE];
gSaveBlock2Ptr->optionsWindowFrameType = gTasks[taskId].data[TD_FRAMETYPE];
+ gTasks[taskId].data[TD_FOLLOWER] == 0 ? FlagClear(FLAG_POKEMON_FOLLOWERS) : FlagSet(FLAG_POKEMON_FOLLOWERS);
+ VarSet(VAR_DIFFICULTY, gTasks[taskId].data[TD_DIFFICULTY]);
BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK);
gTasks[taskId].func = Task_OptionMenuFadeOut;
}
@@ -485,7 +723,7 @@ static void BattleScene_DrawChoices(u8 selection)
DrawOptionMenuChoice(gText_BattleStyleShift, 104, YPOS_BATTLESTYLE, styles[0]);
DrawOptionMenuChoice(gText_BattleStyleSet, GetStringRightAlignXOffset(FONT_NORMAL, gText_BattleStyleSet, 198), YPOS_BATTLESTYLE, styles[1]);
}
+
+static u8 Follower_ProcessInput(u8 selection)
+{
+ if (JOY_NEW(DPAD_LEFT | DPAD_RIGHT))
+ {
+ selection ^= 1;
+ sArrowPressed = TRUE;
+ }
+
+ return selection;
+}
+
+static void Follower_DrawChoices(u8 selection)
+{
+ u8 styles[2];
+ styles[0] = 0;
+ styles[1] = 0;
+ styles[selection] = 1;
+ DrawOptionMenuChoice(gText_FollowerOff, 104, YPOS_FOLLOWER, styles[0]);
+ DrawOptionMenuChoice(gText_FollowerOn, GetStringRightAlignXOffset(FONT_NORMAL, gText_FollowerOn, 198), YPOS_FOLLOWER, styles[1]);
+}
+
+static u8 Difficulty_ProcessInput(u8 selection)
+{
+ if (JOY_NEW(DPAD_RIGHT))
+ {
+ if (selection <= 1)
+ selection++;
+ else
+ selection = 0;
+
+ sArrowPressed = TRUE;
+ }
+ if (JOY_NEW(DPAD_LEFT))
+ {
+ if (selection != 0)
+ selection--;
+ else
+ selection = 2;
+
+ sArrowPressed = TRUE;
+ }
+ return selection;
+}
+
+static void Difficulty_DrawChoices(u8 selection)
+{
+ u8 styles[3];
+ /* FALSE = Have the middle text be exactly in between where the first text ends and second text begins.
+ TRUE = Have the mid text be in the middle of the frame, ignoring the first and last text size.
+ Setting it to FALSE is how vanilla code does it for the TEST SPEED, but the layout looks off-center if there's
+ multiple three-item options in one page and the length of characters for the first and last choices
+ of one of the options mismatch.*/
+ bool8 centerMid = TRUE;
+ s32 widthEasy, widthNormal, widthHard, xMid;
+
+ styles[0] = 0;
+ styles[1] = 0;
+ styles[2] = 0;
+ styles[selection] = 1;
+
+ DrawOptionMenuChoice(gText_DifficultyEasy, 104, YPOS_DIFFICULTY, styles[0]);
+
+ widthNormal = GetStringWidth(FONT_NORMAL, gText_DifficultyNormal, 0);
+ if (centerMid){
+ xMid = (94 - widthNormal) / 2 + 104;
+ }
+ else{
+ widthEasy = GetStringWidth(FONT_NORMAL, gText_DifficultyEasy, 0);
+ widthHard = GetStringWidth(FONT_NORMAL, gText_DifficultyHard, 0);
+ widthNormal -= 94;
+ xMid = (widthEasy - widthNormal - widthHard) / 2 + 104;
+ }
+
+ DrawOptionMenuChoice(gText_DifficultyNormal, xMid, YPOS_DIFFICULTY, styles[1]);
+
+ DrawOptionMenuChoice(gText_DifficultyHard, GetStringRightAlignXOffset(FONT_NORMAL, gText_DifficultyHard, 198), YPOS_DIFFICULTY, styles[2]);
+}
@@ -672,31 +1035,56 @@ static void ButtonMode_DrawChoices(u8 selection)
xLR = (widthNormal - widthLR - widthLA) / 2 + 104;
DrawOptionMenuChoice(gText_ButtonTypeLR, xLR, YPOS_BUTTONMODE, styles[1]);
DrawOptionMenuChoice(gText_ButtonTypeLEqualsA, GetStringRightAlignXOffset(FONT_NORMAL, gText_ButtonTypeLEqualsA, 198), YPOS_BUTTONMODE, styles[2]);
}
static void DrawTextOption(void)
{
+ u32 i, widthOptions, xMid;
+ u8 pageDots[9] = _(""); // Array size should be at least (2 * PAGE_COUNT) -1
+ widthOptions = GetStringWidth(FONT_NORMAL, gText_Option, 0);
+
+ for (i = 0; i < PAGE_COUNT; i++)
+ {
+ if (i == sCurrPage)
+ StringAppend(pageDots, gText_LargeDot);
+ else
+ StringAppend(pageDots, gText_SmallDot);
+ if (i < PAGE_COUNT - 1)
+ StringAppend(pageDots, gText_Space);
+ }
+ xMid = (8 + widthOptions + 5);
FillWindowPixelBuffer(WIN_TEXT_OPTION, PIXEL_FILL(1));
AddTextPrinterParameterized(WIN_TEXT_OPTION, FONT_NORMAL, gText_Option, 8, 1, TEXT_SKIP_DRAW, NULL);
+ AddTextPrinterParameterized(WIN_TEXT_OPTION, FONT_NORMAL, pageDots, xMid, 1, TEXT_SKIP_DRAW, NULL);
+ AddTextPrinterParameterized(WIN_TEXT_OPTION, FONT_NORMAL, gText_PageNav, GetStringRightAlignXOffset(FONT_NORMAL, gText_PageNav, 198), 1, TEXT_SKIP_DRAW, NULL);
CopyWindowToVram(WIN_TEXT_OPTION, COPYWIN_FULL);
}
static void DrawOptionMenuTexts(void)
{
- u8 i;
+ u8 i, items;
+ const u8* const* menu = NULL;
+
+ switch (sCurrPage){
+ case 0:
+ items = MENUITEM_COUNT;
+ menu = sOptionMenuItemsNames;
+ break;
+ case 1:
+ items = MENUITEM_COUNT_PG2;
+ menu = sOptionMenuItemsNames_Pg2;
+ break;
+ }
FillWindowPixelBuffer(WIN_OPTIONS, PIXEL_FILL(1));
- for (i = 0; i < MENUITEM_COUNT; i++)
- AddTextPrinterParameterized(WIN_OPTIONS, FONT_NORMAL, sOptionMenuItemsNames[i], 8, (i * 16) + 1, TEXT_SKIP_DRAW, NULL);
+ for (i = 0; i < items; i++)
+ AddTextPrinterParameterized(WIN_OPTIONS, FONT_NORMAL, menu[i], 8, (i * 16) + 1, TEXT_SKIP_DRAW, NULL);
CopyWindowToVram(WIN_OPTIONS, COPYWIN_FULL);
}