From 9ab399906e9c6ba2d6e029b1d8be50bd1df70ed4 Mon Sep 17 00:00:00 2001
From: Bjørn Lindeijer <bjorn@lindeijer.nl>
Date: Sat, 8 Jan 2005 16:51:00 +0000
Subject: Some improvements to character creation and selection dialogs.

---
 file.list               |   1 +
 src/Makefile.am         |   1 +
 src/gui/char_select.cpp | 333 +++++++++++++++++++++++-------------------------
 src/gui/char_select.h   |  38 ++----
 src/gui/char_server.cpp |  47 +++----
 src/gui/ok_dialog.cpp   |  22 +++-
 src/gui/playerbox.cpp   |  63 +++++++++
 src/gui/playerbox.h     |  58 +++++++++
 src/main.cpp            |   9 +-
 src/main.h              |  26 ++--
 10 files changed, 356 insertions(+), 242 deletions(-)
 create mode 100644 src/gui/playerbox.cpp
 create mode 100644 src/gui/playerbox.h

diff --git a/file.list b/file.list
index 86be4d08..b49df4de 100644
--- a/file.list
+++ b/file.list
@@ -17,6 +17,7 @@ MODULES = src/sound/sound.cpp \
           src/gui/npc_text.cpp \
           src/gui/ok_dialog.cpp \
           src/gui/passwordfield.cpp \
+          src/gui/playerbox.cpp \
           src/gui/progressbar.cpp \
           src/gui/radiobutton.cpp \
           src/gui/scrollarea.cpp \
diff --git a/src/Makefile.am b/src/Makefile.am
index d64b7b7b..8657d35e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,6 +18,7 @@ tmw_SOURCES = sound/sound.cpp \
 	gui/npc_text.cpp \
 	gui/ok_dialog.cpp \
 	gui/passwordfield.cpp \
+	gui/playerbox.cpp \
 	gui/progressbar.cpp \
 	gui/radiobutton.cpp \
 	gui/scrollarea.cpp \
diff --git a/src/gui/char_select.cpp b/src/gui/char_select.cpp
index d54b8ca7..1481276d 100644
--- a/src/gui/char_select.cpp
+++ b/src/gui/char_select.cpp
@@ -26,39 +26,49 @@
 #include "button.h"
 #include "ok_dialog.h"
 #include "../graphic/graphic.h"
-#include "../main.h"
+#include <sstream>
+
+#define NR_HAIR_STYLES 4
+#define NR_HAIR_COLORS 10
 
 CharSelectDialog::CharSelectDialog():
     Window("Select Character")
 {
-    selectButton = new Button(" OK ");
+    selectButton = new Button("OK");
     cancelButton = new Button("Cancel");
-    newCharButton = new Button(" New ");
+    newCharButton = new Button("New");
     delCharButton = new Button("Delete");
     nameLabel = new gcn::Label("Name");
     levelLabel = new gcn::Label("Level");
     jobLevelLabel = new gcn::Label("Job Level");
     moneyLabel = new gcn::Label("Money");
-
-    nameLabel->setDimension(gcn::Rectangle(0, 0, 128, 16));
-    levelLabel->setDimension(gcn::Rectangle(0, 0, 128, 16));
-    jobLevelLabel->setDimension(gcn::Rectangle(0, 0, 128, 16));
-    moneyLabel->setDimension(gcn::Rectangle(0, 0, 128, 16));
+    playerBox = new PlayerBox();
 
     selectButton->setEventId("ok");
     newCharButton->setEventId("new");
     cancelButton->setEventId("cancel");
     delCharButton->setEventId("delete");
 
-    selectButton->setPosition(128, 180);
-    cancelButton->setPosition(166, 180);
-    newCharButton->setPosition(4, 180);
-    delCharButton->setPosition(64, 180);
-    nameLabel->setPosition(10, 100);
-    levelLabel->setPosition(10, 116);
-    jobLevelLabel->setPosition(10, 132);
-    moneyLabel->setPosition(10, 148);
-
+    int w = 195;
+    int h = 195;
+    setSize(w, h);
+    playerBox->setDimension(gcn::Rectangle(5, 5, w - 10, 90));
+    nameLabel->setDimension(gcn::Rectangle(10, 100, 128, 16));
+    levelLabel->setDimension(gcn::Rectangle(10, 116, 128, 16));
+    jobLevelLabel->setDimension(gcn::Rectangle(10, 132, 128, 16));
+    moneyLabel->setDimension(gcn::Rectangle(10, 148, 128, 16));
+    newCharButton->setPosition(5, h - 5 - newCharButton->getHeight());
+    delCharButton->setPosition(
+            5 + newCharButton->getWidth() + 5,
+            newCharButton->getY());
+    cancelButton->setPosition(
+            w - 5 - cancelButton->getWidth(),
+            newCharButton->getY());
+    selectButton->setPosition(
+            cancelButton->getX() - 5 - selectButton->getWidth(),
+            newCharButton->getY());
+
+    add(playerBox);
     add(selectButton);
     add(cancelButton);
     add(newCharButton);
@@ -74,7 +84,6 @@ CharSelectDialog::CharSelectDialog():
     newCharButton->addActionListener(this);
     delCharButton->addActionListener(this);
 
-    setSize(240, 216);
     setLocationRelativeTo(getParent());
 }
 
