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_exptimer,
// Splits
khud_splittime,
khud_splitwin,
khud_splittimer,
khud_splitskin,
khud_splitcolor,
NUMKARTHUD
} 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 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;
boolean demosynced = true; // console warning message
@ -2068,6 +2068,13 @@ void G_BeginRecording(void)
demoattack_p = demobuf.p;
WRITEUINT32(demobuf.p, INT32_MAX);
demosplits_p = demobuf.p;
for (i = 0; i < MAXSPLITS; i++)
{
WRITEUINT32(demobuf.p, INT32_MAX);
}
// Save netvar data
CV_SaveDemoVars(&demobuf.p);
@ -2235,8 +2242,57 @@ void srb2::write_current_demo_end_marker()
void G_SetDemoAttackTiming(tic_t time)
{
if (!demo.playback)
*(UINT32 *)demoattack_p = time;
if (demo.playback)
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)
@ -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?
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
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
UINT32 attackstart = READUINT32(p);
tic_t attackstart = READUINT32(p);
UINT8 *splits = p;
for (i = 0; i < MAXSPLITS; i++)
{
p += 4;
}
// net var data
count = READUINT16(p);
@ -3602,6 +3666,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
gh->skinlist = skinlist;
gh->attackstart = attackstart;
std::memcpy(gh->splits, splits, sizeof(tic_t) * MAXSPLITS);
ghosts = gh;
@ -3755,6 +3820,8 @@ staffbrief_t *G_GetStaffGhostBrief(UINT8 *buffer)
p += 4; // Extrainfo location marker
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
ghostversion = READUINT16(p);

View file

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

View file

@ -525,7 +525,7 @@ void K_LoadKartHUDGraphics(void)
buffer[7] = '0'+((i) % 10);
HU_UpdatePatch(&kp_overdrive[0][i], "%s", buffer);
}
sprintf(buffer, "bsOVRDxx");
for (i = 0; i < 32; i++)
{
@ -2000,7 +2000,7 @@ static void K_drawKartItem(void)
static void K_drawBackupItem(void)
{
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 *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...
@ -3406,7 +3406,7 @@ static void K_drawKartDuelScores(void)
{
flags |= V_SNAPTOBOTTOM;
flags &= ~V_SNAPTOTOP;
basey = BASEVIDHEIGHT - 40;
basey = BASEVIDHEIGHT - 40;
}
basex = BASEVIDWIDTH - 80;
}
@ -3493,7 +3493,7 @@ static void K_drawKartDuelScores(void)
V_DrawScaledPatch(basex-barheight+foeheight, basey, flags, kp_duel_4over);
else
V_DrawScaledPatch(basex, basey-barheight+foeheight, flags, kp_duel_over);
if (!use4p)
{
V_DrawScaledPatch(basex, basey, flags, kp_duel_foe);
@ -3512,7 +3512,7 @@ static void K_drawKartDuelScores(void)
}
foenum.text("{}", foe->duelscore);
younum.text("{}", stplyr->duelscore);
younum.text("{}", stplyr->duelscore);
// minirankings shamelessly copypasted because i know that shit works already
// 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);
UINT16 drawx = basex + (draw ? youx : foex);
UINT16 drawy = basey + (draw ? youy : foey);
if (!playeringame[drawme] || players[drawme].spectator)
continue;
@ -3790,8 +3790,8 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
if (R_GetViewNumber() == 1)
{
flags |= V_SNAPTOBOTTOM;
flags &= ~V_SNAPTOTOP;
basey = 170;
flags &= ~V_SNAPTOTOP;
basey = 170;
}
}
}
@ -3817,7 +3817,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
return;
using srb2::Draw;
srb2::Draw::Font scorefont = Draw::Font::kTimer;
srb2::Draw::Font scorefont = Draw::Font::kTimer;
if (totalscore > 99)
{
@ -3834,7 +3834,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
else
{
scorefont = Draw::Font::kZVote;
}
}
}
UINT32 youscore = stplyr->teamimportance;
@ -3870,7 +3870,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
if (teams_lastleveltime[vn] != leveltime) // Timing consistency
{
INT32 delta = abs(easedallyscore[vn] - allyscore); // how wrong is display score?
if (scorechangecooldown[vn] == 0 && delta)
{
if (allyscore > easedallyscore[vn])
@ -3886,9 +3886,9 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
enemycolor = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_WHITE, GTC_CACHE);
}
scorechangecooldown[vn] = TICRATE/delta;
}
}
}
if (!fromintermission)
{
// replace scores with eased scores
@ -4009,7 +4009,7 @@ void K_drawKartTeamScores(boolean fromintermission, INT32 interoffset)
if (totalscore > 99)
{
enemynum.text("{:03}", enemyscore);
allynum.text("{:03}", allyscore);
allynum.text("{:03}", allyscore);
}
else
{
@ -5856,13 +5856,13 @@ INT32 K_GetMinimapSplitFlags(const boolean usingProgressBar)
#define ICON_DOT_RADIUS (10)
// 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)
{
fixed_t amnumxpos, amnumypos;
INT32 amxpos, amypos;
if (exitcountdown || leveltime > g_battleufo.due || battleprisons)
if (exitcountdown || leveltime > g_battleufo.due || battleprisons)
return;
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;
}
if (countdown <= 10)
{
flags &= ~(V_HUDTRANS|V_HUDTRANSHALF);
@ -7758,9 +7758,48 @@ void K_drawKartHUD(void)
using srb2::Draw;
Draw::TextElement text = Draw::TextElement().parse("<z> Restart");
Draw(BASEVIDWIDTH - 19, 2)
.flags(flags | V_YELLOWMAP)
.flags(flags | V_ORANGEMAP)
.align(Draw::Align::kRight)
.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
{

View file

@ -4422,6 +4422,11 @@ void K_CheckpointCrossAward(player_t *player)
if (gametype != GT_RACE)
return;
if (!demo.playback && G_TimeAttackStart())
{
G_SetDemoCheckpointTiming(player, leveltime, player->gradingpointnum);
}
player->gradingfactor += K_GetGradingFactorAdjustment(player);
player->gradingpointnum++;
player->exp = K_GetEXP(player);
@ -9039,6 +9044,13 @@ void K_KartPlayerHUDUpdate(player_t *player)
if (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)
player->positiondelay--;