Browse Source

Display different timers separately when applicable

Ivan Savenko 1 year ago
parent
commit
f834cb3d99

+ 81 - 15
client/adventureMap/TurnTimerWidget.cpp

@@ -33,23 +33,49 @@ TurnTimerWidget::TurnTimerWidget(const Point & position)
 TurnTimerWidget::TurnTimerWidget(const Point & position, PlayerColor player)
 	: CIntObject(TIME)
 	, lastSoundCheckSeconds(0)
+	, isBattleMode(player.isValidPlayer())
 {
+	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
+
 	pos += position;
-	pos.w = 50;
+	pos.w = 0;
 	pos.h = 0;
 	recActions &= ~DEACTIVATE;
-	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
+	const auto & timers = LOCPLINT->cb->getStartInfo()->turnTimerInfo;
 
 	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);
 
-	if (player.isValidPlayer())
+	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

+ 5 - 2
client/adventureMap/TurnTimerWidget.h

@@ -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

+ 34 - 4
client/battle/BattleWindow.cpp

@@ -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;

+ 5 - 0
client/battle/BattleWindow.h

@@ -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;
 

+ 2 - 0
server/TurnTimerHandler.cpp

@@ -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();