You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
658 lines
21 KiB
658 lines
21 KiB
|
7 years ago
|
#include "selhero.h"
|
||
|
|
|
||
|
7 years ago
|
#include <algorithm>
|
||
|
6 years ago
|
#include <chrono>
|
||
|
|
#include <random>
|
||
|
7 years ago
|
|
||
|
5 years ago
|
#include "control.h"
|
||
|
7 years ago
|
#include "DiabloUI/diabloui.h"
|
||
|
6 years ago
|
#include "DiabloUI/dialogs.h"
|
||
|
|
#include "DiabloUI/scrollbar.h"
|
||
|
6 years ago
|
#include "DiabloUI/selgame.h"
|
||
|
5 years ago
|
#include "DiabloUI/selok.h"
|
||
|
|
#include "DiabloUI/selyesno.h"
|
||
|
5 years ago
|
#include "options.h"
|
||
|
5 years ago
|
#include "pfile.h"
|
||
|
7 years ago
|
|
||
|
6 years ago
|
#ifdef __3DS__
|
||
|
5 years ago
|
#include "platform/ctr/keyboard.h"
|
||
|
6 years ago
|
#endif
|
||
|
|
|
||
|
5 years ago
|
namespace devilution {
|
||
|
7 years ago
|
|
||
|
5 years ago
|
static const char *selhero_GenerateName(HeroClass hero_class);
|
||
|
6 years ago
|
|
||
|
7 years ago
|
std::size_t selhero_SaveCount = 0;
|
||
|
7 years ago
|
_uiheroinfo selhero_heros[MAX_CHARACTERS];
|
||
|
|
_uiheroinfo selhero_heroInfo;
|
||
|
6 years ago
|
const size_t kMaxViewportItems = 6;
|
||
|
7 years ago
|
char textStats[5][4];
|
||
|
|
char title[32];
|
||
|
|
char selhero_Lable[32];
|
||
|
|
char selhero_Description[256];
|
||
|
5 years ago
|
_selhero_selections selhero_result;
|
||
|
7 years ago
|
bool selhero_endMenu;
|
||
|
|
bool selhero_isMultiPlayer;
|
||
|
|
bool selhero_navigateYesNo;
|
||
|
|
bool selhero_deleteEnabled;
|
||
|
|
|
||
|
5 years ago
|
bool(*gfnHeroInfo)
|
||
|
|
(bool (*fninfofunc)(_uiheroinfo *));
|
||
|
|
bool(*gfnHeroCreate)
|
||
|
7 years ago
|
(_uiheroinfo *);
|
||
|
5 years ago
|
void (*gfnHeroStats)(unsigned int, _uidefaultstats *);
|
||
|
7 years ago
|
|
||
|
7 years ago
|
namespace {
|
||
|
|
|
||
|
6 years ago
|
std::vector<UiItemBase *> vecSelHeroDialog;
|
||
|
|
std::vector<UiListItem *> vecSelHeroDlgItems;
|
||
|
|
std::vector<UiItemBase *> vecSelDlgItems;
|
||
|
7 years ago
|
|
||
|
6 years ago
|
UiImage *SELHERO_DIALOG_HERO_IMG;
|
||
|
7 years ago
|
} // namespace
|
||
|
|
|
||
|
6 years ago
|
bool bUIElementsLoaded = false;
|
||
|
|
|
||
|
7 years ago
|
void selhero_UiFocusNavigationYesNo()
|
||
|
|
{
|
||
|
|
if (selhero_deleteEnabled)
|
||
|
|
UiFocusNavigationYesNo();
|
||
|
|
}
|
||
|
|
|
||
|
6 years ago
|
void selhero_FreeListItems()
|
||
|
|
{
|
||
|
|
for (std::size_t i = 0; i < vecSelHeroDlgItems.size(); i++) {
|
||
|
|
UiListItem *pUIItem = vecSelHeroDlgItems[i];
|
||
|
|
delete pUIItem;
|
||
|
|
}
|
||
|
|
vecSelHeroDlgItems.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_FreeDlgItems()
|
||
|
|
{
|
||
|
|
for (std::size_t i = 0; i < vecSelDlgItems.size(); i++) {
|
||
|
|
UiItemBase *pUIItem = vecSelDlgItems[i];
|
||
|
|
delete pUIItem;
|
||
|
|
}
|
||
|
|
vecSelDlgItems.clear();
|
||
|
|
}
|
||
|
|
|
||
|
7 years ago
|
void selhero_Free()
|
||
|
|
{
|
||
|
|
ArtBackground.Unload();
|
||
|
6 years ago
|
|
||
|
|
for (std::size_t i = 0; i < vecSelHeroDialog.size(); i++) {
|
||
|
|
UiItemBase *pUIItem = vecSelHeroDialog[i];
|
||
|
|
delete pUIItem;
|
||
|
|
}
|
||
|
|
vecSelHeroDialog.clear();
|
||
|
|
|
||
|
|
selhero_FreeDlgItems();
|
||
|
|
selhero_FreeListItems();
|
||
|
5 years ago
|
UnloadScrollBar();
|
||
|
6 years ago
|
|
||
|
|
bUIElementsLoaded = false;
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
|
void selhero_SetStats()
|
||
|
|
{
|
||
|
5 years ago
|
SELHERO_DIALOG_HERO_IMG->m_frame = static_cast<int>(selhero_heroInfo.heroclass);
|
||
|
6 years ago
|
snprintf(textStats[0], sizeof(textStats[0]), "%d", selhero_heroInfo.level);
|
||
|
|
snprintf(textStats[1], sizeof(textStats[1]), "%d", selhero_heroInfo.strength);
|
||
|
|
snprintf(textStats[2], sizeof(textStats[2]), "%d", selhero_heroInfo.magic);
|
||
|
|
snprintf(textStats[3], sizeof(textStats[3]), "%d", selhero_heroInfo.dexterity);
|
||
|
|
snprintf(textStats[4], sizeof(textStats[4]), "%d", selhero_heroInfo.vitality);
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
7 years ago
|
namespace {
|
||
|
|
|
||
|
6 years ago
|
std::size_t listOffset = 0;
|
||
|
|
UiArtTextButton *SELLIST_DIALOG_DELETE_BUTTON;
|
||
|
|
|
||
|
7 years ago
|
void selhero_UpdateViewportItems()
|
||
|
7 years ago
|
{
|
||
|
7 years ago
|
const std::size_t num_viewport_heroes = std::min(selhero_SaveCount - listOffset, kMaxViewportItems);
|
||
|
|
for (std::size_t i = 0; i < num_viewport_heroes; i++) {
|
||
|
|
const std::size_t index = i + listOffset;
|
||
|
6 years ago
|
vecSelHeroDlgItems[i]->m_text = selhero_heros[index].name;
|
||
|
|
vecSelHeroDlgItems[i]->m_value = static_cast<int>(index);
|
||
|
7 years ago
|
}
|
||
|
|
if (num_viewport_heroes < kMaxViewportItems) {
|
||
|
6 years ago
|
vecSelHeroDlgItems[num_viewport_heroes]->m_text = "New Hero";
|
||
|
|
vecSelHeroDlgItems[num_viewport_heroes]->m_value = static_cast<int>(selhero_SaveCount);
|
||
|
7 years ago
|
}
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
|
void selhero_ScrollIntoView(std::size_t index)
|
||
|
|
{
|
||
|
|
std::size_t new_offset = listOffset;
|
||
|
|
if (index >= listOffset + kMaxViewportItems)
|
||
|
|
new_offset = index - (kMaxViewportItems - 1);
|
||
|
|
if (index < listOffset)
|
||
|
|
new_offset = index;
|
||
|
|
if (new_offset != listOffset) {
|
||
|
|
listOffset = new_offset;
|
||
|
|
selhero_UpdateViewportItems();
|
||
|
|
}
|
||
|
|
}
|
||
|
7 years ago
|
|
||
|
5 years ago
|
bool SelHero_GetHeroInfo(_uiheroinfo *pInfo)
|
||
|
5 years ago
|
{
|
||
|
|
selhero_heros[selhero_SaveCount] = *pInfo;
|
||
|
|
selhero_SaveCount++;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
7 years ago
|
} // namespace
|
||
|
|
|
||
|
6 years ago
|
void selhero_Init()
|
||
|
|
{
|
||
|
|
LoadBackgroundArt("ui_art\\selhero.pcx");
|
||
|
|
UiAddBackground(&vecSelHeroDialog);
|
||
|
|
UiAddLogo(&vecSelHeroDialog);
|
||
|
|
LoadScrollBar();
|
||
|
|
|
||
|
5 years ago
|
selhero_SaveCount = 0;
|
||
|
|
gfnHeroInfo(SelHero_GetHeroInfo);
|
||
|
|
std::reverse(selhero_heros, selhero_heros + selhero_SaveCount);
|
||
|
|
|
||
|
6 years ago
|
selhero_FreeDlgItems();
|
||
|
5 years ago
|
SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 24), (Sint16)(UI_OFFSET_Y + 161), 590, 35 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText(title, rect1, UIS_CENTER | UIS_BIG));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 30), (Sint16)(UI_OFFSET_Y + 211), 180, 76 };
|
||
|
5 years ago
|
SELHERO_DIALOG_HERO_IMG = new UiImage(&ArtHero, static_cast<int>(enum_size<HeroClass>::value), rect2);
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(SELHERO_DIALOG_HERO_IMG);
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 323), 110, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText("Level:", rect3, UIS_RIGHT));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 323), 110, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText("Level:", rect4, UIS_RIGHT));
|
||
|
5 years ago
|
SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 323), 40, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText(textStats[0], rect5, UIS_CENTER));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect6 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 358), 110, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText("Strength:", rect6, UIS_RIGHT));
|
||
|
5 years ago
|
SDL_Rect rect7 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 358), 40, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText(textStats[1], rect7, UIS_CENTER));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect8 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 380), 110, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText("Magic:", rect8, UIS_RIGHT));
|
||
|
5 years ago
|
SDL_Rect rect9 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 380), 40, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText(textStats[2], rect9, UIS_CENTER));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect10 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 401), 110, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText("Dexterity:", rect10, UIS_RIGHT));
|
||
|
5 years ago
|
SDL_Rect rect11 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 401), 40, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText(textStats[3], rect11, UIS_CENTER));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect12 = { (Sint16)(PANEL_LEFT + 39), (Sint16)(UI_OFFSET_Y + 422), 110, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText("Vitality:", rect12, UIS_RIGHT));
|
||
|
5 years ago
|
SDL_Rect rect13 = { (Sint16)(PANEL_LEFT + 159), (Sint16)(UI_OFFSET_Y + 422), 40, 21 };
|
||
|
6 years ago
|
vecSelHeroDialog.push_back(new UiArtText(textStats[4], rect13, UIS_CENTER));
|
||
|
|
}
|
||
|
|
|
||
|
7 years ago
|
void selhero_List_Init()
|
||
|
|
{
|
||
|
|
listOffset = 0;
|
||
|
6 years ago
|
selhero_FreeDlgItems();
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtText("Select Hero", rect1, UIS_CENTER | UIS_BIG));
|
||
|
|
|
||
|
|
selhero_FreeListItems();
|
||
|
|
const size_t num_viewport_heroes = std::min(selhero_SaveCount + 1, kMaxViewportItems);
|
||
|
|
for (std::size_t i = 0; i < num_viewport_heroes; i++) {
|
||
|
|
vecSelHeroDlgItems.push_back(new UiListItem("", -1));
|
||
|
|
}
|
||
|
7 years ago
|
selhero_UpdateViewportItems();
|
||
|
6 years ago
|
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiList(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 256), 320, 26, UIS_CENTER | UIS_MED | UIS_GOLD));
|
||
|
6 years ago
|
|
||
|
5 years ago
|
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 585), (Sint16)(UI_OFFSET_Y + 244), 25, 178 };
|
||
|
6 years ago
|
UiScrollBar *scrollBar = new UiScrollBar(&ArtScrollBarBackground, &ArtScrollBarThumb, &ArtScrollBarArrow, rect2);
|
||
|
|
vecSelDlgItems.push_back(scrollBar);
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 239), (Sint16)(UI_OFFSET_Y + 429), 120, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("OK", &UiFocusNavigationSelect, rect3, UIS_CENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 364), (Sint16)(UI_OFFSET_Y + 429), 120, 35 };
|
||
|
6 years ago
|
SELLIST_DIALOG_DELETE_BUTTON = new UiArtTextButton("Delete", &selhero_UiFocusNavigationYesNo, rect4, UIS_CENTER | UIS_BIG | UIS_DISABLED);
|
||
|
|
vecSelDlgItems.push_back(SELLIST_DIALOG_DELETE_BUTTON);
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect5 = { (Sint16)(PANEL_LEFT + 489), (Sint16)(UI_OFFSET_Y + 429), 120, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("Cancel", &UiFocusNavigationEsc, rect5, UIS_CENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
6 years ago
|
UiInitList(selhero_SaveCount + 1, selhero_List_Focus, selhero_List_Select, selhero_List_Esc, vecSelDlgItems, false, selhero_List_DeleteYesNo);
|
||
|
6 years ago
|
UiInitScrollBar(scrollBar, kMaxViewportItems, &listOffset);
|
||
|
7 years ago
|
if (selhero_isMultiPlayer) {
|
||
|
7 years ago
|
strcpy(title, "Multi Player Characters");
|
||
|
7 years ago
|
} else {
|
||
|
|
strcpy(title, "Single Player Characters");
|
||
|
7 years ago
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_List_Focus(int value)
|
||
|
|
{
|
||
|
7 years ago
|
const std::size_t index = static_cast<std::size_t>(value);
|
||
|
|
selhero_ScrollIntoView(index);
|
||
|
7 years ago
|
int baseFlags = UIS_CENTER | UIS_BIG;
|
||
|
7 years ago
|
if (selhero_SaveCount && index < selhero_SaveCount) {
|
||
|
|
memcpy(&selhero_heroInfo, &selhero_heros[index], sizeof(selhero_heroInfo));
|
||
|
7 years ago
|
selhero_SetStats();
|
||
|
6 years ago
|
SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UIS_GOLD;
|
||
|
7 years ago
|
selhero_deleteEnabled = true;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
5 years ago
|
SELHERO_DIALOG_HERO_IMG->m_frame = static_cast<int>(enum_size<HeroClass>::value);
|
||
|
6 years ago
|
strncpy(textStats[0], "--", sizeof(textStats[0]) - 1);
|
||
|
|
strncpy(textStats[1], "--", sizeof(textStats[1]) - 1);
|
||
|
|
strncpy(textStats[2], "--", sizeof(textStats[2]) - 1);
|
||
|
|
strncpy(textStats[3], "--", sizeof(textStats[3]) - 1);
|
||
|
|
strncpy(textStats[4], "--", sizeof(textStats[4]) - 1);
|
||
|
6 years ago
|
SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UIS_DISABLED;
|
||
|
7 years ago
|
selhero_deleteEnabled = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool selhero_List_DeleteYesNo()
|
||
|
|
{
|
||
|
|
selhero_navigateYesNo = selhero_deleteEnabled;
|
||
|
|
|
||
|
|
return selhero_navigateYesNo;
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_List_Select(int value)
|
||
|
|
{
|
||
|
7 years ago
|
if (static_cast<std::size_t>(value) == selhero_SaveCount) {
|
||
|
6 years ago
|
selhero_FreeDlgItems();
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtText("Choose Class", rect1, UIS_CENTER | UIS_BIG));
|
||
|
|
|
||
|
|
selhero_FreeListItems();
|
||
|
6 years ago
|
int itemH = 33;
|
||
|
5 years ago
|
vecSelHeroDlgItems.push_back(new UiListItem("Warrior", static_cast<int>(HeroClass::Warrior)));
|
||
|
|
vecSelHeroDlgItems.push_back(new UiListItem("Rogue", static_cast<int>(HeroClass::Rogue)));
|
||
|
|
vecSelHeroDlgItems.push_back(new UiListItem("Sorcerer", static_cast<int>(HeroClass::Sorcerer)));
|
||
|
5 years ago
|
if (gbIsHellfire) {
|
||
|
5 years ago
|
vecSelHeroDlgItems.push_back(new UiListItem("Monk", static_cast<int>(HeroClass::Monk)));
|
||
|
5 years ago
|
}
|
||
|
5 years ago
|
if (gbBard || sgOptions.Gameplay.bTestBard) {
|
||
|
5 years ago
|
vecSelHeroDlgItems.push_back(new UiListItem("Bard", static_cast<int>(HeroClass::Bard)));
|
||
|
6 years ago
|
}
|
||
|
5 years ago
|
if (gbBarbarian || sgOptions.Gameplay.bTestBarbarian) {
|
||
|
5 years ago
|
vecSelHeroDlgItems.push_back(new UiListItem("Barbarian", static_cast<int>(HeroClass::Barbarian)));
|
||
|
6 years ago
|
}
|
||
|
|
if (vecSelHeroDlgItems.size() > 4)
|
||
|
|
itemH = 26;
|
||
|
|
int itemY = 246 + (176 - vecSelHeroDlgItems.size() * itemH) / 2;
|
||
|
|
vecSelDlgItems.push_back(new UiList(vecSelHeroDlgItems, PANEL_LEFT + 264, (UI_OFFSET_Y + itemY), 320, itemH, UIS_CENTER | UIS_MED | UIS_GOLD));
|
||
|
6 years ago
|
|
||
|
5 years ago
|
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 429), 140, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("OK", &UiFocusNavigationSelect, rect2, UIS_CENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 429), (Sint16)(UI_OFFSET_Y + 429), 140, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("Cancel", &UiFocusNavigationEsc, rect3, UIS_CENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
6 years ago
|
UiInitList(vecSelHeroDlgItems.size(), selhero_ClassSelector_Focus, selhero_ClassSelector_Select, selhero_ClassSelector_Esc, vecSelDlgItems);
|
||
|
7 years ago
|
memset(&selhero_heroInfo.name, 0, sizeof(selhero_heroInfo.name));
|
||
|
6 years ago
|
strncpy(title, "New Single Player Hero", sizeof(title) - 1);
|
||
|
7 years ago
|
if (selhero_isMultiPlayer) {
|
||
|
6 years ago
|
strncpy(title, "New Multi Player Hero", sizeof(title) - 1);
|
||
|
7 years ago
|
}
|
||
|
|
return;
|
||
|
6 years ago
|
}
|
||
|
|
|
||
|
|
if (selhero_heroInfo.hassaved) {
|
||
|
|
selhero_FreeDlgItems();
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtText("Save File Exists", rect1, UIS_CENTER | UIS_BIG));
|
||
|
|
|
||
|
|
selhero_FreeListItems();
|
||
|
|
vecSelHeroDlgItems.push_back(new UiListItem("Load Game", 0));
|
||
|
|
vecSelHeroDlgItems.push_back(new UiListItem("New Game", 1));
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiList(vecSelHeroDlgItems, PANEL_LEFT + 265, (UI_OFFSET_Y + 285), 320, 33, UIS_CENTER | UIS_MED | UIS_GOLD));
|
||
|
6 years ago
|
|
||
|
5 years ago
|
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 427), 140, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("OK", &UiFocusNavigationSelect, rect2, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 429), (Sint16)(UI_OFFSET_Y + 427), 140, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("Cancel", &UiFocusNavigationEsc, rect3, UIS_CENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
6 years ago
|
UiInitList(vecSelHeroDlgItems.size(), selhero_Load_Focus, selhero_Load_Select, selhero_List_Init, vecSelDlgItems, true);
|
||
|
6 years ago
|
strncpy(title, "Single Player Characters", sizeof(title) - 1);
|
||
|
7 years ago
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
6 years ago
|
selhero_Load_Select(1);
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
|
void selhero_List_Esc()
|
||
|
|
{
|
||
|
6 years ago
|
UiInitList_clear();
|
||
|
|
|
||
|
7 years ago
|
selhero_endMenu = true;
|
||
|
|
selhero_result = SELHERO_PREVIOUS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_ClassSelector_Focus(int value)
|
||
|
|
{
|
||
|
5 years ago
|
const auto hero_class = static_cast<HeroClass>(vecSelHeroDlgItems[value]->m_value);
|
||
|
5 years ago
|
|
||
|
7 years ago
|
_uidefaultstats defaults;
|
||
|
5 years ago
|
gfnHeroStats(static_cast<unsigned int>(hero_class), &defaults);
|
||
|
7 years ago
|
|
||
|
|
selhero_heroInfo.level = 1;
|
||
|
5 years ago
|
selhero_heroInfo.heroclass = hero_class;
|
||
|
7 years ago
|
selhero_heroInfo.strength = defaults.strength;
|
||
|
|
selhero_heroInfo.magic = defaults.magic;
|
||
|
|
selhero_heroInfo.dexterity = defaults.dexterity;
|
||
|
|
selhero_heroInfo.vitality = defaults.vitality;
|
||
|
|
|
||
|
|
selhero_SetStats();
|
||
|
|
}
|
||
|
|
|
||
|
5 years ago
|
static bool shouldPrefillHeroName()
|
||
|
|
{
|
||
|
5 years ago
|
#if defined __3DS__
|
||
|
|
return false;
|
||
|
|
#elif defined(PREFILL_PLAYER_NAME)
|
||
|
5 years ago
|
return true;
|
||
|
|
#else
|
||
|
|
return sgbControllerActive;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
7 years ago
|
void selhero_ClassSelector_Select(int value)
|
||
|
|
{
|
||
|
5 years ago
|
auto hClass = static_cast<HeroClass>(vecSelHeroDlgItems[value]->m_value);
|
||
|
|
if (gbSpawned && (hClass == HeroClass::Rogue || hClass == HeroClass::Sorcerer || (hClass == HeroClass::Bard && !hfbard_mpq))) {
|
||
|
6 years ago
|
ArtBackground.Unload();
|
||
|
6 years ago
|
UiSelOkDialog(NULL, "The Rogue and Sorcerer are only available in the full retail version of Diablo. Visit https://www.gog.com/game/diablo to purchase.", false);
|
||
|
6 years ago
|
LoadBackgroundArt("ui_art\\selhero.pcx");
|
||
|
|
selhero_List_Select(selhero_SaveCount);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
6 years ago
|
strncpy(title, "New Single Player Hero", sizeof(title) - 1);
|
||
|
7 years ago
|
if (selhero_isMultiPlayer) {
|
||
|
6 years ago
|
strncpy(title, "New Multi Player Hero", sizeof(title) - 1);
|
||
|
7 years ago
|
}
|
||
|
|
memset(selhero_heroInfo.name, '\0', sizeof(selhero_heroInfo.name));
|
||
|
5 years ago
|
#if defined __3DS__
|
||
|
6 years ago
|
ctr_vkbdInput("Enter Hero name..", selhero_GenerateName(selhero_heroInfo.heroclass), selhero_heroInfo.name);
|
||
|
5 years ago
|
#endif
|
||
|
5 years ago
|
if (shouldPrefillHeroName())
|
||
|
|
strncpy(selhero_heroInfo.name, selhero_GenerateName(selhero_heroInfo.heroclass), sizeof(selhero_heroInfo.name) - 1);
|
||
|
6 years ago
|
selhero_FreeDlgItems();
|
||
|
5 years ago
|
SDL_Rect rect1 = { (Sint16)(PANEL_LEFT + 264), (Sint16)(UI_OFFSET_Y + 211), 320, 33 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtText("Enter Name", rect1, UIS_CENTER | UIS_BIG));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect2 = { (Sint16)(PANEL_LEFT + 265), (Sint16)(UI_OFFSET_Y + 317), 320, 33 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiEdit(selhero_heroInfo.name, 15, rect2, UIS_MED | UIS_GOLD));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect3 = { (Sint16)(PANEL_LEFT + 279), (Sint16)(UI_OFFSET_Y + 429), 140, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("OK", &UiFocusNavigationSelect, rect3, UIS_CENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
5 years ago
|
SDL_Rect rect4 = { (Sint16)(PANEL_LEFT + 429), (Sint16)(UI_OFFSET_Y + 429), 140, 35 };
|
||
|
6 years ago
|
vecSelDlgItems.push_back(new UiArtTextButton("Cancel", &UiFocusNavigationEsc, rect4, UIS_CENTER | UIS_BIG | UIS_GOLD));
|
||
|
|
|
||
|
6 years ago
|
UiInitList(0, NULL, selhero_Name_Select, selhero_Name_Esc, vecSelDlgItems);
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
|
void selhero_ClassSelector_Esc()
|
||
|
|
{
|
||
|
6 years ago
|
selhero_FreeDlgItems();
|
||
|
|
selhero_FreeListItems();
|
||
|
|
|
||
|
7 years ago
|
if (selhero_SaveCount) {
|
||
|
|
selhero_List_Init();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
selhero_List_Esc();
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_Name_Select(int value)
|
||
|
|
{
|
||
|
6 years ago
|
|
||
|
6 years ago
|
if (!UiValidPlayerName(selhero_heroInfo.name)) {
|
||
|
6 years ago
|
ArtBackground.Unload();
|
||
|
6 years ago
|
UiSelOkDialog(title, "Invalid name. A name cannot contain spaces, reserved characters, or reserved words.\n", false);
|
||
|
|
LoadBackgroundArt("ui_art\\selhero.pcx");
|
||
|
7 years ago
|
} else {
|
||
|
6 years ago
|
bool overwrite = true;
|
||
|
|
for (std::size_t i = 0; i < selhero_SaveCount; i++) {
|
||
|
|
if (strcasecmp(selhero_heros[i].name, selhero_heroInfo.name) == 0) {
|
||
|
6 years ago
|
ArtBackground.Unload();
|
||
|
6 years ago
|
char dialogText[256];
|
||
|
6 years ago
|
snprintf(dialogText, sizeof(dialogText), "Character already exists. Do you want to overwrite \"%s\"?", selhero_heroInfo.name);
|
||
|
6 years ago
|
overwrite = UiSelHeroYesNoDialog(title, dialogText);
|
||
|
|
LoadBackgroundArt("ui_art\\selhero.pcx");
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (overwrite) {
|
||
|
|
if (gfnHeroCreate(&selhero_heroInfo)) {
|
||
|
6 years ago
|
selhero_Load_Select(1);
|
||
|
6 years ago
|
return;
|
||
|
|
} else {
|
||
|
6 years ago
|
UiErrorOkDialog("Unable to create character.", vecSelDlgItems);
|
||
|
6 years ago
|
}
|
||
|
|
}
|
||
|
7 years ago
|
}
|
||
|
6 years ago
|
|
||
|
|
memset(selhero_heroInfo.name, '\0', sizeof(selhero_heroInfo.name));
|
||
|
6 years ago
|
selhero_ClassSelector_Select(0);
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
|
void selhero_Name_Esc()
|
||
|
|
{
|
||
|
|
selhero_List_Select(selhero_SaveCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_Load_Focus(int value)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void selhero_Load_Select(int value)
|
||
|
|
{
|
||
|
6 years ago
|
UiInitList_clear();
|
||
|
7 years ago
|
selhero_endMenu = true;
|
||
|
6 years ago
|
if (vecSelHeroDlgItems[value]->m_value == 0) {
|
||
|
7 years ago
|
selhero_result = SELHERO_CONTINUE;
|
||
|
|
return;
|
||
|
5 years ago
|
}
|
||
|
|
|
||
|
|
if (!selhero_isMultiPlayer) {
|
||
|
|
// This is part of a dangerous hack to enable difficulty selection in single-player.
|
||
|
|
// FIXME: Dialogs should not refer to each other's variables.
|
||
|
|
|
||
|
|
// We disable `selhero_endMenu` and replace the background and art
|
||
|
|
// and the item list with the difficulty selection ones.
|
||
|
|
//
|
||
|
|
// This means selhero's render loop will render selgame's items,
|
||
|
|
// which happens to work because the render loops are similar.
|
||
|
6 years ago
|
selhero_endMenu = false;
|
||
|
|
selhero_Free();
|
||
|
|
LoadBackgroundArt("ui_art\\selgame.pcx");
|
||
|
|
selgame_GameSelection_Select(0);
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
5 years ago
|
selhero_result = SELHERO_NEW_DUNGEON;
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
5 years ago
|
static void UiSelHeroDialog(
|
||
|
5 years ago
|
bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)),
|
||
|
|
bool (*fncreate)(_uiheroinfo *),
|
||
|
5 years ago
|
void (*fnstats)(unsigned int, _uidefaultstats *),
|
||
|
5 years ago
|
bool (*fnremove)(_uiheroinfo *),
|
||
|
5 years ago
|
_selhero_selections *dlgresult,
|
||
|
5 years ago
|
char (*name)[16])
|
||
|
7 years ago
|
{
|
||
|
6 years ago
|
bUIElementsLoaded = true;
|
||
|
|
|
||
|
7 years ago
|
do {
|
||
|
6 years ago
|
gfnHeroInfo = fninfo;
|
||
|
7 years ago
|
gfnHeroCreate = fncreate;
|
||
|
6 years ago
|
gfnHeroStats = fnstats;
|
||
|
|
selhero_result = *dlgresult;
|
||
|
7 years ago
|
|
||
|
|
selhero_navigateYesNo = false;
|
||
|
|
|
||
|
5 years ago
|
selhero_Init();
|
||
|
7 years ago
|
|
||
|
|
if (selhero_SaveCount) {
|
||
|
|
selhero_List_Init();
|
||
|
|
} else {
|
||
|
|
selhero_List_Select(selhero_SaveCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
selhero_endMenu = false;
|
||
|
|
while (!selhero_endMenu && !selhero_navigateYesNo) {
|
||
|
6 years ago
|
UiClearScreen();
|
||
|
6 years ago
|
UiRenderItems(vecSelHeroDialog);
|
||
|
7 years ago
|
UiPollAndRender();
|
||
|
7 years ago
|
}
|
||
|
|
selhero_Free();
|
||
|
6 years ago
|
|
||
|
7 years ago
|
if (selhero_navigateYesNo) {
|
||
|
6 years ago
|
char dialogTitle[32];
|
||
|
|
char dialogText[256];
|
||
|
|
if (selhero_isMultiPlayer) {
|
||
|
6 years ago
|
strncpy(dialogTitle, "Delete Multi Player Hero", sizeof(dialogTitle) - 1);
|
||
|
6 years ago
|
} else {
|
||
|
6 years ago
|
strncpy(dialogTitle, "Delete Single Player Hero", sizeof(dialogTitle) - 1);
|
||
|
6 years ago
|
}
|
||
|
6 years ago
|
snprintf(dialogText, sizeof(dialogText), "Are you sure you want to delete the character \"%s\"?", selhero_heroInfo.name);
|
||
|
6 years ago
|
|
||
|
|
if (UiSelHeroYesNoDialog(dialogTitle, dialogText))
|
||
|
|
fnremove(&selhero_heroInfo);
|
||
|
7 years ago
|
}
|
||
|
|
} while (selhero_navigateYesNo);
|
||
|
|
|
||
|
|
*dlgresult = selhero_result;
|
||
|
5 years ago
|
strncpy(*name, selhero_heroInfo.name, sizeof(*name));
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
5 years ago
|
void UiSelHeroSingDialog(
|
||
|
5 years ago
|
bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)),
|
||
|
|
bool (*fncreate)(_uiheroinfo *),
|
||
|
|
bool (*fnremove)(_uiheroinfo *),
|
||
|
5 years ago
|
void (*fnstats)(unsigned int, _uidefaultstats *),
|
||
|
5 years ago
|
_selhero_selections *dlgresult,
|
||
|
5 years ago
|
char (*name)[16],
|
||
|
5 years ago
|
_difficulty *difficulty)
|
||
|
7 years ago
|
{
|
||
|
|
selhero_isMultiPlayer = false;
|
||
|
5 years ago
|
UiSelHeroDialog(fninfo, fncreate, fnstats, fnremove, dlgresult, name);
|
||
|
5 years ago
|
*difficulty = nDifficulty;
|
||
|
7 years ago
|
}
|
||
|
|
|
||
|
5 years ago
|
void UiSelHeroMultDialog(
|
||
|
5 years ago
|
bool (*fninfo)(bool (*fninfofunc)(_uiheroinfo *)),
|
||
|
|
bool (*fncreate)(_uiheroinfo *),
|
||
|
|
bool (*fnremove)(_uiheroinfo *),
|
||
|
5 years ago
|
void (*fnstats)(unsigned int, _uidefaultstats *),
|
||
|
5 years ago
|
_selhero_selections *dlgresult,
|
||
|
5 years ago
|
char (*name)[16])
|
||
|
7 years ago
|
{
|
||
|
|
selhero_isMultiPlayer = true;
|
||
|
5 years ago
|
UiSelHeroDialog(fninfo, fncreate, fnstats, fnremove, dlgresult, name);
|
||
|
7 years ago
|
}
|
||
|
6 years ago
|
|
||
|
5 years ago
|
static const char *selhero_GenerateName(HeroClass hero_class)
|
||
|
6 years ago
|
{
|
||
|
5 years ago
|
static const char *const kNames[6][10] = {
|
||
|
6 years ago
|
{
|
||
|
5 years ago
|
// Warrior
|
||
|
6 years ago
|
"Aidan",
|
||
|
|
"Qarak",
|
||
|
|
"Born",
|
||
|
|
"Cathan",
|
||
|
|
"Halbu",
|
||
|
|
"Lenalas",
|
||
|
|
"Maximus",
|
||
|
|
"Vane",
|
||
|
|
"Myrdgar",
|
||
|
|
"Rothat",
|
||
|
|
},
|
||
|
|
{
|
||
|
5 years ago
|
// Rogue
|
||
|
6 years ago
|
"Moreina",
|
||
|
|
"Akara",
|
||
|
|
"Kashya",
|
||
|
|
"Flavie",
|
||
|
|
"Divo",
|
||
|
|
"Oriana",
|
||
|
|
"Iantha",
|
||
|
|
"Shikha",
|
||
|
|
"Basanti",
|
||
|
|
"Elexa",
|
||
|
|
},
|
||
|
|
{
|
||
|
5 years ago
|
// Sorcerer
|
||
|
6 years ago
|
"Jazreth",
|
||
|
|
"Drognan",
|
||
|
|
"Armin",
|
||
|
|
"Fauztin",
|
||
|
|
"Jere",
|
||
|
|
"Kazzulk",
|
||
|
|
"Ranslor",
|
||
|
|
"Sarnakyle",
|
||
|
|
"Valthek",
|
||
|
|
"Horazon",
|
||
|
5 years ago
|
},
|
||
|
|
{
|
||
|
|
// Monk
|
||
|
|
"Akyev",
|
||
|
|
"Dvorak",
|
||
|
|
"Kekegi",
|
||
|
|
"Kharazim",
|
||
|
|
"Mikulov",
|
||
|
|
"Shenlong",
|
||
|
|
"Vedenin",
|
||
|
|
"Vhalit",
|
||
|
|
"Vylnas",
|
||
|
|
"Zhota",
|
||
|
5 years ago
|
},
|
||
|
|
{
|
||
|
|
// Bard (uses Rogue names)
|
||
|
|
"Moreina",
|
||
|
|
"Akara",
|
||
|
|
"Kashya",
|
||
|
|
"Flavie",
|
||
|
|
"Divo",
|
||
|
|
"Oriana",
|
||
|
|
"Iantha",
|
||
|
|
"Shikha",
|
||
|
|
"Basanti",
|
||
|
|
"Elexa",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
// Barbarian
|
||
|
|
"Alaric",
|
||
|
|
"Barloc",
|
||
|
|
"Egtheow",
|
||
|
|
"Guthlaf",
|
||
|
|
"Heorogar",
|
||
|
|
"Hrothgar",
|
||
|
|
"Oslaf",
|
||
|
|
"Qual-Kehk",
|
||
|
|
"Ragnar",
|
||
|
|
"Ulf",
|
||
|
|
},
|
||
|
6 years ago
|
};
|
||
|
6 years ago
|
|
||
|
5 years ago
|
int iRand = rand() % 10;
|
||
|
6 years ago
|
|
||
|
5 years ago
|
return kNames[static_cast<std::size_t>(hero_class) % 6][iRand];
|
||
|
7 years ago
|
}
|
||
|
6 years ago
|
|
||
|
5 years ago
|
} // namespace devilution
|