@@ -83,6 +92,12 @@ CharSelectDialog::~CharSelectDialog()
     delete selectButton;
     delete cancelButton;
     delete newCharButton;
+    delete delCharButton;
+    delete nameLabel;
+    delete levelLabel;
+    delete jobLevelLabel;
+    delete moneyLabel;
+    delete playerBox;
 }
 
 void CharSelectDialog::action(const std::string& eventId)
@@ -99,7 +114,7 @@ void CharSelectDialog::action(const std::string& eventId)
         if (n_character > 0)
             return;
         // Start new character dialog...
-        charCreate();
+        new CharCreateDialog();
     } else if (eventId == "delete") {
         // Delete character
         if (n_character <= 0)
@@ -108,14 +123,28 @@ void CharSelectDialog::action(const std::string& eventId)
     }
 }
 
-#define MAX_HAIR_STYLE 3
-#define MAX_HAIR_COLOR 9
-int curHairColor = 0;
-int curHairStyle = 0;
-std::string curName;
+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;
+
+    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;
+}
+
 
 CharCreateDialog::CharCreateDialog():
-    Window("Create Character")
+    Window("Create Character", true)
 {
     nameField = new TextField("");
     nameLabel = new gcn::Label("Name:");
@@ -126,31 +155,47 @@ CharCreateDialog::CharCreateDialog():
     prevHairStyleButton = new Button("<");
     hairStyleLabel = new gcn::Label("Hair Style:");
     createButton = new Button("Create");
+    cancelButton = new Button("Cancel");
+    playerBox = new PlayerBox();
+    playerBox->showPlayer = true;
 
+    nameField->setEventId("create");
     nextHairColorButton->setEventId("nextcolor");
     prevHairColorButton->setEventId("prevcolor");
     nextHairStyleButton->setEventId("nextstyle");
     prevHairStyleButton->setEventId("prevstyle");
     createButton->setEventId("create");
+    cancelButton->setEventId("cancel");
 
-    nameField->setDimension(gcn::Rectangle(0, 0, 96, 16));
-
-    nameField->setPosition(40, 4);
-    nameLabel->setPosition(4, 4);
-    nextHairColorButton->setPosition(160, 32);
-    prevHairColorButton->setPosition(96, 32);
-    hairColorLabel->setPosition(4, 34);
-    nextHairStyleButton->setPosition(160, 64);
-    prevHairStyleButton->setPosition(96, 64);
-    hairStyleLabel->setPosition(4, 66);
-    createButton->setPosition(125, 96);
-
+    int w = 200;
+    int h = 150;
+    setSize(w, h);
+    playerBox->setDimension(gcn::Rectangle(80, 30, 110, 85));
+    nameLabel->setPosition(5, 5);
+    nameField->setDimension(
+            gcn::Rectangle(45, 5, w - 45 - 7, nameField->getHeight()));
+    prevHairColorButton->setPosition(90, 35);
+    nextHairColorButton->setPosition(165, 35);
+    hairColorLabel->setPosition(5, 40);
+    prevHairStyleButton->setPosition(90, 64);
+    nextHairStyleButton->setPosition(165, 64);
+    hairStyleLabel->setPosition(5, 70);
+    cancelButton->setPosition(
+            w - 5 - cancelButton->getWidth(),
+            h - 5 - cancelButton->getHeight());
+    createButton->setPosition(
+            cancelButton->getX() - 5 - createButton->getWidth(),
+            h - 5 - cancelButton->getHeight());
+
+    nameField->addActionListener(this);
     nextHairColorButton->addActionListener(this);
     prevHairColorButton->addActionListener(this);
     nextHairStyleButton->addActionListener(this);
     prevHairStyleButton->addActionListener(this);
     createButton->addActionListener(this);
+    cancelButton->addActionListener(this);
 
+    add(playerBox);
     add(nameField);
     add(nameLabel);
     add(nextHairColorButton);
@@ -160,8 +205,8 @@ CharCreateDialog::CharCreateDialog():
     add(prevHairStyleButton);
     add(hairStyleLabel);
     add(createButton);
+    add(cancelButton);
 
-    setSize(200, 128);
     setLocationRelativeTo(getParent());
 }
 
