-
Notifications
You must be signed in to change notification settings - Fork 151
feat(gui): Implement Observer Player List #2136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Greptile Overview
|
| Filename | Overview |
|---|---|
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp | Implemented getObserverListFontSize() with defaults and validation, added save logic to refresh resources |
| GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h | Added ObserverList struct with labels/values arrays, refresh method, and draw method declarations |
| GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp | Implemented observer list rendering with initialization, resource management, and display logic using fixed column widths |
Sequence Diagram
sequenceDiagram
participant User
participant OptionsMenu
participant GlobalData
participant InGameUI
participant DisplayStringManager
participant GameLogic
participant PlayerList
participant Display
User->>OptionsMenu: Set ObserverListFontSize option
OptionsMenu->>GlobalData: m_observerListFontSize = value
OptionsMenu->>InGameUI: refreshObserverListResources()
InGameUI->>DisplayStringManager: newDisplayString() for labels
InGameUI->>DisplayStringManager: newDisplayString() for values
InGameUI->>InGameUI: Initialize lastValues cache
InGameUI->>InGameUI: Set font properties from GlobalData
Note over InGameUI: During game frame
GameLogic->>InGameUI: postWindowDraw()
InGameUI->>InGameUI: Check if observer mode active
alt Observer Mode Active
InGameUI->>InGameUI: drawObserverList()
loop For each slot/player
InGameUI->>PlayerList: findPlayerWithNameKey()
PlayerList-->>InGameUI: Player object
InGameUI->>InGameUI: Get team, money, rank, XP, name
alt Value changed
InGameUI->>DisplayStringManager: setText() on value DisplayString
end
InGameUI->>Display: drawFillRect() for background
InGameUI->>Display: draw() labels and values
end
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
6 files reviewed, 2 comments
|
Needs a Rebase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 files reviewed, 2 comments
b6779ec to
b7d5c72
Compare
|
Rebased and tweaked with the last suggestions. |
b7d5c72 to
c7d0276
Compare
xezon
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code would be a lot simpler if there was in text coloring with DisplayStrings.
GenTool does this by using §0..§9, §a..§z for in text color presets. Is beyond the scope of this change, but a consideration for the future.
For reference, this is how the code looks in GenTool to draw the Player List with:
void CGentool::MakePlayerMoneyText(std::wstring& text) const
{
if (m_pPlayerMoneyManager->IsActive())
{
const uint32 playerCount = m_pPlayerMoneyManager->GetPlayerMoneyDataCount();
for (uint32 playerId = 0; playerId < playerCount; ++playerId)
{
const CPlayerMoneyData& playerMoneyData = m_pPlayerMoneyManager->GetPlayerMoneyData(playerId);
if (playerMoneyData.IsAnyGamePlayer() && !playerMoneyData.GetName().empty())
{
const SGameColor gameColor = gGame.GetCachedColorValue(playerMoneyData.GetColor());
boost::wformat form(
L"\n§9T§0%d" // team
L"\t.4§9$§0%u" // money
L"\t.13§9*§0%u" // promotion
L"\t.16§9XP§0%u" // experience
L"\t.24§x%.8X%ls"); // name
form % (1 + playerMoneyData.GetTeam());
form % std::min(999999u, playerMoneyData.GetCash());
form % std::min(9u, playerMoneyData.GetPromotion());
form % std::min(9999u, playerMoneyData.GetExperience());
form % gameColor.argb;
form % playerMoneyData.GetShortName().c_str();
text += form.str();
}
}
}
}| m_gameTimeColor = GameMakeColor( 255, 255, 255, 255 ); | ||
| m_gameTimeDropColor = GameMakeColor( 0, 0, 0, 255 ); | ||
|
|
||
| for (i = 0; i < ARRAY_SIZE(m_observerList.labels); ++i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can rewrite this loop as std::fill
| } | ||
| for (i = 0; i < ObserverList::ValueType_Count; ++i) | ||
| { | ||
| for (j = 0; j < MAX_PLAYER_COUNT; ++j) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can rewrite this loop as std::fill
| m_observerList.lastValues.team[i] = -1; | ||
| m_observerList.lastValues.money[i] = ~0u; | ||
| m_observerList.lastValues.rank[i] = -1; | ||
| m_observerList.lastValues.xp[i] = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's ok. Alternatively add a Constructor to LastValues struct with 4 std::fill's.
| TheDisplayStringManager->freeDisplayString(m_observerList.labels[i]); | ||
| m_observerList.labels[i] = nullptr; | ||
| } | ||
| for (i = 0; i < ObserverList::ValueType_Count; ++i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above it uses ARRAY_SIZE(m_observerList.labels) and here ObserverList::ValueType_Count. Either use constants consistently or ARRAY_SIZE. Both work.
(ARRAY_SIZE also works for multi arrays)
| Int observerXp = observerPlayer->getSkillPoints(); | ||
| const UnicodeString observerName = observerPlayer->getPlayerDisplayName(); | ||
|
|
||
| UnicodeString observerListValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be moved before loop.
| const Int observerTeam = (slot && slot->getTeamNumber() >= 0) ? (slot->getTeamNumber() + 1) : 0; | ||
| UnsignedInt observerMoney = observerPlayer->getMoney()->countMoney(); | ||
| Int observerRank = observerPlayer->getRankLevel(); | ||
| Int observerXp = observerPlayer->getSkillPoints(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Several values can be const.
| Int observerRow = 0; | ||
| for (Int slotIndex = 0; slotIndex < MAX_SLOTS && observerRow < MAX_PLAYER_COUNT; ++slotIndex) | ||
| { | ||
| AsciiString name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be moved before loop.
| } | ||
| if (m_observerList.lastValues.xp[row] != observerXp) | ||
| { | ||
| observerListValue.format(L"%d", observerXp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Values need clamping or reformatting if the room is not large enough, or text spacing needs extending.
GenTool clamps (not great)
- Money at 999999
- Promotion at 9
- XP at 9999
- Name to 12 characters (optional because it is at the end)
This change implements player money/rank/XP display for match Observers in Generals and Zero Hour.
It is enabled by default with a size of 8 replicating GenTool implementation.
The following option has been added:
It can be styled and repositioned by adding the relevant fields to the InGameUI.ini data file.
Example:
TODO