diff --git a/client/battle/BattleResultWindow.cpp b/client/battle/BattleResultWindow.cpp index 2f79ba894..f5a49589c 100644 --- a/client/battle/BattleResultWindow.cpp +++ b/client/battle/BattleResultWindow.cpp @@ -12,6 +12,9 @@ #include "BattleWindow.h" +#include "../GameInstance.h" +#include "../Client.h" +#include "../CServerHandler.h" #include "../CPlayerInterface.h" #include "../GameEngine.h" #include "../gui/Shortcut.h" @@ -23,6 +26,7 @@ #include "../widgets/VideoWidget.h" #include "../../lib/CStack.h" +#include "../../lib/CPlayerState.h" #include "../../lib/ConditionalWait.h" #include "../../lib/GameLibrary.h" #include "../../lib/StartInfo.h" @@ -45,7 +49,14 @@ BattleResultWindow::BattleResultWindow(const BattleResult & br, CPlayerInterface exit = std::make_shared(Point(384, 505), AnimationPath::builtin("iok6432.def"), std::make_pair("", ""), [this](){ bExitf();}, EShortcut::GLOBAL_ACCEPT); exit->setBorderColor(Colors::METALLIC_GOLD); - if(allowReplay || owner.cb->getStartInfo()->extraOptionsInfo.unlimitedReplay) + auto battle = owner.cb->getBattle(br.battleID); + const auto * attackerPlayer = GAME->server().client->gameInfo().getPlayerState(battle->sideToPlayer(BattleSide::ATTACKER)); + const auto * defenderPlayer = GAME->server().client->gameInfo().getPlayerState(battle->sideToPlayer(BattleSide::DEFENDER)); + bool isAttackerHuman = attackerPlayer && attackerPlayer->isHuman(); + bool isDefenderHuman = defenderPlayer && defenderPlayer->isHuman(); + bool onlyOnePlayerHuman = isAttackerHuman != isDefenderHuman; + + if((allowReplay || owner.cb->getStartInfo()->extraOptionsInfo.unlimitedReplay) && onlyOnePlayerHuman) { repeat = std::make_shared(Point(24, 505), AnimationPath::builtin("icn6432.def"), std::make_pair("", ""), [this](){ bRepeatf();}, EShortcut::GLOBAL_CANCEL); repeat->setBorderColor(Colors::METALLIC_GOLD); diff --git a/client/lobby/BattleOnlyMode.cpp b/client/lobby/BattleOnlyMode.cpp index 2a99eb9ea..77b60106b 100644 --- a/client/lobby/BattleOnlyMode.cpp +++ b/client/lobby/BattleOnlyMode.cpp @@ -58,8 +58,6 @@ void BattleOnlyMode::openBattleWindow() { - if(GAME->server().isGuest()) - return; GAME->server().sendGuiAction(LobbyGuiAction::BATTLE_MODE); ENGINE->windows().createAndPushWindow(); } @@ -67,6 +65,7 @@ void BattleOnlyMode::openBattleWindow() BattleOnlyModeWindow::BattleOnlyModeWindow() : CWindowObject(BORDERED) , startInfo(std::make_shared()) + , disabledColor(GAME->server().isHost() ? Colors::WHITE : Colors::ORANGE) { OBJECT_CONSTRUCTION; @@ -81,10 +80,12 @@ BattleOnlyModeWindow::BattleOnlyModeWindow() backgroundTexture = std::make_shared(Rect(0, 0, pos.w, pos.h)); backgroundTexture->setPlayerColor(PlayerColor(1)); buttonOk = std::make_shared(Point(191, 203), AnimationPath::builtin("MuBchck"), CButton::tooltip(), [this](){ startBattle(); }, EShortcut::GLOBAL_ACCEPT); + buttonOk->block(true); buttonAbort = std::make_shared(Point(265, 203), AnimationPath::builtin("MuBcanc"), CButton::tooltip(), [this](){ GAME->server().sendGuiAction(LobbyGuiAction::NO_TAB); close(); }, EShortcut::GLOBAL_CANCEL); + buttonAbort->block(true); title = std::make_shared(260, 20, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyMode")); battlefieldSelector = std::make_shared(Point(29, 174), AnimationPath::builtin("GSPButtonClear"), CButton::tooltip(), [this](){ @@ -198,7 +199,7 @@ void BattleOnlyModeWindow::applyStartInfo(std::shared_ptrsetTextOverlay(LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefield") + ": " + (startInfo->selectedTerrain ? (*startInfo->selectedTerrain).toEntity(LIBRARY)->getNameTranslated() : (*startInfo->selectedTown).toEntity(LIBRARY)->getNameTranslated()), EFonts::FONT_SMALL, Colors::WHITE); + battlefieldSelector->setTextOverlay(LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeBattlefield") + ": " + (startInfo->selectedTerrain ? (*startInfo->selectedTerrain).toEntity(LIBRARY)->getNameTranslated() : (*startInfo->selectedTown).toEntity(LIBRARY)->getNameTranslated()), EFonts::FONT_SMALL, disabledColor); } void BattleOnlyModeWindow::setOkButtonEnabled() @@ -211,12 +212,12 @@ void BattleOnlyModeWindow::setOkButtonEnabled() buttonAbort->block(GAME->server().isGuest()); } -std::shared_ptr drawBlackBox(Point size, std::string text) +std::shared_ptr drawBlackBox(Point size, std::string text, ColorRGBA color) { auto image = ENGINE->renderHandler().createImage(size, CanvasScalingPolicy::AUTO); Canvas canvas = image->getCanvas(); canvas.drawColor(Rect(0, 0, size.x, size.y), Colors::BLACK); - canvas.drawText(Point(size.x / 2, size.y / 2), FONT_TINY, Colors::WHITE, ETextAlignment::CENTER, text); + canvas.drawText(Point(size.x / 2, size.y / 2), FONT_TINY, color, ETextAlignment::CENTER, text); return image; } @@ -238,6 +239,7 @@ BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(int id, BattleOnlyModeWin primSkillsBorder.push_back(std::make_shared(Rect(78 + i * 36, 26, 32, 32))); primSkillsBorder.back()->addRectangle(Point(0, 0), Point(32, 32), ColorRGBA(44, 108, 255)); primSkillsInput.push_back(std::make_shared(Rect(78 + i * 36, 58, 32, 16), EFonts::FONT_SMALL, ETextAlignment::CENTER, false)); + primSkillsInput.back()->setColor(id == 1 ? Colors::WHITE : parent.disabledColor); primSkillsInput.back()->setFilterNumber(0, 100); primSkillsInput.back()->setText("0"); primSkillsInput.back()->setCallback([this, i, id](const std::string & text){ @@ -250,20 +252,17 @@ BattleOnlyModeHeroSelector::BattleOnlyModeHeroSelector(int id, BattleOnlyModeWin for(size_t i=0; i(Rect(5 + i * 36, 113, 32, 16), EFonts::FONT_SMALL, ETextAlignment::CENTER, false)); + selectedArmyInput.back()->setColor(id == 1 ? Colors::WHITE : parent.disabledColor); selectedArmyInput.back()->setFilterNumber(1, 10000000, 3); selectedArmyInput.back()->setText("1"); selectedArmyInput.back()->setCallback([this, i, id](const std::string & text){ - if(!parent.startInfo->selectedArmy[id][i]) + if(parent.startInfo->selectedArmy[id][i]) { - if(!parent.startInfo->selectedArmy[id][i]) - { - selectedArmyInput[i]->setText("1"); - return; - } - (*parent.startInfo->selectedArmy[id][i]).second = TextOperations::parseMetric(text); parent.onChange(); } + else + selectedArmyInput[i]->setText("1"); }); } @@ -277,15 +276,15 @@ void BattleOnlyModeHeroSelector::setHeroIcon() if(!parent.startInfo->selectedHero[id]) { - heroImage = std::make_shared(drawBlackBox(Point(58, 64), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6, 7)); - heroLabel = std::make_shared(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, LIBRARY->generaltexth->translate("core.genrltxt.507")); + heroImage = std::make_shared(drawBlackBox(Point(58, 64), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect"), id == 1 ? Colors::WHITE : parent.disabledColor), Point(6, 7)); + heroLabel = std::make_shared(160, 16, FONT_SMALL, ETextAlignment::CENTER, id == 1 ? Colors::WHITE : parent.disabledColor, LIBRARY->generaltexth->translate("core.genrltxt.507")); for(size_t i=0; isetText("0"); } else { heroImage = std::make_shared(ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("PortraitsLarge"), EImageBlitMode::COLORKEY)->getImage((*parent.startInfo->selectedHero[id]).toHeroType()->imageIndex), Point(6, 7)); - heroLabel = std::make_shared(160, 16, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, (*parent.startInfo->selectedHero[id]).toHeroType()->getNameTranslated()); + heroLabel = std::make_shared(160, 16, FONT_SMALL, ETextAlignment::CENTER, id == 1 ? Colors::WHITE : parent.disabledColor, (*parent.startInfo->selectedHero[id]).toHeroType()->getNameTranslated()); for(size_t i=0; isetText(std::to_string(parent.startInfo->primSkillLevel[id][i])); } @@ -361,7 +360,7 @@ void BattleOnlyModeHeroSelector::setCreatureIcons() { if(!parent.startInfo->selectedArmy[id][i]) { - creatureImage[i] = std::make_shared(drawBlackBox(Point(32, 32), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect")), Point(6 + i * 36, 78)); + creatureImage[i] = std::make_shared(drawBlackBox(Point(32, 32), LIBRARY->generaltexth->translate("vcmi.lobby.battleOnlyModeSelect"), id == 1 ? Colors::WHITE : parent.disabledColor), Point(6 + i * 36, 78)); selectedArmyInput[i]->setText("1"); } else @@ -369,7 +368,7 @@ void BattleOnlyModeHeroSelector::setCreatureIcons() auto unit = (*parent.startInfo->selectedArmy[id][i]); auto creatureID = unit.first; creatureImage[i] = std::make_shared(ENGINE->renderHandler().loadAnimation(AnimationPath::builtin("CPRSMALL"), EImageBlitMode::COLORKEY)->getImage(LIBRARY->creh->objects.at(creatureID)->getIconIndex()), Point(6 + i * 36, 78)); - selectedArmyInput[i]->setText(std::to_string(unit.second)); + selectedArmyInput[i]->setText(TextOperations::formatMetric(unit.second, 3)); } creatureImage[i]->addLClickCallback([this, i](){ diff --git a/client/lobby/BattleOnlyMode.h b/client/lobby/BattleOnlyMode.h index 86615bf2e..eac3f08ef 100644 --- a/client/lobby/BattleOnlyMode.h +++ b/client/lobby/BattleOnlyMode.h @@ -78,6 +78,8 @@ private: std::shared_ptr heroSelector1; std::shared_ptr heroSelector2; + ColorRGBA disabledColor; + void init(); void onChange(); void update(); diff --git a/client/lobby/SelectionTab.cpp b/client/lobby/SelectionTab.cpp index 47ef38567..ddd8afb34 100644 --- a/client/lobby/SelectionTab.cpp +++ b/client/lobby/SelectionTab.cpp @@ -323,6 +323,8 @@ void SelectionTab::toggleMode() { if(slider) slider->block(true); + if(buttonBattleOnlyMode) + buttonBattleOnlyMode->block(true); } else { diff --git a/lib/StartInfo.cpp b/lib/StartInfo.cpp index 7b879f0ab..50181bfe0 100644 --- a/lib/StartInfo.cpp +++ b/lib/StartInfo.cpp @@ -21,7 +21,6 @@ #include "mapping/CMapHeader.h" #include "mapping/CMapService.h" #include "modding/ModIncompatibility.h" -#include "mapObjects/army/CCreatureSet.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/StartInfo.h b/lib/StartInfo.h index 74de232c5..a80f36f33 100644 --- a/lib/StartInfo.h +++ b/lib/StartInfo.h @@ -15,7 +15,6 @@ #include "TurnTimerInfo.h" #include "ExtraOptionsInfo.h" #include "campaign/CampaignConstants.h" -#include "mapObjects/army/CCreatureSet.h" #include "serializer/GameConnectionID.h" #include "serializer/Serializeable.h" #include "serializer/PlayerConnectionID.h" diff --git a/server/battles/BattleResultProcessor.cpp b/server/battles/BattleResultProcessor.cpp index 5f6e850f9..9fedd7057 100644 --- a/server/battles/BattleResultProcessor.cpp +++ b/server/battles/BattleResultProcessor.cpp @@ -276,7 +276,7 @@ void BattleResultProcessor::endBattle(const CBattleInfoCallback & battle) bool isDefenderHuman = defenderPlayer && defenderPlayer->isHuman(); bool onlyOnePlayerHuman = isAttackerHuman != isDefenderHuman; // in battles against neutrals attacker can ask to replay battle manually, additionally in battles against AI player human side can also ask for replay - if(onlyOnePlayerHuman || gameHandler->gameState().getMap().battleOnly) + if(onlyOnePlayerHuman) { auto battleDialogQuery = std::make_shared(gameHandler, battle.getBattle(), battleQuery->result); battleResult->queryID = battleDialogQuery->queryID;