@@ -175,37 +220,101 @@ CharCreateDialog::~CharCreateDialog()
     delete nextHairStyleButton;
     delete prevHairStyleButton;
     delete hairStyleLabel;
+    delete playerBox;
 }
 
 void CharCreateDialog::action(const std::string& eventId)
 {
     if (eventId == "create") {
-        // Create character (used to exit create dialog loop)
-        state = CHAR_SELECT;
+        // Attempt to create the character and schedule this dialog for
+        // deletion.
+        serverCharCreate();
+        windowContainer->scheduleDelete(this);
+    }
+    else if (eventId == "cancel") {
+        windowContainer->scheduleDelete(this);
     }
     else if (eventId == "nextcolor") {
-        curHairColor++;
+        playerBox->hairColor++;
     }
     else if (eventId == "prevcolor") {
-        curHairColor--;
+        playerBox->hairColor += NR_HAIR_COLORS - 1;
     }
     else if (eventId == "nextstyle") {
-        curHairStyle++;
+        playerBox->hairStyle++;
     }
     else if (eventId == "prevstyle") {
-        curHairStyle--;
+        playerBox->hairStyle += NR_HAIR_STYLES - 1;
     }
 
-    if (curHairColor < 0)
-        curHairColor = 0;
-    if (curHairColor > MAX_HAIR_COLOR)
-        curHairColor = MAX_HAIR_COLOR;
-    if (curHairStyle < 0)
-        curHairStyle = 0;
-    if (curHairStyle > MAX_HAIR_STYLE)
-        curHairStyle = MAX_HAIR_STYLE;
+    playerBox->hairColor %= NR_HAIR_COLORS;
+    playerBox->hairStyle %= NR_HAIR_STYLES;
 }
 
