* added posibility to create chars from the GUI. thx shlainn!

-> stuffextract: extract classmask field
* implemented irrlicht event message queueing. might fix some gui bugs.
This commit is contained in:
false_genesis 2009-04-20 21:09:38 +00:00
parent 53e88fca44
commit 585046fce2
13 changed files with 402 additions and 223 deletions

View File

@ -8,7 +8,10 @@
4=Back
5=OK
6=Cancel
7=Create
8=Cancel
[2]
0=Realmlist
1=Create New Character

View File

@ -6,6 +6,7 @@ name_short=Hu
faction=7
name_general=Human
name=Human
classmask=886
[2]
model_m=51
@ -14,6 +15,7 @@ name_short=Or
faction=1
name_general=Orc
name=Orc
classmask=730
[3]
model_m=53
@ -22,6 +24,7 @@ name_short=Dw
faction=7
name_general=Dwarf
name=Dwarf
classmask=126
[4]
model_m=55
@ -30,6 +33,7 @@ name_short=Ni
faction=7
name_general=NightElf
name=Night Elf
classmask=2170
[5]
model_m=57
@ -38,6 +42,7 @@ name_short=Sc
faction=1
name_general=Scourge
name=Undead
classmask=882
[6]
model_m=59
@ -46,6 +51,7 @@ name_short=Ta
faction=1
name_general=Tauren
name=Tauren
classmask=2250
[7]
model_m=1563
@ -54,6 +60,7 @@ name_short=Gn
faction=7
name_general=Gnome
name=Gnome
classmask=850
[8]
model_m=1478
@ -62,6 +69,7 @@ name_short=Tr
faction=1
name_general=Troll
name=Troll
classmask=506
[9]
model_m=6894
@ -70,6 +78,7 @@ name_short=Go
faction=7
name_general=Goblin
name=Goblin
classmask=0
[10]
model_m=15476
@ -78,6 +87,7 @@ name_short=Be
faction=1
name_general=BloodElf
name=Blood Elf
classmask=892
[11]
model_m=16125
@ -86,6 +96,7 @@ name_short=Dr
faction=7
name_general=Draenei
name=Draenei
classmask=494
[12]
model_m=16981
@ -94,6 +105,7 @@ name_short=Fo
faction=7
name_general=FelOrc
name=Fel Orc
classmask=0
[13]
model_m=17402
@ -102,6 +114,7 @@ name_short=Na
faction=7
name_general=Naga_
name=Naga
classmask=0
[14]
model_m=17576
@ -110,6 +123,7 @@ name_short=Br
faction=7
name_general=Broken
name=Broken
classmask=0
[15]
model_m=17578
@ -118,6 +132,7 @@ name_short=Sk
faction=7
name_general=Skeleton
name=Skeleton
classmask=0
[16]
model_m=21685
@ -126,6 +141,7 @@ name_short=Vr
faction=7
name_general=Vrykul
name=Vrykul
classmask=0
[17]
model_m=21780
@ -134,6 +150,7 @@ name_short=Tu
faction=7
name_general=Tuskarr
name=Tuskarr
classmask=0
[18]
model_m=21963
@ -142,6 +159,7 @@ name_short=Ft
faction=7
name_general=ForestTroll
name=Forest Troll
classmask=0
[19]
model_m=26316
@ -150,6 +168,7 @@ name_short=Wt
faction=7
name_general=Taunka
name=Taunka
classmask=0
[20]
model_m=26871
@ -158,6 +177,7 @@ name_short=NS
faction=7
name_general=NorthrendSkeleton
name=Northrend Skeleton
classmask=0
[21]
model_m=26873
@ -166,4 +186,5 @@ name_short=It
faction=7
name_general=IceTroll
name=Ice Troll
classmask=0

View File

@ -5,12 +5,6 @@
#include "SImage.h"
#include "CImageLoaderBLP.h"
#if defined(_DEBUG) && !defined(DEBUG)
#define DEBUG(code) code;
#else
#define DEBUG(code) ;
#endif
namespace irr
{
namespace video

View File

@ -1,6 +1,8 @@
#ifndef GUIEVENTRECEIVER_H
#define GUIEVENTRECEIVER_H
#include <queue>
class GUIEventReceiver : public IEventReceiver
{
@ -9,30 +11,24 @@ public:
{
buttons = 0;
react_to_keys = true;
memset(&guievent, 0 , sizeof(SEvent));
memset(&keyevent, 0 , sizeof(SEvent));
memset(&mouseevent, 0 , sizeof(SEvent));
guievent_proc = false;
mouseevent_proc = false;
keyevent_proc = false;
store_gui = true;
store_keys = true;
store_mouse = true;
}
virtual bool OnEvent(const SEvent& event)
{
// copy all 3 event types into different stores for later external use
if(event.EventType == EET_GUI_EVENT)
{
guievent = event;
guievent_proc = false;
guieventqueue.push_back(event.GUIEvent);
}
else if(event.EventType == EET_KEY_INPUT_EVENT)
{
keyevent = event;
keyevent_proc = false;
keyeventqueue.push_back(event.KeyInput);
}
else if(event.EventType == EET_MOUSE_INPUT_EVENT)
{
mouseevent = event;
mouseevent_proc = false;
mouseeventqueue.push_back(event.MouseInput);
}
bool proc = false;
@ -74,13 +70,45 @@ public:
return proc;
}
bool react_to_keys;
inline bool HasMouseEvent(void) { return mouseeventqueue.size(); }
inline bool HasGUIEvent(void) { return guieventqueue.size(); }
inline bool HasKeyEvent(void) { return keyeventqueue.size(); }
inline SEvent::SMouseInput NextMouseEvent(void)
{
ASSERT(HasMouseEvent())
const SEvent::SMouseInput ev = mouseeventqueue.front();
mouseeventqueue.pop_front();
return ev;
}
inline SEvent::SGUIEvent NextGUIEvent(void)
{
ASSERT(HasGUIEvent())
SEvent::SGUIEvent ev = guieventqueue.front();
guieventqueue.pop_front();
return ev;
}
inline SEvent::SKeyInput NextKeyEvent(void)
{
ASSERT(HasKeyEvent())
SEvent::SKeyInput ev = keyeventqueue.front();
keyeventqueue.pop_front();
return ev;
}
bool react_to_keys, store_mouse, store_keys, store_gui;
u32 buttons;
SEvent guievent, mouseevent, keyevent;
bool keyevent_proc, mouseevent_proc, guievent_proc;
std::map<u32,u32> keyToButtonMap; // to simulate button press on key input
std::set<u32> customHandledEvents;
protected:
std::list<SEvent::SGUIEvent> guieventqueue;
std::list<SEvent::SMouseInput> mouseeventqueue;
std::list<SEvent::SKeyInput> keyeventqueue;
};
#endif

View File

@ -317,13 +317,11 @@ void PseuGUI::_UpdateSceneState(void)
case SCENESTATE_REALMSELECT:
_scene = new SceneCharSelection(this);
_scene->SetData(ISCENE_CHARSEL_REALMFIRST, 1);
_scene->OnResize();
_scenestate_new = SCENESTATE_CHARSELECT;
break;
case SCENESTATE_CHARSELECT:
_scene = new SceneCharSelection(this);
_scene->SetData(ISCENE_CHARSEL_REALMFIRST, 0);
_scene->OnResize();
break;
default: _scene = new Scene(this); // will draw nothing, just yield the gui
}

View File

@ -63,7 +63,7 @@ protected:
CCursorController *cursor;
SceneState _scenestate;
uint32 scenedata[SCENEDATA_SIZE]; // generic storage for anything the PseuInstance thread wants to tell us
SCPDatabase *textdb;
SCPDatabase *textdb, *racedb, *classdb;
ZThread::FastMutex mutex;
};
@ -107,6 +107,12 @@ private:
IGUIWindow *realmwin;
IGUIListBox *realmlistbox;
IGUIListBox *charlistbox; // temporary until something better found
//Character creation //temporary. maybe a whole new character creation scene should be used?
IGUIWindow *newcharwin;
IGUIComboBox *raceselect;
IGUIComboBox *classselect;
IGUIEditBox *charname;
std::map<u32,u32> racemap, classmap; //<comboBoxId,dbId> maps DB IDs in db to IDs in the combobox, because irrlicht does not allow custom ids in comboboxes
};

View File

