WIP: splits

This commit is contained in:
Antonio Martinez 2025-08-06 19:51:36 -04:00
parent bf8511c495
commit a11acfaf0e
5 changed files with 151 additions and 22 deletions

View file

@ -350,6 +350,13 @@ typedef enum
khud_exp, khud_exp,
khud_exptimer, khud_exptimer,
// Splits
khud_splittime,
khud_splitwin,
khud_splittimer,
khud_splitskin,
khud_splitcolor,
NUMKARTHUD NUMKARTHUD
} karthudtype_t; } karthudtype_t;

View file

@ -118,7 +118,7 @@ size_t copy_fixed_buf(void* p, const void* s, size_t n)
static char demoname[MAX_WADPATH]; static char demoname[MAX_WADPATH];
static savebuffer_t demobuf = {0}; static savebuffer_t demobuf = {0};
static UINT8 *demotime_p, *demoinfo_p, *demoattack_p; static UINT8 *demotime_p, *demoinfo_p, *demoattack_p, *demosplits_p;
static UINT16 demoflags; static UINT16 demoflags;
boolean demosynced = true; // console warning message boolean demosynced = true; // console warning message
@ -2068,6 +2068,13 @@ void G_BeginRecording(void)
demoattack_p = demobuf.p; demoattack_p = demobuf.p;
WRITEUINT32(demobuf.p, INT32_MAX); WRITEUINT32(demobuf.p, INT32_MAX);
demosplits_p = demobuf.p;
for (i = 0; i < MAXSPLITS; i++)
{
WRITEUINT32(demobuf.p, INT32_MAX);
}
// Save netvar data // Save netvar data
CV_SaveDemoVars(&demobuf.p); CV_SaveDemoVars(&demobuf.p);
@ -2235,8 +2242,57 @@ void srb2::write_current_demo_end_marker()
void G_SetDemoAttackTiming(tic_t time) void G_SetDemoAttackTiming(tic_t time)
{ {
if (!demo.playback) if (demo.playback)
*(UINT32 *)demoattack_p = time; return;
*(UINT32 *)demoattack_p = time;
}
void G_SetDemoCheckpointTiming(player_t *player, tic_t time, UINT8 checkpoint)
{
if (demo.playback)
return;
if (checkpoint >= MAXSPLITS || checkpoint < 0)
return;
UINT32 *splits = (UINT32 *)demosplits_p;
splits[checkpoint] = time;
CONS_Printf("%d / %d\n", checkpoint, time);
demoghost *g;
tic_t lowest = INT32_MAX;
UINT32 lowestskin = ((skin_t*)player->mo->skin) - skins;
UINT32 lowestcolor = player->skincolor;
for (g = ghosts; g; g = g->next)
{
if (lowest > g->splits[checkpoint])
{
lowest = g->splits[checkpoint];
lowestskin = ((skin_t*)g->mo->skin)-skins;
lowestcolor = g->mo->color;
}
CONS_Printf("->%d\n", g->splits[checkpoint]);
}
if (lowest != INT32_MAX)
{
player->karthud[khud_splittimer] = 1;
player->karthud[khud_splitskin] = lowestskin;
player->karthud[khud_splitcolor] = lowestcolor;
if (lowest < time)
{
player->karthud[khud_splittime] = time - lowest;
player->karthud[khud_splitwin] = false;
}
else
{
player->karthud[khud_splittime] = lowest - time;
player->karthud[khud_splitwin] = true;
}
}
} }
void G_SetDemoTime(UINT32 ptime, UINT32 plap) void G_SetDemoTime(UINT32 ptime, UINT32 plap)
@ -2594,6 +2650,8 @@ void G_LoadDemoInfo(menudemo_t *pdemo, boolean allownonmultiplayer)
extrainfo_p = info.buffer + READUINT32(info.p); // The extra UINT32 read is for a blank 4 bytes? extrainfo_p = info.buffer + READUINT32(info.p); // The extra UINT32 read is for a blank 4 bytes?
info.p += 4; // attack start info.p += 4; // attack start
for (i = 0; i < MAXSPLITS; i++)
info.p += 4; // splits
// Pared down version of CV_LoadNetVars to find the kart speed // Pared down version of CV_LoadNetVars to find the kart speed
pdemo->kartspeed = KARTSPEED_NORMAL; // Default to normal speed pdemo->kartspeed = KARTSPEED_NORMAL; // Default to normal speed
@ -3509,7 +3567,13 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
} }
p += 4; // Extra data location reference p += 4; // Extra data location reference
UINT32 attackstart = READUINT32(p); tic_t attackstart = READUINT32(p);
UINT8 *splits = p;
for (i = 0; i < MAXSPLITS; i++)
{
p += 4;
}
// net var data // net var data
count = READUINT16(p); count = READUINT16(p);
@ -3602,6 +3666,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
gh->skinlist = skinlist; gh->skinlist = skinlist;
gh->attackstart = attackstart; gh->attackstart = attackstart;
std::memcpy(gh->splits, splits, sizeof(tic_t) * MAXSPLITS);
ghosts = gh; ghosts = gh;
@ -3755,6 +3820,8 @@ staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
p += 4; // Extrainfo location marker p += 4; // Extrainfo location marker
p += 4; // Attack start info p += 4; // Attack start info
for (i = 0; i < MAXSPLITS; i++)
p += 4; // splits
// Ehhhh don't need ghostversion here (?) so I'll reuse the var here // Ehhhh don't need ghostversion here (?) so I'll reuse the var here
ghostversion = READUINT16(p); ghostversion = READUINT16(p);