+std::string CharCreateDialog::getName() {
+    return nameField->getText();
+}
+
+void CharCreateDialog::serverCharCreate()
+{
+    n_character = 1;
+
+    WFIFOW(0) = net_w_value(0x0067);
+    strcpy(WFIFOP(2), getName().c_str());
+    WFIFOB(26) = net_b_value(5);
+    WFIFOB(27) = net_b_value(5);
+    WFIFOB(28) = net_b_value(5);
+    WFIFOB(29) = net_b_value(5);
+    WFIFOB(30) = net_b_value(5);
+    WFIFOB(31) = net_b_value(5);
+    WFIFOB(32) = net_b_value(0);
+    WFIFOW(33) = net_w_value(playerBox->hairColor + 1);
+    WFIFOW(35) = net_w_value(playerBox->hairStyle + 1);
+    WFIFOSET(37);
+
+    while ((in_size < 3) || (out_size > 0)) flush();
+    if (RFIFOW(0) == 0x006d) {
+        while (in_size < 108) flush();
+        char_info = (PLAYER_INFO *)malloc(sizeof(PLAYER_INFO));
+        char_info->id = RFIFOL(2);//account_ID;
+        memset(char_info->name, '\0', 24);
+        strcpy(char_info[0].name, RFIFOP(2 + 74));
+        char_info->hp = RFIFOW(2 + 42);
+        char_info->max_hp = RFIFOW(2 + 44);
+        char_info->sp = RFIFOW(2 + 46);
+        char_info->max_sp = RFIFOW(2 + 48);
+        char_info->job_lv = RFIFOL(2 + 16);
+        char_info->job_xp = RFIFOL(2 + 12);
+        char_info->lv = RFIFOW(2 + 58);
+        char_info->xp = RFIFOL(2 + 4);
+        char_info->gp = RFIFOL(2 + 8);
+        char_info->STR = RFIFOB(2 + 98);
+        char_info->AGI = RFIFOB(2 + 99);
+        char_info->VIT = RFIFOB(2 + 100);
+        char_info->INT = RFIFOB(2 + 101);
+        char_info->DEX = RFIFOB(2 + 102);
+        char_info->LUK = RFIFOB(2 + 103);
+        char_info->hair_style = RFIFOW(2 + 54);
+        char_info->hair_color = RFIFOW(2 + 70);
+        char_info->weapon = RFIFOW(2 + 56);
+        RFIFOSKIP(108);
+        //n_character++;
+    } 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);
+        n_character = 0;
+    } else {
+        ok("Error", "Unknown error");
+        n_character = 0;
+    }
+}
 
 void charSelect()
 {
@@ -217,14 +326,7 @@ void charSelect()
     while (!key[KEY_ESC] && !key[KEY_ENTER] && state != EXIT && state == LOGIN)
     {
         if (n_character > 0) {
-            char tmpBuf[64];
-            sel->setName(char_info->name);
-            sprintf(tmpBuf, "Lvl: %d", char_info->lv);
-            sel->setLevel(tmpBuf);
-            sprintf(tmpBuf, "Job Lvl: %d", char_info->job_lv);
-            sel->setJobLevel(tmpBuf);
-            sprintf(tmpBuf, "Gold: %d", char_info->gp);
-            sel->setMoney(tmpBuf);
+            sel->setPlayerInfo(char_info);
         }
 
         // Draw background
@@ -232,19 +334,6 @@ void charSelect()
 
         gui->update();
 
-        // Draw character
-        const int pX = 8, pY = 16;
-        if (n_character > 0) {
-            playerset->spriteset[0]->draw(buffer,
-                    pX + sel->getX() - 31,
-                    pY + sel->getY() - 15);
-
-            int hf = char_info->hair_color + 40 * (char_info->hair_style) - 41;
-            hairset->spriteset[hf]->draw(buffer,
-                    pX + 31 + sel->getX(),
-                    pY + 15 + sel->getY());
-        }
-
         // Draw to screen
         blit(buffer, screen, 0, 0, 0, 0, 800, 600);
 
@@ -306,43 +395,6 @@ void serverCharSelect()
     // Todo: add other packets
 }
 
-void charCreate()
-{
-    CharCreateDialog *create = new CharCreateDialog();
-
-    state = LOGIN;
-    while (!key[KEY_ESC] && !key[KEY_ENTER] && state != EXIT &&
-            state != CHAR_SELECT)
-    {
-        // Draw background
-        blit(login_wallpaper, buffer, 0, 0, 0, 0, 800, 600);
-
-        gui->update();
-
-        // Draw character
-        const int pX = 96, pY = 40;
-        playerset->spriteset[0]->draw(buffer,
-                pX + create->getX() - 31,
-                pY + create->getY() - 15);
-
-        int hf = curHairColor + 40 * (curHairStyle);
-        hairset->spriteset[hf]->draw(buffer,
-                pX + 31 + create->getX(),
-                pY + 15 + create->getY());
-
-        // Draw to screen
-        blit(buffer, screen, 0, 0, 0, 0, 800, 600);
-
-        curName = create->getName();
-    }
-
-    if (state == CHAR_SELECT) {
-        serverCharCreate();
-    }
-
-    delete create;
-}
-
 void serverCharDelete() {
     state = CHAR_SELECT;
     // Delete a character
@@ -375,64 +427,3 @@ void serverCharDelete() {
         }
     }
 }
