From 587032f1f6710a8dbe5d006e1fdbba5da1364cb9 Mon Sep 17 00:00:00 2001 From: Shpoike Date: Mon, 5 Jun 2023 23:51:02 +0100 Subject: [PATCH] Hexen2: Tweaks to the sbar to better match hexen2's. --- engine/client/client.h | 1 + engine/client/sbar.c | 204 +++++++++++++++++++++++++++++++-------- engine/common/bothdefs.h | 3 + 3 files changed, 170 insertions(+), 38 deletions(-) diff --git a/engine/client/client.h b/engine/client/client.h index f80fee5bc..fde4ab33a 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -657,6 +657,7 @@ struct playerview_s #ifdef HEXEN2 int sb_hexen2_cur_item;//hexen2 hud float sb_hexen2_item_time; + float sb_hexen2_extra_info_lines; qboolean sb_hexen2_extra_info;//show the extra stuff qboolean sb_hexen2_infoplaque; #endif diff --git a/engine/client/sbar.c b/engine/client/sbar.c index d4e5c9fdb..c0b7ba899 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -126,7 +126,8 @@ static apic_t *hsb_items[2]; static qboolean sbarfailed; #ifdef HEXEN2 -static qboolean sbar_hexen2; +qboolean sbar_hexen2; +static const char *puzzlenames; #endif #ifdef NQPROT static void Sbar_CTFScores_f(void); @@ -842,13 +843,14 @@ static void Sbar_Hexen2InvLeft_f(void) int tries = 15; playerview_t *pv = &cl.playerview[seat]; pv->sb_hexen2_item_time = realtime; + S_LocalSound("misc/invmove.wav"); while (tries-- > 0) { pv->sb_hexen2_cur_item--; if (pv->sb_hexen2_cur_item < 0) pv->sb_hexen2_cur_item = 14; - if (pv->stats[STAT_H2_CNT_TORCH+pv->sb_hexen2_cur_item] > 0) + if (pv->stats[STAT_H2_CNT_FIRST+pv->sb_hexen2_cur_item] > 0) break; } } @@ -869,13 +871,14 @@ static void Sbar_Hexen2InvRight_f(void) int tries = 15; playerview_t *pv = &cl.playerview[seat]; pv->sb_hexen2_item_time = realtime; + S_LocalSound("misc/invmove.wav"); while (tries-- > 0) { pv->sb_hexen2_cur_item++; if (pv->sb_hexen2_cur_item > 14) pv->sb_hexen2_cur_item = 0; - if (pv->stats[STAT_H2_CNT_TORCH+pv->sb_hexen2_cur_item] > 0) + if (pv->stats[STAT_H2_CNT_FIRST+pv->sb_hexen2_cur_item] > 0) break; } } @@ -895,6 +898,7 @@ static void Sbar_Hexen2InvUse_f(void) else { playerview_t *pv = &cl.playerview[seat]; + S_LocalSound("misc/invuse.wav"); Cmd_ExecuteString(va("impulse %d\n", 100+pv->sb_hexen2_cur_item), Cmd_ExecLevel); } } @@ -2422,26 +2426,45 @@ void Sbar_DrawScoreboard (playerview_t *pv) static void Sbar_Hexen2DrawActiveStuff(playerview_t *pv) { int x = r_refdef.grect.x + r_refdef.grect.width; - mpic_t *pic; + int y = 0; + + //rings are vertical... + if (pv->stats[STAT_H2_RINGS_ACTIVE] & 8) + { //turning... + R2D_ScalePic(x-32, r_refdef.grect.y+y, 32, 32, R2D_SafeCachePic(va("gfx/rngtrn%d.lmp", ((int)(cl.time*16)%15)+1))); + y += 32; + } + if (pv->stats[STAT_H2_RINGS_ACTIVE] & 2) + { //water breathing + R2D_ScalePic(x-32, r_refdef.grect.y+y, 32, 32, R2D_SafeCachePic(va("gfx/rngwtr%d.lmp", ((int)(cl.time*16)%15)+1))); + y += 32; + } + if (pv->stats[STAT_H2_RINGS_ACTIVE] & 1) + { //flight + R2D_ScalePic(x-32, r_refdef.grect.y+y, 32, 32, R2D_SafeCachePic(va("gfx/rngfly%d.lmp", ((int)(cl.time*16)%15)+1))); + y += 32; + } + + if (y) //if we drew the rings column, move artifacts over so they don't fight + x -= 50; + + //artifacts are horizontal (without stomping on rings)... if (pv->stats[STAT_H2_ARTIFACT_ACTIVE] & 4) - { - pic = R2D_SafeCachePic(va("gfx/pwrbook%d.lmp", ((int)(cl.time*16)%15)+1)); + { //tome of power x -= 32; - R2D_ScalePic(x, r_refdef.grect.y, 32, 32, pic); + R2D_ScalePic(x, r_refdef.grect.y, 32, 32, R2D_SafeCachePic(va("gfx/pwrbook%d.lmp", ((int)(cl.time*16)%15)+1))); x -= 18; } if (pv->stats[STAT_H2_ARTIFACT_ACTIVE] & 1) - { - pic = R2D_SafeCachePic(va("gfx/durhst%d.lmp", ((int)(cl.time*16)%15)+1)); + { //boots x -= 32; - R2D_ScalePic(x, r_refdef.grect.y, 32, 32, pic); + R2D_ScalePic(x, r_refdef.grect.y, 32, 32, R2D_SafeCachePic(va("gfx/durhst%d.lmp", ((int)(cl.time*16)%15)+1))); x -= 18; } if (pv->stats[STAT_H2_ARTIFACT_ACTIVE] & 2) - { - pic = R2D_SafeCachePic(va("gfx/durshd%d.lmp", ((int)(cl.time*16)%15)+1)); + { //invincibility x -= 32; - R2D_ScalePic(x, r_refdef.grect.y, 32, 32, pic); + R2D_ScalePic(x, r_refdef.grect.y, 32, 32, R2D_SafeCachePic(va("gfx/durshd%d.lmp", ((int)(cl.time*16)%15)+1))); x -= 18; } } @@ -2450,9 +2473,11 @@ static void Sbar_Hexen2DrawItem(playerview_t *pv, float x, float y, int itemnum) int num; Sbar_DrawMPic(x, y, 29, 28, R2D_SafeCachePic(va("gfx/arti%02d.lmp", itemnum))); - num = pv->stats[STAT_H2_CNT_TORCH+itemnum]; + num = pv->stats[STAT_H2_CNT_FIRST+itemnum]; if(num > 0) { + if (num > 99) + num = 99; if (num >= 10) Sbar_DrawMPic(x+20, y+21, 4, 6, R2D_SafeCachePic(va("gfx/artinum%d.lmp", num/10))); Sbar_DrawMPic(x+20+4, y+21, 4, 6, R2D_SafeCachePic(va("gfx/artinum%d.lmp", num%10))); @@ -2467,23 +2492,26 @@ static void Sbar_Hexen2DrawInventory(playerview_t *pv) int activeright = 0; /*always select an artifact that we actually have whether we are drawing the full bar or not.*/ - for (i = 0; i < 15; i++) + /*NOTE: Hexen2 reorders them in collection order.*/ + for (i = 0; i < STAT_H2_CNT_COUNT; i++) { - if (pv->stats[STAT_H2_CNT_TORCH+(i+pv->sb_hexen2_cur_item)%15]) + if (pv->stats[STAT_H2_CNT_FIRST+(i+pv->sb_hexen2_cur_item)%STAT_H2_CNT_COUNT]) { - pv->sb_hexen2_cur_item = (pv->sb_hexen2_cur_item + i)%15; + pv->sb_hexen2_cur_item = (pv->sb_hexen2_cur_item + i)%STAT_H2_CNT_COUNT; break; } } if (pv->sb_hexen2_item_time+3 < realtime) return; + if (!pv->stats[STAT_H2_CNT_FIRST+pv->sb_hexen2_cur_item]) + return; //no items... don't confuse the user. - for (i = pv->sb_hexen2_cur_item; i < 15; i++) - if (pv->sb_hexen2_cur_item == i || pv->stats[STAT_H2_CNT_TORCH+i] > 0) + for (i = pv->sb_hexen2_cur_item; i < STAT_H2_CNT_COUNT; i++) + if (pv->sb_hexen2_cur_item == i || pv->stats[STAT_H2_CNT_FIRST+i] > 0) activeright++; for (i = pv->sb_hexen2_cur_item-1; i >= 0; i--) - if (pv->sb_hexen2_cur_item == i || pv->stats[STAT_H2_CNT_TORCH+i] > 0) + if (pv->sb_hexen2_cur_item == i || pv->stats[STAT_H2_CNT_FIRST+i] > 0) activeleft++; if (activeleft > 3 + (activeright<=3?(4-activeright):0)) @@ -2491,7 +2519,7 @@ static void Sbar_Hexen2DrawInventory(playerview_t *pv) x=320/2-114 + (activeleft-1)*33; for (i = pv->sb_hexen2_cur_item-1; x>=320/2-114; i--) { - if (!pv->stats[STAT_H2_CNT_TORCH+i]) + if (!pv->stats[STAT_H2_CNT_FIRST+i]) continue; if (i == pv->sb_hexen2_cur_item) @@ -2501,9 +2529,9 @@ static void Sbar_Hexen2DrawInventory(playerview_t *pv) } x=320/2-114 + activeleft*33; - for (i = pv->sb_hexen2_cur_item; i < 15 && x < 320/2-114+7*33; i++) + for (i = pv->sb_hexen2_cur_item; i < STAT_H2_CNT_COUNT && x < 320/2-114+7*33; i++) { - if (i != pv->sb_hexen2_cur_item && !pv->stats[STAT_H2_CNT_TORCH+i]) + if (i != pv->sb_hexen2_cur_item && !pv->stats[STAT_H2_CNT_FIRST+i]) continue; if (i == pv->sb_hexen2_cur_item) Sbar_DrawMPic(x+9, y-12, 11, 11, R2D_SafeCachePic("gfx/artisel.lmp")); @@ -2512,6 +2540,83 @@ static void Sbar_Hexen2DrawInventory(playerview_t *pv) } } +static void Sbar_Hexen2DrawPuzzles (playerview_t *pv) +{ + unsigned int i, place=0, x, y, mid, j; + char name[64]; + const char *line; + mpic_t *pic; + + puzzlenames = FS_LoadMallocFile("puzzles.txt", NULL); + if (!puzzlenames) + puzzlenames = Z_StrDup(""); + + for (i = 0; i < 8; i++) + { + if (pv->statsstr[STAT_H2_PUZZLE1+i] && *pv->statsstr[STAT_H2_PUZZLE1+i]) + { + pic = R2D_SafeCachePic(va("gfx/puzzle/%s.lmp", pv->statsstr[STAT_H2_PUZZLE1+i])); + + strcpy(name, "Unknown"); + for (line = puzzlenames; (line = COM_Parse(line)); ) + { + if (!Q_strcasecmp(com_token, pv->statsstr[STAT_H2_PUZZLE1+i])) + { + while (*line == ' ' || *line == '\t') + line++; + for (j = 0; j < countof(name)-1; j++) + { + if (*line == '\r' || *line == '\n' || !*line) + break; + name[j] = *line++; + } + name[j] = 0; + break; + } + line = strchr(line, '\n'); + if (!line) + break; + line++; + } + + if (r_refdef.grect.width < 320) + { //screen too narrow for side by side. depend on height. + x = r_refdef.grect.x + 10; + y = 50 + place*32; + if (y+26 > r_refdef.grect.height) + continue; + y += sbar_rect.y; + mid = r_refdef.grect.x + r_refdef.grect.width; + R2D_ScalePic(x, y, 26, 26, pic); + Draw_FunStringWidth(x+35, y+(26-8)/2, name, mid-(x+35), false, false); + } + else if (place < 4) + { //first four are on the left. + x = r_refdef.grect.x + 10; + y = 50 + place*32; + if (y+26 > r_refdef.grect.height) + continue; + y += sbar_rect.y; + mid = r_refdef.grect.x + r_refdef.grect.width/2; + R2D_ScalePic(x, y, 26, 26, pic); + R_DrawTextField(x+35, y, mid-(x+35), 26, name, CON_WHITEMASK, CPRINT_LALIGN, font_default, NULL); + } + else + { //last four are on the right + x = r_refdef.grect.x + r_refdef.grect.width - 10 - 26; + y = 50 + (place-4)*32; + if (y+26 > r_refdef.grect.height) + continue; + y += sbar_rect.y; + mid = r_refdef.grect.x + r_refdef.grect.width/2; + R2D_ScalePic(x, y, 26, 26, pic); + R_DrawTextField(mid, y, x-(35-26)-mid, 26, name, CON_WHITEMASK, CPRINT_RALIGN, font_default, NULL); + } + place++; + } + } +} + static void Sbar_Hexen2DrawExtra (playerview_t *pv) { unsigned int i, slot; @@ -2528,20 +2633,13 @@ static void Sbar_Hexen2DrawExtra (playerview_t *pv) "Demoness" }; - if (!pv->sb_hexen2_extra_info) - { - sbar_rect.y -= 46-SBAR_HEIGHT; - return; - } +// if (!pv->sb_hexen2_extra_info) +// return; pclass = cl.players[pv->playernum].h2playerclass; if (pclass >= sizeof(pclassname)/sizeof(pclassname[0])) pclass = 0; - - //adjust it so there's space - sbar_rect.y -= 46+98-SBAR_HEIGHT; - Sbar_DrawMPic(0, 46, 160, 98, R2D_SafeCachePic("gfx/btmbar1.lmp")); Sbar_DrawMPic(160, 46, 160, 98, R2D_SafeCachePic("gfx/btmbar2.lmp")); @@ -2694,8 +2792,8 @@ static void Sbar_Hexen2DrawBasic(playerview_t *pv) Sbar_DrawMPic(43, 36, 10, 10, R2D_SafeCachePic("gfx/chnlcov.lmp")); Sbar_DrawMPic(267, 36, 10, 10, R2D_SafeCachePic("gfx/chnrcov.lmp")); - - Sbar_Hexen2DrawItem(pv, 144, 3, pv->sb_hexen2_cur_item); + if (pv->stats[STAT_H2_CNT_FIRST+pv->sb_hexen2_cur_item]) + Sbar_Hexen2DrawItem(pv, 144, 3, pv->sb_hexen2_cur_item); } static void Sbar_Hexen2DrawMinimal(playerview_t *pv) @@ -2709,6 +2807,9 @@ static void Sbar_Hexen2DrawMinimal(playerview_t *pv) Sbar_DrawTinyStringf(10, y+18+6, "%03d", pv->stats[STAT_H2_GREENMANA]); Sbar_Hexen2DrawNum(38, y+18, pv->stats[STAT_HEALTH], 3); + + if (pv->stats[STAT_H2_CNT_FIRST+pv->sb_hexen2_cur_item]) + Sbar_Hexen2DrawItem(pv, 320-32, y+10, pv->sb_hexen2_cur_item); } #endif @@ -2999,6 +3100,8 @@ void Sbar_Draw (playerview_t *pv) #ifdef HEXEN2 if (sbar_hexen2) { + extern cvar_t scr_conspeed; + float targlines; //hexen2 hud if (pv->sb_hexen2_infoplaque) @@ -3013,19 +3116,44 @@ void Sbar_Draw (playerview_t *pv) pv->sb_hexen2_infoplaque = false; } - if (sb_lines > 24 || pv->sb_hexen2_extra_info) + if (pv->sb_hexen2_extra_info) + targlines = 46+98; //extra stuff shown when hitting tab + else if (sb_lines > SBAR_HEIGHT) + targlines = 46; //viewsize 100 stuff... + else + targlines = -23; //viewsize 110/120 transparent overlay. negative covers the extra translucent details above. + if (targlines > pv->sb_hexen2_extra_info_lines) + { //expand + pv->sb_hexen2_extra_info_lines += scr_conspeed.value*host_frametime; + if (pv->sb_hexen2_extra_info_lines > targlines) + pv->sb_hexen2_extra_info_lines = targlines; + } + else + { //shrink + pv->sb_hexen2_extra_info_lines -= scr_conspeed.value*host_frametime; + if (pv->sb_hexen2_extra_info_lines < targlines) + pv->sb_hexen2_extra_info_lines = targlines; + } + + if (sb_lines > 0 && pv->sb_hexen2_extra_info_lines < 46) + Sbar_Hexen2DrawMinimal(pv); + if (pv->sb_hexen2_extra_info_lines > -23) { - Sbar_Hexen2DrawExtra(pv); + sbar_rect.y -= pv->sb_hexen2_extra_info_lines - SBAR_HEIGHT; //Sbar_DrawMPic... eww. + if (pv->sb_hexen2_extra_info_lines > 46) + Sbar_Hexen2DrawExtra(pv); Sbar_Hexen2DrawBasic(pv); } - else if (sb_lines > 0) - Sbar_Hexen2DrawMinimal(pv); Sbar_Hexen2DrawInventory(pv); if (minidmoverlay) Sbar_MiniDeathmatchOverlay (pv); Sbar_Hexen2DrawActiveStuff(pv); + + if (!cls.deathmatch) + if (pv->sb_showscores || pv->sb_showteamscores || pv->stats[STAT_HEALTH] <= 0) + Sbar_Hexen2DrawPuzzles(pv); } else #endif diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index ef214f141..5bf71d061 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -968,6 +968,7 @@ STAT_H2_DEXTERITY, // changes stat bar STAT_H2_BLUEMANA, // changes stat bar STAT_H2_GREENMANA, // changes stat bar STAT_H2_EXPERIENCE, // changes stat bar +#define STAT_H2_CNT_FIRST (STAT_H2_CNT_TORCH) STAT_H2_CNT_TORCH, // changes stat bar STAT_H2_CNT_H_BOOST, // changes stat bar STAT_H2_CNT_SH_BOOST, // changes stat bar @@ -983,6 +984,8 @@ STAT_H2_CNT_POLYMORPH, // changes stat bar STAT_H2_CNT_FLIGHT, // changes stat bar STAT_H2_CNT_CUBEOFFORCE, // changes stat bar STAT_H2_CNT_INVINCIBILITY, // changes stat bar +#define STAT_H2_CNT_LAST (STAT_H2_CNT_INVINCIBILITY) +#define STAT_H2_CNT_COUNT (STAT_H2_CNT_LAST+1-STAT_H2_CNT_FIRST) STAT_H2_ARTIFACT_ACTIVE, STAT_H2_ARTIFACT_LOW, STAT_H2_MOVETYPE,