HUD tracking: refactor nametags to use generic HUD tracker sorting

This commit is contained in:
James R 2024-01-25 21:58:40 -08:00
parent fa63dffe6b
commit 8ac2efe82c
3 changed files with 145 additions and 142 deletions

View file

@ -3749,6 +3749,55 @@ static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p)
V_DrawThinStringAtFixed(x + (5*FRACUNIT), y - (26*FRACUNIT), clr, player_names[p - players]);
}
playertagtype_t K_WhichPlayerTag(player_t *p)
{
UINT8 cnum = R_GetViewNumber();
if (!(demo.playback == true && camera[cnum].freecam == true) && P_IsDisplayPlayer(p) &&
p != &players[displayplayers[cnum]])
{
return PLAYERTAG_LOCAL;
}
else if (p->bot)
{
if (p->botvars.rival == true)
{
return PLAYERTAG_RIVAL;
}
}
else if (netgame || demo.playback)
{
if (K_ShowPlayerNametag(p) == true)
{
return PLAYERTAG_NAME;
}
}
return PLAYERTAG_NONE;
}
void K_DrawPlayerTag(fixed_t x, fixed_t y, player_t *p, playertagtype_t type)
{
switch (type)
{
case PLAYERTAG_LOCAL:
K_DrawLocalTagForPlayer(x, y, p, G_PartyPosition(p - players));
break;
case PLAYERTAG_RIVAL:
K_DrawRivalTagForPlayer(x, y);
break;
case PLAYERTAG_NAME:
K_DrawNameTagForPlayer(x, y, p);
K_DrawTypingNotifier(x, y, p);
break;
default:
break;
}
}
typedef struct weakspotdraw_t
{
UINT8 i;
@ -3788,12 +3837,8 @@ static void K_DrawWeakSpot(weakspotdraw_t *ws)
static void K_drawKartNameTags(void)
{
const fixed_t maxdistance = 8192*mapobjectscale;
vector3_t c;
UINT8 cnum = R_GetViewNumber();
UINT8 tobesorted[MAXPLAYERS];
fixed_t sortdist[MAXPLAYERS];
UINT8 sortlen = 0;
size_t i, j;
if (stplyr == NULL || stplyr->mo == NULL || P_MobjWasRemoved(stplyr->mo))
@ -3912,141 +3957,6 @@ static void K_drawKartNameTags(void)
K_drawTargetHUD(&c, stplyr);
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *ntplayer = &players[i];
fixed_t distance = maxdistance+1;
vector3_t v;
if (!playeringame[i] || ntplayer->spectator)
{
// Not in-game
continue;
}
if (ntplayer->mo == NULL || P_MobjWasRemoved(ntplayer->mo))
{
// No object
continue;
}
if (ntplayer->mo->renderflags & K_GetPlayerDontDrawFlag(stplyr))
{
// Invisible on this screen
continue;
}
if (!P_CheckSight(stplyr->mo, ntplayer->mo))
{
// Can't see
continue;
}
v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x);
v.y = R_InterpolateFixed(ntplayer->mo->old_y, ntplayer->mo->y);
v.z = R_InterpolateFixed(ntplayer->mo->old_z, ntplayer->mo->z);
if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP))
{
v.z += ntplayer->mo->height;
}
distance = R_PointToDist2(c.x, c.y, v.x, v.y);
if (distance > maxdistance)
{
// Too far away
continue;
}
tobesorted[sortlen] = ntplayer - players;
sortdist[sortlen] = distance;
sortlen++;
}
if (sortlen > 0)
{
UINT8 sortedplayers[MAXPLAYERS];
for (i = 0; i < sortlen; i++)
{
UINT8 pos = 0;
for (j = 0; j < sortlen; j++)
{
if (j == i)
{
continue;
}
if (sortdist[i] < sortdist[j]
|| (sortdist[i] == sortdist[j] && i > j))
{
pos++;
}
}
sortedplayers[pos] = tobesorted[i];
}
for (i = 0; i < sortlen; i++)
{
trackingResult_t result;
player_t *ntplayer = &players[sortedplayers[i]];
fixed_t headOffset = 36*ntplayer->mo->scale;
SINT8 localindicator = -1;
vector3_t v;
v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x);
v.y = R_InterpolateFixed(ntplayer->mo->old_y, ntplayer->mo->y);
v.z = R_InterpolateFixed(ntplayer->mo->old_z, ntplayer->mo->z);
v.z += (ntplayer->mo->height / 2);
if (stplyr->mo->eflags & MFE_VERTICALFLIP)
{
v.z -= headOffset;
}
else
{
v.z += headOffset;
}
K_ObjectTracking(&result, &v, false);
if (result.onScreen == true)
{
if (!(demo.playback == true && camera[cnum].freecam == true) && P_IsDisplayPlayer(ntplayer) &&
ntplayer != &players[displayplayers[cnum]])
{
localindicator = G_PartyPosition(ntplayer - players);
}
if (localindicator >= 0)
{
K_DrawLocalTagForPlayer(result.x, result.y, ntplayer, localindicator);
}
else if (ntplayer->bot)
{
if (ntplayer->botvars.rival == true)
{
K_DrawRivalTagForPlayer(result.x, result.y);
}
}
else if (netgame || demo.playback)
{
if (K_ShowPlayerNametag(ntplayer) == true)
{
K_DrawNameTagForPlayer(result.x, result.y, ntplayer);
K_DrawTypingNotifier(result.x, result.y, ntplayer);
}
}
}
}
}
V_ClearClipRect();
}

