From aeedc755b55b372bb7ec7027bbdc5f9886fbcc59 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Sun, 27 Jan 2019 06:51:09 +0100 Subject: [PATCH] Implement basic MP menu --- Stub/diabloui.cpp | 454 +++++++++++++++++++++++++++------------------ Stub/miniwin.cpp | 8 +- Stub/sdlrender.cpp | 44 ++++- Stub/sdlrender.h | 1 + Stub/storm.cpp | 3 +- enums.h | 1 + 6 files changed, 330 insertions(+), 181 deletions(-) diff --git a/Stub/diabloui.cpp b/Stub/diabloui.cpp index a42a59e34..f476cf583 100644 --- a/Stub/diabloui.cpp +++ b/Stub/diabloui.cpp @@ -88,7 +88,7 @@ BOOL IsInsideRect(int x, int y, SDL_Rect rect) void InitHiracy() { MenuItem[SINGLEPLAYER_CLASSES] = 3; - MenuItem[MULTIPLAYER_CONNECTIONS] = 4; + MenuItem[MULTIPLAYER_CONNECTIONS] = 3; MenuItem[MULTIPLAYER_LOBBY] = 2; MenuItem[MULTIPLAYER_DIFFICULTY] = 3; MenuItem[MULTIPLAYER_BNET_GATEWAYS] = 3; @@ -96,7 +96,6 @@ void InitHiracy() PreviousItem[SINGLEPLAYER_CLASSES] = SINGLEPLAYER_LOAD; PreviousItem[SINGLEPLAYER_NAME] = SINGLEPLAYER_CLASSES; PreviousItem[MULTIPLAYER_CONNECTIONS] = MAINMENU; - PreviousItem[MULTIPLAYER_LOBBY] = MULTIPLAYER_CONNECTIONS; PreviousItem[MULTIPLAYER_DIFFICULTY] = MULTIPLAYER_LOBBY; PreviousItem[MULTIPLAYER_BNET_GATEWAYS] = MULTIPLAYER_CONNECTIONS; PreviousItem[MULTIPLAYER_ERROR] = MAINMENU; @@ -172,6 +171,7 @@ void UiInitialize() BOOL __stdcall UiMainMenuDialog(char *name, int *pdwResult, void(__stdcall *fnSound)(char *file), int a4) { TitleImageLoaded = false; + SelectedItem = 1; SelectedItemMax = 5; SDL_Event event; int x, y; @@ -234,6 +234,7 @@ BOOL __stdcall UiMainMenuDialog(char *name, int *pdwResult, void(__stdcall *fnSo } break; } + break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { x = event.button.x; @@ -264,8 +265,6 @@ BOOL __stdcall UiMainMenuDialog(char *name, int *pdwResult, void(__stdcall *fnSo } break; case SDL_QUIT: - fnSound("sfx\\items\\titlslct.wav"); - Sleep(250); // Wait for soudn to play *pdwResult = MAINMENU_EXIT_DIABLO; return TRUE; } @@ -293,7 +292,6 @@ BOOL __stdcall UiSelHeroSingDialog( int *difficulty) { TitleImageLoaded = false; - DUMMY(); submenu = SINGLEPLAYER_LOAD; if (!TotalPlayers) { @@ -301,6 +299,7 @@ BOOL __stdcall UiSelHeroSingDialog( submenu = SINGLEPLAYER_CLASSES; } + SelectedItem = 1; SelectedItemMax = MenuItem[submenu]; SDL_Event event; int x, y; @@ -388,6 +387,7 @@ BOOL __stdcall UiSelHeroSingDialog( } break; } + break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { x = event.button.x; @@ -543,6 +543,9 @@ BOOL __stdcall UiSelHeroSingDialog( } } break; + case SDL_QUIT: + SDL_Quit(); + exit(0); } } } @@ -605,204 +608,215 @@ int __stdcall UiProgressDialog(HWND window, char *msg, int a3, void *fnfunc, int UNIMPLEMENTED(); } -BOOL __stdcall UiSelHeroMultDialog(BOOL(__stdcall *fninfo)(BOOL(__stdcall *fninfofunc)(_uiheroinfo *)), - BOOL(__stdcall *fncreate)(_uiheroinfo *), BOOL(__stdcall *fnremove)(_uiheroinfo *), - BOOL(__stdcall *fnstats)(unsigned int, _uidefaultstats *), int *dlgresult, int *hero_is_created, +BOOL __stdcall UiSelHeroMultDialog( + BOOL(__stdcall *fninfo)(BOOL(__stdcall *fninfofunc)(_uiheroinfo *)), + BOOL(__stdcall *fncreate)(_uiheroinfo *), + BOOL(__stdcall *fnremove)(_uiheroinfo *), + BOOL(__stdcall *fnstats)(unsigned int, _uidefaultstats *), + int *dlgresult, + int *hero_is_created, char *name) { + DUMMY(); TitleImageLoaded = false; + submenu = MULTIPLAYER_LOBBY; + + SelectedItem = 1; SelectedItemMax = MenuItem[submenu]; SDL_Event event; int x, y; - switch (submenu) { - case MULTIPLAYER_LOBBY: - DrawPreGameOptions(HeroChosen, 1); - break; - case MULTIPLAYER_DIFFICULTY: - DrawPreGameDifficultySelection(HeroChosen, 1); - break; - } + int done = false; + while (done == false) { + switch (submenu) { + case MULTIPLAYER_LOBBY: + DrawPreGameOptions(HeroChosen, 1); + break; + case MULTIPLAYER_DIFFICULTY: + DrawPreGameDifficultySelection(HeroChosen, 1); + break; + } - if (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_KEYDOWN: - switch (event.key.keysym.sym) { - case SDLK_ESCAPE: - SetMenu(PreviousItem[submenu]); - break; - case SDLK_BACKSPACE: - if (NewHeroNameIndex > 0) { - HeroUndecidedName[NewHeroNameIndex - 1] = 0; - NewHeroNameIndex--; - } - break; - case SDLK_UP: - SelectedItem--; - if (SelectedItem < 1) { - SelectedItem = SelectedItemMax ? SelectedItemMax : 1; - } - effects_play_sound("sfx\\items\\titlemov.wav"); - break; - case SDLK_DOWN: - SelectedItem++; - if (SelectedItem > SelectedItemMax) { - SelectedItem = 1; - } - effects_play_sound("sfx\\items\\titlemov.wav"); - break; - default: - char letter = event.key.keysym.sym; - if (int(letter) > 96 && int(letter) < 123 || int(letter) == 32) + if (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: + if (PreviousItem[submenu]) { + SetMenu(PreviousItem[submenu]); + break; + } - if (NewHeroNameIndex < 17) { - HeroUndecidedName[NewHeroNameIndex] = letter; - NewHeroNameIndex++; + *dlgresult = 4; + return TRUE; + case SDLK_UP: + SelectedItem--; + if (SelectedItem < 1) { + SelectedItem = SelectedItemMax ? SelectedItemMax : 1; } + effects_play_sound("sfx\\items\\titlemov.wav"); + break; + case SDLK_DOWN: + SelectedItem++; + if (SelectedItem > SelectedItemMax) { + SelectedItem = 1; + } + effects_play_sound("sfx\\items\\titlemov.wav"); + break; + case SDLK_RETURN: + case SDLK_KP_ENTER: + case SDLK_SPACE: + switch (submenu) { + case MULTIPLAYER_LOBBY: + SetMenu(MULTIPLAYER_DIFFICULTY); + break; + case MULTIPLAYER_DIFFICULTY: + CreateSinglePlayerChar = 1; + done = true; + break; + } + break; + } break; - } - case SDL_KEYUP: - break; - } + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT) { + x = event.button.x; + y = event.button.y; + printf("X %d , Y %d\n", x, y); - // If a key was pressed - if (event.type == SDL_MOUSEBUTTONDOWN /*&& event.button.clicks == 2*/) { - - if (event.button.button == SDL_BUTTON_LEFT) { - x = event.button.x; - y = event.button.y; - printf("X %d , Y %d\n", x, y); - - int ItemLeft; - int ItemTop; - int ItemHeight; - int ItemWidth; - - int CreateHeroOkBoxX = 330; - int CreateHeroOkBoxY = 441; - int CreateHeroCanBBoxX = 445; - int CreateHeroCanBBoxY = 473; - - SDL_Rect CreateHeroCancelBox; - CreateHeroCancelBox.y = 550; - CreateHeroCancelBox.x = 675; - CreateHeroCancelBox.w = 100; - CreateHeroCancelBox.h = 30; - - clock_t start, end; - double cpu_time_used; - - switch (submenu) { - case 5: - if (timestart == 0) { - start = clock(); - timestart = 1; - } + int ItemLeft; + int ItemTop; + int ItemHeight; + int ItemWidth; - end = clock(); + int CreateHeroOkBoxX = 330; + int CreateHeroOkBoxY = 441; + int CreateHeroCanBBoxX = 445; + int CreateHeroCanBBoxY = 473; - cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; + SDL_Rect CreateHeroCancelBox; + CreateHeroCancelBox.y = 550; + CreateHeroCancelBox.x = 675; + CreateHeroCancelBox.w = 100; + CreateHeroCancelBox.h = 30; - printf("TIEM DELAY %f\n", cpu_time_used); + clock_t start, end; + double cpu_time_used; - SDL_Rect NewGameBox; - NewGameBox.y = 350; - NewGameBox.x = 280; - NewGameBox.w = 300; - NewGameBox.h = 30; + switch (submenu) { + case 5: + if (timestart == 0) { + start = clock(); + timestart = 1; + } - SDL_Rect LoadGameBox; - LoadGameBox.y = 392; - LoadGameBox.x = 280; - LoadGameBox.w = 300; - LoadGameBox.h = 30; - // X450 Y 392 ; - // X 447 Y 428 + end = clock(); - if (cpu_time_used > 0.5 && IsInsideRect(x, y, NewGameBox)) { - printf(" New Game I was hit\n\n\n"); - SetMenu(MULTIPLAYER_DIFFICULTY); - cpu_time_used = 0; - timestart = 0; - start = 0; - } else if (cpu_time_used > 0.5 && IsInsideRect(x, y, LoadGameBox)) { + cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; - printf(" Load Game I was hit\n\n\n"); - break; - } else if (IsInsideRect(x, y, CreateHeroCancelBox)) { - timestart = 0; - cpu_time_used = 0; - start = 0; - end = 0; - cpu_time_used = 0; + printf("TIEM DELAY %f\n", cpu_time_used); - printf("Cancel\n\n\n"); + SDL_Rect NewGameBox; + NewGameBox.y = 350; + NewGameBox.x = 280; + NewGameBox.w = 300; + NewGameBox.h = 30; - SetMenu(SINGLEPLAYER_CLASSES); // TODO skip to main menu if no valid saves - } - break; - case MULTIPLAYER_DIFFICULTY: - if (timestart == 0) { - start = clock(); - timestart = 1; - } + SDL_Rect LoadGameBox; + LoadGameBox.y = 392; + LoadGameBox.x = 280; + LoadGameBox.w = 300; + LoadGameBox.h = 30; + // X450 Y 392 ; + // X 447 Y 428 - end = clock(); - cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; - - // int x = 280; - // int y = 430; - - SDL_Rect NormalSelectBox; - NormalSelectBox.y = 350; - NormalSelectBox.x = 280; - NormalSelectBox.w = 300; - NormalSelectBox.h = 30; - - SDL_Rect NightmareSelectBox; - NightmareSelectBox.y = 392; - NightmareSelectBox.x = 280; - NightmareSelectBox.w = 300; - NightmareSelectBox.h = 30; - // X450 Y 392 ; - - SDL_Rect HellSelectBox; - HellSelectBox.y = 428; - HellSelectBox.x = 280; - HellSelectBox.w = 300; - HellSelectBox.h = 30; - // X 447 Y 428 - - if (cpu_time_used > 0.5 && IsInsideRect(x, y, NormalSelectBox)) { - StartNewGame = 1; - gnDifficulty = DIFF_NORMAL; - break; - } else if (cpu_time_used > 0.5 && IsInsideRect(x, y, NightmareSelectBox)) { - StartNewGame = 1; - gnDifficulty = DIFF_NIGHTMARE; + if (cpu_time_used > 0.5 && IsInsideRect(x, y, NewGameBox)) { + printf(" New Game I was hit\n\n\n"); + SetMenu(MULTIPLAYER_DIFFICULTY); + cpu_time_used = 0; + timestart = 0; + start = 0; + } else if (cpu_time_used > 0.5 && IsInsideRect(x, y, LoadGameBox)) { + + printf(" Load Game I was hit\n\n\n"); + break; + } else if (IsInsideRect(x, y, CreateHeroCancelBox)) { + timestart = 0; + cpu_time_used = 0; + start = 0; + end = 0; + cpu_time_used = 0; + + printf("Cancel\n\n\n"); + + SetMenu(SINGLEPLAYER_CLASSES); // TODO skip to main menu if no valid saves + } break; - } else if (cpu_time_used > 1 && IsInsideRect(x, y, HellSelectBox)) { - gnDifficulty = DIFF_HELL; - StartNewGame = 1; + case MULTIPLAYER_DIFFICULTY: + if (timestart == 0) { + start = clock(); + timestart = 1; + } + + end = clock(); + cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC; + + // int x = 280; + // int y = 430; + + SDL_Rect NormalSelectBox; + NormalSelectBox.y = 350; + NormalSelectBox.x = 280; + NormalSelectBox.w = 300; + NormalSelectBox.h = 30; + + SDL_Rect NightmareSelectBox; + NightmareSelectBox.y = 392; + NightmareSelectBox.x = 280; + NightmareSelectBox.w = 300; + NightmareSelectBox.h = 30; + // X450 Y 392 ; + + SDL_Rect HellSelectBox; + HellSelectBox.y = 428; + HellSelectBox.x = 280; + HellSelectBox.w = 300; + HellSelectBox.h = 30; + // X 447 Y 428 + + if (cpu_time_used > 0.5 && IsInsideRect(x, y, NormalSelectBox)) { + StartNewGame = 1; + gnDifficulty = DIFF_NORMAL; + break; + } else if (cpu_time_used > 0.5 && IsInsideRect(x, y, NightmareSelectBox)) { + StartNewGame = 1; + gnDifficulty = DIFF_NIGHTMARE; + break; + } else if (cpu_time_used > 1 && IsInsideRect(x, y, HellSelectBox)) { + gnDifficulty = DIFF_HELL; + StartNewGame = 1; + break; + } else if (IsInsideRect(x, y, CreateHeroCancelBox)) { + timestart = 0; + cpu_time_used = 0; + start = 0; + end = 0; + cpu_time_used = 0; + + printf("Cancel\n\n\n"); + SetMenu(MULTIPLAYER_LOBBY); + } break; - } else if (IsInsideRect(x, y, CreateHeroCancelBox)) { - timestart = 0; - cpu_time_used = 0; - start = 0; - end = 0; - cpu_time_used = 0; - - printf("Cancel\n\n\n"); - SetMenu(MULTIPLAYER_LOBBY); } - break; } + break; + case SDL_QUIT: + SDL_Quit(); + exit(0); } } } - return TRUE; - hero_infos.clear(); fninfo(&ui_add_hero_info); @@ -897,15 +911,103 @@ BOOL __stdcall UiArtCallback(int game_type, unsigned int art_code, PALETTEENTRY } int __stdcall UiSelectGame(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, - _SNETVERSIONDATA *file_info, int *a6) + _SNETVERSIONDATA *file_info, int *playerId) { - UNIMPLEMENTED(); + DUMMY(); + *playerId = 0; + return 1; } int __stdcall UiSelectProvider(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, _SNETVERSIONDATA *file_info, int *type) { - UNIMPLEMENTED(); + int gameType = 0; + + TitleImageLoaded = false; + SelectedItem = 1; + SelectedItemMax = 3; + SDL_Event event; + int x, y; + int ItemTop = 191; + int ItemHeight = 42; + int ItemWidth = 515; + int ItemLeft = GetCenterOffset(ItemWidth); + + bool done = false; + while (done == false) { + DrawSelMultiConnection(); + if (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_UP: + SelectedItem--; + if (SelectedItem < MAINMENU_SINGLE_PLAYER) { + SelectedItem = SelectedItemMax; + } + effects_play_sound("sfx\\items\\titlemov.wav"); + break; + case SDLK_DOWN: + SelectedItem++; + if (SelectedItem > SelectedItemMax) { + SelectedItem = MAINMENU_SINGLE_PLAYER; + } + effects_play_sound("sfx\\items\\titlemov.wav"); + break; + case SDLK_ESCAPE: + if (PreviousItem[submenu]) { + SetMenu(PreviousItem[submenu]); + break; + } + + return FALSE; + case SDLK_RETURN: + case SDLK_KP_ENTER: + case SDLK_SPACE: + switch (SelectedItem) { + case 1: + effects_play_sound("sfx\\items\\titlslct.wav"); + done = !SNetInitializeProvider('ipc', client_info, user_info, ui_info, file_info); + break; + case 2: + effects_play_sound("sfx\\items\\titlslct.wav"); + done = !SNetInitializeProvider('dial', client_info, user_info, ui_info, file_info); + break; + case 3: + effects_play_sound("sfx\\items\\titlslct.wav"); + done = !SNetInitializeProvider('null', client_info, user_info, ui_info, file_info); + break; + } + break; + } + break; + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT) { + x = event.button.x; + y = event.button.y; + + if (IsInside(x, y, ItemLeft, ItemTop, ItemWidth, ItemHeight)) { + effects_play_sound("sfx\\items\\titlslct.wav"); + done = true; + break; + } else if (IsInside(x, y, ItemLeft, ItemTop + ItemHeight + 1, ItemWidth, ItemHeight)) { + effects_play_sound("sfx\\items\\titlslct.wav"); + break; + } else if (IsInside(x, y, ItemLeft, ItemTop + ItemHeight * 2 + 1, ItemWidth, ItemHeight)) { + effects_play_sound("sfx\\items\\titlslct.wav"); + done = true; + break; + } + } + break; + case SDL_QUIT: + SDL_Quit(); + exit(0); + } + } + } + + return false; } int __stdcall UiCreatePlayerDescription(_uiheroinfo *info, int mode, char *desc) diff --git a/Stub/miniwin.cpp b/Stub/miniwin.cpp index d7f556482..bda10218c 100644 --- a/Stub/miniwin.cpp +++ b/Stub/miniwin.cpp @@ -52,7 +52,8 @@ VOID WINAPI Sleep(DWORD dwMilliseconds) HANDLE WINAPI FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) { - UNIMPLEMENTED(); + DUMMY(); + return (HANDLE)-1; } WINBOOL WINAPI FindClose(HANDLE hFindFile) @@ -62,7 +63,7 @@ WINBOOL WINAPI FindClose(HANDLE hFindFile) UINT WINAPI GetWindowsDirectoryA(LPSTR lpBuffer, UINT uSize) { - UNIMPLEMENTED(); + DUMMY(); } WINBOOL WINAPI GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, @@ -97,7 +98,8 @@ WINBOOL WINAPI CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, WINBOO HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle) { - UNIMPLEMENTED(); + DUMMY(); + return HFILE_ERROR; } HWND WINAPI SetCapture(HWND hWnd) diff --git a/Stub/sdlrender.cpp b/Stub/sdlrender.cpp index e1dbcbbcb..3dd6f10cc 100644 --- a/Stub/sdlrender.cpp +++ b/Stub/sdlrender.cpp @@ -1338,7 +1338,7 @@ void CreateHeroMenu() selectorTop += 1; // "Rouge" and "Sorcerer" has a smaller gap then other items } - DrawSelector(x, selectorTop - 2, w, 39, 26); + DrawSelector(x, selectorTop - 2, w, 39, 33); PrintText30Gold(329, 429, "OK"); PrintText30Gold(451, 429, "Cancel"); @@ -1431,3 +1431,45 @@ void DrawPreGameDifficultySelection(int HeroClass, int ShowClasses) DrawMouse(); SetFadeLevel(256); } + +void DrawSelMultiConnection() +{ + LoadTitelArt("ui_art\\selgame.pcx"); + DrawArtImage(0, 0, gdwTitleWidth, gdwTitleHeight, 0, pPcxTitleImage); + RenderDiabloLogoSm(); + + PrintText30Silver(-1, 161, "Multi Player Game", JustCentre); + + int w = 334; + int x = 280; + int y = 261; + + PrintText30Silver(x, 211, "Select Connection", JustCentre, w); + + char *connections[3] = { "Local Area Network (IPC)", "Modem", "Direct Cable Connection" }; + + int selectorTop = y; + + for (int i = 0; i < 3; i++) { + PrintText16Gold(x - 1, y, connections[i], JustCentre, w); + y += 26; + } + + DrawSelector16(x, selectorTop - 2, w, 35, 26); + + PrintText16Silver(35, 218, "Players Supported: 4"); + + PrintText16Silver(35, 256, "Requirements:"); + // TODO need a word wrap function + PrintText16Silver(35, 275, "All computers must be"); + PrintText16Silver(35, 291, "connected to an"); + PrintText16Silver(35, 307, "IPX-compatible network."); + + PrintText24Silver(26, 356, "no gateway needed", JustCentre, 226); + + PrintText30Gold(349, 429, "OK"); + PrintText30Gold(476, 429, "Cancel"); + + DrawMouse(); + SetFadeLevel(256); +} diff --git a/Stub/sdlrender.h b/Stub/sdlrender.h index 47259a5c8..78e20e537 100644 --- a/Stub/sdlrender.h +++ b/Stub/sdlrender.h @@ -110,6 +110,7 @@ void LoadHeroStats(); void RenderDefaultStats(int HeroClass); void DrawPreGameOptions(int HeroClass, int ShowClasses); void DrawPreGameDifficultySelection(int HeroClass, int ShowClasses); +void DrawSelMultiConnection(); int GetCenterOffset(int w, int bw = 0); void DrawPCXString(int x, int y, int w, int h, BYTE *str, BYTE *font, void *pBuff); void DrawArtWithMask(int SX, int SY, int SW, int SH, int nFrame, BYTE bMask, void *pBuffer); diff --git a/Stub/storm.cpp b/Stub/storm.cpp index 8deacef25..5d5864660 100644 --- a/Stub/storm.cpp +++ b/Stub/storm.cpp @@ -136,7 +136,8 @@ void *STORMAPI SMemReAlloc(void *location, unsigned int amount, char *logfilenam BOOL STORMAPI SRegLoadData(const char *keyname, const char *valuename, int size, LPBYTE lpData, BYTE flags, LPDWORD lpcbData) { - UNIMPLEMENTED(); + DUMMY(); + return 0; } BOOL STORMAPI SRegLoadString(const char *keyname, const char *valuename, BYTE flags, char *buffer, unsigned int buffersize) diff --git a/enums.h b/enums.h index 15caaf240..655750a06 100644 --- a/enums.h +++ b/enums.h @@ -2259,6 +2259,7 @@ typedef enum menus SINGLEPLAYER_CLASSES, SINGLEPLAYER_NAME, MULTIPLAYER_CONNECTIONS, + MULTIPLAYER_CONNECTION, MULTIPLAYER_LOBBY, MULTIPLAYER_DIFFICULTY, MULTIPLAYER_BNET_GATEWAYS,