summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog24
-rw-r--r--src/gui/skill.cpp174
-rw-r--r--src/gui/skill.h12
-rw-r--r--src/gui/table.cpp11
-rw-r--r--src/gui/table_model.cpp10
-rw-r--r--src/gui/table_model.h11
-rw-r--r--src/main.cpp3
-rw-r--r--src/net/beinghandler.cpp19
-rw-r--r--src/net/network.h4
-rw-r--r--src/net/skillhandler.cpp1
10 files changed, 202 insertions, 67 deletions
diff --git a/ChangeLog b/ChangeLog
index 71b9986a..181a1de6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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: