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

Display different timers separately when applicable

This commit is contained in:
Ivan Savenko 2023-12-19 19:02:46 +02:00
parent da9c0feebc
commit f834cb3d99
5 changed files with 130 additions and 24 deletions

View File

@ -33,23 +33,49 @@ TurnTimerWidget::TurnTimerWidget(const Point & position)
TurnTimerWidget::TurnTimerWidget(const Point & position, PlayerColor player)
: CIntObject(TIME)
, lastSoundCheckSeconds(0)
, isBattleMode(player.isValidPlayer())
{
pos += position;
pos.w = 50;
pos.h = 0;
recActions &= ~DEACTIVATE;
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
backgroundTexture = std::make_shared<CFilledTexture>(ImagePath::builtin("DiBoxBck"), pos); // 1 px smaller on all sides
backgroundBorder = std::make_shared<TransparentFilledRectangle>(pos, ColorRGBA(0, 0, 0, 128), Colors::METALLIC_GOLD);
pos += position;
pos.w = 0;
pos.h = 0;
recActions &= ~DEACTIVATE;
const auto & timers = LOCPLINT->cb->getStartInfo()->turnTimerInfo;
if (player.isValidPlayer())
backgroundTexture = std::make_shared<CFilledTexture>(ImagePath::builtin("DiBoxBck"), pos); // 1 px smaller on all sides
if (isBattleMode)
backgroundBorder = std::make_shared<TransparentFilledRectangle>(pos, ColorRGBA(0, 0, 0, 128), Colors::BRIGHT_YELLOW);
else
backgroundBorder = std::make_shared<TransparentFilledRectangle>(pos, ColorRGBA(0, 0, 0, 128), Colors::BLACK);
if (isBattleMode)
{
pos.w = 76;
pos.h += 16;
playerLabels[player] = std::make_shared<CLabel>(pos.w / 2, pos.h - 8, FONT_BIG, ETextAlignment::CENTER, graphics->playerColors[player], "");
playerLabelsMain[player] = std::make_shared<CLabel>(pos.w / 2, pos.h - 8, FONT_BIG, ETextAlignment::CENTER, graphics->playerColors[player], "");
if (timers.battleTimer != 0)
{
pos.h += 16;
playerLabelsBattle[player] = std::make_shared<CLabel>(pos.w / 2, pos.h - 8, FONT_BIG, ETextAlignment::CENTER, graphics->playerColors[player], "");
}
if (!timers.accumulatingUnitTimer && timers.unitTimer != 0)
{
pos.h += 16;
playerLabelsUnit[player] = std::make_shared<CLabel>(pos.w / 2, pos.h - 8, FONT_BIG, ETextAlignment::CENTER, graphics->playerColors[player], "");
}
}
else
{
if (!timers.accumulatingTurnTimer && timers.baseTimer != 0)
pos.w = 120;
else
pos.w = 50;
for(PlayerColor player(0); player < PlayerColor::PLAYER_LIMIT; ++player)
{
if (LOCPLINT->cb->getStartInfo()->playerInfos.count(player) == 0)
@ -59,7 +85,7 @@ TurnTimerWidget::TurnTimerWidget(const Point & position, PlayerColor player)
continue;
pos.h += 16;
playerLabels[player] = std::make_shared<CLabel>(pos.w / 2, pos.h - 8, FONT_BIG, ETextAlignment::CENTER, graphics->playerColors[player], "");
playerLabelsMain[player] = std::make_shared<CLabel>(pos.w / 2, pos.h - 8, FONT_BIG, ETextAlignment::CENTER, graphics->playerColors[player], "");
}
}
@ -84,14 +110,54 @@ void TurnTimerWidget::updateNotifications(PlayerColor player, int timeMs)
lastSoundCheckSeconds = newTimeSeconds;
}
void TurnTimerWidget::updateTextLabel(PlayerColor player, int timeMs)
static std::string msToString(int timeMs)
{
auto label = playerLabels[player];
int timeSeconds = timeMs / 1000;
std::ostringstream oss;
oss << lastSoundCheckSeconds / 60 << ":" << std::setw(2) << std::setfill('0') << lastSoundCheckSeconds % 60;
label->setText(oss.str());
label->setColor(graphics->playerColors[player]);
oss << timeSeconds / 60 << ":" << std::setw(2) << std::setfill('0') << timeSeconds % 60;
return oss.str();
}
void TurnTimerWidget::updateTextLabel(PlayerColor player, const TurnTimerInfo & timer)
{
const auto & timerSettings = LOCPLINT->cb->getStartInfo()->turnTimerInfo;
auto mainLabel = playerLabelsMain[player];
if (isBattleMode)
{
mainLabel->setText(msToString(timer.baseTimer + timer.turnTimer));
if (timerSettings.battleTimer != 0)
{
auto battleLabel = playerLabelsBattle[player];
if (timer.battleTimer != 0)
{
if (timerSettings.accumulatingUnitTimer)
battleLabel->setText("+" + msToString(timer.battleTimer + timer.unitTimer));
else
battleLabel->setText("+" + msToString(timer.battleTimer));
}
else
battleLabel->setText("");
}
if (!timerSettings.accumulatingUnitTimer && timerSettings.unitTimer != 0)
{
auto unitLabel = playerLabelsUnit[player];
if (timer.unitTimer != 0)
unitLabel->setText("+" + msToString(timer.unitTimer));
else
unitLabel->setText("");
}
}
else
{
if (!timerSettings.accumulatingTurnTimer && timerSettings.baseTimer != 0)
mainLabel->setText(msToString(timer.baseTimer) + "+" + msToString(timer.turnTimer));
else
mainLabel->setText(msToString(timer.baseTimer + timer.turnTimer));
}
}
void TurnTimerWidget::updateTimer(PlayerColor player, uint32_t msPassed)
@ -110,12 +176,12 @@ void TurnTimerWidget::updateTimer(PlayerColor player, uint32_t msPassed)
countingDownTimer.substractTimer(msPassed);
updateNotifications(player, countingDownTimer.valueMs());
updateTextLabel(player, countingDownTimer.valueMs());
updateTextLabel(player, countingDownTimer);
}
void TurnTimerWidget::tick(uint32_t msPassed)
{
for(const auto & player : playerLabels)
for(const auto & player : playerLabelsMain)
{
if (LOCPLINT->battleInt)
{
@ -123,7 +189,7 @@ void TurnTimerWidget::tick(uint32_t msPassed)
bool isDefender = battle->sideToPlayer(BattleSide::DEFENDER) == player.first;
bool isAttacker = battle->sideToPlayer(BattleSide::ATTACKER) == player.first;
bool isMakingUnitTurn = battle->battleActiveUnit()->unitOwner() == player.first;
bool isMakingUnitTurn = battle->battleActiveUnit() && battle->battleActiveUnit()->unitOwner() == player.first;
bool isEngagedInBattle = isDefender || isAttacker;
// Due to way our network message queue works during battle animation

View File

@ -26,12 +26,15 @@ VCMI_LIB_NAMESPACE_END
class TurnTimerWidget : public CIntObject
{
int lastSoundCheckSeconds;
bool isBattleMode;
std::set<int> notificationThresholds;
std::map<PlayerColor, TurnTimerInfo> lastUpdateTimers;
std::map<PlayerColor, TurnTimerInfo> countingDownTimers;
std::map<PlayerColor, std::shared_ptr<CLabel>> playerLabels;
std::map<PlayerColor, std::shared_ptr<CLabel>> playerLabelsMain;
std::map<PlayerColor, std::shared_ptr<CLabel>> playerLabelsBattle;
std::map<PlayerColor, std::shared_ptr<CLabel>> playerLabelsUnit;
std::shared_ptr<CFilledTexture> backgroundTexture;
std::shared_ptr<TransparentFilledRectangle> backgroundBorder;
@ -41,7 +44,7 @@ class TurnTimerWidget : public CIntObject
void tick(uint32_t msPassed) override;
void updateNotifications(PlayerColor player, int timeMs);
void updateTextLabel(PlayerColor player, int timeMs);
void updateTextLabel(PlayerColor player, const TurnTimerInfo & timer);
public:
/// Activates adventure map mode in which widget will display timer for all players

View File

@ -31,6 +31,7 @@
#include "../render/Canvas.h"
#include "../render/IRenderHandler.h"
#include "../adventureMap/CInGameConsole.h"
#include "../adventureMap/TurnTimerWidget.h"
#include "../../CCallback.h"
#include "../../lib/CGeneralTextHandler.h"
@ -39,6 +40,7 @@
#include "../../lib/CStack.h"
#include "../../lib/CConfigHandler.h"
#include "../../lib/filesystem/ResourcePath.h"
#include "../../lib/StartInfo.h"
#include "../windows/settings/SettingsMainWindow.h"
BattleWindow::BattleWindow(BattleInterface & owner):
@ -83,6 +85,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
createQueue();
createStickyHeroInfoWindows();
createTimerInfoWindows();
if ( owner.tacticsMode )
tacticPhaseStarted();
@ -128,8 +131,8 @@ void BattleWindow::createStickyHeroInfoWindows()
InfoAboutHero info;
info.initFromHero(owner.defendingHeroInstance, InfoAboutHero::EInfoLevel::INBATTLE);
Point position = (GH.screenDimensions().x >= 1000)
? Point(pos.x + pos.w + 15, pos.y)
: Point(pos.x + pos.w -79, pos.y + 135);
? Point(pos.x + pos.w + 15, pos.y + 50)
: Point(pos.x + pos.w -79, pos.y + 185);
defenderHeroWindow = std::make_shared<HeroInfoBasicPanel>(info, &position);
}
if(owner.attackingHeroInstance)
@ -137,8 +140,8 @@ void BattleWindow::createStickyHeroInfoWindows()
InfoAboutHero info;
info.initFromHero(owner.attackingHeroInstance, InfoAboutHero::EInfoLevel::INBATTLE);
Point position = (GH.screenDimensions().x >= 1000)
? Point(pos.x - 93, pos.y)
: Point(pos.x + 1, pos.y + 135);
? Point(pos.x - 93, pos.y + 50)
: Point(pos.x + 1, pos.y + 185);
attackerHeroWindow = std::make_shared<HeroInfoBasicPanel>(info, &position);
}
@ -154,6 +157,33 @@ void BattleWindow::createStickyHeroInfoWindows()
}
}
void BattleWindow::createTimerInfoWindows()
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
if(LOCPLINT->cb->getStartInfo()->turnTimerInfo.unitTimer != 0)
{
PlayerColor attacker = owner.getBattle()->sideToPlayer(BattleSide::ATTACKER);
PlayerColor defender = owner.getBattle()->sideToPlayer(BattleSide::DEFENDER);
if (attacker.isValidPlayer())
{
if (GH.screenDimensions().x >= 1000)
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(-92, 1), attacker);
else
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(1, 135), attacker);
}
if (defender.isValidPlayer())
{
if (GH.screenDimensions().x >= 1000)
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(pos.w + 15, 1), defender);
else
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(pos.w - 79, 135), defender);
}
}
}
BattleWindow::~BattleWindow()
{
CPlayerInterface::battleInt = nullptr;

View File

@ -24,6 +24,7 @@ class BattleInterface;
class BattleConsole;
class BattleRenderer;
class StackQueue;
class TurnTimerWidget;
class HeroInfoBasicPanel;
/// GUI object that handles functionality of panel at the bottom of combat screen
@ -36,6 +37,9 @@ class BattleWindow : public InterfaceObjectConfigurable
std::shared_ptr<HeroInfoBasicPanel> attackerHeroWindow;
std::shared_ptr<HeroInfoBasicPanel> defenderHeroWindow;
std::shared_ptr<TurnTimerWidget> attackerTimerWidget;
std::shared_ptr<TurnTimerWidget> defenderTimerWidget;
/// button press handling functions
void bOptionsf();
void bSurrenderf();
@ -65,6 +69,7 @@ class BattleWindow : public InterfaceObjectConfigurable
void toggleStickyHeroWindowsVisibility();
void createStickyHeroInfoWindows();
void createTimerInfoWindows();
std::shared_ptr<BattleConsole> buildBattleConsole(const JsonNode &) const;

View File

@ -34,6 +34,8 @@ void TurnTimerHandler::onGameplayStart(PlayerColor player)
{
timers[player] = si->turnTimerInfo;
timers[player].turnTimer = 0;
timers[player].battleTimer = 0;
timers[player].unitTimer = 0;
timers[player].isActive = true;
timers[player].isBattle = false;
lastUpdate[player] = std::numeric_limits<int>::max();