hhdeath/src/client/hud.qc

412 lines
8.2 KiB
Plaintext

/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void HUD_DrawWeaponSelect(void);
/* Use first frame for drawing (needs precache) */
#define HUD_NUMS "sprites/640_numbers.spr_0.tga"
#define NUMSIZE_X 32/256
#define NUMSIZE_Y 32/64
#define HUD_ALPHA 1.0
vector spr_hudnum[10] = {
[0 / 256, 0],
[32 / 256, 0],
[(32*2) / 256, 0],
[(32*3) / 256, 0],
[(32*4) / 256, 0],
[(32*5) / 256, 0],
[(32*6) / 256, 0],
[(32*7) / 256, 0],
[0 / 256, 32/64],
[32 / 256, 32/64]
};
/* pre-calculated sprite definitions */
float spr_health[4] = {
80 / 256, // pos x
24 / 128, // pos y
32 / 256, // size x
32 / 128 // size y
};
#define HUD_SUIT "sprites/640_suit.spr_0.tga"
#define SUITSIZE_X 32/128
#define SUITSIZE_Y 32/64
float spr_suit1[4] = {
0 / 128, // pos x
0 / 128, // pos y
40 / 128, // size x
40 / 64 // size y
};
float spr_suit2[4] = {
40 / 128, // pos x
0 / 128, // pos y
40 / 128, // size x
40 / 64 // size y
};
#define HUD_FLASH "sprites/640hud7.spr_0.tga"
#define FLASHSIZE_X 24/256
#define FLASHSIZE_Y 24/128
float spr_flash1[4] = {
160 / 256, // pos x
24 / 128, // pos y
32 / 256, // size x
32 / 128 // size y
};
float spr_flash2[4] = {
112 / 256, // pos x
24 / 128, // pos u
48 / 256, // size x
32 / 128 // size y
};
/* precaches */
void
HUD_Init(void)
{
precache_model("sprites/640_cross.spr");
precache_model("sprites/640_numbers.spr");
precache_model("sprites/640_logo.spr");
precache_model("sprites/640_suit.spr");
precache_model("sprites/640hud7.spr");
HUD_DamageNotify_Init();
}
/* handle single/multiple digits */
void
HUD_DrawNumber(int iNumber, vector vecPos, float fAlpha, vector vColor)
{
drawsubpic(vecPos,
[32,32],
"sprites/640_numbers.spr_0.tga",
spr_hudnum[iNumber],
[NUMSIZE_X, NUMSIZE_Y],
vColor,
fAlpha,
DRAWFLAG_ADDITIVE
);
}
void
HUD_DrawNums(float fNumber, vector vecPos, float fAlpha, vector vColor)
{
int i = fNumber;
if (i > 0) {
while (i > 0) {
HUD_DrawNumber((float)i % 10, vecPos, fAlpha, vColor);
i = i / 10;
vecPos[0] -= 32;
}
} else {
HUD_DrawNumber(0, vecPos, fAlpha, vColor);
}
}
/* health */
/* We don't need the changing color if case
* it's always red in Household DEATH! */
void
HUD_DrawHealth(void)
{
vector pos;
player pl = (player)pSeat->m_ePlayer;
if (pl.health != pSeatLocal->m_iHealthOld) {
pSeatLocal->m_flHealthAlpha = 1.0;
}
if (pSeatLocal->m_flHealthAlpha >= HUD_ALPHA) {
pSeatLocal->m_flHealthAlpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flHealthAlpha = HUD_ALPHA;
}
pos = g_hudmins + [14, g_hudres[1] - 42];
drawpic(
pos,
"sprites/640_cross.spr_0.tga",
[32,32],
[1,1,1],
pSeatLocal->m_flHealthAlpha
);
HUD_DrawNums(pl.health, pos + [96], pSeatLocal->m_flHealthAlpha, g_hud_color);
pSeatLocal->m_iHealthOld = pl.health;
}
/* armor/suit charge */
void
HUD_DrawArmor(void)
{
vector pos;
player pl = (player)pSeat->m_ePlayer;
pos = g_hudmins + [198, g_hudres[1] - 42];
if (pl.armor != pSeatLocal->m_iArmorOld) {
pSeatLocal->m_flArmorAlpha = 1.0;
}
if (pSeatLocal->m_flArmorAlpha >= HUD_ALPHA) {
pSeatLocal->m_flArmorAlpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flArmorAlpha = HUD_ALPHA;
}
drawsubpic(
pos + [-48,-9],
[40,40],
HUD_SUIT,
[spr_suit2[0], spr_suit2[1]],
[spr_suit2[2], spr_suit2[3]],
[1,1,1],
1.0f
);
if (pl.armor > 0) {
drawsubpic(
pos + [-48,-9],
[40, 40 * (pl.armor / 100)],
HUD_SUIT,
[spr_suit1[0],
spr_suit1[1]],
[spr_suit1[2], spr_suit1[3] * (pl.armor / 100)],
[1,1,1],
1.0f
);
}
HUD_DrawNums(pl.armor, pos + [48] , pSeatLocal->m_flArmorAlpha, g_hud_color);
pSeatLocal->m_iArmorOld = pl.armor;
}
/* magazine/clip ammo */
void
HUD_DrawAmmo1(void)
{
player pl = (player)pSeat->m_ePlayer;
vector pos;
if (pl.a_ammo1 != pSeatLocal->m_iAmmo1Old) {
pSeatLocal->m_flAmmo1Alpha = 1.0;
pSeatLocal->m_iAmmo1Old = pl.a_ammo1;
}
if (pSeatLocal->m_flAmmo1Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo1Alpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flAmmo1Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 152, g_hudres[1] - 42];
HUD_DrawNums(pl.a_ammo1, pos, pSeatLocal->m_flAmmo1Alpha, g_hud_color);
}
/* leftover type ammo */
void
HUD_DrawAmmo2(void)
{
player pl = (player)pSeat->m_ePlayer;
vector pos;
if (pl.a_ammo2 != pSeatLocal->m_iAmmo2Old) {
pSeatLocal->m_flAmmo2Alpha = 1.0;
pSeatLocal->m_iAmmo2Old = pl.a_ammo2;
}
if (pSeatLocal->m_flAmmo2Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo2Alpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flAmmo2Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42];
HUD_DrawNums(pl.a_ammo2, pos, pSeatLocal->m_flAmmo2Alpha, g_hud_color);
}
/* special ammo */
void
HUD_DrawAmmo3(void)
{
player pl = (player)pSeat->m_ePlayer;
vector pos;
if (pl.a_ammo3 != pSeatLocal->m_iAmmo3Old) {
pSeatLocal->m_flAmmo3Alpha = 1.0;
pSeatLocal->m_iAmmo3Old = pl.a_ammo3;
}
if (pSeatLocal->m_flAmmo3Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo3Alpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flAmmo3Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74];
HUD_DrawNums(pl.a_ammo3, pos, pSeatLocal->m_flAmmo3Alpha, g_hud_color);
}
/* ammo bar */
void
HUD_DrawAmmoBar(vector pos, float val, float max, float a)
{
if (val <= 0)
return;
float perc;
perc = val / max;
drawfill(pos + [10,0], [20,4], g_hud_color, a, DRAWFLAG_NORMAL);
drawfill(pos + [10,0], [20 * perc,4], [0,1,0], a, DRAWFLAG_NORMAL);
}
/* flashlight/torch indicator */
void
HUD_DrawFlashlight(void)
{
vector pos;
player pl = (player)pSeat->m_ePlayer;
pos = g_hudmins + [g_hudres[0] - 48, 16];
/* both on, draw both sprites at full intensity */
if (pl.gflags & GF_FLASHLIGHT) {
drawsubpic(
pos,
[32,32],
HUD_FLASH,
[spr_flash1[0], spr_flash1[1]],
[spr_flash1[2], spr_flash1[3]],
g_hud_color,
1.0f,
DRAWFLAG_ADDITIVE
);
drawsubpic(
pos,
[48,32],
HUD_FLASH,
[spr_flash2[0], spr_flash2[1]],
[spr_flash2[2], spr_flash2[3]],
g_hud_color,
1.0f,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[32,32],
HUD_FLASH,
[spr_flash1[0], spr_flash1[1]],
[spr_flash1[2], spr_flash1[3]],
g_hud_color,
HUD_ALPHA,
DRAWFLAG_ADDITIVE
);
}
}
/* logo animation used during e3 1998 */
void
HUD_DrawLogo(void)
{
vector pos;
static int f;
static float frame_timer;
frame_timer -= clframetime;
pos = [g_hudres[0] - 262, 48];
drawpic(
pos,
sprintf("sprites/640_logo.spr_%i.tga", f),
[256,48],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
if (frame_timer > 0) {
return;
}
frame_timer = 0.1f;
f++;
if (f == 31) {
f = 0;
}
}
/* weapon/ammo pickup notifications */
void
HUD_DrawNotify(void)
{
vector pos;
player pl = (player)pSeat->m_ePlayer;
if (pSeatLocal->m_flPickupAlpha <= 0.0f) {
return;
}
pos = g_hudmins + [g_hudres[0] - 192, g_hudres[1] - 128];
Weapons_HUDPic(pl, pSeatLocal->m_iPickupWeapon, 1, pos, pSeatLocal->m_flPickupAlpha);
pSeatLocal->m_flPickupAlpha -= clframetime;
}
void
HUD_WeaponPickupNotify(int w)
{
pSeatLocal->m_iPickupWeapon = w;
pSeatLocal->m_flPickupAlpha = 1.0f;
}
/* main entry */
void
HUD_Draw(void)
{
player pl = (player)pSeat->m_ePlayer;
g_hud_color = autocvar_con_color * (1 / 255);
/* little point in not drawing these, even if you don't have a suit */
Weapons_DrawCrosshair(pl);
HUD_DrawWeaponSelect();
Obituary_Draw();
if (!(pl.g_items & ITEM_SUIT)) {
return;
}
HUD_DrawHealth();
HUD_DamageNotify_Draw();
HUD_DrawArmor();
HUD_DrawFlashlight();
HUD_DrawNotify();
Damage_Draw();
}
/* specatator main entry */
void
HUD_DrawSpectator(void)
{
// FIXME
}