View file

@ -99,6 +99,18 @@ void K_ClearPersistentMessages(void);
void K_ClearPersistentMessageForPlayer(player_t *player);
void K_TickMessages(void);
typedef enum
{
PLAYERTAG_NONE,
PLAYERTAG_LOCAL,
PLAYERTAG_RIVAL,
PLAYERTAG_NAME,
}
playertagtype_t;
playertagtype_t K_WhichPlayerTag(player_t *p);
void K_DrawPlayerTag(fixed_t x, fixed_t y, player_t *p, playertagtype_t type);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -6,6 +6,7 @@
#include "core/static_vec.hpp"
#include "v_draw.hpp"
#include "g_game.h"
#include "k_battle.h"
#include "k_hud.h"
#include "k_kart.h"
@ -67,6 +68,7 @@ struct TargetTracking
trackingResult_t result;
fixed_t camDist;
bool foreground;
playertagtype_t nametag;
skincolornum_t color() const
{
@ -165,6 +167,42 @@ struct TargetTracking
return nullptr;
}
bool is_player_nametag_on_screen() const
{
const player_t* player = mobj->player;
if (nametag == PLAYERTAG_NONE)
{
return false;
}
if (player->spectator)
{
// Not in-game
return false;
}
if (mobj->renderflags & K_GetPlayerDontDrawFlag(stplyr))
{
// Invisible on this screen
return false;
}
if (camDist > 8192*mapobjectscale)
{
// Too far away
return false;
}
if (!P_CheckSight(stplyr->mo, const_cast<mobj_t*>(mobj)))
{
// Can't see
return false;
}
return true;
}
private:
Graphics graphics() const
{
@ -320,6 +358,12 @@ Visibility is_object_visible(const mobj_t* mobj)
void K_DrawTargetTracking(const TargetTracking& target)
{
if (target.nametag != PLAYERTAG_NONE)
{
K_DrawPlayerTag(target.result.x, target.result.y, target.mobj->player, target.nametag);
return;
}
Visibility visibility = is_object_visible(target.mobj);
if (visibility == Visibility::kFlicker && (leveltime & 1))
@ -553,6 +597,11 @@ void K_CullTargetList(std::vector<TargetTracking>& targetList)
return;
}
if (tr.nametag != PLAYERTAG_NONE)
{
return;
}
fixed_t x1 = std::max(((tr.result.x - kTrackerRadius) / kBlockSize) / FRACUNIT, 0);
fixed_t x2 = std::min(((tr.result.x + kTrackerRadius) / kBlockSize) / FRACUNIT, kXBlocks - 1);
fixed_t y1 = std::max(((tr.result.y - kTrackerRadius) / kBlockSize) / FRACUNIT, 0);
@ -618,7 +667,10 @@ void K_drawTargetHUD(const vector3_t* origin, player_t* player)
continue;
}
if (is_object_tracking_target(mobj) == false)
bool tracking = is_object_tracking_target(mobj);
playertagtype_t nametag = mobj->player ? K_WhichPlayerTag(mobj->player) : PLAYERTAG_NONE;
if (tracking == false && nametag == PLAYERTAG_NONE)
{
continue;
}
@ -634,10 +686,39 @@ void K_drawTargetHUD(const vector3_t* origin, player_t* player)
tr.mobj = mobj;
tr.camDist = R_PointToDist2(origin->x, origin->y, pos.x, pos.y);
tr.foreground = false;
tr.nametag = PLAYERTAG_NONE;
K_ObjectTracking(&tr.result, &pos, false);
if (tracking)
{
K_ObjectTracking(&tr.result, &pos, false);
targetList.push_back(tr);
}
targetList.push_back(tr);
if (!mobj->player)
{
continue;
}
tr.nametag = nametag;
if (tr.is_player_nametag_on_screen())
{
fixed_t headOffset = 36*mobj->scale;
if (stplyr->mo->eflags & MFE_VERTICALFLIP)
{
pos.z -= headOffset;
}
else
{
pos.z += headOffset;
}
K_ObjectTracking(&tr.result, &pos, false);
if (tr.result.onScreen == true)
{
targetList.push_back(tr);
}
}
}
// Sort by distance from camera. Further trackers get