@ -15,141 +15,28 @@ enum GuiElementID
BUTTON_SELECT_REALM = 0x10,
BUTTON_REALMWIN_OK = 0x20,
BUTTON_REALMWIN_CANCEL = 0x40,
BUTTON_NEWCHARWIN_OK = 0x80,
BUTTON_NEWCHARWIN_CANCEL = 0x100,
};
SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui)
{
realmwin = NULL;
newcharwin = NULL;
textdb = instance->dbmgr.GetDB("gui_charselect_text");
racedb = instance->dbmgr.GetDB("race");
classdb = instance->dbmgr.GetDB("class");
eventrecv = new GUIEventReceiver();
device->setEventReceiver(eventrecv);
eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_BACK | BUTTON_REALMWIN_CANCEL;
eventrecv->keyToButtonMap[KEY_RETURN] = BUTTON_ENTER_WORLD | BUTTON_REALMWIN_OK;
eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_BACK | BUTTON_REALMWIN_CANCEL | BUTTON_NEWCHARWIN_CANCEL;
eventrecv->keyToButtonMap[KEY_RETURN] = BUTTON_ENTER_WORLD | BUTTON_REALMWIN_OK | BUTTON_NEWCHARWIN_OK;
eventrecv->customHandledEvents.insert(EGET_LISTBOX_SELECTED_AGAIN);
eventrecv->store_mouse = false; // do not queue mouse input
dimension2d<s32> scrn = driver->getScreenSize();
OnResize(); // call this manually to draw all buttons and stuff
if(soundengine)
{
ISoundSource *main_theme = soundengine->getSoundSource("data/misc/main_theme.ogg");
if(main_theme && !soundengine->isCurrentlyPlaying(main_theme))
{
soundengine->play2D(main_theme,true);
}
}
}
void SceneCharSelection::OnUpdate(s32 timepassed)
{
// treat doubleclick on listboxes as OK button click
if(!eventrecv->guievent_proc)
{
eventrecv->guievent_proc = true;
if(eventrecv->guievent.GUIEvent.EventType == EGET_LISTBOX_SELECTED_AGAIN)
{
if(eventrecv->guievent.GUIEvent.Caller == realmlistbox)
{
eventrecv->buttons |= BUTTON_REALMWIN_OK;
}
else if(eventrecv->guievent.GUIEvent.Caller == charlistbox)
{
eventrecv->buttons |= BUTTON_ENTER_WORLD;
}
}
}
if(eventrecv->buttons & BUTTON_ENTER_WORLD && !realmwin)
{
logdebug("GUI: SceneCharSelect: Entering world");
WorldSession *ws = instance->GetWSession();
if(ws)
{
u32 selected = charlistbox->getSelected();
if(selected < ws->GetCharsCount())
{
ws->EnterWorldWithCharacter(ws->GetCharFromList(selected).p._name);
}
else
logerror("Character selection out of bounds! (%u)",selected);
}
else
logerror("GUI: BUTTON_ENTER_ WORLD pressed, but no WorldSession exists!");
}
if(eventrecv->buttons & BUTTON_BACK && !realmwin) // cant cancel with realmwin open (important for ESC key handling)
{
logdebug("GUI: SceneCharSelect: Back to Loginscreen");
gui->SetSceneState(SCENESTATE_LOGINSCREEN);
// disconnect from realm server if connected
if(RealmSession *rs = instance->GetRSession())
rs->SetMustDie();
if(WorldSession *ws = instance->GetWSession())
ws->SetMustDie();
}
if(eventrecv->buttons & BUTTON_DELETE_CHARACTER)
{
guienv->addMessageBox(L"Not yet implemented!", L"Deleting a character does not yet work!");
}
if(eventrecv->buttons & BUTTON_NEW_CHARACTER)
{
guienv->addMessageBox(L"Not yet implemented!", L"Creating a new character does not yet work!");
}
if(eventrecv->buttons & BUTTON_SELECT_REALM)
{
if(instance->GetRSession())
{
scenedata[ISCENE_CHARSEL_REALMFIRST] = 1; // show realm selection window
OnResize(); // force gui redraw to remove window
// TODO: there should exist a better way without full redraw
}
else
{
guienv->addMessageBox(L"Not yet implemented!", L"This action is not yet supported.\nYou can change the realm only while still connected to the realm server.");
}
}
if(eventrecv->buttons & BUTTON_REALMWIN_OK)
{
RealmSession *rs = instance->GetRSession();
if(rs)
{
u32 selected = realmlistbox->getSelected();
if(selected < rs->GetRealmCount())
{
rs->SetRealmAddr(rs->GetRealm(selected).addr_port);
instance->CreateWorldSession();
eventrecv->buttons |= BUTTON_REALMWIN_CANCEL; // easiest way to close the window without much additional code
}
else
logerror("Realmlist selection out of bounds! (%u)",selected);
}
}
// realmlist window
if(eventrecv->buttons & BUTTON_REALMWIN_CANCEL)
{
scenedata[ISCENE_CHARSEL_REALMFIRST] = 0; // do not show realm selection window
OnResize(); // force gui redraw to remove window
// TODO: there should exist a better way without full redraw
}
eventrecv->buttons = 0;
}
void SceneCharSelection::OnDelete(void)
{
}
void SceneCharSelection::OnResize(void)
{
// this seems to be necessary since after a window resize <textdb> == 0x00000001 for some unknown reason (=CRASH!)
// if anyone knows how to fix that or whats causing it... please do so.
// note: used VC71. also tested it with resizing SceneLogin, there the ptr stays fine. wtf?!
textdb = instance->dbmgr.GetDB("gui_charselect_text");
guienv->clear(); // drop all elements and redraw
guienv->addButton(CalcRelativeScreenPos(driver, 0.45f ,0.9f, 0.15f, 0.05f), NULL, BUTTON_ENTER_WORLD,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_ENTERWORLD).c_str());
guienv->addButton(CalcRelativeScreenPos(driver, 0.9f, 0.92f, 0.08f, 0.03f), NULL, BUTTON_BACK,
@ -160,73 +47,13 @@ void SceneCharSelection::OnResize(void)
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_NEWCHAR).c_str());
guienv->addButton(CalcRelativeScreenPos(driver, 0.78f, 0.92f, 0.1f, 0.03f), NULL, BUTTON_DELETE_CHARACTER,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_DELCHAR).c_str());
realmwin = NULL;
mutex.acquire();
if(scenedata[ISCENE_CHARSEL_REALMFIRST])
{
dimension2d<s32> dim;
rect<s32> pos;
realmwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true,
GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_REALMWIN).c_str());
pos = realmwin->getAbsolutePosition(); // get absolute position and trandform <dim> to absolute in-window position
dim.Width = pos.LowerRightCorner.X - pos.UpperLeftCorner.X;
dim.Height = pos.LowerRightCorner.Y - pos.UpperLeftCorner.Y;
realmwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.7f, 0.93f, 0.12f, 0.05f), realmwin, BUTTON_REALMWIN_OK,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_OK).c_str()));
realmwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.85f, 0.93f, 0.12f, 0.05f), realmwin, BUTTON_REALMWIN_CANCEL,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_CANCEL).c_str()));
realmlistbox = guienv->addListBox(CalcRelativeScreenPos(dim, 0.1f, 0.1f, 0.8f, 0.8f), realmwin);
realmwin->addChild(realmlistbox);
RealmSession *rs = instance->GetRSession();
for(uint32 i = 0; i < rs->GetRealmCount(); i++)
{
SRealmInfo& r = rs->GetRealm(i);
core::stringw entry;
entry += r.name.c_str();
entry += L", ";
switch(r.icon) // icon means here RealmType
{
case 0: entry += "Normal"; break;
case 1: entry += "PvP"; break;
case 4: entry += "Normal(4)"; break;
case 6: entry += "RP"; break;
case 8: entry += "RP-PvP"; break;
case 16: entry += "FFA-PvP"; break; // MaNGOS custom realm type
default: entry += "Unknown"; break;
}
entry += L", (";
entry += r.chars_here;
entry += L") Chars";
entry += L" [";
entry += r.addr_port.c_str();
entry += L"]";
realmlistbox->addItem(entry.c_str(), -1);
SColor col;
switch(r.color)
{
case 0: col.set(0xFF, 0x00, 0xFF, 0x00); break;
case 1: col.set(0xFF, 0xFF, 0x00, 0x00); break;
case 2: col.set(0xFF, 0x7F, 0x7F, 0x7F); break;
case 3: col.set(0xFF, 0xB0, 0xB0, 0x00); break;
default: col.set(0xFFFFFFFF);
}
realmlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col);
realmlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col);
}
if(realmlistbox->getItemCount())
realmlistbox->setSelected(0);
}
rect<s32> clb_rect = CalcRelativeScreenPos(driver, 0.65f, 0.12f, 0.34f, 0.67f);
charlistbox = guienv->addListBox(clb_rect);
mutex.acquire();
WorldSession *ws = instance->GetWSession();
if(ws)
{
SCPDatabase *racedb = instance->dbmgr.GetDB("race");
uint32 ffaction = racedb->GetFieldId("faction");
for(uint32 i = 0; i < ws->GetCharsCount(); i++)
{
@ -236,7 +63,7 @@ void SceneCharSelection::OnResize(void)
entry += L", ";
entry += L"Level ";
entry += c.p._level;
entry += "L ";
entry += L" ";
entry += c.race.c_str();
entry += L" ";
entry += c.class_.c_str();
@ -262,6 +89,265 @@ void SceneCharSelection::OnResize(void)
}
}
mutex.release();
if(soundengine)
{
ISoundSource *main_theme = soundengine->getSoundSource("data/misc/main_theme.ogg");
if(main_theme && !soundengine->isCurrentlyPlaying(main_theme))
{
soundengine->play2D(main_theme,true);
}
}
}
void SceneCharSelection::OnUpdate(s32 timepassed)
{
// treat doubleclick on listboxes as OK button click
if(eventrecv->HasGUIEvent())
{
SEvent::SGUIEvent& ev = eventrecv->NextGUIEvent();
if(ev.EventType == EGET_LISTBOX_SELECTED_AGAIN)
{
if(ev.Caller == realmlistbox)
{
eventrecv->buttons |= BUTTON_REALMWIN_OK;
}
else if(ev.Caller == charlistbox)
{
eventrecv->buttons |= BUTTON_ENTER_WORLD;
}
}
if(ev.EventType == EGET_ELEMENT_CLOSED)
{
if(ev.Caller == realmwin)//realmwin got closed via the close button, remove pointer
{
realmwin = NULL;
}
if(ev.Caller == newcharwin)//got closed via the close button, remove pointer
{
newcharwin = NULL;
}
}
if(ev.EventType == EGET_COMBO_BOX_CHANGED)
{
if(ev.Caller == raceselect)
{
classselect->clear();
u32 class_name = classdb->GetFieldId("name");
u32 race_classmask = racedb->GetFieldId("classmask");
u32 classmask = racedb->GetInt(racemap[raceselect->getSelected()],race_classmask);
for(u32 i=1;i<=classdb->GetRowsCount();i++)
{
if(classmask & 1<<i)//if class is in classmask, put it into the list
{
core::stringw name = classdb->GetString(i,class_name);
classmap[classselect->addItem(name.c_str())]=i;
}
}
}
}
}
if(eventrecv->buttons & BUTTON_ENTER_WORLD && !realmwin && !newcharwin)
{
logdebug("GUI: SceneCharSelect: Entering world");
WorldSession *ws = instance->GetWSession();
if(ws)
{
u32 selected = charlistbox->getSelected();
if(selected < ws->GetCharsCount())
{
ws->EnterWorldWithCharacter(ws->GetCharFromList(selected).p._name);
}
else
logerror("Character selection out of bounds! (%u)",selected);
}
else
logerror("GUI: BUTTON_ENTER_ WORLD pressed, but no WorldSession exists!");
}
if(eventrecv->buttons & BUTTON_BACK && !realmwin && !newcharwin) // cant cancel with any window open (important for ESC key handling)
{
logdebug("GUI: SceneCharSelect: Back to Loginscreen");
gui->SetSceneState(SCENESTATE_LOGINSCREEN);
// disconnect from realm server if connected
if(RealmSession *rs = instance->GetRSession())
rs->SetMustDie();
if(WorldSession *ws = instance->GetWSession())
ws->SetMustDie();
}
if(eventrecv->buttons & BUTTON_DELETE_CHARACTER)
{
guienv->addMessageBox(L"Not yet implemented!", L"Deleting a character does not yet work!");
}
if(eventrecv->buttons & BUTTON_NEW_CHARACTER)
{
dimension2d<s32> dim;
rect<s32> pos;
newcharwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true,
GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_NEWCHARWIN).c_str());
pos = newcharwin->getAbsolutePosition(); // get absolute position and transform <dim> to absolute in-window position
dim.Width = pos.LowerRightCorner.X - pos.UpperLeftCorner.X;
dim.Height = pos.LowerRightCorner.Y - pos.UpperLeftCorner.Y;
newcharwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.7f, 0.93f, 0.12f, 0.05f), newcharwin, BUTTON_NEWCHARWIN_OK,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_NEWCHARWIN_OK).c_str()));
newcharwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.85f, 0.93f, 0.12f, 0.05f), newcharwin, BUTTON_NEWCHARWIN_CANCEL,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_NEWCHARWIN_CANCEL).c_str()));
raceselect = guienv->addComboBox(CalcRelativeScreenPos(dim, 0.1f,0.1f,0.8f,0.05f), newcharwin);
u32 race_name = racedb->GetFieldId("name");
u32 race_classmask = racedb->GetFieldId("classmask");
for(u32 i=1;i<=racedb->GetRowsCount();i++)
{
if(racedb->GetUint32(i,race_classmask)) //If the race has a classmask, it is playable
{
core::stringw name = racedb->GetString(i,race_name);
racemap[raceselect->addItem(name.c_str())] = i;
}
}
newcharwin->addChild(raceselect);
classselect = guienv->addComboBox(CalcRelativeScreenPos(dim, 0.1f,0.2f,0.8f,0.05f), newcharwin);
//newcharwin->addChild(classselect);
guienv->addStaticText(L"Char Name", CalcRelativeScreenPos(dim,0.1f,0.3f,0.8f,0.05f),false,true,newcharwin);
charname = guienv->addEditBox(L"", CalcRelativeScreenPos(dim,0.1f,0.35f,0.8f,0.05f),true, newcharwin);
//guienv->addMessageBox(L"Not yet implemented!", L"Creating a new character does not yet work!");
}
if(eventrecv->buttons & BUTTON_SELECT_REALM || scenedata[ISCENE_CHARSEL_REALMFIRST])
{
scenedata[ISCENE_CHARSEL_REALMFIRST] = 0;
if(instance->GetRSession())
{
dimension2d<s32> dim;
rect<s32> pos;
realmwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true,
GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_REALMWIN).c_str());
pos = realmwin->getAbsolutePosition(); // get absolute position and transform <dim> to absolute in-window position
dim.Width = pos.LowerRightCorner.X - pos.UpperLeftCorner.X;
dim.Height = pos.LowerRightCorner.Y - pos.UpperLeftCorner.Y;
realmwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.7f, 0.93f, 0.12f, 0.05f), realmwin, BUTTON_REALMWIN_OK,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_OK).c_str()));
realmwin->addChild(guienv->addButton(CalcRelativeScreenPos(dim, 0.85f, 0.93f, 0.12f, 0.05f), realmwin, BUTTON_REALMWIN_CANCEL,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_CANCEL).c_str()));
realmlistbox = guienv->addListBox(CalcRelativeScreenPos(dim, 0.1f, 0.1f, 0.8f, 0.8f), realmwin);
realmwin->addChild(realmlistbox);
mutex.acquire();
RealmSession *rs = instance->GetRSession();
for(uint32 i = 0; i < rs->GetRealmCount(); i++)
{
SRealmInfo& r = rs->GetRealm(i);
core::stringw entry;
entry += r.name.c_str();
entry += L", ";
switch(r.icon) // icon means here RealmType
{
case 0: entry += "Normal"; break;
case 1: entry += "PvP"; break;
case 4: entry += "Normal(4)"; break;
case 6: entry += "RP"; break;
case 8: entry += "RP-PvP"; break;
case 16: entry += "FFA-PvP"; break; // MaNGOS custom realm type
default: entry += "Unknown"; break;
}
entry += L", (";
entry += r.chars_here;
entry += L") Chars";
entry += L" [";
entry += r.addr_port.c_str();
entry += L"]";
realmlistbox->addItem(entry.c_str(), -1);
SColor col;
switch(r.color)
{
case 0: col.set(0xFF, 0x00, 0xFF, 0x00); break;
case 1: col.set(0xFF, 0xFF, 0x00, 0x00); break;
case 2: col.set(0xFF, 0x7F, 0x7F, 0x7F); break;
case 3: col.set(0xFF, 0xB0, 0xB0, 0x00); break;
default: col.set(0xFFFFFFFF);
}
realmlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col);
realmlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col);
}
if(realmlistbox->getItemCount())
realmlistbox->setSelected(0);
mutex.release();
}
else
{
guienv->addMessageBox(L"Not yet implemented!", L"This action is not yet supported.\nYou can change the realm only while still connected to the realm server.");
}
}
if(eventrecv->buttons & BUTTON_REALMWIN_OK && realmwin)
{
RealmSession *rs = instance->GetRSession();
if(rs)
{
u32 selected = realmlistbox->getSelected();
if(selected < rs->GetRealmCount())
{
rs->SetRealmAddr(rs->GetRealm(selected).addr_port);
instance->CreateWorldSession();
eventrecv->buttons |= BUTTON_REALMWIN_CANCEL; // easiest way to close the window without much additional code
}
else
logerror("Realmlist selection out of bounds! (%u)",selected);
}
}
if(eventrecv->buttons & BUTTON_NEWCHARWIN_OK && newcharwin)
{
core::stringc tmp=charname->getText();
u8 race = racemap[raceselect->getSelected()];
u8 cclass = classmap[classselect->getSelected()];
log("Creating character Race %i Class %i Name %s",race,cclass,tmp.c_str());
if(tmp.size() && race && cclass)
{
WorldSession *ws=instance->GetWSession();
if(ws)
{
WorldPacket packet(CMSG_CHAR_CREATE,(tmp.size()+1)+1+1+1+1+1+1+1+1+1);
packet<<tmp.c_str();
// name, race, class, gender, skin, face, hairstyle, haircolor, facialhair, outfitID
packet << race << cclass <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0 <<(u8)0;
ws->AddSendWorldPacket(packet);
eventrecv->buttons |= BUTTON_NEWCHARWIN_CANCEL; // easiest way to close the window without much additional code
}
else
logerror("Trying to create new Character, but no WorldSession exists.");
}
else
logerror("Race, Class or Name not set!");
}
// realmlist window
if(eventrecv->buttons & BUTTON_REALMWIN_CANCEL && realmwin)
{
realmwin->remove();
realmwin=NULL;
}
// new character window
if(eventrecv->buttons & BUTTON_NEWCHARWIN_CANCEL && newcharwin)
{
newcharwin->remove();
newcharwin=NULL;
}
eventrecv->buttons = 0;
}
void SceneCharSelection::OnDelete(void)
{
}
void SceneCharSelection::OnResize(void)
{
//TODO: Handle Resizes correctly. This goes for the loginscreen as well
}

