Merge pull request #19 from WumboSpasm/followers

Follower improvements. Thanks Wumbo!
This commit is contained in:
NepDisk 2024-09-12 23:17:27 -04:00 committed by GitHub
commit 6816173d98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 124 additions and 35 deletions

View file

@ -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,17 +855,20 @@ 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.
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+2].value = 0;
Color_cons_t[MAXSKINCOLORS].strvalue = Followercolor_cons_t[MAXSKINCOLORS+2].strvalue = NULL;
@ -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)

View file

@ -3684,7 +3684,7 @@ void readfollower(MYFILE *f)
followers[numfollowers].horzlag = 3*FRACUNIT;
followers[numfollowers].vertlag = 6*FRACUNIT;
followers[numfollowers].anglelag = 8*FRACUNIT;
followers[numfollowers].bobspeed = TICRATE*2;
followers[numfollowers].bobspeed = (TICRATE*2)*FRACUNIT;
followers[numfollowers].bobamp = 4*FRACUNIT;
followers[numfollowers].hitconfirmtime = TICRATE;
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
@ -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);
}

View file

@ -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");

View file

@ -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)

View file

@ -9404,7 +9404,7 @@ static state_t *multi_state;
static UINT8 multi_spr2;
// used for follower display on player setup menu
static INT32 follower_tics;
static fixed_t follower_tics;
static UINT32 follower_frame; // used for FF_ANIMATE garbo
static state_t *follower_state;
@ -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
@ -9679,14 +9680,15 @@ static void M_DrawSetupMultiPlayerMenu(void)
{
// animate the follower
if (--follower_tics <= 0)
follower_tics -= renderdeltatics;
if (follower_tics <= 0)
{
// FF_ANIMATE; cycle through FRAMES and get back afterwards. This will be prominent amongst followers hence why it's being supported here.
if (follower_state->frame & FF_ANIMATE)
{
follower_frame++;
follower_tics = follower_state->var2;
follower_tics = follower_state->var2*FRACUNIT;
if (follower_frame > (follower_state->frame & FF_FRAMEMASK) + follower_state->var1) // that's how it works, right?
follower_frame = follower_state->frame & FF_FRAMEMASK;
}
@ -9695,9 +9697,7 @@ static void M_DrawSetupMultiPlayerMenu(void)
st = follower_state->nextstate;
if (st != S_NULL)
follower_state = &states[st];
follower_tics = follower_state->tics;
if (follower_tics == -1)
follower_tics = 15; // er, what?
follower_tics = follower_state->tics*FRACUNIT;
// get spritedef:
follower_frame = follower_state->frame & FF_FRAMEMASK;
}
@ -9713,20 +9713,30 @@ 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));
tic_t bobspeed = fl.bobspeed;
if (fl.mode == FOLLOWERMODE_GROUND)
bobspeed = FixedDiv(bobspeed, fl.bobamp / 6); // Rough approximation of bounce speed
UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, setupm_fakecolor->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);
// smooth floating, totally not stolen from rocket sneakers.
fixed_t sine = FixedMul(fl.bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, bobspeed) * followertimer)>>ANGLETOFINESHIFT) & FINEMASK));
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...?
INT32 x = (mx+65)*FRACUNIT;
INT32 y = ((my+100)*FRACUNIT);
if (fl.mode == FOLLOWERMODE_GROUND)
y += 40*FRACUNIT - abs(sine) * 2; // Bounce animation
else
y += sine;
V_DrawFixedPatch(x, y, fl.scale, flags, patch, colormap);
Z_Free(colormap);
}
}
@ -9748,9 +9758,9 @@ static void M_GetFollowerState(void)
follower_state = &states[followers[setupm_fakefollower].followstate];
if (follower_state->frame & FF_ANIMATE)
follower_tics = follower_state->var2; // support for FF_ANIMATE
follower_tics = follower_state->var2*FRACUNIT; // support for FF_ANIMATE
else
follower_tics = follower_state->tics;
follower_tics = follower_state->tics*FRACUNIT;
follower_frame = follower_state->frame & FF_FRAMEMASK;
}
@ -9930,6 +9940,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 +9984,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 +10028,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 +10072,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;