diff options
Diffstat (limited to 'src/gui/statuswindow.cpp')
-rw-r--r-- | src/gui/statuswindow.cpp | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp new file mode 100644 index 000000000..349893bfa --- /dev/null +++ b/src/gui/statuswindow.cpp @@ -0,0 +1,880 @@ +/* + * The Mana Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * + * This file is part of The Mana Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/statuswindow.h" + +#include "configuration.h" +#include "event.h" +#include "localplayer.h" +#include "playerinfo.h" +#include "units.h" +#include "viewport.h" + +#include "gui/setup.h" +#include "gui/theme.h" + +#include "gui/widgets/button.h" +#include "gui/widgets/label.h" +#include "gui/widgets/layouthelper.h" +#include "gui/widgets/progressbar.h" +#include "gui/widgets/scrollarea.h" +#include "gui/widgets/vertcontainer.h" +#include "gui/widgets/windowcontainer.h" + +#include "net/net.h" +#include "net/playerhandler.h" +#include "net/gamehandler.h" + +#include "utils/gettext.h" +#include "utils/mathutils.h" +#include "utils/stringutils.h" + +class AttrDisplay : public Container +{ + public: + enum Type + { + DERIVED = 0, + CHANGEABLE, + UNKNOWN + }; + + ~AttrDisplay(); + + virtual std::string update(); + + virtual Type getType() + { return UNKNOWN; } + + protected: + AttrDisplay(int id, const std::string &name); + + const int mId; + const std::string mName; + + LayoutHelper *mLayout; + Label *mLabel; + Label *mValue; +}; + +class DerDisplay : public AttrDisplay +{ + public: + DerDisplay(int id, const std::string &name); + + virtual Type getType() + { return DERIVED; } +}; + +class ChangeDisplay : public AttrDisplay, gcn::ActionListener +{ + public: + ChangeDisplay(int id, const std::string &name); + + std::string update(); + + virtual Type getType() + { return CHANGEABLE; } + + void setPointsNeeded(int needed); + + private: + void action(const gcn::ActionEvent &event); + + int mNeeded; + + Label *mPoints; + Button *mDec; + Button *mInc; +}; + +StatusWindow::StatusWindow(): + Window(player_node ? player_node->getName() : "?") +{ + listen(CHANNEL_ATTRIBUTES); + + setWindowName("Status"); + setupWindow->registerWindowForReset(this); + setResizable(true); + setCloseButton(true); + setSaveVisible(true); + setDefaultSize((windowContainer->getWidth() - 365) / 2, + (windowContainer->getHeight() - 255) / 2, 365, 275); + + // ---------------------- + // Status Part + // ---------------------- + + mLvlLabel = new Label(strprintf(_("Level: %d"), 0)); + mMoneyLabel = new Label(strprintf(_("Money: %s"), "")); + + int max = PlayerInfo::getAttribute(MAX_HP); + if (!max) + max = 1; + + mHpLabel = new Label(_("HP:")); + mHpBar = new ProgressBar(max ? + static_cast<float>(PlayerInfo::getAttribute(HP)) + / static_cast<float>(max): + static_cast<float>(0), 80, 15, Theme::PROG_HP); + + max = PlayerInfo::getAttribute(EXP_NEEDED); + mXpLabel = new Label(_("Exp:")); + mXpBar = new ProgressBar(max ? + static_cast<float>(PlayerInfo::getAttribute(EXP)) + / static_cast<float>(max): + static_cast<float>(0), 80, 15, Theme::PROG_EXP); + + bool magicBar = Net::getGameHandler()->canUseMagicBar(); + + int job = Net::getPlayerHandler()->getJobLocation() + && serverConfig.getValueBool("showJob", false); + + if (magicBar) + { + max = PlayerInfo::getAttribute(MAX_MP); + mMpLabel = new Label(_("MP:")); + mMpBar = new ProgressBar(max ? + static_cast<float>(PlayerInfo::getAttribute(MAX_MP)) + / static_cast<float>(max) : static_cast<float>(0), + 80, 15, Net::getPlayerHandler()->canUseMagic() ? + Theme::PROG_MP : Theme::PROG_NO_MP); + } + else + { + mMpLabel = 0; + mMpBar = 0; + } + + place(0, 0, mLvlLabel, 3); + // 5, 0 Job Level + place(8, 0, mMoneyLabel, 3); + place(0, 1, mHpLabel).setPadding(3); + place(1, 1, mHpBar, 4); + place(5, 1, mXpLabel).setPadding(3); + place(6, 1, mXpBar, 5); + if (magicBar) + { + place(0, 2, mMpLabel).setPadding(3); + // 5, 2 and 6, 2 Job Progress Bar + if (job) + place(1, 2, mMpBar, 4); + else + place(1, 2, mMpBar, 10); + } + + if (job) + { + mJobLvlLabel = new Label(strprintf(_("Job: %d"), 0)); + mJobLabel = new Label(_("Job:")); + mJobBar = new ProgressBar(0.0f, 80, 15, Theme::PROG_JOB); + + place(5, 0, mJobLvlLabel, 3); + place(5, 2, mJobLabel).setPadding(3); + place(6, 2, mJobBar, 5); + } + else + { + mJobLvlLabel = 0; + mJobLabel = 0; + mJobBar = 0; + } + + // ---------------------- + // Stats Part + // ---------------------- + + mAttrCont = new VertContainer(32); + mAttrScroll = new ScrollArea(mAttrCont); + mAttrScroll->setOpaque(false); + mAttrScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); + mAttrScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO); + place(0, 3, mAttrScroll, 5, 3); + + mDAttrCont = new VertContainer(32); + mDAttrScroll = new ScrollArea(mDAttrCont); + mDAttrScroll->setOpaque(false); + mDAttrScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); + mDAttrScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO); + place(6, 3, mDAttrScroll, 5, 3); + + getLayout().setRowHeight(3, Layout::AUTO_SET); + + mCharacterPointsLabel = new Label("C"); + place(0, 6, mCharacterPointsLabel, 5); + + if (Net::getPlayerHandler()->canCorrectAttributes()) + { + mCorrectionPointsLabel = new Label("C"); + place(0, 7, mCorrectionPointsLabel, 5); + } + + loadWindowState(); + + // Update bars + updateHPBar(mHpBar, true); + if (magicBar) + updateMPBar(mMpBar, true); + updateXPBar(mXpBar, false); + + mMoneyLabel->setCaption(strprintf(_("Money: %s"), + Units::formatCurrency(PlayerInfo::getAttribute(MONEY)).c_str())); + mMoneyLabel->adjustSize(); + mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"), + PlayerInfo::getAttribute(CHAR_POINTS))); + mCharacterPointsLabel->adjustSize(); + + if (player_node && player_node->isGM()) + { + mLvlLabel->setCaption(strprintf(_("Level: %d (GM %d)"), + PlayerInfo::getAttribute(LEVEL), player_node->getGMLevel())); + } + else + { + mLvlLabel->setCaption(strprintf(_("Level: %d"), + PlayerInfo::getAttribute(LEVEL))); + } + mLvlLabel->adjustSize(); +} + +void StatusWindow::event(Channels channel _UNUSED_, + const Mana::Event &event) +{ + if (event.getName() == EVENT_UPDATEATTRIBUTE) + { + switch(event.getInt("id")) + { + case HP: case MAX_HP: + updateHPBar(mHpBar, true); + break; + + case MP: case MAX_MP: + updateMPBar(mMpBar, true); + break; + + case EXP: case EXP_NEEDED: + updateXPBar(mXpBar, false); + break; + + case MONEY: + mMoneyLabel->setCaption(strprintf(_("Money: %s"), + Units::formatCurrency(event.getInt("newValue")).c_str())); + mMoneyLabel->adjustSize(); + break; + + case CHAR_POINTS: + mCharacterPointsLabel->setCaption(strprintf( + _("Character points: %d"), event.getInt("newValue"))); + + mCharacterPointsLabel->adjustSize(); + // Update all attributes + for (Attrs::iterator it = mAttrs.begin(); + it != mAttrs.end(); it++) + { + if (it->second) + it->second->update(); + } + break; + + case CORR_POINTS: + mCorrectionPointsLabel->setCaption(strprintf( + _("Correction points: %d"), event.getInt("newValue"))); + mCorrectionPointsLabel->adjustSize(); + // Update all attributes + for (Attrs::iterator it = mAttrs.begin(); + it != mAttrs.end(); it++) + { + if (it->second) + it->second->update(); + } + break; + + case LEVEL: + mLvlLabel->setCaption(strprintf(_("Level: %d"), + event.getInt("newValue"))); + mLvlLabel->adjustSize(); + break; + + default: + break; + } + } + else if (event.getName() == EVENT_UPDATESTAT) + { + int id = event.getInt("id"); + if (id == Net::getPlayerHandler()->getJobLocation()) + { + if (mJobLvlLabel) + { + mJobLvlLabel->setCaption(strprintf(_("Job: %d"), + PlayerInfo::getStatBase(id))); + mJobLvlLabel->adjustSize(); + + updateProgressBar(mJobBar, id, false); + } + } + else + { + updateMPBar(mMpBar, true); + Attrs::iterator it = mAttrs.find(id); + if (it != mAttrs.end() && it->second) + { + if (it->second) + it->second->update(); + } + } + } +} + +void StatusWindow::setPointsNeeded(int id, int needed) +{ + Attrs::iterator it = mAttrs.find(id); + + if (it != mAttrs.end()) + { + AttrDisplay *disp = it->second; + if (disp && disp->getType() == AttrDisplay::CHANGEABLE) + static_cast<ChangeDisplay*>(disp)->setPointsNeeded(needed); + } +} + +void StatusWindow::addAttribute(int id, const std::string &name, + bool modifiable, + const std::string &description _UNUSED_) +{ + AttrDisplay *disp; + + if (modifiable) + { + disp = new ChangeDisplay(id, name); + mAttrCont->add(disp); + } + else + { + disp = new DerDisplay(id, name); + mDAttrCont->add(disp); + } + + mAttrs[id] = disp; +} + +void StatusWindow::updateHPBar(ProgressBar *bar, bool showMax) +{ + if (!bar) + return; + + if (showMax) + bar->setText(toString(PlayerInfo::getAttribute(HP)) + + "/" + toString(PlayerInfo::getAttribute(MAX_HP))); + else + bar->setText(toString(PlayerInfo::getAttribute(HP))); + + float prog = 1.0; + + if (PlayerInfo::getAttribute(MAX_HP) > 0) + { + prog = static_cast<float>(PlayerInfo::getAttribute(HP)) + / static_cast<float>(PlayerInfo::getAttribute(MAX_HP)); + } + bar->setProgress(prog); +} + +void StatusWindow::updateMPBar(ProgressBar *bar, bool showMax) +{ + if (!bar) + return; + + if (showMax) + { + bar->setText(toString(PlayerInfo::getAttribute(MP)) + + "/" + toString(PlayerInfo::getAttribute(MAX_MP))); + } + else + { + bar->setText(toString(PlayerInfo::getAttribute(MP))); + } + + float prog = 1.0f; + + if (PlayerInfo::getAttribute(MAX_MP) > 0) + { + if (PlayerInfo::getAttribute(MAX_MP)) + { + prog = static_cast<float>(PlayerInfo::getAttribute(MP)) + / static_cast<float>(PlayerInfo::getAttribute(MAX_MP)); + } + else + { + prog = static_cast<float>(PlayerInfo::getAttribute(MP)); + } + } + + if (Net::getPlayerHandler()->canUseMagic()) + bar->setProgressPalette(Theme::PROG_MP); + else + bar->setProgressPalette(Theme::PROG_NO_MP); + + bar->setProgress(prog); +} + +void StatusWindow::updateProgressBar(ProgressBar *bar, int value, int max, + bool percent) +{ + if (!bar) + return; + + if (max == 0) + { + bar->setText(_("Max")); + bar->setProgress(1.0); + } + else + { + float progress = static_cast<float>(value) + / static_cast<float>(max); + + if (percent) + bar->setText(strprintf("%2.5f", 100 * progress) + "%"); + else + bar->setText(toString(value) + "/" + toString(max)); + + bar->setProgress(progress); + } +} + +void StatusWindow::updateXPBar(ProgressBar *bar, bool percent) +{ + if (!bar) + return; + + updateProgressBar(bar, PlayerInfo::getAttribute(EXP), + PlayerInfo::getAttribute(EXP_NEEDED), percent); +} + +void StatusWindow::updateProgressBar(ProgressBar *bar, int id, bool percent) +{ + std::pair<int, int> exp = PlayerInfo::getStatExperience(id); + updateProgressBar(bar, exp.first, exp.second, percent); +} + +void StatusWindow::updateStatusBar(ProgressBar *bar, bool percent _UNUSED_) +{ + if (!player_node || !viewport) + return; + + std::string str; + + switch (player_node->getInvertDirection()) + { + case 0: + str = "D"; + break; + case 1: + str = "I"; + break; + case 2: + str = "c"; + break; + case 3: + str = "C"; + break; + case 4: + str = "d"; + break; + default: + str = "?"; + break; + } + + if (player_node->getCrazyMoveType() < 10) + str += toString(player_node->getCrazyMoveType()); + else + { + switch (player_node->getCrazyMoveType()) + { + case 10: + str += "a"; + break; + default: + str += "?"; + break; + } + } + + switch (player_node->getMoveToTargetType()) + { + case 0: + str += "0"; + break; + case 1: + str += "1"; + break; + case 2: + str += "2"; + break; + case 3: + str += "3"; + break; + case 4: + str += "5"; + break; + case 5: + str += "7"; + break; + case 6: + str += "A"; + break; + default: + str += "?"; + break; + } + + switch (player_node->getFollowMode()) + { + case 0: + str += "D"; + break; + case 1: + str += "R"; + break; + case 2: + str += "M"; + break; + case 3: + str += "P"; + break; + default: + str += "?"; + break; + } + + str += " "; + switch (player_node->getAttackWeaponType()) + { + case 1: + str += "D"; + break; + case 2: + str += "s"; + break; + case 3: + str += "S"; + break; + default: + str += "?"; + break; + } + + switch (player_node->getAttackType()) + { + case 0: + str += "D"; + break; + case 1: + str += "G"; + break; + case 2: + str += "A"; + break; + case 3: + str += "d"; + break; + default: + str += "?"; + break; + } + + switch (player_node->getMagicAttackType()) + { + case 0: + str += "f"; + break; + case 1: + str += "c"; + break; + case 2: + str += "I"; + break; + case 3: + str += "F"; + break; + case 4: + str += "U"; + break; + default: + str += "?"; + break; + } + + str += " " + toString(player_node->getQuickDropCounter()); + + switch (player_node->getPickUpType()) + { + case 0: + str += "S"; + break; + case 1: + str += "D"; + break; + case 2: + str += "F"; + break; + case 3: + str += "3"; + break; + case 4: + str += "g"; + break; + case 5: + str += "G"; + break; + case 6: + str += "A"; + break; + default: + str += "?"; + break; + } + + switch (viewport->getDebugPath()) + { + case 0: + str += " N"; + break; + case 1: + str += " D"; + break; + case 2: + str += " u"; + break; + case 3: + str += " U"; + break; + case 4: + str += " e"; + break; + case 5: + str += " b"; + break; + default: + str += " ?"; + break; + } + + switch (player_node->getImitationMode()) + { + case 0: + str += " D"; + break; + case 1: + str += " O"; + break; + default: + str += " ?"; + break; + } + + switch (viewport->getCameraMode()) + { + case 0: + str += "G"; + break; + case 1: + str += "F"; + break; + case 2: + str += "D"; + break; + default: + str += "?"; + break; + } + + switch (player_node->getAwayMode()) + { + case 0: + str += "O"; + break; + case 1: + str += "A"; + break; + default: + str += "?"; + break; + } + + bar->setText(str); + bar->setProgress(50); + if (player_node->getDisableGameModifiers()) + { + gcn::Color col; + col.r = 100; + col.g = 100; + col.b = 100; +// bar->setColor(new gcn::Color(100, 100, 100)); + bar->setColor(col); + } + else + { + gcn::Color col; + col.r = 255; + col.g = 255; + col.b = 0; +// bar->setColor(new gcn::Color(255, 255, 0)); + bar->setColor(col); + } +} + +AttrDisplay::AttrDisplay(int id, const std::string &name): + mId(id), + mName(name) +{ + setSize(100, 32); + mLabel = new Label(name); + mValue = new Label("1 "); + + mLabel->setAlignment(Graphics::CENTER); + mValue->setAlignment(Graphics::CENTER); + + mLayout = new LayoutHelper(this); +} + +AttrDisplay::~AttrDisplay() +{ + delete mLayout; +} + +std::string AttrDisplay::update() +{ + int base = PlayerInfo::getStatBase(mId); + int bonus = PlayerInfo::getStatMod(mId); + std::string value = toString(base + bonus); + if (bonus) + value += strprintf("=%d%+d", base, bonus); + mValue->setCaption(value); + return mName; +} + +DerDisplay::DerDisplay(int id, const std::string &name): + AttrDisplay(id, name) +{ + // Do the layout + LayoutHelper h(this); + ContainerPlacer place = mLayout->getPlacer(0, 0); + + place(0, 0, mLabel, 3); + place(3, 0, mValue, 2); + + update(); +} + +ChangeDisplay::ChangeDisplay(int id, const std::string &name): + AttrDisplay(id, name), mNeeded(1) +{ + mPoints = new Label(_("Max")); + mInc = new Button(_("+"), "inc", this); + + // Do the layout + ContainerPlacer place = mLayout->getPlacer(0, 0); + + place(0, 0, mLabel, 3); + place(4, 0, mValue, 2); + place(6, 0, mInc); + place(7, 0, mPoints); + + if (Net::getPlayerHandler()->canCorrectAttributes()) + { + mDec = new Button(_("-"), "dec", this); + mDec->setWidth(mInc->getWidth()); + + place(3, 0, mDec); + } + else + { + mDec = 0; + } + + update(); +} + +std::string ChangeDisplay::update() +{ + if (mNeeded > 0) + mPoints->setCaption(toString(mNeeded)); + else + mPoints->setCaption(_("Max")); + + if (mDec) + mDec->setEnabled(PlayerInfo::getAttribute(CORR_POINTS)); + + mInc->setEnabled(PlayerInfo::getAttribute(CHAR_POINTS) >= mNeeded && + mNeeded > 0); + + return AttrDisplay::update(); +} + +void ChangeDisplay::setPointsNeeded(int needed) +{ + mNeeded = needed; + + update(); +} + +void ChangeDisplay::action(const gcn::ActionEvent &event) +{ + if (Net::getPlayerHandler()->canCorrectAttributes() && + event.getSource() == mDec) + { + int newcorpoints = PlayerInfo::getAttribute(CORR_POINTS) - 1; + PlayerInfo::setAttribute(CORR_POINTS, newcorpoints); + + int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) + 1; + PlayerInfo::setAttribute(CHAR_POINTS, newpoints); + + int newbase = PlayerInfo::getStatBase(mId) - 1; + PlayerInfo::setStatBase(mId, newbase); + + Net::getPlayerHandler()->decreaseAttribute(mId); + } + else if (event.getSource() == mInc) + { + int cnt = 1; + if (config.getBoolValue("quickStats")) + { + cnt = mInc->getClickCount(); + if (cnt > 10) + cnt = 10; + } + + int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) - cnt; + PlayerInfo::setAttribute(CHAR_POINTS, newpoints); + + int newbase = PlayerInfo::getStatBase(mId) + cnt; + PlayerInfo::setStatBase(mId, newbase); + + for (unsigned f = 0; f < mInc->getClickCount(); f ++) + { + Net::getPlayerHandler()->increaseAttribute(mId); + if (cnt != 1) + SDL_Delay(100); + } + } +} |