diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 396478520..ace69eff1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -316,10 +316,10 @@ consvar_t cv_follower[MAXSPLITSCREENPLAYERS] = { // player's follower colors... Also saved... consvar_t cv_followercolor[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("followercolor", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange), - CVAR_INIT ("followercolor2", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange), - CVAR_INIT ("followercolor3", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange), - CVAR_INIT ("followercolor4", "1", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange) + CVAR_INIT ("followercolor", "Default", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange), + CVAR_INIT ("followercolor2", "Default", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange), + CVAR_INIT ("followercolor3", "Default", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange), + CVAR_INIT ("followercolor4", "Default", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange) }; consvar_t cv_skipmapcheck = CVAR_INIT ("skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL); @@ -855,20 +855,23 @@ void D_RegisterClientCommands(void) Color_cons_t[i].strvalue = skincolors[i].name; } - for (i = 2; i < MAXSKINCOLORS; i++) + for (i = 3; i < MAXSKINCOLORS; i++) { - Followercolor_cons_t[i].value = i-2; - Followercolor_cons_t[i].strvalue = skincolors[i-2].name; + Followercolor_cons_t[i].value = i-3; + Followercolor_cons_t[i].strvalue = skincolors[i-3].name; } - Followercolor_cons_t[1].value = FOLLOWERCOLOR_MATCH; - Followercolor_cons_t[1].strvalue = "Match"; // Add "Match" option, which will make the follower color match the player's + Followercolor_cons_t[2].value = FOLLOWERCOLOR_MATCH; + Followercolor_cons_t[2].strvalue = "Match"; // Add "Match" option, which will make the follower color match the player's - Followercolor_cons_t[0].value = FOLLOWERCOLOR_OPPOSITE; - Followercolor_cons_t[0].strvalue = "Opposite"; // Add "Opposite" option, ...which is like "Match", but for coloropposite. + Followercolor_cons_t[1].value = FOLLOWERCOLOR_OPPOSITE; + Followercolor_cons_t[1].strvalue = "Opposite"; // Add "Opposite" option, ...which is like "Match", but for coloropposite. - Color_cons_t[MAXSKINCOLORS].value = Followercolor_cons_t[MAXSKINCOLORS+2].value = 0; - Color_cons_t[MAXSKINCOLORS].strvalue = Followercolor_cons_t[MAXSKINCOLORS+2].strvalue = NULL; + Followercolor_cons_t[0].value = FOLLOWERCOLOR_DEFAULT; + Followercolor_cons_t[0].strvalue = "Default"; // Add "Default" option, which will use the default color of the selected follower + + Color_cons_t[MAXSKINCOLORS].value = Followercolor_cons_t[MAXSKINCOLORS+3].value = 0; + Color_cons_t[MAXSKINCOLORS].strvalue = Followercolor_cons_t[MAXSKINCOLORS+3].strvalue = NULL; // Set default player names // Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well @@ -1516,7 +1519,7 @@ static void SendNameAndColor(UINT8 n) // ditto for follower colour: if (!cv_followercolor[n].value) - CV_StealthSet(&cv_followercolor[n], "Match"); // set it to "Match". I don't care about your stupidity! + CV_StealthSet(&cv_followercolor[n], "Default"); // set it to "Default". I don't care about your stupidity! // so like, this is sent before we even use anything like cvars or w/e so it's possible that follower is set to a pretty yikes value, so let's fix that before we send garbage that could crash the game: if (cv_follower[n].value >= numfollowers || cv_follower[n].value < -1) diff --git a/src/deh_soc.c b/src/deh_soc.c index a16ff32d6..f6a917afe 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3735,7 +3735,15 @@ void readfollower(MYFILE *f) } else if (fastcmp(word, "DEFAULTCOLOR")) { - followers[numfollowers].defaultcolor = get_number(word2); + if (word2) + strupr(word2); + + if (fastcmp(word2, "MATCH")) + followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH; + else if (fastcmp(word2, "OPPOSITE")) + followers[numfollowers].defaultcolor = FOLLOWERCOLOR_OPPOSITE; + else + followers[numfollowers].defaultcolor = get_skincolor(word2); } else if (fastcmp(word, "SCALE")) { @@ -3894,9 +3902,11 @@ if ((signed)followers[numfollowers].field < threshold) \ #undef FALLBACK // Special case for color I suppose - if (followers[numfollowers].defaultcolor > (unsigned)(numskincolors-1)) + if (followers[numfollowers].defaultcolor > (unsigned)(numskincolors-1) + && followers[numfollowers].defaultcolor != FOLLOWERCOLOR_MATCH + && followers[numfollowers].defaultcolor != FOLLOWERCOLOR_OPPOSITE) { - followers[numfollowers].defaultcolor = SKINCOLOR_GREEN; + followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH; deh_warning("Follower \'%s\': Value for 'color' should be between 1 and %d.\n", dname, numskincolors-1); } diff --git a/src/k_follower.c b/src/k_follower.c index 53c211458..d9facdcf6 100644 --- a/src/k_follower.c +++ b/src/k_follower.c @@ -175,6 +175,43 @@ static void K_SetFollowerState(mobj_t *f, statenum_t state) } } +/*-------------------------------------------------- + UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin) + + See header file for description. +--------------------------------------------------*/ +UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin) +{ + if (followercolor == SKINCOLOR_NONE && follower != NULL) // "Default" + { + followercolor = follower->defaultcolor; + } + + if (followercolor > SKINCOLOR_NONE && followercolor < numskincolors) // bog standard + { + return followercolor; + } + + if (playercolor == SKINCOLOR_NONE) // get default color + { + if (playerskin == NULL) + { + // Nothing from this line down is valid if playerskin is invalid, just guess Eggman? + playerskin = &skins[0]; + } + + playercolor = playerskin->prefcolor; + } + + if (followercolor == FOLLOWERCOLOR_OPPOSITE) // "Opposite" + { + return skincolors[playercolor].invcolor; + } + + // "Match" + return playercolor; +} + /*-------------------------------------------------- static void K_UpdateFollowerState(mobj_t *f, statenum_t state, followerstate_t type) @@ -312,15 +349,20 @@ void K_HandleFollower(player_t *player) color = skincolors[player->skincolor].invcolor; break; + case FOLLOWERCOLOR_DEFAULT: // "Default" + color = fl.defaultcolor; + break; + default: color = player->followercolor; - if (color == 0 || color > MAXSKINCOLORS+2) // Make sure this isn't garbage - { - color = player->skincolor; // "Match" as fallback. - } break; } + if (color == 0 || color > MAXSKINCOLORS+2) // Make sure this isn't garbage + { + color = player->skincolor; // "Match" as fallback. + } + if (player->follower == NULL) // follower doesn't exist / isn't valid { //CONS_Printf("Spawning follower...\n"); diff --git a/src/k_follower.h b/src/k_follower.h index 0466bdfac..77f1c9377 100644 --- a/src/k_follower.h +++ b/src/k_follower.h @@ -19,6 +19,7 @@ #define FOLLOWERCOLOR_MATCH UINT16_MAX #define FOLLOWERCOLOR_OPPOSITE (UINT16_MAX-1) +#define FOLLOWERCOLOR_DEFAULT 0 extern CV_PossibleValue_t Followercolor_cons_t[]; // follower colours table, not a duplicate because of the "Match" option. @@ -136,6 +137,25 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname); void K_SetFollowerByNum(INT32 playernum, INT32 skinnum); +/*-------------------------------------------------- + UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin) + + Updates a player's follower pointer, and does + its positioning and animations. + + Input Arguments:- + followercolor - The raw color setting for the follower + follower - Follower struct to retrieve default color from. Can be NULL + playercolor - The player's associated colour, for reference + playerskin - Skin struct to retrieve default color from. Can be NULL + + Return:- + The resultant skincolor enum for the follower +--------------------------------------------------*/ + +UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin); + + /*-------------------------------------------------- void K_HandleFollower(player_t *player) diff --git a/src/m_menu.c b/src/m_menu.c index 53355c371..734f4acf7 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9416,6 +9416,7 @@ static consvar_t *setupm_cvskin; static consvar_t *setupm_cvcolor; static consvar_t *setupm_cvname; static consvar_t *setupm_cvfollower; +static consvar_t *setupm_cvfollowercolor; static INT32 setupm_fakeskin; static menucolor_t *setupm_fakecolor; static INT32 setupm_fakefollower; // -1 is for none, our followers start at 0 @@ -9713,19 +9714,17 @@ static void M_DrawSetupMultiPlayerMenu(void) if (sprframe->flip & 2) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! - // @TODO: Reminder that followers on the menu right now do NOT support the 'followercolor' command, considering this whole menu is getting remade anyway, I see no point in incorporating it in right now. - // draw follower sprite if (setupm_fakecolor->color) // inverse should never happen { - // Fake the follower's in game appearance by now also applying some of its variables! coolio, eh? follower_t fl = followers[setupm_fakefollower]; // shortcut for our sanity // smooth floating, totally not stolen from rocket sneakers. fixed_t sine = FixedMul(fl.bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, fl.bobspeed) * followertimer)>>ANGLETOFINESHIFT) & FINEMASK)); - UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, setupm_fakecolor->color, 0); // why does GTC_MENUCACHE not work here...? + UINT16 color = K_GetEffectiveFollowerColor(setupm_cvfollowercolor->value, &fl, setupm_fakecolor->color, &skins[setupm_fakeskin]); + UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, color, 0); // why does GTC_MENUCACHE not work here...? V_DrawFixedPatch((mx+65)*FRACUNIT, ((my+131)*FRACUNIT)-fl.zoffs+sine, fl.scale, flags, patch, colormap); Z_Free(colormap); } @@ -9930,6 +9929,7 @@ static void M_SetupMultiPlayer(INT32 choice) setupm_cvcolor = &cv_playercolor[0]; setupm_cvname = &cv_playername[0]; setupm_cvfollower = &cv_follower[0]; + setupm_cvfollowercolor = &cv_followercolor[0]; setupm_fakefollower = setupm_cvfollower->value; @@ -9973,6 +9973,7 @@ static void M_SetupMultiPlayer2(INT32 choice) setupm_cvcolor = &cv_playercolor[1]; setupm_cvname = &cv_playername[1]; setupm_cvfollower = &cv_follower[1]; + setupm_cvfollowercolor = &cv_followercolor[1]; setupm_fakefollower = setupm_cvfollower->value; @@ -10016,6 +10017,7 @@ static void M_SetupMultiPlayer3(INT32 choice) setupm_cvcolor = &cv_playercolor[2]; setupm_cvname = &cv_playername[2]; setupm_cvfollower = &cv_follower[2]; + setupm_cvfollowercolor = &cv_followercolor[2]; setupm_fakefollower = setupm_cvfollower->value; @@ -10059,6 +10061,7 @@ static void M_SetupMultiPlayer4(INT32 choice) setupm_cvcolor = &cv_playercolor[3]; setupm_cvname = &cv_playername[3]; setupm_cvfollower = &cv_follower[3]; + setupm_cvfollowercolor = &cv_followercolor[3]; setupm_fakefollower = setupm_cvfollower->value;