* 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 4=Back
5=OK 5=OK
6=Cancel 6=Cancel
7=Create
8=Cancel
[2] [2]
0=Realmlist 0=Realmlist
1=Create New Character

View File

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

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ protected:
CCursorController *cursor; CCursorController *cursor;
SceneState _scenestate; SceneState _scenestate;
uint32 scenedata[SCENEDATA_SIZE]; // generic storage for anything the PseuInstance thread wants to tell us uint32 scenedata[SCENEDATA_SIZE]; // generic storage for anything the PseuInstance thread wants to tell us
SCPDatabase *textdb; SCPDatabase *textdb, *racedb, *classdb;
ZThread::FastMutex mutex; ZThread::FastMutex mutex;
}; };
@ -107,6 +107,12 @@ private:
IGUIWindow *realmwin; IGUIWindow *realmwin;
IGUIListBox *realmlistbox; IGUIListBox *realmlistbox;
IGUIListBox *charlistbox; // temporary until something better found 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,21 +15,80 @@ enum GuiElementID
BUTTON_SELECT_REALM = 0x10, BUTTON_SELECT_REALM = 0x10,
BUTTON_REALMWIN_OK = 0x20, BUTTON_REALMWIN_OK = 0x20,
BUTTON_REALMWIN_CANCEL = 0x40, BUTTON_REALMWIN_CANCEL = 0x40,
BUTTON_NEWCHARWIN_OK = 0x80,
BUTTON_NEWCHARWIN_CANCEL = 0x100,
}; };
SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui) SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui)
{ {
realmwin = NULL;
newcharwin = NULL;
textdb = instance->dbmgr.GetDB("gui_charselect_text"); textdb = instance->dbmgr.GetDB("gui_charselect_text");
racedb = instance->dbmgr.GetDB("race");
classdb = instance->dbmgr.GetDB("class");
eventrecv = new GUIEventReceiver(); eventrecv = new GUIEventReceiver();
device->setEventReceiver(eventrecv); device->setEventReceiver(eventrecv);
eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_BACK | BUTTON_REALMWIN_CANCEL; eventrecv->keyToButtonMap[KEY_ESCAPE] = BUTTON_BACK | BUTTON_REALMWIN_CANCEL | BUTTON_NEWCHARWIN_CANCEL;
eventrecv->keyToButtonMap[KEY_RETURN] = BUTTON_ENTER_WORLD | BUTTON_REALMWIN_OK; eventrecv->keyToButtonMap[KEY_RETURN] = BUTTON_ENTER_WORLD | BUTTON_REALMWIN_OK | BUTTON_NEWCHARWIN_OK;
eventrecv->customHandledEvents.insert(EGET_LISTBOX_SELECTED_AGAIN); eventrecv->customHandledEvents.insert(EGET_LISTBOX_SELECTED_AGAIN);
eventrecv->store_mouse = false; // do not queue mouse input
dimension2d<s32> scrn = driver->getScreenSize(); dimension2d<s32> scrn = driver->getScreenSize();
OnResize(); // call this manually to draw all buttons and stuff 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,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_BACK).c_str());
guienv->addButton(CalcRelativeScreenPos(driver, 0.85f, 0.05f, 0.12f, 0.04f), NULL, BUTTON_SELECT_REALM,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_CHANGEREALM).c_str());
guienv->addButton(CalcRelativeScreenPos(driver, 0.85f, 0.8f, 0.1f, 0.04f), NULL, BUTTON_NEW_CHARACTER,
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());
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)
{
uint32 ffaction = racedb->GetFieldId("faction");
for(uint32 i = 0; i < ws->GetCharsCount(); i++)
{
CharacterListExt& c = ws->GetCharFromList(i);
core::stringw entry;
entry += c.p._name.c_str();
entry += L", ";
entry += L"Level ";
entry += c.p._level;
entry += L" ";
entry += c.race.c_str();
entry += L" ";
entry += c.class_.c_str();
entry += L", ";
entry += c.zone.c_str();
entry += L" (";
entry += c.map_.c_str();
entry += L")";
charlistbox->addItem(entry.c_str());
uint32 faction = racedb->GetInt(c.p._race, ffaction);
SColor col;
switch(faction)
{
case 1: col.set(0xFF, 0xFF, 0x30, 0x30); break;
case 7: col.set(0xFF, 0x30, 0x30, 0xFF); break;
default: col.set(0xFFFFFFFF);
}
charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col);
charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col);
}
}
mutex.release();
if(soundengine) if(soundengine)
{ {
@ -44,23 +103,54 @@ SceneCharSelection::SceneCharSelection(PseuGUI *gui) : Scene(gui)
void SceneCharSelection::OnUpdate(s32 timepassed) void SceneCharSelection::OnUpdate(s32 timepassed)
{ {
// treat doubleclick on listboxes as OK button click // treat doubleclick on listboxes as OK button click
if(!eventrecv->guievent_proc) if(eventrecv->HasGUIEvent())
{ {
eventrecv->guievent_proc = true; SEvent::SGUIEvent& ev = eventrecv->NextGUIEvent();
if(eventrecv->guievent.GUIEvent.EventType == EGET_LISTBOX_SELECTED_AGAIN) if(ev.EventType == EGET_LISTBOX_SELECTED_AGAIN)
{ {
if(eventrecv->guievent.GUIEvent.Caller == realmlistbox) if(ev.Caller == realmlistbox)
{ {
eventrecv->buttons |= BUTTON_REALMWIN_OK; eventrecv->buttons |= BUTTON_REALMWIN_OK;
} }
else if(eventrecv->guievent.GUIEvent.Caller == charlistbox) else if(ev.Caller == charlistbox)
{ {
eventrecv->buttons |= BUTTON_ENTER_WORLD; 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)
}
}
}
if(eventrecv->buttons & BUTTON_ENTER_WORLD && !realmwin && !newcharwin)
{ {
logdebug("GUI: SceneCharSelect: Entering world"); logdebug("GUI: SceneCharSelect: Entering world");
WorldSession *ws = instance->GetWSession(); WorldSession *ws = instance->GetWSession();
@ -77,7 +167,7 @@ void SceneCharSelection::OnUpdate(s32 timepassed)
else else
logerror("GUI: BUTTON_ENTER_ WORLD pressed, but no WorldSession exists!"); 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) if(eventrecv->buttons & BUTTON_BACK && !realmwin && !newcharwin) // cant cancel with any window open (important for ESC key handling)
{ {
logdebug("GUI: SceneCharSelect: Back to Loginscreen"); logdebug("GUI: SceneCharSelect: Back to Loginscreen");
gui->SetSceneState(SCENESTATE_LOGINSCREEN); gui->SetSceneState(SCENESTATE_LOGINSCREEN);
@ -87,99 +177,63 @@ void SceneCharSelection::OnUpdate(s32 timepassed)
if(WorldSession *ws = instance->GetWSession()) if(WorldSession *ws = instance->GetWSession())
ws->SetMustDie(); ws->SetMustDie();
} }
if(eventrecv->buttons & BUTTON_DELETE_CHARACTER) if(eventrecv->buttons & BUTTON_DELETE_CHARACTER)
{ {
guienv->addMessageBox(L"Not yet implemented!", L"Deleting a character does not yet work!"); guienv->addMessageBox(L"Not yet implemented!", L"Deleting a character does not yet work!");
} }
if(eventrecv->buttons & BUTTON_NEW_CHARACTER) if(eventrecv->buttons & BUTTON_NEW_CHARACTER)
{ {
guienv->addMessageBox(L"Not yet implemented!", L"Creating a new character does not yet work!"); dimension2d<s32> dim;
} rect<s32> pos;
if(eventrecv->buttons & BUTTON_SELECT_REALM) 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()) 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,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_BACK).c_str());
guienv->addButton(CalcRelativeScreenPos(driver, 0.85f, 0.05f, 0.12f, 0.04f), NULL, BUTTON_SELECT_REALM,
GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_BUTTON_CHANGEREALM).c_str());
guienv->addButton(CalcRelativeScreenPos(driver, 0.85f, 0.8f, 0.1f, 0.04f), NULL, BUTTON_NEW_CHARACTER,
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; dimension2d<s32> dim;
rect<s32> pos; rect<s32> pos;
realmwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true, realmwin = guienv->addWindow(CalcRelativeScreenPos(driver, 0.2f, 0.2f, 0.6f, 0.6f), true,
GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_REALMWIN).c_str()); GetStringFromDB(ISCENE_CHARSEL_LABELS, DSCENE_CHARSEL_LABEL_REALMWIN).c_str());
pos = realmwin->getAbsolutePosition(); // get absolute position and trandform <dim> to absolute in-window position pos = realmwin->getAbsolutePosition(); // get absolute position and transform <dim> to absolute in-window position
dim.Width = pos.LowerRightCorner.X - pos.UpperLeftCorner.X; dim.Width = pos.LowerRightCorner.X - pos.UpperLeftCorner.X;
dim.Height = pos.LowerRightCorner.Y - pos.UpperLeftCorner.Y; 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, 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())); 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, 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())); GetStringFromDB(ISCENE_CHARSEL_BUTTONS, DSCENE_CHARSEL_REALMWIN_CANCEL).c_str()));
realmlistbox = guienv->addListBox(CalcRelativeScreenPos(dim, 0.1f, 0.1f, 0.8f, 0.8f), realmwin); realmlistbox = guienv->addListBox(CalcRelativeScreenPos(dim, 0.1f, 0.1f, 0.8f, 0.8f), realmwin);
realmwin->addChild(realmlistbox); realmwin->addChild(realmlistbox);
mutex.acquire();
RealmSession *rs = instance->GetRSession(); RealmSession *rs = instance->GetRSession();
for(uint32 i = 0; i < rs->GetRealmCount(); i++) for(uint32 i = 0; i < rs->GetRealmCount(); i++)
@ -219,49 +273,81 @@ void SceneCharSelection::OnResize(void)
} }
if(realmlistbox->getItemCount()) if(realmlistbox->getItemCount())
realmlistbox->setSelected(0); 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);
}
} }
rect<s32> clb_rect = CalcRelativeScreenPos(driver, 0.65f, 0.12f, 0.34f, 0.67f); if(eventrecv->buttons & BUTTON_NEWCHARWIN_OK && newcharwin)
charlistbox = guienv->addListBox(clb_rect); {
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(); WorldSession *ws=instance->GetWSession();
if(ws) if(ws)
{ {
SCPDatabase *racedb = instance->dbmgr.GetDB("race"); WorldPacket packet(CMSG_CHAR_CREATE,(tmp.size()+1)+1+1+1+1+1+1+1+1+1);
uint32 ffaction = racedb->GetFieldId("faction"); packet<<tmp.c_str();
for(uint32 i = 0; i < ws->GetCharsCount(); i++) // 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)
{ {
CharacterListExt& c = ws->GetCharFromList(i); realmwin->remove();
core::stringw entry; realmwin=NULL;
entry += c.p._name.c_str(); }
entry += L", ";
entry += L"Level ";
entry += c.p._level;
entry += "L ";
entry += c.race.c_str();
entry += L" ";
entry += c.class_.c_str();
entry += L", ";
entry += c.zone.c_str();
entry += L" (";
entry += c.map_.c_str();
entry += L")";
charlistbox->addItem(entry.c_str());
uint32 faction = racedb->GetInt(c.p._race, ffaction); // new character window
if(eventrecv->buttons & BUTTON_NEWCHARWIN_CANCEL && newcharwin)
SColor col;
switch(faction)
{ {
case 1: col.set(0xFF, 0xFF, 0x30, 0x30); break; newcharwin->remove();
case 7: col.set(0xFF, 0x30, 0x30, 0xFF); break; newcharwin=NULL;
default: col.set(0xFFFFFFFF);
} }
charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT,col);
charlistbox->setItemOverrideColor(i,EGUI_LBC_TEXT_HIGHLIGHT,col);
eventrecv->buttons = 0;
} }
void SceneCharSelection::OnDelete(void)
{
} }
mutex.release();
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_BUTTON_BACK = 4,
DSCENE_CHARSEL_REALMWIN_OK = 5, DSCENE_CHARSEL_REALMWIN_OK = 5,
DSCENE_CHARSEL_REALMWIN_CANCEL = 6, DSCENE_CHARSEL_REALMWIN_CANCEL = 6,
DSCENE_CHARSEL_NEWCHARWIN_OK = 7,
DSCENE_CHARSEL_NEWCHARWIN_CANCEL = 8,
}; };
enum SceneCharSelectLabels enum SceneCharSelectLabels
{ {
DSCENE_CHARSEL_LABEL_REALMWIN = 0, 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 PlayerEnum plr[10]; // max characters per realm is 10
uint8 dummy8; uint8 dummy8;
uint32 dummy32; uint32 dummy32;
bool char_found;
_charList.clear(); _charList.clear();
recvPacket >> num; recvPacket >> num;
if(num==0) if(num==0)
{ {
logerror("No chars found!"); logdetail("No chars found!");
GetInstance()->SetError(); char_found = false;
return; //GetInstance()->SetError();
//return;
} }
else
{
logdetail("Chars in list: %u",num); logdetail("Chars in list: %u",num);
_LoadCache(); // we are about to login, so we need cache data _LoadCache(); // we are about to login, so we need cache data
// TODO: load cache on loadingscreen // 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 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"), SCPDatabase *zonedb = GetDBMgr().GetDB("zone"),
*racedb = GetDBMgr().GetDB("race"), *racedb = GetDBMgr().GetDB("race"),
@ -667,12 +669,13 @@ void WorldSession::_HandleCharEnumOpcode(WorldPacket& recvPacket)
if(plr[i]._items[inv].displayId) if(plr[i]._items[inv].displayId)
logdebug("-> Has Item: Model=%u InventoryType=%u",plr[i]._items[inv].displayId,plr[i]._items[inv].inventorytype); 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; charId = i;
char_found=true; char_found=true;
} }
}
} }
if(!char_found) if(!char_found)
{ {

View File

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

View File

@ -187,6 +187,14 @@ std::string AutoGetDataString(DBCFile::Iterator& it, const char* format, uint32
s << (*it).getFloat(field); s << (*it).getFloat(field);
return s.str(); 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)) else if(format[field]=='s' && (*it).getUInt(field))
{ {
return (*it).getString(field); return (*it).getString(field);
@ -254,10 +262,11 @@ void OutMD5(char *path, MD5FileMap& fm)
bool ConvertDBC(void) bool ConvertDBC(void)
{ {
std::map<uint8,std::string> racemap; // needed to extract other dbc files correctly 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, 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, 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"); printf("Opening DBC archive...\n");
MPQHelper mpq("dbc"); MPQHelper mpq("dbc");
@ -275,10 +284,20 @@ bool ConvertDBC(void)
GameObjectDisplayInfo.openmem(mpq.ExtractFile("DBFilesClient\\GameObjectDisplayInfo.dbc")); GameObjectDisplayInfo.openmem(mpq.ExtractFile("DBFilesClient\\GameObjectDisplayInfo.dbc"));
NPCSounds.openmem(mpq.ExtractFile("DBFilesClient\\NPCSounds.dbc")); NPCSounds.openmem(mpq.ExtractFile("DBFilesClient\\NPCSounds.dbc"));
CharSections.openmem(mpq.ExtractFile("DBFilesClient\\CharSections.dbc")); CharSections.openmem(mpq.ExtractFile("DBFilesClient\\CharSections.dbc"));
ChrBaseInfo.openmem(mpq.ExtractFile("DBFilesClient\\CharBaseInfo.dbc"));
//... //...
printf("DBC files opened.\n"); 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) for(DBCFile::Iterator it = ChrRaces.begin(); it != ChrRaces.end(); ++it)
{ {
uint32 id = (*it).getUInt(CHRRACES_RACEID); uint32 id = (*it).getUInt(CHRRACES_RACEID);
@ -292,6 +311,9 @@ bool ConvertDBC(void)
RaceDataStorage[id].push_back(std::string(ChrRacesFieldNames[field]).append("=").append(value)); 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.."); printf("emotes..");
@ -562,7 +584,6 @@ bool ConvertDBC(void)
} }
//... //...
printf("DONE!\n"); printf("DONE!\n");
//... //...

View File

@ -76,7 +76,8 @@ bool DBCFile::openmem(ByteBuffer bb)
if(fieldCount*4 != recordSize) 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]; data = new unsigned char[recordSize*recordCount+stringSize];

View File

@ -54,6 +54,11 @@ public:
assert(field < file.fieldCount); assert(field < file.fieldCount);
return *reinterpret_cast<int*>(offset+field*4); 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 const char *getString(size_t field) const
{ {
assert(field < file.fieldCount); assert(field < file.fieldCount);