HalfLife
January 22

Half-Life SDK: Заполняющаяся шкала здоровья

Суть: Сделать заполняющуюся шкалу здоровья игрока.

Итоговый результат:

1) Создать спрайт. Я взял шкалу здоровья из "Mass Effect 3" ("Umodel Viewer": пакет "Startup").

Для обработки изображений использовал "GIMP" (Под шкалой создать чёрный фон->Объединить слои->"Изображение"->"Режим"->"Индексированный"->"Создать оптимальную палитру"->"Максимальное количество цветов": 256->"Преобразовать"->Сохранить как "Windows BMP").

Для создания файла спрайта использовал "QSpriteViewer" от "FreeSlave" (https://bitbucket.org/FreeSlave/qspriteviewer/src/master/). Для этого в окне программы: "Tools"->"Sprite creator"->Оставляем "Format: Half-Life" и жмём "Next"->"Load palette from sample image"->Выбираем наш "BMP"-файл->"Next"->"Add images"->Выбираем наш "BMP"-файл снова->Выбираем место сохранения спрайта в папку "sprites" проекта.

2) Редактуем файл "hud.txt". В файл вписываем:

health_empty		640 zdrvo 0 128 256 128
health_full			640 zdrvo 0 0 256 128

где "zdrvo" — имя створенного спрайта.

3) Редактуем "cl_dll/health.h". Фактично код для шкалы здоровья повторяет код батареи ("cl_dll/battery.cpp").

В "private"-секцию "class CHudHealth : public CHudBase" вписываем:

HSPRITE m_hSprite1;
HSPRITE m_hSprite2;
Rect* m_prc1;
Rect* m_prc2;
int m_iHeight;

3) Редактуем "cl_dll/health.cpp". Вносим в "bool CHudHealth::VidInit()" следующее:

int HUD_health_empty = gHUD.GetSpriteIndex("health_empty");
int HUD_health_full = gHUD.GetSpriteIndex("health_full");
m_hSprite1 = m_hSprite2 = 0;

m_prc1 = &gHUD.GetSpriteRect(HUD_health_empty);
m_prc2 = &gHUD.GetSpriteRect(HUD_health_full);
m_iHeight = m_prc2->left - m_prc1->right;
m_fFade = 0;

Функция "bool CHudHealth::Draw(float flTime)" выглядит так:

bool CHudHealth::Draw(float flTime)
{
  if ((gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) != 0 || 0 != gEngfuncs.IsSpectateOnly())
		return true;

	int r, g, b, x, y, a;
	Rect rc;

	rc = *m_prc2;

	rc.right += m_iHeight * ((float)(100 - (V_min(100, m_iHealth))) * 0.01);

	UnpackRGB(r, g, b, RGB_YELLOWISH);

	if (!gHUD.HasSuit())
		return true;

	if (0 != m_fFade)
	{
		if (m_fFade > FADE_TIME)
			m_fFade = FADE_TIME;

		m_fFade -= (gHUD.m_flTimeDelta * 20);
		if (m_fFade <= 0)
		{
			a = 128;
			m_fFade = 0;
		}

		// Fade the health number back to dim

		a = MIN_ALPHA + (m_fFade / FADE_TIME) * 128;
	}
	else
		a = MIN_ALPHA;

	ScaleColors(r, g, b, a);

	int iOffset = (m_prc1->bottom - m_prc1->top) / 6;

	y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
	x = ScreenWidth / 3;

	if (0 == m_hSprite1)
		m_hSprite1 = gHUD.GetSprite(gHUD.GetSpriteIndex("health_empty"));
	if (0 == m_hSprite2)
		m_hSprite2 = gHUD.GetSprite(gHUD.GetSpriteIndex("health_full"));

	SPR_Set(m_hSprite1, r, g, b);
	SPR_DrawAdditive(0, x, y - iOffset, m_prc1);

	if (rc.bottom > rc.top)
	{
		SPR_Set(m_hSprite2, r, g, b);
		SPR_DrawAdditive(0, x, y - iOffset + (rc.top - m_prc2->top), &rc);
	}
	return true;
}

В этом коде не ествует часть, отвечающая за отображение сторон-источников урона ("DrawDamage(flTime)" и т.д.).

Аналогичный код и для батареи.