summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-02-23 16:58:19 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-02-25 18:28:11 +0100
commit228e7a50ce1553b3fe21d16d0c7c642cf025be48 (patch)
treec4f02f7231d8a288a0c5d2c5b080cd87a90053cb /src
parent656d74376b1458cd32c97a217d22b8e0e7e6fea7 (diff)
downloadmana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.tar.gz
mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.tar.bz2
mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.tar.xz
mana-228e7a50ce1553b3fe21d16d0c7c642cf025be48.zip
Added tooltips to status effect icons
Based on the name attributes in the status-effect XML elements. Also cleanup the code a little. Since the MiniStatusWindow now adjust its size to respect the status icons, those icons no longer have to be drawn from the Viewport.
Diffstat (limited to 'src')
-rw-r--r--src/gui/ministatuswindow.cpp186
-rw-r--r--src/gui/ministatuswindow.h24
-rw-r--r--src/gui/viewport.cpp6
-rw-r--r--src/resources/statuseffectdb.cpp2
-rw-r--r--src/statuseffect.h1
5 files changed, 118 insertions, 101 deletions
diff --git a/src/gui/ministatuswindow.cpp b/src/gui/ministatuswindow.cpp
index 4c2a7b1d..4e32848c 100644
--- a/src/gui/ministatuswindow.cpp
+++ b/src/gui/ministatuswindow.cpp
@@ -47,12 +47,15 @@
#include "utils/stringutils.h"
#include "utils/time.h"
-static constexpr int ICON_SPACING = 4;
+#include <algorithm>
+
+static constexpr int ICON_SPACING = 3;
MiniStatusWindow::MiniStatusWindow():
Popup("MiniStatus")
{
setPadding(3);
+ setMinHeight(0);
listen(Event::AttributesChannel);
listen(Event::ActorSpriteChannel);
@@ -87,8 +90,7 @@ MiniStatusWindow::MiniStatusWindow():
add(mMpBar);
add(mXpBar);
- setContentSize(mXpBar->getX() + mXpBar->getWidth(),
- mXpBar->getY() + mXpBar->getHeight());
+ updateSize();
auto stateIt = config.windows.find(getPopupName());
setVisible(stateIt != config.windows.end() ? stateIt->second.visible.value_or(true)
@@ -101,34 +103,21 @@ MiniStatusWindow::MiniStatusWindow():
MiniStatusWindow::~MiniStatusWindow() = default;
-void MiniStatusWindow::setIcon(int index, Sprite *sprite)
-{
- if (index >= (int) mIcons.size())
- mIcons.resize(index + 1);
-
- mIcons[index].reset(sprite);
-}
-
-void MiniStatusWindow::eraseIcon(int index)
-{
- mIcons.erase(mIcons.begin() + index);
-}
-
void MiniStatusWindow::drawIcons(Graphics *graphics)
{
const auto game = Game::instance();
const int tileWidth = game->getCurrentTileWidth();
const int tileHeight = game->getCurrentTileHeight();
- int iconX = mXpBar->getX() + mXpBar->getWidth() + 3 + tileWidth / 2;
- int iconY = 3 + tileHeight;
+ int iconX = mXpBar->getX() + mXpBar->getWidth() + ICON_SPACING + tileWidth / 2;
+ int iconY = ICON_SPACING + tileHeight;
- for (auto &icon : mIcons)
+ for (auto &icon : mStatusIcons)
{
- icon->draw(graphics,
- iconX - icon->getWidth() / 2,
- iconY - icon->getHeight());
- iconX += ICON_SPACING + icon->getWidth();
+ icon.sprite->draw(graphics,
+ iconX - icon.sprite->getWidth() / 2,
+ iconY - icon.sprite->getHeight());
+ iconX += ICON_SPACING + icon.sprite->getWidth();
}
}
@@ -168,48 +157,25 @@ void MiniStatusWindow::event(Event::Channel channel, const Event &event)
const int id = event.getInt("index");
const bool newStatus = event.getBool("newStatus");
- if (auto effect = StatusEffectDB::getStatusEffect(id))
- {
- effect->deliverMessage(newStatus);
- effect->playSfx(newStatus);
-
- Sprite *sprite = newStatus ? effect->getIconSprite() : nullptr;
-
- if (!sprite)
- {
- // delete sprite, if necessary
- for (unsigned int i = 0; i < mStatusEffectIcons.size();)
- if (mStatusEffectIcons[i] == id)
- {
- mStatusEffectIcons.erase(mStatusEffectIcons.begin()
- + i);
- eraseIcon(i);
- }
- else
- i++;
- }
- else
- {
- // replace sprite or append
- bool found = false;
-
- for (unsigned int i = 0; i < mStatusEffectIcons.size();
- i++)
- if (mStatusEffectIcons[i] == id)
- {
- setIcon(i, sprite);
- found = true;
- break;
- }
-
- if (!found)
- { // add new
- int offset = mStatusEffectIcons.size();
- setIcon(offset, sprite);
- mStatusEffectIcons.push_back(id);
- }
- }
- }
+ auto effect = StatusEffectDB::getStatusEffect(id);
+ if (!effect)
+ return;
+
+ effect->deliverMessage(newStatus);
+ effect->playSfx(newStatus);
+
+ Sprite *sprite = newStatus ? effect->getIconSprite() : nullptr;
+ auto it = std::find_if(mStatusIcons.begin(), mStatusIcons.end(),
+ [id](const StatusIcon &icon) {
+ return icon.effectId == id;
+ });
+
+ if (!sprite && it != mStatusIcons.end())
+ mStatusIcons.erase(it);
+ else if (sprite && it == mStatusIcons.end())
+ mStatusIcons.push_back(StatusIcon{id, std::unique_ptr<Sprite>(sprite)});
+
+ updateSize();
}
}
}
@@ -231,42 +197,84 @@ void MiniStatusWindow::logic()
}
*/
- for (auto &icon : mIcons)
- icon->update(Time::deltaTimeMs());
+ for (auto &icon : mStatusIcons)
+ icon.sprite->update(Time::deltaTimeMs());
+}
+
+void MiniStatusWindow::draw(gcn::Graphics *graphics)
+{
+ drawChildren(graphics);
+
+ drawIcons(static_cast<Graphics*>(graphics));
}
void MiniStatusWindow::mouseMoved(gcn::MouseEvent &event)
{
Popup::mouseMoved(event);
- const int x = event.getX();
- const int y = event.getY();
+ std::string tooltip1;
+ std::string tooltip2;
if (event.getSource() == mXpBar)
{
- mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", PlayerInfo::getAttribute(EXP),
- PlayerInfo::getAttribute(EXP_NEEDED)),
- strprintf("%s: %u", _("Need"),
- PlayerInfo::getAttribute(EXP_NEEDED)
- - PlayerInfo::getAttribute(EXP)));
+ const int xp = PlayerInfo::getAttribute(EXP);
+ const int xpNeeded = PlayerInfo::getAttribute(EXP_NEEDED);
+ tooltip1 = strprintf("%u/%u", xp, xpNeeded);
+ tooltip2 = strprintf("%s: %u", _("Need"), xpNeeded - xp);
}
else if (event.getSource() == mHpBar)
{
- mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", PlayerInfo::getAttribute(HP),
- PlayerInfo::getAttribute(MAX_HP)));
+ const int hp = PlayerInfo::getAttribute(HP);
+ const int maxHp = PlayerInfo::getAttribute(MAX_HP);
+ tooltip1 = strprintf("%u/%u", hp, maxHp);
}
else if (event.getSource() == mMpBar)
{
- mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", PlayerInfo::getAttribute(MP),
- PlayerInfo::getAttribute(MAX_MP)));
+ const int mp = PlayerInfo::getAttribute(MP);
+ const int maxMp = PlayerInfo::getAttribute(MAX_MP);
+ tooltip1 = strprintf("%u/%u", mp, maxMp);
}
else
{
+ // Check if the mouse is over one of the status icons
+ const auto game = Game::instance();
+ const int tileWidth = game->getCurrentTileWidth();
+ const int tileHeight = game->getCurrentTileHeight();
+
+ int iconX = mXpBar->getX() + mXpBar->getWidth() + ICON_SPACING + tileWidth / 2;
+ int iconY = ICON_SPACING + tileHeight;
+
+ for (const auto &icon : mStatusIcons)
+ {
+ int spriteX = iconX + icon.sprite->getOffsetX() - icon.sprite->getWidth() / 2;
+ int spriteY = iconY + icon.sprite->getOffsetY() - icon.sprite->getHeight();
+
+ if (event.getX() >= spriteX &&
+ event.getX() < spriteX + icon.sprite->getWidth() &&
+ event.getY() >= spriteY &&
+ event.getY() < spriteY + icon.sprite->getHeight())
+ {
+ auto effect = StatusEffectDB::getStatusEffect(icon.effectId);
+ if (effect)
+ tooltip1 = effect->name;
+ break;
+ }
+
+ iconX += ICON_SPACING + icon.sprite->getWidth();
+ }
+ }
+
+ if (tooltip1.empty())
+ {
mTextPopup->setVisible(false);
}
+ else
+ {
+ mTextPopup->show(event.getX() + getX(),
+ event.getY() + getY(),
+ tooltip1,
+ tooltip2);
+ }
}
void MiniStatusWindow::mouseExited(gcn::MouseEvent &event)
@@ -275,3 +283,19 @@ void MiniStatusWindow::mouseExited(gcn::MouseEvent &event)
mTextPopup->setVisible(false);
}
+
+void MiniStatusWindow::updateSize()
+{
+ int width = mXpBar->getX() + mXpBar->getWidth();
+ int height = mXpBar->getY() + mXpBar->getHeight();
+
+ // Increase width based on the size of the status icons
+ if (!mStatusIcons.empty())
+ {
+ width += ICON_SPACING;
+ for (const auto &icon : mStatusIcons)
+ width += ICON_SPACING + icon.sprite->getWidth();
+ }
+
+ setContentSize(width, height);
+}
diff --git a/src/gui/ministatuswindow.h b/src/gui/ministatuswindow.h
index a92ab63a..21c4b76e 100644
--- a/src/gui/ministatuswindow.h
+++ b/src/gui/ministatuswindow.h
@@ -44,27 +44,18 @@ class MiniStatusWindow : public Popup, public EventListener
MiniStatusWindow();
~MiniStatusWindow() override;
- void drawIcons(Graphics *graphics);
-
void event(Event::Channel channel, const Event &event) override;
void logic() override; // Updates icons
- void draw(gcn::Graphics *graphics) override
- { drawChildren(graphics); }
+ void draw(gcn::Graphics *graphics) override;
void mouseMoved(gcn::MouseEvent &mouseEvent) override;
void mouseExited(gcn::MouseEvent &event) override;
private:
- bool isInBar(ProgressBar *bar, int x, int y) const;
-
- /**
- * Sets one of the icons.
- */
- void setIcon(int index, Sprite *sprite);
-
- void eraseIcon(int index);
+ void drawIcons(Graphics *graphics);
+ void updateSize();
/*
* Mini Status Bars
@@ -74,8 +65,13 @@ class MiniStatusWindow : public Popup, public EventListener
ProgressBar *mXpBar;
TextPopup *mTextPopup;
- std::vector<int> mStatusEffectIcons;
- std::vector<std::unique_ptr<Sprite>> mIcons;
+ struct StatusIcon
+ {
+ int effectId;
+ std::unique_ptr<Sprite> sprite;
+ };
+
+ std::vector<StatusIcon> mStatusIcons;
};
extern MiniStatusWindow *miniStatusWindow;
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index fba08a9a..8f4ee686 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -32,7 +32,6 @@
#include "textmanager.h"
#include "gui/gui.h"
-#include "gui/ministatuswindow.h"
#include "gui/popupmenu.h"
#include "gui/beingpopup.h"
@@ -237,11 +236,6 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
}
}
- // The icons for the MiniStatusWindow are drawn here, otherwise they would
- // be clipped by the window.
- if (miniStatusWindow)
- miniStatusWindow->drawIcons(graphics);
-
// Draw contained widgets
WindowContainer::draw(gcnGraphics);
}
diff --git a/src/resources/statuseffectdb.cpp b/src/resources/statuseffectdb.cpp
index 1bfff5e1..fe179191 100644
--- a/src/resources/statuseffectdb.cpp
+++ b/src/resources/statuseffectdb.cpp
@@ -62,6 +62,8 @@ void StatusEffectDB::readStatusEffectNode(XML::Node node, const std::string &/*
auto &effect = mStatusEffects[id];
+ node.attribute("name", effect.name);
+
node.attribute("start-message", effect.start.message);
node.attribute("start-audio", effect.start.sfx);
node.attribute("start-particle", effect.start.particleEffect);
diff --git a/src/statuseffect.h b/src/statuseffect.h
index fce52603..2ab98d4f 100644
--- a/src/statuseffect.h
+++ b/src/statuseffect.h
@@ -36,6 +36,7 @@ public:
std::string particleEffect;
};
+ std::string name;
Event start;
Event end;
std::string icon;