/*
* The Mana World
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
*
* The Mana World 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.
*
* The Mana World 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 The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#include "status.h"
#include <guichan/widgets/label.hpp>
#include <sstream>
#include "button.h"
#include "progressbar.h"
#include "../playerinfo.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
#include "../graphics.h"
extern Graphics *graphics;
StatusWindow::StatusWindow():
Window(player_info->name)
{
setWindowName("Status");
setResizable(true);
setDefaultSize((graphics->getWidth() - 365) / 2,
(graphics->getHeight() - 255) / 2, 365, 255);
loadWindowState();
// ----------------------
// Status Part
// ----------------------
lvlLabel = new gcn::Label("Level:");
gpLabel = new gcn::Label("Money:");
hpLabel = new gcn::Label("HP:");
hpValueLabel = new gcn::Label("");
mpLabel = new gcn::Label("MP:");
mpValueLabel = new gcn::Label("");
xpLabel = new gcn::Label("Exp:");
xpValueLabel = new gcn::Label("");
jobXpLabel = new gcn::Label("Job:");
jobValueLabel = new gcn::Label("");
lvlLabel->setPosition(5, 3);
gpLabel->setPosition(lvlLabel->getX() + lvlLabel->getWidth() + 40, 3);
hpLabel->setPosition(5, lvlLabel->getY() + lvlLabel->getHeight() + 5);
hpBar = new ProgressBar(1.0f,
hpLabel->getX() + hpLabel->getWidth() + 5, hpLabel->getY(), 80,
15, 0, 171, 34);
hpValueLabel->setPosition(hpBar->getX() + hpBar->getWidth() + 5, hpBar->getY());
mpLabel->setPosition(5,hpLabel->getY() + hpLabel->getHeight() + 5);
mpBar = new ProgressBar(1.0f, hpBar->getX(),
mpLabel->getY(), 80, 15, 26, 102, 230);
mpValueLabel->setPosition(hpValueLabel->getX(), mpBar->getY());
xpLabel->setPosition(175, hpLabel->getY());
xpBar = new ProgressBar(1.0f, 205, xpLabel->getY(), 80, 15,
143, 192, 211);
xpValueLabel->setPosition(290, xpBar->getY());
jobXpLabel->setPosition(175, mpLabel->getY());
jobXpBar = new ProgressBar(1.0f, 225, jobXpLabel->getY(), 60, 15,
220, 135, 203);
jobValueLabel->setPosition(290, jobXpBar->getY());
add(lvlLabel);
add(gpLabel);
add(hpLabel);
add(hpValueLabel);
add(mpLabel);
add(mpValueLabel);
add(xpLabel);
add(xpValueLabel);
add(jobXpLabel);
add(jobValueLabel);
add(hpBar);
add(mpBar);
add(xpBar);
add(jobXpBar);
// ----------------------
// Stats Part
// ----------------------
// Static Labels
statsTitleLabel = new gcn::Label("Stats");
statsTotalLabel = new gcn::Label("Total");
statsCostLabel = new gcn::Label("Cost");
// Derived Stats
statsAttackLabel = new gcn::Label("Attack:");
statsDefenseLabel= new gcn::Label("Defense:");
statsMagicAttackLabel = new gcn::Label("M.Attack:");
statsMagicDefenseLabel = new gcn::Label("M.Defense:");
statsAccuracyLabel = new gcn::Label("% Accuracy:");
statsEvadeLabel = new gcn::Label("% Evade:");
statsReflexLabel = new gcn::Label("% Reflex:");
statsAttackPoints = new gcn::Label("");
statsDefensePoints = new gcn::Label("");
statsMagicAttackPoints = new gcn::Label("");
statsMagicDefensePoints = new gcn::Label("");
statsAccuracyPoints = new gcn::Label("% Accuracy:");
statsEvadePoints = new gcn::Label("% Evade:");
statsReflexPoints = new gcn::Label("% Reflex:");
// New labels
for (int i = 0; i < 6; i++) {
statsLabel[i] = new gcn::Label();
statsDisplayLabel[i] = new gcn::Label();
pointsLabel[i] = new gcn::Label("0");
}
remainingStatsPointsLabel = new gcn::Label();
// New buttons
for (int i = 0; i < 6; i++) {
statsButton[i] = new Button("+");
}
// Set button events Id
statsButton[0]->setEventId("STR");
statsButton[1]->setEventId("AGI");
statsButton[2]->setEventId("VIT");
statsButton[3]->setEventId("INT");
statsButton[4]->setEventId("DEX");
statsButton[5]->setEventId("LUK");
// Set position
statsTitleLabel->setPosition(mpLabel->getX(), mpLabel->getY() + 23 );
statsTotalLabel->setPosition(110, statsTitleLabel->getY() + 15);
statsCostLabel->setPosition(170, statsTotalLabel->getY());
for (int i = 0; i < 6; i++)
{
statsLabel[i]->setPosition(5, statsTotalLabel->getY() + (i * 23) + 15);
statsDisplayLabel[i]->setPosition(115, statsTotalLabel->getY() + (i * 23) + 15);
statsButton[i]->setPosition(145, statsTotalLabel->getY() + (i * 23) + 10);
pointsLabel[i]->setPosition(175, statsTotalLabel->getY() + (i * 23) + 15);
}
remainingStatsPointsLabel->setPosition(5, pointsLabel[5]->getY() + 25);
statsAttackLabel->setPosition(220, statsLabel[0]->getY());
statsDefenseLabel->setPosition(220, statsLabel[1]->getY());
statsMagicAttackLabel->setPosition(220, statsLabel[2]->getY());
statsMagicDefenseLabel->setPosition(220, statsLabel[3]->getY());
statsAccuracyLabel->setPosition(220, statsLabel[4]->getY());
statsEvadeLabel->setPosition(220, statsLabel[5]->getY());
statsReflexLabel->setPosition(220, remainingStatsPointsLabel->getY());
statsAttackPoints->setPosition(310, statsLabel[0]->getY());
statsDefensePoints->setPosition(310, statsLabel[1]->getY());
statsMagicAttackPoints->setPosition(310, statsLabel[2]->getY());
statsMagicDefensePoints->setPosition(310, statsLabel[3]->getY());
statsAccuracyPoints->setPosition(310, statsLabel[4]->getY());
statsEvadePoints->setPosition(310, statsLabel[5]->getY());
statsReflexPoints->setPosition(310, remainingStatsPointsLabel->getY());
// Assemble
add(statsTitleLabel);
add(statsTotalLabel);
add(statsCostLabel);
for(int i = 0; i < 6; i++)
{
add(statsLabel[i]);
add(statsDisplayLabel[i]);
add(statsButton[i]);
add(pointsLabel[i]);
statsButton[i]->addActionListener(this);
}
add(statsAttackLabel);
add(statsDefenseLabel);
add(statsMagicAttackLabel);
add(statsMagicDefenseLabel);
add(statsAccuracyLabel);
add(statsEvadeLabel);
add(statsReflexLabel);
add(statsAttackPoints);
add(statsDefensePoints);
add(statsMagicAttackPoints);
add(statsMagicDefensePoints);
add(statsAccuracyPoints);
add(statsEvadePoints);
add(statsReflexPoints);
add(remainingStatsPointsLabel);
}
StatusWindow::~StatusWindow()
{
// Status Part
delete lvlLabel;
delete gpLabel;
delete hpLabel;
delete hpValueLabel;
delete mpLabel;
delete mpValueLabel;
delete xpLabel;
delete xpValueLabel;
delete jobXpLabel;
delete jobValueLabel;
delete hpBar;
delete mpBar;
delete xpBar;
delete jobXpBar;
// Stats Part
delete statsTitleLabel;
delete statsTotalLabel;
delete statsCostLabel;
for (int i = 0; i < 6; i++)
{
delete statsLabel[i];
delete pointsLabel[i];
delete statsDisplayLabel[i];
delete statsButton[i];
}
delete statsAttackLabel;
delete statsDefenseLabel;
delete statsMagicAttackLabel;
delete statsMagicDefenseLabel;
delete statsAccuracyLabel;
delete statsEvadeLabel;
delete statsReflexLabel;
delete statsAttackPoints;
delete statsDefensePoints;
delete statsMagicAttackPoints;
delete statsMagicDefensePoints;
delete statsAccuracyPoints;
delete statsEvadePoints;
delete statsReflexPoints;
delete remainingStatsPointsLabel;
}
void StatusWindow::update()
{
std::stringstream updateText;
// Status Part
// -----------
updateText.str("");
updateText << "Level: " << player_info->lvl;
lvlLabel->setCaption(updateText.str());
lvlLabel->adjustSize();
updateText.str("");
updateText << "Money: " << player_info->gp << " GP";
gpLabel->setCaption(updateText.str());
gpLabel->adjustSize();
updateText.str("");
updateText << "Job: " << player_info->jobLvl;
jobXpLabel->setCaption(updateText.str());
jobXpLabel->adjustSize();
updateText.str("");
updateText << player_info->hp << "/" << player_info->maxHp;
hpValueLabel->setCaption(updateText.str());
hpValueLabel->adjustSize();
updateText.str("");
updateText << player_info->mp << "/" << player_info->maxMp;
mpValueLabel->setCaption(updateText.str());
mpValueLabel->adjustSize();
updateText.str("");
updateText << (int)player_info->xp << "/" << (int)player_info->xpForNextLevel;
xpValueLabel->setCaption(updateText.str());
xpValueLabel->adjustSize();
updateText.str("");
updateText << (int)player_info->jobXp << "/" << (int)player_info->jobXpForNextLevel;
jobValueLabel->setCaption(updateText.str());
jobValueLabel->adjustSize();
// HP Bar coloration
if (player_info->hp < int(player_info->maxHp / 3))
{
hpBar->setColor(223, 32, 32); // Red
}
else
{
if (player_info->hp < int((player_info->maxHp / 3) * 2))
{
hpBar->setColor(230, 171, 34); // Orange
}
else
{
hpBar->setColor(0, 171, 34); // Green
}
}
hpBar->setProgress((float)player_info->hp / (float)player_info->maxHp);
// mpBar->setProgress((float)player_info->mp / (float)player_info->maxMp);
xpBar->setProgress(
(float)player_info->xp / (float)player_info->xpForNextLevel);
jobXpBar->setProgress(
(float)player_info->jobXp / (float)player_info->jobXpForNextLevel);
// Stats Part
// ----------
std::stringstream statsStr[6];
std::stringstream figureStr[6];
std::stringstream pointsStr[6];
statsStr[0] << "Strength:";
figureStr[0] << (int)player_info->STR;
statsStr[1] << "Agility:";
figureStr[1] << (int)player_info->AGI;
statsStr[2] << "Vitality:";
figureStr[2] << (int)player_info->VIT;
statsStr[3] << "Intelligence:";
figureStr[3] << (int)player_info->INT;
statsStr[4] << "Dexterity:";
figureStr[4] << (int)player_info->DEX;
statsStr[5] << "Luck:";
figureStr[5] << (int)player_info->LUK;
int statusPoints = player_info->statsPointsToAttribute;
updateText.str("");
updateText << "Remaining Status Points: " << statusPoints;
pointsStr[0] << (int)player_info->STRUp;
pointsStr[1] << (int)player_info->AGIUp;
pointsStr[2] << (int)player_info->VITUp;
pointsStr[3] << (int)player_info->INTUp;
pointsStr[4] << (int)player_info->DEXUp;
pointsStr[5] << (int)player_info->LUKUp;
// Enable buttons for which there are enough status points
statsButton[0]->setEnabled(player_info->STRUp <= statusPoints);
statsButton[1]->setEnabled(player_info->AGIUp <= statusPoints);
statsButton[2]->setEnabled(player_info->VITUp <= statusPoints);
statsButton[3]->setEnabled(player_info->INTUp <= statusPoints);
statsButton[4]->setEnabled(player_info->DEXUp <= statusPoints);
statsButton[5]->setEnabled(player_info->LUKUp <= statusPoints);
// Update labels
for (int i = 0; i < 6; i++) {
statsLabel[i]->setCaption(statsStr[i].str());
statsLabel[i]->adjustSize();
statsDisplayLabel[i]->setCaption(figureStr[i].str());
statsDisplayLabel[i]->adjustSize();
pointsLabel[i]->setCaption(pointsStr[i].str());
pointsLabel[i]->adjustSize();
}
remainingStatsPointsLabel->setCaption(updateText.str());
remainingStatsPointsLabel->adjustSize();
// Derived Stats Points
// Attack TODO: Count equipped Weapons and items attack bonuses
updateText.str("");
updateText << int(player_info->ATK + player_info->ATKBonus);
statsAttackPoints->setCaption(updateText.str());
statsAttackPoints->adjustSize();
// Defense TODO: Count equipped Armors and items defense bonuses
updateText.str("");
updateText << int(player_info->DEF + player_info->DEFBonus);
statsDefensePoints->setCaption(updateText.str());
statsDefensePoints->adjustSize();
// Magic Attack TODO: Count equipped items M.Attack bonuses
updateText.str("");
updateText << int(player_info->MATK + player_info->MATKBonus);
statsMagicAttackPoints->setCaption(updateText.str());
statsMagicAttackPoints->adjustSize();
// Magic Defense TODO: Count equipped items M.Defense bonuses
updateText.str("");
updateText << int(player_info->MDEF + player_info->MDEFBonus);
statsMagicDefensePoints->setCaption(updateText.str());
statsMagicDefensePoints->adjustSize();
// Accuracy %
updateText.str("");
updateText << (int)player_info->HIT;
statsAccuracyPoints->setCaption(updateText.str());
statsAccuracyPoints->adjustSize();
// Evasion %
updateText.str("");
updateText << (int)player_info->FLEE;
statsEvadePoints->setCaption(updateText.str());
statsEvadePoints->adjustSize();
// Reflex %
updateText.str("");
updateText << ((int)player_info->DEX / 4); // + counter
statsReflexPoints->setCaption(updateText.str());
statsReflexPoints->adjustSize();
}
void StatusWindow::draw(gcn::Graphics *graphics)
{
update();
Window::draw(graphics);
}
void StatusWindow::action(const std::string& eventId)
{
// Stats Part
if (eventId.length() == 3)
{
MessageOut outMsg;
outMsg.writeShort(CMSG_STAT_UPDATE_REQUEST);
if (eventId == "STR")
{
outMsg.writeShort(0x000d);
}
if (eventId == "AGI")
{
outMsg.writeShort(0x000e);
}
if (eventId == "VIT")
{
outMsg.writeShort(0x000f);
}
if (eventId == "INT")
{
outMsg.writeShort(0x0010);
}
if (eventId == "DEX")
{
outMsg.writeShort(0x0011);
}
if (eventId == "LUK")
{
outMsg.writeShort(0x0012);
}
outMsg.writeByte(1);
}
}