diff options
-rw-r--r-- | src/game.cpp | 12 | ||||
-rw-r--r-- | src/gui/char_select.cpp | 242 | ||||
-rw-r--r-- | src/gui/char_select.h | 16 | ||||
-rw-r--r-- | src/gui/ok_dialog.cpp | 16 | ||||
-rw-r--r-- | src/gui/ok_dialog.h | 13 | ||||
-rw-r--r-- | src/gui/playerbox.cpp | 4 | ||||
-rw-r--r-- | src/gui/skill.cpp | 3 | ||||
-rw-r--r-- | src/gui/skill.h | 2 | ||||
-rw-r--r-- | src/gui/window.cpp | 22 | ||||
-rw-r--r-- | src/gui/window.h | 18 | ||||
-rw-r--r-- | src/gui/windowcontainer.cpp | 49 | ||||
-rw-r--r-- | src/gui/windowcontainer.h | 18 |
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; }; |