1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Improve mod status window and add warning dialog before startup

This commit is contained in:
Arseniy Shestakov 2018-04-14 22:07:40 +07:00
parent ded71332c9
commit bbc9a0224a
8 changed files with 77 additions and 63 deletions

View File

@ -441,9 +441,9 @@ void CServerHandler::sendGuiAction(ui8 action) const
sendLobbyPack(lga);
}
void CServerHandler::sendStartGame(bool allowOnlyAI) const
void CServerHandler::sendStartGame(ui8 startOptions) const
{
verifyStateBeforeStart(allowOnlyAI ? true : settings["session"]["onlyai"].Bool());
verifyStateBeforeStart(settings["session"]["onlyai"].Bool() ? startOptions | StartInfo::IGNORE_ONLY_AI : startOptions);
LobbyStartGame lsg;
sendLobbyPack(lsg);
}

View File

@ -60,7 +60,7 @@ public:
virtual void setTurnLength(int npos) const = 0;
virtual void sendMessage(const std::string & txt) const = 0;
virtual void sendGuiAction(ui8 action) const = 0; // TODO: possibly get rid of it?
virtual void sendStartGame(bool allowOnlyAI = false) const = 0;
virtual void sendStartGame(ui8 startOptions = StartInfo::NO_OPTIONS) const = 0;
};
/// structure to handle running server and connecting to it
@ -129,7 +129,7 @@ public:
void setTurnLength(int npos) const override;
void sendMessage(const std::string & txt) const override;
void sendGuiAction(ui8 action) const override;
void sendStartGame(bool allowOnlyAI = false) const override;
void sendStartGame(ui8 startOptions = StartInfo::NO_OPTIONS) const override;
void startGameplay();
void endGameplay(bool closeConnection = true);

View File