-
-void serverCharCreate()
-{
-    n_character = 1;
-
-    WFIFOW(0) = net_w_value(0x0067);
-    strcpy(WFIFOP(2), curName.c_str());
-    WFIFOB(26) = net_b_value(5);
-    WFIFOB(27) = net_b_value(5);
-    WFIFOB(28) = net_b_value(5);
-    WFIFOB(29) = net_b_value(5);
-    WFIFOB(30) = net_b_value(5);
-    WFIFOB(31) = net_b_value(5);
-    WFIFOB(32) = net_b_value(0);
-    WFIFOW(33) = net_w_value(curHairColor + 1);
-    WFIFOW(35) = net_w_value(curHairStyle + 1);
-    WFIFOSET(37);
-
-    while ((in_size < 3) || (out_size > 0)) flush();
-    if (RFIFOW(0) == 0x006d) {
-        while (in_size < 108) flush();
-        char_info = (PLAYER_INFO *)malloc(sizeof(PLAYER_INFO));
-        char_info->id = RFIFOL(2);//account_ID;
-        memset(char_info->name, '\0', 24);
-        strcpy(char_info[0].name, RFIFOP(2+74));
-        char_info->hp = RFIFOW(2+42);
-        char_info->max_hp = RFIFOW(2+44);
-        char_info->sp = RFIFOW(2+46);
-        char_info->max_sp = RFIFOW(2+48);
-        char_info->job_lv = RFIFOL(2+16);
-        char_info->job_xp = RFIFOL(2+12);
-        char_info->lv = RFIFOW(2+58);
-        char_info->xp = RFIFOL(2+4);
-        char_info->gp = RFIFOL(2+8);
-        char_info->STR = RFIFOB(2+98);
-        char_info->AGI = RFIFOB(2+99);
-        char_info->VIT = RFIFOB(2+100);
-        char_info->INT = RFIFOB(2+101);
-        char_info->DEX = RFIFOB(2+102);
-        char_info->LUK = RFIFOB(2+103);
-        char_info->hair_style = RFIFOW(2+54);
-        char_info->hair_color = RFIFOW(2+70);
-        char_info->weapon = RFIFOW(2+56);
-        RFIFOSKIP(108);
-        //n_character++;
-    } 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);
-        n_character = 0;
-    } else {
-        ok("Error", "Unknown error");
-        n_character = 0;
-    }
-}
diff --git a/src/gui/char_select.h b/src/gui/char_select.h
index 475deab0..5711fb2f 100644
--- a/src/gui/char_select.h
+++ b/src/gui/char_select.h
@@ -29,6 +29,7 @@
 #include "../main.h"
 #include "../net/network.h"
 #include "gui.h"
