From c099b91f6448660793ea7af19cc971a9a8ac4690 Mon Sep 17 00:00:00 2001 From: MrS-ibra Date: Sun, 1 Feb 2026 00:31:24 +0300 Subject: [PATCH] Fix observer overlay crash during surrender/replay --- .../GameEngine/Source/GameClient/InGameUI.cpp | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index 77c2f4285a..7dc9548dbf 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -6009,6 +6009,15 @@ void InGameUI::drawObserverStats(Int& x, Int& y) Real scale = (Real)screenW / 1920.0f; scale = (scale < 0.7f) ? 0.7f : (scale > 2.0f) ? 2.0f : scale; + auto freeDisplayStrings = [](std::vector& strings) { + for (DisplayString* ds : strings) { + if (ds) { + TheDisplayStringManager->freeDisplayString(ds); + } + } + strings.clear(); + }; + static const Int numCols = 8; static const wchar_t* headers[numCols] = { L"(T) Name", L"Army", L"Cash", L"Cash/m", L"(R) XP", L"SP", L"K/D", L"Power" @@ -6023,6 +6032,10 @@ void InGameUI::drawObserverStats(Int& x, Int& y) static Int totalWidth = 0; static Int totalHeight = 0; + static bool isUpdating = false; + if (isUpdating) + return; + UnsignedInt currentFrame = TheGameLogic ? TheGameLogic->getFrame() : 0; Bool needUpdate = (lastUpdateFrame == 0) || (currentFrame - lastUpdateFrame >= LOGICFRAMES_PER_SECOND) || @@ -6032,6 +6045,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) // UPDATE: gather data, format strings, measure layout // ==================================================================== if (needUpdate) { + isUpdating = true; lastUpdateFrame = currentFrame; lastFontSize = TheWritableGlobalData->m_observerStatsFontSize; refreshObserverStatsResources(); @@ -6111,6 +6125,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) [](const PlayerData& a, const PlayerData& b) { if (a.team != b.team) return a.team < b.team; // sort by team first + return false; }); // Format cash and cash/m with commas @@ -6128,6 +6143,7 @@ void InGameUI::drawObserverStats(Int& x, Int& y) // Create Display Strings if (headerStrings.size() != numCols) { + freeDisplayStrings(headerStrings); headerStrings.clear(); for (Int i = 0; i < numCols; ++i) { DisplayString* ds = TheDisplayStringManager->newDisplayString(); @@ -6139,12 +6155,12 @@ void InGameUI::drawObserverStats(Int& x, Int& y) headerStrings[i]->setFont(m_observerStatsString->getFont()); headerStrings[i]->setText(headers[i]); } - + for (DisplayString* ds : cellStrings) { if (ds) TheDisplayStringManager->freeDisplayString(ds); } - cellStrings.clear(); + freeDisplayStrings(cellStrings); cellStrings.reserve(players.size() * numCols); for (const PlayerData& pd : players) { @@ -6164,6 +6180,13 @@ void InGameUI::drawObserverStats(Int& x, Int& y) for (Int i = 0; i < numCols; ++i) { DisplayString* ds = TheDisplayStringManager->newDisplayString(); + if (!ds) { + freeDisplayStrings(headerStrings); + freeDisplayStrings(cellStrings); + players.clear(); + isUpdating = false; + return; + } ds->setFont(m_observerStatsString->getFont()); ds->setText(cells[i]); cellStrings.push_back(ds); @@ -6194,11 +6217,15 @@ void InGameUI::drawObserverStats(Int& x, Int& y) Int lineHeight = (m_observerStatsLineStep > 0) ? m_observerStatsLineStep : Int(16 * scale); Int rowSpacing = Int(2 * scale); totalHeight = (lineHeight + rowSpacing) * (1 + Int(players.size())); + isUpdating = false; } if (players.empty()) return; + if (cellStrings.size() != players.size() * numCols) + return; + // ==================================================================== // DRAWINGS // ==================================================================== @@ -6669,3 +6696,4 @@ void InGameUI::drawGameTime() +