Merge pull request '[FEAT] Hardcoded Restat' (#211) from hardcode-restat into next

Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/211
This commit is contained in:
minenice55 2026-01-24 21:10:48 +01:00
commit 90fdec38dc
5 changed files with 243 additions and 5 deletions

View file

@ -233,6 +233,11 @@ static void Command_Teamchange2_f(void);
static void Command_Teamchange3_f(void); static void Command_Teamchange3_f(void);
static void Command_Teamchange4_f(void); static void Command_Teamchange4_f(void);
static void Command_Restat(void);
static void Command_Restat2(void);
static void Command_Restat3(void);
static void Command_Restat4(void);
static void Command_ServerTeamChange_f(void); static void Command_ServerTeamChange_f(void);
static void Command_Clearscores_f(void); static void Command_Clearscores_f(void);
@ -1440,6 +1445,117 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_connectawaittime); CV_RegisterVar(&cv_connectawaittime);
CV_RegisterVar(&cv_serverinfoscreen); CV_RegisterVar(&cv_serverinfoscreen);
// player restat
CV_RegisterVar(&cv_allowrestat);
CV_RegisterVar(&cv_notifyrestat);
COM_AddCommand("restat", Command_Restat);
COM_AddCommand("restat2", Command_Restat2);
COM_AddCommand("restat3", Command_Restat3);
COM_AddCommand("restat4", Command_Restat4);
}
static void RestatForPlayer(UINT32 ssplayer)
{
player_t* player = &players[g_localplayers[ssplayer]];
int speed;
int weight;
if (!cv_allowrestat.value)
{
CONS_Printf("This command has been disabled by the server host.\n");
return;
}
if (COM_Argc() > 2)
{
if (sscanf(COM_Argv(1), " %d", &speed) == 0 ||
sscanf(COM_Argv(2), " %d", &weight) == 0)
{
CONS_Printf("Expected two numbers (<speed> <weight>) in the range of 1-9.\n");
return;
}
// range checking
if (speed < 1 || speed > 9 ||
weight < 1 || weight > 9)
{
CONS_Printf("Expected two numbers (<speed> <weight>) in the range of 1-9.\n");
return;
}
// should be good now 🥲
player->kartspeedrestat = speed;
player->kartweightrestat = weight;
player->randomrestat = false;
CONS_Printf("You will be %d speed, %d weight for the next race.\n", speed, weight);
CONS_Printf("Use \"restat off\" to return to your skin's default stats.\n");
WeaponPref_Send(ssplayer);
return;
}
else if (COM_Argc() > 1)
{
if (fasticmp(COM_Argv(1), "random"))
{
player->randomrestat = !player->randomrestat;
if (player->randomrestat)
{
CONS_Printf("Random restat is now enabled.\n");
}
else
{
CONS_Printf("Random restat is now disabled.\n");
}
WeaponPref_Send(ssplayer);
return;
}
else if (fasticmp(COM_Argv(1), "off"))
{
player->kartspeedrestat = 0;
player->kartweightrestat = 0;
player->randomrestat = false;
WeaponPref_Send(ssplayer);
CONS_Printf("Now using skin default stats.\n");
return;
}
else
{
CONS_Printf(
"Usage: \"restat<playernum> <speed> <weight>\"\n"
"Alternatively: \"restat<playernum> random\" to toggle the use of random stats each round.\n"
"or \"restat<playernum> off\" to use your skin's default stats.\n");
}
}
else
{
CONS_Printf(
"Usage: \"restat<playernum> <speed> <weight>\"\n"
"Alternatively: \"restat<playernum> random\" to use random stats each round.\n"
"or \"restat<playernum> off\" to use your skin's default stats.\n");
}
}
static void Command_Restat(void)
{
RestatForPlayer(0);
}
static void Command_Restat2(void)
{
RestatForPlayer(1);
}
static void Command_Restat3(void)
{
RestatForPlayer(2);
}
static void Command_Restat4(void)
{
RestatForPlayer(3);
} }
/** /**
@ -2230,11 +2346,13 @@ enum {
WP_KICKSTARTACCEL = 1<<0, WP_KICKSTARTACCEL = 1<<0,
WP_SHRINKME = 1<<1, WP_SHRINKME = 1<<1,
WP_FLIPCAM = 1<<2, WP_FLIPCAM = 1<<2,
WP_LEGACYJITTER = 1<<3 WP_LEGACYJITTER = 1<<3,
WP_RANDOMRESTAT = 1<<4
}; };
void WeaponPref_Send(UINT8 ssplayer) void WeaponPref_Send(UINT8 ssplayer)
{ {
player_t* player = &players[g_localplayers[ssplayer]];
UINT8 prefs = 0; UINT8 prefs = 0;
if (cv_kickstartaccel[ssplayer].value) if (cv_kickstartaccel[ssplayer].value)
@ -2248,10 +2366,15 @@ void WeaponPref_Send(UINT8 ssplayer)
if (!(cv_jitterlegacy[ssplayer].value)) if (!(cv_jitterlegacy[ssplayer].value))
prefs |= WP_LEGACYJITTER; prefs |= WP_LEGACYJITTER;
if (player->randomrestat)
prefs |= WP_RANDOMRESTAT;
UINT8 buf[2]; UINT8 buf[4];
buf[0] = prefs; buf[0] = prefs;
buf[1] = cv_mindelay.value; buf[1] = cv_mindelay.value;
buf[2] = player->kartspeedrestat;
buf[3] = player->kartweightrestat;
SendNetXCmdForPlayer(ssplayer, XD_WEAPONPREF, buf, sizeof buf); SendNetXCmdForPlayer(ssplayer, XD_WEAPONPREF, buf, sizeof buf);
} }
@ -2274,6 +2397,9 @@ void WeaponPref_Save(UINT8 **cp, INT32 playernum)
if (player->jitterlegacy) if (player->jitterlegacy)
prefs |= WP_LEGACYJITTER; prefs |= WP_LEGACYJITTER;
if (player->randomrestat)
prefs |= WP_RANDOMRESTAT;
WRITEUINT8(*cp, prefs); WRITEUINT8(*cp, prefs);
} }
@ -2285,6 +2411,7 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum)
player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_FLIPCAM); player->pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME|PF_FLIPCAM);
player->jitterlegacy = false; player->jitterlegacy = false;
player->randomrestat = false;
if (prefs & WP_KICKSTARTACCEL) if (prefs & WP_KICKSTARTACCEL)
player->pflags |= PF_KICKSTARTACCEL; player->pflags |= PF_KICKSTARTACCEL;
@ -2298,6 +2425,9 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum)
if (prefs & WP_LEGACYJITTER) if (prefs & WP_LEGACYJITTER)
player->jitterlegacy = true; player->jitterlegacy = true;
if (prefs & WP_RANDOMRESTAT)
player->randomrestat = true;
if (leveltime < 2) if (leveltime < 2)
{ {
// BAD HACK: No other place I tried to slot this in // BAD HACK: No other place I tried to slot this in
@ -2309,14 +2439,28 @@ void WeaponPref_Parse(UINT8 **cp, INT32 playernum)
static void Got_WeaponPref(UINT8 **cp,INT32 playernum) static void Got_WeaponPref(UINT8 **cp,INT32 playernum)
{ {
player_t *player = &players[playernum];
WeaponPref_Parse(cp, playernum); WeaponPref_Parse(cp, playernum);
UINT8 mindelay = READUINT8(*cp); UINT8 mindelay = READUINT8(*cp);
if (server) if (server)
{ {
for (UINT8 i = 0; i < G_LocalSplitscreenPartySize(playernum); ++i) for (UINT8 i = 0; i < G_LocalSplitscreenPartySize(playernum); ++i)
playerdelaytable[G_LocalSplitscreenPartyMember(playernum, i)] = mindelay; playerdelaytable[G_LocalSplitscreenPartyMember(playernum, i)] = mindelay;
} }
UINT8 kartspeedrestat = READUINT8(*cp);
UINT8 kartweightrestat = READUINT8(*cp);
if (kartspeedrestat < 0 || kartspeedrestat > 9 ||
kartweightrestat < 0 || kartweightrestat > 9)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal restat values received from %s\n"), player_names[playernum]);
if (server)
SendKick(playernum, KICK_MSG_CON_FAIL);
return;
}
player->kartspeedrestat = kartspeedrestat;
player->kartweightrestat = kartweightrestat;
// SEE ALSO g_demo.c // SEE ALSO g_demo.c
demo_extradata[playernum] |= DXD_WEAPONPREF; demo_extradata[playernum] |= DXD_WEAPONPREF;

View file

@ -504,6 +504,10 @@ struct player_t
UINT8 kartspeed; // Kart speed stat between 1 and 9 UINT8 kartspeed; // Kart speed stat between 1 and 9
UINT8 kartweight; // Kart weight stat between 1 and 9 UINT8 kartweight; // Kart weight stat between 1 and 9
UINT8 kartspeedrestat; // Player's wanted kart speed from restat
UINT8 kartweightrestat; // Player's wanted kart weight from restat
boolean randomrestat; // Randomly set the restat values of the player every game
INT32 followerskin; // Kart: This player's follower "skin" INT32 followerskin; // Kart: This player's follower "skin"
boolean followerready; // Kart: Used to know when we can have a follower or not. (This is set on the first NameAndColor follower update) boolean followerready; // Kart: Used to know when we can have a follower or not. (This is set on the first NameAndColor follower update)
UINT16 followercolor; // Kart: Used to store the follower colour the player wishes to use UINT16 followercolor; // Kart: Used to store the follower colour the player wishes to use

View file

@ -493,6 +493,10 @@ consvar_t cv_deadzonestyle[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("deadzonestyle4", "Kart", CV_SAVE, deadzonestyle_cons_t, NULL) CVAR_INIT ("deadzonestyle4", "Kart", CV_SAVE, deadzonestyle_cons_t, NULL)
}; };
// allows players to use restat (server toggle)
consvar_t cv_allowrestat = CVAR_INIT ("allowrestat", "Yes", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_notifyrestat = CVAR_INIT ("notifyrestat", "Yes", CV_NETVAR, CV_YesNo, NULL);
// now automatically allocated in D_RegisterClientCommands // now automatically allocated in D_RegisterClientCommands
// so that it doesn't have to be updated depending on the value of MAXPLAYERS // so that it doesn't have to be updated depending on the value of MAXPLAYERS
char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
@ -2736,6 +2740,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
UINT8 kartspeed; UINT8 kartspeed;
UINT8 kartweight; UINT8 kartweight;
UINT8 kartspeedrestat;
UINT8 kartweightrestat;
boolean randomrestat;
boolean notifyrestat;
boolean followerready; boolean followerready;
INT32 followerskin; INT32 followerskin;
@ -2833,6 +2841,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
kartspeed = players[player].kartspeed; kartspeed = players[player].kartspeed;
kartweight = players[player].kartweight; kartweight = players[player].kartweight;
kartspeedrestat = players[player].kartspeedrestat;
kartweightrestat = players[player].kartweightrestat;
randomrestat = players[player].randomrestat;
followerready = players[player].followerready; followerready = players[player].followerready;
followercolor = players[player].followercolor; followercolor = players[player].followercolor;
followerskin = players[player].followerskin; followerskin = players[player].followerskin;
@ -2858,7 +2870,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_FLIPCAM)); pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_FLIPCAM));
// SRB2kart // SRB2kart
if (betweenmaps || leveltime <= starttime || spectator == true) if (betweenmaps || leveltime <= starttime || spectator == true || players[player].jointime == 0)
{ {
itemroulette = 0; itemroulette = 0;
previtemroulette = 0; previtemroulette = 0;
@ -2884,7 +2896,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
exiting = 0; exiting = 0;
khudfinish = 0; khudfinish = 0;
khudcardanimation = 0; khudcardanimation = 0;
starpostx =0; starpostx = 0;
starposty = 0; starposty = 0;
starpostz = 0; starpostz = 0;
starpostangle = 0; starpostangle = 0;
@ -2898,6 +2910,42 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
{ {
laptime[i] = 0; laptime[i] = 0;
} }
// might cause issues with weponpref sync?
if (!cv_allowrestat.value)
{
kartspeedrestat = 0;
kartweightrestat = 0;
randomrestat = false;
}
if (randomrestat)
{
kartspeedrestat = P_RandomRange(1, 9);
kartweightrestat = P_RandomRange(1, 9);
}
if (kartspeedrestat != 0 && kartweightrestat != 0)
{
kartspeed = kartspeedrestat;
kartweight = kartweightrestat;
notifyrestat = (
randomrestat ||
kartspeedrestat != players[player].kartspeed ||
kartweightrestat != players[player].kartweight
) && cv_notifyrestat.value;
}
else
{
kartspeed = skins[players[player].skin].kartspeed;
kartweight = skins[players[player].skin].kartweight;
notifyrestat = (
players[player].kartspeed != skins[players[player].skin].kartspeed ||
players[player].kartweight != skins[players[player].skin].kartweight
) && cv_notifyrestat.value;
}
} }
else else
{ {
@ -2990,6 +3038,38 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
else else
{ {
follower = NULL; follower = NULL;
if (players[player].jointime > 0)
{
if (kartspeedrestat != 0 && kartweightrestat != 0)
{
if (playeringame[player] && notifyrestat)
{
if ((splitscreen && player == consoleplayer) || player != consoleplayer)
{
HU_AddChatText(va("%s is now %d speed, %d weight.", player_names[player], kartspeed, kartweight), true);
}
else
{
HU_AddChatText(va("You are now %d speed, %d weight.", kartspeed, kartweight), true);
}
}
}
else
{
if (playeringame[player] && notifyrestat)
{
if ((splitscreen && player == consoleplayer) || player != consoleplayer)
{
HU_AddChatText(va("%s is now using their skin's default stats.", player_names[player]), true);
}
else
{
HU_AddChatText(va("You are now using your skin's default stats."), true);
}
}
}
}
} }
spectatorreentry = (betweenmaps ? 0 : players[player].spectatorreentry); spectatorreentry = (betweenmaps ? 0 : players[player].spectatorreentry);
@ -3021,6 +3101,10 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->voice_id = voice; p->voice_id = voice;
p->kartspeed = kartspeed; p->kartspeed = kartspeed;
p->kartweight = kartweight; p->kartweight = kartweight;
p->kartspeedrestat = kartspeedrestat;
p->kartweightrestat = kartweightrestat;
p->randomrestat = randomrestat;
// //
p->charflags = charflags; p->charflags = charflags;
memcpy(players[player].availabilities, availabilities, sizeof(availabilities)); memcpy(players[player].availabilities, availabilities, sizeof(availabilities));

View file

@ -96,6 +96,8 @@ extern consvar_t cv_resetspecialmusic;
extern consvar_t cv_resume; extern consvar_t cv_resume;
extern consvar_t cv_allowrestat, cv_notifyrestat;
void weaponPrefChange(void); void weaponPrefChange(void);
void weaponPrefChange2(void); void weaponPrefChange2(void);
void weaponPrefChange3(void); void weaponPrefChange3(void);

View file

@ -555,6 +555,10 @@ static void P_NetSyncPlayers(savebuffer_t *save)
SYNC(players[i].kartspeed); SYNC(players[i].kartspeed);
SYNC(players[i].kartweight); SYNC(players[i].kartweight);
SYNC(players[i].kartspeedrestat);
SYNC(players[i].kartweightrestat);
SYNC(players[i].randomrestat);
for (j = 0; j < MAXPREDICTTICS; j++) for (j = 0; j < MAXPREDICTTICS; j++)
{ {
SYNC(players[i].lturn_max[j]); SYNC(players[i].lturn_max[j]);