@ -71,16 +71,16 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType)
card->iconDifficulty->addCallback(std::bind(&IServerAPI::setDifficulty, CSH, _1));
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, false), SDLK_b);
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, StartInfo::NO_OPTIONS), SDLK_b);
initLobby();
break;
}
case ESelectionScreen::loadGame:
{
buttonMods = std::make_shared<CButton>(Point(619, 105), "GSPBUT2.DEF", std::make_pair<std::string, std::string>("", ""), [](){ GH.pushInt(new CModsBox()); }, SDLK_h);
buttonMods = std::make_shared<CButton>(Point(619, 105), "GSPBUT2.DEF", std::make_pair<std::string, std::string>("", ""), [](){ GH.pushInt(new CModStatusBox()); }, SDLK_h);
buttonMods->addTextOverlay(CGI->generaltexth->localizedTexts["lobby"]["buttonMods"]["default"].String(), EFonts::FONT_SMALL, Colors::WHITE);
tabOpt = std::make_shared<OptionsTab>();
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, false), SDLK_l);
buttonStart = std::make_shared<CButton>(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, StartInfo::NO_OPTIONS), SDLK_l);
initLobby();
break;
}
@ -124,11 +124,11 @@ void CLobbyScreen::startCampaign()
}
}
void CLobbyScreen::startScenario(bool allowOnlyAI)
void CLobbyScreen::startScenario(ui8 startOptions)
{
try
{
CSH->sendStartGame(allowOnlyAI);
CSH->sendStartGame(startOptions);
buttonStart->block(true);
}
catch(ExceptionMapMissing & e)
@ -138,7 +138,11 @@ void CLobbyScreen::startScenario(bool allowOnlyAI)
catch(ExceptionNoHuman & e)
{
// You must position yourself prior to starting the game.
CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), 0, std::bind(&CLobbyScreen::startScenario, this, true), PlayerColor(1));
CInfoWindow::showYesNoDialog(std::ref(CGI->generaltexth->allTexts[530]), CInfoWindow::TCompsInfo(), std::bind(&CLobbyScreen::startScenario, this, startOptions | StartInfo::IGNORE_ONLY_AI), 0, PlayerColor(1));
}
catch(ExceptionWrongMods & e)
{
GH.pushInt(new CModStatusBox(true, startOptions));
}
catch(ExceptionNoTemplate & e)
{
@ -225,60 +229,49 @@ const CMapInfo * CLobbyScreen::getMapInfo()
return CSH->mi.get();
}
CModsBox::CModsBox()
CModStatusBox::CModStatusBox(bool showError, ui8 startOptions)
: CWindowObject(BORDERED | SHADOW_DISABLED, "DIBOXBCK")
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
pos.w = 256;
pos.w = 360;
int lineHeight = graphics->fonts[FONT_SMALL]->getLineHeight();
pos.h = 90 + 50 * 3 + lineHeight * CSH->mi->scenarioOptionsOfSave->mods.size();
pos.h = 110 + lineHeight * CSH->mi->scenarioOptionsOfSave->mods.size();
labelTitle = std::make_shared<CLabel>(180, 30, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["title"].String());
labelGroupMods = std::make_shared<CLabelGroup>(FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE);
labelGroupStatusWorking = std::make_shared<CLabelGroup>(FONT_SMALL, EAlignment::TOPLEFT, Colors::GREEN);
labelGroupStatusMissing = std::make_shared<CLabelGroup>(FONT_SMALL, EAlignment::TOPLEFT, Colors::ORANGE);
labelGroupStatusIncompatible = std::make_shared<CLabelGroup>(FONT_SMALL, EAlignment::TOPLEFT, Colors::WHITE);
labelTitle = std::make_shared<CLabel>(128, 30, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["title"].String());
labelGroupStatus = std::make_shared<CLabelGroup>(FONT_SMALL, EAlignment::CENTER, Colors::WHITE);
labelGroupMods = std::make_shared<CLabelGroup>(FONT_SMALL, EAlignment::CENTER, Colors::WHITE);
auto erroredMods = CGI->modh->checkModsPresent(CSH->mi->scenarioOptionsOfSave->mods);
for(int i = 0; i < 3; i++)
for(auto & mod : CSH->mi->scenarioOptionsOfSave->mods)
{
std::vector<ui8> flags;
if(i == 0)
labelGroupStatus->add(128, 65 + 50 * i, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["groups"]["working"].String());
if(i == 1)
labelGroupStatus->add(128, 65 + 50 * i + lineHeight * labelGroupMods->currentSize(), CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["groups"]["missing"].String());
if(i == 2)
labelGroupStatus->add(128, 65 + 50 * i + lineHeight * labelGroupMods->currentSize(), CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["groups"]["incompatible"].String());
for(auto & mod : CSH->mi->scenarioOptionsOfSave->mods)
int positionY = 50 + lineHeight * labelGroupMods->currentSize();
labelGroupMods->add(20, positionY, mod.name.substr(0, 30));
if(!vstd::contains(erroredMods, mod.identifier))
{
if(!vstd::contains(erroredMods, mod.identifier))
{
if(i == 0)
labelGroupMods->add(128, 75 + 50 * i + lineHeight * labelGroupMods->currentSize(), mod.name);
}
else
{
if(i == 1 && erroredMods[mod.identifier] == CModInfo::MISSING)
{
labelGroupMods->add(128, 75 + 50 * i + lineHeight * labelGroupMods->currentSize(), mod.name);
}
else if(i == 2 && erroredMods[mod.identifier] == CModInfo::INCOMPATIBLE)
{
labelGroupMods->add(128, 75 + 50 * i + lineHeight * labelGroupMods->currentSize(), mod.name);
}
}
labelGroupStatusWorking->add(258, positionY, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["groups"]["compatible"].String());
}
for(int j = 0; j < PlayerColor::PLAYER_LIMIT_I; j++)
else if(erroredMods[mod.identifier] == CModInfo::INCOMPATIBLE)
{
if((SEL->getPlayerInfo(j).canHumanPlay || SEL->getPlayerInfo(j).canComputerPlay)
&& SEL->getPlayerInfo(j).team == TeamID(i))
{
flags.push_back(j);
}
labelGroupStatusIncompatible->add(258, positionY, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["groups"]["incompatible"].String());
}
else if(erroredMods[mod.identifier] == CModInfo::MISSING)
{
labelGroupStatusMissing->add(258, positionY, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["groups"]["missing"].String());
}
}
buttonCancel = std::make_shared<CButton>(Point(100, pos.h-50), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE);
if(showError)
{
pos.h += 40;
labelErrorMessage = std::make_shared<CMultiLineLabel>(Rect(20, pos.h-90, 320, graphics->fonts[EFonts::FONT_SMALL]->getLineHeight()*2), EFonts::FONT_SMALL, EAlignment::CENTER, Colors::WHITE, CGI->generaltexth->localizedTexts["lobby"]["windowMods"]["errorMessage"].String());
buttonOk = std::make_shared<CButton>(Point(110, pos.h-50), "MUBCHCK.DEF", CGI->generaltexth->zelp[561], std::bind(&IServerAPI::sendStartGame, CSH, startOptions | StartInfo::IGNORE_WRONG_MODS), SDLK_RETURN);
buttonCancel = std::make_shared<CButton>(Point(196, pos.h-50), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE);
}
else
{
buttonCancel = std::make_shared<CButton>(Point(154, pos.h-50), "MUBCANC.DEF", CGI->generaltexth->zelp[561], std::bind(&CGuiHandler::popIntTotally, &GH, this), SDLK_ESCAPE);
}
background->scaleTo(Point(pos.w, pos.h));
center();

