summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2009-02-15 11:29:40 +0000
committerJared Adams <jaxad0127@gmail.com>2009-02-15 11:29:40 +0000
commit79e803232438d41cce80467a97e9efde8e6c0c70 (patch)
treef8fd399a13913ccbc6942f6385f9852426f9ebf1
parent0a106989bd16c48525f01cb8515809e74f37a8d8 (diff)
downloadmana-client-79e803232438d41cce80467a97e9efde8e6c0c70.tar.gz
mana-client-79e803232438d41cce80467a97e9efde8e6c0c70.tar.bz2
mana-client-79e803232438d41cce80467a97e9efde8e6c0c70.tar.xz
mana-client-79e803232438d41cce80467a97e9efde8e6c0c70.zip
Add configurable units system
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gui/buy.cpp8
-rw-r--r--src/gui/char_select.cpp22
-rw-r--r--src/gui/char_select.h2
-rw-r--r--src/gui/chat.cpp2
-rw-r--r--src/gui/inventorywindow.cpp18
-rw-r--r--src/gui/inventorywindow.h3
-rw-r--r--src/gui/itempopup.cpp6
-rw-r--r--src/gui/sell.cpp11
-rw-r--r--src/gui/status.cpp15
-rw-r--r--src/gui/status.h2
-rw-r--r--src/gui/trade.cpp8
-rw-r--r--src/main.cpp3
-rw-r--r--src/net/playerhandler.cpp5
-rw-r--r--src/shopitem.cpp5
-rw-r--r--src/units.cpp233
-rw-r--r--src/units.h46
17 files changed, 353 insertions, 38 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 65b60c8c..2777f38b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -342,6 +342,8 @@ tmw_SOURCES = gui/widgets/dropdown.cpp \
textparticle.cpp \
textparticle.h \
tileset.h \
+ units.cpp \
+ units.h \
vector.cpp \
vector.h
diff --git a/src/gui/buy.cpp b/src/gui/buy.cpp
index 0c8c4d9d..23bf89f5 100644
--- a/src/gui/buy.cpp
+++ b/src/gui/buy.cpp
@@ -31,6 +31,7 @@
#include "widgets/layout.h"
#include "../npc.h"
+#include "../units.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
@@ -54,7 +55,8 @@ BuyDialog::BuyDialog(Network *network):
mScrollArea = new ScrollArea(mShopItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
- mMoneyLabel = new gcn::Label(strprintf(_("Price: %d GP / Total: %d GP"), 0, 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("Price: %s / Total: %s"),
+ "", ""));
mIncreaseButton = new Button("+", "+", this);
mDecreaseButton = new Button("-", "-", this);
mBuyButton = new Button(_("Buy"), "buy", this);
@@ -235,5 +237,7 @@ void BuyDialog::updateButtonsAndLabels()
// Update quantity and money labels
mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems));
mMoneyLabel->setCaption
- (strprintf(_("Price: %d GP / Total: %d GP"), price, mMoney - price));
+ (strprintf(_("Price: %s / Total: %s"),
+ Units::formatCurrency(price).c_str(),
+ Units::formatCurrency(mMoney - price).c_str()));
}
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index 8de4f5a7..34174275 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -37,6 +37,7 @@
#include "../game.h"
#include "../localplayer.h"
#include "../main.h"
+#include "../units.h"
#include "../net/charserverhandler.h"
#include "../net/messageout.h"
@@ -85,6 +86,9 @@ CharSelectDialog::CharSelectDialog(Network *network,
Window(_("Select Character")), mNetwork(network),
mCharInfo(charInfo), mGender(gender), mCharSelected(false)
{
+ LocalPlayer *pi = mCharInfo->getEntry();
+ if (pi)
+ mMoney = Units::formatCurrency(pi->mGp);
// Control that shows the Player
mPlayerBox = new PlayerBox;
mPlayerBox->setWidth(74);
@@ -92,7 +96,7 @@ CharSelectDialog::CharSelectDialog(Network *network,
mNameLabel = new gcn::Label(strprintf(_("Name: %s"), ""));
mLevelLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
mJobLevelLabel = new gcn::Label(strprintf(_("Job Level: %d"), 0));
- mMoneyLabel = new gcn::Label(strprintf(_("Money: %d"), 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("Money: %s"), mMoney.c_str()));
const std::string tempString = getFont()->getWidth(_("New")) <
getFont()->getWidth(_("Delete")) ?
@@ -163,10 +167,16 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
else if (event.getId() == "previous")
{
mCharInfo->prev();
+ LocalPlayer *pi = mCharInfo->getEntry();
+ if (pi)
+ mMoney = Units::formatCurrency(pi->mGp);
}
else if (event.getId() == "next")
{
mCharInfo->next();
+ LocalPlayer *pi = mCharInfo->getEntry();
+ if (pi)
+ mMoney = Units::formatCurrency(pi->mGp);
}
}
@@ -176,10 +186,12 @@ void CharSelectDialog::updatePlayerInfo()
if (pi)
{
- mNameLabel->setCaption(strprintf(_("Name: %s"), pi->getName().c_str()));
+ mNameLabel->setCaption(strprintf(_("Name: %s"),
+ pi->getName().c_str()));
mLevelLabel->setCaption(strprintf(_("Level: %d"), pi->mLevel));
- mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), pi->mJobLevel));
- mMoneyLabel->setCaption(strprintf(_("Gold: %d"), pi->mGp));
+ mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"),
+ pi->mJobLevel));
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"), mMoney.c_str()));
if (!mCharSelected)
{
mNewDelCharButton->setCaption(_("Delete"));
@@ -191,7 +203,7 @@ void CharSelectDialog::updatePlayerInfo()
mNameLabel->setCaption(strprintf(_("Name: %s"), ""));
mLevelLabel->setCaption(strprintf(_("Level: %d"), 0));
mJobLevelLabel->setCaption(strprintf(_("Job Level: %d"), 0));
- mMoneyLabel->setCaption(strprintf(_("Money: %d"), 0));
+ mMoneyLabel->setCaption(strprintf(_("Money: %s"), 0));
mNewDelCharButton->setCaption(_("New"));
mSelectButton->setEnabled(false);
}
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 23de061d..28091a18 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -71,7 +71,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener
gcn::Label *mNameLabel;
gcn::Label *mLevelLabel;
gcn::Label *mJobLevelLabel;
- gcn::Label *mMoneyLabel;
+ gcn::Label *mMoneyLabel; std::string mMoney;
PlayerBox *mPlayerBox;
diff --git a/src/gui/chat.cpp b/src/gui/chat.cpp
index 484426dd..21e4f106 100644
--- a/src/gui/chat.cpp
+++ b/src/gui/chat.cpp
@@ -667,7 +667,7 @@ std::string ChatWindow::const_msg(CHATSKILL act)
msg += _("You cannot do that right now!");
break;
case RFAIL_ZENY:
- msg += _("Seems you need more GP... ;-)");
+ msg += _("Seems you need more money... ;-)");
break;
case RFAIL_WEAPON:
msg += _("You cannot use this skill with that kind of weapon!");
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index af3b29a2..6debf473 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -38,6 +38,7 @@
#include "../inventory.h"
#include "../item.h"
+#include "../units.h"
#include "../resources/iteminfo.h"
@@ -76,8 +77,8 @@ InventoryWindow::InventoryWindow(int invSize):
mInvenScroll = new ScrollArea(mItems);
mInvenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- mTotalWeight = toString(player_node->mTotalWeight);
- mMaxWeight = toString(player_node->mMaxWeight);
+ mTotalWeight = -1;
+ mMaxWeight = -1;
mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
mSlotsLabel = new gcn::Label(_("Slots: "));
@@ -124,12 +125,12 @@ void InventoryWindow::logic()
// redesign of InventoryWindow and ItemContainer probably.
updateButtons();
- if ((mMaxWeight != toString(player_node->mMaxWeight)) ||
- mTotalWeight != toString(player_node->mTotalWeight) ||
+ if (mMaxWeight != player_node->mMaxWeight ||
+ mTotalWeight != player_node->mTotalWeight ||
mUsedSlots != toString(player_node->getInventory()->getNumberOfSlotsUsed()))
{
- mTotalWeight = toString(player_node->mTotalWeight);
- mMaxWeight = toString(player_node->mMaxWeight);
+ mTotalWeight = player_node->mTotalWeight;
+ mMaxWeight = player_node->mMaxWeight;
mUsedSlots = toString(player_node->getInventory()->getNumberOfSlotsUsed());
// Weight Bar coloration
@@ -154,8 +155,9 @@ void InventoryWindow::logic()
player_node->mMaxWeight);
mSlotsBar->setText(strprintf("%s/%d", mUsedSlots.c_str(), mMaxSlots));
- mWeightBar->setText(strprintf("%sg/%sg", mTotalWeight.c_str(),
- mMaxWeight.c_str()));
+ mWeightBar->setText(strprintf("%s/%s",
+ Units::formatWeight(mTotalWeight).c_str(),
+ Units::formatWeight(mMaxWeight).c_str()));
}
}
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 78d30461..6c66b95e 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -78,8 +78,7 @@ class InventoryWindow : public Window, gcn::ActionListener,
std::string mWeight;
std::string mSlots;
std::string mUsedSlots;
- std::string mTotalWeight;
- std::string mMaxWeight;
+ int mTotalWeight, mMaxWeight;
gcn::Button *mUseButton, *mDropButton;
gcn::ScrollArea *mInvenScroll;
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 008a41d9..ee28435b 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -32,6 +32,8 @@
#include "widgets/layout.h"
+#include "../units.h"
+
#include "../resources/iteminfo.h"
#include "../utils/gettext.h"
@@ -108,8 +110,8 @@ void ItemPopup::setItem(const ItemInfo &item)
mItemName->setWidth(boldFont->getWidth(item.getName()));
mItemDesc->setTextWrapped(item.getDescription(), 196);
mItemEffect->setTextWrapped(item.getEffect(), 196);
- mItemWeight->setTextWrapped(_("Weight: ") + toString(item.getWeight()) +
- _(" grams"), 196);
+ mItemWeight->setTextWrapped(_("Weight: ") +
+ Units::formatWeight(item.getWeight()), 196);
int minWidth = mItemName->getWidth();
diff --git a/src/gui/sell.cpp b/src/gui/sell.cpp
index e4be7921..a46f3ce6 100644
--- a/src/gui/sell.cpp
+++ b/src/gui/sell.cpp
@@ -31,6 +31,7 @@
#include "widgets/layout.h"
#include "../npc.h"
+#include "../units.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
@@ -55,8 +56,8 @@ SellDialog::SellDialog(Network *network):
mScrollArea = new ScrollArea(mShopItemList);
mSlider = new Slider(1.0);
mQuantityLabel = new gcn::Label("0");
- mMoneyLabel = new gcn::Label(
- strprintf(_("Price: %d GP / Total: %d GP"), 0, 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("Price: %s / Total: %s"),
+ "", ""));
mIncreaseButton = new Button("+", "+", this);
mDecreaseButton = new Button("-", "-", this);
mSellButton = new Button(_("Sell"), "sell", this);
@@ -249,7 +250,7 @@ void SellDialog::updateButtonsAndLabels()
// Update the quantity and money labels
mQuantityLabel->setCaption(strprintf("%d / %d", mAmountItems, mMaxItems));
- mMoneyLabel->setCaption
- (strprintf(_("Price: %d GP / Total: %d GP"),
- income, mPlayerMoney + income));
+ mMoneyLabel->setCaption(strprintf(_("Price: %s / Total: %s"),
+ Units::formatCurrency(income).c_str(),
+ Units::formatCurrency(mPlayerMoney - income).c_str()));
}
diff --git a/src/gui/status.cpp b/src/gui/status.cpp
index 683a9a41..cb02a57a 100644
--- a/src/gui/status.cpp
+++ b/src/gui/status.cpp
@@ -29,6 +29,7 @@
#include "widgets/layout.h"
#include "../localplayer.h"
+#include "../units.h"
#include "../utils/gettext.h"
#include "../utils/strprintf.h"
@@ -36,7 +37,9 @@
StatusWindow::StatusWindow(LocalPlayer *player):
Window(player->getName()),
- mPlayer(player)
+ mPlayer(player),
+ currency(-1),
+ currencyS("?")
{
setWindowName(_("Status"));
setCloseButton(true);
@@ -49,7 +52,7 @@ StatusWindow::StatusWindow(LocalPlayer *player):
mLvlLabel = new gcn::Label(strprintf(_("Level: %d"), 0));
mJobLvlLabel = new gcn::Label(strprintf(_("Job: %d"), 0));
- mGpLabel = new gcn::Label(strprintf(_("Money: %d GP"), 0));
+ mGpLabel = new gcn::Label(strprintf(_("Money: %s"), ""));
mHpLabel = new gcn::Label(_("HP:"));
mHpBar = new ProgressBar(1.0f, 80, 15, 0, 171, 34);
@@ -171,8 +174,12 @@ void StatusWindow::update()
mJobLvlLabel->setCaption(strprintf(_("Job: %d"), mPlayer->mJobLevel));
mJobLvlLabel->adjustSize();
- mGpLabel->setCaption(strprintf(_("Money: %d GP"), mPlayer->mGp));
- mGpLabel->adjustSize();
+ if (currency != mPlayer->mGp) {
+ currency = mPlayer->mGp;
+ currencyS = strprintf(_("Money: %s"), Units::formatCurrency(currency).c_str());
+ mGpLabel->setCaption(currencyS);
+ mGpLabel->adjustSize();
+ }
mHpBar->setText(toString(mPlayer->mHp) +
"/" + toString(mPlayer->mMaxHp));
diff --git a/src/gui/status.h b/src/gui/status.h
index 00a48f4e..7545d696 100644
--- a/src/gui/status.h
+++ b/src/gui/status.h
@@ -64,7 +64,7 @@ class StatusWindow : public Window, public gcn::ActionListener
* Status Part
*/
gcn::Label *mLvlLabel, *mJobLvlLabel;
- gcn::Label *mGpLabel;
+ gcn::Label *mGpLabel; int currency; std::string currencyS;
gcn::Label *mHpLabel, *mMpLabel, *mXpLabel, *mJobLabel;
ProgressBar *mHpBar, *mMpBar;
ProgressBar *mXpBar, *mJobBar;
diff --git a/src/gui/trade.cpp b/src/gui/trade.cpp
index af30d1fe..9c11afd4 100644
--- a/src/gui/trade.cpp
+++ b/src/gui/trade.cpp
@@ -37,6 +37,7 @@
#include "../inventory.h"
#include "../item.h"
#include "../localplayer.h"
+#include "../units.h"
#include "../net/messageout.h"
#include "../net/protocol.h"
@@ -77,7 +78,7 @@ TradeWindow::TradeWindow(Network *network):
mPartnerScroll = new ScrollArea(mPartnerItemContainer);
- mMoneyLabel = new gcn::Label(strprintf(_("You get %d GP."), 0));
+ mMoneyLabel = new gcn::Label(strprintf(_("You get %s."), ""));
mMoneyLabel2 = new gcn::Label(_("You give:"));
mMoneyField = new TextField;
mMoneyField->setWidth(50);
@@ -119,7 +120,8 @@ void TradeWindow::widgetResized(const gcn::Event &event)
void TradeWindow::addMoney(int amount)
{
- mMoneyLabel->setCaption(strprintf(_("You get %d GP."), amount));
+ mMoneyLabel->setCaption(strprintf(_("You get %s."),
+ Units::formatCurrency(amount).c_str()));
mMoneyLabel->adjustSize();
}
@@ -169,7 +171,7 @@ void TradeWindow::reset()
mOkButton->setEnabled(true);
mOkOther = false;
mOkMe = false;
- mMoneyLabel->setCaption(strprintf(_("You get %d GP."), 0));
+ mMoneyLabel->setCaption(strprintf(_("You get %s."), ""));
mMoneyField->setEnabled(true);
mMoneyField->setText("");
}
diff --git a/src/main.cpp b/src/main.cpp
index a9cf5abf..a368ae5c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -51,6 +51,7 @@
#include "player_relations.h"
#include "serverinfo.h"
#include "sound.h"
+#include "units.h"
#include "gui/button.h"
#include "gui/char_server.h"
@@ -897,6 +898,8 @@ int main(int argc, char *argv[])
login_wallpaper->decRef();
login_wallpaper = ResourceManager::getInstance()->
getImage(wallpaperName);
+ // Load units
+ Units::loadUnits();
break;
// Those states don't cause a network disconnect
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index cfdfbe63..e142dd91 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -27,6 +27,7 @@
#include "../localplayer.h"
#include "../log.h"
#include "../npc.h"
+#include "../units.h"
#include "../gui/buy.h"
#include "../gui/chat.h"
@@ -281,8 +282,8 @@ void PlayerHandler::handleMessage(MessageIn *msg)
player_node->mGp = msg->readInt32();
if (player_node->mGp > curGp)
chatWindow->chatLog(_("You picked up ") +
- toString(player_node->mGp - curGp) + " GP",
- BY_SERVER);
+ Units::formatCurrency(player_node->mGp
+ - curGp), BY_SERVER);
}
break;
case 0x0016:
diff --git a/src/shopitem.cpp b/src/shopitem.cpp
index 3b90dfdd..6547aaf1 100644
--- a/src/shopitem.cpp
+++ b/src/shopitem.cpp
@@ -21,11 +21,12 @@
#include "shopitem.h"
-#include "utils/tostring.h"
+#include "units.h"
ShopItem::ShopItem(int id, int quantity, int price):
Item(id, quantity),
mPrice(price)
{
- mDisplayName = getInfo().getName() + " (" + toString(mPrice) + " GP)";
+ mDisplayName = getInfo().getName() +
+ " (" + Units::formatCurrency(mPrice).c_str() + ")";
}
diff --git a/src/units.cpp b/src/units.cpp
new file mode 100644
index 00000000..8fa11c9f
--- /dev/null
+++ b/src/units.cpp
@@ -0,0 +1,233 @@
+/*
+ * Support for custom units
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "units.h"
+
+#include <cmath>
+#include <climits>
+#include <vector>
+
+#include "log.h"
+
+#include "utils/strprintf.h"
+#include "utils/tostring.h"
+#include "utils/trim.h"
+#include "utils/xml.h"
+
+struct UnitLevel {
+ std::string symbol;
+ int count;
+ int round;
+};
+
+struct UnitDescription {
+ std::vector<struct UnitLevel> levels;
+ double conversion;
+ bool mix;
+};
+
+enum UnitType {
+ UNIT_WEIGHT = 0,
+ UNIT_CURRENCY = 1,
+ UNIT_END
+};
+
+struct UnitDescription units[UNIT_END];
+
+void Units::loadUnits()
+{
+ int level;
+ std::string type;
+ XML::Document doc("units.xml");
+ xmlNodePtr root = doc.rootNode();
+
+ { // Setup default weight
+ struct UnitDescription ud;
+
+ ud.conversion = 1.0;
+ ud.mix = false;
+
+ struct UnitLevel bu;
+ bu.symbol = "g";
+ bu.count = 1;
+ bu.round = 0;
+
+ ud.levels.push_back(bu);
+
+ struct UnitLevel ul;
+ ul.symbol = "kg";
+ ul.count = 1000;
+ ul.round = 2;
+
+ ud.levels.push_back(ul);
+
+ units[UNIT_WEIGHT] = ud;
+ }
+
+ { // Setup default currency
+ struct UnitDescription ud;
+
+ ud.conversion = 1.0;
+ ud.mix = false;
+
+ struct UnitLevel bu;
+ bu.symbol = "¤";
+ bu.count = 1;
+ bu.round = 0;
+
+ ud.levels.push_back(bu);
+
+ units[UNIT_CURRENCY] = ud;
+ }
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "units"))
+ {
+ logger->log("Error loading unit definition file: units.xml");
+ return;
+ }
+
+ for_each_xml_child_node(node, root)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "unit"))
+ {
+ struct UnitDescription ud;
+ level = 1;
+ type = XML::getProperty(node, "type", "");
+ ud.conversion = XML::getProperty(node, "conversion", 1.0);
+ ud.mix = XML::getProperty(node, "mix", "no") == "yes";
+
+ struct UnitLevel bu;
+ bu.symbol = XML::getProperty(node, "base", "¤");
+ bu.count = 1;
+ bu.round = XML::getProperty(node, "round", 2);
+
+ ud.levels.push_back(bu);
+
+ for_each_xml_child_node(uLevel, node)
+ {
+ if (xmlStrEqual(uLevel->name, BAD_CAST "level"))
+ {
+ struct UnitLevel ul;
+ ul.symbol = XML::getProperty(uLevel, "symbol",
+ strprintf("¤%d",level));
+ ul.count = XML::getProperty(uLevel, "count", -1);
+ ul.round = XML::getProperty(uLevel, "round", bu.round);
+
+ if (ul.count > 0)
+ {
+ ud.levels.push_back(ul);
+ level++;
+ }
+ else
+ {
+ logger->log("Error bad unit count: %d for %s in %s",
+ ul.count, ul.symbol.c_str(), bu.symbol.c_str());
+ }
+ }
+ }
+
+ // Add one more level for saftey
+ struct UnitLevel ll;
+ ll.symbol = "";
+ ll.count = INT_MAX;
+ ll.round = 0;
+
+ ud.levels.push_back(ll);
+
+ if (type == "weight") units[UNIT_WEIGHT] = ud;
+ else if (type =="currency") units[UNIT_CURRENCY] = ud;
+ else logger->log("Error unknown unit type: %s", type.c_str());
+ }
+ }
+}
+
+std::string formatUnit(const int value, const int type)
+{
+ struct UnitDescription ud = units[type];
+ struct UnitLevel ul;
+ double amount = ud.conversion * value;
+
+ // Shortcut for 0
+ if (value == 0) {
+ ul = ud.levels[0];
+ return strprintf("0%s", ul.symbol.c_str());
+ } else {
+ // If only the first level is needed, act like mix if false
+ if (ud.mix && ud.levels.size() > 0 && ud.levels[1].count < amount)
+ {
+ std::string output;
+ struct UnitLevel pl = ud.levels[0];
+ ul = ud.levels[1];
+ int levelAmount = (int) amount;
+ int nextAmount;
+
+ levelAmount /= ul.count;
+
+ amount -= levelAmount * ul.count;
+
+ if (amount > 0) {
+ output = strprintf("%.*f%s", pl.round, amount,
+ pl.symbol.c_str());
+ }
+
+ for (int i = 2; i < ud.levels.size(); i++)
+ {
+ pl = ul;
+ ul = ud.levels[i];
+
+ nextAmount = levelAmount / ul.count;
+ levelAmount %= ul.count;
+
+ if (levelAmount > 0) output = strprintf("%d%s",
+ levelAmount, pl.symbol.c_str()) + output;
+
+ if (!nextAmount) break;
+ levelAmount = nextAmount;
+ }
+
+ return output;
+ }
+ else
+ {
+ for (int i = 0; i < ud.levels.size(); i++)
+ {
+ ul = ud.levels[i];
+ if (amount < ul.count && ul.count > 0) {
+ ul = ud.levels[i - 1];
+ break;
+ }
+ amount /= ul.count;
+ }
+
+ return strprintf("%.*f%s", ul.round, amount, ul.symbol.c_str());
+ }
+ }
+}
+
+std::string Units::formatCurrency(const int value)
+{
+ return formatUnit(value, UNIT_CURRENCY);
+}
+
+std::string Units::formatWeight(const int value)
+{
+ return formatUnit(value, UNIT_WEIGHT);
+}
diff --git a/src/units.h b/src/units.h
new file mode 100644
index 00000000..67e027de
--- /dev/null
+++ b/src/units.h
@@ -0,0 +1,46 @@
+/*
+ * Support for custom units
+ * Copyright (C) 2009 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef UNITS_H
+#define UNITS_H
+
+#include <string>
+
+class Units
+{
+ public:
+ /**
+ * Loads and parses the units.xml file (if found).
+ */
+ static void loadUnits();
+
+ /**
+ * Formats the given number in the correct currency format.
+ */
+ static std::string formatCurrency(const int value);
+
+ /**
+ * Formats the given number in the correct weight/mass format.
+ */
+ static std::string formatWeight(const int value);
+};
+
+#endif // UNITS_H