View File

@ -62,11 +62,14 @@ enum SceneCharSelectButtons
DSCENE_CHARSEL_BUTTON_BACK = 4,
DSCENE_CHARSEL_REALMWIN_OK = 5,
DSCENE_CHARSEL_REALMWIN_CANCEL = 6,
DSCENE_CHARSEL_NEWCHARWIN_OK = 7,
DSCENE_CHARSEL_NEWCHARWIN_CANCEL = 8,
};
enum SceneCharSelectLabels
{
DSCENE_CHARSEL_LABEL_REALMWIN = 0,
DSCENE_CHARSEL_LABEL_NEWCHARWIN = 1,
};

View File

@ -577,17 +577,19 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
PlayerEnum plr[10]; // max characters per realm is 10
uint8 dummy8;
uint32 dummy32;
bool char_found;
_charList.clear();
recvPacket >> num;
if(num==0)
{
logerror("No chars found!");
GetInstance()->SetError();
return;
logdetail("No chars found!");
char_found = false;
//GetInstance()->SetError();
//return;
}
else
{
logdetail("Chars in list: %u",num);
_LoadCache(); // we are about to login, so we need cache data
// TODO: load cache on loadingscreen
@ -623,7 +625,7 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
plrNameCache.AddInfo(plr[i]._guid, plr[i]._name); // TODO: set after loadingscreen, after loading cache
}
bool char_found=false;
char_found=false;
SCPDatabase *zonedb = GetDBMgr().GetDB("zone"),
*racedb = GetDBMgr().GetDB("race"),
@ -667,13 +669,14 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
if(plr[i]._items[inv].displayId)
logdebug("-> Has Item: Model=%u InventoryType=%u",plr[i]._items[inv].displayId,plr[i]._items[inv].inventorytype);
}
if(plr[i]._name==GetInstance()->GetConf()->charname || num == 1)
if(plr[i]._name==GetInstance()->GetConf()->charname)
{
charId = i;
char_found=true;
}
}
}
if(!char_found)
{
if(PseuGUI *gui = GetInstance()->GetGUI())

View File

@ -427,6 +427,16 @@ static const char *GameObjectDisplayInfoFormat = {
};
// GameObjectDisplayInfo
enum ChrBaseInfoEnum
{
CBI_RACE = 0,
CBI_CLASS = 1,
CBI_END = 2
};
#endif

View File

@ -187,6 +187,14 @@ std::string AutoGetDataString(DBCFile::Iterator& it, const char* format, uint32
s << (*it).getFloat(field);
return s.str();
}
else if(format[field]=='c')
{
if((*it).getUChar(field) == 0 && skip_null)
return ""; // do not explicitly write float fields that are 0
std::stringstream s;
s << (int)(*it).getUChar(field);
return s.str();
}
else if(format[field]=='s' && (*it).getUInt(field))
{
return (*it).getString(field);
@ -254,10 +262,11 @@ void OutMD5(char *path, MD5FileMap& fm)
bool ConvertDBC(void)
{
std::map<uint8,std::string> racemap; // needed to extract other dbc files correctly
std::map<uint8,uint32> classmask; //from CharBaseInfo.dbc
SCPStorageMap EmoteDataStorage,RaceDataStorage,SoundDataStorage,MapDataStorage,ZoneDataStorage,ItemDisplayInfoStorage,
CreatureModelStorage,CreatureDisplayInfoStorage,NPCSoundStorage,CharSectionStorage, GameObjectDisplayInfoStorage; // will store the converted data from dbc files
CreatureModelStorage,CreatureDisplayInfoStorage,NPCSoundStorage,CharSectionStorage, GameObjectDisplayInfoStorage, ChrBaseInfoStorage; // will store the converted data from dbc files
DBCFile EmotesText,EmotesTextData,EmotesTextSound,ChrRaces,SoundEntries,Map,AreaTable,ItemDisplayInfo,
CreatureModelData,CreatureDisplayInfo,NPCSounds,CharSections,GameObjectDisplayInfo;
CreatureModelData,CreatureDisplayInfo,NPCSounds,CharSections,GameObjectDisplayInfo, ChrBaseInfo;
printf("Opening DBC archive...\n");
MPQHelper mpq("dbc");
@ -275,10 +284,20 @@ bool ConvertDBC(void)
GameObjectDisplayInfo.openmem(mpq.ExtractFile("DBFilesClient\\GameObjectDisplayInfo.dbc"));
NPCSounds.openmem(mpq.ExtractFile("DBFilesClient\\NPCSounds.dbc"));
CharSections.openmem(mpq.ExtractFile("DBFilesClient\\CharSections.dbc"));
ChrBaseInfo.openmem(mpq.ExtractFile("DBFilesClient\\CharBaseInfo.dbc"));
//...
printf("DBC files opened.\n");
//...
printf("Reading data: races..");
printf("Reading data: chrbaseinfo..");
for(DBCFile::Iterator it = ChrBaseInfo.begin(); it != ChrBaseInfo.end(); ++it)
{
uint32 race = (uint32)(*it).getUChar(CBI_RACE);
uint32 cclass = (uint32)(*it).getUChar(CBI_CLASS);
classmask[race] |= 1<<cclass;
}
printf("races..");
for(DBCFile::Iterator it = ChrRaces.begin(); it != ChrRaces.end(); ++it)
{
uint32 id = (*it).getUInt(CHRRACES_RACEID);
@ -292,6 +311,9 @@ bool ConvertDBC(void)
RaceDataStorage[id].push_back(std::string(ChrRacesFieldNames[field]).append("=").append(value));
}
}
std::stringstream temp;
temp << classmask[id];
RaceDataStorage[id].push_back(std::string("classmask").append("=").append(temp.str()));
}
printf("emotes..");
@ -562,7 +584,6 @@ bool ConvertDBC(void)
}
//...
printf("DONE!\n");
//...

View File

@ -76,7 +76,8 @@ bool DBCFile::openmem(ByteBuffer bb)
if(fieldCount*4 != recordSize)
{
return false;
printf("DBCFile::openmem():Nonstandard record size\n");
// return false;//records in CharBaseData are 2*1byte
}
data = new unsigned char[recordSize*recordCount+stringSize];

View File

@ -54,6 +54,11 @@ public:
assert(field < file.fieldCount);
return *reinterpret_cast<int*>(offset+field*4);
}
unsigned char getUChar(size_t field) const
{
assert(field < file.fieldCount);
return *reinterpret_cast<unsigned char*>(offset+field);
}
const char *getString(size_t field) const
{
assert(field < file.fieldCount);