summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/game.cpp12
-rw-r--r--src/gui/char_select.cpp242
-rw-r--r--src/gui/char_select.h16
-rw-r--r--src/gui/ok_dialog.cpp16
-rw-r--r--src/gui/ok_dialog.h13
-rw-r--r--src/gui/playerbox.cpp4
-rw-r--r--src/gui/skill.cpp3
-rw-r--r--src/gui/skill.h2
-rw-r--r--src/gui/window.cpp22
-rw-r--r--src/gui/window.h18
-rw-r--r--src/gui/windowcontainer.cpp49
-rw-r--r--src/gui/windowcontainer.h18
12 files changed, 261 insertions, 154 deletions
diff --git a/src/game.cpp b/src/game.cpp
index 71340f16..4c2e055f 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -421,8 +421,8 @@ void do_parse() {
break;
// Success to walk request
case 0x0087:
- if(walk_status==1) {
- if(RFIFOL(2)>server_tick) {
+ if (walk_status == 1) {
+ if (RFIFOL(2) > server_tick) {
walk_status = 2;
server_tick = RFIFOL(2);
}
@@ -430,7 +430,7 @@ void do_parse() {
break;
// Add new being / stop monster
case 0x0078:
- if(find_node(RFIFOL(2))==NULL) {
+ if (find_node(RFIFOL(2)) == NULL) {
node = new NODE();
node->id = RFIFOL(2);
node->speed = RFIFOW(6);
@@ -445,7 +445,7 @@ void do_parse() {
add_node(node);
}
else {
- if(node) {
+ if (node) {
empty_path(node);
memcpy(node->coordinates, RFIFOP(46), 3);
node->frame = 0;
@@ -457,7 +457,7 @@ void do_parse() {
// Remove a being
case 0x0080:
node = find_node(RFIFOL(2));
- if(node!=NULL) {
+ if (node != NULL) {
if(RFIFOB(6)==1) { // Death
if(node->job>110) {
node->action = MONSTER_DEAD;
@@ -473,7 +473,7 @@ void do_parse() {
case 0x01d8:
case 0x01d9:
node = find_node(RFIFOL(2));
- if(node==NULL) {
+ if (node == NULL) {
node = new NODE();
node->id = RFIFOL(2);
node->job = RFIFOW(14);
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index 1481276d..ebf439b1 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -102,49 +102,139 @@ CharSelectDialog::~CharSelectDialog()
void CharSelectDialog::action(const std::string& eventId)
{
- if (eventId == "ok") {
+ if (eventId == "ok" && n_character > 0) {
// Start game
- state = GAME;
+ serverCharSelect();
+ close_session();
}
else if (eventId == "cancel") {
state = EXIT;
}
else if (eventId == "new") {
- // Create new character
- if (n_character > 0)
- return;
- // Start new character dialog...
- new CharCreateDialog();
+ if (n_character == 0) {
+ // Start new character dialog
+ new CharCreateDialog(this);
+ }
} else if (eventId == "delete") {
// Delete character
- if (n_character <= 0)
- return;
- serverCharDelete();
+ if (n_character > 0) {
+ serverCharDelete();
+ }
}
}
void CharSelectDialog::setPlayerInfo(PLAYER_INFO *pi)
{
- std::stringstream nameCaption, levelCaption, jobCaption, moneyCaption;
-
- nameCaption << pi->name;
- levelCaption << "Lvl: " << pi->lv;
- jobCaption << "Job Lvl: " << pi->job_lv;
- moneyCaption << "Gold: " << pi->gp;
+ if (pi) {
+ std::stringstream nameCaption, levelCaption, jobCaption, moneyCaption;
+
+ nameCaption << pi->name;
+ levelCaption << "Lvl: " << pi->lv;
+ jobCaption << "Job Lvl: " << pi->job_lv;
+ moneyCaption << "Gold: " << pi->gp;
+
+ nameLabel->setCaption(nameCaption.str());
+ levelLabel->setCaption(levelCaption.str());
+ jobLevelLabel->setCaption(jobCaption.str());
+ moneyLabel->setCaption(moneyCaption.str());
+
+ playerBox->hairStyle = pi->hair_style - 1;
+ playerBox->hairColor = pi->hair_color - 1;
+ playerBox->showPlayer = true;
+ }
+ else {
+ nameLabel->setCaption("Name");
+ levelLabel->setCaption("Level");
+ jobLevelLabel->setCaption("Job Level");
+ moneyLabel->setCaption("Money");
+
+ playerBox->hairStyle = 0;
+ playerBox->hairColor = 0;
+ playerBox->showPlayer = false;
+ }
+}
- nameLabel->setCaption(nameCaption.str());
- levelLabel->setCaption(levelCaption.str());
- jobLevelLabel->setCaption(jobCaption.str());
- moneyLabel->setCaption(moneyCaption.str());
+void CharSelectDialog::serverCharDelete() {
+ // Delete a character
+ if (yes_no("Confirm", "Are you sure?") == 0) {
+ // Request character deletion
+ WFIFOW(0) = net_w_value(0x0068);
+ WFIFOL(2) = net_l_value(char_info->id);
+ WFIFOSET(46);
- playerBox->hairStyle = pi->hair_style - 1;
- playerBox->hairColor = pi->hair_color - 1;
- playerBox->showPlayer = true;
+ while ((in_size < 2) || (out_size > 0)) flush();
+ if (RFIFOW(0) == 0x006f) {
+ RFIFOSKIP(2);
+ free(char_info);
+ n_character = 0;
+ setPlayerInfo(NULL);
+ new OkDialog(this, "Info", "Player deleted");
+ }
+ else if (RFIFOW(0) == 0x006c) {
+ switch (RFIFOB(2)) {
+ case 0:
+ new OkDialog(this, "Error", "Access denied");
+ break;
+ case 1:
+ new OkDialog(this, "Error", "Cannot use this ID");
+ break;
+ }
+ RFIFOSKIP(3);
+ }
+ else {
+ new OkDialog(this, "Error", "Unknown error");
+ }
+ }
}
+void CharSelectDialog::serverCharSelect()
+{
+ // Request character selection
+ WFIFOW(0) = net_w_value(0x0066);
+ WFIFOB(2) = net_b_value(0);
+ WFIFOSET(3);
-CharCreateDialog::CharCreateDialog():
- Window("Create Character", true)
+ while ((in_size < 3) || (out_size > 0)) {
+ flush();
+ }
+
+ log("CharSelect", "Packet ID: %x, Length: %d, Packet_in_size %d",
+ RFIFOW(0),
+ get_length(RFIFOW(0)),
+ RFIFOW(2));
+ log("CharSelect", "In_size: %d", in_size);
+
+ if (RFIFOW(0) == 0x0071) {
+ while (in_size < 28) {
+ flush();
+ }
+ char_ID = RFIFOL(2);
+ memset(map_path, '\0', 480);
+ append_filename(map_path, "./data/map/", RFIFOP(6), 480);
+ map_address = RFIFOL(22);
+ map_port = RFIFOW(26);
+ state = GAME;
+
+ log("CharSelect", "Map: %s", map_name);
+ log("CharSelect", "Server: %s:%d", iptostring(map_address), map_port);
+ RFIFOSKIP(28);
+ close_session();
+ } else if (RFIFOW(0) == 0x006c) {
+ switch (RFIFOB(2)) {
+ case 0:
+ new OkDialog(this, "Error", "Access denied");
+ break;
+ case 1:
+ new OkDialog(this, "Error", "Cannot use this ID");
+ break;
+ }
+ RFIFOSKIP(3);
+ }
+ // Todo: add other packets
+}
+
+CharCreateDialog::CharCreateDialog(Window *parent):
+ Window("Create Character", true, parent)
{
nameField = new TextField("");
nameLabel = new gcn::Label("Name:");
@@ -229,7 +319,6 @@ void CharCreateDialog::action(const std::string& eventId)
// Attempt to create the character and schedule this dialog for
// deletion.
serverCharCreate();
- windowContainer->scheduleDelete(this);
}
else if (eventId == "cancel") {
windowContainer->scheduleDelete(this);
@@ -302,18 +391,23 @@ void CharCreateDialog::serverCharCreate()
} else if (RFIFOW(0) == 0x006c) {
switch (RFIFOB(2)) {
case 0:
- ok("Error", "Access denied");
+ new OkDialog(this, "Error", "Access denied");
break;
case 1:
- ok("Error", "Cannot use this ID");
+ new OkDialog(this, "Error", "Cannot use this ID");
break;
}
RFIFOSKIP(3);
n_character = 0;
} else {
- ok("Error", "Unknown error");
+ new OkDialog(this, "Error", "Unknown error");
n_character = 0;
}
+
+ // Remove window when succeeded
+ if (n_character == 1) {
+ windowContainer->scheduleDelete(this);
+ }
}
void charSelect()
@@ -321,9 +415,9 @@ void charSelect()
CharSelectDialog *sel;
sel = new CharSelectDialog();
- state = LOGIN;
+ state = CHAR_SELECT;
- while (!key[KEY_ESC] && !key[KEY_ENTER] && state != EXIT && state == LOGIN)
+ while (!key[KEY_ESC] && !key[KEY_ENTER] && state == CHAR_SELECT)
{
if (n_character > 0) {
sel->setPlayerInfo(char_info);
@@ -336,94 +430,8 @@ void charSelect()
// Draw to screen
blit(buffer, screen, 0, 0, 0, 0, 800, 600);
-
- }
-
- if (state == GAME)
- {
- serverCharSelect();
- close_session();
}
delete sel;
}
-void serverCharSelect()
-{
- // Request character selection
- WFIFOW(0) = net_w_value(0x0066);
- WFIFOB(2) = net_b_value(0);
- WFIFOSET(3);
-
- while ((in_size < 3) || (out_size > 0)) {
- flush();
- }
-
- log("CharSelect", "Packet ID: %x, Length: %d, Packet_in_size %d",
- RFIFOW(0),
- get_length(RFIFOW(0)),
- RFIFOW(2));
- log("CharSelect", "In_size: %d", in_size);
-
- if (RFIFOW(0) == 0x0071) {
- while (in_size < 28) {
- flush();
- }
- char_ID = RFIFOL(2);
- memset(map_path, '\0', 480);
- append_filename(map_path, "./data/map/", RFIFOP(6), 480);
- map_address = RFIFOL(22);
- map_port = RFIFOW(26);
- state = GAME;
-
- log("CharSelect", "Map: %s", map_name);
- log("CharSelect", "Server: %s:%d", iptostring(map_address), map_port);
- RFIFOSKIP(28);
- close_session();
- } else if (RFIFOW(0) == 0x006c) {
- switch (RFIFOB(2)) {
- case 0:
- ok("Error", "Access denied");
- break;
- case 1:
- ok("Error", "Cannot use this ID");
- break;
- }
- state = CHAR_SELECT;
- RFIFOSKIP(3);
- }
- // Todo: add other packets
-}
-
-void serverCharDelete() {
- state = CHAR_SELECT;
- // Delete a character
- if (yes_no("Confirm", "Are you sure?") == 0) {
- // Request character deletion
- WFIFOW(0) = net_w_value(0x0068);
- WFIFOL(2) = net_l_value(char_info->id);
- WFIFOSET(46);
-
- while ((in_size < 2) || (out_size > 0)) flush();
- if (RFIFOW(0) == 0x006f) {
- RFIFOSKIP(2);
- free(char_info);
- n_character = 0;
- ok("Info", "Player deleted");
- }
- else if (RFIFOW(0) == 0x006c) {
- switch (RFIFOB(2)) {
- case 0:
- ok("Error", "Access denied");
- break;
- case 1:
- ok("Error", "Cannot use this ID");
- break;
- }
- RFIFOSKIP(3);
- }
- else {
- ok("Error", "Unknown error");
- }
- }
-}
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 5711fb2f..f1675cb1 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -51,6 +51,16 @@ class CharSelectDialog : public Window, public gcn::ActionListener {
PlayerBox *playerBox;
+ /**
+ * Communicate character deletion to the server.
+ */
+ void serverCharDelete();
+
+ /**
+ * Communicate character selection to the server.
+ */
+ void serverCharSelect();
+
public:
/**
* Constructor.
@@ -97,7 +107,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener {
/**
* Constructor.
*/
- CharCreateDialog();
+ CharCreateDialog(Window *parent = NULL);
/**
* Destructor.
@@ -110,9 +120,5 @@ class CharCreateDialog : public Window, public gcn::ActionListener {
};
void charSelect();
-void serverCharSelect();
-
-void charCreate();
-void serverCharDelete();
#endif
diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp
index fa704ecc..54ddf3e9 100644
--- a/src/gui/ok_dialog.cpp
+++ b/src/gui/ok_dialog.cpp
@@ -24,9 +24,21 @@
#include "ok_dialog.h"
#include "button.h"
-OkDialog::OkDialog(const std::string& title, const std::string& msg):
+OkDialog::OkDialog(const std::string &title, const std::string &msg):
Window(title, true)
{
+ init(msg);
+}
+
+OkDialog::OkDialog(Window *parent, const std::string &title,
+ const std::string &msg):
+ Window(title, true, parent)
+{
+ init(msg);
+}
+
+void OkDialog::init(const std::string &msg)
+{
userLabel = new gcn::Label(msg);
okButton = new Button("OK");
@@ -59,7 +71,7 @@ OkDialog::~OkDialog()
delete okButton;
}
-void OkDialog::action(const std::string& eventId)
+void OkDialog::action(const std::string &eventId)
{
if (eventId == "ok") {
windowContainer->scheduleDelete(this);
diff --git a/src/gui/ok_dialog.h b/src/gui/ok_dialog.h
index ad0359b1..95ae52da 100644
--- a/src/gui/ok_dialog.h
+++ b/src/gui/ok_dialog.h
@@ -42,6 +42,14 @@ class OkDialog : public Window, public gcn::ActionListener {
OkDialog(const std::string &title, const std::string &msg);
/**
+ * Constructor with parent reference.
+ *
+ * @see Window::Window
+ */
+ OkDialog(Window *window, const std::string &title,
+ const std::string &msg);
+
+ /**
* Destructor.
*/
~OkDialog();
@@ -52,6 +60,11 @@ class OkDialog : public Window, public gcn::ActionListener {
void action(const std::string& eventId);
private:
+ /**
+ * Initializes the dialog.
+ */
+ void init(const std::string &msg);
+
gcn::Label *userLabel;
gcn::Button *okButton;
};
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
index eca0f04f..243849e6 100644
--- a/src/gui/playerbox.cpp
+++ b/src/gui/playerbox.cpp
@@ -45,7 +45,9 @@ void PlayerBox::draw(gcn::Graphics *graphics)
// Draw his hair
int hf = hairColor + 40 * (hairStyle);
- hairset->spriteset[hf]->draw(gui_bitmap, x + 37, y + 5);
+ if (hf >= 0 && hf < (int)hairset->spriteset.size()) {
+ hairset->spriteset[hf]->draw(gui_bitmap, x + 37, y + 5);
+ }
}
}
diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp
index b66a5426..f2bf610c 100644
--- a/src/gui/skill.cpp
+++ b/src/gui/skill.cpp
@@ -25,8 +25,7 @@
#include "listbox.h"
#include "scrollarea.h"
#include "button.h"
-
-extern PLAYER_INFO *char_info;
+#include "../main.h"
char *skill_db[] = {
// 0-99
diff --git a/src/gui/skill.h b/src/gui/skill.h
index f4da74ea..dd3772cc 100644
--- a/src/gui/skill.h
+++ b/src/gui/skill.h
@@ -25,8 +25,6 @@
#define _TMW_SKILL_H
#include <allegro.h>
-#include "../main.h"
-#include "gui.h"
#include "window.h"
struct SKILL {
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 19621c07..9ab17799 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -27,14 +27,20 @@
WindowContainer *Window::windowContainer = NULL;
-Window::Window(const std::string& text, bool modal):
+Window::Window(const std::string& text, bool modal, Window *parent):
+ parent(parent),
caption(text),
mousePX(0),
mousePY(0),
snapSize(8),
mouseDown(false),
+ modal(modal),
titlebarHeight(20)
{
+#ifdef __DEBUG
+ std::cout << "Window::Window(\"" << caption << "\")\n";
+#endif
+
titlebarColor.r = 203;
titlebarColor.g = 203;
titlebarColor.b = 203;
@@ -66,6 +72,10 @@ Window::Window(const std::string& text, bool modal):
Window::~Window()
{
+#ifdef __DEBUG
+ std::cout << "Window::~Window(\"" << caption << "\")\n";
+#endif
+
// Free dialog bitmaps
release_bitmap(dLeft);
release_bitmap(dMid);
@@ -172,6 +182,16 @@ void Window::setSize(int width, int height)
setHeight(height);
}
+Window *Window::getParentWindow()
+{
+ return parent;
+}
+
+bool Window::isModal()
+{
+ return modal;
+}
+
void Window::add(gcn::Widget *w)
{
chrome->add(w);
diff --git a/src/gui/window.h b/src/gui/window.h
index b80a14c1..39d04ddb 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -38,12 +38,14 @@ class Window : public gcn::Container, public gcn::MouseListener
{
protected:
gcn::Container *chrome; /**< Contained container */
+ Window *parent; /**< The parent window */
std::string caption; /**< Title bar caption */
int z; /**< Z position of the window */
int mousePX; /**< Mouse down location */
int mousePY; /**< Mouse down location */
int snapSize; /**< Snap distance to window edge */
bool mouseDown; /**< Mouse button state */
+ bool modal; /**< Window is modal */
gcn::Color titlebarColor; /**< Title bar color */
int titlebarHeight; /**< Height of title bar */
@@ -62,7 +64,8 @@ class Window : public gcn::Container, public gcn::MouseListener
* @param text The initial window title, "Window" by default.
* @param modal Block input to other windows.
*/
- Window(const std::string& text = "Window", bool modal = false);
+ Window(const std::string& text = "Window", bool modal = false,
+ Window *parent = NULL);
/**
* Destructor.
@@ -119,6 +122,19 @@ class Window : public gcn::Container, public gcn::MouseListener
*/
void setSize(int width, int height);
+ /**
+ * Returns the parent window.
+ *
+ * @return The parent window or <code>NULL</code> if there is none.
+ */
+ Window *getParentWindow();
+
+ /**
+ * Returns wether this window is modal. This doesn't necessarily mean
+ * that is gets input as a child modal window could get it.
+ */
+ bool isModal();
+
// Mouse handling
void mousePress(int mx, int my, int button);
diff --git a/src/gui/windowcontainer.cpp b/src/gui/windowcontainer.cpp
index c9ce6eff..3367b5f4 100644
--- a/src/gui/windowcontainer.cpp
+++ b/src/gui/windowcontainer.cpp
@@ -23,10 +23,11 @@
#include <iostream>
#include "windowcontainer.h"
+#include "window.h"
WindowContainer::WindowContainer():
mouseDown(false),
- modalWidget(NULL)
+ modalWindow(NULL)
{
}
@@ -84,7 +85,7 @@ void WindowContainer::_mouseInputMessage(const gcn::MouseInput &mouseInput)
}
if (mWidgetWithMouse && !mWidgetWithMouse->hasFocus() &&
- (!modalWidget || modalWidget == mWidgetWithMouse)) {
+ (!modalWindow || (gcn::Widget*)modalWindow == mWidgetWithMouse)) {
gcn::MouseInput mi = mouseInput;
mi.x -= mWidgetWithMouse->getX();
mi.y -= mWidgetWithMouse->getY();
@@ -96,44 +97,66 @@ void WindowContainer::_mouseInputMessage(const gcn::MouseInput &mouseInput)
}
}
-void WindowContainer::add(gcn::Widget *widget, bool modal)
+void WindowContainer::add(gcn::Widget *widget)
{
gcn::Container::add(widget);
+}
+
+void WindowContainer::add(Window *window, bool modal)
+{
+ gcn::Container::add(window);
if (modal) {
- setModalWidget(widget);
+ setModalWindow(window);
}
}
void WindowContainer::remove(gcn::Widget *widget)
{
- if (modalWidget == widget) {
- modalWidget = NULL;
+ if (modalWindow == widget) {
+ setModalWindow(NULL);
}
gcn::Container::remove(widget);
}
void WindowContainer::_announceDeath(gcn::Widget *widget)
{
- if (modalWidget == widget) {
- modalWidget = NULL;
+ if (modalWindow == widget) {
+ setModalWindow(NULL);
}
gcn::Container::_announceDeath(widget);
}
void WindowContainer::clear()
{
- modalWidget = NULL;
+ modalWindow = NULL;
gcn::Container::clear();
}
-void WindowContainer::setModalWidget(gcn::Widget *widget)
+void WindowContainer::setModalWindow(Window *window)
{
- modalWidget = widget;
+ if (modalWindow != window) {
+ if (!window) {
+ // Removing modal window, at this point there must be a modal
+ // window set.
+ Window *modalParent = modalWindow->getParentWindow();
+ if (modalParent && modalParent->isModal()) {
+ // Return modality to parent.
+ modalWindow = modalParent;
+ return;
+ }
+ }
+ else if (modalWindow && window->getParentWindow() != modalWindow) {
+ // Adding a modal window, but failed sanity check.
+ std::cerr << "Error: existing modal window not parent.\n";
+ return;
+ }
+ modalWindow = window;
+ }
}
-gcn::Widget *WindowContainer::getModalWidget()
+gcn::Widget *WindowContainer::getModalWindow()
{
- return modalWidget;
+ return modalWindow;
}
void WindowContainer::scheduleDelete(gcn::Widget *widget)
diff --git a/src/gui/windowcontainer.h b/src/gui/windowcontainer.h
index 8b5753a5..582faf7a 100644
--- a/src/gui/windowcontainer.h
+++ b/src/gui/windowcontainer.h
@@ -26,6 +26,8 @@
#include <guichan.hpp>
+class Window;
+
/**
* A window container. This container makes draggable windows possible.
*
@@ -54,7 +56,15 @@ class WindowContainer : public gcn::Container {
* Adds a widget. The widget can be set to be modal, which will ensure
* only that widget will receive input.
*/
- void add(gcn::Widget *widget, bool modal = false);
+ void add(gcn::Widget *widget);
+
+ /**
+ * Adds a window. The window can be set to be modal, which will ensure
+ * only that window will receive input. Note that when a modal widget
+ * has already been set, a new window can only be made model when the
+ * previously modal window is its parent.
+ */
+ void WindowContainer::add(Window *window, bool modal);
/**
* Removes a widget.
@@ -78,13 +88,13 @@ class WindowContainer : public gcn::Container {
*
* @see Window::Window
*/
- void setModalWidget(gcn::Widget *widget);
+ void setModalWindow(Window *window);
/**
* Returns the current modal widget, or <code>NULL</code> if there
* is none.
*/
- gcn::Widget *getModalWidget();
+ gcn::Widget *getModalWindow();
/**
* Schedule a widget for deletion. It will be deleted at the start of
@@ -94,7 +104,7 @@ class WindowContainer : public gcn::Container {
protected:
bool mouseDown;
- gcn::Widget *modalWidget;
+ Window *modalWindow;
std::list<gcn::Widget*> deathList;
};