Mana
Loading...
Searching...
No Matches
statuswindow.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "gui/statuswindow.h"
23
24#include "localplayer.h"
25#include "playerinfo.h"
26#include "units.h"
27
28#include "gui/setup.h"
29
30#include "gui/widgets/button.h"
31#include "gui/widgets/label.h"
32#include "gui/widgets/layout.h"
37
38#include "net/net.h"
39#include "net/playerhandler.h"
40#include "net/gamehandler.h"
41
42#include "net/tmwa/protocol.h"
43
44#include "resources/theme.h"
45
46#include "utils/gettext.h"
47#include "utils/mathutils.h"
48#include "utils/stringutils.h"
49
50class AttrDisplay : public Container
51{
52 public:
56
57 ~AttrDisplay() override;
58
59 virtual std::string update();
60 virtual Type getType() { return UNKNOWN; }
61
62 protected:
63 AttrDisplay(int id, const std::string &name);
64
65 const int mId;
66 const std::string mName;
67
70};
71
72class DerDisplay : public AttrDisplay
73{
74 public:
75 DerDisplay(int id, const std::string &name);
76 Type getType() override { return DERIVED; }
77};
78
79class ChangeDisplay : public AttrDisplay, gcn::ActionListener
80{
81 public:
82 ChangeDisplay(int id, const std::string &name);
83 std::string update() override;
84 Type getType() override { return CHANGEABLE; }
85 void setPointsNeeded(int needed);
86
87 private:
88 void action(const gcn::ActionEvent &event) override;
89
90 int mNeeded = 1;
91
95};
96
98 Window(local_player->getName())
99{
101
102 setWindowName("Status");
104 setResizable(true);
105 setCloseButton(true);
106 setSaveVisible(true);
107 setDefaultSize((windowContainer->getWidth() - 365) / 2,
108 (windowContainer->getHeight() - 255) / 2, 480, 275);
109 setMinWidth(480);
110 setMinHeight(131);
111
112 // ----------------------
113 // Status Part
114 // ----------------------
115
116 mLvlLabel = new Label(strprintf(_("Level: %d"), 0));
117 mMoneyLabel = new Label(strprintf(_("Money: %s"), ""));
118
120 mHpLabel = new Label(_("HP:"));
121 mHpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(HP) / max :
122 0, 80, 15, Theme::PROG_HP);
123
125 mXpLabel = new Label(_("Exp:"));
126 mXpBar = new ProgressBar(max ? (float) PlayerInfo::getAttribute(EXP) / max :
127 0, 80, 15, Theme::PROG_EXP);
128
129 bool magicBar = Net::getGameHandler()->canUseMagicBar();
130 if (magicBar)
131 {
133 mMpLabel = new Label(_("MP:"));
134 mMpBar = new ProgressBar(max ?
135 (float) PlayerInfo::getAttribute(MAX_MP) / max :
136 0, 80, 15, Net::getPlayerHandler()->canUseMagic() ?
138 }
139
140 place(0, 0, mLvlLabel, 3);
141 // 5, 0 Job Level
142 place(8, 0, mMoneyLabel, 3);
143 place(0, 1, mHpLabel).setPadding(3);
144 place(1, 1, mHpBar, 4);
145 place(5, 1, mXpLabel).setPadding(3);
146 place(6, 1, mXpBar, 5);
147
148 int attributesFirstRow = 2;
149 if (magicBar)
150 {
151 place(0, 2, mMpLabel).setPadding(3);
152 // 5, 2 and 6, 2 Job Progress Bar
153 place(1, 2, mMpBar, 4);
154
155 // We move the attribute row to the next one
156 attributesFirstRow = 3;
157 }
158
159 if (Net::getPlayerHandler()->getJobLocation() > 0)
160 {
161 mJobLvlLabel = new Label(strprintf(_("Job: %d"), 0));
162 mJobLabel = new Label(_("Job:"));
163 mJobBar = new ProgressBar(0.0f, 80, 15, Theme::PROG_JOB);
164
165 place(5, 0, mJobLvlLabel, 3);
166 place(5, 2, mJobLabel).setPadding(3);
167 place(6, 2, mJobBar, 5);
168
169 // We move the attribute row to the next one
170 attributesFirstRow = 3;
171 }
172
173 // ----------------------
174 // Stats Part
175 // ----------------------
176
177 mAttrCont = new VertContainer(28);
179 mAttrScroll->setOpaque(false);
180 mAttrScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
181 mAttrScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
182 place(0, attributesFirstRow, mAttrScroll, 5, 3);
183
184 mDAttrCont = new VertContainer(28);
186 mDAttrScroll->setOpaque(false);
187 mDAttrScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
188 mDAttrScroll->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO);
189 place(6, attributesFirstRow, mDAttrScroll, 5, 3);
190
191 getLayout().setRowHeight(attributesFirstRow, Layout::AUTO_SET);
192
193 mCharacterPointsLabel = new Label("Character points: 0");
194 place(0, attributesFirstRow + 3, mCharacterPointsLabel, 4);
195
196 if (Net::getPlayerHandler()->canCorrectAttributes())
197 {
198 mCorrectionPointsLabel = new Label("Correction points: 0");
199 place(4, attributesFirstRow + 3, mCorrectionPointsLabel, 4);
200 }
201
203
204 // Update bars
205 updateHPBar(mHpBar, true);
206 if (magicBar)
207 updateMPBar(mMpBar, true);
208 updateXPBar(mXpBar, false);
209
210
211 mMoneyLabel->setCaption(strprintf(_("Money: %s"),
213 mMoneyLabel->adjustSize();
214 mCharacterPointsLabel->setCaption(strprintf(_("Character points: %d"),
216 mCharacterPointsLabel->adjustSize();
217
218 mLvlLabel->setCaption(strprintf(_("Level: %d"),
220 mLvlLabel->adjustSize();
221}
222
224 const Event &event)
225{
226 if (event.getType() == Event::UpdateAttribute)
227 {
228 switch(event.getInt("id"))
229 {
230 case HP: case MAX_HP:
231 updateHPBar(mHpBar, true);
232 break;
233
234 case MP: case MAX_MP:
235 updateMPBar(mMpBar, true);
236 break;
237
238 case EXP: case EXP_NEEDED:
239 updateXPBar(mXpBar, false);
240 break;
241
242 case MONEY:
243 mMoneyLabel->setCaption(strprintf(_("Money: %s"),
245 event.getInt("newValue")).c_str()));
246 mMoneyLabel->adjustSize();
247 break;
248
249 case CHAR_POINTS:
251 _("Character points: %d"),
252 event.getInt("newValue")));
253 mCharacterPointsLabel->adjustSize();
254 updateAttrs();
255 break;
256
257 case CORR_POINTS:
259 _("Correction points: %d"),
260 event.getInt("newValue")));
261 mCorrectionPointsLabel->adjustSize();
262 updateAttrs();
263 break;
264
265 case LEVEL:
266 mLvlLabel->setCaption(strprintf(_("Level: %d"),
267 event.getInt("newValue")));
268 mLvlLabel->adjustSize();
269 break;
270 }
271 }
272 else if (event.getType() == Event::UpdateStat)
273 {
274 int id = event.getInt("id");
275
276 if (id == Net::getPlayerHandler()->getJobLocation())
277 {
278
279 mJobLvlLabel->setCaption(strprintf(_("Job: %d"),
281 mJobLvlLabel->adjustSize();
282
283 updateProgressBar(mJobBar, id, false);
284 }
285 else
286 {
287 auto it = mAttrs.find(id);
288 if (it != mAttrs.end())
289 {
290 it->second->update();
291 }
292
294 id == TmwAthena::MATK)
295 {
296 updateMPBar(mMpBar, true);
297 }
298 }
299 }
300}
301
303{
304 for (auto &attr : mAttrs)
305 {
306 attr.second->update();
307 }
308}
309
310void StatusWindow::setPointsNeeded(int id, int needed)
311{
312 auto it = mAttrs.find(id);
313
314 if (it != mAttrs.end())
315 {
316 AttrDisplay *disp = it->second;
317 if (disp->getType() == AttrDisplay::CHANGEABLE)
318 static_cast<ChangeDisplay*>(disp)->setPointsNeeded(needed);
319 }
320}
321
322void StatusWindow::addAttribute(int id, const std::string &name,
323 bool modifiable,
324 const std::string &description)
325{
326 AttrDisplay *disp;
327
328 if (modifiable)
329 {
330 disp = new ChangeDisplay(id, name);
331 mAttrCont->add(disp);
332 }
333 else
334 {
335 disp = new DerDisplay(id, name);
336 mDAttrCont->add(disp);
337 }
338
339 mAttrs[id] = disp;
340}
341
343{
344 if (!bar)
345 return;
346
347 if (showMax)
350 else
352
353 float prog = 1.0;
354
356 prog = (float) PlayerInfo::getAttribute(HP)
358 bar->setProgress(prog);
359}
360
362{
363 if (!bar)
364 return;
365
366 if (showMax)
369 else
371
372 float prog = 1.0f;
373
375 prog = (float) PlayerInfo::getAttribute(MP)
377
378 if (Net::getPlayerHandler()->canUseMagic())
380 else
382
383 bar->setProgress(prog);
384}
385
386void StatusWindow::updateProgressBar(ProgressBar *bar, int value, int max,
387 bool percent)
388{
389 if (!bar)
390 return;
391
392 if (max == 0)
393 {
394 bar->setText(_("Max"));
395 bar->setProgress(1.0);
396 }
397 else
398 {
399 float progress = ((float) value) / max;
400
401 if (percent)
402 bar->setText(strprintf("%2.2f", 100 * progress) + "%");
403 else
404 bar->setText(toString(value) + "/" + toString(max));
405
406 bar->setProgress(progress);
407 }
408}
409
411{
412 if (!bar)
413 return;
414
417}
418
419void StatusWindow::updateProgressBar(ProgressBar *bar, int id, bool percent)
420{
421 std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
422 updateProgressBar(bar, exp.first, exp.second, percent);
423}
424
425AttrDisplay::AttrDisplay(int id, const std::string &name):
426 mId(id),
427 mName(name)
428{
429 setSize(100, 32);
430 mLabel = new Label(name);
431 mValue = new Label("1");
432
433 mLabel->setAlignment(Graphics::CENTER);
434 mValue->setAlignment(Graphics::CENTER);
435}
436
440
442{
443 int base = PlayerInfo::getStatBase(mId);
444 int bonus = PlayerInfo::getStatMod(mId);
445 std::string value = toString(base);
446 if (bonus)
447 value += strprintf(" (%+d)", bonus);
448 mValue->setCaption(value);
449
450 return mName;
451}
452
453DerDisplay::DerDisplay(int id, const std::string &name):
454 AttrDisplay(id, name)
455{
456 // Do the layout
457 place(0, 0, mLabel, 3);
458 place(3, 0, mValue, 2);
459
460 update();
461}
462
463ChangeDisplay::ChangeDisplay(int id, const std::string &name):
464 AttrDisplay(id, name)
465{
466 mPoints = new Label(_("Max"));
467 mInc = new Button(_("+"), "inc", this);
468
469 // Do the layout
470 place(0, 0, mLabel, 3);
471 place(4, 0, mValue, 2);
472 place(6, 0, mInc);
473 place(7, 0, mPoints);
474
475 if (Net::getPlayerHandler()->canCorrectAttributes())
476 {
477 mDec = new Button(_("-"), "dec", this);
478 mDec->setWidth(mInc->getWidth());
479
480 place(3, 0, mDec);
481 }
482 else
483 {
484 mDec = nullptr;
485 }
486
487 update();
488}
489
491{
492 if (mNeeded > 0)
493 {
494 mPoints->setCaption(toString(mNeeded));
495 }
496 else
497 {
498 mPoints->setCaption(_("Max"));
499 }
500
501 if (mDec)
502 {
504 }
506 mNeeded > 0);
507
508 return AttrDisplay::update();
509}
510
512{
513 mNeeded = needed;
514
515 update();
516}
517
518void ChangeDisplay::action(const gcn::ActionEvent &event)
519{
520 if (Net::getPlayerHandler()->canCorrectAttributes() &&
521 event.getSource() == mDec)
522 {
523 int newcorpoints = PlayerInfo::getAttribute(CORR_POINTS) - 1;
525
526 int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) + 1;
528
529 int newbase = PlayerInfo::getStatBase(mId) - 1;
531
533 }
534 else if (event.getSource() == mInc)
535 {
536 int newpoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
538
539 int newbase = PlayerInfo::getStatBase(mId) + 1;
541
543 }
544}
virtual std::string update()
const int mId
const std::string mName
AttrDisplay(int id, const std::string &name)
~AttrDisplay() override
virtual Type getType()
Button widget.
Definition button.h:38
ChangeDisplay(int id, const std::string &name)
void setPointsNeeded(int needed)
Type getType() override
void action(const gcn::ActionEvent &event) override
std::string update() override
A widget container.
Definition container.h:41
LayoutCell & place(int x, int y, gcn::Widget *wg, int w=1, int h=1)
Adds a widget to the container and sets it at given cell.
Definition container.cpp:46
Type getType() override
DerDisplay(int id, const std::string &name)
void listen(Event::Channel channel)
Definition event.h:42
@ UpdateAttribute
Definition event.h:99
@ UpdateStat
Definition event.h:100
Channel
Definition event.h:45
@ AttributesChannel
Definition event.h:47
Label widget.
Definition label.h:34
void setRowHeight(int n, int h)
Definition layout.h:221
LayoutCell & setPadding(int p)
Sets the padding around the cell content.
Definition layout.h:179
@ AUTO_SET
Uses the share as the new size.
Definition layout.h:304
virtual bool canUseMagicBar() const =0
Tells whether the protocol is using the MP status bar.
virtual void decreaseAttribute(int attr)=0
virtual void increaseAttribute(int attr)=0
virtual bool canUseMagic()=0
A progress bar.
Definition progressbar.h:34
void setProgress(float progress)
Sets the current progress.
void setText(const std::string &text)
Sets the text shown on the progress bar.
Definition progressbar.h:82
void setProgressPalette(int progressPalette)
Change the ProgressPalette for this ProgressBar to follow or -1 to disable this and manage color manu...
A scroll area.
Definition scrollarea.h:38
void setOpaque(bool opaque)
Sets whether the widget should draw its background or not.
void registerWindowForReset(Window *window)
Enables the Reset Windows button.
Definition setup.cpp:108
static void updateMPBar(ProgressBar *bar, bool showMax=false)
void event(Event::Channel channel, const Event &event) override
std::map< int, AttrDisplay * > mAttrs
gcn::Label * mCorrectionPointsLabel
ScrollArea * mAttrScroll
gcn::Label * mMoneyLabel
void setPointsNeeded(int id, int needed)
gcn::Label * mMpLabel
static void updateHPBar(ProgressBar *bar, bool showMax=false)
gcn::Label * mCharacterPointsLabel
gcn::Label * mXpLabel
static void updateProgressBar(ProgressBar *bar, int value, int max, bool percent)
gcn::Label * mJobLvlLabel
gcn::Label * mLvlLabel
Status Part.
ScrollArea * mDAttrScroll
gcn::Label * mJobLabel
ProgressBar * mMpBar
VertContainer * mAttrCont
gcn::Label * mHpLabel
ProgressBar * mJobBar
ProgressBar * mXpBar
VertContainer * mDAttrCont
ProgressBar * mHpBar
void addAttribute(int id, const std::string &name, bool modifiable, const std::string &description)
static void updateXPBar(ProgressBar *bar, bool percent=true)
@ PROG_HP
Definition theme.h:270
@ PROG_JOB
Definition theme.h:276
@ PROG_EXP
Definition theme.h:273
@ PROG_MP
Definition theme.h:271
@ PROG_NO_MP
Definition theme.h:272
static std::string formatCurrency(int value)
Formats the given number in the correct currency format.
Definition units.cpp:216
A widget container.
void add(gcn::Widget *widget) override
A window.
Definition window.h:59
void setMinHeight(int height)
Sets the minimum height of the window.
Definition window.cpp:197
Layout & getLayout()
Gets the layout handler for this window.
Definition window.cpp:714
void setWindowName(const std::string &name)
Sets the name of the window.
Definition window.h:272
void setResizable(bool resize)
Sets whether or not the window can be resized.
Definition window.cpp:212
void setSaveVisible(bool save)
Sets whether the window will save it's visibility.
Definition window.h:225
LayoutCell & place(int x, int y, gcn::Widget *, int w=1, int h=1)
Adds a widget to the window and sets it at given cell.
Definition window.cpp:737
void setCloseButton(bool flag)
Sets whether or not the window has a close button.
Definition window.cpp:262
void setDefaultSize()
Set the default win pos and size to the current ones.
Definition window.cpp:545
void loadWindowState()
Reads the position (and the size for resizable windows) in the configuration based on the given strin...
Definition window.cpp:467
void setMinWidth(int width)
Sets the minimum width of the window.
Definition window.cpp:192
#define _(s)
Definition gettext.h:38
LocalPlayer * local_player
ServerType getNetworkType()
Definition net.cpp:200
GameHandler * getGameHandler()
Definition net.cpp:75
PlayerHandler * getPlayerHandler()
Definition net.cpp:110
int getStatBase(int id)
Returns the base value of the given stat.
void setStatBase(int id, int value, bool notify)
Changes the base value of the given stat.
void setAttribute(int id, int value, bool notify)
Changes the value of the given attribute.
int getAttribute(int id)
Returns the value of the given attribute.
int getStatMod(int id)
Returns the modifier for the given stat.
std::pair< int, int > getStatExperience(int id)
Returns the experience of the given stat.
@ EXP
Definition playerinfo.h:33
@ HP
Definition playerinfo.h:31
@ CORR_POINTS
Definition playerinfo.h:37
@ MAX_HP
Definition playerinfo.h:31
@ LEVEL
Definition playerinfo.h:30
@ EXP_NEEDED
Definition playerinfo.h:33
@ CHAR_POINTS
Definition playerinfo.h:37
@ MP
Definition playerinfo.h:32
@ MAX_MP
Definition playerinfo.h:32
@ MONEY
Definition playerinfo.h:34
Setup * setupWindow
Definition setup.cpp:120
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
std::string toString(const T &arg)
Converts the given value to a string using std::stringstream.
Definition stringutils.h:68
WindowContainer * windowContainer