-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Add Description Submenu
voloved edited this page Oct 20, 2023
·
11 revisions
By devolov
Goal: When pushing START
in battle, show the move's stats and description in a sub-menu.
Most of the credit goes to TheXaman's tx_ui_battle_typing system. I just pulled the small parts that I needed to make it easy to see what the move's description and effects are.
-------------------------- include/constants/battle.h --------------------------
index 4dfa31cec8..b1ac50303e 100644
@@ -361,8 +361,12 @@
#define B_WIN_VS_MULTI_PLAYER_4 20
#define B_WIN_VS_OUTCOME_DRAW 21
#define B_WIN_VS_OUTCOME_LEFT 22
#define B_WIN_VS_OUTCOME_RIGHT 23
+#define B_WIN_MOVE_DESCRIPTION 24
// The following are duplicate id values for windows that Battle Arena uses differently.
#define ARENA_WIN_PLAYER_NAME 15
#define ARENA_WIN_VS 16
------------------------------- src/battle_bg.c -------------------------------
index f24bb5d28a..9f76f1e0ff 100644
@@ -376,35 +376,44 @@ static const struct WindowTemplate sStandardBattleWindowTemplates[] =
[B_WIN_VS_OUTCOME_RIGHT] = {
.bg = 0,
.tilemapLeft = 19,
.tilemapTop = 2,
.width = 7,
.height = 2,
.paletteNum = 0,
.baseBlock = 0x00b0,
},
+ [B_WIN_MOVE_DESCRIPTION] = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 47,
+ .width = 18,
+ .height = 6,
+ .paletteNum = 5,
+ .baseBlock = 0x0350,
+ },
DUMMY_WIN_TEMPLATE
};
@@ -376,35 +376,44 @@ static const struct WindowTemplate sBattleArenaWindowTemplates[] =
[ARENA_WIN_JUDGMENT_TEXT] = {
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 15,
.width = 26,
.height = 4,
.paletteNum = 7,
.baseBlock = 0x0090,
},
+ [B_WIN_MOVE_DESCRIPTION] = {
+ .bg = 0,
+ .tilemapLeft = 1,
+ .tilemapTop = 47,
+ .width = 18,
+ .height = 6,
+ .paletteNum = 5,
+ .baseBlock = 0x0350,
+ },
DUMMY_WIN_TEMPLATE
};
static const struct WindowTemplate sBattleArenaWindowTemplates[] =
------------------------ src/battle_controller_player.c ------------------------
index 6bf2b9d0cb..1d0317c010 100644
@@ -36,8 +36,10 @@
#include "constants/party_menu.h"
#include "constants/songs.h"
#include "constants/trainers.h"
#include "constants/rgb.h"
+#include "menu.h"
+#include "pokemon_summary_screen.h"
static void PlayerHandleGetMonData(void);
static void PlayerHandleSetMonData(void);
static void PlayerHandleSetRawMonData(void);
@@ -104,8 +106,9 @@ static void MoveSelectionDestroyCursorAt(u8);
static void MoveSelectionDisplayPpNumber(void);
static void MoveSelectionDisplayPpString(void);
static void MoveSelectionDisplayMoveTypeDoubles(u8 targetId, u8 targetIdPrev);
static void MoveSelectionDisplayMoveType(void);
+static void MoveSelectionDisplayMoveDescription(void);
static void MoveSelectionDisplayMoveNames(void);
static void HandleMoveSwitching(void);
static void SwitchIn_HandleSoundAndEnd(void);
static void WaitForMonSelection(void);
@@ -185,8 +188,12 @@ static void (*const sPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(void) =
[CONTROLLER_ENDLINKBATTLE] = PlayerHandleEndLinkBattle,
[CONTROLLER_TERMINATOR_NOP] = PlayerCmdEnd
};
+static EWRAM_DATA bool8 sDescriptionSubmenu = 0;
+
static const u8 sTargetIdentities[MAX_BATTLERS_COUNT] = {B_POSITION_PLAYER_LEFT, B_POSITION_PLAYER_RIGHT, B_POSITION_OPPONENT_RIGHT, B_POSITION_OPPONENT_LEFT};
// unknown unused data
static const u8 sUnused[] = {0x48, 0x48, 0x20, 0x5a, 0x50, 0x50, 0x50, 0x58};
@@ -497,9 +504,23 @@ static void HandleInputChooseMove(void)
gPlayerDpadHoldFrames++;
else
gPlayerDpadHoldFrames = 0;
- if (JOY_NEW(A_BUTTON))
+ if (JOY_NEW(A_BUTTON) && !sDescriptionSubmenu)
{
u8 moveTarget;
PlaySE(SE_SELECT);
@@ -591,9 +578,9 @@ static void HandleInputChooseMove(void)
gSprites[gBattlerSpriteIds[gMultiUsePlayerCursor]].callback = SpriteCB_ShowAsMoveTarget;
}
}
- else if (JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59)
+ else if ((JOY_NEW(B_BUTTON) || gPlayerDpadHoldFrames > 59) && !sDescriptionSubmenu)
{
PlaySE(SE_SELECT);
BtlController_EmitTwoReturnValues(BUFFER_B, 10, 0xFFFF);
PlayerBufferExecCompleted();
@@ -607,8 +594,10 @@ static void HandleInputChooseMove(void)
PlaySE(SE_SELECT);
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
+ if (sDescriptionSubmenu)
+ MoveSelectionDisplayMoveDescription();
}
}
else if (JOY_NEW(DPAD_RIGHT))
{
@@ -620,8 +609,10 @@ static void HandleInputChooseMove(void)
PlaySE(SE_SELECT);
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
+ if (sDescriptionSubmenu)
+ MoveSelectionDisplayMoveDescription();
}
}
else if (JOY_NEW(DPAD_UP))
{
@@ -632,8 +623,10 @@ static void HandleInputChooseMove(void)
PlaySE(SE_SELECT);
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
+ if (sDescriptionSubmenu)
+ MoveSelectionDisplayMoveDescription();
}
}
else if (JOY_NEW(DPAD_DOWN))
{
@@ -645,11 +638,13 @@ static void HandleInputChooseMove(void)
PlaySE(SE_SELECT);
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0);
MoveSelectionDisplayPpNumber();
MoveSelectionDisplayMoveType();
+ if (sDescriptionSubmenu)
+ MoveSelectionDisplayMoveDescription();
}
}
- else if (JOY_NEW(SELECT_BUTTON))
+ else if (JOY_NEW(SELECT_BUTTON) && !sDescriptionSubmenu)
{
if (gNumberOfMovesToChoose > 1 && !(gBattleTypeFlags & BATTLE_TYPE_LINK))
{
MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 29);
@@ -633,8 +654,13 @@ static void HandleInputChooseMove(void)
BattlePutTextOnWindow(gText_BattleSwitchWhich, B_WIN_SWITCH_PROMPT);
gBattlerControllerFuncs[gActiveBattler] = HandleMoveSwitching;
}
}
+ if (sDescriptionSubmenu)
+ {
+ if (JOY_NEW(START_BUTTON) || JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON))
+ {
+ sDescriptionSubmenu = FALSE;
+ FillWindowPixelBuffer(B_WIN_MOVE_DESCRIPTION, PIXEL_FILL(0));
+ ClearStdWindowAndFrame(B_WIN_MOVE_DESCRIPTION, FALSE);
+ CopyWindowToVram(B_WIN_MOVE_DESCRIPTION, COPYWIN_GFX);
+ PlaySE(SE_SELECT);
+ MoveSelectionDisplayPpNumber();
+ MoveSelectionDisplayMoveType();
+ }
+ }
+ else if (JOY_NEW(START_BUTTON)) //AdditionalBattleInfo
+ {
+ sDescriptionSubmenu = TRUE;
+ MoveSelectionDisplayMoveDescription();
+ }
}
static u32 HandleMoveInputUnused(void)
{
@@ -1574,8 +1600,54 @@ static void MoveSelectionDisplayPpNumber(void)
BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_PP_REMAINING);
}
+static void MoveSelectionDisplayMoveDescription(void)
+{
+ struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct*)(&gBattleBufferA[gActiveBattler][4]);
+ u16 move = moveInfo->moves[gMoveSelectionCursor[gActiveBattler]];
+ u16 pwr = gBattleMoves[move].power;
+ u16 acc = gBattleMoves[move].accuracy;
+ s16 pri = gBattleMoves[move].priority;
+ u8 pwr_num[3], acc_num[3], pri_num[3], i;
+ u8 pwr_desc[7] = _("PWR: ");
+ u8 acc_desc[7] = _("ACC: ");
+ u8 pri_desc[7] = _("PRI: ");
+ u8 pwr_start[] = _("{CLEAR_TO 0x03}");
+ u8 acc_start[] = _("{CLEAR_TO 0x38}");
+ u8 pri_start[] = _("{CLEAR_TO 0x6D}");
+ LoadMessageBoxAndBorderGfx();
+ DrawStdWindowFrame(B_WIN_MOVE_DESCRIPTION, FALSE);
+ if (pwr < 2)
+ StringCopy(pwr_num, gText_BattleSwitchWhich5);
+ else
+ ConvertIntToDecimalStringN(pwr_num, pwr, STR_CONV_MODE_LEFT_ALIGN, 3);
+ if (acc < 2)
+ StringCopy(acc_num, gText_BattleSwitchWhich5);
+ else
+ ConvertIntToDecimalStringN(acc_num, acc, STR_CONV_MODE_LEFT_ALIGN, 3);
+ ConvertIntToDecimalStringN(pri_num, pri, STR_CONV_MODE_LEFT_ALIGN, 2);
+ StringCopy(gDisplayedStringBattle, pwr_start);
+ StringAppend(gDisplayedStringBattle, pwr_desc);
+ StringAppend(gDisplayedStringBattle, pwr_num);
+ StringAppend(gDisplayedStringBattle, acc_start);
+ StringAppend(gDisplayedStringBattle, acc_desc);
+ StringAppend(gDisplayedStringBattle, acc_num);
+ StringAppend(gDisplayedStringBattle, pri_start);
+ StringAppend(gDisplayedStringBattle, pri_desc);
+ StringAppend(gDisplayedStringBattle, pri_num);
+ StringAppend(gDisplayedStringBattle, gText_NewLine);
+ StringAppend(gDisplayedStringBattle, gMoveDescriptionPointers[move -1]);
+ BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_MOVE_DESCRIPTION);
+ CopyWindowToVram(B_WIN_MOVE_DESCRIPTION, COPYWIN_FULL);
+}
+
static void MoveSelectionCreateCursorAt(u8 cursorPosition, u8 baseTileNum)
{
u16 src[2];
src[0] = baseTileNum + 1;
----------------------------- src/battle_message.c -----------------------------
index 0835dda70c..4949575d00 100644
@@ -1784,9 +1784,9 @@ static const struct BattleWindowText sTextOnWindowsInfo_Normal[] =
.fgColor = TEXT_COLOR_WHITE,
.bgColor = TEXT_COLOR_TRANSPARENT,
.shadowColor = TEXT_COLOR_GREEN,
},
+ [B_WIN_MOVE_DESCRIPTION] = {
+ .fillValue = PIXEL_FILL(0xE),
+ .fontId = FONT_NARROW,
+ .x = 0,
+ .y = 1,
+ .letterSpacing = 0,
+ .lineSpacing = 0,
+ .speed = 0,
+ .fgColor = TEXT_DYNAMIC_COLOR_4,
+ .bgColor = TEXT_DYNAMIC_COLOR_5,
+ .shadowColor = TEXT_DYNAMIC_COLOR_6,
+ },
};
static const struct BattleWindowText sTextOnWindowsInfo_Arena[] =
{
@@ -1784,9 +1784,9 @@ static const struct BattleWindowText sTextOnWindowsInfo_Arena[] =
.fgColor = TEXT_COLOR_DARK_GRAY,
.bgColor = TEXT_COLOR_WHITE,
.shadowColor = TEXT_COLOR_LIGHT_GRAY,
},
+ [B_WIN_MOVE_DESCRIPTION] = {
+ .fillValue = PIXEL_FILL(0xE),
+ .fontId = FONT_NARROW,
+ .x = 0,
+ .y = 1,
+ .letterSpacing = 0,
+ .lineSpacing = 0,
+ .speed = 0,
+ .fgColor = TEXT_DYNAMIC_COLOR_4,
+ .bgColor = TEXT_DYNAMIC_COLOR_5,
+ .shadowColor = TEXT_DYNAMIC_COLOR_6,
+ },
};
Add this logic into string_util.c
to allow for negative numbers to be shown when displaying the move's priority.
----------------------------- gflib/string_util.c -----------------------------
index 8d969d1bf..88fd34164 100644
u8 *ConvertIntToDecimalStringN(u8 *dest, s32 value, enum StringConvertMode mode, u8 n)
{
enum { WAITING_FOR_NONZERO_DIGIT, WRITING_DIGITS, WRITING_SPACES } state;
s32 powerOfTen;
s32 largestPowerOfTen = sPowersOfTen[n - 1];
+ bool8 addNegSign = FALSE;
+ if (value < 0)
+ {
+ addNegSign = TRUE;
+ value = abs(value);
+ }
state = WAITING_FOR_NONZERO_DIGIT;
if (mode == STR_CONV_MODE_RIGHT_ALIGN)
state = WRITING_SPACES;
if (mode == STR_CONV_MODE_LEADING_ZEROS)
state = WRITING_DIGITS;
for (powerOfTen = largestPowerOfTen; powerOfTen > 0; powerOfTen /= 10)
{
u8 c;
u16 digit = value / powerOfTen;
s32 temp = value - (powerOfTen * digit);
if (state == WRITING_DIGITS)
{
u8 *out = dest++;
+ if (addNegSign)
+ {
+ addNegSign = FALSE;
+ *out = CHAR_HYPHEN;
+ out = dest++;
+ }
if (digit <= 9)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (digit != 0 || powerOfTen == 1)
{
u8 *out;
state = WRITING_DIGITS;
out = dest++;
+ if (addNegSign)
+ {
+ addNegSign = FALSE;
+ *out = CHAR_HYPHEN;
+ out = dest++;
+ }
if (digit <= 9)
c = sDigits[digit];
else
c = CHAR_QUESTION_MARK;
*out = c;
}
else if (state == WRITING_SPACES)
{
*dest++ = CHAR_SPACER;
}
value = temp;
}
*dest = EOS;
return dest;
}
If you're using make
and not make modern
, you'll need to add the battle_controller_player.o
to sym_ewram.txt
to add sDescriptionSubmenu
into EWRAM
.
----------------------------- sym_ewarm.txt -----------------------------
.include "src/pokenav.o"
.include "src/pokenav_list.o"
.include "src/menu_specialized.o"
.include "src/faraway_island.o"
.include "src/trainer_hill.o"
.include "src/rayquaza_scene.o"
+ .include "src/battle_controller_player.o"