Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
31ad501
Implement text truncation support and improve scoreboard legibility
Lightningbulb2 May 8, 2026
f002a2a
Merge branch 'develop' of https://github.com/Lightningbulb2/fa into d…
Lightningbulb2 May 8, 2026
16066fb
update annotations
Lightningbulb2 May 8, 2026
5eb1c4d
add changelog snippet
Lightningbulb2 May 8, 2026
3653d26
code rabbit suggestions
Lightningbulb2 May 8, 2026
eb39955
restore text on resize fix
Lightningbulb2 May 8, 2026
7e707b6
Merge branch 'develop' into develop
Lightningbulb2 May 8, 2026
a6c3eca
Merge branch 'develop' into develop
Lightningbulb2 May 11, 2026
a49fc59
Merge branch 'develop' into develop
Lightningbulb2 May 14, 2026
608e8d8
fix redundant text truncation checks and remove string comparisons
Lightningbulb2 Jun 17, 2026
789136f
fix truncation edge case for un-refreshed UI layouts
Lightningbulb2 Jun 17, 2026
9d9b4be
Merge branch 'FAForever:develop' into develop
Lightningbulb2 Jun 23, 2026
c0d1c64
Merge branch 'FAForever:develop' into feature/text-truncation
Lightningbulb2 Jul 5, 2026
2471fc6
update snippet
Lightningbulb2 Jul 5, 2026
64b67c1
preserve pre-existing OnDirty callbacks when toggling text truncation
Lightningbulb2 Sep 7, 2026
62b6814
use 'SetTruncationEnabled' to setup OnDirty handlers rather than putt…
Lightningbulb2 Sep 7, 2026
972927d
prevent recursive OnDirty wrappers when calling SetTruncationEnabled(…
Lightningbulb2 Sep 7, 2026
ffb1b94
prevent duplicate calls of SetDisplayText() when calling SetText()
Lightningbulb2 Sep 7, 2026
660cdcc
apply SetDisplayText() even if truncation is invalid, to keep SetText…
Lightningbulb2 Sep 7, 2026
529540d
Apply truncation immediately so SetText() and SetTruncationEnabled() …
Lightningbulb2 Sep 7, 2026
d575162
Split snippets in two and improve format
lL1l1 Sep 7, 2026
3d1fcc4
Fix SetDisplayText type annotation
lL1l1 Sep 7, 2026
0a6bd62
Align SetText's param type with engine SetText's
lL1l1 Sep 7, 2026
74e2046
Update SetText-related function descriptions
lL1l1 Sep 7, 2026
d272065
More annotations
lL1l1 Sep 10, 2026
9cc31ea
Remove the "ellipsis" wording
lL1l1 Sep 10, 2026
633b9f9
Fix table.copy annotation with nodiscard
lL1l1 Sep 10, 2026
1d3bdb4
type-check in SetText
lL1l1 Sep 10, 2026
fc7d45c
More legible anonymous function in score.lua
lL1l1 Sep 11, 2026
44fbcc2
Update score.lua
lL1l1 Sep 11, 2026
e5d4f76
Merge branch 'develop' into pr/7169
lL1l1 Sep 11, 2026
a3d86b1
Revert "Update score.lua"
lL1l1 Sep 11, 2026
d959b21
Use SetAlpha for nameHover bitmap
lL1l1 Sep 11, 2026
a2e6983
grey out ratings of dead players on the leaderboard
Lightningbulb2 Sep 12, 2026
bdfbf67
check for width initialization before truncating and add truncation s…
Lightningbulb2 Sep 12, 2026
715b888
Fix bad condition for preserving OnDirty
Lightningbulb2 Sep 15, 2026
51696b5
remove test string and fix scoreboard bolding
Lightningbulb2 Sep 15, 2026
86b634c
Restore original text immediately when truncation is disabled
Lightningbulb2 Sep 15, 2026
5cde680
fix variable initialization and optional bool check
Lightningbulb2 Sep 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/snippets/graphics.7169.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Improve scoreboard legibility with better alignment, tooltips, dropshadows, and text cropping (#7169).
4 changes: 4 additions & 0 deletions changelog/snippets/other.7169.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- Add truncation for the Text control (#7169):
- Accessible with `SetTruncationEnabled()`
- Use `SetTruncationText()` to assign custom trailing characters like "..." when text is cropped
- `SetText()` is split into `SetText()` and its implicitly called `SetDisplayText()`. This allows for text preprocessing operations such as truncation.
4 changes: 4 additions & 0 deletions loc/US/strings_db.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5964,6 +5964,10 @@ tooltipui0734="No Vote"
tooltipui0735="Vote no to your team recalling from battle as a defeat."
tooltipui0736="[Hide/Show] Mass Fabricator Panel"
tooltipui0737="[Hide/Show] Voting Panel"
tooltipui0738="Game Speed"
tooltipui0739="[your requested speed] / [actual game speed]"
tooltipui0740="Game Quality"
tooltipui0741="Estimated game quality"

-- External Factory and Auto-Deploy tooltips
tooltipui0750 = "Mobile Factory"
Expand Down
131 changes: 130 additions & 1 deletion lua/maui/text.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ local LazyVarCreate = import("/lua/lazyvar.lua").Create
Text = ClassUI(moho.text_methods, Control) {

__init = function(self, parent, debugname)

self._truncationText = "..."
self._fullText = ""
self._truncationEnabled = false

InternalCreateText(self, parent)
if debugname then
self:SetName(debugname)
Expand All @@ -33,6 +38,7 @@ Text = ClassUI(moho.text_methods, Control) {
self._color.OnDirty = function(var)
self:SetNewColor(var())
end

end,

OnInit = function(self)
Expand All @@ -41,15 +47,138 @@ Text = ClassUI(moho.text_methods, Control) {
self:SetClipToWidth(false)
end,

SetClipToWidth = function(self, clipToWidth)
--- Directly sets displayed text
---@see Text.SetText # To set the raw text
---@type fun(self: Text, str: string | number)
SetDisplayText = moho.text_methods.SetText,

--- Directly gets the current displayed text
---@see Text.SetText # To get the raw text
---@type fun(self: Text): string
GetDisplayText = moho.text_methods.GetText,

--- Sets the raw text; actual displayed text is affected by operations like truncation
---@see Text.SetDisplayText # To directly set the displayed text
---@param text string | number
SetText = function(self, text)
local t_text = type(text)
if t_text ~= "string" and t_text ~= "number" then
error('Expected string or number but got ' .. t_text, 2)
end
self._fullText = tostring(text)
if self._truncationEnabled then
self:_applyTruncation()
else
self:SetDisplayText(self._fullText)
end
end,
Comment thread
Lightningbulb2 marked this conversation as resolved.

--- Get the raw text before operations like truncation
---@see Text.GetDisplayText # To directly get the displayed text
---@return string
GetText = function(self)
return self._fullText
end,

--- Sets custom truncation trailing characters like "..." or "-".
---@param text string
SetTruncationText = function(self, text)
self._truncationText = tostring(text)
end,

---@param enabled boolean
SetTruncationEnabled = function(self, enabled)

-- prevent recursive OnDirty wrappers
if self._truncationEnabled == enabled then
return
end

self._truncationEnabled = enabled
if enabled then
-- Preserve any existing OnDirty callback before adding _applyTruncation
if self.Width.OnDirty then
self._originalWidthOnDirty = self.Width.OnDirty
end

self.Width.OnDirty = function(var)

if self._originalWidthOnDirty then
self._originalWidthOnDirty(var)
end

self:_applyTruncation()
end
Comment on lines +99 to +111

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this will fail if truncation is enabled and then OnDirty is changed later.
You'd need to put the width lazyvar behind a proxy that intercepts modifications to OnDirty to avoid this.
Proxy meaning an empty table with a metatable that uses a function for __newindex to intercept OnDirty. Not sure how the engine interacts with that though, sometimes it rawgets things.

This is an optional change though because from what I see in the codebase, Width.OnDirty is rarely changed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah at least this one won't overwrite another OnDirty, but it will be up to someone else to preserve the truncation OnDirty when setting their own. Although that could get really frustrating to troubleshoot, but it's sorta a limitation of only having a single OnDirty for any given property.

Maybe some sort of helper version that won't overwrite an existing one like PreservedOnDirty or StackOnDirty

Or a more complex system that allows you to add/remove to a list of named OnDirty functions. (I'd rather have a global fix rather than a niche hacky one, but that is probably out of the scope of this)


-- Apply truncation immediately so SetText() and SetTruncationEnabled() order doesn't matter
self:_applyTruncation()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a circular lazyvar error because SetTruncationEnabled is called in score.lua before Left/Right/Width are set, and applyTruncation calls Width(). Ideally SetTruncationEnabled shouldn't interact with the layout LazyVars by calling them directly as from a user perspective it is a property of the text, kinda unrelated to the layout, but I am not experienced with UI code that much so I don't have a direct solution. Could you see if something elegant is possible?

@Lightningbulb2 Lightningbulb2 Sep 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I think I see what you're saying, but correct me if anything is wrong here:

(I'll use "element" in the context of HTML, hopefully you've seen its syntax)

The Control type defined in control.lua is basically the lowest level UI element. It contains all the dimensions, state, and properties for a "standard" element.

Elements like Text, Bitmap, and Button all extend Control

So with the current setup, it's not that Text is modifying the layout, but rather the Text element is managing its own layout while also containing the text.

The way FAF does it would be like if standard HTML was like this:

<!--used for alignment and formatting-->
<div width="50%" text-align="center" background-color="lightblue">

    <text Cropping="true" TruncationText="..." Color="red" Width="30">
       YOURWORDSHERE
    </text> 
    
    <Bitmap file="path/to/file/" Width="30">
     
    <Button="path/to/standardButton">

</div>

But HTML sort of does what you're suggesting and uses the generic formatting element <div> to both contain and style raw text, but also layout many other elements

<div width="50%" text-align="center" background-color="lightblue">

   <!-- class properties OR inline definitions ("color: red" for example)-->
    <div class="beautiful-text" color="red">
       YOURWORDSHERE
    </div> 
    
    <Bitmap file="path/to/file/" Width="30">
     
    <Button="path/to/standardButton">
</div>
// CSS class definition for above text

.beautiful-text {
  width: 250px;             /* 1. Explicit width is required */
  white-space: nowrap;      /* 2. Prevents the text from wrapping to a new line */
  overflow: hidden;         /* 3. Hides the overflowing content */
  text-overflow: ellipsis;  /* 4. Adds the '...' at the end */
}

But while HTML is generally designed as a text-first system, I see why the FAF engine kept it as its own element. Things would get cluttered and confusing if control.lua was designed to hold and display text by default.

If text starts getting a lot of complex/incompatible features then you would want to split/inherit it into several text types. (Like scrolling animated text for example) HTML has <H1> to <H6> for header sizes.


So while I'm still unsure about the solution to the circular dependency problem, that's the explanation to why it's setup like this.


Why does SetClipToWidth() seem to have no problem with the lazyvar thing, but mine does?

    ---@param clipToWidth boolean
    SetClipToWidth = function(self, clipToWidth)
        if clipToWidth then
            self.Width:Set(function() return self.Right() - self.Left() end)
        else
            self.Width:Set(function() return math.floor(self.TextAdvance()) end)
        end
        self:SetNewClipToWidth(clipToWidth)
    end,

Thanks for reviewing and helping me with this!

(I had a fun time writing this! I didn't anticipate my basic HTML experience would help me understand FAF UI xD)

Written without any AI

@Lightningbulb2 Lightningbulb2 Sep 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe not perfect, but this fixes the lazyvar width() initialization

--- Internal function to fit the truncation string inside the max width
_applyTruncation = function(self)

  -- Avoid unnecessary truncation, and no width issues
  if self._fullText == "" then return end

  local initialized, maxWidth = pcall(function() return self.Width() end)
  if not initialized or maxWidth <= 0 then
      self:SetDisplayText(self._fullText)
      return
end

and that also makes me realize that we could have optional truncation as a shorthand in SetClipToWidth()

    --- Adjusts text cropping behavior
    ---@param clipToWidth boolean
    ---@param truncationEnabled? boolean
    ---@param customTruncationSymbol? string
    SetClipToWidth = function(self, clipToWidth, truncationEnabled, customTruncationSymbol)
        if clipToWidth then
            self.Width:Set(function() return self.Right() - self.Left() end)
        else
            self:SetTruncationEnabled(false)
            self.Width:Set(function() return math.floor(self.TextAdvance()) end)
        end

        if truncationEnabled then
            self:SetTruncationEnabled(truncationEnabled)
        end

        if customTruncationSymbol ~= nil then
            self:SetTruncationText(customTruncationSymbol)
        end

        self:SetNewClipToWidth(clipToWidth)
    end,

But then I wonder if it should all only be in SetClipToWidth() as that is required for truncation anyway.

else
-- Restore to the original OnDirty callback if it exists, otherwise set it to nil
if self._originalWidthOnDirty then
self.Width.OnDirty = self._originalWidthOnDirty
self._originalWidthOnDirty = nil
else
self.Width.OnDirty = nil
end
self:SetDisplayText(self._fullText)
end
Comment thread
coderabbitai[bot] marked this conversation as resolved.

end,

--- Adjusts text cropping behavior
---@param clipToWidth boolean
---@param truncationEnabled? boolean
---@param customTruncationSymbol? string
SetClipToWidth = function(self, clipToWidth, truncationEnabled, customTruncationSymbol)
if clipToWidth then
self.Width:Set(function() return self.Right() - self.Left() end)
else
self:SetTruncationEnabled(false)
self.Width:Set(function() return math.floor(self.TextAdvance()) end)
end

if truncationEnabled ~= nil then
self:SetTruncationEnabled(truncationEnabled)
end

if customTruncationSymbol ~= nil then
self:SetTruncationText(customTruncationSymbol)
end

self:SetNewClipToWidth(clipToWidth)
end,

--- Internal function to fit the truncation string inside the max width
_applyTruncation = function(self)

-- Avoid unnecessary truncation, and no width issues
if self._fullText == "" then return end

local initialized, maxWidth = pcall(function () return self.Width() end)
if not initialized or maxWidth <= 0 then
self:SetDisplayText(self._fullText)
return
end

local truncationText = self._truncationText
local str = self._fullText
if str == nil then return end
-- restore full text if it now fits
if self:GetStringAdvance(str) <= maxWidth then
self:SetDisplayText(str)
return
end

--iterate until string + truncation text fit
local i = STR_Utf8Len(str)
while i > 0 and self:GetStringAdvance(str .. truncationText) > maxWidth do
str = STR_Utf8SubString(str, 1, i - 1)
i = i - 1
end

self:SetDisplayText(str .. truncationText)
end,

-- lazy var support
SetFont = function(self, family, pointsize)
if self._font then
Expand Down
1 change: 1 addition & 0 deletions lua/system/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ end
---@generic T
---@param t T
---@return T
---@nodiscard
function table.copy(t)
if type(t) ~= 'table' then return t end

Expand Down
4 changes: 4 additions & 0 deletions lua/ui/game/layouts/score_mini.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ function SetLayout()
controls.timeIcon:SetTexture(UIUtil.UIFile('/game/unit_view_icons/time.dds'))
LayoutHelpers.RightOf(controls.time, controls.timeIcon)

LayoutHelpers.RightOf(controls.gameSpeed, controls.time, 4)

LayoutHelpers.AtLeftTopIn(controls.gameQuality, controls.bgTop, 138, 6)

LayoutHelpers.AtRightTopIn(controls.unitIcon, controls.bgTop, 10, 6)
controls.unitIcon:SetTexture(UIUtil.UIFile('/dialogs/score-overlay/tank_bmp.dds'))
LayoutHelpers.LeftOf(controls.units, controls.unitIcon)
Expand Down
69 changes: 58 additions & 11 deletions lua/ui/game/score.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,14 @@ function updatePlayerName(line)
end

if sessionInfo.Options.Divisions then
line.name:SetText(playerClan .. playerName .. playerDivision)
line.division:SetText(playerDivision)
else
line.name:SetText(playerClan .. playerName .. playerRating)
line.division:SetText(playerRating)
end

line.name:SetText(playerClan .. playerName)
line.name:SetDropShadow(true)
LayoutHelpers.AnchorToLeft(line.name, line.division)
end

function armyGroupHeight()
Expand Down Expand Up @@ -119,14 +123,20 @@ function CreateScoreUI(parent)

LayoutHelpers.SetWidth(controls.bgTop, 320)

controls.time = UIUtil.CreateText(controls.bgTop, '0', 12, UIUtil.bodyFont)
controls.time = UIUtil.CreateText(controls.bgTop, '0', 12, UIUtil.bodyFont, true)
controls.time:SetColor('ff00dbff')
controls.timeIcon = Bitmap(controls.bgTop)
Tooltip.AddControlTooltip(controls.timeIcon, 'score_time')
Tooltip.AddControlTooltip(controls.time, 'score_time')
controls.gameSpeed = UIUtil.CreateText(controls.bgTop, '', 12, UIUtil.bodyFont, true)
controls.gameSpeed:SetColor('ffbadaff')
Tooltip.AddControlTooltip(controls.gameSpeed, 'score_game_speed')
controls.gameQuality = UIUtil.CreateText(controls.bgTop, '', 12, UIUtil.bodyFont, true)
controls.gameQuality:SetColor('ff00dbff')
Tooltip.AddControlTooltip(controls.gameQuality, 'score_game_quality')
controls.unitIcon = Bitmap(controls.bgTop)
Tooltip.AddControlTooltip(controls.unitIcon, 'score_units')
controls.units = UIUtil.CreateText(controls.bgTop, '0', 12, UIUtil.bodyFont)
controls.units = UIUtil.CreateText(controls.bgTop, '0', 12, UIUtil.bodyFont, true)
controls.units:SetColor('ffff9900')
Tooltip.AddControlTooltip(controls.units, 'score_units')

Expand Down Expand Up @@ -303,14 +313,20 @@ function SetupPlayerLines()
LayoutHelpers.AtVerticalCenterIn(group.name, group)
group.name:SetColor('ffffffff')

group.division = UIUtil.CreateText(group, '', 12, UIUtil.bodyFont, true)
group.division:DisableHitTest()
LayoutHelpers.AtRightIn(group.division, group, 135)
LayoutHelpers.AtVerticalCenterIn(group.division, group)
group.division:SetColor('ffffffff')

group.score = UIUtil.CreateText(group, '', 12, UIUtil.bodyFont)
group.score:DisableHitTest()
LayoutHelpers.AtRightIn(group.score, group, sw * 2 + 16)
LayoutHelpers.AtVerticalCenterIn(group.score, group)
group.score:SetColor('ffffffff')

LayoutHelpers.AnchorToLeft(group.name, group.score, 5)
group.name:SetClipToWidth(true)
group.name:SetClipToWidth(true, true)

if armyIndex ~= 0 then
group.mass = Bitmap(group)
Expand Down Expand Up @@ -373,6 +389,19 @@ function SetupPlayerLines()
Tooltip.AddControlTooltip(group.units, {text = '', body = bodyText}, 1)
end

-- hover to see full name (incase they are cut off)
group.nameHover = Bitmap(group)
group.nameHover:SetAlpha(0)
LayoutHelpers.AnchorToLeft(group.nameHover, group.division)
LayoutHelpers.AtLeftIn(group.nameHover, group, 12)
group.nameHover.Height:Set(group.name.Height)
LayoutHelpers.AtVerticalCenterIn(group.nameHover, group)
Tooltip.AddAutoUpdatedControlTooltip(group.nameHover,
function() return group.name:GetText() or "" end,
function() return "" end,
0.5
)

group.Height:Set(group.faction.Height)
group.Width:Set(controls.armyGroup.Width)
group.armyID = armyIndex
Expand Down Expand Up @@ -417,6 +446,7 @@ function SetupPlayerLines()
observerLine:Hide()
observerLine.OnHide = blockOnHide
observerLine.name.Top:Set(observerLine.Top)
observerLine.name:SetDropShadow(true)
LayoutHelpers.SetHeight(observerLine, 15)

if SessionIsReplay() then
Expand Down Expand Up @@ -477,7 +507,7 @@ function SetupPlayerLines()
end

-- ui for share conditions
group.ShareConditions = UIUtil.CreateText(group, data.ShareConditionsTitle, 10, UIUtil.bodyFont)
group.ShareConditions = UIUtil.CreateText(group, data.ShareConditionsTitle, 10, UIUtil.bodyFont, true)
Tooltip.AddForcedControlTooltipManual(group.ShareConditions, data.ShareConditionsTitle, data.ShareConditionsDescription)
LayoutHelpers.AtLeftIn(group.ShareConditions, group)
LayoutHelpers.AtVerticalCenterIn(group.ShareConditions, group)
Expand All @@ -486,15 +516,15 @@ function SetupPlayerLines()
previous = AddDash()

-- ui for map size
group.Size = UIUtil.CreateText(group, data.SizeText, 10, UIUtil.bodyFont)
group.Size = UIUtil.CreateText(group, data.SizeText, 10, UIUtil.bodyFont, true)
LayoutHelpers.RightOf(group.Size, previous)
LayoutHelpers.AtVerticalCenterIn(group.Size, group)
group.Size:SetColor('ffffffff')
previous = group.Size
previous = AddDash()

-- ui for map name
group.MapName = UIUtil.CreateText(group, data.MapTitle, 10, UIUtil.bodyFont)
group.MapName = UIUtil.CreateText(group, data.MapTitle, 10, UIUtil.bodyFont, true)
Tooltip.AddForcedControlTooltipManual(group.MapName, data.MapTitle, data.MapDescription)
LayoutHelpers.RightOf(group.MapName, previous)
LayoutHelpers.AtVerticalCenterIn(group.MapName, group)
Expand Down Expand Up @@ -619,11 +649,17 @@ local prevPlayableWidth = sessionInfo.PlayableAreaWidth
local prevPlayableHeight = sessionInfo.PlayableAreaHeight

function _OnBeat()
local s = string.format("%s (%+d / %+d)", GetGameTime(), gameSpeed, GetSimRate())
local t = string.format("%s", GetGameTime())
controls.time:SetText(t)

local s = string.format("(%+d / %+d)",gameSpeed, GetSimRate())
controls.gameSpeed:SetText(s)

if sessionInfo.Options.Quality then
s = string.format("%s Q:%.2f%%", s, sessionInfo.Options.Quality)
local q = string.format("Q:%.2f%%", sessionInfo.Options.Quality)
controls.gameQuality:SetText(q)
end
controls.time:SetText(s)


if sessionInfo.Options.NoRushOption and sessionInfo.Options.NoRushOption ~= 'Off' then
local norush = tonumber(sessionInfo.Options.NoRushOption) * 60
Expand Down Expand Up @@ -666,6 +702,7 @@ function _OnBeat()
if GetFocusArmy() ~= index then
line.name:SetColor('ffa0a0a0')
line.score:SetColor('ffa0a0a0')
line.division:SetColor('ffa0a0a0')
end
line.mass_in:SetColor('ffa0a0a0')
line.energy_in:SetColor('ffa0a0a0')
Expand Down Expand Up @@ -718,26 +755,36 @@ function _OnBeat()
if line.armyID == prevArmy then
if line.OOG then
line.name:SetColor('ffa0a0a0')
line.division:SetColor('ffa0a0a0')
line.score:SetColor('ffa0a0a0')
else
line.name:SetColor('ffffffff')
line.division:SetColor('ffffffff')
line.score:SetColor('ffffffff')
end
line.name:SetFont(UIUtil.bodyFont, 12)
line.division:SetFont(UIUtil.bodyFont, 12)
line.score:SetFont(UIUtil.bodyFont, 12)
elseif line.armyID == curFA then
line.name:SetColor('ffff7f00')
line.division:SetColor('ffff7f00')
line.score:SetColor('ffff7f00')

line.name:SetFont('Arial Bold', 12)
line.division:SetFont('Arial Bold', 12)
line.score:SetFont('Arial Bold', 12)
end
end
if curFA < 1 then
observerLine.name:SetColor('ffff7f00')
observerLine.division:SetColor('ffff7f00')
observerLine.division:SetFont('Arial Bold', 12)
observerLine.name:SetFont('Arial Bold', 12)
elseif prevArmy < 1 then
observerLine.name:SetColor('ffffffff')
observerLine.division:SetColor('ffffffff')
observerLine.name:SetFont(UIUtil.bodyFont, 12)
observerLine.division:SetFont(UIUtil.bodyFont, 12)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
end
if observerLine:IsHidden() and ((curFA < 1) or (sessionInfo.Options.CheatsEnabled == 'true')) then
table.insert(controls.armyLines, table.getsize(controls.armyLines), observerLine)
Expand Down
8 changes: 8 additions & 0 deletions lua/ui/help/tooltips.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1817,6 +1817,14 @@ Tooltips = {
title = "<LOC tooltipui0473>Game Time",
description = "",
},
score_game_speed ={
title = "<LOC tooltipui0738>Game Speed",
description = "<LOC tooltipui0739>[your requested speed] / [actual game speed]",
},
score_game_quality = {
title = "<LOC tooltipui0740>Game Quality",
description = "<LOC tooltipui0741>Estimated game quality",
},
score_units = {
title = "<LOC tooltipui0474>Unit Count",
description = "<LOC tooltipui0507>Current and maximum unit counts",
Expand Down