+#include "playerbox.h"
 #include <guichan/allegro.hpp>
 
 /**
@@ -48,6 +49,8 @@ class CharSelectDialog : public Window, public gcn::ActionListener {
         gcn::Label *jobLevelLabel;
         gcn::Label *moneyLabel;
 
+        PlayerBox *playerBox;
+
     public:
         /**
          * Constructor.
@@ -61,25 +64,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener {
 
         void action(const std::string& eventId);
 
-        void setName(const std::string name)
-        {
-            nameLabel->setCaption(name);
-        }
-
-        void setLevel(const std::string level)
-        {
-            levelLabel->setCaption(level);
-        }
-
-        void setJobLevel(const std::string level)
-        {
-            jobLevelLabel->setCaption(level);
-        }
-
-        void setMoney(const std::string money)
-        {
-            moneyLabel->setCaption(money);
-        }
+        void setPlayerInfo(PLAYER_INFO* pi);
 };
 
 /**
@@ -97,8 +82,16 @@ class CharCreateDialog : public Window, public gcn::ActionListener {
         gcn::Button *nextHairStyleButton;
         gcn::Button *prevHairStyleButton;
         gcn::Label *hairStyleLabel;
-
         gcn::Button *createButton;
+        gcn::Button *cancelButton;
+
+        PlayerBox *playerBox;
+
+        /**
+         * Communicate character creation to the server and receive new char
+         * info.
+         */
+        void serverCharCreate();
 
     public:
         /**
@@ -113,9 +106,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener {
 
         void action(const std::string& eventId);
 
-        std::string getName() {
-            return nameField->getText();
-        }
+        std::string getName();
 };
 
 void charSelect();
@@ -123,6 +114,5 @@ void serverCharSelect();
 
 void charCreate();
 void serverCharDelete();
-void serverCharCreate();
 
 #endif
diff --git a/src/gui/char_server.cpp b/src/gui/char_server.cpp
index b042a05a..82c5f05e 100644
--- a/src/gui/char_server.cpp
+++ b/src/gui/char_server.cpp
@@ -151,31 +151,32 @@ void server_char_server(int serverIndex) {
 
     while (in_size<3)flush();
 
-    if (RFIFOW(0)==0x006b) {
-        while(in_size<RFIFOW(2))flush();
-        n_character = (RFIFOW(2)-24)/106;
+    if (RFIFOW(0) == 0x006b) {
+        while(in_size < RFIFOW(2))flush();
+        n_character = (RFIFOW(2) - 24) / 106;
         char_info = (PLAYER_INFO *)malloc(sizeof(PLAYER_INFO) * n_character);
         for (int i = 0; i < n_character; i++) {
-            char_info[i].id = RFIFOL(24+106*i);
-            strcpy(char_info[i].name, RFIFOP(24+106*i+74));
-            char_info[i].hp = RFIFOW(24+106*i+42);
-            char_info[i].max_hp = RFIFOW(24+106*i+44);
-            char_info[i].xp = RFIFOL(24+106*i+4);
-            char_info[i].gp = RFIFOL(24+106*i+8);
-            char_info[i].job_xp = RFIFOL(24+106*i+12);
-            char_info[i].job_lv = RFIFOL(24+106*i+16);
-            char_info[i].sp = RFIFOW(24+106*i+46);
-            char_info[i].max_sp = RFIFOW(24+106*i+48);
-            char_info[i].lv = RFIFOW(24+106*i+58);
-            char_info[i].STR = RFIFOB(24+106*i+98);
-            char_info[i].AGI = RFIFOB(24+106*i+99);
-            char_info[i].VIT = RFIFOB(24+106*i+100);
-            char_info[i].INT = RFIFOB(24+106*i+101);
-            char_info[i].DEX = RFIFOB(24+106*i+102);
-            char_info[i].LUK = RFIFOB(24+106*i+103);
-            char_info[i].hair_style = RFIFOW(24+106*i+54);
-            char_info[i].hair_color = RFIFOW(24+106*i+70);
-            char_info[i].weapon = RFIFOW(24+106*i+56);
+            int n = 24 + 106 * i;
+            char_info[i].id = RFIFOL(n);
+            strcpy(char_info[i].name, RFIFOP(n + 74));
+            char_info[i].hp = RFIFOW( n+ 42);
+            char_info[i].max_hp = RFIFOW(n + 44);
+            char_info[i].xp = RFIFOL(n + 4);
+            char_info[i].gp = RFIFOL(n + 8);
+            char_info[i].job_xp = RFIFOL(n + 12);
+            char_info[i].job_lv = RFIFOL(n + 16);
+            char_info[i].sp = RFIFOW(n + 46);
+            char_info[i].max_sp = RFIFOW(n + 48);
+            char_info[i].lv = RFIFOW(n + 58);
+            char_info[i].STR = RFIFOB(n + 98);
+            char_info[i].AGI = RFIFOB(n + 99);
+            char_info[i].VIT = RFIFOB(n + 100);
+            char_info[i].INT = RFIFOB(n + 101);
+            char_info[i].DEX = RFIFOB(n + 102);
+            char_info[i].LUK = RFIFOB(n + 103);
+            char_info[i].hair_style = RFIFOW(n + 54);
+            char_info[i].hair_color = RFIFOW(n + 70);
+            char_info[i].weapon = RFIFOW(n + 56);
         }
         state = CHAR_SELECT;
 
diff --git a/src/gui/ok_dialog.cpp b/src/gui/ok_dialog.cpp
index 887c09f7..fa704ecc 100644
--- a/src/gui/ok_dialog.cpp
+++ b/src/gui/ok_dialog.cpp
@@ -29,12 +29,21 @@ OkDialog::OkDialog(const std::string& title, const std::string& msg):
 {
     userLabel = new gcn::Label(msg);
     okButton = new Button("OK");
-    
-    setSize(200, 80);
-    userLabel->setPosition(4, 11);
-    okButton->setPosition(120, 52);
-    okButton->setEventId("ok");
-    
+
+    int w = userLabel->getWidth() + 20;
+    int h = userLabel->getHeight() + 25 + okButton->getHeight();
+
+    if (okButton->getWidth() + 10 > w) {
+        w = okButton->getWidth() + 10;
+    }
+
+    setSize(w, h);
+    userLabel->setPosition(10, 10);
+    okButton->setPosition(
+            (w - okButton->getWidth()) / 2,
+            h - 5 - okButton->getHeight());
+
+    okButton->setEventId("ok");    
     okButton->addActionListener(this);
     
     add(userLabel);
@@ -53,7 +62,6 @@ OkDialog::~OkDialog()
 void OkDialog::action(const std::string& eventId)
 {
     if (eventId == "ok") {
-        //getParent()->remove(this);
         windowContainer->scheduleDelete(this);
     }
 }
diff --git a/src/gui/playerbox.cpp b/src/gui/playerbox.cpp
new file mode 100644
index 00000000..eca0f04f
--- /dev/null
+++ b/src/gui/playerbox.cpp
@@ -0,0 +1,63 @@
+/*
+ *  The Mana World
+ *  Copyright 2004 The Mana World Development Team
+ *
+ *  This file is part of The Mana World.
+ *
+ *  The Mana World is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  The Mana World is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  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$
+ */
+
+#include "playerbox.h"
+#include "gui.h"
+#include "../main.h"
+
+PlayerBox::PlayerBox():
+    hairColor(0),
+    hairStyle(0),
+    showPlayer(false)
+{
+    setBorderSize(2);
+}
+
+void PlayerBox::draw(gcn::Graphics *graphics)
+{
+    if (showPlayer)
+    {
+        int x, y;
+        getAbsolutePosition(x, y);
+
+        // Draw character
+        playerset->spriteset[0]->draw(gui_bitmap, x - 25, y - 25);
+
+        // Draw his hair
+        int hf = hairColor + 40 * (hairStyle);
+        hairset->spriteset[hf]->draw(gui_bitmap, x + 37, y + 5);
+    }
+}
+
+void PlayerBox::drawBorder(gcn::Graphics *graphics)
+{
+    int x, y, w, h, bs;
+    getAbsolutePosition(x, y);
+    bs = getBorderSize();
+    w = getWidth() + bs * 2;
+    h = getHeight() + bs * 2;
+    x -= bs;
+    y -= bs;
+
+    draw_skinned_rect(gui_bitmap, &gui_skin.textbox.bg, x, y, w, h);
+}
diff --git a/src/gui/playerbox.h b/src/gui/playerbox.h
new file mode 100644
index 00000000..87ab24e0
--- /dev/null
+++ b/src/gui/playerbox.h
@@ -0,0 +1,58 @@
+/*
+ *  The Mana World
+ *  Copyright 2004 The Mana World Development Team
+ *
+ *  This file is part of The Mana World.
+ *
+ *  The Mana World is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  any later version.
+ *
+ *  The Mana World is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  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$
+ */
+
+#ifndef __TMW_PLAYERBOX_H__
+#define __TMW_PLAYERBOX_H__
+
+#include <allegro.h>
+#include <guichan.hpp>
+
+/**
+ * A box showing a player. Draws the various hair styles a player can have
+ * currently.
+ *
+ * \ingroup GUI
+ */
+class PlayerBox : public gcn::ScrollArea {
+    public:
+        /**
+         * Constructor.
+         */
+        PlayerBox();
+
+        /**
+         * Draws the scroll area.
+         */
+        void draw(gcn::Graphics *graphics);
+
+        /**
+         * Draws the background and border of the scroll area.
+         */
+        void drawBorder(gcn::Graphics *graphics);
+
+        int hairColor;         /**< The hair color index */
+        int hairStyle;         /**< The hair style index */
+        bool showPlayer;       /**< Wether to show the player or not */
+};
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index 625b385d..57422e63 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -22,6 +22,9 @@
  */
 
 #include "main.h"
