/* * The Mana World * Copyright (C) 2004 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 #include "button.h" #include "listbox.h" #include "scrollarea.h" #include "skill.h" #include "table.h" #include "windowcontainer.h" #include "widgets/layout.h" #include "../localplayer.h" #include "../log.h" #include "../utils/dtor.h" #include "../utils/gettext.h" #include "../utils/strprintf.h" #include "../utils/xml.h" static const char *SKILLS_FILE = _("skills.xml"); struct SkillInfo { std::string name; bool modifiable; }; static const SkillInfo fakeSkillInfo = { _("Mystery Skill"), false }; std::vector skill_db; static void initSkillinfo(); class SkillGuiTableModel : public StaticTableModel { public: SkillGuiTableModel(SkillDialog *dialog) : StaticTableModel(0, 3) { mEntriesNr = 0; mDialog = dialog; update(); } virtual int getRows(void) { return mEntriesNr; } virtual int getColumnWidth(int index) { if (index == 0) return 160; return 35; } virtual int getRowHeight() { return 12; } virtual void update() { mEntriesNr = mDialog->getSkills().size(); resize(); for (int i = 0; i < mEntriesNr; i++) { SKILL *skill = mDialog->getSkills()[i]; SkillInfo const *info; char tmp[128]; if (skill->id >= 0 && (unsigned int) skill->id < skill_db.size()) info = &skill_db[skill->id]; else info = &fakeSkillInfo; sprintf(tmp, "%c%s", info->modifiable? ' ' : '*', info->name.c_str()); gcn::Label *name_label = new gcn::Label(tmp); sprintf(tmp, "Lv:%i", skill->lv); gcn::Label *lv_label = new gcn::Label(tmp); sprintf(tmp, "Sp:%i", skill->sp); gcn::Label *sp_label = new gcn::Label(tmp); set(i, 0, name_label); set(i, 1, lv_label); set(i, 2, sp_label); } } private: SkillDialog *mDialog; int mEntriesNr; }; SkillDialog::SkillDialog(): Window(_("Skills")) { initSkillinfo(); mTableModel = new SkillGuiTableModel(this); mTable = new GuiTable(mTableModel); mTable->setOpaque(false); mTable->setLinewiseSelection(true); mTable->setWrappingEnabled(true); mTable->setActionEventId("skill"); mTable->addActionListener(this); setWindowName(_("Skills")); setCloseButton(true); setDefaultSize(windowContainer->getWidth() - 260, 25, 255, 260); setMinHeight(50 + mTableModel->getHeight()); setMinWidth(200); ScrollArea *skillScrollArea = new ScrollArea(mTable); mPointsLabel = new gcn::Label(strprintf(_("Skill points: %d"), 0)); mIncButton = new Button(_("Up"), _("inc"), this); mUseButton = new Button(_("Use"), _("use"), this); mUseButton->setEnabled(false); skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); place(0, 0, skillScrollArea, 5).setPadding(3); place(0, 1, mPointsLabel, 2); place(3, 2, mIncButton); place(4, 2, mUseButton); Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); setLocationRelativeTo(getParent()); loadWindowState(); } SkillDialog::~SkillDialog() { delete mTable; } void SkillDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "inc") { // Increment skill int selectedSkill = mTable->getSelectedRow(); if (selectedSkill >= 0) player_node->raiseSkill(mSkillList[selectedSkill]->id); } else if (event.getId() == "skill" && mTable->getSelectedRow() > -1) { SKILL *skill = mSkillList[mTable->getSelectedRow()]; SkillInfo const *info; if (skill->id >= 0 && (unsigned int) skill->id < skill_db.size()) info = &skill_db[skill->id]; else info = &fakeSkillInfo; mIncButton->setEnabled(player_node->mSkillPoint > 0 && info->modifiable); } else if (event.getId() == "close") setVisible(false); } void SkillDialog::update() { mPointsLabel->setCaption(strprintf(_("Skill points: %d"), player_node->mSkillPoint)); int selectedSkill = mTable->getSelectedRow(); if (selectedSkill >= 0) { int skillId = mSkillList[selectedSkill]->id; bool modifiable; if (skillId >= 0 && (unsigned int) skillId < skill_db.size()) modifiable = skill_db[skillId].modifiable; else modifiable = false; mIncButton->setEnabled(modifiable && player_node->mSkillPoint > 0); } else mIncButton->setEnabled(false); mTableModel->update(); setMinHeight(50 + mTableModel->getHeight()); } int SkillDialog::getNumberOfElements() { return mSkillList.size(); } bool SkillDialog::hasSkill(int id) { for (unsigned int i = 0; i < mSkillList.size(); i++) { if (mSkillList[i]->id == id) return true; } return false; } void SkillDialog::addSkill(int id, int lvl, int mp) { SKILL *tmp = new SKILL; tmp->id = id; tmp->lv = lvl; tmp->sp = mp; mSkillList.push_back(tmp); } void SkillDialog::setSkill(int id, int lvl, int mp) { for (unsigned int i = 0; i < mSkillList.size(); i++) { if (mSkillList[i]->id == id) { mSkillList[i]->lv = lvl; mSkillList[i]->sp = mp; } } } void SkillDialog::cleanList() { delete_all(mSkillList); mSkillList.clear(); } static void initSkillinfo() { SkillInfo emptySkillInfo = { "", false }; XML::Document doc(SKILLS_FILE); xmlNodePtr root = doc.rootNode(); if (!root || !xmlStrEqual(root->name, BAD_CAST "skills")) { logger->log("Error loading skills file: %s", SKILLS_FILE); skill_db.resize(2, emptySkillInfo); skill_db[1].name = "Basic"; skill_db[1].modifiable = true; return; } for_each_xml_child_node(node, root) { if (xmlStrEqual(node->name, BAD_CAST "skill")) { int index = atoi(XML::getProperty(node, "id", "-1").c_str()); std::string name = XML::getProperty(node, "name", ""); bool modifiable = !atoi(XML::getProperty(node, "fixed", "0").c_str()); if (index >= 0) { skill_db.resize(index + 1, emptySkillInfo); skill_db[index].name = name; skill_db[index].modifiable = modifiable; } } } }