Добавлен , опубликован
В патче 2.0 была добавлена новая настройка, а именно ползунок HUD Scale, позволяющий уменьшать размер стандартного интерфейса.
Естественно, эта опция влияет и на кастомные фреймы, и может сломать интерфейс. Челы с хайва просят добавить возможность форсить этот параметр из карты, но пока с этим всё равно приходится жить.

Ползунок позволяет игроку установить значение от 0 до 100. Итоговый масштаб определяется по формуле (val / 2 + 50) / 100, или проще (val + 100) / 200. То есть диапазон значений от 0.5 до 1. Далее игра применяет масштаб к ряду стандартных фреймов.
Ряд стандартных фреймов
// Кривоватый дизасм, но названия элементов худа можно разглядеть
void __fastcall CGameUI::UpdateHUDScale(CGameUI *this, float scale)
{
  CToolTipWar3 *Tooltip; // [rsp+78h] [rbp-30h]

  ((void (__fastcall *)(CLayoutFrame *))this->m_miniMap->SetLayoutScale)(&this->m_miniMap->CLayoutFrame);
  ((void (__fastcall *)(CSimpleFrame *))this->m_minimapButtonBar->SetLayoutScale)(this->m_minimapButtonBar);
  CSpriteFrame::SetSpriteScale(this->m_currentPortraitButton, 1.0 / scale);
  ((void (__fastcall *)(CLayoutFrame *))this->m_currentPortraitButton->SetLayoutScale)(&this->m_currentPortraitButton->CLayoutFrame);
  ((void (__fastcall *)(CSimpleFrame *))this->m_simpleConsoleBottomBarFrame->SetLayoutScale)(this->m_simpleConsoleBottomBarFrame);
  ((void (__fastcall *)(CLayoutFrame *))this->m_consoleBackdropFrame->SetLayoutScale)(&this->m_consoleBackdropFrame->CLayoutFrame);
  Tooltip = CGameUI::GetTooltip(this);
  ((void (__fastcall *)(CToolTipWar3 *))Tooltip->SetLayoutScale)(Tooltip);
  if ( this->m_trackingStub )
    ((void (__fastcall *)(CSimpleButton *))this->m_trackingStub->SetLayoutScale)(this->m_trackingStub);
}
Я предпринимал некоторые попытки перебивать опцию настроек, выставляя масштаб упомянутым фреймам вручную из кода, но это приводило лишь к поломкам стандартного интерфейса. Не делайте так, не надо.

Как защитить кастомные фреймы?

В тот момент когда эта опция была добавлена в игру, я делал карту с визуализацией целиком на фреймах. Я был уверен, что это сломает буквально всю карту, но реальность оказалась не такой страшной.

Модельки и текстурки

Как оказалось, для спрайтов и бекдропов достаточно лишь явно указать масштаб. Да, даже если масштабирование не предполагается, всё равно нужно вызвать BlzFrameSetScale(frame, 1), чтобы опция перестала масштабировать эти фреймы.
Можно убедиться в этом запустив карту Flappy Bird, в которой весь экран занимают спрайты и бекдропы. Она абсолютно не чувствительна к изменениям HUD Scale.

Текст

У фреймов типа TEXT немного другое поведение. Сложно объяснить, но суть в том, что значение HUD Scale влияет не на уже существующие текстовые фреймы, а на создающиеся. То есть, если игрок запустит игру с пониженным HUD Scale, то созданный кодом TEXT будет... увеличен. Даже если затем вернуть HUD Scale в 100, то фрейм не вернётся в нормальный размер. Как с этим бороться? Всё той же явной установкой масштаба, но не самому текстовому фрейма, а его родителю до создания фрейма. Пример на картинках. Слева просто созданные текстовые фреймы (вверху и внизу экрана) с родителем "ConsoleUIBackdrop", а справа этому родителю явно задан масштаб 1.

Как узнать значение HUD Scale игрока?

Это не моя идея, но сейчас не вспомню никнейм автора, который обнаружил эту зависимость. API позволяет получить ширину фрейма "ConsoleBottomBar", которая зависит от значения масштаба в настройках. А дальше нам нужно лишь немного математики.
---returns a value from 0 to 0.4
function getHUDScaleDelta()
    return BlzFrameGetWidth(BlzGetFrameByName("ConsoleBottomBar", 0)) - .4
end

---returns a value from 0.5 to 1.0
function getHUDScaleRealValue()
    return getHUDScaleDelta() * 1.25 + 0.5
end

---returns a value from 0 to 100
function getHUDScaleIntValue()
    return MathRound(getHUDScaleDelta() * 250)
end

---returns true if HUD Scale less than 100
function isCustomHUDScale()
    return math.abs(BlzFrameGetWidth(BlzGetFrameByName("ConsoleBottomBar", 0)) - 0.8) > 0.0001
end
Интовое значение из ползунка вернёт функция getHUDScaleIntValue, а фактический масштаб — getHUDScaleRealValue. В мультиплеерных картах это, конечно же, нужно делать для локального игрока.
`
ОЖИДАНИЕ РЕКЛАМЫ...