Browse Source

Cleanup panel code (Part 1) (#7417)

HPPer changed from 80 to 81. The globes have 81 rows of pixels that can be filled.
pull/7423/head
Eric Robinson 2 years ago committed by GitHub
parent
commit
8970eaa410
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 298
      Source/control.cpp
  2. 10
      Source/control.h
  3. 4
      Source/controls/plrctrls.cpp
  4. 2
      Source/controls/touch/renderers.cpp
  5. 2
      Source/engine/render/scrollrt.cpp
  6. 2
      Source/panels/mainpanel.cpp
  7. 4
      Source/player.h

298
Source/control.cpp

@ -116,27 +116,41 @@ bool IsRightPanelOpen()
constexpr Size IncrementAttributeButtonSize { 41, 22 }; constexpr Size IncrementAttributeButtonSize { 41, 22 };
/** Maps from attribute_id to the rectangle on screen used for attribute increment buttons. */ /** Maps from attribute_id to the rectangle on screen used for attribute increment buttons. */
Rectangle ChrBtnsRect[4] = { Rectangle CharButtonRect[4] = {
{ { 137, 138 }, IncrementAttributeButtonSize }, { { 137, 138 }, IncrementAttributeButtonSize },
{ { 137, 166 }, IncrementAttributeButtonSize }, { { 137, 166 }, IncrementAttributeButtonSize },
{ { 137, 195 }, IncrementAttributeButtonSize }, { { 137, 195 }, IncrementAttributeButtonSize },
{ { 137, 223 }, IncrementAttributeButtonSize } { { 137, 223 }, IncrementAttributeButtonSize }
}; };
constexpr Size WidePanelButtonSize { 71, 20 };
constexpr Size PanelButtonSize { 33, 32 };
/** Positions of panel buttons. */ /** Positions of panel buttons. */
SDL_Rect PanBtnPos[8] = { Rectangle PanelButtonRect[8] = {
// clang-format off // clang-format off
{ 9, 9, 71, 19 }, // char button { { 9, 9 }, WidePanelButtonSize }, // char button
{ 9, 35, 71, 19 }, // quests button { { 9, 35 }, WidePanelButtonSize }, // quests button
{ 9, 75, 71, 19 }, // map button { { 9, 75 }, WidePanelButtonSize }, // map button
{ 9, 101, 71, 19 }, // menu button { { 9, 101 }, WidePanelButtonSize }, // menu button
{ 560, 9, 71, 19 }, // inv button { { 560, 9 }, WidePanelButtonSize }, // inv button
{ 560, 35, 71, 19 }, // spells button { { 560, 35 }, WidePanelButtonSize }, // spells button
{ 87, 91, 33, 32 }, // chat button { { 87, 91 }, PanelButtonSize }, // chat button
{ 527, 91, 33, 32 }, // friendly fire button { { 527, 91 }, PanelButtonSize }, // friendly fire button
// clang-format on // clang-format on
}; };
Rectangle LevelButtonRect = { { 40, -39 }, { 41, 22 } };
int beltItems = 8;
Size BeltSize { (INV_SLOT_SIZE_PX + 1) * beltItems, INV_SLOT_SIZE_PX };
Rectangle BeltRect { { 205, 5 }, BeltSize };
Rectangle SpellButtonRect { { 565, 64 }, { 56, 56 } };
Rectangle FlaskTopRect = { { 13, 3 }, { 60, 13 } };
constexpr Size FlaskBottomSize = { 84, 69 };
Rectangle FlaskBottomRect = { { 0, 16 }, FlaskBottomSize };
namespace { namespace {
std::optional<OwnedSurface> pLifeBuff; std::optional<OwnedSurface> pLifeBuff;
@ -146,21 +160,9 @@ OptionalOwnedClxSpriteList pDurIcons;
OptionalOwnedClxSpriteList multiButtons; OptionalOwnedClxSpriteList multiButtons;
OptionalOwnedClxSpriteList pPanelButtons; OptionalOwnedClxSpriteList pPanelButtons;
bool PanelButtons[8];
int PanelButtonIndex;
char TalkSave[8][MAX_SEND_STR_LEN];
uint8_t TalkSaveIndex;
uint8_t NextTalkSave;
char TalkMessage[MAX_SEND_STR_LEN];
bool TalkButtonsDown[3];
int sgbPlrTalkTbl;
bool WhisperList[MAX_PLRS];
TextInputCursorState ChatCursor;
std::optional<TextInputState> ChatInputState;
enum panel_button_id : uint8_t { enum panel_button_id : uint8_t {
PanelButtonCharinfo, PanelButtonCharinfo,
PanelButtonFirst = PanelButtonCharinfo,
PanelButtonQlog, PanelButtonQlog,
PanelButtonAutomap, PanelButtonAutomap,
PanelButtonMainmenu, PanelButtonMainmenu,
@ -168,8 +170,24 @@ enum panel_button_id : uint8_t {
PanelButtonSpellbook, PanelButtonSpellbook,
PanelButtonSendmsg, PanelButtonSendmsg,
PanelButtonFriendly, PanelButtonFriendly,
PanelButtonLast = PanelButtonFriendly,
}; };
bool PanelButtons[PanelButtonLast + 1];
int TotalSpButtons = 6;
int TotalMpButtons = 8;
char TalkSave[8][MAX_SEND_STR_LEN];
uint8_t TalkSaveIndex;
uint8_t NextTalkSave;
char TalkMessage[MAX_SEND_STR_LEN];
bool TalkButtonsDown[3];
int sgbPlrTalkTbl;
bool WhisperList[MAX_PLRS];
int PanelPaddingHeight = 16;
TextInputCursorState ChatCursor;
std::optional<TextInputState> ChatInputState;
/** Maps from panel_button_id to hotkey name. */ /** Maps from panel_button_id to hotkey name. */
const char *const PanBtnHotKey[8] = { "'c'", "'q'", N_("Tab"), N_("Esc"), "'i'", "'b'", N_("Enter"), nullptr }; const char *const PanBtnHotKey[8] = { "'c'", "'q'", N_("Tab"), N_("Esc"), "'i'", "'b'", N_("Enter"), nullptr };
/** Maps from panel_button_id to panel button description. */ /** Maps from panel_button_id to panel button description. */
@ -184,21 +202,6 @@ const char *const PanBtnStr[8] = {
"" // Player attack "" // Player attack
}; };
/**
* Draws a section of the empty flask cel on top of the panel to create the illusion
* of the flask getting empty. This function takes a cel and draws a
* horizontal stripe of height (max-min) onto the given buffer.
* @param out Target buffer.
* @param position Buffer coordinate.
* @param celBuf Buffer of the empty flask cel.
* @param y0 Top of the flask cel section to draw.
* @param y1 Bottom of the flask cel section to draw.
*/
void DrawFlaskTop(const Surface &out, Point position, const Surface &celBuf, int y0, int y1)
{
out.BlitFrom(celBuf, MakeSdlRect(0, static_cast<decltype(SDL_Rect {}.y)>(y0), celBuf.w(), y1 - y0), position);
}
/** /**
* Draws the dome of the flask that protrudes above the panel top line. * Draws the dome of the flask that protrudes above the panel top line.
* It draws a rectangle of fixed width 59 and height 'h' from the source buffer * It draws a rectangle of fixed width 59 and height 'h' from the source buffer
@ -209,10 +212,9 @@ void DrawFlaskTop(const Surface &out, Point position, const Surface &celBuf, int
* @param targetPosition Target buffer coordinate. * @param targetPosition Target buffer coordinate.
* @param h How many lines of the source buffer that will be copied. * @param h How many lines of the source buffer that will be copied.
*/ */
void DrawFlask(const Surface &out, const Surface &celBuf, Point sourcePosition, Point targetPosition, int h) void DrawFlaskAbovePanel(const Surface &out, const Surface &celBuf, Point sourcePosition, Point targetPosition, int h)
{ {
constexpr int FlaskWidth = 59; out.BlitFromSkipColorIndexZero(celBuf, MakeSdlRect(sourcePosition.x, sourcePosition.y, FlaskTopRect.size.width, h), targetPosition);
out.BlitFromSkipColorIndexZero(celBuf, MakeSdlRect(sourcePosition.x, sourcePosition.y, FlaskWidth, h), targetPosition);
} }
/** /**
@ -221,18 +223,35 @@ void DrawFlask(const Surface &out, const Surface &celBuf, Point sourcePosition,
* @param out The display region to draw to * @param out The display region to draw to
* @param sourceBuffer A sprite representing the appropriate background/empty flask style * @param sourceBuffer A sprite representing the appropriate background/empty flask style
* @param offset X coordinate offset for where the flask should be drawn * @param offset X coordinate offset for where the flask should be drawn
* @param fillPer How full the flask is (a value from 0 to 80) * @param fillPer How full the flask is (a value from 0 to 81)
*/ */
void DrawFlaskUpper(const Surface &out, const Surface &sourceBuffer, int offset, int fillPer) void DrawFlaskUpper(const Surface &out, const Surface &sourceBuffer, int offset, int fillPer)
{ {
// clamping because this function only draws the top 12% of the flask display int emptyRows = std::clamp(81 - fillPer, 0, FlaskTopRect.size.height);
int emptyPortion = std::clamp(80 - fillPer, 0, 11) + 2; // +2 to account for the frame being included in the sprite int filledRows = FlaskTopRect.size.height - emptyRows;
// Draw the empty part of the flask // Draw the empty part of the flask
DrawFlask(out, sourceBuffer, { 13, 3 }, GetMainPanel().position + Displacement { offset, -13 }, emptyPortion); DrawFlaskAbovePanel(out, sourceBuffer, FlaskTopRect.position, GetMainPanel().position + Displacement { offset, -FlaskTopRect.size.height }, FlaskTopRect.size.height);
if (emptyPortion < 13)
// Draw the filled part of the flask // Draw the filled part of the flask over the empty part
DrawFlask(out, *pBtmBuff, { offset, emptyPortion + 3 }, GetMainPanel().position + Displacement { offset, -13 + emptyPortion }, 13 - emptyPortion); if (filledRows > 0) {
DrawFlaskAbovePanel(out, *pBtmBuff, { offset, FlaskTopRect.position.y + emptyRows }, GetMainPanel().position + Displacement { offset, -FlaskTopRect.size.height + emptyRows }, filledRows);
}
}
/**
* Draws a section of the empty flask cel on top of the panel to create the illusion
* of the flask getting empty. This function takes a cel and draws a
* horizontal stripe of height (max-min) onto the given buffer.
* @param out Target buffer.
* @param position Buffer coordinate.
* @param celBuf Buffer of the empty flask cel.
* @param y0 Top of the flask cel section to draw.
* @param y1 Bottom of the flask cel section to draw.
*/
void DrawFlaskOnPanel(const Surface &out, Point position, const Surface &celBuf, int y0, int y1)
{
out.BlitFrom(celBuf, MakeSdlRect(0, static_cast<decltype(SDL_Rect {}.y)>(y0), celBuf.w(), y1 - y0), position);
} }
/** /**
@ -245,15 +264,10 @@ void DrawFlaskUpper(const Surface &out, const Surface &sourceBuffer, int offset,
*/ */
void DrawFlaskLower(const Surface &out, const Surface &sourceBuffer, int offset, int fillPer) void DrawFlaskLower(const Surface &out, const Surface &sourceBuffer, int offset, int fillPer)
{ {
int filled = std::clamp(fillPer, 0, 69); int filled = std::clamp(fillPer, 0, FlaskBottomSize.height);
if (filled < 69)
DrawFlaskTop(out, GetMainPanel().position + Displacement { offset, 0 }, sourceBuffer, 16, 85 - filled);
// It appears that the panel defaults to having a filled flask and DrawFlaskTop only overlays the appropriate amount of empty space. if (filled < FlaskBottomSize.height)
// This draw might not be necessary? DrawFlaskOnPanel(out, GetMainPanel().position + Displacement { offset, 0 }, sourceBuffer, FlaskBottomRect.position.y, FlaskBottomRect.position.y + FlaskBottomRect.size.height - filled);
if (filled > 0)
DrawPanelBox(out, MakeSdlRect(offset, 85 - filled, 88, filled), GetMainPanel().position + Displacement { offset, 69 - filled });
} }
void SetButtonStateDown(int btnId) void SetButtonStateDown(int btnId)
@ -269,7 +283,9 @@ void PrintInfo(const Surface &out)
return; return;
const int space[] = { 18, 12, 6, 3, 0 }; const int space[] = { 18, 12, 6, 3, 0 };
Rectangle infoArea { GetMainPanel().position + InfoBoxTopLeft, InfoBoxSize }; Rectangle infoBox = InfoBoxRect;
infoBox.position = GetPanelPosition(UiPanels::Main, infoBox.position);
const auto newLineCount = static_cast<int>(c_count(InfoString.str(), '\n')); const auto newLineCount = static_cast<int>(c_count(InfoString.str(), '\n'));
const int spaceIndex = std::min(4, newLineCount); const int spaceIndex = std::min(4, newLineCount);
@ -279,11 +295,11 @@ void PrintInfo(const Surface &out)
// Adjusting the line height to add spacing between lines // Adjusting the line height to add spacing between lines
// will also add additional space beneath the last line // will also add additional space beneath the last line
// which throws off the vertical centering // which throws off the vertical centering
infoArea.position.y += spacing / 2; infoBox.position.y += spacing / 2;
SpeakText(InfoString); SpeakText(InfoString);
DrawString(out, InfoString, infoArea, DrawString(out, InfoString, infoBox,
{ {
.flags = InfoColor | UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::KerningFitSpacing, .flags = InfoColor | UiFlags::AlignCenter | UiFlags::VerticalCenter | UiFlags::KerningFitSpacing,
.spacing = 2, .spacing = 2,
@ -730,7 +746,7 @@ void FocusOnCharInfo()
if (stat == -1) if (stat == -1)
return; return;
SetCursorPos(ChrBtnsRect[stat].Center()); SetCursorPos(CharButtonRect[stat].Center());
} }
void OpenCharPanel() void OpenCharPanel()
@ -849,7 +865,7 @@ void control_update_life_mana()
void InitControlPan() void InitControlPan()
{ {
if (!HeadlessMode) { if (!HeadlessMode) {
pBtmBuff.emplace(GetMainPanel().size.width, (GetMainPanel().size.height + 16) * (IsChatAvailable() ? 2 : 1)); pBtmBuff.emplace(GetMainPanel().size.width, (GetMainPanel().size.height + PanelPaddingHeight) * (IsChatAvailable() ? 2 : 1));
pManaBuff.emplace(88, 88); pManaBuff.emplace(88, 88);
pLifeBuff.emplace(88, 88); pLifeBuff.emplace(88, 88);
@ -857,7 +873,7 @@ void InitControlPan()
LoadLargeSpellIcons(); LoadLargeSpellIcons();
{ {
const OwnedClxSpriteList sprite = LoadCel("ctrlpan\\panel8", GetMainPanel().size.width); const OwnedClxSpriteList sprite = LoadCel("ctrlpan\\panel8", GetMainPanel().size.width);
ClxDraw(*pBtmBuff, { 0, (GetMainPanel().size.height + 16) - 1 }, sprite[0]); ClxDraw(*pBtmBuff, { 0, (GetMainPanel().size.height + PanelPaddingHeight) - 1 }, sprite[0]);
} }
{ {
const Point bulbsPosition { 0, 87 }; const Point bulbsPosition { 0, 87 };
@ -872,7 +888,7 @@ void InitControlPan()
if (!HeadlessMode) { if (!HeadlessMode) {
{ {
const OwnedClxSpriteList sprite = LoadCel("ctrlpan\\talkpanl", GetMainPanel().size.width); const OwnedClxSpriteList sprite = LoadCel("ctrlpan\\talkpanl", GetMainPanel().size.width);
ClxDraw(*pBtmBuff, { 0, (GetMainPanel().size.height + 16) * 2 - 1 }, sprite[0]); ClxDraw(*pBtmBuff, { 0, (GetMainPanel().size.height + PanelPaddingHeight) * 2 - 1 }, sprite[0]);
} }
multiButtons = LoadCel("ctrlpan\\p8but2", 33); multiButtons = LoadCel("ctrlpan\\p8but2", 33);
talkButtons = LoadCel("ctrlpan\\talkbutt", 61); talkButtons = LoadCel("ctrlpan\\talkbutt", 61);
@ -894,10 +910,6 @@ void InitControlPan()
pChrButtons = LoadCel("data\\charbut", CharButtonsFrameWidths); pChrButtons = LoadCel("data\\charbut", CharButtonsFrameWidths);
} }
ClearPanBtn(); ClearPanBtn();
if (!IsChatAvailable())
PanelButtonIndex = 6;
else
PanelButtonIndex = 8;
if (!HeadlessMode) if (!HeadlessMode)
pDurIcons = LoadCel("items\\duricons", 32); pDurIcons = LoadCel("items\\duricons", 32);
for (bool &buttonEnabled : chrbtn) for (bool &buttonEnabled : chrbtn)
@ -925,29 +937,34 @@ void InitControlPan()
void DrawCtrlPan(const Surface &out) void DrawCtrlPan(const Surface &out)
{ {
DrawPanelBox(out, MakeSdlRect(0, sgbPlrTalkTbl + 16, GetMainPanel().size.width, GetMainPanel().size.height), GetMainPanel().position); DrawPanelBox(out, MakeSdlRect(0, sgbPlrTalkTbl + PanelPaddingHeight, GetMainPanel().size.width, GetMainPanel().size.height), GetMainPanel().position);
DrawInfoBox(out); DrawInfoBox(out);
} }
void DrawCtrlBtns(const Surface &out) void DrawCtrlBtns(const Surface &out)
{ {
const Point mainPanelPosition = GetMainPanel().position; const Point mainPanelPosition = GetMainPanel().position;
for (int i = 0; i < 6; i++) { int totalButtons = IsChatAvailable() ? TotalMpButtons : TotalSpButtons;
for (int i = 0; i < TotalSpButtons; i++) {
if (!PanelButtons[i]) { if (!PanelButtons[i]) {
DrawPanelBox(out, MakeSdlRect(PanBtnPos[i].x, PanBtnPos[i].y + 16, 71, 20), mainPanelPosition + Displacement { PanBtnPos[i].x, PanBtnPos[i].y }); DrawPanelBox(out, MakeSdlRect(PanelButtonRect[i].position.x, PanelButtonRect[i].position.y + PanelPaddingHeight, PanelButtonRect[i].size.width, PanelButtonRect[i].size.height + 1), mainPanelPosition + Displacement { PanelButtonRect[i].position.x, PanelButtonRect[i].position.y });
} else { } else {
Point position = mainPanelPosition + Displacement { PanBtnPos[i].x, PanBtnPos[i].y + 18 }; Point position = mainPanelPosition + Displacement { PanelButtonRect[i].position.x, PanelButtonRect[i].position.y };
ClxDraw(out, position, (*pPanelButtons)[i]); RenderClxSprite(out, (*pPanelButtons)[i], position);
RenderClxSprite(out, (*PanelButtonDown)[i], position + Displacement { 4, -18 }); RenderClxSprite(out, (*PanelButtonDown)[i], position + Displacement { 4, 0 });
} }
} }
if (PanelButtonIndex == 8) { if (IsChatAvailable()) {
ClxDraw(out, mainPanelPosition + Displacement { 87, 122 }, (*multiButtons)[PanelButtons[6] ? 1 : 0]); RenderClxSprite(out, (*multiButtons)[PanelButtons[PanelButtonSendmsg] ? 1 : 0], mainPanelPosition + Displacement { PanelButtonRect[PanelButtonSendmsg].position.x, PanelButtonRect[PanelButtonSendmsg].position.y });
Point friendlyButtonPosition = mainPanelPosition + Displacement { PanelButtonRect[PanelButtonFriendly].position.x, PanelButtonRect[PanelButtonFriendly].position.y };
if (MyPlayer->friendlyMode) if (MyPlayer->friendlyMode)
ClxDraw(out, mainPanelPosition + Displacement { 527, 122 }, (*multiButtons)[PanelButtons[7] ? 3 : 2]); RenderClxSprite(out, (*multiButtons)[PanelButtons[PanelButtonFriendly] ? 3 : 2], friendlyButtonPosition);
else else
ClxDraw(out, mainPanelPosition + Displacement { 527, 122 }, (*multiButtons)[PanelButtons[7] ? 5 : 4]); RenderClxSprite(out, (*multiButtons)[PanelButtons[PanelButtonFriendly] ? 5 : 4], friendlyButtonPosition);
} }
} }
@ -963,18 +980,25 @@ void DoPanBtn()
{ {
const Point mainPanelPosition = GetMainPanel().position; const Point mainPanelPosition = GetMainPanel().position;
for (int i = 0; i < PanelButtonIndex; i++) { int totalButtons = IsChatAvailable() ? TotalMpButtons : TotalSpButtons;
int x = PanBtnPos[i].x + mainPanelPosition.x + PanBtnPos[i].w;
int y = PanBtnPos[i].y + mainPanelPosition.y + PanBtnPos[i].h; for (int i = 0; i < totalButtons; i++) {
if (MousePosition.x >= PanBtnPos[i].x + mainPanelPosition.x && MousePosition.x <= x) { Rectangle button = PanelButtonRect[i];
if (MousePosition.y >= PanBtnPos[i].y + mainPanelPosition.y && MousePosition.y <= y) {
PanelButtons[i] = true; button.position = GetPanelPosition(UiPanels::Main, button.position);
RedrawComponent(PanelDrawComponent::ControlButtons);
panbtndown = true; if (button.contains(MousePosition)) {
} PanelButtons[i] = true;
RedrawComponent(PanelDrawComponent::ControlButtons);
panbtndown = true;
} }
} }
if (!spselflag && MousePosition.x >= 565 + mainPanelPosition.x && MousePosition.x < 621 + mainPanelPosition.x && MousePosition.y >= 64 + mainPanelPosition.y && MousePosition.y < 120 + mainPanelPosition.y) {
Rectangle spellSelectButton = SpellButtonRect;
spellSelectButton.position = GetPanelPosition(UiPanels::Main, spellSelectButton.position);
if (!spselflag && spellSelectButton.contains(MousePosition)) {
if ((SDL_GetModState() & KMOD_SHIFT) != 0) { if ((SDL_GetModState() & KMOD_SHIFT) != 0) {
Player &myPlayer = *MyPlayer; Player &myPlayer = *MyPlayer;
myPlayer._pRSpell = SpellID::Invalid; myPlayer._pRSpell = SpellID::Invalid;
@ -989,22 +1013,21 @@ void DoPanBtn()
void control_check_btn_press() void control_check_btn_press()
{ {
const Point mainPanelPosition = GetMainPanel().position; Rectangle menuButton = PanelButtonRect[PanelButtonMainmenu];
int x = PanBtnPos[3].x + mainPanelPosition.x + PanBtnPos[3].w;
int y = PanBtnPos[3].y + mainPanelPosition.y + PanBtnPos[3].h; menuButton.position = GetPanelPosition(UiPanels::Main, menuButton.position);
if (MousePosition.x >= PanBtnPos[3].x + mainPanelPosition.x
&& MousePosition.x <= x if (menuButton.contains(MousePosition)) {
&& MousePosition.y >= PanBtnPos[3].y + mainPanelPosition.y SetButtonStateDown(PanelButtonMainmenu);
&& MousePosition.y <= y) { return;
SetButtonStateDown(3);
} }
x = PanBtnPos[6].x + mainPanelPosition.x + PanBtnPos[6].w;
y = PanBtnPos[6].y + mainPanelPosition.y + PanBtnPos[6].h; Rectangle chatButton = PanelButtonRect[PanelButtonSendmsg];
if (MousePosition.x >= PanBtnPos[6].x + mainPanelPosition.x
&& MousePosition.x <= x chatButton.position = GetPanelPosition(UiPanels::Main, chatButton.position);
&& MousePosition.y >= PanBtnPos[6].y + mainPanelPosition.y
&& MousePosition.y <= y) { if (chatButton.contains(MousePosition)) {
SetButtonStateDown(6); SetButtonStateDown(PanelButtonSendmsg);
} }
} }
@ -1034,11 +1057,15 @@ void CheckPanelInfo()
{ {
panelflag = false; panelflag = false;
InfoString = StringOrView {}; InfoString = StringOrView {};
const Point mainPanelPosition = GetMainPanel().position;
for (int i = 0; i < PanelButtonIndex; i++) { int totalButtons = IsChatAvailable() ? TotalMpButtons : TotalSpButtons;
int xend = PanBtnPos[i].x + mainPanelPosition.x + PanBtnPos[i].w;
int yend = PanBtnPos[i].y + mainPanelPosition.y + PanBtnPos[i].h; for (int i = 0; i < totalButtons; i++) {
if (MousePosition.x >= PanBtnPos[i].x + mainPanelPosition.x && MousePosition.x <= xend && MousePosition.y >= PanBtnPos[i].y + mainPanelPosition.y && MousePosition.y <= yend) { Rectangle button = PanelButtonRect[i];
button.position = GetPanelPosition(UiPanels::Main, button.position);
if (button.contains(MousePosition)) {
if (i != 7) { if (i != 7) {
InfoString = _(PanBtnStr[i]); InfoString = _(PanBtnStr[i]);
} else { } else {
@ -1054,7 +1081,12 @@ void CheckPanelInfo()
panelflag = true; panelflag = true;
} }
} }
if (!spselflag && MousePosition.x >= 565 + mainPanelPosition.x && MousePosition.x < 621 + mainPanelPosition.x && MousePosition.y >= 64 + mainPanelPosition.y && MousePosition.y < 120 + mainPanelPosition.y) {
Rectangle spellSelectButton = SpellButtonRect;
spellSelectButton.position = GetPanelPosition(UiPanels::Main, spellSelectButton.position);
if (!spselflag && spellSelectButton.contains(MousePosition)) {
InfoString = _("Select current spell button"); InfoString = _("Select current spell button");
InfoColor = UiFlags::ColorWhite; InfoColor = UiFlags::ColorWhite;
panelflag = true; panelflag = true;
@ -1087,35 +1119,37 @@ void CheckPanelInfo()
} }
} }
} }
if (MousePosition.x > 190 + mainPanelPosition.x && MousePosition.x < 437 + mainPanelPosition.x && MousePosition.y > 4 + mainPanelPosition.y && MousePosition.y < 33 + mainPanelPosition.y)
Rectangle belt = BeltRect;
belt.position = GetPanelPosition(UiPanels::Main, belt.position);
if (belt.contains(MousePosition))
pcursinvitem = CheckInvHLight(); pcursinvitem = CheckInvHLight();
if (CheckXPBarInfo()) { if (CheckXPBarInfo())
panelflag = true; panelflag = true;
}
} }
void CheckBtnUp() void CheckBtnUp()
{ {
bool gamemenuOff = true; bool gamemenuOff = true;
const Point mainPanelPosition = GetMainPanel().position;
RedrawComponent(PanelDrawComponent::ControlButtons); RedrawComponent(PanelDrawComponent::ControlButtons);
panbtndown = false; panbtndown = false;
for (int i = 0; i < 8; i++) { for (int i = PanelButtonFirst; i <= PanelButtonLast; i++) {
if (!PanelButtons[i]) { if (!PanelButtons[i])
continue; continue;
}
PanelButtons[i] = false; PanelButtons[i] = false;
if (MousePosition.x < PanBtnPos[i].x + mainPanelPosition.x Rectangle button = PanelButtonRect[i];
|| MousePosition.x > PanBtnPos[i].x + mainPanelPosition.x + PanBtnPos[i].w
|| MousePosition.y < PanBtnPos[i].y + mainPanelPosition.y button.position = GetPanelPosition(UiPanels::Main, button.position);
|| MousePosition.y > PanBtnPos[i].y + mainPanelPosition.y + PanBtnPos[i].h) {
if (!button.contains(MousePosition))
continue; continue;
}
switch (i) { switch (i) {
case PanelButtonCharinfo: case PanelButtonCharinfo:
@ -1188,7 +1222,7 @@ void FreeControlPan()
void DrawInfoBox(const Surface &out) void DrawInfoBox(const Surface &out)
{ {
DrawPanelBox(out, { 177, 62, InfoBoxSize.width, InfoBoxSize.height }, GetMainPanel().position + InfoBoxTopLeft); DrawPanelBox(out, { InfoBoxRect.position.x, InfoBoxRect.position.y + PanelPaddingHeight, InfoBoxRect.size.width, InfoBoxRect.size.height }, GetMainPanel().position + Displacement { InfoBoxRect.position.x, InfoBoxRect.position.y });
if (!panelflag && !trigflag && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && !spselflag && pcurs != CURSOR_HOURGLASS) { if (!panelflag && !trigflag && pcursinvitem == -1 && pcursstashitem == StashStruct::EmptyCell && !spselflag && pcurs != CURSOR_HOURGLASS) {
InfoString = StringOrView {}; InfoString = StringOrView {};
InfoColor = UiFlags::ColorWhite; InfoColor = UiFlags::ColorWhite;
@ -1245,14 +1279,22 @@ void CheckLvlBtn()
} }
const Point mainPanelPosition = GetMainPanel().position; const Point mainPanelPosition = GetMainPanel().position;
if (!lvlbtndown && MousePosition.x >= 40 + mainPanelPosition.x && MousePosition.x <= 81 + mainPanelPosition.x && MousePosition.y >= -39 + mainPanelPosition.y && MousePosition.y <= -17 + mainPanelPosition.y) Rectangle button = LevelButtonRect;
button.position = GetPanelPosition(UiPanels::Main, button.position);
if (!lvlbtndown && button.contains(MousePosition))
lvlbtndown = true; lvlbtndown = true;
} }
void ReleaseLvlBtn() void ReleaseLvlBtn()
{ {
const Point mainPanelPosition = GetMainPanel().position; const Point mainPanelPosition = GetMainPanel().position;
if (MousePosition.x >= 40 + mainPanelPosition.x && MousePosition.x <= 81 + mainPanelPosition.x && MousePosition.y >= -39 + mainPanelPosition.y && MousePosition.y <= -17 + mainPanelPosition.y) { Rectangle button = LevelButtonRect;
button.position = GetPanelPosition(UiPanels::Main, button.position);
if (button.contains(MousePosition)) {
OpenCharPanel(); OpenCharPanel();
} }
lvlbtndown = false; lvlbtndown = false;
@ -1262,9 +1304,9 @@ void DrawLevelUpIcon(const Surface &out)
{ {
if (IsLevelUpButtonVisible()) { if (IsLevelUpButtonVisible()) {
int nCel = lvlbtndown ? 2 : 1; int nCel = lvlbtndown ? 2 : 1;
DrawString(out, _("Level Up"), { GetMainPanel().position + Displacement { 0, -62 }, { 120, 0 } }, DrawString(out, _("Level Up"), { GetMainPanel().position + Displacement { 0, LevelButtonRect.position.y - 23 }, { 120, 0 } },
{ .flags = UiFlags::ColorWhite | UiFlags::AlignCenter | UiFlags::KerningFitSpacing }); { .flags = UiFlags::ColorWhite | UiFlags::AlignCenter | UiFlags::KerningFitSpacing });
ClxDraw(out, GetMainPanel().position + Displacement { 40, -17 }, (*pChrButtons)[nCel]); RenderClxSprite(out, (*pChrButtons)[nCel], GetMainPanel().position + Displacement { LevelButtonRect.position.x, LevelButtonRect.position.y });
} }
} }
@ -1279,7 +1321,7 @@ void CheckChrBtns()
if (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute)) if (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute))
continue; continue;
auto buttonId = static_cast<size_t>(attribute); auto buttonId = static_cast<size_t>(attribute);
Rectangle button = ChrBtnsRect[buttonId]; Rectangle button = CharButtonRect[buttonId];
button.position = GetPanelPosition(UiPanels::Character, button.position); button.position = GetPanelPosition(UiPanels::Character, button.position);
if (button.contains(MousePosition)) { if (button.contains(MousePosition)) {
chrbtn[buttonId] = true; chrbtn[buttonId] = true;
@ -1297,7 +1339,7 @@ void ReleaseChrBtns(bool addAllStatPoints)
continue; continue;
chrbtn[buttonId] = false; chrbtn[buttonId] = false;
Rectangle button = ChrBtnsRect[buttonId]; Rectangle button = CharButtonRect[buttonId];
button.position = GetPanelPosition(UiPanels::Character, button.position); button.position = GetPanelPosition(UiPanels::Character, button.position);
if (button.contains(MousePosition)) { if (button.contains(MousePosition)) {
Player &myPlayer = *MyPlayer; Player &myPlayer = *MyPlayer;
@ -1557,7 +1599,7 @@ void control_type_message()
for (bool &talkButtonDown : TalkButtonsDown) { for (bool &talkButtonDown : TalkButtonsDown) {
talkButtonDown = false; talkButtonDown = false;
} }
sgbPlrTalkTbl = GetMainPanel().size.height + 16; sgbPlrTalkTbl = GetMainPanel().size.height + PanelPaddingHeight;
RedrawEverything(); RedrawEverything();
TalkSaveIndex = NextTalkSave; TalkSaveIndex = NextTalkSave;
SDL_StartTextInput(); SDL_StartTextInput();

10
Source/control.h

@ -35,9 +35,7 @@ namespace devilution {
constexpr Size SidePanelSize { 320, 352 }; constexpr Size SidePanelSize { 320, 352 };
// Info box displacement of the top-left corner relative to GetMainPanel().position. constexpr Rectangle InfoBoxRect = { { 177, 46 }, { 288, 64 } };
constexpr Displacement InfoBoxTopLeft { 177, 46 };
constexpr Size InfoBoxSize { 288, 64 };
extern bool dropGoldFlag; extern bool dropGoldFlag;
extern TextInputCursorState GoldDropCursor; extern TextInputCursorState GoldDropCursor;
@ -62,7 +60,7 @@ bool IsLeftPanelOpen();
bool IsRightPanelOpen(); bool IsRightPanelOpen();
extern std::optional<OwnedSurface> pBtmBuff; extern std::optional<OwnedSurface> pBtmBuff;
extern OptionalOwnedClxSpriteList pGBoxBuff; extern OptionalOwnedClxSpriteList pGBoxBuff;
extern SDL_Rect PanBtnPos[8]; extern Rectangle PanelButtonRect[8];
void CalculatePanelAreas(); void CalculatePanelAreas();
bool IsChatAvailable(); bool IsChatAvailable();
@ -123,7 +121,7 @@ void DrawFlaskValues(const Surface &out, Point pos, int currValue, int maxValue)
/** /**
* @brief calls on the active player object to update HP/Mana percentage variables * @brief calls on the active player object to update HP/Mana percentage variables
* *
* This is used to ensure that DrawFlask routines display an accurate representation of the players health/mana * This is used to ensure that DrawFlaskAbovePanel routines display an accurate representation of the players health/mana
* *
* @see Player::UpdateHitPointPercentage() and Player::UpdateManaPercentage() * @see Player::UpdateHitPointPercentage() and Player::UpdateManaPercentage()
*/ */
@ -192,6 +190,6 @@ void OpenGoldDrop(int8_t invIndex, int max);
void CloseGoldDrop(); void CloseGoldDrop();
int GetGoldDropMax(); int GetGoldDropMax();
bool HandleGoldDropTextInputEvent(const SDL_Event &event); bool HandleGoldDropTextInputEvent(const SDL_Event &event);
extern Rectangle ChrBtnsRect[4]; extern Rectangle CharButtonRect[4];
} // namespace devilution } // namespace devilution

4
Source/controls/plrctrls.cpp

@ -562,7 +562,7 @@ void AttrIncBtnSnap(AxisDirection dir)
int slot = 0; int slot = 0;
Rectangle button; Rectangle button;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
button = ChrBtnsRect[i]; button = CharButtonRect[i];
button.position = GetPanelPosition(UiPanels::Character, button.position); button.position = GetPanelPosition(UiPanels::Character, button.position);
if (button.contains(MousePosition)) { if (button.contains(MousePosition)) {
slot = i; slot = i;
@ -579,7 +579,7 @@ void AttrIncBtnSnap(AxisDirection dir)
} }
// move cursor to our new location // move cursor to our new location
button = ChrBtnsRect[slot]; button = CharButtonRect[slot];
button.position = GetPanelPosition(UiPanels::Character, button.position); button.position = GetPanelPosition(UiPanels::Character, button.position);
SetCursorPos(button.Center()); SetCursorPos(button.Center());
} }

2
Source/controls/touch/renderers.cpp

@ -166,7 +166,7 @@ bool InteractsWithCharButton(Point point)
if (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute)) if (myPlayer.GetBaseAttributeValue(attribute) >= myPlayer.GetMaximumAttributeValue(attribute))
continue; continue;
auto buttonId = static_cast<size_t>(attribute); auto buttonId = static_cast<size_t>(attribute);
Rectangle button = ChrBtnsRect[buttonId]; Rectangle button = CharButtonRect[buttonId];
button.position = GetPanelPosition(UiPanels::Character, button.position); button.position = GetPanelPosition(UiPanels::Character, button.position);
if (button.contains(point)) { if (button.contains(point)) {
return true; return true;

2
Source/engine/render/scrollrt.cpp

@ -1332,7 +1332,7 @@ void DrawMain(int dwHgt, bool drawDesc, bool drawHp, bool drawMana, bool drawSba
// When chat input is displayed, the belt is hidden and the chat moves up. // When chat input is displayed, the belt is hidden and the chat moves up.
DoBlitScreen({ mainPanelPosition + Displacement { 171, 6 }, { 298, 116 } }); DoBlitScreen({ mainPanelPosition + Displacement { 171, 6 }, { 298, 116 } });
} else { } else {
DoBlitScreen({ mainPanelPosition + InfoBoxTopLeft, InfoBoxSize }); DoBlitScreen({ mainPanelPosition + Displacement { InfoBoxRect.position.x, InfoBoxRect.position.y }, { InfoBoxRect.size } });
} }
} }
if (drawMana) { if (drawMana) {

2
Source/panels/mainpanel.cpp

@ -48,7 +48,7 @@ void DrawButtonOnPanel(Point position, std::string_view text, int frame)
void RenderMainButton(const Surface &out, int buttonId, std::string_view text, int frame) void RenderMainButton(const Surface &out, int buttonId, std::string_view text, int frame)
{ {
Point panelPosition { PanBtnPos[buttonId].x + 4, PanBtnPos[buttonId].y + 17 }; Point panelPosition { PanelButtonRect[buttonId].position + Displacement { 4, 17 } };
DrawButtonOnPanel(panelPosition, text, frame); DrawButtonOnPanel(panelPosition, text, frame);
if (IsChatAvailable()) if (IsChatAvailable())
DrawButtonOnPanel(panelPosition + Displacement { 0, GetMainPanel().size.height + 16 }, text, frame); DrawButtonOnPanel(panelPosition + Displacement { 0, GetMainPanel().size.height + 16 }, text, frame);

4
Source/player.h

@ -689,7 +689,7 @@ public:
// Maximum achievable HP is approximately 1200. Diablo uses fixed point integers where the last 6 bits are // Maximum achievable HP is approximately 1200. Diablo uses fixed point integers where the last 6 bits are
// fractional values. This means that we will never overflow HP values normally by doing this multiplication // fractional values. This means that we will never overflow HP values normally by doing this multiplication
// as the max value is representable in 17 bits and the multiplication result will be at most 23 bits // as the max value is representable in 17 bits and the multiplication result will be at most 23 bits
_pHPPer = std::clamp(_pHitPoints * 80 / _pMaxHP, 0, 80); // hp should never be greater than maxHP but just in case _pHPPer = std::clamp(_pHitPoints * 81 / _pMaxHP, 0, 81); // hp should never be greater than maxHP but just in case
} }
return _pHPPer; return _pHPPer;
@ -700,7 +700,7 @@ public:
if (_pMaxMana <= 0) { if (_pMaxMana <= 0) {
_pManaPer = 0; _pManaPer = 0;
} else { } else {
_pManaPer = std::clamp(_pMana * 80 / _pMaxMana, 0, 80); _pManaPer = std::clamp(_pMana * 81 / _pMaxMana, 0, 81);
} }
return _pManaPer; return _pManaPer;

Loading…
Cancel
Save