Dial speedometer

HUDTRANS is kind of b0rked on software
This commit is contained in:
yamamama 2026-05-02 16:41:20 -04:00
parent 011147e39a
commit 6a3a78a002

View file

@ -88,6 +88,7 @@ static CV_PossibleValue_t speedo_cons_t[]= {
{0, "Default"},
{1, "Small"},
{2, "P-Meter"},
{3, "Dial"},
{0, NULL}
};
@ -242,6 +243,13 @@ patch_t *kp_itemtarget_far[2][2];
patch_t *kp_itemtarget_far_text[2];
patch_t *kp_itemtarget_near[2][8];
// dial speedometer
static patch_t *kp_dial = NULL;
static patch_t *kp_dialfinish = NULL;
static patch_t *kp_dialbase[4] = {NULL};
static patch_t *kp_speedpatchesdial[8] = {NULL};
static patch_t *kp_dialnum[20] = {NULL};
void K_RegisterKartHUDStuff(void)
{
K_ReloadHUDColorCvar();
@ -436,6 +444,41 @@ void K_LoadKartHUDGraphics(void)
// Speedometer Sticker Color
HU_UpdatePatch(&kp_speedometersticker[1], "SC_SMSTC");
// Dial speedometer
HU_UpdatePatch(&kp_dial, "K_DSDIAL");
kp_dial->pivot.x = kp_dial->width / 2;
kp_dial->pivot.y = kp_dial->height / 2;
kp_dial->alignflags |= PATCHALIGN_USEPIVOTS;
HU_UpdatePatch(&kp_dialfinish, "K_DILFIN");
HU_UpdatePatch(&kp_dialbase[0], "K_DSPBS1");
HU_UpdatePatch(&kp_dialbase[1], "K_DSPBS2");
HU_UpdatePatch(&kp_dialbase[2], "K_DSPBC1");
HU_UpdatePatch(&kp_dialbase[3], "K_DSPBC2");
HU_UpdatePatch(&kp_speedpatchesdial[0], "SP_DKMH");
HU_UpdatePatch(&kp_speedpatchesdial[1], "SP_DMPH");
HU_UpdatePatch(&kp_speedpatchesdial[2], "SP_DFRAC");
HU_UpdatePatch(&kp_speedpatchesdial[3], "SP_DPERC");
HU_UpdatePatch(&kp_speedpatchesdial[4], "SC_DKMH");
HU_UpdatePatch(&kp_speedpatchesdial[5], "SC_DMPH");
HU_UpdatePatch(&kp_speedpatchesdial[6], "SC_DFRAC");
HU_UpdatePatch(&kp_speedpatchesdial[7], "SC_DPERC");
sprintf(buffer, "K_DSPNMx");
for (i = 0; i < 10; i++)
{
buffer[7] = '0'+(i%10);
HU_UpdatePatch(&kp_dialnum[i], "%s", buffer);
}
sprintf(buffer, "K_DSPNCx");
for (i = 0; i < 10; i++)
{
buffer[7] = '0'+(i%10);
HU_UpdatePatch(&kp_dialnum[i+10], "%s", buffer);
}
// Driftgauge Stickers
HU_UpdatePatch(&kp_driftgauge[0], "K_DGAU0"); // Spee
HU_UpdatePatch(&kp_driftgauge[1], "K_DGAU1"); // Achii
@ -3047,7 +3090,7 @@ static void K_drawKartStatsnLives(void)
if ((cv_lives_xoffset.value == 0 && cv_lives_yoffset.value == 0) || split)
{
if ((cv_newspeedometer.value == 0 || cv_newspeedometer.value == 2) && !K_RingsActive() && !split)
if ((cv_newspeedometer.value == 0 || cv_newspeedometer.value == 2 || cv_newspeedometer.value == 3) && !K_RingsActive() && !split)
{
offsetx = 25;
offsety = 15;
@ -3161,33 +3204,188 @@ static void K_drawKartAccessibilityIcons(INT32 fx)
}
}
#ifdef ROTSPRITE
#define DIALSPDDIV 97090 // 1.48148; converts 200 to 135
#define MPHDIV 68283 // 1.04192; converts 141 to 135
static void K_DrawDialNum(INT32 x, INT32 y, boolean colorized, INT32 flags, INT32 num, INT32 digits, const UINT8 *colormap)
{
INT32 w = 0;
w = kp_dialnum[0]->width;
if (flags & V_NOSCALESTART)
w *= vid.dup;
if (num < 0)
num = -num;
// draw the number
do
{
x -= (w);
if (colorized)
V_DrawFixedPatch(x << FRACBITS, y << FRACBITS, FRACUNIT, flags, kp_dialnum[(num % 10) + 10], colormap);
else
V_DrawFixedPatch(x << FRACBITS, y << FRACBITS, FRACUNIT, flags, kp_dialnum[num % 10], colormap);
num /= 10;
} while (--digits);
}
static void K_DrawDialLaps(INT32 x, INT32 y, INT32 num, INT32 total, INT32 flags)
{
INT32 fx;
fx = x + ((num < 10) ? 0 : 6);
V_DrawRankNum(fx, y, flags, num, (num < 10) ? 1 : 2, NULL);
V_DrawScaledPatch(fx + 2, y, flags, frameslash);
V_DrawRankNum(fx + 13 + ((total < 10) ? 0 : 6), y, flags, total, (total < 10) ? 1 : 2, NULL);
}
static void K_DrawDialSpeedometer(fixed_t speed,
fixed_t divisor,
UINT16 labeln,
INT32 splitflags,
boolean battlemode,
boolean infoactive,
boolean colorized)
{
const UINT8* colormap = R_GetTranslationColormap(TC_DEFAULT, K_GetHudColor(), GTC_CACHE);
INT32 ringoffset = 0;
const UINT8 infoidx = (infoactive) ? 1 : 0;
const fixed_t spd = FixedDiv(speed, divisor);
const angle_t speedangle =
FixedAngle(((min(135 * FRACUNIT, spd) - (45 * FRACUNIT))));
if (K_RingsActive() == true)
{
ringoffset = -16;
}
if (colorized) // Colourized hud
{
V_DrawMappedPatch(
SPDM_X, SPDM_Y - 25 + ringoffset, (V_HUDTRANS | splitflags), kp_dialbase[infoidx + 2], colormap);
V_DrawMappedPatch(SPDM_X,
SPDM_Y + 14 + ringoffset,
V_HUDTRANS | splitflags,
kp_speedpatchesdial[labeln + 4],
colormap);
}
else
{
V_DrawScaledPatch(SPDM_X, SPDM_Y - 25 + ringoffset, (V_HUDTRANS | splitflags), kp_dialbase[infoidx]);
V_DrawScaledPatch(SPDM_X,
SPDM_Y + 14 + ringoffset,
V_HUDTRANS | splitflags,
kp_speedpatchesdial[labeln]);
}
K_DrawDialNum(SPDM_X + 10,
SPDM_Y + 9 + ringoffset,
colorized,
V_HUDTRANS | splitflags,
speed / FRACUNIT,
3,
colormap);
// gotta center the dial manually
V_DrawRotatedPatch((SPDM_X - 19) << FRACBITS,
(SPDM_Y - 1 + ringoffset) << FRACBITS,
speedangle,
FRACUNIT,
FRACUNIT,
(V_HUDTRANS | splitflags),
kp_dial,
colormap);
if (!infoactive)
{
// no need to draw info if we're not supposed to
return;
}
// draw the info
if (battlemode)
{
if (stplyr->kartstuff[k_bumper] <= 0)
{
V_DrawMappedPatch(
SPDM_X + 28, SPDM_Y + 12 + ringoffset, V_HUDTRANS | splitflags, kp_splitkarmabomb, colormap);
K_DrawDialLaps(SPDM_X + 46,
SPDM_Y + ringoffset + 13,
stplyr->kartstuff[k_comebackpoints],
2,
V_HUDTRANS | splitflags);
}
else // the above doesn't need to account for weird stuff since the max amount of karma
// necessary is always 2 ^^^^
{
V_DrawMappedPatch(
SPDM_X + 28, SPDM_Y + 12, V_HUDTRANS | splitflags, kp_rankbumper, colormap);
K_DrawDialLaps(SPDM_X + 46,
SPDM_Y + ringoffset + 13,
stplyr->kartstuff[k_bumper],
cv_kartbumpers.value,
V_HUDTRANS | splitflags);
}
}
else
{
V_DrawScaledPatch(SPDM_X + 28, SPDM_Y + 12 + ringoffset, V_HUDTRANS | splitflags, kp_splitlapflag);
if (stplyr->exiting)
V_DrawScaledPatch(SPDM_X + 39, SPDM_Y + 29 + ringoffset, V_HUDTRANS | splitflags, kp_dialfinish);
else
K_DrawDialLaps(SPDM_X + 46,
SPDM_Y + ringoffset + 13,
stplyr->laps,
numlaps,
V_HUDTRANS | splitflags);
}
}
#endif
static void K_drawKartSpeedometer(void)
{
static fixed_t convSpeed;
static fixed_t convSpeed[2] = {0};
UINT8 labeln = 0;
UINT8 numbers[3];
INT32 splitflags = V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_SPLITSCREEN;
INT32 battleoffset = 0;
INT32 ringoffset = 0;
INT32 oldringoffset = 0;
#ifdef ROTSPRITE
fixed_t dial_divisor = DIALSPDDIV;
#endif
switch (cv_kartspeedometer.value)
{
case 1: // Kilometers
convSpeed = FixedDiv(FixedMul(stplyr->speed, 142371), mapobjectscale) / FRACUNIT; // 2.172409058
convSpeed[0] = FixedDiv(FixedMul(stplyr->speed, 142371), mapobjectscale); // 2.172409058
convSpeed[1] = convSpeed[0] / FRACUNIT;
labeln = 0;
break;
case 2: // Miles
convSpeed = FixedDiv(FixedMul(stplyr->speed, 88465), mapobjectscale) / FRACUNIT; // 1.349868774
convSpeed[0] = FixedDiv(FixedMul(stplyr->speed, 88465), mapobjectscale); // 1.349868774
convSpeed[1] = convSpeed[0] / FRACUNIT;
labeln = 1;
break;
case 3: // Fracunits
convSpeed = FixedDiv(stplyr->speed, mapobjectscale) / FRACUNIT; // 1.0. duh.
convSpeed[0] = FixedDiv(stplyr->speed, mapobjectscale); // 1.0. duh.
convSpeed[1] = convSpeed[0] / FRACUNIT;
labeln = 2;
break;
case 4: // Sonic Drift 2 style percentage
if (stplyr->mo)
convSpeed = (FixedDiv(stplyr->speed, FixedMul(K_GetKartSpeed(stplyr, false, false), K_PlayerBaseFriction(stplyr, ORIG_FRICTION)))*100)>>FRACBITS;
{
convSpeed[0] = (FixedDiv(stplyr->speed, FixedMul(K_GetKartSpeed(stplyr, false, false), K_PlayerBaseFriction(stplyr, ORIG_FRICTION)))*100);
convSpeed[1] = convSpeed[0] >> FRACBITS;
}
labeln = 3;
break;
default:
@ -3196,8 +3394,11 @@ static void K_drawKartSpeedometer(void)
// Don't overflow
// (negative speed IS really high speed :V)
if (convSpeed > 999 || convSpeed < 0)
convSpeed = 999;
if (convSpeed[1] > 999 || convSpeed[1] < 0)
{
convSpeed[1] = 999;
convSpeed[0] = convSpeed[1] * FRACUNIT;
}
if (cv_speed_xoffset.value == 0 && cv_speed_yoffset.value == 0)
{
@ -3215,16 +3416,16 @@ static void K_drawKartSpeedometer(void)
{
switch (cv_kartspeedometer.value) {
case 1:
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%3d km/h", convSpeed));
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%3d km/h", convSpeed[1]));
break;
case 2:
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%3d mph", convSpeed));
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%3d mph", convSpeed[1]));
break;
case 3:
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%3d fu/t", convSpeed));
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%3d fu/t", convSpeed[1]));
break;
case 4:
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%4d %%", convSpeed));
V_DrawKartString(SPDM_X + oldringoffset, SPDM_Y-18 + battleoffset + ringoffset, V_HUDTRANS|splitflags, va("%4d %%", convSpeed[1]));
break;
default:
break;
@ -3232,9 +3433,9 @@ static void K_drawKartSpeedometer(void)
}
else if (cv_newspeedometer.value == 1)
{
numbers[0] = ((convSpeed / 100) % 10);
numbers[1] = ((convSpeed / 10) % 10);
numbers[2] = (convSpeed % 10);
numbers[0] = ((convSpeed[1] / 100) % 10);
numbers[1] = ((convSpeed[1] / 10) % 10);
numbers[2] = (convSpeed[1] % 10);
if (!K_UseColorHud())
{
@ -3278,10 +3479,27 @@ static void K_drawKartSpeedometer(void)
V_DrawScaledPatch(SPDM_X, SPDM_Y-yoffset + battleoffset + ringoffset, V_HUDTRANS|splitflags, (!K_RingsActive() ? kp_kartzspeedo : kp_kartzspeedo_smol)[spdpatch]);
}
#ifdef ROTSPRITE
else if (cv_newspeedometer.value == 3)
{
K_DrawDialSpeedometer(convSpeed[0],
dial_divisor,
labeln,
splitflags,
(boolean)((gametypes[gametype]->rules & GTR_BUMPERS) == GTR_BUMPERS),
(LUA_HudEnabled(hud_gametypeinfo)),
(K_UseColorHud()));
}
#endif
K_drawKartAccessibilityIcons((cv_newspeedometer.value == 0 || cv_newspeedometer.value == 2) ? 50 : 56);
}
#ifdef ROTSPRITE
#undef DIALSPDDIV
#undef MPHDIV
#endif
static void K_drawRingMeter(void)
{
UINT8 rn[2];
@ -6265,10 +6483,33 @@ static void K_SlipstreamIndicator(boolean tiny)
V_DrawThinString(fx - V_StringWidth(str, flags)/2, fy, flags, str);
}
// determines if gametype info (laps/bumpers) should be hidden
static boolean K_DisableGametypeInfo(void)
{
if (!LUA_HudEnabled(hud_gametypeinfo))
{
return true;
}
#ifdef ROTSPRITE
if (r_splitscreen || (!cv_kartspeedometer.value))
{
// don't need to run checks if we're in splitscreen, or not using the speedometer
return false;
}
if (cv_newspeedometer.value == 3)
return true;
#endif
return false;
}
void K_drawKartHUD(void)
{
boolean islonesome = false;
boolean battlefullscreen = false;
boolean gameinfovisible = false;
UINT8 viewnum = R_GetViewNumber();
boolean freecam = camera[viewnum].freecam; //disable some hud elements w/ freecam
UINT8 i;
@ -6376,6 +6617,9 @@ void K_drawKartHUD(void)
if (!stplyr->spectator && !freecam) // Bottom of the screen elements, don't need in spectate mode
{
// get gametype info visibility ahead of time
gameinfovisible = (!K_DisableGametypeInfo());
if (demo.title) // Draw title logo instead in demo.titles
{
INT32 x = (BASEVIDWIDTH - 32), y = 128, snapflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT;
@ -6412,12 +6656,15 @@ void K_drawKartHUD(void)
{
if (gametypes[gametype]->rules & GTR_CIRCUIT)
{
K_drawKartLaps();
if (gameinfovisible)
K_drawKartLaps();
K_drawKartStatsnLives();
}
else if (gametypes[gametype]->rules & GTR_BUMPERS)
{
K_drawKartBumpersOrKarma();
if (gameinfovisible)
K_drawKartBumpersOrKarma();
}
}