diff options
author | Fate <fate.tmw@googlemail.com> | 2008-11-01 22:39:26 +0000 |
---|---|---|
committer | Fate <fate.tmw@googlemail.com> | 2008-11-01 22:39:26 +0000 |
commit | 4cfdb3620ccbd0de6bd53c5f22e7b6d3801627bf (patch) | |
tree | 20471d3a652d35a193b6c9873b45eded59bd3e63 | |
parent | 885a9c145464a2b376edfd1c9677b84f6d4a8ce5 (diff) | |
download | mana-client-4cfdb3620ccbd0de6bd53c5f22e7b6d3801627bf.tar.gz mana-client-4cfdb3620ccbd0de6bd53c5f22e7b6d3801627bf.tar.bz2 mana-client-4cfdb3620ccbd0de6bd53c5f22e7b6d3801627bf.tar.xz mana-client-4cfdb3620ccbd0de6bd53c5f22e7b6d3801627bf.zip |
* Updated GUI table and model to better handle NULL widgets during initialisation
* On SMSG_MOVE et al., ignore boots and glove information-- that information is incorrect and we're guaranteed to already have the correct information anyway.
* Properly decode `is dead' information for PCs, so that dead players, when encountered, will be lying on the ground, dead, rather than standing.
* Use `skills.xml' file from client data to determine skill names
* Report client version number (hereby bumped to 1) in unused charserver slot (ignored by vanilla eAthena)
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | src/gui/skill.cpp | 174 | ||||
-rw-r--r-- | src/gui/skill.h | 12 | ||||
-rw-r--r-- | src/gui/table.cpp | 11 | ||||
-rw-r--r-- | src/gui/table_model.cpp | 10 | ||||
-rw-r--r-- | src/gui/table_model.h | 11 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/net/beinghandler.cpp | 19 | ||||
-rw-r--r-- | src/net/network.h | 4 | ||||
-rw-r--r-- | src/net/skillhandler.cpp | 1 |
10 files changed, 202 insertions, 67 deletions
@@ -1,3 +1,27 @@ +2008-11-01 Fate <fate.tmw@googlemail.com> + + * src/gui/skill.cpp (SkillDialog): Display skills using a table + and using an external `skills.xml' file + (SkillDialog::update): No longer segfault when skills beyond 199 + are reported + + * src/gui/table_model.cpp: Several fixes to tables and table + models to better handle `NULL' widgets and `NULL' models during + initialisation. + + * src/main.cpp (charLogin): Send client protocol version to + character server (this is ignored in vanilla eAthena). + + * src/net/network.h (TMW_CLIENT_PROTOCOL_VERSION): Record client + protocol version + + * src/net/beinghandler.cpp (BeingHandler::handleMessage): Properly + decode whether character is dead + (BeingHandler::handleMessage): for SMSG_PLAYER_MOVE et al., ignore + shoe and glove updates-- they are incorrect and not needed (we get + them correctly when the PC is spawned for the client and they are + updated as needed by other packages.) + 2008-10-31 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/gui/gui.cpp: Applied patch by vargavind which adds more special diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 3ab40c9a..c753ee1a 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -35,48 +35,103 @@ #include "../localplayer.h" #include "../utils/dtor.h" +#include "utils/xml.h" +#include "log.h" -const char *skill_db[] = { - // 0-99 - "", "Basic", "Sword", "Two hand", "HP regeneration", "Bash", "Provoke", "Magnum", "Endure", "MP regeneration", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "MAX weight", "Discount", "Overcharge", "", - "Identify", "", "", "", "", "", "", "", "Double", "Miss", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - // 100-199 - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "First aid", "Play as dead", "Moving recovery", "Fatal blow", "Auto berserk", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", "", "", "", +#define SKILLS_FILE "skills.xml" + +struct SkillInfo { + std::string name; + bool modifiable; +}; + +std::vector<SkillInfo> skill_db; + +static void initSkillinfo(void); + +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) + { + switch (index) { + case 0: return 160; + default: return 35; + } + } + + virtual int + getRowHeight(void) + { + return 12; + } + + virtual void + update(void) + { + mEntriesNr = mDialog->getSkills().size(); + resize(); + + for (int i = 0; i < mEntriesNr; i++) { + SKILL *skill = mDialog->getSkills()[i]; + SkillInfo *info = &skill_db[skill->id]; + char tmp[128]; + + sprintf(tmp, "%c%s", info->modifiable? ' ' : '*', info->name.c_str()); + gcn::Label *name_label = new gcn::Label(std::string(tmp)); + + sprintf(tmp, "Lv:%i", skill->lv); + gcn::Label *lv_label = new gcn::Label(std::string(tmp)); + + sprintf(tmp, "Sp:%i", skill->sp); + gcn::Label *sp_label = new gcn::Label(std::string(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.setModel(mTableModel); + mTable.setLinewiseSelection(true); + setWindowName("Skills"); setCloseButton(true); setDefaultSize(windowContainer->getWidth() - 255, 25, 240, 240); - mSkillListBox = new ListBox(this); - ScrollArea *skillScrollArea = new ScrollArea(mSkillListBox); +// mSkillListBox = new ListBox(this); + ScrollArea *skillScrollArea = new ScrollArea(&mTable); mPointsLabel = new gcn::Label("Skill Points:"); mIncButton = new Button("Up", "inc", this); mUseButton = new Button("Use", "use", this); mUseButton->setEnabled(false); - mSkillListBox->setActionEventId("skill"); +// mSkillListBox->setActionEventId("skill"); + mTable.setActionEventId("skill"); skillScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); skillScrollArea->setDimension(gcn::Rectangle(5, 5, 230, 180)); @@ -90,7 +145,8 @@ SkillDialog::SkillDialog(): add(mIncButton); add(mUseButton); - mSkillListBox->addActionListener(this); +// mSkillListBox->addActionListener(this); + mTable.addActionListener(this); setLocationRelativeTo(getParent()); loadWindowState(); @@ -98,7 +154,6 @@ SkillDialog::SkillDialog(): SkillDialog::~SkillDialog() { - cleanList(); } void SkillDialog::action(const gcn::ActionEvent &event) @@ -106,7 +161,7 @@ void SkillDialog::action(const gcn::ActionEvent &event) if (event.getId() == "inc") { // Increment skill - int selectedSkill = mSkillListBox->getSelected(); + int selectedSkill = mTable.getSelectedRow();//mSkillListBox->getSelected(); if (selectedSkill >= 0) { player_node->raiseSkill(mSkillList[selectedSkill]->id); @@ -115,7 +170,7 @@ void SkillDialog::action(const gcn::ActionEvent &event) else if (event.getId() == "skill") { mIncButton->setEnabled( - mSkillListBox->getSelected() > -1 && + mTable.getSelectedRow() > -1 && player_node->mSkillPoint > 0); } else if (event.getId() == "close") @@ -132,8 +187,13 @@ void SkillDialog::update() mPointsLabel->setCaption(tmp); } - mIncButton->setEnabled(mSkillListBox->getSelected() > -1 && - player_node->mSkillPoint > 0); + int selectedSkill = mTable.getSelectedRow(); + + mIncButton->setEnabled(selectedSkill > -1 + && skill_db[mSkillList[selectedSkill]->id].modifiable + && player_node->mSkillPoint > 0); + + mTableModel->update(); } int SkillDialog::getNumberOfElements() @@ -141,20 +201,6 @@ int SkillDialog::getNumberOfElements() return mSkillList.size(); } -std::string SkillDialog::getElementAt(int i) -{ - if (i >= 0 && i < (int)mSkillList.size()) - { - char tmp[128]; - sprintf(tmp, "%s Lv: %i Sp: %i", - skill_db[mSkillList[i]->id], - mSkillList[i]->lv, - mSkillList[i]->sp); - return tmp; - } - return ""; -} - bool SkillDialog::hasSkill(int id) { for (unsigned int i = 0; i < mSkillList.size(); i++) { @@ -189,3 +235,39 @@ void SkillDialog::cleanList() for_each(mSkillList.begin(), mSkillList.end(), make_dtor(mSkillList)); mSkillList.clear(); } + +static void +initSkillinfo(void) +{ + 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: " + 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; + } + } + } +} + diff --git a/src/gui/skill.h b/src/gui/skill.h index 6879640c..66ec35f3 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -30,6 +30,7 @@ #include <guichan/actionlistener.hpp> #include "window.h" +#include "table.h" #include "../guichanfwd.h" @@ -38,13 +39,14 @@ struct SKILL { short lv, sp; }; +class SkillGuiTableModel; + /** * The skill dialog. * * \ingroup Interface */ -class SkillDialog : public Window, public gcn::ActionListener, - public gcn::ListModel +class SkillDialog : public Window, public gcn::ActionListener { public: /** @@ -62,15 +64,17 @@ class SkillDialog : public Window, public gcn::ActionListener, void update(); int getNumberOfElements(); - std::string getElementAt(int); bool hasSkill(int id); void addSkill(int id, int lv, int sp); void setSkill(int id, int lv, int sp); void cleanList(); + const std::vector<SKILL*>& getSkills(void) const { return mSkillList; } + private: - gcn::ListBox *mSkillListBox; + GuiTable mTable;//gcn::ListBox *mSkillListBox; + SkillGuiTableModel *mTableModel; gcn::Label *mPointsLabel; gcn::Button *mIncButton; gcn::Button *mUseButton; diff --git a/src/gui/table.cpp b/src/gui/table.cpp index 89a93825..bddfbfed 100644 --- a/src/gui/table.cpp +++ b/src/gui/table.cpp @@ -105,8 +105,10 @@ GuiTable::setModel(TableModel *new_model) mModel = new_model; installActionListeners(); - new_model->installListener(this); - recomputeDimensions(); + if (new_model) { + new_model->installListener(this); + recomputeDimensions(); + } } @@ -187,6 +189,9 @@ GuiTable::uninstallActionListeners(void) void GuiTable::installActionListeners(void) { + if (!mModel) + return; + int rows = mModel->getRows(); int columns = mModel->getColumns(); @@ -367,7 +372,7 @@ GuiTable::getWidgetAt(int x, int y) if (row > -1 && column > -1) { gcn::Widget *w = mModel->getElementAt(row, column); - if (w->isFocusable()) + if (w && w->isFocusable()) return w; else return NULL; // Grab the event locally diff --git a/src/gui/table_model.cpp b/src/gui/table_model.cpp index 78df0636..57da29d9 100644 --- a/src/gui/table_model.cpp +++ b/src/gui/table_model.cpp @@ -71,10 +71,18 @@ StaticTableModel::~StaticTableModel(void) } void +StaticTableModel::resize(void) +{ + mRows = getRows(); + mColumns = getColumns(); + mTableModel.resize(mRows * mColumns, NULL); +} + +void StaticTableModel::set(int row, int column, gcn::Widget *widget) { if (row >= mRows || row < 0 - || column >= mColumns || row > 0) + || column >= mColumns || column < 0) // raise exn? return; diff --git a/src/gui/table_model.h b/src/gui/table_model.h index 48ef1c0d..4be4e60e 100644 --- a/src/gui/table_model.h +++ b/src/gui/table_model.h @@ -120,9 +120,14 @@ public: */ virtual void fixRowHeight(int height); - virtual int getRows(); - virtual int getColumns(); - virtual int getRowHeight(); + /** + * Resizes the table model + */ + virtual void resize(void); + + virtual int getRows(void); + virtual int getColumns(void); + virtual int getRowHeight(void); virtual int getColumnWidth(int index); virtual gcn::Widget *getElementAt(int row, int column); diff --git a/src/main.cpp b/src/main.cpp index 373dc100..6c9fe45c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -600,7 +600,8 @@ void charLogin(Network *network, LoginData *loginData) outMsg.writeInt32(loginData->account_ID); outMsg.writeInt32(loginData->session_ID1); outMsg.writeInt32(loginData->session_ID2); - outMsg.writeInt16(0); // unknown + // [Fate] The next word is unused by the old char server, so we squeeze in tmw client version information + outMsg.writeInt16(TMW_CLIENT_PROTOCOL_VERSION); outMsg.writeInt8(loginData->sex); // We get 4 useless bytes before the real answer comes in diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index fa2b6728..1f2463b3 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -405,8 +405,8 @@ void BeingHandler::handleMessage(MessageIn *msg) headTop = msg->readInt16(); headMid = msg->readInt16(); hairColor = msg->readInt16(); - shoes = msg->readInt16(); // clothes color - "abused" as shoes - gloves = msg->readInt16(); // head dir - "abused" as gloves + msg->readInt16(); // clothes color - Aethyra-"abused" as shoes, we ignore it + msg->readInt16(); // head dir - Aethyra-"abused" as gloves, we ignore it msg->readInt32(); // guild msg->readInt32(); // emblem msg->readInt16(); // manner @@ -419,10 +419,6 @@ void BeingHandler::handleMessage(MessageIn *msg) dstBeing->setSprite(Being::BOTTOMCLOTHES_SPRITE, headBottom); dstBeing->setSprite(Being::TOPCLOTHES_SPRITE, headMid); dstBeing->setSprite(Being::HAT_SPRITE, headTop); - dstBeing->setSprite(Being::SHOE_SPRITE, shoes); - // Compensation for the unpatched TMW server - if (gloves > 10) - dstBeing->setSprite(Being::GLOVES_SPRITE, gloves); dstBeing->setSprite(Being::CAPE_SPRITE, cape); dstBeing->setSprite(Being::MISC1_SPRITE, misc1); dstBeing->setSprite(Being::MISC2_SPRITE, misc2); @@ -447,9 +443,14 @@ void BeingHandler::handleMessage(MessageIn *msg) if (msg->getId() == SMSG_PLAYER_UPDATE_1) { - if (msg->readInt8() == 2) - { - dstBeing->setAction(Being::SIT); + switch (msg->readInt8()) { + + case 1: dstBeing->setAction(Being::DEAD); + break; + + case 2: dstBeing->setAction(Being::SIT); + break; + } } else if (msg->getId() == SMSG_PLAYER_MOVE) diff --git a/src/net/network.h b/src/net/network.h index d6fec761..0326b6ce 100644 --- a/src/net/network.h +++ b/src/net/network.h @@ -29,6 +29,10 @@ #include <SDL_thread.h> #include <string> +#define TMW_CLIENT_PROTOCOL_VERSION 1 + /**< Protocol version, reported to the eAthena char and mapserver who + can adjust the protocol accordingly */ + class MessageHandler; class MessageIn; diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp index 828c2378..53cfda1a 100644 --- a/src/net/skillhandler.cpp +++ b/src/net/skillhandler.cpp @@ -73,6 +73,7 @@ void SkillHandler::handleMessage(MessageIn *msg) } } } + skillDialog->update(); break; case SMSG_SKILL_FAILED: |