View File

@ -12,6 +12,7 @@
#include "CSelectionBase.h"
class CBonusSelection;
class CMultiLineLabel;
class CLobbyScreen : public CSelectionBase
{
@ -23,7 +24,7 @@ public:
~CLobbyScreen();
void toggleTab(std::shared_ptr<CIntObject> tab) override;
void startCampaign();
void startScenario(bool allowOnlyAI = false);
void startScenario(ui8 startOptions = 0);
void toggleMode(bool host);
void toggleChat();
@ -35,12 +36,16 @@ public:
CBonusSelection * bonusSel;
};
class CModsBox : public CWindowObject
class CModStatusBox : public CWindowObject
{
std::shared_ptr<CLabel> labelTitle;
std::shared_ptr<CLabelGroup> labelGroupStatus;
std::shared_ptr<CLabelGroup> labelGroupMods;
std::shared_ptr<CLabelGroup> labelGroupStatusWorking;
std::shared_ptr<CLabelGroup> labelGroupStatusMissing;
std::shared_ptr<CLabelGroup> labelGroupStatusIncompatible;
std::shared_ptr<CMultiLineLabel> labelErrorMessage;
std::shared_ptr<CButton> buttonOk;
std::shared_ptr<CButton> buttonCancel;
public:
CModsBox();
CModStatusBox(bool showError = false, ui8 startOptions = 0);
};

View File

@ -5,11 +5,12 @@
"windowMods" :
{
"title" : "Mods status",
"errorMessage" : "Missing or changed mods might cause crashes. Would you like to continue?"
"groups" :
{
"working" : "Available",
"missing" : "Missing",
"incompatible" : "Wrong version"
"compatible" : "Same version",
"incompatible" : "Wrong version",
"missing" : "Not installed"
}
},
"buttonMods" :

View File

@ -61,7 +61,7 @@ std::string StartInfo::getCampaignName() const
return VLC->generaltexth->allTexts[508];
}
void LobbyInfo::verifyStateBeforeStart(bool ignoreNoHuman) const
void LobbyInfo::verifyStateBeforeStart(ui8 startOptions) const
{
if(!mi)
throw ExceptionMapMissing();
@ -72,9 +72,16 @@ void LobbyInfo::verifyStateBeforeStart(bool ignoreNoHuman) const
if(i->second.isControlledByHuman())
break;
if(i == si->playerInfos.cend() && !ignoreNoHuman)
if(i == si->playerInfos.cend() && !(startOptions & StartInfo::IGNORE_ONLY_AI))
throw ExceptionNoHuman();
if(mi->scenarioOptionsOfSave)
{
auto erroredMods = VLC->modh->checkModsPresent(mi->scenarioOptionsOfSave->mods);
if(erroredMods.size() && !(startOptions & StartInfo::IGNORE_WRONG_MODS))
throw ExceptionWrongMods();
}
if(si->mapGenOptions && si->mode == StartInfo::NEW_GAME)
{
if(!si->mapGenOptions->checkOptions())

View File

@ -82,6 +82,13 @@ struct DLL_LINKAGE PlayerSettings
/// Struct which describes the difficulty, the turn time,.. of a heroes match.
struct DLL_LINKAGE StartInfo
{
enum EStartOptions : ui8
{
NO_OPTIONS = 0,
IGNORE_ONLY_AI = 1,
IGNORE_WRONG_MODS = 2
};
enum EMode {NEW_GAME, LOAD_GAME, CAMPAIGN, INVALID = 255};
EMode mode;
@ -179,7 +186,7 @@ struct DLL_LINKAGE LobbyInfo : public LobbyState
LobbyInfo() {}
void verifyStateBeforeStart(bool ignoreNoHuman = false) const;
void verifyStateBeforeStart(ui8 startOptions = StartInfo::NO_OPTIONS) const;
bool isClientHost(int clientId) const;
std::set<PlayerColor> getAllClientPlayers(int clientId);
@ -196,4 +203,5 @@ struct DLL_LINKAGE LobbyInfo : public LobbyState
class ExceptionMapMissing : public std::exception {};
class ExceptionNoHuman : public std::exception {};
class ExceptionWrongMods : public std::exception {};
class ExceptionNoTemplate : public std::exception {};

View File

@ -165,7 +165,7 @@ bool LobbyStartGame::applyOnServer(CVCMIServer * srv)
{
try
{
srv->verifyStateBeforeStart(true);
srv->verifyStateBeforeStart(StartInfo::IGNORE_ONLY_AI | StartInfo::IGNORE_WRONG_MODS);
}
catch(...)
{