diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 52e3ea042..209befb8a 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1211,7 +1211,13 @@ void PressChar(int vkey) } return; case 'v': - NetSendCmdString(1 << myplr, gszProductName); + char *difficulties[3]; + char pszStr[120]; + difficulties[0] = "Normal"; + difficulties[1] = "Nightmare"; + difficulties[2] = "Hell"; + sprintf(pszStr, "%s, mode = %s", gszProductName, difficulties[gnDifficulty]); + NetSendCmdString(1 << myplr, pszStr); return; case 'V': NetSendCmdString(1 << myplr, gszVersionNumber); diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index cf4e8d73f..ad0ff4e30 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -46,6 +46,10 @@ void LoadGame(BOOL firstflag) LoadPlayer(myplr); + gnDifficulty = plr[myplr].pDifficulty; + if (gnDifficulty < DIFF_NORMAL || gnDifficulty > DIFF_HELL) + gnDifficulty = DIFF_NORMAL; + for (i = 0; i < MAXQUESTS; i++) LoadQuest(i); for (i = 0; i < MAXPORTAL; i++) @@ -276,6 +280,7 @@ void CopyInt64(const void *src, void *dst) void LoadPlayer(int i) { PlayerStruct *pPlayer = &plr[i]; + char tempChar; CopyInt(tbuff, &pPlayer->_pmode); CopyBytes(tbuff, MAX_PATH_LENGTH, pPlayer->walkpath); @@ -443,7 +448,9 @@ void LoadPlayer(int i) CopyInt(tbuff, &pPlayer->_pIGetHit); CopyChar(tbuff, &pPlayer->_pISplLvlAdd); CopyChar(tbuff, &pPlayer->_pISplCost); - tbuff += 2; // Alignment + CopyChar(tbuff, &tempChar); + pPlayer->pDifficulty = tempChar & 3; // Use 2 alignment bits for difficulty + tbuff += 1; // Alignment CopyInt(tbuff, &pPlayer->_pISplDur); CopyInt(tbuff, &pPlayer->_pIEnAc); CopyInt(tbuff, &pPlayer->_pIFMinDam); @@ -857,6 +864,7 @@ void SaveGame() WSave(gnLevelTypeTbl[i]); } + plr[myplr].pDifficulty = gnDifficulty; SavePlayer(myplr); for (i = 0; i < MAXQUESTS; i++) @@ -1004,6 +1012,7 @@ void OSave(BOOL v) void SavePlayer(int i) { PlayerStruct *pPlayer = &plr[i]; + char tempChar; CopyInt(&pPlayer->_pmode, tbuff); CopyBytes(&pPlayer->walkpath, MAX_PATH_LENGTH, tbuff); @@ -1169,7 +1178,9 @@ void SavePlayer(int i) CopyChar(&pPlayer->_pISplLvlAdd, tbuff); CopyChar(&pPlayer->_pISplCost, tbuff); - tbuff += 2; // Alignment + tempChar = pPlayer->pDifficulty & 3; // Use 2 alignment bits for difficulty + CopyChar(&tempChar, tbuff); + tbuff += 1; // Alignment CopyInt(&pPlayer->_pISplDur, tbuff); CopyInt(&pPlayer->_pIEnAc, tbuff); CopyInt(&pPlayer->_pIFMinDam, tbuff); diff --git a/Source/mainmenu.cpp b/Source/mainmenu.cpp index ce2231383..5a8e0330c 100644 --- a/Source/mainmenu.cpp +++ b/Source/mainmenu.cpp @@ -56,6 +56,7 @@ BOOL mainmenu_select_hero_dialog( gszHero, &gnDifficulty)) app_fatal("Unable to display SelHeroSing"); + client_info->initdata->bDiff = gnDifficulty; if (dlgresult == SELHERO_CONTINUE) gbLoadGame = TRUE; diff --git a/SourceX/DiabloUI/selgame.cpp b/SourceX/DiabloUI/selgame.cpp index 2de0bd1f1..ccbdf2253 100644 --- a/SourceX/DiabloUI/selgame.cpp +++ b/SourceX/DiabloUI/selgame.cpp @@ -6,6 +6,7 @@ #include "DiabloUI/text.h" #include "DiabloUI/dialogs.h" #include "DiabloUI/selok.h" +#include "DiabloUI/selhero.h" namespace dvl { @@ -235,13 +236,18 @@ bool IsDifficultyAllowed(int value) void selgame_Diff_Select(int value) { - if (!IsDifficultyAllowed(value)) { + if (selhero_isMultiPlayer && !IsDifficultyAllowed(value)) { selgame_GameSelection_Select(0); return; } gbDifficulty = value; + if (!selhero_isMultiPlayer) { + selhero_endMenu = true; + return; + } + if (provider == SELCONN_LOOPBACK) { selgame_Password_Select(0); return; @@ -252,6 +258,14 @@ void selgame_Diff_Select(int value) void selgame_Diff_Esc() { + if (!selhero_isMultiPlayer) { + selgame_Free(); + + selhero_Init(); + selhero_List_Init(); + return; + } + if (provider == SELCONN_LOOPBACK) { selgame_GameSelection_Esc(); return; diff --git a/SourceX/DiabloUI/selgame.h b/SourceX/DiabloUI/selgame.h index 6d175b16b..715080ad1 100644 --- a/SourceX/DiabloUI/selgame.h +++ b/SourceX/DiabloUI/selgame.h @@ -2,6 +2,8 @@ namespace dvl { +extern int gbDifficulty; + void selgame_GameSelection_Init(); void selgame_GameSelection_Focus(int value); void selgame_GameSelection_Select(int value); diff --git a/SourceX/DiabloUI/selhero.cpp b/SourceX/DiabloUI/selhero.cpp index be096d8d6..0394e5592 100644 --- a/SourceX/DiabloUI/selhero.cpp +++ b/SourceX/DiabloUI/selhero.cpp @@ -11,6 +11,7 @@ #include "DiabloUI/scrollbar.h" #include "DiabloUI/selyesno.h" #include "DiabloUI/selok.h" +#include "DiabloUI/selgame.h" namespace dvl { @@ -132,6 +133,50 @@ void selhero_ScrollIntoView(std::size_t index) } // namespace +void selhero_Init() +{ + LoadBackgroundArt("ui_art\\selhero.pcx"); + UiAddBackground(&vecSelHeroDialog); + UiAddLogo(&vecSelHeroDialog); + LoadScrollBar(); + + selhero_FreeDlgItems(); + SDL_Rect rect1 = { PANEL_LEFT + 24, 161, 590, 35 }; + vecSelHeroDialog.push_back(new UiArtText(title, rect1, UIS_CENTER | UIS_BIG)); + + SDL_Rect rect2 = { PANEL_LEFT + 30, 211, 180, 76 }; + SELHERO_DIALOG_HERO_IMG = new UiImage(&ArtHero, UI_NUM_CLASSES, rect2); + vecSelHeroDialog.push_back(SELHERO_DIALOG_HERO_IMG); + + SDL_Rect rect3 = { PANEL_LEFT + 39, 323, 110, 21 }; + vecSelHeroDialog.push_back(new UiArtText("Level:", rect3, UIS_RIGHT)); + + SDL_Rect rect4 = { PANEL_LEFT + 39, 323, 110, 21 }; + vecSelHeroDialog.push_back(new UiArtText("Level:", rect4, UIS_RIGHT)); + SDL_Rect rect5 = { PANEL_LEFT + 159, 323, 40, 21 }; + vecSelHeroDialog.push_back(new UiArtText(textStats[0], rect5, UIS_CENTER)); + + SDL_Rect rect6 = { PANEL_LEFT + 39, 358, 110, 21 }; + vecSelHeroDialog.push_back(new UiArtText("Strength:", rect6, UIS_RIGHT)); + SDL_Rect rect7 = { PANEL_LEFT + 159, 358, 40, 21 }; + vecSelHeroDialog.push_back(new UiArtText(textStats[1], rect7, UIS_CENTER)); + + SDL_Rect rect8 = { PANEL_LEFT + 39, 380, 110, 21 }; + vecSelHeroDialog.push_back(new UiArtText("Magic:", rect8, UIS_RIGHT)); + SDL_Rect rect9 = { PANEL_LEFT + 159, 380, 40, 21 }; + vecSelHeroDialog.push_back(new UiArtText(textStats[2], rect9, UIS_CENTER)); + + SDL_Rect rect10 = { PANEL_LEFT + 39, 401, 110, 21 }; + vecSelHeroDialog.push_back(new UiArtText("Dexterity:", rect10, UIS_RIGHT)); + SDL_Rect rect11 = { PANEL_LEFT + 159, 401, 40, 21 }; + vecSelHeroDialog.push_back(new UiArtText(textStats[3], rect11, UIS_CENTER)); + + SDL_Rect rect12 = { PANEL_LEFT + 39, 422, 110, 21 }; + vecSelHeroDialog.push_back(new UiArtText("Vitality:", rect12, UIS_RIGHT)); + SDL_Rect rect13 = { PANEL_LEFT + 159, 422, 40, 21 }; + vecSelHeroDialog.push_back(new UiArtText(textStats[4], rect13, UIS_CENTER)); +} + void selhero_List_Init() { listOffset = 0; @@ -253,8 +298,7 @@ void selhero_List_Select(int value) return; } - UiInitList_clear(); - selhero_endMenu = true; + selhero_Load_Select(1); } void selhero_List_Esc() @@ -349,8 +393,7 @@ void selhero_Name_Select(int value) if (overwrite) { if (gfnHeroCreate(&selhero_heroInfo)) { - UiInitList_clear(); - selhero_endMenu = true; + selhero_Load_Select(1); return; } else { UiErrorOkDialog("Unable to create character.", vecSelDlgItems); @@ -381,6 +424,11 @@ void selhero_Load_Select(int value) if (value == 0) { selhero_result = SELHERO_CONTINUE; return; + } else if (!selhero_isMultiPlayer) { + selhero_endMenu = false; + selhero_Free(); + LoadBackgroundArt("ui_art\\selgame.pcx"); + selgame_GameSelection_Select(0); } selhero_result = 0; @@ -405,46 +453,7 @@ BOOL UiSelHeroDialog( bUIElementsLoaded = true; do { - LoadBackgroundArt("ui_art\\selhero.pcx"); - UiAddBackground(&vecSelHeroDialog); - UiAddLogo(&vecSelHeroDialog); - LoadScrollBar(); - - selhero_FreeDlgItems(); - SDL_Rect rect1 = { PANEL_LEFT + 24, 161, 590, 35 }; - vecSelHeroDialog.push_back(new UiArtText(title, rect1, UIS_CENTER | UIS_BIG)); - - SDL_Rect rect2 = { PANEL_LEFT + 30, 211, 180, 76 }; - SELHERO_DIALOG_HERO_IMG = new UiImage(&ArtHero, UI_NUM_CLASSES, rect2); - vecSelHeroDialog.push_back(SELHERO_DIALOG_HERO_IMG); - - SDL_Rect rect3 = { PANEL_LEFT + 39, 323, 110, 21 }; - vecSelHeroDialog.push_back(new UiArtText("Level:", rect3, UIS_RIGHT)); - - SDL_Rect rect4 = { PANEL_LEFT + 39, 323, 110, 21 }; - vecSelHeroDialog.push_back(new UiArtText("Level:", rect4, UIS_RIGHT)); - SDL_Rect rect5 = { PANEL_LEFT + 159, 323, 40, 21 }; - vecSelHeroDialog.push_back(new UiArtText(textStats[0], rect5, UIS_CENTER)); - - SDL_Rect rect6 = { PANEL_LEFT + 39, 358, 110, 21 }; - vecSelHeroDialog.push_back(new UiArtText("Strength:", rect6, UIS_RIGHT)); - SDL_Rect rect7 = { PANEL_LEFT + 159, 358, 40, 21 }; - vecSelHeroDialog.push_back(new UiArtText(textStats[1], rect7, UIS_CENTER)); - - SDL_Rect rect8 = { PANEL_LEFT + 39, 380, 110, 21 }; - vecSelHeroDialog.push_back(new UiArtText("Magic:", rect8, UIS_RIGHT)); - SDL_Rect rect9 = { PANEL_LEFT + 159, 380, 40, 21 }; - vecSelHeroDialog.push_back(new UiArtText(textStats[2], rect9, UIS_CENTER)); - - SDL_Rect rect10 = { PANEL_LEFT + 39, 401, 110, 21 }; - vecSelHeroDialog.push_back(new UiArtText("Dexterity:", rect10, UIS_RIGHT)); - SDL_Rect rect11 = { PANEL_LEFT + 159, 401, 40, 21 }; - vecSelHeroDialog.push_back(new UiArtText(textStats[3], rect11, UIS_CENTER)); - - SDL_Rect rect12 = { PANEL_LEFT + 39, 422, 110, 21 }; - vecSelHeroDialog.push_back(new UiArtText("Vitality:", rect12, UIS_RIGHT)); - SDL_Rect rect13 = { PANEL_LEFT + 159, 422, 40, 21 }; - vecSelHeroDialog.push_back(new UiArtText(textStats[4], rect13, UIS_CENTER)); + selhero_Init(); gfnHeroInfo = fninfo; gfnHeroCreate = fncreate; @@ -503,7 +512,9 @@ BOOL UiSelHeroSingDialog( int *difficulty) { selhero_isMultiPlayer = false; - return UiSelHeroDialog(fninfo, fncreate, fnstats, fnremove, dlgresult, name); + BOOL success = UiSelHeroDialog(fninfo, fncreate, fnstats, fnremove, dlgresult, name); + *difficulty = gbDifficulty; + return success; } BOOL UiSelHeroMultDialog( diff --git a/SourceX/DiabloUI/selhero.h b/SourceX/DiabloUI/selhero.h index 33d77bcf1..ad6584c1e 100644 --- a/SourceX/DiabloUI/selhero.h +++ b/SourceX/DiabloUI/selhero.h @@ -4,6 +4,10 @@ namespace dvl { +extern bool selhero_isMultiPlayer; +extern bool selhero_endMenu; + +void selhero_Init(); void selhero_List_Init(); void selhero_List_Focus(int value); void selhero_List_Select(int value); diff --git a/structs.h b/structs.h index 65d08a729..d345d2226 100644 --- a/structs.h +++ b/structs.h @@ -345,6 +345,7 @@ typedef struct PlayerStruct { char bReserved[3]; short wReserved[8]; DWORD pDiabloKillLevel; + int pDifficulty; int dwReserved[7]; unsigned char *_pNData; unsigned char *_pWData;