diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 91d3a9199..7d080c03a 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1051,7 +1051,14 @@ static void SendNameAndColor(const UINT8 n) WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME); WRITEUINT16(p, sendColor); WRITEUINT8(p, (UINT8)cv_skin[n].value); - WRITEINT16(p, (INT16)cv_follower[n].value); + if (horngoner) + { + WRITEINT16(p, (-1)); + } + else + { + WRITEINT16(p, (INT16)cv_follower[n].value); + } //CONS_Printf("Sending follower id %d\n", (INT16)cv_follower[n].value); WRITEUINT16(p, sendFollowerColor); diff --git a/src/k_follower.c b/src/k_follower.c index d80835f61..847a95c50 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -32,6 +32,8 @@ follower_t followers[MAXFOLLOWERS]; INT32 numfollowercategories; followercategory_t followercategories[MAXFOLLOWERCATEGORIES]; +boolean horngoner = false; + CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for "Match", "Opposite" & NULL /*-------------------------------------------------- diff --git a/src/k_follower.h b/src/k_follower.h index dc5ca9a72..78dbc9b0e 100644 --- a/src/k_follower.h +++ b/src/k_follower.h @@ -115,6 +115,8 @@ struct followercategory_t extern INT32 numfollowercategories; extern followercategory_t followercategories[MAXFOLLOWERCATEGORIES]; +extern boolean horngoner; + /*-------------------------------------------------- INT32 K_FollowerAvailable(const char *name) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 183afba6d..281589de5 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -1526,7 +1526,7 @@ static void K_initKartHUD(void) } } -void K_DrawMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, UINT16 map, const UINT8 *colormap) +void K_DrawMapThumbnail2(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, UINT16 map, const UINT8 *colormap, fixed_t accordion) { patch_t *PictureOfLevel = NULL; @@ -1543,58 +1543,79 @@ void K_DrawMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, UINT1 PictureOfLevel = static_cast(mapheaderinfo[map]->thumbnailPic); } - K_DrawLikeMapThumbnail(x, y, width, flags, PictureOfLevel, colormap); + K_DrawLikeMapThumbnail(x, y, width, flags, PictureOfLevel, colormap, accordion); } -void K_DrawLikeMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, patch_t *patch, const UINT8 *colormap) +void K_DrawLikeMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, patch_t *patch, const UINT8 *colormap, fixed_t accordion) { - if (flags & V_FLIP) - x += width; + fixed_t scale = FixedDiv(width, (320 << FRACBITS)); - V_DrawFixedPatch( + if (flags & V_FLIP) + x += FixedMul(width, accordion); + + V_DrawStretchyFixedPatch( x, y, - FixedDiv(width, (320 << FRACBITS)), + FixedMul(scale, accordion), + scale, flags, patch, colormap ); } -void K_DrawMapAsFace(INT32 x, INT32 y, UINT32 flags, UINT16 map, const UINT8 *colormap) +void K_DrawMapAsFace(INT32 x, INT32 y, UINT32 flags, UINT16 map, const UINT8 *colormap, fixed_t accordion, INT32 scalefactor) { - const fixed_t iconHeight = (14 << FRACBITS); + const fixed_t iconHeight = ((16 * scalefactor) - 2) << FRACBITS; const fixed_t iconWidth = (iconHeight * 320) / 200; - INT32 unit = 1; fixed_t mul = FRACUNIT; + + INT32 dup = 1; if (flags & V_NOSCALESTART) { - unit = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + dup = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); mul = 1; } + INT32 hdup = (dup * accordion); + V_DrawFill( x, y, - 16 * unit, - 16 * unit, + (16 * scalefactor * hdup)/FRACUNIT, + 16 * scalefactor * dup, (flags & ~V_FLIP) ); + INT32 xclip = ((16 * scalefactor) - 2) * dup * mul; + + if (flags & V_NOSCALESTART) + { + hdup /= FRACUNIT; + } + else + { + hdup = FixedMul(hdup, mul); + xclip = FixedMul(xclip, accordion); + } + + dup *= mul; + V_SetClipRect( - (x + unit) * mul, - (y + unit) * mul, - (14 * unit) * mul, - (14 * unit) * mul, + (x * mul) + hdup, + (y * mul) + dup, + xclip, + ((16 * scalefactor) - 2) * dup, (flags & ~V_FLIP) ); - K_DrawMapThumbnail( - ((x + unit) * FRACUNIT) - (iconWidth - iconHeight)/2, - ((y + unit) * FRACUNIT), + K_DrawMapThumbnail2( + (x * mul) + hdup - FixedMul(iconWidth - iconHeight, accordion)/2, + (y * mul) + dup, iconWidth, flags, map, - colormap + colormap, + accordion ); V_ClearClipRect(); diff --git a/src/k_hud.h b/src/k_hud.h index af5a30b68..c251fc137 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -58,9 +58,10 @@ INT32 K_drawKartMicroTime(const char *todrawtext, INT32 workx, INT32 worky, INT3 void K_drawKart2PTimestamp(void); void K_drawKart4PTimestamp(void); void K_drawEmeraldWin(boolean overlay); -void K_DrawMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, UINT16 map, const UINT8 *colormap); -void K_DrawLikeMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, patch_t *patch, const UINT8 *colormap); -void K_DrawMapAsFace(INT32 x, INT32 y, UINT32 flags, UINT16 map, const UINT8 *colormap); +void K_DrawMapThumbnail2(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, UINT16 map, const UINT8 *colormap, fixed_t accordion); +#define K_DrawMapThumbnail(x, y, w, f, m, c) K_DrawMapThumbnail2(x, y, w, f, m, c, FRACUNIT) +void K_DrawLikeMapThumbnail(fixed_t x, fixed_t y, fixed_t width, UINT32 flags, patch_t *patch, const UINT8 *colormap, fixed_t accordion); +void K_DrawMapAsFace(INT32 x, INT32 y, UINT32 flags, UINT16 map, const UINT8 *colormap, fixed_t accordion, INT32 unit); void K_drawTargetHUD(const vector3_t *origin, player_t *player); void K_drawButton(fixed_t x, fixed_t y, INT32 flags, patch_t *button[2], boolean pressed); void K_drawButtonAnim(INT32 x, INT32 y, INT32 flags, patch_t *button[2], tic_t animtic); diff --git a/src/k_menu.h b/src/k_menu.h index 4847a988f..bc69c2299 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1428,6 +1428,8 @@ typedef enum #define CHAOHOLD_END (3) #define CHAOHOLD_PADDING (CHAOHOLD_BEGIN + CHAOHOLD_END) +#define EASEOFFHORN 50 + extern struct timeattackmenu_s { tic_t ticker; // How long the menu's been open for @@ -1461,11 +1463,14 @@ extern struct challengesmenu_s { UINT16 tutorialfound; boolean requestflip; + UINT16 nowplayingtile; UINT16 unlockcount[CMC_MAX]; UINT8 fade; + UINT8 hornposting; + boolean cache_secondrowlocked; patch_t *tile_category[10][2]; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 94357b020..09bc1e8b4 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1862,6 +1862,9 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, boolean charfli follower_t *fl; UINT8 rotation = (charflip ? 1 : 7); + if (horngoner) + return false; + if (p != NULL) followernum = p->followern; else @@ -2406,7 +2409,7 @@ void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p) V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], ccolormap); } - if (fln >= 0) + if (!horngoner && fln >= 0) { UINT16 fcol = K_GetEffectiveFollowerColor( p->followercolor, @@ -6722,7 +6725,6 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash fixed_t siz, accordion; UINT16 id, num; boolean unlockedyet; - boolean categoryside; id = (i * CHALLENGEGRIDHEIGHT) + j; num = gamedata->challengegrid[id]; @@ -6797,20 +6799,88 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash accordion = FRACUNIT; - if (challengesmenu.extradata[id].flip != 0 + boolean categoryside = (challengesmenu.extradata[id].flip == 0); + + if (!categoryside // optimised, this is not the true value with anything but instaflip && challengesmenu.extradata[id].flip != (TILEFLIP_MAX/2)) { - angle_t bad = (FixedAngle(FixedMul(challengesmenu.extradata[id].flip * FRACUNIT + rendertimefrac, 360*FRACUNIT/TILEFLIP_MAX)) >> ANGLETOFINESHIFT) & FINEMASK; - accordion = FINECOSINE(bad); + fixed_t bad = challengesmenu.extradata[id].flip * FRACUNIT + rendertimefrac; + angle_t worse = (FixedAngle(FixedMul(bad, 360*FRACUNIT/TILEFLIP_MAX)) >> ANGLETOFINESHIFT) & FINEMASK; + accordion = FINECOSINE(worse); if (accordion < 0) accordion = -accordion; + + // NOW we set it in an interp-friendly way + categoryside = (bad <= FRACUNIT*TILEFLIP_MAX/4 + || bad > (3*FRACUNIT*TILEFLIP_MAX)/4); } pat = W_CachePatchName( (ref->majorunlock ? "UN_BORDB" : "UN_BORDA"), PU_CACHE); - bgmap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_SILVER, GTC_MENUCACHE); + UINT8 iconid = 0; + + { + UINT16 bcol = SKINCOLOR_SILVER; + switch (ref->type) + { + case SECRET_SKIN: + bcol = SKINCOLOR_NOVA; + iconid = 1; + break; + case SECRET_FOLLOWER: + if (horngoner) + { + bcol = SKINCOLOR_BLACK; + } + else + { + bcol = SKINCOLOR_SAPPHIRE; + iconid = 2; + } + break; + case SECRET_COLOR: + //bcol = SKINCOLOR_SILVER; + iconid = 3; + break; + case SECRET_CUP: + bcol = SKINCOLOR_GOLD; + iconid = 4; + break; + case SECRET_MAP: + bcol = SKINCOLOR_PURPLE; + iconid = 8; + break; + case SECRET_HARDSPEED: + case SECRET_MASTERMODE: + case SECRET_ENCORE: + bcol = SKINCOLOR_RUBY; + iconid = 5; + break; + case SECRET_ONLINE: + case SECRET_ADDONS: + case SECRET_EGGTV: + case SECRET_SOUNDTEST: + case SECRET_ALTTITLE: + bcol = SKINCOLOR_BLUEBERRY; + iconid = 6; + break; + case SECRET_TIMEATTACK: + case SECRET_PRISONBREAK: + case SECRET_SPECIALATTACK: + case SECRET_SPBATTACK: + bcol = SKINCOLOR_PERIDOT; + iconid = 7; + break; + case SECRET_ALTMUSIC: + bcol = SKINCOLOR_MAGENTA; + iconid = 9; + break; + } + + bgmap = R_GetTranslationColormap(TC_DEFAULT, bcol, GTC_MENUCACHE); + } V_DrawStretchyFixedPatch( (x*FRACUNIT) + (SHORT(pat->width)*(FRACUNIT-accordion)/2), y*FRACUNIT, @@ -6822,65 +6892,25 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash pat = missingpat; - categoryside = (challengesmenu.extradata[id].flip <= TILEFLIP_MAX/4 - || challengesmenu.extradata[id].flip > (3*TILEFLIP_MAX)/4); - #ifdef DEVELOP if (cv_debugchallenges.value) { - // Show the content of every tile without needing to - // flip them. + // Show the content of every tile without needing to flip them. categoryside = false; } #endif - if (categoryside) + if (horngoner && ref->type == SECRET_FOLLOWER) + goto drawborder; + else if (categoryside) { - char categoryid = '0'; - colormap = bgmap; - switch (ref->type) - { - case SECRET_SKIN: - categoryid = '1'; - break; - case SECRET_FOLLOWER: - categoryid = '2'; - break; - case SECRET_COLOR: - categoryid = '3'; - break; - case SECRET_CUP: - categoryid = '4'; - break; - case SECRET_MAP: - categoryid = '8'; - break; - case SECRET_HARDSPEED: - case SECRET_MASTERMODE: - case SECRET_ENCORE: - categoryid = '5'; - break; - case SECRET_ONLINE: - case SECRET_ADDONS: - case SECRET_EGGTV: - case SECRET_SOUNDTEST: - case SECRET_ALTTITLE: - categoryid = '6'; - break; - case SECRET_TIMEATTACK: - case SECRET_PRISONBREAK: - case SECRET_SPECIALATTACK: - case SECRET_SPBATTACK: - categoryid = '7'; - break; - case SECRET_ALTMUSIC: - categoryid = '9'; - break; - } - pat = challengesmenu.tile_category[categoryid - '0'][ref->majorunlock ? 1 : 0]; + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_SILVER, GTC_MENUCACHE); + + // iconid is already prepopulated because we had to draw the border + pat = challengesmenu.tile_category[iconid][ref->majorunlock ? 1 : 0]; if (pat == missingpat) { - pat = challengesmenu.tile_category[categoryid - '0'][ref->majorunlock ? 0 : 1]; + pat = challengesmenu.tile_category[iconid][ref->majorunlock ? 0 : 1]; } } else if (ref->icon != NULL && ref->icon[0]) @@ -6893,7 +6923,7 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash } else { - UINT8 iconid = 0; + iconid = 0; // reuse switch (ref->type) { case SECRET_SKIN: @@ -6930,8 +6960,42 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash } case SECRET_MAP: - iconid = 14; + { + UINT16 mapnum = M_UnlockableMapNum(ref); + if (mapnum < nummapheaders && mapheaderinfo[mapnum] + && ( + ( // Check for visitation + (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + || (mapheaderinfo[mapnum]->records.mapvisited & MV_VISITED) + ) && ( // Check for completion + !(mapheaderinfo[mapnum]->menuflags & LF2_FINISHNEEDED) + || (mapheaderinfo[mapnum]->records.mapvisited & MV_BEATEN) + ) + )) + { + if (ref->majorunlock) + { + K_DrawMapAsFace( + (x + 5) + (32*(FRACUNIT-accordion))/(2*FRACUNIT), (y + 5), + tileflags, + mapnum, + NULL, accordion, 2 + ); + } + else + { + K_DrawMapAsFace( + (x + 2) + (16*(FRACUNIT-accordion))/(2*FRACUNIT), (y + 2), + tileflags, + mapnum, + NULL, accordion, 1 + ); + } + pat = NULL; + } + iconid = 0; //14; -- This one suits a little better for "go complete this level normally" break; + } case SECRET_ALTMUSIC: iconid = 16; break; @@ -7001,29 +7065,32 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash } } - siz = (SHORT(pat->width) << FRACBITS); + if (pat) + { + siz = (SHORT(pat->width) << FRACBITS); - if (!siz) - ; // prevent div/0 - else if (ref->majorunlock) - { - V_DrawStretchyFixedPatch( - ((x + 5)*FRACUNIT) + (32*(FRACUNIT-accordion)/2), (y + 5)*FRACUNIT, - FixedDiv(32*accordion, siz), - FixedDiv(32 << FRACBITS, siz), - tileflags, pat, - colormap - ); - } - else - { - V_DrawStretchyFixedPatch( - ((x + 2)*FRACUNIT) + (16*(FRACUNIT-accordion)/2), (y + 2)*FRACUNIT, - FixedDiv(16*accordion, siz), - FixedDiv(16 << FRACBITS, siz), - tileflags, pat, - colormap - ); + if (!siz) + ; // prevent div/0 + else if (ref->majorunlock) + { + V_DrawStretchyFixedPatch( + ((x + 5)*FRACUNIT) + (32*(FRACUNIT-accordion))/2, (y + 5)*FRACUNIT, + FixedDiv(32*accordion, siz), + FixedDiv(32 << FRACBITS, siz), + tileflags, pat, + colormap + ); + } + else + { + V_DrawStretchyFixedPatch( + ((x + 2)*FRACUNIT) + (16*(FRACUNIT-accordion))/2, (y + 2)*FRACUNIT, + FixedDiv(16*accordion, siz), + FixedDiv(16 << FRACBITS, siz), + tileflags, pat, + colormap + ); + } } drawborder: @@ -7154,7 +7221,7 @@ void M_DrawCharacterIconAndEngine(INT32 x, INT32 y, UINT8 skin, UINT8 *colormap, V_DrawFill(x+16 + (s*5), y + (w*5), 6, 6, 0); } -static void M_DrawChallengePreview(INT32 x, INT32 y) +static const char* M_DrawChallengePreview(INT32 x, INT32 y) { unlockable_t *ref = NULL; UINT8 *colormap = NULL; @@ -7162,12 +7229,9 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) if (challengesmenu.currentunlock >= MAXUNLOCKABLES) { - return; + return NULL; } - // Okay, this is what we want to draw. - ref = &unlockables[challengesmenu.currentunlock]; - // Funny question mark? if (!gamedata->unlocked[challengesmenu.currentunlock]) { @@ -7179,7 +7243,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) if (!sprdef->numframes) { - return; + return NULL; } useframe = (challengesmenu.ticker / 2) % sprdef->numframes; @@ -7193,9 +7257,14 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) } V_DrawFixedPatch(x*FRACUNIT, (y+2)*FRACUNIT, FRACUNIT, addflags, patch, NULL); - return; + return NULL; } + // Okay, this is what we want to draw. + ref = &unlockables[challengesmenu.currentunlock]; + + const char *actiontext = NULL; + switch (ref->type) { case SECRET_SKIN: @@ -7207,6 +7276,19 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE); M_DrawCharacterSprite(x, y, skin, SPR2_STIN, 7, 0, 0, colormap); + y = (BASEVIDHEIGHT-14); + + if (setup_numplayers <= 1 && cv_lastprofile[0].value != PROFILE_GUEST) + { + profile_t *pr = PR_GetProfile(cv_lastprofile[0].value); + + actiontext = (pr && strcmp(pr->skinname, skins[skin]->name)) + ? " Set on Profile" + : " Set on Profile"; + + y -= 14; + } + for (i = 0; i < skin; i++) { if (!R_SkinUsable(-1, i, false)) @@ -7220,7 +7302,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) break; } - M_DrawCharacterIconAndEngine(4, BASEVIDHEIGHT-(4+16), i, colormap, skin); + M_DrawCharacterIconAndEngine(4, y-6, i, colormap, skin); } break; } @@ -7235,6 +7317,11 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) colormap = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_BLACK, GTC_MENUCACHE); M_DrawCharacterSprite(x, y, skin, SPR2_STIN, 7, 0, 0, colormap); + if (horngoner) + { + return " MISSING."; + } + // Draw follower next to them if (fskin != -1) { @@ -7242,9 +7329,69 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE); M_DrawFollowerSprite(x - 16, y, fskin, false, 0, colormap, NULL); + y = (BASEVIDHEIGHT-14); + + if (setup_numplayers <= 1 && cv_lastprofile[0].value != PROFILE_GUEST) + { + profile_t *pr = PR_GetProfile(cv_lastprofile[0].value); + + if (pr && strcmp(pr->follower, followers[fskin].name)) + { + actiontext = (followers[fskin].hornsound == sfx_melody) + ? " Set on Profile" + : " Set on Profile"; + } + } + + if (!actiontext) + { + if (followers[fskin].hornsound == sfx_melody) + { + actiontext = " Play Ancient Melody?"; + } + else if (challengesmenu.hornposting >= EASEOFFHORN) + actiontext = " Time to die"; + else if (challengesmenu.hornposting >= (EASEOFFHORN-5)) + { + if (challengesmenu.hornposting == EASEOFFHORN) + actiontext = "Time to die"; + else + actiontext = "I asked politely"; + actiontext = va("%s%s", + (M_MenuConfirmPressed(0) + ? " " + : " " + ), actiontext + ); + } + else if (challengesmenu.hornposting >= (EASEOFFHORN-10)) + { + actiontext = M_MenuConfirmPressed(0) + ? " Ease off the horn" + : " Ease off the horn"; + } + else switch (challengesmenu.hornposting % 4) + { + default: + actiontext = " Say hello"; + break; + case 1: + actiontext = " Express your feelings"; + break; + case 2: + actiontext = " Celebrate victory"; + break; + case 3: + actiontext = " Announce you are pressing horn"; + break; + } + } + + y -= 14; + if (followers[fskin].category < numfollowercategories) { - V_DrawFixedPatch(4*FRACUNIT, (BASEVIDHEIGHT-(4+16))*FRACUNIT, + V_DrawFixedPatch(4*FRACUNIT, (y - 6)*FRACUNIT, FRACUNIT, 0, W_CachePatchName(followercategories[followers[fskin].category].icon, PU_CACHE), NULL); @@ -7264,6 +7411,16 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) // Draw reference for character bathed in coloured slime M_DrawCharacterSprite(x, y, skin, SPR2_STIN, 7, 0, 0, colormap); + + if (setup_numplayers <= 1 && cv_lastprofile[0].value != PROFILE_GUEST) + { + profile_t *pr = PR_GetProfile(cv_lastprofile[0].value); + + actiontext = (pr && pr->color != colorid) + ? " Set on Profile" + : " Set on Profile"; + } + break; } case SECRET_CUP: @@ -7346,6 +7503,8 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) const char *gtname = "Find your prize..."; UINT16 mapnum = M_UnlockableMapNum(ref); + y = (BASEVIDHEIGHT-14); + if (mapnum >= nummapheaders || mapheaderinfo[mapnum] == NULL || mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) @@ -7389,7 +7548,13 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) guessgt = GT_SPECIAL; } - if (guessgt == GT_SPECIAL && !M_SecretUnlocked(SECRET_SPECIALATTACK, true)) + if (setup_numplayers <= 1 && guessgt == GT_TUTORIAL) + { + // Only for 1p + actiontext = " Play Tutorial"; + gtname = NULL; + } + else if (guessgt == GT_SPECIAL && !M_SecretUnlocked(SECRET_SPECIALATTACK, true)) { gtname = "???"; } @@ -7409,7 +7574,10 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) NULL); } - V_DrawThinString(1, BASEVIDHEIGHT-(9+3), 0, gtname); + if (gtname) + { + V_DrawThinString(4, y, 0, gtname); + } break; } @@ -7519,8 +7687,8 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) } case SECRET_ALTTITLE: { - x = 8; - y = BASEVIDHEIGHT-16; + x = 4; + y = BASEVIDHEIGHT-14; V_DrawGamemodeString(x, y - 33, 0, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_MENUCACHE), M_UseAlternateTitleScreen() ? "On" : "Off"); K_DrawGameControl(x, y, 0, " Toggle", 0, TINY_FONT, 0); @@ -7537,7 +7705,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) if (map >= nummapheaders || !mapheaderinfo[map]) { - return; + break; } UINT8 musicid; @@ -7549,78 +7717,104 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) if (musicid == MAXMUSNAMES) { - return; + break; } - spritedef_t *sprdef = &sprites[SPR_ALTM]; - spriteframe_t *sprframe; - patch_t *patch; - UINT32 addflags = 0; + const char *tune = "challenge_altmusic"; - x -= 10; - y += 15; + SINT8 pushed = 0; + const boolean epossible = (M_SecretUnlocked(SECRET_ENCORE, true) + && musicid < mapheaderinfo[map]->encoremusname_size); - if (sprdef->numframes) + if (challengesmenu.nowplayingtile == ((challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy) + && Music_Playing(tune)) { - sprframe = &sprdef->spriteframes[0]; - patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); - - if (sprframe->flip & 1) // Only for first sprite - { - addflags ^= V_FLIP; // This sprite is left/right flipped! - } - - V_DrawFixedPatch(x*FRACUNIT, (y+2)*FRACUNIT, FRACUNIT/2, addflags, patch, NULL); + const char *song = Music_Song(tune); + if (epossible + && strcmp(song, mapheaderinfo[map]->encoremusname[musicid]) == 0) + pushed = -1; + else if (musicid < mapheaderinfo[map]->musname_size + && strcmp(song, mapheaderinfo[map]->musname[musicid]) == 0) + pushed = 1; } - x = 8; - y = BASEVIDHEIGHT-16; - - const boolean thismusplaying = Music_Playing("challenge_altmusic"); - boolean pushed = false; - const char *song = NULL; - - if (M_SecretUnlocked(SECRET_ENCORE, true) - && musicid < mapheaderinfo[map]->encoremusname_size) + // Draw CD { - if (thismusplaying) + spritedef_t *sprdef = &sprites[SPR_ALTM]; + spriteframe_t *sprframe; + patch_t *patch = NULL; + UINT32 addflags = 0; + + x -= 10; + y += 15; + + if (sprdef->numframes) { - song = Music_Song("challenge_altmusic"); - pushed = strcmp(song, mapheaderinfo[map]->encoremusname[musicid]) == 0; +#ifdef ROTSPRITE + spriteinfo_t *sprinfo = &spriteinfo[SPR_ALTM]; + INT32 rollangle = 0; + if (pushed != 0) + { + rollangle = (Music_Elapsed(tune) % (ROTANGLES/2))*2; + if (rendertimefrac >= FRACUNIT/2) + { + // A fun interp ability: inbetweens + rollangle++; + } + if (pushed > 0) + { + rollangle = ((ROTANGLES-1) - rollangle); + } + } +#endif + + sprframe = &sprdef->spriteframes[0]; + +#ifdef ROTSPRITE + if (rollangle) + { + patch = Patch_GetRotatedSprite(sprframe, 0, 0, (sprframe->flip & 1), false, sprinfo, rollangle); + } +#endif + if (!patch) + { + patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + if (sprframe->flip & 1) // Only for first sprite + { + addflags ^= V_FLIP; // This sprite is left/right flipped! + } + } + + V_DrawFixedPatch(x*FRACUNIT, (y+2)*FRACUNIT, FRACUNIT/2, addflags, patch, NULL); } - - if (!pushed) - K_DrawGameControl(x, y, 0, " E Side", 0, TINY_FONT, 0); - else - K_DrawGameControl(x, y, 0, " E Side", 0, TINY_FONT, 0); - // K_drawButton(x&FRACUNIT, y*FRACUNIT, 0, kp_button_l, pushed); - // x += SHORT(kp_button_l[0]->width); - // V_DrawThinString(x, y + 1, (pushed ? V_GRAYMAP : highlightflags), "E Side"); - - x = 8; - y -= 10; } if (musicid < mapheaderinfo[map]->musname_size) { - if (pushed || !thismusplaying) - { - pushed = false; - } - else - { - if (!song) - song = Music_Song("challenge_altmusic"); - pushed = strcmp(song, mapheaderinfo[map]->musname[musicid]) == 0; - } + actiontext = (pushed > 0) + ? " Stop CD" + : " Play CD"; + } - if (!pushed) - K_DrawGameControl(x, y, 0, " Play CD", 0, TINY_FONT, 0); + if (epossible) + { + const char *secondtext = (pushed < 0) + ? " E Stop" + : " E Side"; + if (actiontext) + { + // weird encoded height + actiontext = va("\x1""%s\n%s", + (pushed < 0) + ? " E Stop" + : " E Side", + actiontext + ); + } else - K_DrawGameControl(x, y, 0, " Play CD", 0, TINY_FONT, 0); - // K_drawButton(x*FRACUNIT, y*FRACUNIT, 0, kp_button_a[1], pushed); - // x += SHORT(kp_button_a[1][0]->width); - // V_DrawThinString(x, y + 1, (pushed ? V_GRAYMAP : highlightflags), "Play CD"); + { + actiontext = secondtext; + } } } default: @@ -7630,7 +7824,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) } if (specialmap == NEXTMAP_INVALID || !ref) - return; + return actiontext; x -= 50; y = 146+2; @@ -7678,6 +7872,8 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) W_CachePatchName("K_LAPE02", PU_CACHE), colormap); } + + return actiontext; } #define challengesgridstep 22 @@ -7914,11 +8110,6 @@ static void M_DrawChallengeScrollBar(UINT8 *flashmap) V_DrawFill(barx + hilix, bary-1, hiliw, 1, 0); V_DrawFill(barx + hilix, bary+barh, hiliw, 1, 0); - INT32 mindiscouragement = 2; // skipping major unlocks is just a LITTLE cringe - if (challengesmenu.unlockcount[CMC_PERCENT] == 100 - && challengesmenu.unlockcount[CMC_MAJORSKIPPED] == 0) - mindiscouragement = 1; // so someone looking for 101% isn't hunting forever - // unbounded so that we can do the last remaining completionamount draw nextstep = numincolumn = completionamount = skiplevel = 0; for (i = 0; ; i++) @@ -7932,7 +8123,7 @@ static void M_DrawChallengeScrollBar(UINT8 *flashmap) if (completionamount >= numincolumn) { // If any have been skipped, we subtract a little for awareness... - completionamount = (skiplevel >= mindiscouragement) ? 9 : 10; + completionamount = skiplevel ? 9 : 10; } else { @@ -7969,6 +8160,14 @@ static void M_DrawChallengeScrollBar(UINT8 *flashmap) } #endif + if (i == challengesmenu.nowplayingtile && Music_Playing("challenge_altmusic")) + { + V_DrawFill(barx + hilix, bary, hiliw, barh, (challengesmenu.ticker & 2) ? 177 : 122); + + // The now-playing fill overrides everything else. + completionamount = -1; + } + if (completionamount == -1) continue; @@ -7978,9 +8177,9 @@ static void M_DrawChallengeScrollBar(UINT8 *flashmap) unlockable_t *ref = &unlockables[gamedata->challengegrid[i]]; - if (skiplevel < 2 && M_Achieved(ref->conditionset - 1) == false) + if (!skiplevel && M_Achieved(ref->conditionset - 1) == false) { - skiplevel = ref->majorunlock ? 2 : 1; + skiplevel = 1; } } @@ -8231,9 +8430,10 @@ challengedesc: y = BASEVIDHEIGHT-16; // Unlock preview - M_DrawChallengePreview(x, y); + const char *actiontext = M_DrawChallengePreview(x, y); // Conditions for unlock + // { -- please don't call va() anywhere between here... i = (challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy; if (challengesmenu.unlockcondition != NULL @@ -8246,6 +8446,25 @@ challengedesc: { V_DrawCenteredThinString(BASEVIDWIDTH/2, 120 + 32, 0, challengesmenu.unlockcondition); } + + // Extracted from M_DrawCharSelectPreview for ordering reasons + if (actiontext && actiontext[0]) + { + x = 4; + y = (BASEVIDHEIGHT-14); + if (actiontext[0] < '\x5') + { + // weird encoded height, supports max 5 rows + y -= (13 * actiontext[0]); + actiontext++; + } + K_DrawGameControl( + x, y, 0, + actiontext, + 0, TINY_FONT, 0 + ); + // } -- ...and here (since actiontext needs it) + } } #undef challengetransparentstrength diff --git a/src/k_vote.c b/src/k_vote.c index 21b1494f5..13ce0b22e 100644 --- a/src/k_vote.c +++ b/src/k_vote.c @@ -705,7 +705,7 @@ static void Y_DrawVoteThumbnail(fixed_t center_x, fixed_t center_y, fixed_t widt fy + fh - whiteSq + dupy, flags | V_NOSCALESTART | ((encore == true) ? V_FLIP : 0), g_voteLevels[v][0], - NULL + NULL, FRACUNIT, 1 ); } } diff --git a/src/m_cond.c b/src/m_cond.c index 54d5725e5..c1a4ffb9f 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1655,7 +1655,12 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) case UC_TOTALMEDALS: // Requires number of emblems >= x return (M_GotEnoughMedals(cn->requirement)); case UC_EMBLEM: // Requires emblem x to be obtained - return gamedata->collected[cn->requirement-1]; + { + INT32 i = cn->requirement-1; + if (i >= 0 && i < numemblems && emblemlocations[i].type != ET_NONE) + return gamedata->collected[cn->requirement-1]; + return false; + } case UC_UNLOCKABLE: // Requires unlockable x to be obtained return gamedata->unlocked[cn->requirement-1]; case UC_CONDITIONSET: // requires condition set x to already be achieved @@ -3204,7 +3209,7 @@ static boolean M_CheckUnlockConditions(player_t *player) { UINT32 i; conditionset_t *c; - boolean ret; + boolean ret = false; for (i = 0; i < MAXCONDITIONSETS; ++i) { diff --git a/src/menus/extras-challenges.c b/src/menus/extras-challenges.c index 64b07d8a8..aeae6aae2 100644 --- a/src/menus/extras-challenges.c +++ b/src/menus/extras-challenges.c @@ -82,6 +82,10 @@ static void M_UpdateChallengeGridVisuals(void) challengesmenu.unlockcount[CMC_UNLOCKED] = 0; challengesmenu.unlockcount[CMC_TOTAL] = 0; + challengesmenu.unlockcount[CMC_KEYED] = 0; + challengesmenu.unlockcount[CMC_MAJORSKIPPED] = 0; + +//#define MAJORDISTINCTION -- The "basic" medal is basically never seen because Major challenges are usually completed last before 101%. Correct that with this for (i = 0; i < MAXUNLOCKABLES; i++) { @@ -106,12 +110,14 @@ static void M_UpdateChallengeGridVisuals(void) challengesmenu.unlockcount[CMC_KEYED]++; +#ifdef MAJORDISTINCTION if (unlockables[i].majorunlock == false) { continue; } challengesmenu.unlockcount[CMC_MAJORSKIPPED]++; +#endif } challengesmenu.unlockcount[CMC_PERCENT] = @@ -125,7 +131,9 @@ static void M_UpdateChallengeGridVisuals(void) challengesmenu.unlockcount[CMC_MEDALFILLED] = (medalheight * ( challengesmenu.unlockcount[CMC_UNLOCKED] +#ifdef MAJORDISTINCTION - challengesmenu.unlockcount[CMC_MAJORSKIPPED] +#endif )) / challengesmenu.unlockcount[CMC_TOTAL]; if (challengesmenu.unlockcount[CMC_PERCENT] == 100) @@ -135,7 +143,10 @@ static void M_UpdateChallengeGridVisuals(void) challengesmenu.unlockcount[CMC_MEDALID] = 2; challengesmenu.unlockcount[CMC_PERCENT]++; // 101% } - else if (challengesmenu.unlockcount[CMC_MAJORSKIPPED] == 0) + else +#ifdef MAJORDISTINCTION + if (challengesmenu.unlockcount[CMC_MAJORSKIPPED] == 0) +#endif { challengesmenu.unlockcount[CMC_MEDALID] = 1; } @@ -364,10 +375,13 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu) if ((challengesmenu.pending = (newunlock != MAXUNLOCKABLES))) { Music_StopAll(); - MISC_ChallengesDef.prevMenu = desiredmenu; + if (desiredmenu && desiredmenu != &MISC_ChallengesDef) + { + MISC_ChallengesDef.prevMenu = desiredmenu; + } } - if (challengesmenu.pending || desiredmenu == NULL) + if (challengesmenu.pending || desiredmenu == &MISC_ChallengesDef) { static boolean firstopen = true; @@ -379,10 +393,12 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu) challengesmenu.tutorialfound = NEXTMAP_INVALID; challengesmenu.chaokeyhold = 0; challengesmenu.unlockcondition = NULL; + challengesmenu.hornposting = 0; if (firstopen) { challengesmenu.currentunlock = MAXUNLOCKABLES; + challengesmenu.nowplayingtile = UINT16_MAX; firstopen = false; } @@ -402,9 +418,14 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu) if (challengesmenu.pending) M_ChallengesAutoFocus(newunlock, true); - else if (newunlock >= MAXUNLOCKABLES && gamedata->pendingkeyrounds > 0 - && (gamedata->chaokeys < GDMAX_CHAOKEYS)) - challengesmenu.chaokeyadd = true; + else + { + if (newunlock >= MAXUNLOCKABLES && gamedata->pendingkeyrounds > 0 + && (gamedata->chaokeys < GDMAX_CHAOKEYS)) + challengesmenu.chaokeyadd = true; + + M_ChallengesAutoFocus(UINT16_MAX, true); + } M_CacheChallengeTiles(); @@ -418,17 +439,24 @@ void M_Challenges(INT32 choice) { (void)choice; - M_InterruptMenuWithChallenges(NULL); + M_InterruptMenuWithChallenges(&MISC_ChallengesDef); MISC_ChallengesDef.prevMenu = currentMenu; - if (gamedata->challengegrid != NULL && !challengesmenu.pending) - { - M_ChallengesAutoFocus(UINT16_MAX, true); - } - M_SetupNextMenu(&MISC_ChallengesDef, false); } +static void M_CloseChallenges(void) +{ + Music_Stop("challenge_altmusic"); + challengesmenu.nowplayingtile = UINT16_MAX; + + Z_Free(challengesmenu.extradata); + challengesmenu.extradata = NULL; + + Z_Free(challengesmenu.unlockcondition); + challengesmenu.unlockcondition = NULL; +} + boolean M_CanKeyHiliTile(void) { // No tile data? @@ -569,13 +597,20 @@ void M_ChallengesTick(void) { UINT16 id = (challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy; boolean seeeveryone = challengesmenu.requestflip; - boolean allthewaythrough; + boolean allthewaythrough = allthewaythrough = (!seeeveryone && !challengesmenu.pending); + UINT8 maxflip; + + if (id == challengesmenu.nowplayingtile) + { + // Don't permit the active song to stop spinning + id = UINT16_MAX; + } + for (i = 0; i < (CHALLENGEGRIDHEIGHT * gamedata->challengegridwidth); i++) { - allthewaythrough = (!seeeveryone && !challengesmenu.pending && i != id); - maxflip = ((seeeveryone || !allthewaythrough) ? (TILEFLIP_MAX/2) : TILEFLIP_MAX); - if ((seeeveryone || (i == id) || (challengesmenu.extradata[i].flip > 0)) + maxflip = ((allthewaythrough && i != id) ? TILEFLIP_MAX : (TILEFLIP_MAX/2)); + if ((seeeveryone || (i == id) || (i == challengesmenu.nowplayingtile) || (challengesmenu.extradata[i].flip > 0)) && (challengesmenu.extradata[i].flip != maxflip)) { challengesmenu.extradata[i].flip++; @@ -943,19 +978,12 @@ boolean M_ChallengesInputs(INT32 ch) { if (M_MenuBackPressed(pid) || start) { - Music_Stop("challenge_altmusic"); - currentMenu->prevMenu = M_SpecificMenuRestore(currentMenu->prevMenu); M_GoBack(0); M_SetMenuDelay(pid); - Z_Free(challengesmenu.extradata); - challengesmenu.extradata = NULL; - - if (challengesmenu.unlockcondition) - Z_Free(challengesmenu.unlockcondition); - challengesmenu.unlockcondition = NULL; + M_CloseChallenges(); return true; } @@ -1137,8 +1165,56 @@ boolean M_ChallengesInputs(INT32 ch) if (challengesmenu.currentunlock < MAXUNLOCKABLES && gamedata->unlocked[challengesmenu.currentunlock]) { + unlockable_t *ref = &unlockables[challengesmenu.currentunlock]; + + boolean forceflip = false; + switch (unlockables[challengesmenu.currentunlock].type) { + case SECRET_MAP: + { + // Only for 1p + if (setup_numplayers <= 1 && M_MenuConfirmPressed(pid)) + { + // Map exists... + UINT16 mapnum = M_UnlockableMapNum(ref); + if (mapnum < nummapheaders && mapheaderinfo[mapnum]) + { + // is tutorial... + INT32 guessgt = G_GuessGametypeByTOL(mapheaderinfo[mapnum]->typeoflevel); + if (guessgt == GT_TUTORIAL) + { + M_SetMenuDelay(pid); + + multiplayer = true; + + restoreMenu = currentMenu; + restorelevellist = levellist; + + // mild hack + levellist.newgametype = guessgt; + levellist.netgame = false; + M_MenuToLevelPreamble(0, false); + + D_MapChange( + mapnum+1, + guessgt, + false, + true, + 1, + false, + false + ); + + M_CloseChallenges(); + M_ClearMenus(true); + + return false; // DO NOT + } + } + } + break; + } case SECRET_ALTTITLE: { if (M_MenuConfirmPressed(pid)) @@ -1147,6 +1223,103 @@ boolean M_ChallengesInputs(INT32 ch) CV_AddValue(&cv_alttitle, 1); S_StartSound(NULL, sfx_s3kc3s); M_SetMenuDelay(pid); + + forceflip = true; + } + break; + } + case SECRET_SKIN: + { + if (setup_numplayers <= 1 && cv_lastprofile[0].value != PROFILE_GUEST && M_MenuConfirmPressed(pid)) + { + INT32 skin = M_UnlockableSkinNum(ref); + if (skin != -1) + { + profile_t *pr = PR_GetProfile(cv_lastprofile[0].value); + + if (pr && strcmp(pr->skinname, skins[skin]->name)) + { + strcpy(pr->skinname, skins[skin]->name); + CV_Set(&cv_skin[0], skins[skin]->name); + + S_StartSound(NULL, sfx_s3k63); + S_StartSound(NULL, skins[skin]->soundsid[S_sfx[sfx_kattk1].skinsound]); + M_SetMenuDelay(pid); + + forceflip = true; + } + } + } + break; + } + case SECRET_FOLLOWER: + { + if (!horngoner && M_MenuConfirmPressed(pid)) + { + INT32 fskin = M_UnlockableFollowerNum(ref); + if (fskin != -1) + { + if (setup_numplayers <= 1 && cv_lastprofile[0].value != PROFILE_GUEST) + { + profile_t *pr = PR_GetProfile(cv_lastprofile[0].value); + + if (pr && strcmp(pr->follower, followers[fskin].name)) + { + strcpy(pr->follower, followers[fskin].name); + CV_Set(&cv_follower[0], followers[fskin].name); + + challengesmenu.hornposting = 0; + + S_StartSound(NULL, sfx_s3k63); + forceflip = true; + } + } + + if (!forceflip) + challengesmenu.hornposting++; + + if (challengesmenu.hornposting > EASEOFFHORN) + { + challengesmenu.hornposting = 0; + horngoner = true; + S_StartSound(NULL, sfx_s3k72); + } + else + { + S_StartSound(NULL, followers[fskin].hornsound); + } + + M_SetMenuDelay(pid); + + forceflip = true; + } + } + break; + } + case SECRET_COLOR: + { + if (setup_numplayers <= 1 && cv_lastprofile[0].value != PROFILE_GUEST && M_MenuConfirmPressed(pid)) + { + INT32 colorid = M_UnlockableColorNum(ref); + if (colorid != SKINCOLOR_NONE) + { + profile_t *pr = PR_GetProfile(cv_lastprofile[0].value); + + if (pr && pr->color != colorid) + { + pr->color = colorid; + CV_SetValue(&cv_playercolor[0], colorid); + if (setup_numplayers) + { + G_SetPlayerGamepadIndicatorToPlayerColor(0); + } + + S_StartSound(NULL, sfx_s3k63); + M_SetMenuDelay(pid); + + forceflip = true; + } + } } break; } @@ -1167,7 +1340,7 @@ boolean M_ChallengesInputs(INT32 ch) { const char *trymusname = NULL; - UINT16 map = M_UnlockableMapNum(&unlockables[challengesmenu.currentunlock]); + UINT16 map = M_UnlockableMapNum(ref); if (map >= nummapheaders || !mapheaderinfo[map]) { @@ -1196,15 +1369,18 @@ boolean M_ChallengesInputs(INT32 ch) if (trymusname) { - if (!Music_Playing("challenge_altmusic") - || strcmp(Music_Song("challenge_altmusic"), trymusname)) + const char *tune = "challenge_altmusic"; + if (!Music_Playing(tune) + || strcmp(Music_Song(tune), trymusname)) { - Music_Remap("challenge_altmusic", trymusname); - Music_Play("challenge_altmusic"); + Music_Remap(tune, trymusname); + Music_Play(tune); + challengesmenu.nowplayingtile = (challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy; } else { - Music_Stop("challenge_altmusic"); + Music_Stop(tune); + challengesmenu.nowplayingtile = UINT16_MAX; } M_SetMenuDelay(pid); @@ -1217,6 +1393,16 @@ boolean M_ChallengesInputs(INT32 ch) break; } + if (forceflip) + { + UINT16 id = (challengesmenu.hilix * CHALLENGEGRIDHEIGHT) + challengesmenu.hiliy; + // This construction helps pressing too early + if (challengesmenu.extradata[id].flip <= TILEFLIP_MAX/2) + { + challengesmenu.extradata[id].flip = 1 + (TILEFLIP_MAX/2); + } + } + return true; } } diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index fa5eb661c..948e9178a 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -109,6 +109,11 @@ static void M_ProfileEditApply(void) if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS) { PR_ApplyProfileToggles(optionsmenu.profilen, belongsto); + if (gamestate == GS_MENU) + { + // Safe to apply skin, etc here. + PR_ApplyProfileLight(optionsmenu.profilen, belongsto); + } } // Reapply player 1's real profile ID. diff --git a/src/menus/play-char-select.c b/src/menus/play-char-select.c index 27f2c8494..1a055a7b5 100644 --- a/src/menus/play-char-select.c +++ b/src/menus/play-char-select.c @@ -304,47 +304,6 @@ void M_CharacterSelectInit(void) memset(setup_explosions, 0, sizeof(setup_explosions)); setup_animcounter = 0; - for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) - { - // Default to no follower / match colour. - setup_player[i].followern = -1; - setup_player[i].followercategory = -1; - setup_player[i].followercolor = SKINCOLOR_NONE; - - setup_player[i].profilen_slide.start = 0; - setup_player[i].profilen_slide.dist = 0; - - // If we're on prpfile select, skip straight to CSSTEP_CHARS - // do the same if we're midgame, but make sure to consider splitscreen properly. - if (optionsmenu.profile && i == 0) - { - setup_player[i].profilen = optionsmenu.profilen; - //PR_ApplyProfileLight(setup_player[i].profilen, 0); - M_SetupProfileGridPos(&setup_player[i]); - setup_player[i].mdepth = CSSTEP_CHARS; - } - else - { - // Set default selected profile to the last used profile for each player: - // (Make sure we don't overshoot it somehow if we deleted profiles or whatnot) - setup_player[i].profilen = min(cv_lastprofile[i].value, PR_GetNumProfiles()); - - if (gamestate != GS_MENU && i <= splitscreen) - { - M_SetupMidGameGridPos(&setup_player[i], i); - setup_player[i].mdepth = CSSTEP_CHARS; - } - else - { - // Un-set devices - G_SetDeviceForPlayer(i, -1); -#ifdef CHARSELECT_DEVICEDEBUG - CONS_Printf("M_CharacterSelectInit: Device for %d set to %d\n", i, -1); -#endif - } - } - } - for (i = 0; i < numskins; i++) { UINT8 x = skins[i]->kartspeed-1; @@ -391,6 +350,47 @@ void M_CharacterSelectInit(void) } setup_page = 0; + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + // Default to no follower / match colour. + setup_player[i].followern = -1; + setup_player[i].followercategory = -1; + setup_player[i].followercolor = SKINCOLOR_NONE; + + setup_player[i].profilen_slide.start = 0; + setup_player[i].profilen_slide.dist = 0; + + // If we're on prpfile select, skip straight to CSSTEP_CHARS + // do the same if we're midgame, but make sure to consider splitscreen properly. + if (optionsmenu.profile && i == 0) + { + setup_player[i].profilen = optionsmenu.profilen; + //PR_ApplyProfileLight(setup_player[i].profilen, 0); + M_SetupProfileGridPos(&setup_player[i]); + setup_player[i].mdepth = CSSTEP_CHARS; + } + else + { + // Set default selected profile to the last used profile for each player: + // (Make sure we don't overshoot it somehow if we deleted profiles or whatnot) + setup_player[i].profilen = min(cv_lastprofile[i].value, PR_GetNumProfiles()); + + if (gamestate != GS_MENU && i <= splitscreen) + { + M_SetupMidGameGridPos(&setup_player[i], i); + setup_player[i].mdepth = CSSTEP_CHARS; + } + else + { + // Un-set devices + G_SetDeviceForPlayer(i, -1); +#ifdef CHARSELECT_DEVICEDEBUG + CONS_Printf("M_CharacterSelectInit: Device for %d set to %d\n", i, -1); +#endif + } + } + } } @@ -777,7 +777,7 @@ static boolean M_HandleBeginningColors(setup_player_t *p) static void M_HandleBeginningFollowers(setup_player_t *p) { - if (setup_numfollowercategories == 0) + if (horngoner || setup_numfollowercategories == 0) { p->followern = -1; M_HandlePlayerFinalise(p); @@ -1392,7 +1392,9 @@ static void M_MPConfirmCharacterSelection(void) CV_StealthSetValue(&cv_playercolor[i], col); // follower - if (setup_player[i].followern < 0) + if (horngoner) + ; + else if (setup_player[i].followern < 0) CV_StealthSet(&cv_follower[i], "None"); else CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name); @@ -1457,9 +1459,12 @@ void M_CharacterSelectTick(void) strcpy(optionsmenu.profile->skinname, skins[setup_player[0].skin]->name); optionsmenu.profile->color = setup_player[0].color; - // save follower - strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].name); - optionsmenu.profile->followercolor = setup_player[0].followercolor; + if (!horngoner) // so you don't lose your choice after annoying the game + { + // save follower + strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].name); + optionsmenu.profile->followercolor = setup_player[0].followercolor; + } // reset setup_player memset(setup_player, 0, sizeof(setup_player)); @@ -1475,7 +1480,9 @@ void M_CharacterSelectTick(void) CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin]->name); CV_StealthSetValue(&cv_playercolor[i], setup_player[i].color); - if (setup_player[i].followern < 0) + if (horngoner) + ; + else if (setup_player[i].followern < 0) CV_StealthSet(&cv_follower[i], "None"); else CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 426560456..d62ce2b15 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -8099,7 +8099,7 @@ static void P_InitPlayers(void) skin = 0; } - if (netgame) + if (netgame || horngoner) ; // shouldn't happen but at least attempt to sync if it does else for (i = 0; i < numfollowers; i++) { diff --git a/src/y_inter.cpp b/src/y_inter.cpp index a7668b1b2..a096b71f9 100644 --- a/src/y_inter.cpp +++ b/src/y_inter.cpp @@ -1615,7 +1615,7 @@ void Y_RoundQueueDrawer(y_data_t *standings, INT32 offset, boolean doanimations, x - 9, y - 13, (baseflags|((menuqueue.entries[i].encore) ? V_FLIP : 0)), menuqueue.entries[i].mapnum, - NULL + NULL, FRACUNIT, 1 ); x += 24;