From a4d89f30834d600ebcb5af87f2c76e1049157f3e Mon Sep 17 00:00:00 2001 From: Anonimus Date: Sun, 14 Sep 2025 07:05:12 -0400 Subject: [PATCH] Spinout rotations --- src/d_netcmd.c | 4 + src/d_netcmd.h | 1 + src/d_player.h | 2 + src/g_game.c | 1 + src/k_hud.c | 210 +++++++++++++++++++++++++++++++++++++++++++------ src/m_menu.c | 29 +++++-- src/p_mobj.c | 1 + src/p_saveg.c | 2 + src/p_user.c | 33 ++++++++ src/st_stuff.c | 20 +++++ src/y_inter.c | 14 +++- 11 files changed, 282 insertions(+), 35 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 9dc9040a3..7bb5460da 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -661,6 +661,9 @@ static CV_PossibleValue_t minimapdot_cons_t[] = {{0, "Off"}, {1, "Dot"}, {2, "He consvar_t cv_showminimapangle = CVAR_INIT ("showminimapangle", "Dot", CV_SAVE, minimapdot_cons_t, NULL); consvar_t cv_minihead = CVAR_INIT ("smallminimapplayers", "Off", CV_SAVE, CV_OnOff, NULL); +static CV_PossibleValue_t spinoutroll_cons_t[] = {{0, "Off"}, {1, "Minimap Only"}, {2, "Rankings Only"}, {3, "Minimap+Rankings"}, {0, NULL}}; +consvar_t cv_spinoutroll = CVAR_INIT ("spinoutroll", "Minimap+Rankings", CV_SAVE, spinoutroll_cons_t, NULL); + consvar_t cv_showviewpointtext = CVAR_INIT ("showviewpointtext", "On", CV_SAVE, CV_OnOff, NULL); // Intermission time Tails 04-19-2002 @@ -973,6 +976,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_showminimapnames); CV_RegisterVar(&cv_showminimapangle); CV_RegisterVar(&cv_minihead); + CV_RegisterVar(&cv_spinoutroll); CV_RegisterVar(&cv_showlapemblem); CV_RegisterVar(&cv_racesplits); CV_RegisterVar(&cv_showviewpointtext); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index de6cfdeaf..f4b169f63 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -226,6 +226,7 @@ extern consvar_t cv_pingmeasurement; extern consvar_t cv_showminimapnames; extern consvar_t cv_showminimapangle; extern consvar_t cv_minihead; +extern consvar_t cv_spinoutroll; extern consvar_t cv_showlapemblem; extern consvar_t cv_racesplits; diff --git a/src/d_player.h b/src/d_player.h index 4c68c2c45..bc4124e8c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -625,6 +625,8 @@ struct player_t tic_t driftsparkGrowTimer; tic_t driftelapsed; // Elapsed time spent during a drift. + fixed_t spinoutrot; // When a player spins out, this value increments modulus 360. + SINT8 aizdriftstrat; // (-1 to 1) - Let go of your drift while boosting? Helper for the SICK STRATZ (sliptiding!) you have just unlocked INT32 aizdrifttilt; INT32 aizdriftturn; diff --git a/src/g_game.c b/src/g_game.c index 26a21d50a..b48b8b076 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2725,6 +2725,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->ringvolume = 255; p->ringtransparency = 255; + p->spinoutrot = 0; p->spectatorreentry = spectatorreentry; p->grieftime = grieftime; diff --git a/src/k_hud.c b/src/k_hud.c index 8a295175f..f077f5160 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -366,6 +366,9 @@ void K_LoadKartHUDGraphics(void) { buffer[7] = '0'+(i+1); HU_UpdatePatch(&kp_facehighlight[i], "%s", buffer); + + kp_facehighlight[i]->leftoffset = kp_facehighlight[i]->width / 2; + kp_facehighlight[i]->topoffset = kp_facehighlight[i]->height / 2; } // Special minimap icons @@ -1856,6 +1859,16 @@ static UINT32 K_InvincibilityHUDVisibility(UINT16 t) return min(9, 10 - alphalevel)<color, GTC_CACHE); - V_DrawMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin][FACE_RANK], colormap); + patch_t *facerank = faceprefix[players[rankplayer[i]].skin][FACE_RANK]; + + offsets.x = facerank->leftoffset; + offsets.y = facerank->topoffset; + +#ifdef ROTSPRITE + if ((K_RankIconCanSpinout()) && (players[rankplayer[i]].spinoutrot)) + { + // Rotate counterclockwise. + rollangle = FixedAngle(players[rankplayer[i]].spinoutrot * -1); + rot = R_GetRollAngle(rollangle); + + if (rot) + { + facerank = Patch_GetRotated(facerank, rot, false); + } + } +#endif + + V_DrawMappedPatch(FACE_X + offsets.x, Y + offsets.y, V_HUDTRANS|V_SNAPTOLEFT, facerank, colormap); if ((players[rankplayer[i]].invincibilitytimer) && (K_GetKartInvinType() == KARTINVIN_ALTERN)) { colormap = R_GetTranslationColormap(TC_BLINK, K_AltInvincibilityColor(leveltime / 2), GTC_CACHE); invinchudtrans = K_InvincibilityHUDVisibility(players[rankplayer[i]].invincibilitytimer); - V_DrawMappedPatch(FACE_X, Y, invinchudtrans|V_SNAPTOLEFT|V_ADD, faceprefix[players[rankplayer[i]].skin][FACE_RANK], colormap); + V_DrawMappedPatch(FACE_X + offsets.x, Y + offsets.y, invinchudtrans|V_SNAPTOLEFT|V_ADD, facerank, colormap); } if (LUA_HudEnabled(hud_battlebumpers)) @@ -1985,7 +2025,30 @@ static boolean K_drawKartPositionFaces(void) } if (i == strank) - V_DrawScaledPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_facehighlight[(leveltime / 4) % 8]); + { + patch_t *highlight = kp_facehighlight[(leveltime / 4) % 8]; + + INT32 left, top; + + left = highlight->leftoffset; + top = highlight->topoffset; + +#ifdef ROTSPRITE + if ((K_RankIconCanSpinout()) && (players[rankplayer[i]].spinoutrot)) + { + // Rotate counterclockwise. + rollangle = FixedAngle(players[rankplayer[i]].spinoutrot * -1); + rot = R_GetRollAngle(rollangle); + + if (rot) + { + highlight = Patch_GetRotated(highlight, rot, false); + } + } +#endif + + V_DrawScaledPatch(FACE_X+left, Y+top, V_HUDTRANS|V_SNAPTOLEFT, highlight); + } if (gametype == GT_BATTLE && players[rankplayer[i]].bumper <= 0) V_DrawScaledPatch(FACE_X-4, Y-3, V_HUDTRANS|V_SNAPTOLEFT, kp_ranknobumpers); @@ -2201,7 +2264,17 @@ INT32 K_DrawNeoTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines V_DrawThinString(x2 + 20, y2, ((tab[i].num == whiteplayer) ? hightlightcolor : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, playername); - V_DrawFixedPatch((x2+11)*FRACUNIT, (y+1)*FRACUNIT, FRACUNIT/2, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap); + patch_t *facerank = faceprefix[players[tab[i].num].skin][FACE_RANK]; + fixed_t scale = FRACUNIT/2; + + V_DrawFixedPatch( + ((x2+11)*FRACUNIT) + ((facerank->leftoffset) * scale), + ((y+1)*FRACUNIT) + ((facerank->topoffset) * scale), + scale, + 0, + facerank, + colormap + ); /*if (gametype == GT_BATTLE && players[tab[i].num].bumper > 0) -- not enough space for this { @@ -2214,8 +2287,17 @@ INT32 K_DrawNeoTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines } }*/ + patch_t *highlight = kp_facehighlight[(leveltime / 4) % 8]; + if (tab[i].num == whiteplayer) - V_DrawFixedPatch((x2+11)*FRACUNIT, (y+1)*FRACUNIT, FRACUNIT/2, 0, kp_facehighlight[(leveltime / 4) % 8], NULL); + V_DrawFixedPatch( + ((x2+11)*FRACUNIT)+(highlight->leftoffset * scale), + ((y+1)*FRACUNIT)+(highlight->topoffset * scale), + scale, + 0, + highlight, + NULL + ); if ((gametyperules & GTR_BUMPERS) && players[tab[i].num].bumper <= 0) V_DrawScaledPatch(x2-4, y-7, 0, kp_ranknobumpers); @@ -2434,7 +2516,9 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN else V_DrawString(x + 20, y2, ((tab[i].num == whiteplayer) ? hightlightcolor : 0)|V_ALLOWLOWERCASE, playername); - V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap); + patch_t *facerank = faceprefix[players[tab[i].num].skin][FACE_RANK]; + + V_DrawMappedPatch(x+facerank->leftoffset, y-4+facerank->topoffset, 0, facerank, colormap); /*if (gametype == GT_BATTLE && players[tab[i].num].bumper > 0) -- not enough space for this { @@ -2448,7 +2532,10 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN }*/ if (tab[i].num == whiteplayer) - V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]); + { + patch_t *highlight = kp_facehighlight[(leveltime / 4) % 8]; + V_DrawScaledPatch(x+highlight->leftoffset, y-4+highlight->topoffset, 0, highlight); + } if (gametype == GT_BATTLE && players[tab[i].num].bumper <= 0) V_DrawScaledPatch(x-4, y-7, 0, kp_ranknobumpers); @@ -2519,7 +2606,9 @@ static void K_drawKartLaps(void) if (LUA_HudEnabled(hud_lives) && uselives) { UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, K_GetHudColor(), GTC_CACHE); - V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); + patch_t *mmappatch = faceprefix[stplyr->skin][FACE_MINIMAP]; + + V_DrawMappedPatch(fr+21+mmappatch->leftoffset, fy-13+mmappatch->topoffset, V_HUDTRANS|splitflags, mmappatch, colormap); if (stplyr->lives >= 0) V_DrawScaledPatch(fr+34, fy-10, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[(stplyr->lives % 10)]); // make sure this doesn't overflow OR underflow } @@ -2564,7 +2653,8 @@ static void K_drawKartLaps(void) } UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, K_GetHudColor(), GTC_CACHE); - V_DrawMappedPatch(fx+59+offsetx, fy-16+offsety, V_HUDTRANS|splitflags, faceprefix[stplyr->skin][FACE_RANK], colormap); + patch_t *facerank = faceprefix[stplyr->skin][FACE_RANK]; + V_DrawMappedPatch(fx+59+offsetx+facerank->leftoffset, fy-16+offsety+facerank->topoffset, V_HUDTRANS|splitflags, facerank, colormap); if (stplyr->lives >= 0) V_DrawScaledPatch(fx+77+offsetx, fy-11+offsety, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow OR underflow } @@ -3072,7 +3162,8 @@ static void K_drawKartWanted(void) if (players[battlewanted[i]].skincolor) { colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE); - V_DrawFixedPatch(x<skin][FACE_WANTED] : faceprefix[p->skin][FACE_RANK]), colormap); + patch_t *wantedicon = (scale == FRACUNIT ? faceprefix[p->skin][FACE_WANTED] : faceprefix[p->skin][FACE_RANK]); + V_DrawFixedPatch((x+wantedicon->leftoffset)<topoffset)<skin][FACE_WANTED] : faceprefix[p->skin][FACE_RANK]), colormap);*/ } @@ -3569,7 +3660,7 @@ static void K_drawKartNameTags(void) V_ClearClipRect(); } -static inline void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap) +static inline void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap, vector2_t *origin) { // amnum xpos & ypos are the icon's speed around the HUD. // The number being divided by is for how fast it moves. @@ -3582,6 +3673,20 @@ static inline void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 amxpos, amypos; fixed_t scale = FRACUNIT; + INT16 w, h; + + if (origin) + { + w = origin->x * 2; + h = origin->y * 2; + } + else + { + w = icon->width; + h = icon->height; + } + + if (!cv_showminimapangle.value && (icon == kp_minimapdot)) return; @@ -3594,8 +3699,8 @@ static inline void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, if (encoremode) amnumxpos = -amnumxpos; - amxpos = amnumxpos + ((hudx + (minimapinfo.minimap_pic->width-icon->width)/2)<height-icon->height)/2)<width-w)/2)<height-h)/2)<mo->old_x, g->mo->x); interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap); + patch_t *ghostPic = faceprefix[skin][FACE_MINIMAP]; + iconoffsets.x = ((ghostPic->width) / 2) - ghostPic->leftoffset; + iconoffsets.y = ((ghostPic->height) / 2) - ghostPic->topoffset; + + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, ghostPic, colormap, &iconoffsets); g = g->next; } @@ -3924,6 +4043,10 @@ static void K_drawKartMinimap(void) if (players[i].mo->health <= 0 && players[i].pflags & PF_NOCONTEST) { workingPic = kp_nocontestminimap; + + iconoffsets.x = ((workingPic->width) / 2); + iconoffsets.y = ((workingPic->height) / 2); + colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE); } else @@ -3932,6 +4055,23 @@ static void K_drawKartMinimap(void) workingPic = faceprefix[skin][FACE_MINIMAP]; + iconoffsets.x = ((workingPic->width) / 2) - workingPic->leftoffset; + iconoffsets.y = ((workingPic->height) / 2) - workingPic->topoffset; + +#ifdef ROTSPRITE + if ((K_MinimapIconCanSpinout()) && (players[i].spinoutrot)) + { + // Rotate counterclockwise. + rollangle = FixedAngle(players[i].spinoutrot * -1); + rot = R_GetRollAngle(rollangle); + + if (rot) + { + workingPic = Patch_GetRotated(workingPic, rot, false); + } + } +#endif + colorizeplayer = players[i].mo->colorized; if ((players[i].invincibilitytimer) && ((K_InvincibilityGradient(players[i].invincibilitytimer) > (FRACUNIT/2)) || (K_GetKartInvinType() == KARTINVIN_LEGACY))) @@ -3966,7 +4106,7 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, &iconoffsets); if (mobj->player) { @@ -3978,7 +4118,7 @@ static void K_drawKartMinimap(void) if ((gametype == GT_RACE && players[i].position == spbplace) || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[i]))) { - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, NULL); } } } @@ -4029,7 +4169,7 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, NULL); } for (mobj = misccap; mobj; mobj = next) @@ -4064,7 +4204,7 @@ static void K_drawKartMinimap(void) interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpy = R_InterpolateFixed(mobj->old_y, mobj->y); - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, NULL); } // draw our local players here, opaque. @@ -4097,7 +4237,7 @@ static void K_drawKartMinimap(void) interpy = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y); // temporary graphic? - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap, NULL); } } @@ -4116,6 +4256,10 @@ static void K_drawKartMinimap(void) if (players[localplayers[i]].mo->health <= 0 && players[localplayers[i]].pflags & PF_NOCONTEST) { workingPic = kp_nocontestminimap; + + iconoffsets.x = ((workingPic->width) / 2); + iconoffsets.y = ((workingPic->height) / 2); + colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE); nocontest = true; @@ -4126,6 +4270,23 @@ static void K_drawKartMinimap(void) workingPic = faceprefix[skin][FACE_MINIMAP]; + iconoffsets.x = ((workingPic->width) / 2) - workingPic->leftoffset; + iconoffsets.y = ((workingPic->height) / 2) - workingPic->topoffset; + +#ifdef ROTSPRITE + if ((K_MinimapIconCanSpinout()) && (players[localplayers[i]].spinoutrot)) + { + // Rotate counterclockwise. + rollangle = FixedAngle(players[localplayers[i]].spinoutrot * -1); + rot = R_GetRollAngle(rollangle); + + if (rot) + { + workingPic = Patch_GetRotated(workingPic, rot, false); + } + } +#endif + colorizeplayer = players[localplayers[i]].mo->colorized; if ((players[localplayers[i]].invincibilitytimer) && @@ -4178,7 +4339,8 @@ static void K_drawKartMinimap(void) y - FixedMul(FSIN(ang), ICON_DOT_RADIUS), splitflags, kp_minimapdot, - colormap + colormap, + NULL ); } else if (cv_showminimapangle.value == 2) @@ -4196,13 +4358,13 @@ static void K_drawKartMinimap(void) } } - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, &iconoffsets); // Target reticule if ((gametype == GT_RACE && players[localplayers[i]].position == spbplace) || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[localplayers[i]]))) { - K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL); + K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, NULL); } K_drawKartMinimapNametag(interpx, interpy, x, y, splitflags, mobj->player); @@ -4977,7 +5139,9 @@ static void K_drawLapSplitComparison(void) INT32 stwidth = V_StringWidth(buffer, splitflags) / 2; // vibes offset - V_DrawMappedPatch(row_position[0] - stwidth - 35, row_position[1], splitflags, faceprefix[skin][FACE_MINIMAP], skincolor); + patch_t *face = faceprefix[skin][FACE_MINIMAP]; + + V_DrawMappedPatch(row_position[0] - stwidth - 35 + face->leftoffset, row_position[1] + face->topoffset, splitflags, face, skincolor); if (pos > 1) { diff --git a/src/m_menu.c b/src/m_menu.c index 3f824c213..eae8ffe09 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4182,6 +4182,7 @@ void MD_DrawReplayStartMenu(void) { const char *warning; UINT8 i; + INT32 xoffs, yoffs; MD_DrawGenericMenu(); @@ -4189,6 +4190,7 @@ void MD_DrawReplayStartMenu(void) // Draw rankings beyond first for (i = 1; i < MAXPLAYERS && demolist[dir_on[menudepthleft]].standings[i].ranking; i++) { + xoffs = yoffs = 0; patch_t *patch; UINT8 *colormap; @@ -4210,6 +4212,10 @@ void MD_DrawReplayStartMenu(void) if (demolist[dir_on[menudepthleft]].standings[i].skin < numskins && W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facewant) != LUMPERROR) { patch = faceprefix[demolist[dir_on[menudepthleft]].standings[i].skin][FACE_RANK]; + + xoffs = SHORT(patch->leftoffset); + yoffs = SHORT(patch->topoffset); + colormap = R_GetTranslationColormap( demolist[dir_on[menudepthleft]].standings[i].skin, demolist[dir_on[menudepthleft]].standings[i].color, @@ -4224,7 +4230,7 @@ void MD_DrawReplayStartMenu(void) GTC_MENUCACHE); } - V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width), STARTY + i*20, V_SNAPTOTOP, patch, colormap); + V_DrawMappedPatch(BASEVIDWIDTH-5 - SHORT(patch->width) + xoffs, STARTY + i*20 + yoffs, V_SNAPTOTOP, patch, colormap); } #undef STARTY @@ -4378,8 +4384,11 @@ void MD_DrawPlaybackMenu(void) //M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15); //M_DrawCenteredMenu(); + INT32 xoffs, yoffs; + for (i = 0; i < currentMenu->numitems; i++) { + xoffs = yoffs = 0; UINT8 *inactivemap = NULL; INT16 splitnum = i == M_GetMenuIndex(MN_PLAYBACK, "VIEW1") ? 0 : @@ -4396,6 +4405,10 @@ void MD_DrawPlaybackMenu(void) INT32 ply = displayplayers[splitnum]; icon = faceprefix[players[ply].skin][FACE_RANK]; + + xoffs = icon->leftoffset; + yoffs = icon->topoffset; + if (i != itemOn) inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); } @@ -4412,9 +4425,9 @@ void MD_DrawPlaybackMenu(void) icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp if ((i == M_GetMenuIndex(MN_PLAYBACK, "FASTFORWARD") && cv_playbackspeed.value > 1) || (i == M_GetMenuIndex(MN_PLAYBACK, "REWIND") && demo.rewinding)) - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].x, currentMenu->y, transmap|V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].x + xoffs, currentMenu->y + yoffs, transmap|V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE)); else - V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].x, currentMenu->y, transmap|V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].x + xoffs, currentMenu->y + yoffs, transmap|V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap); if (i == itemOn) { @@ -7096,8 +7109,8 @@ void MD_DrawBarCssSelector(void) { scale = FRACUNIT/2; face = faceprefix[col][FACE_RANK]; - offx = 8; - offy = 8; + offx = 8 + face->leftoffset; + offy = 8 + face->topoffset; } colmap = R_GetTranslationColormap(col, cv_dummycolor.value, GTC_MENUCACHE); if (face) @@ -7209,7 +7222,7 @@ void MD_DrawGridCssSelector(void) { face = faceprefix[skinn][FACE_RANK]; colmap = R_GetTranslationColormap(skinn, skins[skinn].prefcolor, GTC_MENUCACHE); - V_DrawFixedPatch(gridx * FRACUNIT, gridy * FRACUNIT, FRACUNIT, 0, face, colmap); + V_DrawFixedPatch((gridx + face->leftoffset) * FRACUNIT, (gridy + face->topoffset) * FRACUNIT, FRACUNIT, 0, face, colmap); } } @@ -7232,7 +7245,7 @@ void MD_DrawGridCssSelector(void) { face = faceprefix[skintodisplay][FACE_RANK]; colmap = R_GetTranslationColormap(skintodisplay, cv_dummycolor.value, GTC_MENUCACHE); - V_DrawFixedPatch(cursorx * FRACUNIT, cursory * FRACUNIT, FRACUNIT, 0, face, colmap); + V_DrawFixedPatch((cursorx + face->leftoffset) * FRACUNIT, (cursory + face->topoffset) * FRACUNIT, FRACUNIT, 0, face, colmap); cursor = W_CachePatchName("M_FSEL", PU_CACHE); if (skullAnimCounter < 4) @@ -8644,7 +8657,7 @@ void MD_DrawViewServer(void) } - V_DrawFixedPatch(x<leftoffset)<topoffset)<grieftime = 0; + p->spinoutrot = 0; if (gametyperules & GTR_BUMPERS) { diff --git a/src/p_saveg.c b/src/p_saveg.c index 33d7ac1fb..5e211359b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -258,6 +258,7 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT16(save->p, players[i].flashing); WRITEUINT16(save->p, players[i].spinouttimer); + WRITEINT32(save->p, players[i].spinoutrot); WRITEUINT8(save->p, players[i].spinouttype); WRITEUINT16(save->p, players[i].flipovertimer); WRITEANGLE(save->p, players[i].flipoverangle); @@ -610,6 +611,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].flashing = READUINT16(save->p); players[i].spinouttimer = READUINT16(save->p); + players[i].spinoutrot = READINT32(save->p); players[i].spinouttype = READUINT8(save->p); players[i].flipoverangle = READUINT16(save->p); players[i].flipovertimer = READANGLE(save->p); diff --git a/src/p_user.c b/src/p_user.c index 5e2921dd2..dc164ce06 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3785,6 +3785,9 @@ DoABarrelRoll (player_t *player) player->tilt = slope; } +#define SPINOUTROTSPEED (24 * FRACUNIT) +#define MAXSPINROT (360 * FRACUNIT) + // // P_PlayerThink // @@ -3946,6 +3949,36 @@ void P_PlayerThink(player_t *player) } } + // MKWii-styled icon spinouts: do a full 360 rotation before stopping. + if (P_PlayerInPain(player)) + { + if (player->spinoutrot < MAXSPINROT) + { + if ((player->spinoutrot + SPINOUTROTSPEED) >= MAXSPINROT) + { + player->spinoutrot = (player->spinoutrot + SPINOUTROTSPEED) % MAXSPINROT; + } + else + { + player->spinoutrot += SPINOUTROTSPEED; + } + } + } + else + { + if ((player->spinoutrot) && (player->spinoutrot < MAXSPINROT)) + { + if ((player->spinoutrot + SPINOUTROTSPEED) >= MAXSPINROT) + { + player->spinoutrot = 0; + } + else + { + player->spinoutrot += SPINOUTROTSPEED; + } + } + } + // If it is set, start subtracting // Don't allow it to go back to 0 if (player->exiting > 1 && (player->exiting < raceexittime+2 || !(gametyperules & GTR_CIRCUIT))) // SRB2kart - "&& player->exiting > 1" diff --git a/src/st_stuff.c b/src/st_stuff.c index aa2ebbf27..0704e39df 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -190,6 +190,11 @@ void ST_LoadGraphics(void) #endif } +static boolean ST_IconCanSpinout(UINT8 icon) +{ + return ((icon == FACE_MINIMAP)||(icon == FACE_RANK)); +} + // made separate so that skins code can reload custom face graphics void ST_LoadFaceGraphics(INT32 skinnum) { @@ -201,6 +206,21 @@ void ST_LoadFaceGraphics(INT32 skinnum) { sprframe = &sprdef->spriteframes[i]; faceprefix[skinnum][i] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); + + if (ST_IconCanSpinout(i)) + { + // Auto-center all minimap and rank patches with no offsets defined. + // This is a shitty, hacky solution... but it's less work for spinout rotations! + if (faceprefix[skinnum][i]->leftoffset == 0) + { + faceprefix[skinnum][i]->leftoffset = faceprefix[skinnum][i]->width / 2; + } + + if (faceprefix[skinnum][i]->topoffset == 0) + { + faceprefix[skinnum][i]->topoffset = faceprefix[skinnum][i]->height / 2; + } + } i++; } if (i < FACE_MAX) diff --git a/src/y_inter.c b/src/y_inter.c index 4c71d219e..c16feb7ae 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -525,13 +525,16 @@ void Y_IntermissionDrawer(void) if (data.color[i]) { UINT8 *colormap = R_GetTranslationColormap(*data.character[i], *data.color[i], GTC_CACHE); - V_DrawMappedPatch(x+16, y-4, 0, faceprefix[*data.character[i]][FACE_RANK], colormap); + patch_t *facerank = faceprefix[*data.character[i]][FACE_RANK]; + + V_DrawMappedPatch(x+16+facerank->leftoffset, y-4+facerank->topoffset, 0, facerank, colormap); } if (data.num[i] == whiteplayer) { UINT8 cursorframe = (intertic / 4) % 8; - V_DrawScaledPatch(x+16, y-4, 0, W_CachePatchName(va("K_CHILI%d", cursorframe+1), PU_CACHE)); + patch_t *highlight = W_CachePatchName(va("K_CHILI%d", cursorframe+1), PU_CACHE); + V_DrawScaledPatch(x+16+highlight->leftoffset, y-4+highlight->topoffset, 0, highlight); } if ((players[data.num[i]].pflags & PF_NOCONTEST) && players[data.num[i]].bot) @@ -1467,13 +1470,16 @@ void Y_VoteDrawer(void) if (players[i].skincolor) { UINT8 *colormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, GTC_CACHE); - V_DrawMappedPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin][FACE_RANK], colormap); + patch_t *facerank = faceprefix[*data.character[i]][FACE_RANK]; + + V_DrawMappedPatch(x+24+facerank->leftoffset, y+9+facerank->topoffset, V_SNAPTOLEFT, facerank, colormap); } if (!splitscreen && i == consoleplayer) { UINT8 cursorframe = (votetic / 4) % 8; - V_DrawScaledPatch(x+24, y+9, V_SNAPTOLEFT, W_CachePatchName(va("K_CHILI%d", cursorframe+1), PU_CACHE)); + patch_t *highlight = W_CachePatchName(va("K_CHILI%d", cursorframe+1), PU_CACHE); + V_DrawScaledPatch(x+24+highlight->leftoffset, y+9+highlight->topoffset, V_SNAPTOLEFT, highlight); } }