View file

@ -168,6 +168,8 @@ extern UINT8 demo_writerng;
#define DXD_PST_SPECTATING 0x02 #define DXD_PST_SPECTATING 0x02
#define DXD_PST_LEFT 0x03 #define DXD_PST_LEFT 0x03
#define MAXSPLITS (200)
boolean G_CompatLevel(UINT16 level); boolean G_CompatLevel(UINT16 level);
// Record/playback tics // Record/playback tics
@ -203,6 +205,7 @@ struct demoghost {
UINT16 version; UINT16 version;
UINT8 numskins; UINT8 numskins;
tic_t attackstart; tic_t attackstart;
tic_t splits[MAXSPLITS];
boolean done; boolean done;
democharlist_t *skinlist; democharlist_t *skinlist;
mobj_t oldmo, *mo; mobj_t oldmo, *mo;
@ -238,6 +241,7 @@ void G_SaveDemo(void);
void G_ResetDemoRecording(void); void G_ResetDemoRecording(void);
void G_SetDemoAttackTiming(tic_t time); void G_SetDemoAttackTiming(tic_t time);
void G_SetDemoCheckpointTiming(player_t *player, tic_t time, UINT8 checkpoint);
boolean G_CheckDemoTitleEntry(void); boolean G_CheckDemoTitleEntry(void);

View file

@ -525,7 +525,7 @@ void K_LoadKartHUDGraphics(void)
buffer[7] = '0'+((i) % 10); buffer[7] = '0'+((i) % 10);
HU_UpdatePatch(&kp_overdrive[0][i], "%s", buffer); HU_UpdatePatch(&kp_overdrive[0][i], "%s", buffer);
} }
sprintf(buffer, "bsOVRDxx"); sprintf(buffer, "bsOVRDxx");
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
@ -2000,7 +2000,7 @@ static void K_drawKartItem(void)
static void K_drawBackupItem(void) static void K_drawBackupItem(void)
{ {
bool tiny = r_splitscreen > 1; bool tiny = r_splitscreen > 1;
patch_t *localpatch[3] = { kp_nodraw, kp_nodraw, kp_nodraw }; patch_t *localpatch[3] = { kp_nodraw, kp_nodraw, kp_nodraw };
patch_t *localbg = (kp_itembg[2]); patch_t *localbg = (kp_itembg[2]);
patch_t *localinv = kp_invincibility[((leveltime % (6*3)) / 3) + 7 + tiny]; patch_t *localinv = kp_invincibility[((leveltime % (6*3)) / 3) + 7 + tiny];
INT32 fx = 0, fy = 0, fflags = 0, tx = 0, ty = 0; // final coords for hud and flags... INT32 fx = 0, fy = 0, fflags = 0, tx = 0, ty = 0; // final coords for hud and flags...
@ -3406,7 +3406,7 @@ static void K_drawKartDuelScores(void)
{ {
flags |= V_SNAPTOBOTTOM; flags |= V_SNAPTOBOTTOM;
flags &= ~V_SNAPTOTOP; flags &= ~V_SNAPTOTOP;
basey = BASEVIDHEIGHT - 40; basey = BASEVIDHEIGHT - 40;
} }
basex = BASEVIDWIDTH - 80; basex = BASEVIDWIDTH - 80;
} }
@ -3493,7 +3493,7 @@ static void K_drawKartDuelScores(void)
V_DrawScaledPatch(basex-barheight+foeheight, basey, flags, kp_duel_4over); V_DrawScaledPatch(basex-barheight+foeheight, basey, flags, kp_duel_4over);
else else
V_DrawScaledPatch(basex, basey-barheight+foeheight, flags, kp_duel_over); V_DrawScaledPatch(basex, basey-barheight+foeheight, flags, kp_duel_over);
if (!use4p) if (!use4p)
{ {
V_DrawScaledPatch(basex, basey, flags, kp_duel_foe); V_DrawScaledPatch(basex, basey, flags, kp_duel_foe);
@ -3512,7 +3512,7 @@ static void K_drawKartDuelScores(void)
} }
foenum.text("{}", foe->duelscore); foenum.text("{}", foe->duelscore);
younum.text("{}", stplyr->duelscore); younum.text("{}", stplyr->duelscore);
// minirankings shamelessly copypasted because i know that shit works already // minirankings shamelessly copypasted because i know that shit works already
// and SURELY we will never need to use this somewhere else, right? // and SURELY we will never need to use this somewhere else, right?
@ -3526,7 +3526,7 @@ static void K_drawKartDuelScores(void)
UINT8 drawme = draw ? (stplyr - players) : (foe - players); UINT8 drawme = draw ? (stplyr - players) : (foe - players);
UINT16 drawx = basex + (draw ? youx : foex); UINT16 drawx = basex + (draw ? youx : foex);
UINT16 drawy = basey + (draw ? youy : foey); UINT16 drawy = basey + (draw ? youy : foey);
if (!playeringame[drawme] || players[drawme].spectator) if (!playeringame[drawme] || players[drawme].spectator)
continue; continue;
@ -3790,8 +3790,8 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
if (R_GetViewNumber() == 1) if (R_GetViewNumber() == 1)
{ {
flags |= V_SNAPTOBOTTOM; flags |= V_SNAPTOBOTTOM;
flags &= ~V_SNAPTOTOP; flags &= ~V_SNAPTOTOP;
basey = 170; basey = 170;
} }
} }
} }
@ -3817,7 +3817,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
return; return;
using srb2::Draw; using srb2::Draw;
srb2::Draw::Font scorefont = Draw::Font::kTimer; srb2::Draw::Font scorefont = Draw::Font::kTimer;
if (totalscore > 99) if (totalscore > 99)
{ {
@ -3834,7 +3834,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
else else
{ {
scorefont = Draw::Font::kZVote; scorefont = Draw::Font::kZVote;
} }
} }
UINT32 youscore = stplyr->teamimportance; UINT32 youscore = stplyr->teamimportance;
@ -3870,7 +3870,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
if (teams_lastleveltime[vn] != leveltime) // Timing consistency if (teams_lastleveltime[vn] != leveltime) // Timing consistency
{ {
INT32 delta = abs(easedallyscore[vn] - allyscore); // how wrong is display score? INT32 delta = abs(easedallyscore[vn] - allyscore); // how wrong is display score?
if (scorechangecooldown[vn] == 0 && delta) if (scorechangecooldown[vn] == 0 && delta)
{ {
if (allyscore > easedallyscore[vn]) if (allyscore > easedallyscore[vn])
@ -3886,9 +3886,9 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
enemycolor = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_WHITE, GTC_CACHE); enemycolor = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_WHITE, GTC_CACHE);
} }
scorechangecooldown[vn] = TICRATE/delta; scorechangecooldown[vn] = TICRATE/delta;
} }
} }
if (!fromintermission) if (!fromintermission)
{ {
// replace scores with eased scores // replace scores with eased scores
@ -4009,7 +4009,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
if (totalscore > 99) if (totalscore > 99)
{ {
enemynum.text("{:03}", enemyscore); enemynum.text("{:03}", enemyscore);
allynum.text("{:03}", allyscore); allynum.text("{:03}", allyscore);
} }
else else
{ {
@ -5856,13 +5856,13 @@ INT32 K_GetMinimapSplitFlags(const boolean usingProgressBar)
#define ICON_DOT_RADIUS (10) #define ICON_DOT_RADIUS (10)
// modified pick from blondedradio/RadioRacers (but there are like 57 things we don't want in the commit) // modified pick from blondedradio/RadioRacers (but there are like 57 things we don't want in the commit)
// (so gogo gadget copypaste, thanks for a good feature and saving me work i was supposed to do anyway) // (so gogo gadget copypaste, thanks for a good feature and saving me work i was supposed to do anyway)
static void K_DrawKartUFOTimer(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags) static void K_DrawKartUFOTimer(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags)
{ {
fixed_t amnumxpos, amnumypos; fixed_t amnumxpos, amnumypos;
INT32 amxpos, amypos; INT32 amxpos, amypos;
if (exitcountdown || leveltime > g_battleufo.due || battleprisons) if (exitcountdown || leveltime > g_battleufo.due || battleprisons)
return; return;
tic_t raw = g_battleufo.due - leveltime; tic_t raw = g_battleufo.due - leveltime;
@ -5872,7 +5872,7 @@ static void K_DrawKartUFOTimer(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hud
{ {
flags |= (raw / (TICRATE/2) % 2) ? V_YELLOWMAP : 0; flags |= (raw / (TICRATE/2) % 2) ? V_YELLOWMAP : 0;
} }
if (countdown <= 10) if (countdown <= 10)
{ {
flags &= ~(V_HUDTRANS|V_HUDTRANSHALF); flags &= ~(V_HUDTRANS|V_HUDTRANSHALF);
@ -7758,9 +7758,48 @@ void K_drawKartHUD(void)
using srb2::Draw; using srb2::Draw;
Draw::TextElement text = Draw::TextElement().parse("<z> Restart"); Draw::TextElement text = Draw::TextElement().parse("<z> Restart");
Draw(BASEVIDWIDTH - 19, 2) Draw(BASEVIDWIDTH - 19, 2)
.flags(flags | V_YELLOWMAP) .flags(flags | V_ORANGEMAP)
.align(Draw::Align::kRight) .align(Draw::Align::kRight)
.text(text.string()); .text(text.string());
boolean debug_alwaysdraw = false;
if (stplyr->karthud[khud_splittimer] || debug_alwaysdraw)
{
tic_t split = stplyr->karthud[khud_splittime];
UINT32 skin = stplyr->karthud[khud_splitskin];
UINT32 color = stplyr->karthud[khud_splitcolor];
boolean ahead = stplyr->karthud[khud_splitwin];
// debug
if (!stplyr->karthud[khud_splittimer])
{
ahead = !!((leveltime/17)%2);
split = leveltime;
skin = stplyr->skin;
color = stplyr->skincolor;
}
UINT8 *skincolor = R_GetTranslationColormap(skin, static_cast<skincolornum_t>(color), GTC_CACHE);
UINT8 textcolor = ahead ? SKINCOLOR_SAPPHIRE : SKINCOLOR_KETCHUP;
Draw row = Draw(BASEVIDWIDTH/2, BASEVIDHEIGHT/4).align(Draw::Align::kCenter)
.font(Draw::Font::kThinTimer).flags(V_30TRANS);
// vibes offset
row.x(-32).colormap(skincolor).patch(R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap);
Draw::TextElement text = Draw::TextElement(
std::string(ahead ? "-" : "+") + "{:02}'{:02}\"{:02}",
G_TicsToMinutes(split, true),
G_TicsToSeconds(split),
G_TicsToCentiseconds(split)
);
// vibes offset TWO
row.colormap(textcolor).colorize(textcolor).x(8).text(text);
}
} }
else else
{ {

View file

@ -4422,6 +4422,11 @@ void K_CheckpointCrossAward(player_t *player)
if (gametype != GT_RACE) if (gametype != GT_RACE)
return; return;
if (!demo.playback && G_TimeAttackStart())
{
G_SetDemoCheckpointTiming(player, leveltime, player->gradingpointnum);
}
player->gradingfactor += K_GetGradingFactorAdjustment(player); player->gradingfactor += K_GetGradingFactorAdjustment(player);
player->gradingpointnum++; player->gradingpointnum++;
player->exp = K_GetEXP(player); player->exp = K_GetEXP(player);
@ -9039,6 +9044,13 @@ void K_KartPlayerHUDUpdate(player_t *player)
if (player->karthud[khud_trickcool]) if (player->karthud[khud_trickcool])
player->karthud[khud_trickcool]--; player->karthud[khud_trickcool]--;
if (player->karthud[khud_splittimer])
{
player->karthud[khud_splittimer]++;
if (player->karthud[khud_splittimer] > 2*TICRATE)
player->karthud[khud_splittimer] = 0;
}
if (player->positiondelay) if (player->positiondelay)
player->positiondelay--; player->positiondelay--;