+#include "gui/char_server.h"
+#include "gui/char_select.h"
+#include "gui/inventory.h"
 #include "./sound/sound.h"
 #include "./graphic/graphic.h"
 
@@ -306,9 +309,11 @@ void init_engine() {
          }
          sound.setVolume(64);
         
-         /* left here to serve as an example ;) 
+         // left here to serve as an example ;)
+         /*
          SOUND_SID id = sound.loadItem("./data/sound/wavs/level.ogg");
-         sound.startItem(id, 70);*/
+         sound.startItem(id, 70);
+         */
     } catch (const char *err) {
          ok("Sound Engine", err);
          warning(err);
diff --git a/src/main.h b/src/main.h
index 7f258168..6a9ba209 100644
--- a/src/main.h
+++ b/src/main.h
@@ -34,9 +34,6 @@
 #include "configuration.h"
 #include "gui/login.h"
 #include "gui/gui.h"
-#include "gui/char_server.h"
-#include "gui/char_select.h"
-#include "gui/inventory.h"
 #include "graphic/image.h"
 #include "log.h"
 #include "game.h"
@@ -66,22 +63,21 @@
 #define LEN_PASSWORD 25
 
 
-
 typedef struct {
-	int address;
-	short port;
-	char name[20];
-	short online_users;
+    int address;
+    short port;
+    char name[20];
+    short online_users;
 } SERVER_INFO;
 
 typedef struct {
-	int id;
-	char name[24];
-	short hp, max_hp, sp, max_sp, lv;
-	int xp, gp, job_xp, job_lv;
-	short statp, skill_point, hair_color, hair_style;
-	char STR, AGI, VIT, INT, DEX, LUK;
-	short weapon;
+    int id;
+    char name[24];
+    short hp, max_hp, sp, max_sp, lv;
+    int xp, gp, job_xp, job_lv;
+    short statp, skill_point, hair_color, hair_style;
+    char STR, AGI, VIT, INT, DEX, LUK;
+    short weapon;
 } PLAYER_INFO;
 
 extern BITMAP *login_wallpaper;
-- 
cgit v1.2.3-70-g09d2