|
@@ -77,7 +77,7 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
|
|
OBJECT_CONSTRUCTION;
|
|
|
|
|
|
const auto& bgConfig = config["background"];
|
|
|
- if (bgConfig.isVector() && !bgConfig.Vector().empty())
|
|
|
+ if (bgConfig.isVector())
|
|
|
background = std::make_shared<CPicture>(ImagePath::fromJson(*RandomGeneratorUtil::nextItem(bgConfig.Vector(), CRandomGenerator::getDefault())));
|
|
|
|
|
|
if (bgConfig.isString())
|
|
@@ -88,6 +88,12 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
|
|
|
|
|
pos = background->center();
|
|
|
|
|
|
+ for (const JsonNode& node : config["images"].Vector())
|
|
|
+ {
|
|
|
+ auto image = std::make_shared<CPicture>(ImagePath::fromJson(*RandomGeneratorUtil::nextItem(node["name"].Vector(), CRandomGenerator::getDefault())), Point(node["x"].Integer(), node["y"].Integer()));
|
|
|
+ images.push_back(image);
|
|
|
+ }
|
|
|
+
|
|
|
if(!config["video"].isNull())
|
|
|
{
|
|
|
Point videoPosition(config["video"]["x"].Integer(), config["video"]["y"].Integer());
|
|
@@ -97,9 +103,6 @@ CMenuScreen::CMenuScreen(const JsonNode & configNode)
|
|
|
for(const JsonNode & node : config["items"].Vector())
|
|
|
menuNameToEntry.push_back(node["name"].String());
|
|
|
|
|
|
- for(const JsonNode & node : config["images"].Vector())
|
|
|
- images.push_back(CMainMenu::createPicture(node));
|
|
|
-
|
|
|
//Hardcoded entry
|
|
|
menuNameToEntry.push_back("credits");
|
|
|
|
|
@@ -239,14 +242,13 @@ std::shared_ptr<CButton> CMenuEntry::createButton(CMenuScreen * parent, const Js
|
|
|
EShortcut shortcut = ENGINE->shortcuts().findShortcut(button["shortcut"].String());
|
|
|
|
|
|
if (shortcut == EShortcut::NONE && !button["shortcut"].String().empty())
|
|
|
- {
|
|
|
logGlobal->warn("Unknown shortcut '%s' found when loading main menu config!", button["shortcut"].String());
|
|
|
- }
|
|
|
|
|
|
auto result = std::make_shared<CButton>(Point(posx, posy), AnimationPath::fromJson(button["name"]), help, command, shortcut);
|
|
|
|
|
|
if (button["center"].Bool())
|
|
|
result->moveBy(Point(-result->pos.w/2, -result->pos.h/2));
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -259,32 +261,38 @@ CMenuEntry::CMenuEntry(CMenuScreen * parent, const JsonNode & config)
|
|
|
for(const JsonNode & node : config["images"].Vector())
|
|
|
images.push_back(CMainMenu::createPicture(node));
|
|
|
|
|
|
- for (const JsonNode& node : config["buttons"].Vector()) {
|
|
|
+ for (const JsonNode& node : config["buttons"].Vector())
|
|
|
+ {
|
|
|
auto tokens = node["command"].String().find(' ');
|
|
|
std::pair<std::string, std::string> commandParts = {
|
|
|
node["command"].String().substr(0, tokens),
|
|
|
(tokens == std::string::npos) ? "" : node["command"].String().substr(tokens + 1)
|
|
|
};
|
|
|
|
|
|
- if (commandParts.first == "campaigns") {
|
|
|
+ if (commandParts.first == "campaigns")
|
|
|
+ {
|
|
|
const auto& campaign = CMainMenuConfig::get().getCampaigns()[commandParts.second];
|
|
|
|
|
|
- if (!campaign.isStruct()) {
|
|
|
+ if (!campaign.isStruct())
|
|
|
+ {
|
|
|
logGlobal->warn("Campaign set %s not found", commandParts.second);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
bool fileExists = false;
|
|
|
- for (const auto& item : campaign["items"].Vector()) {
|
|
|
+ for (const auto& item : campaign["items"].Vector())
|
|
|
+ {
|
|
|
std::string filename = item["file"].String();
|
|
|
|
|
|
- if (CResourceHandler::get()->existsResource(ResourcePath(filename, EResType::CAMPAIGN))) {
|
|
|
+ if (CResourceHandler::get()->existsResource(ResourcePath(filename, EResType::CAMPAIGN)))
|
|
|
+ {
|
|
|
fileExists = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!fileExists) {
|
|
|
+ if (!fileExists)
|
|
|
+ {
|
|
|
logGlobal->warn("No valid files found for campaign set %s", commandParts.second);
|
|
|
continue;
|
|
|
}
|
|
@@ -300,8 +308,10 @@ CMainMenuConfig::CMainMenuConfig()
|
|
|
: campaignSets(JsonPath::builtin("config/campaignSets.json"))
|
|
|
, config(JsonPath::builtin("config/mainmenu.json"))
|
|
|
{
|
|
|
- if (config["game-select"].Vector().empty())
|
|
|
- handleFatalError("Main menu config is invalid or corrupted. Please disable any mods or reinstall VCMI", false);
|
|
|
+ if (!config["scenario-selection"].isStruct())
|
|
|
+ // Fallback for 1.6 mods
|
|
|
+ if (config["game-select"].Vector().empty())
|
|
|
+ handleFatalError("The main menu configuration file mainmenu.json is invalid or corrupted. Please check the file for errors, verify your mod setup, or reinstall VCMI to resolve the issue.", false);
|
|
|
}
|
|
|
|
|
|
const CMainMenuConfig & CMainMenuConfig::get()
|
|
@@ -477,15 +487,6 @@ CMultiMode::CMultiMode(ESelectionScreen ScreenType)
|
|
|
if (multiplayerConfig.isVector() && !multiplayerConfig.Vector().empty())
|
|
|
picture = std::make_shared<CPicture>(ImagePath::fromJson(*RandomGeneratorUtil::nextItem(multiplayerConfig.Vector(), CRandomGenerator::getDefault())), 16, 77);
|
|
|
|
|
|
- if (multiplayerConfig.isString())
|
|
|
- picture = std::make_shared<CPicture>(ImagePath::fromJson(multiplayerConfig), 16, 77);
|
|
|
-
|
|
|
- if (!picture)
|
|
|
- {
|
|
|
- picture = std::make_shared<CPicture>(ImagePath::builtin("MUMAP.bmp"), 16, 77);
|
|
|
- logGlobal->error("Failed to load multiplayer picture");
|
|
|
- }
|
|
|
-
|
|
|
textTitle = std::make_shared<CTextBox>("", Rect(7, 18, 440, 50), 0, FONT_BIG, ETextAlignment::CENTER, Colors::WHITE);
|
|
|
textTitle->setText(LIBRARY->generaltexth->zelp[263].second);
|
|
|
|
|
@@ -704,25 +705,38 @@ CLoadingScreen::CLoadingScreen(ImagePath background)
|
|
|
ENGINE->music().stopMusic(5000);
|
|
|
|
|
|
const auto& conf = CMainMenuConfig::get().getConfig()["loading"];
|
|
|
- const auto& nameConfig = conf["name"];
|
|
|
|
|
|
- AnimationPath animationPath;
|
|
|
- if (nameConfig.isVector() && !nameConfig.Vector().empty())
|
|
|
- animationPath = AnimationPath::fromJson(*RandomGeneratorUtil::nextItem(nameConfig.Vector(), CRandomGenerator::getDefault()));
|
|
|
+ const auto& backgroundConfig = conf["background"];
|
|
|
+ if (!backgroundConfig.Vector().empty())
|
|
|
+ backimg = std::make_shared<CPicture>(ImagePath::fromJson(*RandomGeneratorUtil::nextItem(backgroundConfig.Vector(), CRandomGenerator::getDefault())));
|
|
|
|
|
|
- if (nameConfig.isString())
|
|
|
- animationPath = AnimationPath::fromJson(nameConfig);
|
|
|
+ for (const JsonNode& node : conf["images"].Vector())
|
|
|
+ {
|
|
|
+ auto image = std::make_shared<CPicture>(ImagePath::fromJson(*RandomGeneratorUtil::nextItem(node["name"].Vector(), CRandomGenerator::getDefault())), Point(node["x"].Integer(), node["y"].Integer()));
|
|
|
+ images.push_back(image);
|
|
|
+ }
|
|
|
|
|
|
- if (conf.isStruct())
|
|
|
+ const auto& loadframeConfig = conf["loadframe"];
|
|
|
+ if (loadframeConfig.isStruct())
|
|
|
{
|
|
|
- const int posx = conf["x"].Integer();
|
|
|
- const int posy = conf["y"].Integer();
|
|
|
- const int blockSize = conf["size"].Integer();
|
|
|
- const int blocksAmount = conf["amount"].Integer();
|
|
|
-
|
|
|
- for (int i = 0; i < blocksAmount; ++i)
|
|
|
+ loadFrame = std::make_shared<CPicture>(
|
|
|
+ ImagePath::fromJson(*RandomGeneratorUtil::nextItem(loadframeConfig["name"].Vector(), CRandomGenerator::getDefault())),
|
|
|
+ loadframeConfig["x"].Integer(),
|
|
|
+ loadframeConfig["y"].Integer()
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ const auto& loadbarConfig = conf["loadbar"];
|
|
|
+ if (loadbarConfig.isStruct())
|
|
|
+ {
|
|
|
+ AnimationPath loadbarPath = AnimationPath::fromJson(*RandomGeneratorUtil::nextItem(loadbarConfig["name"].Vector(), CRandomGenerator::getDefault()));
|
|
|
+ const int posx = loadbarConfig["x"].Integer();
|
|
|
+ const int posy = loadbarConfig["y"].Integer();
|
|
|
+ const int blockSize = loadbarConfig["size"].Integer();
|
|
|
+ const int blocksAmount = loadbarConfig["amount"].Integer();
|
|
|
+ for (int i = 0; i < blocksAmount; ++i)
|
|
|
{
|
|
|
- progressBlocks.push_back(std::make_shared<CAnimImage>(animationPath, i, 0, posx + i * blockSize, posy));
|
|
|
+ progressBlocks.push_back(std::make_shared<CAnimImage>(loadbarPath, i, 0, posx + i * blockSize, posy));
|
|
|
progressBlocks.back()->deactivate();
|
|
|
progressBlocks.back()->visible = false;
|
|
|
}
|