From 04dd587ef4c10be1e8d1ba1decd83f8441dacb39 Mon Sep 17 00:00:00 2001 From: Anonimus Date: Fri, 12 Sep 2025 14:46:45 -0400 Subject: [PATCH] Add legacy drifting for RR characters Imitates V1 drifts using baked offsets; perfectly netsafe --- src/d_netcmd.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++- src/d_netcmd.h | 1 + src/d_player.h | 3 +++ src/g_game.c | 4 +++ src/k_kart.c | 26 ++++++++++++++------ src/p_saveg.c | 8 +++++- src/p_user.c | 10 ++++++++ src/r_things.cpp | 3 ++- 8 files changed, 108 insertions(+), 10 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 651fc0b0f..8c8db8473 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -131,6 +131,11 @@ static void Skin2_OnChange(void); static void Skin3_OnChange(void); static void Skin4_OnChange(void); +static void Jitter_OnChange(void); +static void Jitter2_OnChange(void); +static void Jitter3_OnChange(void); +static void Jitter4_OnChange(void); + static void Follower_OnChange(void); static void Follower2_OnChange(void); static void Follower3_OnChange(void); @@ -272,6 +277,9 @@ static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"} static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; +// Jon's lament +static CV_PossibleValue_t driftjitter_cons_t[] = {{0, "SRB2Kart"}, {1, "Ring Racers"}, {0, NULL}}; + static consvar_t cv_dummyconsvar = CVAR_INIT ("dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP, CV_OnOff, DummyConsvar_OnChange); consvar_t cv_restrictskinchange = CVAR_INIT ("restrictskinchange", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL); @@ -375,6 +383,14 @@ consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = { //Alam: Dummy for save }; #endif +// Drift jitter settings. +consvar_t cv_jitterlegacy[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("driftjitter", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, Jitter_OnChange), + CVAR_INIT ("driftjitter2", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, Jitter2_OnChange), + CVAR_INIT ("driftjitter3", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, Jitter3_OnChange), + CVAR_INIT ("driftjitter4", "Ring Racers", CV_SAVE|CV_CALL|CV_NOINIT, driftjitter_cons_t, Jitter4_OnChange) +}; + // SRB2kart consvar_t cv_sneaker = CVAR_INIT ("sneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); consvar_t cv_rocketsneaker = CVAR_INIT ("rocketsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL); @@ -1115,6 +1131,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_skin[i]); CV_RegisterVar(&cv_follower[i]); CV_RegisterVar(&cv_followercolor[i]); + CV_RegisterVar(&cv_jitterlegacy[i]); } // preferred number of players @@ -1711,7 +1728,8 @@ static void SendNameAndColor(UINT8 n) && cv_playercolor[n].value == player->skincolor && !strcmp(cv_skin[n].string, skins[player->skin].name) && cv_follower[n].value == player->followerskin - && cv_followercolor[n].value == player->followercolor) + && cv_followercolor[n].value == player->followercolor + && ((boolean)((!cv_jitterlegacy[n].value) & 1)) == player->jitterlegacy) return; player->availabilities = R_GetSkinAvailabilities(); @@ -1738,6 +1756,10 @@ static void SendNameAndColor(UINT8 n) player->followercolor = cv_followercolor[n].value; + // Player jittering. Can't netsynch for hopefully obvious reasons. + // Inverted to prevent tedium. + player->jitterlegacy = (boolean)((!cv_jitterlegacy[n].value) & 1); + if (metalrecording && n == 0) { // Starring Metal Sonic as themselves, obviously. SetPlayerSkinByNum(playernum, 5); @@ -1793,6 +1815,7 @@ static void SendNameAndColor(UINT8 n) WRITEUINT16(p, (UINT16)cv_skin[n].value); WRITESINT8(p, (SINT8)cv_follower[n].value); WRITEUINT16(p, (UINT16)cv_followercolor[n].value); + WRITEUINT8(p, (UINT8)((!cv_jitterlegacy[n].value) & 1)); SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf); } @@ -1804,6 +1827,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) UINT16 color, followercolor; UINT16 skin; SINT8 follower; + boolean jitterlegacy; SINT8 localplayer = -1; UINT16 i; @@ -1834,6 +1858,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) skin = READUINT16(*cp); follower = READSINT8(*cp); followercolor = READUINT16(*cp); + jitterlegacy = READUINT8(*cp); // set name if (player_name_changes[playernum] < MAXNAMECHANGES) @@ -1842,6 +1867,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) SetPlayerName(playernum, name); } + // Set jitter + p->jitterlegacy = jitterlegacy; + // set color p->skincolor = color % numskincolors; if (p->mo) @@ -6829,6 +6857,39 @@ static void Followercolor4_OnChange(void) } } +// Changes a player's jitter settings. +static void Jitter_OnChange(void) +{ + if (!Playing()) + return; // don't send anything there. + + SendNameAndColor(0); +} + +static void Jitter2_OnChange(void) +{ + if (!Playing()) + return; // don't send anything there. + + SendNameAndColor(1); +} + +static void Jitter3_OnChange(void) +{ + if (!Playing()) + return; // don't send anything there. + + SendNameAndColor(2); +} + +static void Jitter4_OnChange(void) +{ + if (!Playing()) + return; // don't send anything there. + + SendNameAndColor(3); +} + /** Sends a skin change for the console player, unless that player is moving. * \sa cv_skin, Skin2_OnChange, Color_OnChange * \author Graue diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 448b60a00..62e1a5357 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -29,6 +29,7 @@ extern consvar_t cv_playercolor[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_skin[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_follower[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_jitterlegacy[MAXSPLITSCREENPLAYERS]; // preferred number of players extern consvar_t cv_splitplayers; diff --git a/src/d_player.h b/src/d_player.h index cc6687518..1f345a272 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -565,6 +565,8 @@ struct player_t // SRB2kart stuff INT32 kartstuff[NUMKARTSTUFF]; INT32 karthud[NUMKARTHUD]; + boolean jitterlegacy; // If true, makes Ring Racers characters jitter during drifts like + // SRB2Kart. // Basic gameplay things UINT8 position; // Used for Kart positions, mostly for deterministic stuff @@ -600,6 +602,7 @@ struct player_t fixed_t driftcharge; // Charge your drift so you can release a burst of speed UINT8 driftboost; // (0 to 125) - Boost you get from drifting tic_t driftsparkGrowTimer; + tic_t driftelapsed; // Elapsed time spent during a drift. SINT8 aizdriftstrat; // (-1 to 1) - Let go of your drift while boosting? Helper for the SICK STRATZ (sliptiding!) you have just unlocked INT32 aizdrifttilt; diff --git a/src/g_game.c b/src/g_game.c index a86c9c7df..766adfdf0 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2467,6 +2467,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT8 lastsafelap; UINT8 lastsafestarpost; UINT16 bigwaypointgap; + boolean jitterlegacy = false; score = players[player].score; lives = players[player].lives; @@ -2490,6 +2491,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) followercolor = players[player].followercolor; followerskin = players[player].followerskin; + jitterlegacy = players[player].jitterlegacy; + availabilities = players[player].availabilities; charflags = players[player].charflags; @@ -2689,6 +2692,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->eggmanblame = -1; p->nocontrol = nocontrol; p->kickstartaccel = kickstartaccel; + p->jitterlegacy = jitterlegacy; p->ringvolume = 255; p->ringtransparency = 255; diff --git a/src/k_kart.c b/src/k_kart.c index 5e8876980..49fb56801 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1565,17 +1565,21 @@ void K_KartMoveAnimation(player_t *player) UINT16 buttons = K_GetKartButtons(player); const boolean spinningwheels = (player->speed > 0); const boolean lookback = ((buttons & BT_LOOKBACK) == BT_LOOKBACK); + const boolean skincompat = wadfiles[((skin_t *)player->mo->skin)->wadnum]->compatmode; SINT8 turndir = intsign(player->cmd.turning); SINT8 destGlanceDir = 0; SINT8 drift = player->drift; UINT8 spr2, glanceofs; + player->mo->rollingxoffset = 0; + player->mo->rollingyoffset = 0; + if (!lookback) player->pflags &= ~PF_GAINAX; // Sliptides: drift -> lookback frames - if (abs(player->aizdriftturn) >= ANGLE_90 && !wadfiles[((skin_t *)player->mo->skin)->wadnum]->compatmode) + if (abs(player->aizdriftturn) >= ANGLE_90 && !skincompat) { destGlanceDir = -(2*intsign(player->aizdriftturn)); player->glanceDir = destGlanceDir; @@ -1690,13 +1694,21 @@ void K_KartMoveAnimation(player_t *player) if (onground && drift) { - if (drift > 0) - turndir *= -1; + if ((player->jitterlegacy) && (!skincompat)) + { + // Make RR characters imitate legacy jitters. + player->mo->rollingxoffset = ((player->driftelapsed & 1) * 2) * -intsign(drift); + } + else + { + if (drift > 0) + turndir *= -1; - if (turndir == -1) - spr2 += 2; // Inwards drift - else if (turndir == 1) - spr2 += 1; // Outwards drift + if (turndir == -1) + spr2 += 2; // Inwards drift + else if (turndir == 1) + spr2 += 1; // Outwards drift + } } else if (glanceofs) spr2 += glanceofs+1; diff --git a/src/p_saveg.c b/src/p_saveg.c index 983b21f28..b4f21ffec 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2363,7 +2363,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 diff2 |= MD2_TID; if (mobj->spritexscale != FRACUNIT || mobj->spriteyscale != FRACUNIT) diff2 |= MD2_SPRITESCALE; - if (mobj->spritexoffset || mobj->spriteyoffset) + if (mobj->spritexoffset || mobj->spriteyoffset || + mobj->rollingxoffset || mobj->rollingyoffset) diff2 |= MD2_SPRITEOFFSET; if (mobj->sprxoff || mobj->spryoff || mobj->sprzoff) diff2 |= MD2_WORLDOFFSET; @@ -2605,6 +2606,8 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 { WRITEFIXED(save->p, mobj->spritexoffset); WRITEFIXED(save->p, mobj->spriteyoffset); + WRITEINT16(save->p, mobj->rollingxoffset); + WRITEINT16(save->p, mobj->rollingyoffset); } if (diff2 & MD2_WORLDOFFSET) { @@ -3872,10 +3875,13 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) { mobj->spritexoffset = READFIXED(save->p); mobj->spriteyoffset = READFIXED(save->p); + mobj->rollingxoffset = READINT16(save->p); + mobj->rollingyoffset = READINT16(save->p); } else { mobj->spritexoffset = mobj->spriteyoffset = 0; + mobj->rollingxoffset = mobj->rollingyoffset = 0; } if (diff2 & MD2_WORLDOFFSET) { diff --git a/src/p_user.c b/src/p_user.c index eb24e8f75..25a1a7211 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3839,6 +3839,16 @@ void P_PlayerThink(player_t *player) player->airtime++; } + // BlanKart: Track drifting time. + if (player->drift != 0) + { + player->driftelapsed++; + } + else + { + player->driftelapsed = 0; + } + cmd = &player->cmd; // SRB2kart diff --git a/src/r_things.cpp b/src/r_things.cpp index 9eb82250a..b79019803 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -857,7 +857,8 @@ boolean R_ThingIsFlashing(mobj_t *thing) boolean R_ThingIsUsingBakedOffsets(mobj_t* thing) { return ((thing->bakexoff) || (thing->bakeyoff) || (thing->bakezoff) || - (thing->bakexpiv) || (thing->bakeypiv) || (thing->bakezpiv)); + (thing->bakexpiv) || (thing->bakeypiv) || (thing->bakezpiv) || + (thing->rollingxoffset) || (thing->rollingyoffset)); } UINT8 *R_GetSpriteTranslation(vissprite_t *vis)