From 3117e979d67aca1012124ae7bf62b4420998f82e Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Fri, 17 Dec 2021 18:22:02 -0800 Subject: [PATCH] Client: Add damage and item pickup notifications to the HUD. This is the last stretch of the HUD stuff (now we only need the tracktrain UI!) --- src/client/damage.qc | 3 + src/client/hud.qc | 11 ++- src/client/hud_ammonotify.qc | 7 +- src/client/hud_dmgnotify.qc | 137 +++++++++++++++++++++++++++++++++++ src/client/hud_itemnotify.qc | 91 +++++++++++++++++++++++ src/client/progs.src | 2 + src/shared/player.qc | 15 +++- 7 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 src/client/hud_dmgnotify.qc create mode 100644 src/client/hud_itemnotify.qc diff --git a/src/client/damage.qc b/src/client/damage.qc index d3007e9..68a2d81 100644 --- a/src/client/damage.qc +++ b/src/client/damage.qc @@ -12,6 +12,7 @@ Damage_Precache(void) g_damage_spr_l = spriteframe("sprites/640_pain.spr", 3, 0.0f); } +void HUD_DamageNotify_Check(); void Damage_Draw(void) { @@ -24,6 +25,8 @@ Damage_Draw(void) return; } + HUD_DamageNotify_Check(); + center = video_mins + (video_res / 2); /* the pos relative to the player + view_dir determines which diff --git a/src/client/hud.qc b/src/client/hud.qc index 008b0c0..78349bd 100644 --- a/src/client/hud.qc +++ b/src/client/hud.qc @@ -84,6 +84,8 @@ HUD_Init(void) g_hud6_spr = spriteframe("sprites/640hud6.spr", 0, 0.0f); g_hud7_spr = spriteframe("sprites/640hud7.spr", 0, 0.0f); HUD_AmmoNotify_Init(); + HUD_DamageNotify_Init(); + HUD_ItemNotify_Init(); } /* seperator for mainly ammo */ @@ -393,16 +395,16 @@ HUD_DrawNotify(void) pos = g_hudmins + [g_hudres[0] - 192, g_hudres[1] - 128]; if (pSeatLocal->m_flPickupAlpha <= 0.0f) { - pos[0] += 148; - pos[1] += 16; + pos[1] += 48; + HUD_ItemNotify_Draw(pos); HUD_AmmoNotify_Draw(pos); return; } a = bound(0.0, pSeatLocal->m_flPickupAlpha, 1.0); + pos[1] += 48 * (1.0 - a); Weapons_HUDPic(pSeatLocal->m_iPickupWeapon, 1, pos, a); - pos[0] += 148; - pos[1] -= 32; + HUD_ItemNotify_Draw(pos); HUD_AmmoNotify_Draw(pos); pSeatLocal->m_flPickupAlpha -= (clframetime * 0.5); } @@ -446,6 +448,7 @@ HUD_Draw(void) return; } + HUD_DamageNotify_Draw(); HUD_DrawHealth(); HUD_DrawArmor(); HUD_DrawFlashlight(); diff --git a/src/client/hud_ammonotify.qc b/src/client/hud_ammonotify.qc index 9ccc592..34d5d10 100644 --- a/src/client/hud_ammonotify.qc +++ b/src/client/hud_ammonotify.qc @@ -43,9 +43,9 @@ HUD_AmmoNotify_Init(void) } void -HUD_AmmoNotify_Draw(vector startpos) +HUD_AmmoNotify_Draw(__inout vector pos) { - vector pos = startpos; + pos[0] = g_hudmins[0] + g_hudres[0] - 40; for (int i = 0; i < AMMO_COUNT; i++) { vector srcpos; @@ -61,6 +61,8 @@ HUD_AmmoNotify_Draw(vector startpos) srcpos = g_ammotype[i]; a = bound(0, g_ammonotify[i].alpha, 1.0); + /* we'll use the alpha to control the offset so it gently glides down when fading out */ + pos -= [0, 32 * a]; /* go up a notch */ drawsubpic(pos, [24,24], g_ammo_spr, @@ -77,7 +79,6 @@ HUD_AmmoNotify_Draw(vector startpos) drawstring(pos + [-offs - 8,4], sprintf("%i", g_ammonotify[i].count), [20,20], g_hud_color, a, DRAWFLAG_ADDITIVE); g_ammonotify[i].alpha -= (clframetime * 0.5); - pos -= [0, 32]; /* go up a notch */ } } diff --git a/src/client/hud_dmgnotify.qc b/src/client/hud_dmgnotify.qc new file mode 100644 index 0000000..af59050 --- /dev/null +++ b/src/client/hud_dmgnotify.qc @@ -0,0 +1,137 @@ + +#define DMG_COUNT 8 + +string g_dmg1_spr; +string g_dmg2_spr; + +typedef struct +{ + float alpha; +} dmgnote_t; +dmgnote_t g_dmgnotify[DMG_COUNT]; + +vector g_dmgtype[DMG_COUNT] = { + [0,0], // chemical + [0.25,0], // drown + [0.5,0], // poison + [0.75,0], // shock + [0,0], // nerve gas + [0.25,0], // freeze / slowfreeze + [0.5,0], // burn / slowburn + [0.75,0], // radiation? +}; + +void +HUD_DamageNotify_Init(void) +{ + g_dmg1_spr = spriteframe("sprites/640hud8.spr", 0, 0.0f); + g_dmg2_spr = spriteframe("sprites/640hud9.spr", 0, 0.0f); +} + +void +HUD_DamageNotify_Draw(void) +{ + vector pos; + + pos = g_hudmins + [16, g_hudres[1] - 128]; + + for (int i = 0; i < DMG_COUNT; i++) { + vector srcpos; + float a; + + /* make sure we skip any faded entries, and also null them */ + if (g_dmgnotify[i].alpha <= 0.0f) { + continue; + } + + /* let's get the src img pos for our type */ + srcpos = g_dmgtype[i]; + + a = (sin(cltime * 2.5) * 0.5) + 0.5; + a *= bound(0.0f, g_dmgnotify[i].alpha, 1.0); + + if (i < 4) + drawsubpic(pos, + [64,64], + g_dmg1_spr, + srcpos, + [64/256, 64/64], + g_hud_color, + a, + DRAWFLAG_ADDITIVE + ); + else + drawsubpic(pos, + [64,64], + g_dmg2_spr, + srcpos, + [64/256, 64/64], + g_hud_color, + a, + DRAWFLAG_ADDITIVE + ); + + g_dmgnotify[i].alpha -= (clframetime * 2.0); + pos -= [0, 64]; /* go up a notch */ + } +} + +typedef enum +{ + DMGNOT_CHEMICAL, + DMGNOT_DROWN, + DMGNOT_POISON, + DMGNOT_SHOCK, + DMGNOT_NERVEGAS, + DMGNOT_FREEZE, + DMGNOT_BURN, + DMGNOT_RADIATION +} dmgnot_e; + +#define DMG_NOTIFY_SET(x) g_dmgnotify[x].alpha = 10.0f + +/* called whenever we should check for pickup updates */ +void +HUD_DamageNotify_Check(void) +{ + if (pSeat->m_iDamageFlags & DMG_CHEMICAL) { + pSeat->m_iDamageFlags &= ~DMG_CHEMICAL; + DMG_NOTIFY_SET(DMGNOT_CHEMICAL); + } + if (pSeat->m_iDamageFlags & DMG_BURN) { + pSeat->m_iDamageFlags &= ~DMG_BURN; + DMG_NOTIFY_SET(DMGNOT_BURN); + } + if (pSeat->m_iDamageFlags & DMG_SLOWBURN) { + pSeat->m_iDamageFlags &= ~DMG_SLOWBURN; + DMG_NOTIFY_SET(DMGNOT_BURN); + } + if (pSeat->m_iDamageFlags & DMG_ELECTRO) { + pSeat->m_iDamageFlags &= ~DMG_ELECTRO; + DMG_NOTIFY_SET(DMGNOT_SHOCK); + } + if (pSeat->m_iDamageFlags & DMG_DROWN) { + pSeat->m_iDamageFlags &= ~DMG_DROWN; + DMG_NOTIFY_SET(DMGNOT_DROWN); + } + if (pSeat->m_iDamageFlags & DMG_NERVEGAS) { + pSeat->m_iDamageFlags &= ~DMG_NERVEGAS; + DMG_NOTIFY_SET(DMGNOT_NERVEGAS); + } + if (pSeat->m_iDamageFlags & DMG_POISON) { + pSeat->m_iDamageFlags &= ~DMG_POISON; + DMG_NOTIFY_SET(DMGNOT_POISON); + } + if (pSeat->m_iDamageFlags & DMG_RADIATION) { + pSeat->m_iDamageFlags &= ~DMG_RADIATION; + DMG_NOTIFY_SET(DMGNOT_RADIATION); + } + if (pSeat->m_iDamageFlags & DMG_FREEZE) { + pSeat->m_iDamageFlags &= ~DMG_FREEZE; + DMG_NOTIFY_SET(DMGNOT_FREEZE); + } + if (pSeat->m_iDamageFlags & DMG_SLOWFREEZE) { + pSeat->m_iDamageFlags &= ~DMG_SLOWFREEZE; + DMG_NOTIFY_SET(DMGNOT_FREEZE); + } +} \ No newline at end of file diff --git a/src/client/hud_itemnotify.qc b/src/client/hud_itemnotify.qc new file mode 100644 index 0000000..d1fb11e --- /dev/null +++ b/src/client/hud_itemnotify.qc @@ -0,0 +1,91 @@ + +#define ITEM_COUNT 3 + +string g_item_spr; + +typedef struct +{ + float alpha; + int count; +} itemnote_t; +itemnote_t g_itemnotify[ITEM_COUNT]; + +vector g_itemtype[ITEM_COUNT] = { + [176/256, 0/256], // battery + [176/256, 48/256], // medkit + [176/256, 96/256], // longjump +}; + +void +HUD_ItemNotify_Init(void) +{ + g_item_spr = spriteframe("sprites/640hud2.spr", 0, 0.0f); +} + +void +HUD_ItemNotify_Draw(__inout vector pos) +{ + pos[0] = g_hudmins[0] + g_hudres[0] - 44; + for (int i = 0; i < ITEM_COUNT; i++) { + vector srcpos; + float a; + + /* make sure we skip any faded entries, and also null them */ + if (g_itemnotify[i].alpha <= 0.0f) { + g_itemnotify[i].count = 0; + continue; + } + + /* let's get the src img pos for our type */ + srcpos = g_itemtype[i]; + a = bound(0, g_itemnotify[i].alpha, 1.0); + + /* we'll use the alpha to control the offset so it gently glides down when fading out */ + pos -= [0, 52 * a]; /* go up a notch */ + drawsubpic(pos + [-20,0], + [44,44], + g_item_spr, + srcpos, + [44/256, 44/256], + g_hud_color, + a, + DRAWFLAG_ADDITIVE + ); + + if (g_itemnotify[i].count > 1) { + drawfont = Font_GetID(FONT_20); + string txt = sprintf("%i", g_itemnotify[i].count); + float offs = stringwidth(txt, FALSE, [20,20]) + 16; + drawstring(pos + [-offs - 8,12], sprintf("%i", g_itemnotify[i].count), [20,20], g_hud_color, a, DRAWFLAG_ADDITIVE); + } + + g_itemnotify[i].alpha -= (clframetime * 0.5); + } +} + +void +HUD_ItemNotify_Insert(int type, int count) +{ + if (count <= 0) + return; + + g_itemnotify[type].count += count; + g_itemnotify[type].alpha = 2.5f; + +} + +/* called whenever we should check for pickup updates */ +void +HUD_ItemNotify_Check(player pl) +{ + int healthdiff = bound(0, pl.health - pl.health_net, 100); + int armordiff = bound(0, pl.armor - pl.armor_net, 100); + int longjumpdiff = ((pl.g_items & ITEM_LONGJUMP) > (pl.g_items_net & ITEM_LONGJUMP)) == TRUE; + + if (healthdiff > 1) + HUD_ItemNotify_Insert(1, 1); + if (armordiff > 1) + HUD_ItemNotify_Insert(0, 1); + if (longjumpdiff) + HUD_ItemNotify_Insert(2, 1); +} \ No newline at end of file diff --git a/src/client/progs.src b/src/client/progs.src index 9d83d29..fdca467 100644 --- a/src/client/progs.src +++ b/src/client/progs.src @@ -32,6 +32,8 @@ game_event.qc ../../../valve/src/client/viewmodel.qc view.qc obituary.qc +hud_itemnotify.qc +hud_dmgnotify.qc hud_ammonotify.qc hud.qc hud_weaponselect.qc diff --git a/src/shared/player.qc b/src/shared/player.qc index 0219403..c0ddc3f 100644 --- a/src/shared/player.qc +++ b/src/shared/player.qc @@ -106,6 +106,7 @@ class player:base_player #ifdef CLIENT void Weapons_AmmoUpdate(entity); void HUD_AmmoNotify_Check(player pl); +void HUD_ItemNotify_Check(player pl); /* ================= player::ReceiveEntity @@ -159,12 +160,24 @@ player::ReceiveEntity(float new, float fl) mode_tempstate = readbyte(); } + setorigin(this, origin); + + /* these only concern the current player */ + CSQC_UpdateSeat(); + if (this != pSeat->m_ePlayer) + return; + + /* do not notify us of updates when spawning initially */ + if (fl == UPDATE_ALL) + PredictPreFrame(); + if (fl & PLAYER_AMMO1 || fl & PLAYER_AMMO2 || fl & PLAYER_AMMO3) { Weapons_AmmoUpdate(this); HUD_AmmoNotify_Check(this); } - setorigin(this, origin); + if (fl & PLAYER_ITEMS || fl & PLAYER_HEALTH || fl & PLAYER_ARMOR) + HUD_ItemNotify_Check(this); } /*