Merge branch 'master' of github.com:fabiangreffrath/woof

This commit is contained in:
Fabian Greffrath 2024-05-19 21:28:46 +02:00
commit efe9729537
13 changed files with 421 additions and 28 deletions

View File

@ -22,8 +22,9 @@ jobs:
matrix:
config:
- name: Linux GCC
os: ubuntu-latest
os: ubuntu-24.04
compiler: gcc
extra-options: -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_FIND_PACKAGE_PREFER_CONFIG=OFF
shell: bash
- name: macOS Clang
@ -51,11 +52,6 @@ jobs:
libsndfile1-dev \
libfluidsynth-dev \
libxmp-dev
sudo sed -e 's/jammy/lunar/g;s/22/23/g' -i /etc/apt/sources.list /etc/apt/sources.list.d/*
sudo apt-get update
sudo apt-get install \
libflac-dev \
libsndfile1-dev
- name: Install dependencies (macOS)
if: runner.os == 'macOS'
@ -95,8 +91,8 @@ jobs:
CC: ${{ matrix.config.compiler }}
run: |
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DENABLE_WERROR=ON -DENABLE_HARDENING=ON -DENABLE_LTO=ON
-DENABLE_WERROR=ON -DENABLE_HARDENING=ON -DENABLE_LTO=ON \
${{ matrix.config.extra-options }}
- name: Build
run: cmake --build build

View File

@ -1,11 +1,14 @@
hud 0
title bottomleft
rate topleft
monsec topleft
sttime topleft
coord topright
fps topright
cmd bottomright
hud 1
title bottomleft
rate topleft
armor bottomleft
health bottomleft
@ -16,8 +19,10 @@ monsec bottomleft
sttime bottomleft
coord topright
fps topright
cmd bottomright
hud 2
title bottomleft
rate topleft
health topright
armor topright
@ -26,5 +31,6 @@ weapon bottomright
keys bottomleft
monsec bottomleft
sttime bottomleft
coord topright
coord topright
fps topright
cmd bottomright

View File

@ -17,8 +17,8 @@ The following lines start with the name of the HUD widget which is to be positio
Possible values for the HUD widget names:
* "title" or "levelname"
* "message" (new in Woof! 12.0.0)
* "secret" (new in Woof! 12.0.0)
* "message"
* "secret"
* "armor"
* "health"
* "ammo"
@ -28,6 +28,7 @@ Possible values for the HUD widget names:
* "sttime" or "time"
* "coord" or "coords"
* "fps" or "rate"
* "cmd" or "commands"
Possible values for the widget position keywords:
@ -49,13 +50,16 @@ The following example represents the current default alignments of the Boom HUD
```
hud 0
title bottomleft
monsec bottomleft
sttime bottomleft
rate topleft
monsec topleft
sttime topleft
coord topright
fps topright
cmd bottomright
hud 1
title bottomleft
rate topleft
armor bottomleft
health bottomleft
ammo bottomleft
@ -65,9 +69,11 @@ monsec bottomleft
sttime bottomleft
coord topright
fps topright
cmd bottomright
hud 2
title bottomleft
rate topleft
health topright
armor topright
ammo bottomright
@ -77,6 +83,7 @@ monsec bottomleft
sttime bottomleft
coord topright
fps topright
cmd bottomright
```
An alternative approach to the distributed HUD, using absolute screen coordinates, could look like this:

View File

@ -28,6 +28,7 @@ set(WOOF_SOURCES
f_wipe.c f_wipe.h
font.h
g_game.c g_game.h
hu_command.c hu_command.h
hu_lib.c hu_lib.h
hu_obituary.c hu_obituary.h
hu_stuff.c hu_stuff.h

View File

@ -1055,6 +1055,7 @@ static void G_DoLoadLevel(void)
P_SetupLevel (gameepisode, gamemap, 0, gameskill);
MN_UpdateFreeLook();
HU_UpdateTurnFormat();
// [Woof!] Do not reset chosen player view across levels in multiplayer
// demo playback. However, it must be reset when starting a new game.
@ -2823,6 +2824,8 @@ void G_Ticker(void)
if (demoplayback)
++playback_tic;
HU_UpdateCommandHistory(&players[displayplayer].cmd);
// check for special buttons
for (i=0; i<MAXPLAYERS; i++)
if (playeringame[i] && players[i].cmd.buttons & BT_SPECIAL)
@ -3839,6 +3842,8 @@ void G_InitNew(skill_t skill, int episode, int map)
totalleveltimes = 0;
playback_tic = 0;
HU_ResetCommandHistory();
//jff 4/16/98 force marks on automap cleared every new level start
AM_clearMarks();

279
src/hu_command.c Normal file
View File

@ -0,0 +1,279 @@
//
// Copyright(C) 2022 Ryan Krafnick
// Copyright(C) 2024 ceski
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Command History HUD Widget
//
#include <string.h>
#include "d_event.h"
#include "doomstat.h"
#include "hu_command.h"
#include "i_printf.h"
#include "m_misc.h"
#include "v_video.h"
boolean hud_command_history;
int hud_command_history_size;
boolean hud_hide_empty_commands;
typedef struct
{
signed char forwardmove;
signed char sidemove;
short angleturn;
boolean attack;
boolean use;
byte change;
} hud_cmd_t;
typedef struct hud_cmd_item_s
{
struct hud_cmd_item_s *prev, *next;
char buf[HU_MAXLINELENGTH];
hud_cmd_t hud_cmd;
int count;
} hud_cmd_item_t;
static hud_cmd_item_t hud_cmd_items[HU_MAXMESSAGES];
static hud_cmd_item_t *current = hud_cmd_items;
static boolean lowres_turn_format;
void HU_UpdateTurnFormat(void)
{
const boolean playdemo = (gameaction == ga_playdemo || demoplayback);
lowres_turn_format = (!playdemo && lowres_turn) || (playdemo && !longtics);
}
void HU_InitCommandHistory(void)
{
for (int i = 1; i < HU_MAXMESSAGES; i++)
{
hud_cmd_items[i].prev = &hud_cmd_items[i - 1];
hud_cmd_items[i - 1].next = &hud_cmd_items[i];
}
hud_cmd_items[0].prev = &hud_cmd_items[HU_MAXMESSAGES - 1];
hud_cmd_items[HU_MAXMESSAGES - 1].next = &hud_cmd_items[0];
}
void HU_ResetCommandHistory(void)
{
for (int i = 0; i < HU_MAXMESSAGES; i++)
{
memset(&hud_cmd_items[i].hud_cmd, 0, sizeof(hud_cmd_t));
hud_cmd_items[i].count = 0;
hud_cmd_items[i].buf[0] = '\0';
}
}
static void TicToHudCmd(hud_cmd_t *hud_cmd, const ticcmd_t *cmd)
{
hud_cmd->forwardmove = cmd->forwardmove;
hud_cmd->sidemove = cmd->sidemove;
if (lowres_turn_format)
{
hud_cmd->angleturn = (cmd->angleturn + 128) >> 8;
}
else
{
hud_cmd->angleturn = cmd->angleturn;
}
if (cmd->buttons && !(cmd->buttons & BT_SPECIAL))
{
hud_cmd->attack = (cmd->buttons & BT_ATTACK) > 0;
hud_cmd->use = (cmd->buttons & BT_USE) > 0;
if (cmd->buttons & BT_CHANGE)
{
hud_cmd->change =
1 + ((cmd->buttons & BT_WEAPONMASK) >> BT_WEAPONSHIFT);
}
else
{
hud_cmd->change = 0;
}
}
else
{
hud_cmd->attack = false;
hud_cmd->use = false;
hud_cmd->change = 0;
}
}
static boolean IsEmpty(const hud_cmd_t *hud_cmd)
{
return (hud_cmd->forwardmove == 0
&& hud_cmd->sidemove == 0
&& hud_cmd->angleturn == 0
&& hud_cmd->attack == false
&& hud_cmd->use == false
&& hud_cmd->change == 0);
}
static boolean IsEqual(const hud_cmd_t *hud_cmd1, const hud_cmd_t *hud_cmd2)
{
return (hud_cmd1->forwardmove == hud_cmd2->forwardmove
&& hud_cmd1->sidemove == hud_cmd2->sidemove
&& hud_cmd1->angleturn == hud_cmd2->angleturn
&& hud_cmd1->attack == hud_cmd2->attack
&& hud_cmd1->use == hud_cmd2->use
&& hud_cmd1->change == hud_cmd2->change);
}
static void UpdateHudCmdText(hud_cmd_item_t *cmd_disp)
{
const hud_cmd_t *hud_cmd = &cmd_disp->hud_cmd;
char *buf = cmd_disp->buf;
const int len = sizeof(cmd_disp->buf);
int i = M_snprintf(buf, len, "\x1b%c", '0' + CR_GRAY);
if (cmd_disp->count)
{
i += M_snprintf(buf + i, len - i, "x%-3d ", cmd_disp->count + 1);
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
if (hud_cmd->forwardmove > 0)
{
i += M_snprintf(buf + i, len - i, "MF%2d ", hud_cmd->forwardmove);
}
else if (hud_cmd->forwardmove < 0)
{
i += M_snprintf(buf + i, len - i, "MB%2d ", -hud_cmd->forwardmove);
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
if (hud_cmd->sidemove > 0)
{
i += M_snprintf(buf + i, len - i, "SR%2d ", hud_cmd->sidemove);
}
else if (hud_cmd->sidemove < 0)
{
i += M_snprintf(buf + i, len - i, "SL%2d ", -hud_cmd->sidemove);
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
if (lowres_turn_format)
{
if (hud_cmd->angleturn > 0)
{
i += M_snprintf(buf + i, len - i, "TL%2d ", hud_cmd->angleturn);
}
else if (hud_cmd->angleturn < 0)
{
i += M_snprintf(buf + i, len - i, "TR%2d ", -hud_cmd->angleturn);
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
}
else
{
if (hud_cmd->angleturn > 0)
{
i += M_snprintf(buf + i, len - i, "TL%5d ", hud_cmd->angleturn);
}
else if (hud_cmd->angleturn < 0)
{
i += M_snprintf(buf + i, len - i, "TR%5d ", -hud_cmd->angleturn);
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
}
if (hud_cmd->attack)
{
i += M_snprintf(buf + i, len - i, "A ");
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
if (hud_cmd->use)
{
i += M_snprintf(buf + i, len - i, "U ");
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
if (hud_cmd->change)
{
i += M_snprintf(buf + i, len - i, "C%d", hud_cmd->change);
}
else
{
i += M_snprintf(buf + i, len - i, " ");
}
}
void HU_UpdateCommandHistory(const ticcmd_t *cmd)
{
hud_cmd_t hud_cmd;
if (!STRICTMODE(hud_command_history))
{
return;
}
TicToHudCmd(&hud_cmd, cmd);
if (hud_hide_empty_commands && IsEmpty(&hud_cmd))
{
return;
}
if (IsEqual(&hud_cmd, &current->hud_cmd))
{
current->count++;
}
else
{
current->count = 0;
current = current->next;
current->hud_cmd = hud_cmd;
}
UpdateHudCmdText(current);
}
void HU_BuildCommandHistory(hu_multiline_t *const multiline)
{
hud_cmd_item_t *hud_cmd = current;
for (int i = 0; i < hud_command_history_size; i++)
{
HUlib_add_string_keep_space(multiline, hud_cmd->buf);
hud_cmd = hud_cmd->prev;
}
}

38
src/hu_command.h Normal file
View File

@ -0,0 +1,38 @@
//
// Copyright(C) 2022 Ryan Krafnick
// Copyright(C) 2024 ceski
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Command History HUD Widget
//
#ifndef __HU_COMMAND__
#define __HU_COMMAND__
#include "doomtype.h"
#include "hu_lib.h"
struct hu_multiline_s;
struct ticcmd_s;
extern boolean hud_command_history;
extern int hud_command_history_size;
extern boolean hud_hide_empty_commands;
void HU_UpdateTurnFormat(void);
void HU_InitCommandHistory(void);
void HU_ResetCommandHistory(void);
void HU_UpdateCommandHistory(const struct ticcmd_s *cmd);
void HU_BuildCommandHistory(struct hu_multiline_s *const multiline);
#endif

View File

@ -160,7 +160,8 @@ static inline void inc_cur_line (hu_multiline_t *const m)
// [FG] add string to line, increasing its (length and) width
static void add_string_to_line (hu_line_t *const l, const hu_font_t *const f, const char *s)
static void add_string_to_line(hu_line_t *const l, const hu_font_t *const f,
const char *s, boolean keep_space)
{
int w = 0;
unsigned char c;
@ -189,8 +190,11 @@ static void add_string_to_line (hu_line_t *const l, const hu_font_t *const f, co
add_char_to_line(l, c);
}
while (*--s == ' ')
w -= f->space_width;
if (!keep_space)
{
while (*--s == ' ')
w -= f->space_width;
}
l->width += w;
}
@ -205,10 +209,10 @@ void HUlib_add_strings_to_cur_line (hu_multiline_t *const m, const char *prefix,
if (prefix)
{
add_string_to_line(l, *m->font, prefix);
add_string_to_line(l, *m->font, prefix, false);
}
add_string_to_line(l, *m->font, s);
add_string_to_line(l, *m->font, s, false);
inc_cur_line(m);
}
@ -218,6 +222,15 @@ void HUlib_add_string_to_cur_line (hu_multiline_t *const m, const char *s)
HUlib_add_strings_to_cur_line(m, NULL, s);
}
void HUlib_add_string_keep_space(hu_multiline_t *const m, const char *s)
{
hu_line_t *const l = m->lines[m->curline];
HUlib_clear_line(l);
add_string_to_line(l, *m->font, s, true);
inc_cur_line(m);
}
// [FG] horizontal and vertical alignment
static int horz_align_widget(const hu_widget_t *const w, const hu_line_t *const l, const align_t h_align)

View File

@ -53,7 +53,7 @@ extern struct patch_s **hu_font;
#define HU_MAXLINELENGTH 120
//jff 2/26/98 maximum number of messages allowed in refresh list
#define HU_MAXMESSAGES 8
#define HU_MAXMESSAGES 20
typedef enum
{
@ -135,6 +135,7 @@ void HUlib_clear_all_lines (hu_multiline_t *const m);
void HUlib_add_string_to_cur_line (hu_multiline_t *const m, const char *s);
void HUlib_add_strings_to_cur_line (hu_multiline_t *const m, const char *prefix, const char *s);
void HUlib_add_string_keep_space(hu_multiline_t *const m, const char *s);
void HUlib_draw_widget (const hu_widget_t *const w);

View File

@ -110,6 +110,7 @@ static player_t *plr;
static hu_font_t big_font = {.space_width = 4, .tab_width = 15, .tab_mask = ~15},
sml_font = {.space_width = 5, .tab_width = 7, .tab_mask = ~7};
static hu_font_t *doom_font = &big_font, *boom_font = &sml_font;
static hu_font_t *cmd_font = &sml_font;
patch_t **hu_font = big_font.patches;
static int CR_BLUE = CR_BLUE1;
@ -139,6 +140,7 @@ static hu_multiline_t w_sttime; // time above status bar
static hu_multiline_t w_coord;
static hu_multiline_t w_fps;
static hu_multiline_t w_rate;
static hu_multiline_t w_cmd;
#define MAX_HUDS 3
#define MAX_WIDGETS 16
@ -429,6 +431,8 @@ void HU_Init(void)
// [FG] support crosshair patches from extras.wad
HU_InitCrosshair();
HU_InitCommandHistory();
HU_InitObituaries();
HU_ParseHUD();
@ -496,6 +500,7 @@ static void HU_widget_build_armor (void);
static void HU_widget_build_coord (void);
static void HU_widget_build_fps (void);
static void HU_widget_build_rate (void);
static void HU_widget_build_cmd(void);
static void HU_widget_build_health (void);
static void HU_widget_build_keys (void);
static void HU_widget_build_frag (void);
@ -607,6 +612,12 @@ void HU_Start(void)
// [FG] draw the IDRATE widget exclusively
w_rate.exclusive = true;
HUlib_init_multiline(&w_cmd, hud_command_history_size,
&cmd_font, colrngs[hudcolor_xyco],
NULL, HU_widget_build_cmd);
// Draw command history bottom up.
w_cmd.bottomup = true;
HU_set_centered_message();
HU_disable_all_widgets();
@ -1237,6 +1248,11 @@ static void HU_widget_build_rate (void)
}
}
static void HU_widget_build_cmd(void)
{
HU_BuildCommandHistory(&w_cmd);
}
// Crosshair
static boolean hud_crosshair_health;
@ -1439,17 +1455,35 @@ void HU_Drawer(void)
}
// [FG] draw Time widget on intermission screen
void WI_DrawTimeWidget(void)
void WI_DrawWidgets(void)
{
const hu_widget_t w = {&w_sttime, align_left, align_top};
HUlib_reset_align_offsets();
if (hud_level_time & HUD_WIDGET_HUD)
{
HUlib_reset_align_offsets();
const hu_widget_t w = {&w_sttime, align_left, align_top};
// leveltime is already added to totalleveltimes before WI_Start()
//HU_widget_build_sttime();
HUlib_draw_widget(&w);
}
if (STRICTMODE(hud_command_history))
{
hu_widget_t *w = widgets[hud_active];
while (w->multiline)
{
if (w->multiline == &w_cmd
&& ((w->multiline->on && *w->multiline->on) || w->multiline->built))
{
w_cmd.built = false;
HU_cond_build_widget(&w_cmd, true);
HUlib_draw_widget(w);
break;
}
w++;
}
}
}
//
@ -1627,6 +1661,7 @@ void HU_Ticker(void)
HU_cond_build_widget(&w_fps, plr->cheats & CF_SHOWFPS);
HU_cond_build_widget(&w_rate, plr->cheats & CF_RENDERSTATS);
HU_cond_build_widget(&w_cmd, STRICTMODE(hud_command_history));
if (hud_displayed &&
scaledviewheight == SCREENHEIGHT &&
@ -1880,6 +1915,7 @@ static const struct {
{"coord", "coords", &w_coord},
{"fps", NULL, &w_fps},
{"rate", NULL, &w_rate},
{"cmd", "commands", &w_cmd},
{NULL},
};
@ -2138,10 +2174,6 @@ void HU_BindHUDVariables(void)
"Display HUD");
M_BindNum("hud_active", &hud_active, NULL, 2, 0, 2, ss_stat, wad_yes,
"HUD layout (by default: 0 = Minimal; 1 = Compact; 2 = Distributed)");
M_BindNum("hud_player_coords", &hud_player_coords, NULL,
HUD_WIDGET_AUTOMAP, HUD_WIDGET_OFF, HUD_WIDGET_ALWAYS,
ss_stat, wad_no,
"Show player coordinates widget (1 = On automap; 2 = On HUD; 3 = Always)");
M_BindNum("hud_level_stats", &hud_level_stats, NULL,
HUD_WIDGET_OFF, HUD_WIDGET_OFF, HUD_WIDGET_ALWAYS,
ss_stat, wad_no,
@ -2151,6 +2183,16 @@ void HU_BindHUDVariables(void)
HUD_WIDGET_OFF, HUD_WIDGET_OFF, HUD_WIDGET_ALWAYS,
ss_stat, wad_no,
"Show level time widget (1 = On automap, 2 = On HUD, 3 = Always)");
M_BindNum("hud_player_coords", &hud_player_coords, NULL,
HUD_WIDGET_AUTOMAP, HUD_WIDGET_OFF, HUD_WIDGET_ALWAYS,
ss_stat, wad_no,
"Show player coordinates widget (1 = On automap; 2 = On HUD; 3 = Always)");
M_BindBool("hud_command_history", &hud_command_history, NULL, false, ss_stat,
wad_no, "Show command history widget");
BIND_NUM(hud_command_history_size, 10, 1, HU_MAXMESSAGES,
"Number of commands to display for command history widget");
BIND_BOOL(hud_hide_empty_commands, true,
"Hide empty commands from command history widget");
M_BindBool("hud_time_use", &hud_time_use, NULL, false, ss_stat, wad_no,
"Show split time when pressing the use-button");
M_BindNum("hud_type", &hud_type, NULL,

View File

@ -21,6 +21,7 @@
#include "doomdef.h"
#include "doomtype.h"
#include "hu_command.h"
struct event_s;
struct mobj_s;
@ -48,7 +49,7 @@ boolean HU_DemoProgressBar(boolean force);
void HU_ResetMessageColors(void);
void WI_DrawTimeWidget(void);
void WI_DrawWidgets(void);
// killough 5/2/98: moved from m_misc.c:

View File

@ -1436,6 +1436,10 @@ static setup_menu_t stat_settings2[] = {
{"Show Player Coords", S_CHOICE | S_STRICT, M_X, M_SPC,
{"hud_player_coords"}, m_null, input_null, str_show_widgets},
{"Show Command History", S_ONOFF | S_STRICT, M_X, M_SPC,
{"hud_command_history"}, m_null, input_null, str_empty,
HU_ResetCommandHistory},
{"Use-Button Timer", S_ONOFF, M_X, M_SPC, {"hud_time_use"}},
MI_GAP,

View File

@ -2139,7 +2139,7 @@ void WI_Drawer (void)
else
WI_drawStats();
// [FG] draw Time widget on intermission screen
WI_DrawTimeWidget();
WI_DrawWidgets();
break;
case ShowNextLoc: