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.
 
 
 
 
 
 

221 lines
5.9 KiB

#include "DiabloUI/hub/hub.h"
#include <fmt/format.h>
#include "DiabloUI/button.h"
#include "DiabloUI/diabloui.h"
#include "DiabloUI/dialogs.h"
#include "DiabloUI/hero/selhero.h"
#include "DiabloUI/hub/chat.h"
#include "DiabloUI/hub/create.h"
#include "DiabloUI/hub/friends.h"
#include "DiabloUI/hub/join.h"
#include "DiabloUI/scrollbar.h"
#include "DiabloUI/selok.h"
#include "config.h"
#include "control.h"
#include "engine/assets.hpp"
#include "engine/load_clx.hpp"
#include "menu.h"
#include "options.h"
#include "storm/storm_net.hpp"
#include "utils/language.h"
#include "utils/str_cat.hpp"
#include "utils/utf8.hpp"
namespace devilution {
bool hubmain_endMenu;
std::vector<std::unique_ptr<UiItemBase>> vecHubMainDialog;
OptionalOwnedClxSpriteList Layout;
namespace {
enum class HubPanels : uint8_t {
Chat,
Friends,
Create,
Join,
};
HubPanels HubPanel = HubPanels::Join;
OptionalOwnedClxSpriteList PlayerIcons;
OptionalOwnedClxSpriteList PlayerSpawnIcon;
OptionalOwnedClxSpriteList PlayerLevelFont;
OptionalOwnedClxSpriteList LagGreen;
OptionalOwnedClxSpriteList LagYellow;
OptionalOwnedClxSpriteList LagRed;
void LoadHubPlayerGraphics()
{
PlayerIcons = LoadPcxSpriteList("ui_art\\heroport", -14);
PlayerSpawnIcon = LoadPcx("ui_art\\spwnport");
PlayerLevelFont = LoadPcxSpriteList("ui_art\\heronum", 10);
LagGreen = LoadPcx("ui_art\\greenlag");
LagYellow = LoadPcx("ui_art\\yellolag");
LagRed = LoadPcx("ui_art\\redlag");
}
std::vector<std::unique_ptr<UiItemBase>> vecHubBackground;
void hub_Init()
{
LoadDialogButtonGraphics();
LoadHubScrollBar();
LoadBackgroundArt("ui_art\\bnconnbg");
ArtBackgroundWidescreen = LoadOptionalClx("ui_art\\bnconnbgw.clx");
uint8_t transparentColor = 250;
AssetRef ref = FindAsset("ui_art\\xsmlogo");
if (ref.ok() && ref.size() == 167723)
transparentColor = 32;
ArtLogo = LoadPcxSpriteList("ui_art\\xsmlogo", /*numFrames=*/15, transparentColor);
switch (HubPanel) {
case HubPanels::Chat:
hubmain_Init();
break;
case HubPanels::Friends:
break;
case HubPanels::Create:
HubLoadCreate();
break;
case HubPanels::Join:
HubLoadJoin();
break;
}
LoadHubPlayerGraphics();
}
void hubmain_Free()
{
FreeDialogButtonGraphics();
ArtBackground = std::nullopt;
ArtBackgroundWidescreen = std::nullopt;
Layout = std::nullopt;
vecHubMainDialog.clear();
}
bool IsKnownHeroType(uint32_t gameMode, HeroClass heroClass)
{
if (gameMode != GameIdDiabloFull && gameMode != GameIdHellfireFull)
return false;
return heroClass == HeroClass::Warrior
|| heroClass == HeroClass::Rogue
|| heroClass == HeroClass::Sorcerer;
}
} // namespace
void LoadHubScrollBar()
{
ScrollBarWidth = 17;
ScrollBarArrowFrame_UP_ACTIVE = 2;
ScrollBarArrowFrame_UP = 0;
ScrollBarArrowFrame_DOWN_ACTIVE = 3;
ScrollBarArrowFrame_DOWN = 1;
ArtScrollBarArrow = LoadPcxSpriteList("ui_art\\scrlarrw", 4);
ArtScrollBarBackground = LoadPcx("ui_art\\scrlbar");
ArtScrollBarThumb = LoadPcx("ui_art\\scrlthmb");
}
void UiHubPlacePlayerIcon(Point position, uint32_t gameMode, const PlayerInfo &player)
{
ClxSprite sprite = (*PlayerSpawnIcon)[0];
if (IsKnownHeroType(gameMode, player.heroClass)) {
int level = player.diabloKillLevel * 3;
sprite = (*PlayerIcons)[level + static_cast<uint8_t>(player.heroClass)];
}
const SDL_Rect rect0 = MakeSdlRect(position.x, position.y, 0, 0);
vecHubMainDialog.push_back(std::make_unique<UiImageClx>(sprite, rect0));
const SDL_Rect rect1 = MakeSdlRect(position.x + 20, position.y + 5, 0, 0);
vecHubMainDialog.push_back(std::make_unique<UiImageClx>((*PlayerLevelFont)[player.level % 10], rect1));
if (player.level > 9) {
const SDL_Rect rect2 = MakeSdlRect(position.x + 14, position.y + 5, 0, 0);
vecHubMainDialog.push_back(std::make_unique<UiImageClx>((*PlayerLevelFont)[player.level / 10], rect2));
}
}
void UiHubPlaceLatencyMeter(int latency, Point position)
{
int bars = latency / 50 + 1;
bars = std::min(bars, 6);
ClxSprite lagSprite = (*LagRed)[0];
if (bars <= 2)
lagSprite = (*LagGreen)[0];
else if (bars <= 4)
lagSprite = (*LagYellow)[0];
const SDL_Rect rect4 = MakeSdlRect(position.x, position.y, 3 * bars, 11);
vecHubMainDialog.push_back(std::make_unique<UiImageClx>(lagSprite, rect4));
}
void hubmain_GameSelection_Focus(int value)
{
}
void hubmain_Diff_Select(int value)
{
}
void hubmain_GameSelection_Esc()
{
UiInitList_clear();
hubmain_endMenu = true;
}
void hub_GameSelection_Init()
{
const Point uiPosition = GetUIRectangle().position;
const SDL_Rect rect0 = MakeSdlRect(0, uiPosition.y, 0, 0);
vecHubBackground.push_back(std::make_unique<UiImageClx>((*ArtBackground)[0], rect0, UiFlags::AlignCenter));
vecHubBackground.push_back(std::make_unique<UiImageClx>((*ArtBackgroundWidescreen)[0], rect0, UiFlags::AlignCenter));
vecHubBackground.push_back(std::make_unique<UiImageAnimatedClx>(*ArtLogo, MakeSdlRect(uiPosition.x, uiPosition.y, 0, 0)));
const SDL_Rect rect1 = MakeSdlRect(uiPosition.x, uiPosition.y + (*ArtBackground)[0].height() - (*Layout)[0].height(), (*Layout)[0].width(), (*Layout)[0].height());
vecHubBackground.push_back(std::make_unique<UiImageClx>((*Layout)[0], rect1, UiFlags::AlignCenter));
switch (HubPanel) {
case HubPanels::Chat:
hubmain_GameSelection_Init();
break;
case HubPanels::Friends:
break;
case HubPanels::Create:
HubInitCreate();
break;
case HubPanels::Join:
HubInitJoin();
break;
}
UiInitList(hubmain_GameSelection_Focus, hubmain_Diff_Select, hubmain_GameSelection_Esc, vecHubMainDialog, true);
}
bool UiHubMain()
{
hub_Init();
hub_GameSelection_Init();
hubmain_endMenu = false;
while (!hubmain_endMenu) {
UiClearScreen();
UiRenderItems(vecHubBackground);
if (HubPanel == HubPanels::Chat)
DrawChat();
UiPollAndRender();
}
hubmain_Free();
return true;
}
} // namespace devilution