Browse Source

Implement ui layout framework

pull/25/head
Anders Jenbo 7 years ago
parent
commit
89c2b533cb
  1. 1
      CMakeLists.txt
  2. 1
      Stub/DiabloUI/credits.cpp
  3. 318
      Stub/DiabloUI/diabloui.cpp
  4. 44
      Stub/DiabloUI/dialogs.cpp
  5. 163
      Stub/DiabloUI/mainmenu.cpp
  6. 1
      Stub/DiabloUI/progress.cpp
  7. 79
      Stub/DiabloUI/sdlrender.h
  8. 204
      Stub/DiabloUI/selconn.cpp
  9. 5
      Stub/DiabloUI/selconn.h
  10. 721
      Stub/DiabloUI/selhero.cpp
  11. 3
      Stub/DiabloUI/selhero.h
  12. 18
      Stub/DiabloUI/title.cpp
  13. 9
      enums.h

1
CMakeLists.txt

@ -146,6 +146,7 @@ set(STUB_SOURCES
Stub/dvlnet/base.cpp
Stub/dvlnet/udp_p2p.cpp
Stub/DiabloUI/dialogs.cpp
Stub/DiabloUI/credits.cpp
Stub/DiabloUI/diabloui.cpp
Stub/DiabloUI/mainmenu.cpp

1
Stub/DiabloUI/credits.cpp

@ -537,7 +537,6 @@ BOOL __stdcall UiCreditsDialog(int a1)
SDL_Event event;
while (!endMenu && lineCount > 0) {
CapFPS();
credts_Render();
UiFadeIn();

318
Stub/DiabloUI/diabloui.cpp

@ -1,8 +1,8 @@
#include "../../types.h"
TTF_Font *font;
int SelectedItemMin = 1;
int SelectedItemMax = 1;
int submenu = 0;
BYTE *FontTables[4];
Art ArtFonts[4][2];
Art ArtLogos[3];
@ -12,12 +12,14 @@ Art ArtCursor;
Art ArtHero;
void(__stdcall *gfnSoundFunction)(char *file);
void(__stdcall *gfnListSelect)(int value);
void(__stdcall *gfnListFocus)(int value);
int SCREEN_WIDTH = 640;
int SCREEN_HEIGHT = 480;
int fadeValue = 0;
int SelectedItem = 1;
int SelectedItem = 0;
char *errorTitle[] = {
"Direct Draw Error",
@ -118,71 +120,96 @@ void __cdecl UiDestroy()
font = NULL;
}
void UiFocuse(int itemIndex, bool wrap)
void UiInitList(int min, int max, void(__stdcall *fnFocus)(int value), void(__stdcall *fnSelect)(int value))
{
SelectedItem = itemIndex;
SelectedItem = min;
SelectedItemMin = min;
SelectedItemMax = max;
gfnListFocus = fnFocus;
gfnListSelect = fnSelect;
if (fnFocus)
fnFocus(min);
}
void UiPlayMoveSound()
{
if (gfnSoundFunction)
gfnSoundFunction("sfx\\items\\titlemov.wav");
}
void UiPlaySelectSound() //TODO play this on menu back step
{
if (gfnSoundFunction)
gfnSoundFunction("sfx\\items\\titlslct.wav");
}
void UiFocus(int itemIndex, bool wrap = false)
{
if (!wrap) {
if (SelectedItem < 1) {
SelectedItem = 1;
if (itemIndex < SelectedItemMin) {
itemIndex = SelectedItemMin;
return;
} else if (SelectedItem > SelectedItemMax) {
SelectedItem = SelectedItemMax ?: 1;
} else if (itemIndex > SelectedItemMax) {
itemIndex = SelectedItemMax ?: SelectedItemMin;
return;
}
} else if (SelectedItem < 1) {
SelectedItem = SelectedItemMax ?: 1;
} else if (SelectedItem > SelectedItemMax) {
SelectedItem = 1;
} else if (itemIndex < SelectedItemMin) {
itemIndex = SelectedItemMax ?: SelectedItemMin;
} else if (itemIndex > SelectedItemMax) {
itemIndex = SelectedItemMin;
}
if (SelectedItem == itemIndex)
return;
SelectedItem = itemIndex;
UiPlayMoveSound();
if (gfnListFocus)
gfnListFocus(itemIndex);
}
bool UiFocuseNavigation(SDL_Event *event, bool wrap)
bool UiFocusNavigation(SDL_Event *event, bool wrap)
{
if (event->type != SDL_KEYDOWN) {
return false;
}
switch (event->key.keysym.sym) {
case SDLK_UP:
UiFocuse(SelectedItem - 1, wrap);
UiFocus(SelectedItem - 1, wrap);
return true;
case SDLK_DOWN:
UiFocuse(SelectedItem + 1, wrap);
UiFocus(SelectedItem + 1, wrap);
return true;
case SDLK_TAB:
if (SDL_GetModState() & KMOD_SHIFT)
UiFocuse(SelectedItem - 1, wrap);
UiFocus(SelectedItem - 1, wrap);
else
UiFocuse(SelectedItem + 1, wrap);
UiFocus(SelectedItem + 1, wrap);
return true;
case SDLK_PAGEUP:
SelectedItem = 1;
UiFocus(SelectedItemMin);
return true;
case SDLK_PAGEDOWN:
SelectedItem = SelectedItemMax;
UiFocus(SelectedItemMax);
return true;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
UiFocusNavigationSelect();
break;
}
return false;
}
void SetMenu(int MenuId)
void UiFocusNavigationSelect()
{
UiPlaySelectSound();
submenu = MenuId;
SelectedItem = 1;
switch (MenuId) {
case SELHERO_CLASSES:
case SELHERO_DIFFICULTY:
SelectedItemMax = 3;
break;
case SELHERO_SELECT_GAME:
SelectedItemMax = 2;
break;
default:
SelectedItemMax = 1;
break;
}
if (gfnListSelect)
gfnListSelect(SelectedItem);
}
bool IsInsideRect(const SDL_Event *event, const SDL_Rect *rect)
@ -356,18 +383,6 @@ BOOL __stdcall UiSoundCallback(int a1, int type, int a3)
UNIMPLEMENTED();
}
void UiPlayMoveSound()
{
if (gfnSoundFunction)
gfnSoundFunction("sfx\\items\\titlemov.wav");
}
void UiPlaySelectSound()
{
if (gfnSoundFunction)
gfnSoundFunction("sfx\\items\\titlslct.wav");
}
void __stdcall UiMessageBoxCallback(HWND hWnd, char *lpText, LPCSTR lpCaption, UINT uType)
{
UNIMPLEMENTED();
@ -434,7 +449,7 @@ void DrawArt(int screenX, int screenY, Art *art, int nFrame, int drawW)
}
}
int GetCenterOffset(int w, int bw = 0)
int GetCenterOffset(int w, int bw)
{
if (bw == 0) {
bw = SCREEN_WIDTH;
@ -458,30 +473,94 @@ int GetStrWidth(BYTE *str, int size)
return strWidth;
}
int TextAlignment(char *text, TXT_JUST align, int bw, int size)
int TextAlignment(UI_Item *item, TXT_JUST align, _artFontTables size)
{
if (align != JustLeft) {
int w = GetStrWidth(text, size);
int w = GetStrWidth(item->caption, size);
if (align == JustCentre) {
return GetCenterOffset(w, bw);
return GetCenterOffset(w, item->rect.w);
} else if (align == JustRight) {
return bw - w;
return item->rect.w - w;
}
}
return 0;
}
void DrawArtStr(int x, int y, int size, int color, BYTE *str, TXT_JUST align, int bw)
void WordWrap(UI_Item *item)
{
x += TextAlignment(str, align, bw, size);
int lineStart = 0;
int len = strlen(item->caption);
for (int i = 0; i <= len; i++) {
if (item->caption[i] == '\n') {
lineStart = i + 1;
continue;
} else if (item->caption[i] != ' ' && i != len) {
continue;
}
for (int i = 0; i < strlen(str); i++) {
BYTE w = FontTables[size][str[i] + 2];
if (!w)
w = FontTables[size][0];
DrawArt(x, y, &ArtFonts[size][color], str[i], w);
x += w;
if (i != len)
item->caption[i] = '\0';
if (GetStrWidth(&item->caption[lineStart], AFT_SMALL) <= item->rect.w) {
if (i != len)
item->caption[i] = ' ';
continue;
}
int j;
for (j = i; j >= lineStart; j--) {
if (item->caption[j] == ' ') {
break; // Scan for previous space
}
}
if (j == lineStart) { // Single word longer then width
if (i == len)
break;
j = i;
}
if (i != len)
item->caption[i] = ' ';
item->caption[j] = '\n';
lineStart = j + 1;
}
};
void DrawArtStr(UI_Item *item)
{
_artFontTables size = AFT_SMALL;
_artFontColors color = item->flags & UIS_GOLD ? AFC_GOLD : AFC_SILVER;
TXT_JUST align = JustLeft;
if (item->flags & UIS_MED)
size = AFT_MED;
else if (item->flags & UIS_BIG)
size = AFT_BIG;
else if (item->flags & UIS_HUGE)
size = AFT_HUGE;
if (item->flags & UIS_CENTER)
align = JustCentre;
else if (item->flags & UIS_RIGHT)
align = JustRight;
int x = item->rect.x + TextAlignment(item, align, size);
int sx = x;
int sy = item->rect.y;
if (item->flags & UIS_VCENTER)
sy += (item->rect.h - ArtFonts[size][color].height) / 2;
for (int i = 0; i < strlen(item->caption); i++) {
if (item->caption[i] == '\n') {
sx = x;
sy += ArtFonts[size][color].height;
continue;
}
BYTE w = FontTables[size][item->caption[i] + 2] ?: FontTables[size][0];
DrawArt(sx, sy, &ArtFonts[size][color], *(BYTE *)&item->caption[i], w);
sx += w;
}
}
@ -512,16 +591,6 @@ int GetAnimationFrame(int frames, int fps)
return frame > frames ? 0 : frame;
}
int frameEnd = 0;
void CapFPS()
{
int now = SDL_GetTicks();
frameEnd += 1000 / 60;
if (now < frameEnd) {
SDL_Delay(frameEnd - now);
}
}
bool UiFadeIn(int steps)
{
if (fadeValue < 256) {
@ -536,6 +605,105 @@ bool UiFadeIn(int steps)
return fadeValue == 256;
}
void UiRenderItemDebug(UI_Item item)
{
return;
item.rect.x += 64; // pal_surface is shifted?
item.rect.y += 160;
SDL_FillRect(pal_surface, &item.rect, random(0, 255));
}
void DrawSelector(UI_Item *item = 0)
{
int size = FOCUS_SMALL;
if (item->rect.h >= 42)
size = FOCUS_BIG;
else if (item->rect.h >= 30)
size = FOCUS_MED;
int frame = GetAnimationFrame(8);
int y = item->rect.y + (item->rect.h - ArtFocus[size].height) / 2; // TODO FOCUS_MED appares higher then the box
DrawArt(item->rect.x, y, &ArtFocus[size], frame);
DrawArt(item->rect.x + item->rect.w - ArtFocus[size].width, y, &ArtFocus[size], frame);
}
void DrawEditBox(UI_Item item)
{
DrawSelector(&item);
item.rect.x += 43;
item.rect.y += 1;
item.rect.w -= 86;
DrawArtStr(&item);
}
void UiRenderItems(UI_Item *items, int size)
{
for (int i = 0; i < size; i++) {
if (items[i].flags & UIS_HIDDEN)
continue;
UiRenderItemDebug(items[i]);
switch (items[i].type) {
case UI_EDIT:
DrawEditBox(items[i]);
break;
case UI_LIST:
if (items[i].caption == NULL)
continue;
if (SelectedItem == items[i].value)
DrawSelector(&items[i]);
case UI_BUTTON:
case UI_TEXT:
DrawArtStr(&items[i]);
break;
case UI_IMAGE:
DrawArt(items[i].rect.x, items[i].rect.y, items[i].context, items[i].value, items[i].rect.w);
break;
default:
UiRenderItemDebug(items[i]);
break;
}
}
}
bool UiItemMouseEvents(SDL_Event *event, UI_Item *items, int size)
{
if (event->type != SDL_MOUSEBUTTONDOWN || event->button.button != SDL_BUTTON_LEFT) {
return false;
}
for (int i = 0; i < size; i++) {
if (!IsInsideRect(event, &items[i].rect)) {
continue;
}
if (items[i].type != UI_BUTTON && items[i].type != UI_LIST) {
continue;
}
if (items[i].type == UI_LIST) {
if (items[i].caption != NULL && *items[i].caption != '\0') {
if (gfnListFocus != NULL && SelectedItem != items[i].value) {
UiFocus(items[i].value);
} else if (gfnListFocus == NULL || event->button.clicks >= 2) {
SelectedItem = items[i].value;
UiFocusNavigationSelect();
}
}
return true;
}
if (items[i].context) {
((void (*)(int value))items[i].context)(items[i].value);
}
return true;
}
return false;
}
void DrawLogo(int t, int size)
{
DrawArt(GetCenterOffset(ArtLogos[size].width), t, &ArtLogos[size], GetAnimationFrame(15));
@ -557,13 +725,3 @@ void DrawMouse()
DrawArt(MouseX, MouseY, &ArtCursor);
}
void DrawSelector(int x, int y, int width, int padding, int spacing, int size)
{
width = width ? width : SCREEN_WIDTH;
y += (SelectedItem - 1) * spacing;
int frame = GetAnimationFrame(8);
DrawArt(x + padding, y, &ArtFocus[size], frame);
DrawArt(x + width - padding - ArtFocus[size].width, y, &ArtFocus[size], frame);
}

44
Stub/DiabloUI/dialogs.cpp

@ -0,0 +1,44 @@
#include "../../types.h"
UI_Item ENTERIP_DIALOG[] = {
{ { 305, 210, 285, 33 }, UI_TEXT, UIS_CENTER, 0, "Enter IP" },
{ { 305, 314, 285, 33 }, UI_EDIT, UIS_LIST, 128 }, // input
{ { 300, 426, 140, 35 }, UI_BUTTON, 0, 0, "OK" },
{ { 450, 426, 140, 35 }, UI_BUTTON, 0, 0, "Cancel" },
};
UI_Item OKCANCEL_DIALOG[] = {
{ { 180, 168, 280, 144 }, UI_IMAGE, 0, 0, "ui_art\\spopup.pcx" },
{ { 200, 180, 240, 80 }, UI_TEXT, UIS_CENTER }, // message
{ { 200, 265, 110, 28 }, UI_BUTTON, UIS_SML1, 0, "OK" },
{ { 330, 265, 110, 28 }, UI_BUTTON, UIS_SML2, 0, "Cancel" },
};
UI_Item OK_DIALOG[] = {
{ { 180, 168, 280, 144 }, UI_IMAGE, 0, 0, "ui_art\\spopup.pcx" },
{ { 200, 180, 240, 80 }, UI_TEXT, UIS_CENTER }, // message
{ { 265, 265, 110, 28 }, UI_BUTTON, UIS_SML1, 0, "OK" },
};
UI_Item PROGRESS_DIALOG[] = {
{ { 180, 168, 280, 144 }, UI_IMAGE, 0, 0, "ui_art\\spopup.pcx" },
{ { 180, 177, 280, 43 }, UI_TEXT, UIS_CENTER }, // Message
{ { 205, 220, 228, 38 }, UI_IMAGE, 0, 0, "ui_art\\prog_bg.pcx" },
{ { 265, 267, 110, 28 }, UI_BUTTON, UIS_SML1, 0, "Cancel" },
};
UI_Item SELOK_DIALOG[] = {
{ { 140, 210, 400, 168 } }, // Message
{ { 230, 390, 180, 35 }, UI_LIST, UIS_CENTER, 0, "OK" },
};
UI_Item SELYESNO_DIALOG[] = {
{ { 120, 210, 400, 168 } }, // Question text
{ { 230, 390, 180, 35 }, UI_LIST, UIS_CENTER, 0, "Yes" },
{ { 230, 426, 180, 35 }, UI_LIST, UIS_CENTER, 0, "No" },
};
UI_Item SPAWNERR_DIALOG[] = {
{ { 140, 199, 400, 177 }, UI_TEXT, 0, 0, "The Rogue and Sorcerer are only available in the full retail version of Diablo. For ordering information call (800) 953-SNOW." },
{ { 230, 407, 180, 43 }, UI_BUTTON, 0, 0, "OK" },
};

163
Stub/DiabloUI/mainmenu.cpp

@ -1,30 +1,21 @@
#include "../../types.h"
void mainmenu_Render(char *name)
{
DrawArt(0, 0, &ArtBackground);
DrawLogo();
int menuTop = 192;
char *MENIITEMS[5] = { "Single Player", "Multi Player", "Replay Intro", "Show Credits", "Exit Diablo" };
int spacing = 43;
for (int i = 0; i < 5; i++) {
int y = menuTop + i * spacing;
DrawArtStr(0, y, AFT_HUGE, AFC_GOLD, MENIITEMS[i], 1);
}
DrawSelector(0, menuTop, 0, 65, spacing, FOCUS_BIG);
int MainMenuResult;
DrawArtStr(17, 444, AFT_SMALL, AFC_SILVER, name);
void UiMainMenuSelect(int value)
{
MainMenuResult = value;
}
void mainmenu_Load()
{
MainMenuResult = 0;
UiInitList(MAINMENU_SINGLE_PLAYER, MAINMENU_EXIT_DIABLO, NULL, UiMainMenuSelect);
char *pszFile = "ui_art\\mainmenu.pcx";
if (false) //DiabloUI_GetSpawned()
pszFile = "ui_art\\swmmenu.pcx";
LoadBackgroundArt(pszFile);
}
@ -34,123 +25,57 @@ void mainmenu_Free()
ArtBackground.data = NULL;
}
BOOL __stdcall UiMainMenuDialog(char *name, int *pdwResult, void(__stdcall *fnSound)(char *file), int a4)
bool UiMainMenuEvent(SDL_Event *event)
{
gfnSoundFunction = fnSound;
mainmenu_Load();
switch (event->type) {
case SDL_KEYDOWN:
if (UiFocusNavigation(event, true))
return true;
if (event->key.keysym.sym == SDLK_ESCAPE) {
UiMainMenuSelect(MAINMENU_EXIT_DIABLO);
return true;
}
break;
case SDL_QUIT:
exit(0);
}
return false;
}
SelectedItem = 1;
SelectedItemMax = 5;
BOOL __stdcall UiMainMenuDialog(char *name, int *pdwResult, void(__stdcall *fnSound)(char *file), int a4)
{
SDL_Event event;
int ItemHeight = 43;
SDL_Rect SinglePlayer = { 0, 191, 515, ItemHeight };
SinglePlayer.x = GetCenterOffset(SinglePlayer.w);
SDL_Rect MultiPlayer = SinglePlayer;
MultiPlayer.y += ItemHeight * 1;
SDL_Rect ReplayIntro = MultiPlayer;
ReplayIntro.y += ItemHeight * 2;
SDL_Rect ShowCredits = ReplayIntro;
ShowCredits.y += ItemHeight * 3;
SDL_Rect ExitDiablo = ShowCredits;
ExitDiablo.y += ItemHeight * 4;
UI_Item MAINMENU_DIALOG[] = {
{ { 0, 0, 640, 480 }, UI_IMAGE, 0, 0, NULL, &ArtBackground },
{ { 64, 192, 510, 43 }, UI_LIST, UIS_HUGE | UIS_GOLD | UIS_CENTER, MAINMENU_SINGLE_PLAYER, "Single Player" },
{ { 64, 235, 510, 43 }, UI_LIST, UIS_HUGE | UIS_GOLD | UIS_CENTER, MAINMENU_MULTIPLAYER, "Multi Player" },
{ { 64, 277, 510, 43 }, UI_LIST, UIS_HUGE | UIS_GOLD | UIS_CENTER, MAINMENU_REPLAY_INTRO, "Replay Intro" },
{ { 64, 320, 510, 43 }, UI_LIST, UIS_HUGE | UIS_GOLD | UIS_CENTER, MAINMENU_SHOW_CREDITS, "Show Credits" },
{ { 64, 363, 510, 43 }, UI_LIST, UIS_HUGE | UIS_GOLD | UIS_CENTER, MAINMENU_EXIT_DIABLO, "Exit Diablo" },
{ { 17, 444, 605, 21 }, UI_TEXT, UIS_SMALL, 0, name },
};
bool endMenu = false;
gfnSoundFunction = fnSound;
mainmenu_Load();
while (!endMenu) {
CapFPS();
mainmenu_Render(name);
while (MainMenuResult == 0) {
UiRenderItems(MAINMENU_DIALOG, size(MAINMENU_DIALOG));
DrawLogo();
DrawMouse();
UiFadeIn();
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
if (UiFocuseNavigation(&event, true))
break;
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
*pdwResult = MAINMENU_EXIT_DIABLO;
UiPlaySelectSound();
Sleep(250); // Wait for soudn to play
endMenu = true;
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
switch (SelectedItem) {
case MAINMENU_SINGLE_PLAYER:
UiPlaySelectSound();
*pdwResult = MAINMENU_SINGLE_PLAYER;
endMenu = true;
break;
case MAINMENU_MULTIPLAYER:
UiPlaySelectSound();
*pdwResult = MAINMENU_MULTIPLAYER;
endMenu = true;
break;
case MAINMENU_REPLAY_INTRO:
UiPlaySelectSound();
*pdwResult = MAINMENU_REPLAY_INTRO;
endMenu = true;
break;
case MAINMENU_SHOW_CREDITS:
UiPlaySelectSound();
*pdwResult = MAINMENU_SHOW_CREDITS;
endMenu = true;
break;
case MAINMENU_EXIT_DIABLO:
UiPlaySelectSound();
Sleep(250); // Wait for sound to play
*pdwResult = MAINMENU_EXIT_DIABLO;
endMenu = true;
break;
}
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
if (IsInsideRect(&event, &SinglePlayer)) {
UiPlaySelectSound();
*pdwResult = MAINMENU_SINGLE_PLAYER;
endMenu = true;
break;
} else if (IsInsideRect(&event, &MultiPlayer)) {
UiPlaySelectSound();
*pdwResult = MAINMENU_MULTIPLAYER;
endMenu = true;
break;
} else if (IsInsideRect(&event, &ReplayIntro)) {
UiPlaySelectSound();
*pdwResult = MAINMENU_REPLAY_INTRO;
endMenu = true;
break;
} else if (IsInsideRect(&event, &ShowCredits)) {
UiPlaySelectSound();
*pdwResult = MAINMENU_SHOW_CREDITS;
endMenu = true;
break;
} else if (IsInsideRect(&event, &ExitDiablo)) {
UiPlaySelectSound();
Sleep(250); // Wait for soudn to play
*pdwResult = MAINMENU_EXIT_DIABLO;
endMenu = true;
break;
}
}
break;
case SDL_QUIT:
*pdwResult = MAINMENU_EXIT_DIABLO;
endMenu = true;
break;
}
if (UiMainMenuEvent(&event))
continue;
UiItemMouseEvents(&event, MAINMENU_DIALOG, size(MAINMENU_DIALOG));
}
}
BlackPalette();
mainmenu_Free();
*pdwResult = MainMenuResult;
return TRUE;
}

1
Stub/DiabloUI/progress.cpp

@ -75,7 +75,6 @@ int __stdcall UiProgressDialog(HWND window, char *msg, int enable, int(__cdecl *
SDL_Event event;
while (!endMenu && progress < 100) {
CapFPS();
progress = fnfunc();
progress_Render(progress);
DrawMouse();

79
Stub/DiabloUI/sdlrender.h

@ -26,6 +26,42 @@ typedef enum _artFontColors {
AFC_GOLD,
} _artFontColors;
typedef enum UiTypes {
UI_TEXT,
UI_IMAGE,
UI_BUTTON,
UI_LIST,
UI_EDIT,
} UiTypes;
typedef enum UiFlags {
UIS_SMALL = 0x1,
UIS_MED = 0x10,
UIS_BIG = 0x100,
UIS_HUGE = 0x1000,
UIS_CENTER = 0x10000,
UIS_RIGHT = 0x100000,
UIS_VCENTER = 0x1000000,
UIS_SILVER = 0x10000000,
UIS_GOLD = 0x100000000,
UIS_SML1 = 0x1000000000,
UIS_SML2 = 0x10000000000,
UIS_LIST = 0x100000000000,
UIS_DISABLED = 0x1000000000000,
UIS_HIDDEN = 0x10000000000000,
} UiFlags;
typedef enum selheromenu_selections
{
SELHERO_LIST,
SELHERO_CLASSES,
SELHERO_NAME,
SELHERO_LOAD,
SELHERO_SELECT_GAME,
SELHERO_DIFFICULTY,
} selheromenu_selections;
typedef struct Art {
BYTE *data;
DWORD width;
@ -34,6 +70,15 @@ typedef struct Art {
BYTE mask;
} Art;
typedef struct UI_Item {
SDL_Rect rect;
UiTypes type;
UiFlags flags;
int value;
BYTE *caption;
void *context;
} UI_Item;
extern TTF_Font *font;
extern BYTE *FontTables[4];
@ -44,44 +89,44 @@ extern Art ArtBackground;
extern Art ArtCursor;
extern Art ArtHero;
extern int SelectedItem;
extern int SelectedItemMax;
extern int SCREEN_WIDTH;
extern int SCREEN_HEIGHT;
extern int submenu;
typedef enum TXT_JUST {
JustLeft = 0,
JustCentre = 1,
JustRight = 2,
} TXT_JUST;
template <class T, size_t N>
constexpr size_t size(T (&)[N])
{
return N;
}
extern void(__stdcall *gfnSoundFunction)(char *file);
DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, char *lpBuffer, DWORD nSize, va_list *Arguments);
int MAKEINTRESOURCE(int i);
int DialogBoxParam(HINSTANCE hInstance, int msgId, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
BOOL SetDlgItemText(HWND hDlg, int nIDDlgItem, LPCSTR lpString);
BOOL EndDialog(HWND hDlg, INT_PTR nResult);
BOOL SetDlgItemText(HWND hDlg, int nIDDlgItem, LPCSTR lpString);
BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
DWORD FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, char *lpBuffer, DWORD nSize, va_list *Arguments);
int DialogBoxParam(HINSTANCE hInstance, int msgId, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
int MAKEINTRESOURCE(int i);
bool IsInsideRect(const SDL_Event *event, const SDL_Rect *rect);
bool UiFadeIn(int steps = 16);
bool UiFocusNavigation(SDL_Event *event, bool wrap = false);
bool UiItemMouseEvents(SDL_Event *event, UI_Item *items, int size);
int GetAnimationFrame(int frames, int fps = 60);
int GetCenterOffset(int w, int bw = 0);
void CapFPS();
void DrawArt(int screenX, int screenY, Art *art, int nFrame = 0, int drawW = 0);
void DrawArtStr(int x, int y, int size, int color, BYTE *str, TXT_JUST align = JustLeft, int bw = 0);
void DrawLogo(int t = 0, int size = LOGO_MED);
void DrawMouse();
void DrawSelector(int x, int y, int width, int padding, int spacing = 0, int size = FOCUS_MED);
void LoadArt(char *pszFile, Art *art, int frames = 1, PALETTEENTRY *pPalette = NULL);
void LoadMaskedArtFont(char *pszFile, Art *art, int frames, int mask = 250);
void LoadBackgroundArt(char *pszFile);
void LoadMaskedArtFont(char *pszFile, Art *art, int frames, int mask = 250);
void SetMenu(int MenuId);
void UiFocuse(int move, bool wrap = false);
bool UiFocuseNavigation(SDL_Event *event, bool wrap = false);
void UiPlayMoveSound();
void UiPlaySelectSound();
void UiFocusNavigationSelect();
void UiInitList(int min, int max, void(__stdcall *fnFocus)(int value) = NULL, void(__stdcall *fnSelect)(int value) = NULL);
void UiRenderItems(UI_Item *items, int size);
void WordWrap(UI_Item *item);

204
Stub/DiabloUI/selconn.cpp

@ -1,67 +1,108 @@
#include "../../types.h"
#include "selconn.h"
char selconn_MaxPlayers[21];
char selconn_Description[64];
char selconn_Gateway[129];
bool selconn_ReturnValue = false;
bool selconn_EndMenu = false;
_SNETPROGRAMDATA *selconn_ClientInfo;
_SNETPLAYERDATA *selconn_UserInfo;
_SNETUIDATA *selconn_UiInfo;
_SNETVERSIONDATA *selconn_FileInfo;
UI_Item SELCONNECT_DIALOG[] = {
{ { 0, 0, 640, 480 }, UI_IMAGE, 0, 0, NULL, &ArtBackground },
{ { 24, 161, 590, 35 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Multi Player Game" },
{ { 300, 211, 295, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Select Connection" },
{ { 305, 256, 285, 26 }, UI_LIST, UIS_CENTER | UIS_VCENTER | UIS_GOLD, 0, "Local Area Network (UDP)" },
{ { 305, 282, 285, 26 }, UI_LIST, UIS_CENTER | UIS_VCENTER | UIS_GOLD, 1, "Solo" },
{ { 305, 308, 285, 26 }, UI_LIST, UIS_CENTER | UIS_VCENTER | UIS_GOLD },
{ { 305, 334, 285, 26 }, UI_LIST, UIS_CENTER | UIS_VCENTER | UIS_GOLD },
{ { 305, 360, 285, 26 }, UI_LIST, UIS_CENTER | UIS_VCENTER | UIS_GOLD },
{ { 305, 386, 285, 26 }, UI_LIST, UIS_CENTER | UIS_VCENTER | UIS_GOLD },
{ { 35, 218, 205, 21 }, UI_TEXT, 0, 0, selconn_MaxPlayers }, // Max players
{ { 35, 256, 205, 21 }, UI_TEXT, 0, 0, "Requirements:" },
{ { 35, 275, 205, 66 }, UI_TEXT, 0, 0, selconn_Description }, //Description
{ { 30, 356, 220, 31 }, UI_TEXT, UIS_CENTER | UIS_MED, 0, "no gateway needed" },
{ { 35, 393, 205, 21 }, UI_TEXT, UIS_CENTER, 0, selconn_Gateway }, // Gateway
{ { 16, 427, 250, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD | UIS_HIDDEN, 0, "Change Gateway" },
{ { 299, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 454, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "Cancel", selconn_Esc },
};
void selconn_Render()
void selconn_Load()
{
DrawArt(0, 0, &ArtBackground);
DrawLogo();
DrawArtStr(0, 161, AFT_BIG, AFC_SILVER, "Multi Player Game", JustCentre);
LoadBackgroundArt("ui_art\\selconn.pcx");
UiInitList(0, 1, selconn_Focus, selconn_Select);
}
int w = 335;
int x = 280;
int y = 261;
void selconn_Free()
{
mem_free_dbg(ArtBackground.data);
ArtBackground.data = NULL;
}
DrawArtStr(x, 211, AFT_BIG, AFC_SILVER, "Select Connection", JustCentre, w);
void selconn_Esc()
{
selconn_ReturnValue = false;
selconn_EndMenu = true;
}
char *connections[2] = {
//"Battle.net",
//"Local Area Network (IPC)",
//"Modem",
//"Direct Cable Connection",
"Local Area Network (UDP)",
"Solo",
};
void selconn_Focus(int value)
{
int players = 4;
switch (value) {
case 0:
sprintf(selconn_Description, "All computers must be connected to an UDP-compatible network.");
players = 4;
break;
case 1:
sprintf(selconn_Description, "Play by your self with no network exposure.");
players = 1;
break;
}
int spacing = 26;
int selectorTop = y;
sprintf(selconn_MaxPlayers, "Players Supported: %d", players);
for (int i = 0; i < 2; i++) {
DrawArtStr(x, y, AFT_SMALL, AFC_GOLD, connections[i], JustCentre, w);
y += spacing;
for (auto &item : SELCONNECT_DIALOG) {
if (item.caption != NULL && !(item.flags & (UIS_VCENTER | UIS_CENTER)))
WordWrap(&item);
}
}
DrawSelector(x, selectorTop - 2, w, 25, spacing, FOCUS_SMALL);
if (SelectedItem == 1) {
DrawArtStr(35, 218, AFT_SMALL, AFC_SILVER, "Players Supported: 4");
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Requirements:");
// TODO need a word wrap function
DrawArtStr(35, 275, AFT_SMALL, AFC_SILVER, "All computers must be");
DrawArtStr(35, 291, AFT_SMALL, AFC_SILVER, "connected to an");
DrawArtStr(35, 307, AFT_SMALL, AFC_SILVER, "UDP-compatible network.");
} else {
DrawArtStr(35, 218, AFT_SMALL, AFC_SILVER, "Players Supported: 1");
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Play by your self with");
DrawArtStr(35, 275, AFT_SMALL, AFC_SILVER, "no network exposure.");
void selconn_Select(int value)
{
DWORD provider;
switch (value) {
case 0:
provider = 'UDPN';
break;
case 1:
provider = 'SCBL';
break;
}
DrawArtStr(26, 356, AFT_MED, AFC_SILVER, "no gateway needed", JustCentre, 226);
DrawArtStr(349, 429, AFT_BIG, AFC_GOLD, "OK");
DrawArtStr(476, 429, AFT_BIG, AFC_GOLD, "Cancel");
selconn_Free();
selconn_EndMenu = SNetInitializeProvider(provider, selconn_ClientInfo, selconn_UserInfo, selconn_UiInfo, selconn_FileInfo);
selconn_Load();
}
void selconn_Load()
bool selconn_Event(SDL_Event *event)
{
LoadBackgroundArt("ui_art\\selconn.pcx");
SelectedItem = 1;
SelectedItemMax = 2;
}
switch (event->type) {
case SDL_KEYDOWN:
if (UiFocusNavigation(event))
return true;
if (event->key.keysym.sym == SDLK_ESCAPE) {
selconn_Esc();
return true;
}
break;
case SDL_QUIT:
exit(0);
}
void selconn_Free()
{
mem_free_dbg(ArtBackground.data);
ArtBackground.data = NULL;
return false;
}
int __stdcall UiSelectProvider(
@ -72,69 +113,30 @@ int __stdcall UiSelectProvider(
_SNETVERSIONDATA *file_info,
int *type)
{
selconn_ClientInfo = client_info;
selconn_UserInfo = user_info;
selconn_UiInfo = ui_info;
selconn_FileInfo = file_info;
selconn_Load();
SDL_Event event;
bool rv = true;
bool endMenu = false;
while (!endMenu) {
CapFPS();
selconn_Render();
selconn_ReturnValue = true;
selconn_EndMenu = false;
while (!selconn_EndMenu) {
UiRenderItems(SELCONNECT_DIALOG, size(SELCONNECT_DIALOG));
DrawLogo();
DrawMouse();
UiFadeIn();
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
if (UiFocuseNavigation(&event))
break;
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
rv = false;
endMenu = true;
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
UiPlaySelectSound();
DWORD provider;
switch (SelectedItem) {
/*
case 1:
provider = 'BNET';
break;
case 2:
provider = 'IPXN';
break;
case 3:
provider = 'MODM';
break;
case 4:
provider = 'SCBL';
break;
case 5:*/
case 1:
provider = 'UDPN';
break;
case 2:
provider = 'SCBL';
break;
}
selconn_Free();
endMenu = SNetInitializeProvider(provider, client_info, user_info, ui_info, file_info);
selconn_Load();
break;
}
break;
case SDL_QUIT:
exit(0);
}
if (selconn_Event(&event))
continue;
UiItemMouseEvents(&event, SELCONNECT_DIALOG, size(SELCONNECT_DIALOG));
}
}
BlackPalette();
selconn_Free();
return rv;
return selconn_ReturnValue;
}

5
Stub/DiabloUI/selconn.h

@ -0,0 +1,5 @@
#include "../../types.h"
void selconn_Esc();
void selconn_Focus(int value);
void selconn_Select(int value);

721
Stub/DiabloUI/selhero.cpp

@ -1,101 +1,119 @@
#include "../../types.h"
#include "selhero.h"
#include <iconv.h>
int selhero_SaveCount = 0;
_uiheroinfo heros[MAX_CHARACTERS];
_uiheroinfo heroInfo;
void RenderStats()
{
char lvl[4] = "--";
char str[4] = "--";
char mag[4] = "--";
char dex[4] = "--";
char vit[4] = "--";
if (heroInfo.heroclass != UI_NUM_CLASSES) {
sprintf(lvl, "%d", heroInfo.level);
sprintf(str, "%d", heroInfo.strength);
sprintf(mag, "%d", heroInfo.magic);
sprintf(dex, "%d", heroInfo.dexterity);
sprintf(vit, "%d", heroInfo.vitality);
}
DrawArtStr(31, 323, AFT_SMALL, AFC_SILVER, "Level:", JustRight, 118);
DrawArtStr(149, 323, AFT_SMALL, AFC_SILVER, lvl, JustCentre, 61);
DrawArtStr(31, 358, AFT_SMALL, AFC_SILVER, "Strength:", JustRight, 118);
DrawArtStr(149, 358, AFT_SMALL, AFC_SILVER, str, JustCentre, 61);
DrawArtStr(31, 380, AFT_SMALL, AFC_SILVER, "Magic:", JustRight, 118);
DrawArtStr(149, 380, AFT_SMALL, AFC_SILVER, mag, JustCentre, 61);
DrawArtStr(31, 401, AFT_SMALL, AFC_SILVER, "Dexterity:", JustRight, 118);
DrawArtStr(149, 401, AFT_SMALL, AFC_SILVER, dex, JustCentre, 61);
DrawArtStr(31, 422, AFT_SMALL, AFC_SILVER, "Vitality:", JustRight, 118);
DrawArtStr(149, 422, AFT_SMALL, AFC_SILVER, vit, JustCentre, 61);
}
void selhero_Render(bool multiPlayer)
char listItems[6][16];
char textStats[5][4];
char title[32];
char selhero_Lable[32];
char selhero_Description[256];
int selhero_result;
bool selhero_return;
bool selhero_endMenu;
bool selhero_endMenu_Single;
int submenu = 0;
bool isMultiPlayer;
bool heroIsCreated;
BOOL(__stdcall *gfnHeroStats)
(unsigned int, _uidefaultstats *);
UI_Item SELHERO_DIALOG[] = {
{ { 0, 0, 640, 480 }, UI_IMAGE, 0, 0, NULL, &ArtBackground },
{ { 24, 161, 590, 35 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, title },
{ { 30, 211, 180, 76 }, UI_IMAGE, 0, UI_NUM_CLASSES, NULL, &ArtHero },
{ { 39, 323, 110, 21 }, UI_TEXT, UIS_RIGHT, 0, "Level:" },
{ { 159, 323, 40, 21 }, UI_TEXT, UIS_CENTER, 0, textStats[0] },
{ { 39, 358, 110, 21 }, UI_TEXT, UIS_RIGHT, 0, "Strength:" },
{ { 159, 358, 40, 21 }, UI_TEXT, UIS_CENTER, 0, textStats[1] },
{ { 39, 380, 110, 21 }, UI_TEXT, UIS_RIGHT, 0, "Magic:" },
{ { 159, 380, 40, 21 }, UI_TEXT, UIS_CENTER, 0, textStats[2] },
{ { 39, 401, 110, 21 }, UI_TEXT, UIS_RIGHT, 0, "Dexterity:" },
{ { 159, 401, 40, 21 }, UI_TEXT, UIS_CENTER, 0, textStats[3] },
{ { 39, 422, 110, 21 }, UI_TEXT, UIS_RIGHT, 0, "Vitality:" },
{ { 159, 422, 40, 21 }, UI_TEXT, UIS_CENTER, 0, textStats[4] },
};
UI_Item SELLIST_DIALOG[] = {
{ { 264, 211, 320, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Select Hero" },
{ { 265, 256, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 0, listItems[0] },
{ { 265, 282, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 1, listItems[1] },
{ { 265, 308, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 2, listItems[2] },
{ { 265, 334, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 3, listItems[3] },
{ { 265, 360, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 4, listItems[4] },
{ { 265, 386, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 5, listItems[5] },
{ { 239, 429, 120, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 364, 429, 120, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_DISABLED, 0, "Delete" },
{ { 489, 429, 120, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_GOLD, 0, "Cancel" },
};
UI_Item SELCLASS_DIALOG[] = {
{ { 264, 211, 320, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Choose Class" },
{ { 264, 285, 320, 33 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, UI_WARRIOR, "Warrior" },
{ { 264, 318, 320, 33 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, UI_ROGUE, "Rogue" },
{ { 264, 352, 320, 33 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, UI_SORCERER, "Sorcerer" },
{ { 279, 429, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 429, 429, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_GOLD, 0, "Cancel" },
};
UI_Item ENTERNAME_DIALOG[] = {
{ { 264, 211, 320, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Enter Name" },
{ { 265, 317, 320, 33 }, UI_EDIT, UIS_LIST | UIS_MED | UIS_GOLD, 0, heroInfo.name, 15 },
{ { 279, 429, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 429, 429, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_BIG | UIS_GOLD, 0, "Cancel" },
};
UI_Item SELLOAD_DIALOG[] = {
{ { 264, 211, 320, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Save File Exists" },
{ { 265, 285, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 0, "Load Game" },
{ { 265, 318, 320, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 1, "New Game" },
{ { 279, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 429, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "Cancel" },
};
UI_Item SELUDPGAME_DIALOG[] = {
{ { 0, 0, 640, 480 }, UI_IMAGE, 0, 0, NULL, &ArtBackground },
{ { 25, 161, 590, 35 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Join UDP Games" },
{ { 300, 211, 295, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Select Action" },
{ { 305, 255, 285, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 0, "Create Game" },
{ { 305, 281, 285, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 1, "Enter IP" },
{ { 305, 307, 285, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, 2, "Localhost" },
{ { 305, 333, 285, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD },
{ { 305, 359, 285, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD },
{ { 305, 385, 285, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD },
{ { 35, 211, 205, 33 }, UI_TEXT, UIS_MED, 0, "Description:" },
{ { 35, 256, 205, 192 }, UI_TEXT, 0, 0, selhero_Description }, // Description
{ { 299, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 449, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "Cancel" },
};
UI_Item SELDIFF_DIALOG[] = {
{ { 0, 0, 640, 480 }, UI_IMAGE, 0, 0, NULL, &ArtBackground },
{ { 24, 161, 590, 35 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Create Game" },
{ { 299, 211, 295, 35 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, "Select Difficulty" },
{ { 300, 282, 295, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, DIFF_NORMAL, "Normal" },
{ { 300, 308, 295, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, DIFF_NIGHTMARE, "Nightmare" },
{ { 300, 334, 295, 26 }, UI_LIST, UIS_CENTER | UIS_MED | UIS_GOLD, DIFF_HELL, "Hell" },
{ { 34, 211, 205, 33 }, UI_TEXT, UIS_CENTER | UIS_BIG, 0, selhero_Lable }, // DIFF
{ { 35, 256, 205, 192 }, UI_TEXT, 0, 0, selhero_Description }, // Description
{ { 299, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "OK", UiFocusNavigationSelect },
{ { 449, 427, 140, 35 }, UI_BUTTON, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD, 0, "Cancel" },
};
void selhero_SetStats()
{
heroInfo.heroclass = UI_NUM_CLASSES;
if (SelectedItem <= selhero_SaveCount) {
memcpy(&heroInfo, &heros[SelectedItem - 1], sizeof(heroInfo));
}
DrawArt(0, 0, &ArtBackground);
DrawLogo();
char *title = "Single Player Characters";
if (multiPlayer) {
title = "Multi Player Characters";
}
DrawArtStr(0, 161, AFT_BIG, AFC_SILVER, title, JustCentre);
DrawArt(30, 211, &ArtHero, heroInfo.heroclass);
RenderStats();
int w = 368;
int x = 241;
DrawArtStr(x, 211, AFT_BIG, AFC_SILVER, "Select Hero", JustCentre, w);
int spacing = 26;
int selectorTop = 256;
int y = selectorTop;
for (int i = 0; i < selhero_SaveCount; i++) {
DrawArtStr(x, y, AFT_MED, AFC_GOLD, heros[i].name, JustCentre, w);
y += spacing;
}
DrawArtStr(x, y, AFT_MED, AFC_GOLD, "New Hero", JustCentre, w);
DrawSelector(x, selectorTop + 3, w, 24, spacing, FOCUS_SMALL);
DrawArtStr(279, 429, AFT_BIG, AFC_GOLD, "OK");
DrawArtStr(378, 429, AFT_BIG, AFC_GOLD, "Delete");
DrawArtStr(501, 429, AFT_BIG, AFC_GOLD, "Cancel");
SELHERO_DIALOG[2].value = heroInfo.heroclass;
sprintf(textStats[0], "%d", heroInfo.level);
sprintf(textStats[1], "%d", heroInfo.strength);
sprintf(textStats[2], "%d", heroInfo.magic);
sprintf(textStats[3], "%d", heroInfo.dexterity);
sprintf(textStats[4], "%d", heroInfo.vitality);
}
void selhero_Render_Name(bool multiPlayer)
void selhero_Render_Name()
{
DrawArt(0, 0, &ArtBackground);
DrawLogo();
DrawArt(30, 211, &ArtHero, heroInfo.heroclass);
RenderStats();
char *title = "New Single Player Hero";
if (multiPlayer) {
title = "New Multi Player Hero";
}
DrawArtStr(0, 161, AFT_BIG, AFC_SILVER, title, JustCentre);
int w = 368;
int x = 241;
int y = 318;
DrawArtStr(x, 211, AFT_BIG, AFC_SILVER, "Enter Name", JustCentre, w);
DrawSelector(x, y - 2, w, 24);
char lable[17];
strcpy(lable, heroInfo.name);
if (GetAnimationFrame(2, 500)) {
@ -103,56 +121,77 @@ void selhero_Render_Name(bool multiPlayer)
lable[len] = '|';
lable[len + 1] = '\0';
}
ENTERNAME_DIALOG[1].caption = lable;
DrawArtStr(x + 67, y, AFT_MED, AFC_GOLD, lable); // todo add blinking "|"
DrawArtStr(329, 429, AFT_BIG, AFC_GOLD, "OK");
DrawArtStr(451, 429, AFT_BIG, AFC_GOLD, "Cancel");
UiRenderItems(ENTERNAME_DIALOG, size(ENTERNAME_DIALOG));
}
// Have this load the function above and then render it in the main menu.
// Cnacel box is also needed.
void selhero_Render_ClassSelector(bool multiPlayer)
BOOL __stdcall SelHero_GetHeroInfo(_uiheroinfo *pInfo)
{
DrawArt(0, 0, &ArtBackground);
DrawLogo();
heros[selhero_SaveCount] = *pInfo;
selhero_SaveCount++;
DrawArt(30, 211, &ArtHero, heroInfo.heroclass);
RenderStats();
return TRUE;
}
char *title = "New Single Player Hero";
if (multiPlayer) {
title = "New Multi Player Hero";
void selhero_Focus_List(int value)
{
if (selhero_SaveCount && value < selhero_SaveCount) {
memcpy(&heroInfo, &heros[value], sizeof(heroInfo));
selhero_SetStats();
return;
}
DrawArtStr(0, 161, AFT_BIG, AFC_SILVER, title, JustCentre);
int w = 369;
int x = 241;
int y = 285;
DrawArtStr(x, 211, AFT_BIG, AFC_SILVER, "Choose Class", JustCentre, w);
char *heroclasses[3] = { "Warrior", "Rogue", "Sorcerer" };
SELHERO_DIALOG[2].value = UI_NUM_CLASSES;
sprintf(textStats[0], "--");
sprintf(textStats[1], "--");
sprintf(textStats[2], "--");
sprintf(textStats[3], "--");
sprintf(textStats[4], "--");
}
int spacing = 33;
int selectorTop = y;
for (int i = 0; i < 3; i++) {
DrawArtStr(x, y, AFT_MED, AFC_GOLD, heroclasses[i], JustCentre, w);
y += spacing;
void selhero_Select_ClassSelector(int value)
{
submenu = SELHERO_NAME;
sprintf(title, "New Single Player Hero");
if (isMultiPlayer) {
sprintf(title, "New Multi Player Hero");
}
memset(heroInfo.name, '\0', 16);
SDL_StartTextInput();
}
void selhero_Focus_ClassSelector(int value)
{
_uidefaultstats defaults;
gfnHeroStats(value, &defaults);
DrawSelector(x, selectorTop - 2, w, 39, spacing);
heroInfo.level = 1;
heroInfo.heroclass = value;
heroInfo.strength = defaults.strength;
heroInfo.magic = defaults.magic;
heroInfo.dexterity = defaults.dexterity;
heroInfo.vitality = defaults.vitality;
DrawArtStr(329, 429, AFT_BIG, AFC_GOLD, "OK");
DrawArtStr(451, 429, AFT_BIG, AFC_GOLD, "Cancel");
selhero_SetStats();
}
BOOL __stdcall SelHero_GetHeroInfo(_uiheroinfo *pInfo)
void selhero_Select_List(int value)
{
heros[selhero_SaveCount] = *pInfo;
selhero_SaveCount++;
if (value == selhero_SaveCount) {
submenu = SELHERO_CLASSES;
UiInitList(0, 2, selhero_Focus_ClassSelector, selhero_Select_ClassSelector);
memset(&heroInfo.name, 0, sizeof(heroInfo.name));
sprintf(title, "New Single Player Hero");
if (isMultiPlayer) {
sprintf(title, "New Multi Player Hero");
}
return;
}
return TRUE;
heroIsCreated = true;
selhero_return = false;
selhero_endMenu = true;
}
void selhero_Load(BOOL(__stdcall *fninfo)(BOOL(__stdcall *fninfofunc)(_uiheroinfo *)))
@ -161,94 +200,85 @@ void selhero_Load(BOOL(__stdcall *fninfo)(BOOL(__stdcall *fninfofunc)(_uiheroinf
selhero_SaveCount = 0;
fninfo(SelHero_GetHeroInfo);
heroInfo.heroclass = UI_NUM_CLASSES;
}
void selhero_Free()
{
mem_free_dbg(ArtBackground.data);
ArtBackground.data = NULL;
memset(listItems, 0, sizeof(listItems));
}
void selhero_setDefaultStats(BOOL(__stdcall *fnstats)(unsigned int, _uidefaultstats *))
void selhero_List_Esc()
{
_uidefaultstats defaults;
fnstats(SelectedItem - 1, &defaults);
heroInfo.heroclass = SelectedItem - 1;
heroInfo.strength = defaults.strength;
heroInfo.magic = defaults.magic;
heroInfo.dexterity = defaults.dexterity;
heroInfo.vitality = defaults.vitality;
selhero_return = true;
selhero_endMenu = true;
}
bool selhero_Event(bool *aborted)
void selhero_Event_List()
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (UiFocusNavigation(&event))
continue;
if (UiItemMouseEvents(&event, SELLIST_DIALOG, size(SELLIST_DIALOG)))
continue;
switch (event.type) {
case SDL_KEYDOWN:
if (UiFocuseNavigation(&event))
if (event.key.keysym.sym == SDLK_ESCAPE) {
selhero_List_Esc();
break;
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
*aborted = true;
return true;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
if (SelectedItem == SelectedItemMax) {
memset(&heroInfo.name, 0, sizeof(heroInfo.name));
SetMenu(SELHERO_CLASSES);
break;
}
return true;
}
break;
case SDL_QUIT:
exit(0);
}
}
}
return false;
void selhero_init_List()
{
submenu = SELHERO_LIST;
UiInitList(0, selhero_SaveCount, selhero_Focus_List, selhero_Select_List);
int i;
for (i = 0; i < selhero_SaveCount && i < 6; i++) {
sprintf(listItems[i], heros[i].name);
}
if (i < 6)
sprintf(listItems[i], "New Hero");
sprintf(title, "Single Player Characters");
if (isMultiPlayer) {
sprintf(title, "Multi Player Characters");
}
}
bool selhero_Event_ClassSelector(bool *aborted)
void selhero_Event_ClassSelector()
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (UiFocusNavigation(&event))
continue;
if (UiItemMouseEvents(&event, SELCLASS_DIALOG, size(SELCLASS_DIALOG)))
continue;
switch (event.type) {
case SDL_KEYDOWN:
if (UiFocuseNavigation(&event, true))
break;
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
if (event.key.keysym.sym == SDLK_ESCAPE) {
if (selhero_SaveCount) {
SetMenu(SELHERO_LOAD);
SelectedItemMax += selhero_SaveCount;
selhero_init_List();
break;
}
*aborted = true;
return true;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
SetMenu(SELHERO_NAME);
memset(heroInfo.name, '\0', 16);
SDL_StartTextInput();
break;
selhero_return = true;
selhero_endMenu = true;
}
break;
case SDL_QUIT:
exit(0);
}
}
return false;
}
bool selhero_CatToName(char *in_buf)
void selhero_CatToName(char *in_buf)
{
iconv_t cd = iconv_open("ISO_8859-1//TRANSLIT//IGNORE", "UTF-8");
if (cd == (iconv_t)-1) {
@ -267,11 +297,10 @@ bool selhero_CatToName(char *in_buf)
strncat(heroInfo.name, output, 15 - strlen(heroInfo.name));
}
bool selhero_Event_Name()
void selhero_Event_Name()
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
exit(0);
@ -285,13 +314,13 @@ bool selhero_Event_Name()
break;
case SDLK_ESCAPE:
SDL_StopTextInput();
SetMenu(SELHERO_CLASSES);
selhero_Select_List(selhero_SaveCount);
break;
case SDLK_RETURN:
case SDLK_RETURN2:
case SDLK_KP_ENTER:
SDL_StopTextInput();
return true;
selhero_endMenu = true;
break;
case SDLK_BACKSPACE:
case SDLK_LEFT:
@ -307,55 +336,88 @@ bool selhero_Event_Name()
break;
}
}
}
return false;
void selhero_Event_Load()
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (UiFocusNavigation(&event, true))
continue;
if (UiItemMouseEvents(&event, SELLOAD_DIALOG, size(SELLOAD_DIALOG)))
continue;
switch (event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
selhero_result = EXIT_MENU;
selhero_endMenu_Single = true;
}
break;
case SDL_QUIT:
exit(0);
}
}
}
bool UiSelHeroDialog(
BOOL(__stdcall *fncreate)(_uiheroinfo *),
BOOL(__stdcall *fnremove)(_uiheroinfo *),
BOOL(__stdcall *fnstats)(unsigned int, _uidefaultstats *),
bool multiPlayer)
{
bool aborted = false;
bool endMenu = false;
isMultiPlayer = multiPlayer;
selhero_return = false;
selhero_endMenu = false;
heroIsCreated = false;
SelectedItem = 1;
submenu = SELHERO_LOAD;
SelectedItemMax = 1 + selhero_SaveCount;
if (!selhero_SaveCount) {
submenu = SELHERO_CLASSES;
SelectedItemMax = 3;
if (selhero_SaveCount) {
selhero_init_List();
} else {
selhero_Select_List(selhero_SaveCount);
}
while (endMenu == false) {
CapFPS();
while (!selhero_endMenu) {
UiRenderItems(SELHERO_DIALOG, size(SELHERO_DIALOG));
switch (submenu) {
case SELHERO_LOAD:
selhero_Render(multiPlayer);
endMenu = selhero_Event(&aborted);
case SELHERO_LIST:
UiRenderItems(SELLIST_DIALOG, size(SELLIST_DIALOG));
selhero_Event_List();
break;
case SELHERO_CLASSES:
selhero_setDefaultStats(fnstats);
selhero_Render_ClassSelector(multiPlayer);
endMenu = selhero_Event_ClassSelector(&aborted);
UiRenderItems(SELCLASS_DIALOG, size(SELCLASS_DIALOG));
selhero_Event_ClassSelector();
break;
case SELHERO_NAME:
selhero_Render_Name(multiPlayer);
endMenu = selhero_Event_Name();
selhero_Render_Name();
selhero_Event_Name();
break;
}
DrawLogo();
DrawMouse();
UiFadeIn();
}
if (!aborted && !heroInfo.hassaved) {
fncreate(&heroInfo); // todo don't overwrite
if (!heroIsCreated) {
fncreate(&heroInfo);
}
return selhero_return;
}
void selhero_Select_Load(int value)
{
selhero_endMenu_Single = true;
if (value == 0) {
selhero_result = LOAD_GAME;
return;
}
return aborted;
selhero_result = NEW_GAME;
}
void selhero_Focus_Load(int value)
{
}
BOOL __stdcall UiSelHeroSingDialog(
@ -367,20 +429,38 @@ BOOL __stdcall UiSelHeroSingDialog(
char *name,
int *difficulty)
{
gfnHeroStats = fnstats;
selhero_Load(fninfo);
if (UiSelHeroDialog(fncreate, fnremove, fnstats, false)) {
bool abort = UiSelHeroDialog(fncreate, fnremove, false);
if (abort) {
BlackPalette();
selhero_Free();
*dlgresult = EXIT_MENU;
} else {
strcpy(name, heroInfo.name);
return TRUE;
}
if (heroInfo.hassaved) {
*dlgresult = LOAD_GAME;
strcpy(name, heroInfo.name);
if (heroInfo.hassaved) {
UiInitList(0, 1, selhero_Focus_Load, selhero_Select_Load);
sprintf(title, "Single Player Characters");
selhero_endMenu_Single = false;
while (!selhero_endMenu_Single) {
UiRenderItems(SELHERO_DIALOG, size(SELHERO_DIALOG));
UiRenderItems(SELLOAD_DIALOG, size(SELLOAD_DIALOG));
DrawLogo();
DrawMouse();
UiFadeIn();
selhero_Event_Load();
}
}
BlackPalette();
selhero_Free();
*dlgresult = selhero_result;
return TRUE;
}
@ -399,192 +479,107 @@ void selhero_multi_Free()
ArtBackground.data = NULL;
}
void selhero_Render_DifficultySelection()
void selhero_Focus_Diff(int value)
{
DrawArt(0, 0, &ArtBackground);
DrawLogo();
DrawArtStr(0, 161, AFT_BIG, AFC_SILVER, "Create Game", JustCentre);
int w = 333;
int x = 281;
int y = 282;
DrawArtStr(x, 211, AFT_BIG, AFC_SILVER, "Select Difficulty", JustCentre, w);
char *gameOptions[] = { "Normal", "Nightmare", "Hell" };
DrawArtStr(23, 211, AFT_BIG, AFC_SILVER, gameOptions[SelectedItem - 1], JustCentre, 226);
if (SelectedItem == 1) {
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Normal Difficulty");
DrawArtStr(35, 272, AFT_SMALL, AFC_SILVER, "This is where a starting");
DrawArtStr(35, 288, AFT_SMALL, AFC_SILVER, "character should begin");
DrawArtStr(35, 304, AFT_SMALL, AFC_SILVER, "the quest to defeat");
DrawArtStr(35, 320, AFT_SMALL, AFC_SILVER, "Diablo.");
} else if (SelectedItem == 2) {
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Nightmare Difficulty");
DrawArtStr(35, 272, AFT_SMALL, AFC_SILVER, "The denizens of the");
DrawArtStr(35, 288, AFT_SMALL, AFC_SILVER, "Labyrinth have been");
DrawArtStr(35, 304, AFT_SMALL, AFC_SILVER, "bolstered and will prove");
DrawArtStr(35, 320, AFT_SMALL, AFC_SILVER, "to be a greater");
DrawArtStr(35, 336, AFT_SMALL, AFC_SILVER, "challenge. This is");
DrawArtStr(35, 352, AFT_SMALL, AFC_SILVER, "recommended for");
DrawArtStr(35, 368, AFT_SMALL, AFC_SILVER, "experienced characters");
DrawArtStr(35, 384, AFT_SMALL, AFC_SILVER, "only.");
} else if (SelectedItem == 3) {
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Hell Difficulty");
DrawArtStr(35, 272, AFT_SMALL, AFC_SILVER, "The most powerful of");
DrawArtStr(35, 288, AFT_SMALL, AFC_SILVER, "the underworld's");
DrawArtStr(35, 304, AFT_SMALL, AFC_SILVER, "creatures lurk at the");
DrawArtStr(35, 320, AFT_SMALL, AFC_SILVER, "gateway into Hell. Only");
DrawArtStr(35, 336, AFT_SMALL, AFC_SILVER, "the most experienced");
DrawArtStr(35, 352, AFT_SMALL, AFC_SILVER, "characters should");
DrawArtStr(35, 368, AFT_SMALL, AFC_SILVER, "venture in this realm.");
switch (value) {
case DIFF_NORMAL:
sprintf(selhero_Lable, "Normal");
sprintf(selhero_Description, "Normal Difficulty\nThis is where a starting character should begin the quest to defeat Diablo.");
break;
case DIFF_NIGHTMARE:
sprintf(selhero_Lable, "Nightmare");
sprintf(selhero_Description, "Nightmare Difficulty\nThe denizens of the Labyrinth have been bolstered and will prove to be a greater challenge. This is recommended for experienced characters only.");
break;
case DIFF_HELL:
sprintf(selhero_Lable, "Hell");
sprintf(selhero_Description, "Hell Difficulty\nThe most powerful of the underworld's creatures lurk at the gateway into Hell. Only the most experienced characters should venture in this realm.");
break;
}
int selectorTop = y;
int spacing = 26;
for (int i = 0; i < 3; i++) {
DrawArtStr(x, y, AFT_MED, AFC_GOLD, gameOptions[i], JustCentre, w);
y += spacing;
for (auto &item : SELDIFF_DIALOG) {
if (item.caption != NULL && !(item.flags & (UIS_VCENTER | UIS_CENTER)))
WordWrap(&item);
}
}
DrawSelector(x, selectorTop + 3, w, 19, spacing, FOCUS_SMALL);
void selhero_Select_Diff(int value)
{
gnDifficulty = value;
selhero_result = NEW_GAME;
}
DrawArtStr(349, 429, AFT_BIG, AFC_GOLD, "OK");
DrawArtStr(471, 429, AFT_BIG, AFC_GOLD, "Cancel");
void selhero_Select_GameSelection(int value)
{
submenu = SELHERO_DIFFICULTY;
UiInitList(0, 2, selhero_Focus_Diff, selhero_Select_Diff);
}
bool selhero_Event_GameSelection(int *dlgresult)
void selhero_Event_GameSelection()
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (UiFocusNavigation(&event))
continue;
if (UiItemMouseEvents(&event, SELUDPGAME_DIALOG, size(SELUDPGAME_DIALOG)))
continue;
switch (event.type) {
case SDL_KEYDOWN:
if (UiFocuseNavigation(&event))
break;
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
*dlgresult = EXIT_MENU;
return true;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
SetMenu(SELHERO_DIFFICULTY);
break;
if (event.key.keysym.sym == SDLK_ESCAPE) {
selhero_result = EXIT_MENU;
selhero_endMenu_Single = true;
}
break;
case SDL_QUIT:
exit(0);
}
}
}
void selhero_Focus_GameSelection(int value)
{
switch (value) {
case 0:
sprintf(selhero_Description, "Create a new game with a difficulty setting of your choice.");
break;
case 1:
sprintf(selhero_Description, "Join a game directly via a know host IP.");
break;
default:
sprintf(selhero_Description, "%s.\nCreated by %s, a level %d %s.", "Normal Difficulty", "Localhost", 1, "Warrior");
break;
}
return false;
for (auto &item : SELUDPGAME_DIALOG) {
if (item.caption != NULL && !(item.flags & (UIS_VCENTER | UIS_CENTER)))
WordWrap(&item);
}
}
bool selhero_Event_DifficultySelection(int *dlgresult)
void selhero_Event_DifficultySelection()
{
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (UiFocusNavigation(&event))
continue;
if (UiItemMouseEvents(&event, SELDIFF_DIALOG, size(SELDIFF_DIALOG)))
continue;
switch (event.type) {
case SDL_KEYDOWN:
if (UiFocuseNavigation(&event, true))
break;
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
SetMenu(SELHERO_SELECT_GAME);
SelectedItemMax += 1;
submenu = SELHERO_SELECT_GAME;
UiInitList(0, 2, selhero_Focus_GameSelection, selhero_Select_GameSelection);
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
case SDLK_SPACE:
switch (SelectedItem) {
case 1:
gnDifficulty = DIFF_NORMAL;
break;
case 2:
gnDifficulty = DIFF_NIGHTMARE;
break;
case 3:
gnDifficulty = DIFF_HELL;
break;
}
*dlgresult = NEW_GAME;
return true;
}
break;
case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) {
SDL_Rect CreateHeroCancelBox;
CreateHeroCancelBox.y = 550;
CreateHeroCancelBox.x = 675;
CreateHeroCancelBox.w = 100;
CreateHeroCancelBox.h = 30;
SDL_Rect NormalSelectBox;
NormalSelectBox.x = 280;
NormalSelectBox.y = 350;
NormalSelectBox.w = 300;
NormalSelectBox.h = 30;
if (IsInsideRect(&event, &NormalSelectBox)) {
gnDifficulty = DIFF_NORMAL;
*dlgresult = LOAD_GAME;
}
break;
selhero_endMenu_Single = true;
}
break;
case SDL_QUIT:
exit(0);
}
}
return false;
}
void selhero_Render_GameSelection()
{
DrawArt(0, 0, &ArtBackground);
DrawLogo();
DrawArtStr(0, 161, AFT_BIG, AFC_SILVER, "Join UPD Game", JustCentre);
int w = 333;
int x = 281;
int y = 282;
DrawArtStr(x, 211, AFT_BIG, AFC_SILVER, "Select Action", JustCentre, w);
char *gameOptions[] = { "Create Game", "Enter IP", "Localhost" };
DrawArtStr(35, 211, AFT_MED, AFC_SILVER, "Description:");
if (SelectedItem == 1) {
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Create a new game with");
DrawArtStr(35, 272, AFT_SMALL, AFC_SILVER, "a difficulty setting of");
DrawArtStr(35, 288, AFT_SMALL, AFC_SILVER, "your choice.");
} else if (SelectedItem == 2) {
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Join a game directly");
DrawArtStr(35, 272, AFT_SMALL, AFC_SILVER, "via a know host IP.");
} else {
DrawArtStr(35, 256, AFT_SMALL, AFC_SILVER, "Normal Difficulty");
DrawArtStr(35, 272, AFT_SMALL, AFC_SILVER, "Created by Localhost, A");
DrawArtStr(35, 288, AFT_SMALL, AFC_SILVER, "level 1 Warrior.");
}
int selectorTop = y;
int spacing = 26;
for (int i = 0; i < 3; i++) {
DrawArtStr(x, y, AFT_MED, AFC_GOLD, gameOptions[i], JustCentre, w);
y += spacing;
}
DrawSelector(x, selectorTop + 3, w, 19, spacing, FOCUS_SMALL);
DrawArtStr(349, 429, AFT_BIG, AFC_GOLD, "OK");
DrawArtStr(471, 429, AFT_BIG, AFC_GOLD, "Cancel");
}
BOOL __stdcall UiSelHeroMultDialog(
@ -596,10 +591,11 @@ BOOL __stdcall UiSelHeroMultDialog(
BOOL *hero_is_created,
char *name)
{
gfnHeroStats = fnstats;
*hero_is_created = false;
selhero_Load(fninfo);
bool abort = UiSelHeroDialog(fncreate, fnremove, fnstats, true);
bool abort = UiSelHeroDialog(fncreate, fnremove, true);
BlackPalette();
selhero_Free();
if (abort) {
@ -612,35 +608,28 @@ BOOL __stdcall UiSelHeroMultDialog(
selhero_multi_Load();
submenu = SELHERO_SELECT_GAME;
UiInitList(0, 2, selhero_Focus_GameSelection, selhero_Select_GameSelection);
SelectedItem = 1;
SelectedItemMax = 2 + 1;
bool endMenu = false;
while (endMenu == false) {
CapFPS();
selhero_endMenu_Single = false;
while (!selhero_endMenu_Single) {
switch (submenu) {
case SELHERO_SELECT_GAME:
selhero_Render_GameSelection();
endMenu = selhero_Event_GameSelection(dlgresult);
UiRenderItems(SELUDPGAME_DIALOG, size(SELUDPGAME_DIALOG));
selhero_Event_GameSelection();
break;
case SELHERO_DIFFICULTY:
selhero_Render_DifficultySelection();
endMenu = selhero_Event_DifficultySelection(dlgresult);
UiRenderItems(SELDIFF_DIALOG, size(SELDIFF_DIALOG));
selhero_Event_DifficultySelection();
break;
}
DrawLogo();
DrawMouse();
UiFadeIn();
}
if (*dlgresult != EXIT_MENU) {
strcpy(name, heroInfo.name);
}
BlackPalette();
selhero_Free();
*dlgresult = selhero_result;
return TRUE;
}

3
Stub/DiabloUI/selhero.h

@ -0,0 +1,3 @@
#include "../../types.h"
void selhero_Select_List(int value);

18
Stub/DiabloUI/title.cpp

@ -1,12 +1,5 @@
#include "../../types.h"
void title_Render()
{
DrawArt(0, 0, &ArtBackground);
DrawArtStr(0, 409, AFT_MED, AFC_SILVER, "Copyright \xA9 1996-2001 Blizzard Entertainment", JustCentre);
DrawLogo(182, LOGO_BIG);
}
void title_Load()
{
LoadBackgroundArt("ui_art\\title.pcx");
@ -23,6 +16,11 @@ void title_Free()
BOOL __stdcall UiTitleDialog(int a1)
{
UI_Item TITLESCREEN_DIALOG[] = {
{ { 0, 0, 640, 480 }, UI_IMAGE, 0, 0, NULL, &ArtBackground },
{ { 49, 410, 550, 26 }, UI_TEXT, UIS_MED | UIS_CENTER, 0, "Copyright \xA9 1996-2001 Blizzard Entertainment" },
};
title_Load();
bool endMenu = false;
@ -30,13 +28,13 @@ BOOL __stdcall UiTitleDialog(int a1)
SDL_Event event;
while (!endMenu && SDL_GetTicks() < timeOut) {
CapFPS();
title_Render();
UiRenderItems(TITLESCREEN_DIALOG, size(TITLESCREEN_DIALOG));
DrawLogo(182, LOGO_BIG);
UiFadeIn();
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:/*
case SDL_KEYDOWN: /* To match the original uncomment this
if (event.key.keysym.sym == SDLK_UP
|| event.key.keysym.sym == SDLK_UP
|| event.key.keysym.sym == SDLK_LEFT

9
enums.h

@ -2252,15 +2252,6 @@ typedef enum _mainmenu_selections {
MAINMENU_ATTRACT_MODE = 6,
} _mainmenu_selections;
typedef enum menus
{
SELHERO_LOAD,
SELHERO_CLASSES,
SELHERO_NAME,
SELHERO_SELECT_GAME,
SELHERO_DIFFICULTY,
} menus;
typedef enum dlgresults
{
NEW_GAME = 0,

Loading…
Cancel
Save