summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIra Rice <irarice@gmail.com>2008-11-02 00:33:31 +0000
committerIra Rice <irarice@gmail.com>2008-11-02 00:33:31 +0000
commit5cf18a062ffca03196b83fe6fda8ea3e54079c57 (patch)
tree00fa520012a6ed4a0fee66a1d65364bf81ccaeb5
parent494e35cda96863f676409d304a916d9308040eab (diff)
downloadmana-client-5cf18a062ffca03196b83fe6fda8ea3e54079c57.tar.gz
mana-client-5cf18a062ffca03196b83fe6fda8ea3e54079c57.tar.bz2
mana-client-5cf18a062ffca03196b83fe6fda8ea3e54079c57.tar.xz
mana-client-5cf18a062ffca03196b83fe6fda8ea3e54079c57.zip
Ported a patch from TMW by fate which de-hardcodes skills, as well as removes the server sending out view id's for
gloves and boots (which weren't needed.) Here's the full log: * 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--src/gui/skill.cpp181
-rw-r--r--src/gui/skill.h18
-rw-r--r--src/gui/table.cpp12
-rw-r--r--src/gui/table_model.cpp10
-rw-r--r--src/gui/table_model.h5
-rw-r--r--src/main.cpp3
-rw-r--r--src/net/beinghandler.cpp14
-rw-r--r--src/net/network.h4
-rw-r--r--src/net/skillhandler.cpp1
9 files changed, 184 insertions, 64 deletions
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index 8cf1e06d..32c961bd 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -18,63 +18,119 @@
* 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: skill.cpp 3754 2007-11-20 15:19:50Z b_lindeijer $
+ * $Id$
*/
+#include <algorithm>
+
#include <guichan/widgets/label.hpp>
#include "skill.h"
#include "button.h"
#include "listbox.h"
-#include "scrollarea.h"
#include "windowcontainer.h"
#include "../localplayer.h"
#include "../utils/dtor.h"
+#include "../utils/xml.h"
+#include "log.h"
+
+#define SKILLS_FILE "skills.xml"
-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", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
+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);
+ 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));
@@ -88,7 +144,8 @@ SkillDialog::SkillDialog():
add(mIncButton);
add(mUseButton);
- mSkillListBox->addActionListener(this);
+// mSkillListBox->addActionListener(this);
+ mTable.addActionListener(this);
setLocationRelativeTo(getParent());
loadWindowState();
@@ -96,7 +153,6 @@ SkillDialog::SkillDialog():
SkillDialog::~SkillDialog()
{
- cleanList();
}
void SkillDialog::action(const gcn::ActionEvent &event)
@@ -104,7 +160,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);
@@ -113,7 +169,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")
@@ -130,8 +186,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()
@@ -139,20 +200,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++) {
@@ -184,6 +231,42 @@ void SkillDialog::setSkill(int id, int lvl, int mp)
void SkillDialog::cleanList()
{
- delete_all(mSkillList);
+ 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 6bd6c51b..92badc8a 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -18,7 +18,7 @@
* 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: skill.h 3494 2007-08-20 05:29:12Z joshlangley $
+ * $Id$
*/
#ifndef _TMW_SKILL_H
@@ -26,9 +26,11 @@
#include <vector>
-#include <guichan/listmodel.hpp>
#include <guichan/actionlistener.hpp>
+#include <guichan/listmodel.hpp>
+#include "scrollarea.h"
+#include "table.h"
#include "window.h"
#include "../guichanfwd.h"
@@ -38,13 +40,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 +65,18 @@ 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;
+ ScrollArea *skillScrollArea;
+ 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..8d2ab86a 100644
--- a/src/gui/table.cpp
+++ b/src/gui/table.cpp
@@ -102,11 +102,14 @@ GuiTable::setModel(TableModel *new_model)
mModel->removeListener(this);
}
+
mModel = new_model;
installActionListeners();
- new_model->installListener(this);
- recomputeDimensions();
+ if (new_model) {
+ new_model->installListener(this);
+ recomputeDimensions();
+ }
}
@@ -187,6 +190,9 @@ GuiTable::uninstallActionListeners(void)
void
GuiTable::installActionListeners(void)
{
+ if (!mModel)
+ return;
+
int rows = mModel->getRows();
int columns = mModel->getColumns();
@@ -367,7 +373,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..69e41cd3 100644
--- a/src/gui/table_model.h
+++ b/src/gui/table_model.h
@@ -120,6 +120,11 @@ public:
*/
virtual void fixRowHeight(int height);
+ /**
+ * Resizes the table model
+ */
+ virtual void resize(void);
+
virtual int getRows();
virtual int getColumns();
virtual int getRowHeight();
diff --git a/src/main.cpp b/src/main.cpp
index d41acba0..db7b16d4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -623,7 +623,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 85e18e5a..f19fd39c 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -406,8 +406,8 @@ void BeingHandler::handleMessage(MessageIn *msg)
headTop = msg->readInt16();
headMid = msg->readInt16();
hairColor = msg->readInt16();
- shoes = msg->readInt16();
- gloves = msg->readInt16();
+ msg->readInt16(); // clothes color
+ msg->readInt16(); // head direction
msg->readInt32(); // guild
msg->readInt32(); // emblem
msg->readInt16(); // manner
@@ -450,9 +450,15 @@ void BeingHandler::handleMessage(MessageIn *msg)
if (msg->getId() == SMSG_PLAYER_UPDATE_1)
{
- if (msg->readInt8() == 2)
+ switch (msg->readInt8())
{
- dstBeing->setAction(Being::SIT);
+ 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 53800b1e..826e6776 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 1f9403f4..3685d04b 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: