mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'follower-fixes' into 'master'
Followers and Character Select improvements See merge request KartKrew/Kart!764
This commit is contained in:
commit
e8a6aa7540
12 changed files with 632 additions and 395 deletions
|
|
@ -2528,6 +2528,11 @@ void CL_ClearPlayer(INT32 playernum)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (players[playernum].follower)
|
||||
{
|
||||
K_RemoveFollower(&players[playernum]);
|
||||
}
|
||||
|
||||
if (players[playernum].mo)
|
||||
{
|
||||
P_RemoveMobj(players[playernum].mo);
|
||||
|
|
|
|||
266
src/d_netcmd.c
266
src/d_netcmd.c
|
|
@ -295,10 +295,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", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor_OnChange),
|
||||
CVAR_INIT ("followercolor2", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor2_OnChange),
|
||||
CVAR_INIT ("followercolor3", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor3_OnChange),
|
||||
CVAR_INIT ("followercolor4", "Match", CV_SAVE|CV_CALL|CV_NOINIT, Followercolor_cons_t, Followercolor4_OnChange)
|
||||
};
|
||||
|
||||
// last selected profile, unaccessible cvar only set internally but is saved.
|
||||
|
|
@ -831,27 +831,6 @@ void D_RegisterClientCommands(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||
{
|
||||
Color_cons_t[i].value = i;
|
||||
Color_cons_t[i].strvalue = skincolors[i].name;
|
||||
}
|
||||
|
||||
for (i = 2; i < MAXSKINCOLORS; i++)
|
||||
{
|
||||
Followercolor_cons_t[i].value = i-2;
|
||||
Followercolor_cons_t[i].strvalue = skincolors[i-2].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[0].value = FOLLOWERCOLOR_OPPOSITE;
|
||||
Followercolor_cons_t[0].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;
|
||||
|
||||
// Set default player names
|
||||
// Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -1493,7 +1472,7 @@ static void SendNameAndColor(UINT8 n)
|
|||
const INT32 playernum = g_localplayers[n];
|
||||
player_t *player = &players[playernum];
|
||||
|
||||
char buf[MAXPLAYERNAME+9];
|
||||
char buf[MAXPLAYERNAME+12];
|
||||
char *p;
|
||||
|
||||
if (splitscreen < n)
|
||||
|
|
@ -1524,14 +1503,11 @@ static void SendNameAndColor(UINT8 n)
|
|||
if (!cv_followercolor[n].value)
|
||||
CV_StealthSet(&cv_followercolor[n], "Match"); // set it to "Match". 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)
|
||||
CV_StealthSet(&cv_follower[n], "-1");
|
||||
|
||||
if (!strcmp(cv_playername[n].string, player_names[playernum])
|
||||
&& cv_playercolor[n].value == player->skincolor
|
||||
&& !strcmp(cv_skin[n].string, skins[player->skin].name)
|
||||
&& cv_follower[n].value == player->followerskin
|
||||
&& !stricmp(cv_skin[n].string, skins[player->skin].name)
|
||||
&& !stricmp(cv_follower[n].string,
|
||||
(player->followerskin < 0 ? "None" : followers[player->followerskin].name))
|
||||
&& cv_followercolor[n].value == player->followercolor)
|
||||
return;
|
||||
|
||||
|
|
@ -1553,31 +1529,28 @@ static void SendNameAndColor(UINT8 n)
|
|||
|
||||
K_KartResetPlayerColor(player);
|
||||
|
||||
// Update follower for local games:
|
||||
if (cv_follower[n].value >= -1 && cv_follower[n].value != player->followerskin)
|
||||
K_SetFollowerByNum(playernum, cv_follower[n].value);
|
||||
|
||||
player->followercolor = cv_followercolor[n].value;
|
||||
|
||||
if (metalrecording && n == 0)
|
||||
{ // Starring Metal Sonic as themselves, obviously.
|
||||
SetPlayerSkinByNum(playernum, 5);
|
||||
CV_StealthSet(&cv_skin[n], skins[5].name);
|
||||
}
|
||||
else if ((foundskin = R_SkinAvailable(cv_skin[n].string)) != -1 && R_SkinUsable(playernum, foundskin))
|
||||
if ((foundskin = R_SkinAvailable(cv_skin[n].string)) != -1 && R_SkinUsable(playernum, foundskin))
|
||||
{
|
||||
cv_skin[n].value = foundskin;
|
||||
SetPlayerSkin(playernum, cv_skin[n].string);
|
||||
CV_StealthSet(&cv_skin[n], skins[cv_skin[n].value].name);
|
||||
CV_StealthSet(&cv_skin[n], skins[foundskin].name);
|
||||
cv_skin[n].value = foundskin;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv_skin[n].value = players[playernum].skin;
|
||||
CV_StealthSet(&cv_skin[n], skins[player->skin].name);
|
||||
cv_skin[n].value = player->skin;
|
||||
// will always be same as current
|
||||
SetPlayerSkin(playernum, cv_skin[n].string);
|
||||
}
|
||||
|
||||
player->followercolor = cv_followercolor[n].value;
|
||||
|
||||
// Update follower for local games:
|
||||
foundskin = K_FollowerAvailable(cv_follower[n].string);
|
||||
CV_StealthSet(&cv_follower[n], (foundskin == -1) ? "None" : followers[foundskin].name);
|
||||
cv_follower[n].value = foundskin;
|
||||
K_SetFollowerByNum(playernum, foundskin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1607,12 +1580,20 @@ static void SendNameAndColor(UINT8 n)
|
|||
cv_skin[n].value = 0;
|
||||
}
|
||||
|
||||
cv_follower[n].value = K_FollowerAvailable(cv_follower[n].string);
|
||||
if (cv_follower[n].value < 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[n], "None");
|
||||
cv_follower[n].value = -1;
|
||||
}
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME);
|
||||
WRITEUINT32(p, (UINT32)player->availabilities);
|
||||
WRITEUINT16(p, (UINT16)cv_playercolor[n].value);
|
||||
WRITEUINT8(p, (UINT8)cv_skin[n].value);
|
||||
WRITESINT8(p, (SINT8)cv_follower[n].value);
|
||||
WRITEINT16(p, (INT16)cv_follower[n].value);
|
||||
//CONS_Printf("Sending follower id %d\n", (INT16)cv_follower[n].value);
|
||||
WRITEUINT16(p, (UINT16)cv_followercolor[n].value);
|
||||
|
||||
SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf);
|
||||
|
|
@ -1624,7 +1605,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
char name[MAXPLAYERNAME+1];
|
||||
UINT16 color, followercolor;
|
||||
UINT8 skin;
|
||||
SINT8 follower;
|
||||
INT16 follower;
|
||||
SINT8 localplayer = -1;
|
||||
UINT8 i;
|
||||
|
||||
|
|
@ -1653,7 +1634,8 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
p->availabilities = READUINT32(*cp);
|
||||
color = READUINT16(*cp);
|
||||
skin = READUINT8(*cp);
|
||||
follower = READSINT8(*cp);
|
||||
follower = READINT16(*cp);
|
||||
//CONS_Printf("Recieved follower id %d\n", follower);
|
||||
followercolor = READUINT16(*cp);
|
||||
|
||||
// set name
|
||||
|
|
@ -6079,6 +6061,7 @@ static void Name_OnChange(void)
|
|||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
|
||||
CV_StealthSet(&cv_playername[0], player_names[consoleplayer]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
SendNameAndColor(0);
|
||||
|
|
@ -6119,207 +6102,56 @@ static void Name4_OnChange(void)
|
|||
}
|
||||
|
||||
// sends the follower change for players
|
||||
static void Follower_OnChange(void)
|
||||
static void FollowerAny_OnChange(UINT8 pnum)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[0].string);
|
||||
strcpy(cpy, cv_follower[0].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[0], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(0);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[0], str);
|
||||
cv_follower[0].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(0);
|
||||
SendNameAndColor(pnum);
|
||||
}
|
||||
|
||||
// sends the follower change for players
|
||||
static void Follower_OnChange(void)
|
||||
{
|
||||
FollowerAny_OnChange(0);
|
||||
}
|
||||
|
||||
// About the same as Color_OnChange but for followers.
|
||||
static void Followercolor_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(consoleplayer))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(0);
|
||||
}
|
||||
FollowerAny_OnChange(0);
|
||||
}
|
||||
|
||||
// repeat for the 3 other players
|
||||
|
||||
static void Follower2_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[1].string);
|
||||
strcpy(cpy, cv_follower[1].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[1], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(1);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[1], str);
|
||||
cv_follower[1].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(1);
|
||||
FollowerAny_OnChange(1);
|
||||
}
|
||||
|
||||
static void Followercolor2_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[1]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(1);
|
||||
}
|
||||
FollowerAny_OnChange(1);
|
||||
}
|
||||
|
||||
static void Follower3_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[2].string);
|
||||
strcpy(cpy, cv_follower[2].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[2], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(2);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[2], str);
|
||||
cv_follower[2].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(2);
|
||||
FollowerAny_OnChange(2);
|
||||
}
|
||||
|
||||
static void Followercolor3_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[2]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(2);
|
||||
}
|
||||
FollowerAny_OnChange(2);
|
||||
}
|
||||
|
||||
static void Follower4_OnChange(void)
|
||||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
strcpy(str, cv_follower[3].string);
|
||||
strcpy(cpy, cv_follower[3].string);
|
||||
strlwr(str);
|
||||
if (stricmp(cpy,"0") !=0 && !atoi(cpy)) // yep, that's a string alright...
|
||||
{
|
||||
if (stricmp(cpy, "None") == 0)
|
||||
{
|
||||
CV_StealthSet(&cv_follower[3], "-1");
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(3);
|
||||
return;
|
||||
}
|
||||
|
||||
num = K_FollowerAvailable(str);
|
||||
|
||||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
CV_StealthSet(&cv_follower[3], str);
|
||||
cv_follower[3].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
return; // don't send anything there.
|
||||
|
||||
SendNameAndColor(3);
|
||||
FollowerAny_OnChange(3);
|
||||
}
|
||||
|
||||
static void Followercolor4_OnChange(void)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want if you aren't in the game or don't have a follower.
|
||||
|
||||
if (!P_PlayerMoving(g_localplayers[3]))
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(3);
|
||||
}
|
||||
FollowerAny_OnChange(3);
|
||||
}
|
||||
|
||||
/** Sends a skin change for the console player, unless that player is moving. Also forces them to spectate if the change is done during gameplay
|
||||
|
|
@ -6339,7 +6171,9 @@ static void Skin_OnChange(void)
|
|||
}
|
||||
|
||||
if (CanChangeSkinWhilePlaying(consoleplayer))
|
||||
{
|
||||
SendNameAndColor(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
|
|
|
|||
138
src/deh_soc.c
138
src/deh_soc.c
|
|
@ -3130,7 +3130,7 @@ void readcupheader(MYFILE *f, cupheader_t *cup)
|
|||
void readfollower(MYFILE *f)
|
||||
{
|
||||
char *s;
|
||||
char *word, *word2, dname[SKINNAMESIZE+1];
|
||||
char *word, *word2;
|
||||
char *tmp;
|
||||
char testname[SKINNAMESIZE+1];
|
||||
|
||||
|
|
@ -3139,10 +3139,9 @@ void readfollower(MYFILE *f)
|
|||
INT32 res;
|
||||
INT32 i;
|
||||
|
||||
if (numfollowers > MAXSKINS)
|
||||
if (numfollowers >= MAXSKINS)
|
||||
{
|
||||
deh_warning("Error: Too many followers, cannot add anymore.\n");
|
||||
return;
|
||||
I_Error("Out of Followers\nLoad less addons to fix this.");
|
||||
}
|
||||
|
||||
s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
@ -3161,8 +3160,9 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].bobspeed = TICRATE*2;
|
||||
followers[numfollowers].bobamp = 4*FRACUNIT;
|
||||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
|
||||
strcpy(followers[numfollowers].icon, "M_NORANK");
|
||||
followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH;
|
||||
followers[numfollowers].category = UINT8_MAX;
|
||||
strcpy(followers[numfollowers].icon, "MISSING");
|
||||
|
||||
do
|
||||
{
|
||||
|
|
@ -3201,6 +3201,23 @@ void readfollower(MYFILE *f)
|
|||
strcpy(followers[numfollowers].icon, word2);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "CATEGORY"))
|
||||
{
|
||||
INT32 j;
|
||||
for (j = 0; j < numfollowercategories; j++)
|
||||
{
|
||||
if (!stricmp(followercategories[j].name, word2))
|
||||
{
|
||||
followers[numfollowers].category = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == numfollowercategories)
|
||||
{
|
||||
deh_warning("Follower %d: unknown follower category '%s'", numfollowers, word2);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "MODE"))
|
||||
{
|
||||
if (word2)
|
||||
|
|
@ -3215,7 +3232,20 @@ void readfollower(MYFILE *f)
|
|||
}
|
||||
else if (fastcmp(word, "DEFAULTCOLOR"))
|
||||
{
|
||||
followers[numfollowers].defaultcolor = get_number(word2);
|
||||
INT32 j;
|
||||
for (j = 0; j < numskincolors +2; j++) // +2 because of Match and Opposite
|
||||
{
|
||||
if (!stricmp(Followercolor_cons_t[j].strvalue, word2))
|
||||
{
|
||||
followers[numfollowers].defaultcolor = Followercolor_cons_t[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == numskincolors+2)
|
||||
{
|
||||
deh_warning("Follower %d: unknown follower color '%s'", numfollowers, word2);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "SCALE"))
|
||||
{
|
||||
|
|
@ -3318,10 +3348,6 @@ void readfollower(MYFILE *f)
|
|||
// set skin name (this is just the follower's name in lowercases):
|
||||
// but before we do, let's... actually check if another follower isn't doing the same shit...
|
||||
|
||||
strcpy(testname, followers[numfollowers].name);
|
||||
|
||||
// lower testname for skin checks...
|
||||
strlwr(testname);
|
||||
res = K_FollowerAvailable(testname);
|
||||
if (res > -1) // yikes, someone else has stolen our name already
|
||||
{
|
||||
|
|
@ -3333,8 +3359,7 @@ void readfollower(MYFILE *f)
|
|||
// in that case, we'll be very lazy and copy numfollowers to the end of our skin name.
|
||||
}
|
||||
|
||||
strcpy(followers[numfollowers].skinname, testname);
|
||||
strcpy(dname, followers[numfollowers].skinname); // display name, just used for printing succesful stuff or errors later down the line.
|
||||
strcpy(testname, followers[numfollowers].name);
|
||||
|
||||
// now that the skin name is ready, post process the actual name to turn the underscores into spaces!
|
||||
for (i = 0; followers[numfollowers].name[i]; i++)
|
||||
|
|
@ -3349,14 +3374,14 @@ void readfollower(MYFILE *f)
|
|||
if (followers[numfollowers].mode < FOLLOWERMODE_FLOAT || followers[numfollowers].mode >= FOLLOWERMODE__MAX)
|
||||
{
|
||||
followers[numfollowers].mode = FOLLOWERMODE_FLOAT;
|
||||
deh_warning("Follower '%s': Value for 'mode' should be between %d and %d.", dname, FOLLOWERMODE_FLOAT, FOLLOWERMODE__MAX-1);
|
||||
deh_warning("Follower '%s': Value for 'mode' should be between %d and %d.", testname, FOLLOWERMODE_FLOAT, FOLLOWERMODE__MAX-1);
|
||||
}
|
||||
|
||||
#define FALLBACK(field, field2, threshold, set) \
|
||||
if ((signed)followers[numfollowers].field < threshold) \
|
||||
{ \
|
||||
followers[numfollowers].field = set; \
|
||||
deh_warning("Follower '%s': Value for '%s' is too low! Minimum should be %d. Value was overwritten to %d.", dname, field2, threshold, set); \
|
||||
deh_warning("Follower '%s': Value for '%s' is too low! Minimum should be %d. Value was overwritten to %d.", testname, field2, threshold, set); \
|
||||
} \
|
||||
|
||||
FALLBACK(dist, "DIST", 0, 0);
|
||||
|
|
@ -3373,13 +3398,6 @@ if ((signed)followers[numfollowers].field < threshold) \
|
|||
|
||||
#undef FALLBACK
|
||||
|
||||
// Special case for color I suppose
|
||||
if (followers[numfollowers].defaultcolor > (unsigned)(numskincolors-1))
|
||||
{
|
||||
followers[numfollowers].defaultcolor = SKINCOLOR_GREEN;
|
||||
deh_warning("Follower \'%s\': Value for 'color' should be between 1 and %d.\n", dname, numskincolors-1);
|
||||
}
|
||||
|
||||
// also check if we forgot states. If we did, we will set any missing state to the follower's idlestate.
|
||||
// Print a warning in case we don't have a fallback and set the state to S_INVISIBLE (rather than S_NULL) if unavailable.
|
||||
|
||||
|
|
@ -3388,7 +3406,7 @@ if (!followers[numfollowers].field) \
|
|||
{ \
|
||||
followers[numfollowers].field = fallbackstate ? fallbackstate : S_INVISIBLE; \
|
||||
if (!fallbackstate) \
|
||||
deh_warning("Follower '%s' is missing state definition for '%s', no idlestate fallback was found", dname, field2); \
|
||||
deh_warning("Follower '%s' is missing state definition for '%s', no idlestate fallback was found", testname, field2); \
|
||||
} \
|
||||
|
||||
NOSTATE(idlestate, "IDLESTATE");
|
||||
|
|
@ -3399,11 +3417,83 @@ if (!followers[numfollowers].field) \
|
|||
NOSTATE(hitconfirmstate, "HITCONFIRMSTATE");
|
||||
#undef NOSTATE
|
||||
|
||||
CONS_Printf("Added follower '%s'\n", dname);
|
||||
CONS_Printf("Added follower '%s'\n", testname);
|
||||
if (followers[numfollowers].category < numfollowercategories)
|
||||
followercategories[followers[numfollowers].category].numincategory++;
|
||||
numfollowers++; // add 1 follower
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
void readfollowercategory(MYFILE *f)
|
||||
{
|
||||
char *s;
|
||||
char *word, *word2;
|
||||
char *tmp;
|
||||
|
||||
boolean nameset;
|
||||
|
||||
if (numfollowercategories == MAXFOLLOWERCATEGORIES)
|
||||
{
|
||||
I_Error("Out of Follower categories\nLoad less addons to fix this.");
|
||||
}
|
||||
|
||||
s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
||||
// Ready the default variables for followers. We will overwrite them as we go! We won't set the name or states RIGHT HERE as this is handled down instead.
|
||||
strcpy(followercategories[numfollowercategories].icon, "MISSING");
|
||||
followercategories[numfollowercategories].numincategory = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
tmp = strchr(s, '#');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
if (s == tmp)
|
||||
continue; // Skip comment lines, but don't break.
|
||||
|
||||
word = strtok(s, " ");
|
||||
if (word)
|
||||
strupr(word);
|
||||
else
|
||||
break;
|
||||
|
||||
word2 = strtok(NULL, " = ");
|
||||
|
||||
if (!word2)
|
||||
break;
|
||||
|
||||
if (word2[strlen(word2)-1] == '\n')
|
||||
word2[strlen(word2)-1] = '\0';
|
||||
|
||||
if (fastcmp(word, "NAME"))
|
||||
{
|
||||
strcpy(followercategories[numfollowercategories].name, word2);
|
||||
nameset = true;
|
||||
}
|
||||
else if (fastcmp(word, "ICON"))
|
||||
{
|
||||
strcpy(followercategories[numfollowercategories].icon, word2);
|
||||
nameset = true;
|
||||
}
|
||||
}
|
||||
} while (!myfeof(f)); // finish when the line is empty
|
||||
|
||||
if (!nameset)
|
||||
{
|
||||
// well this is problematic.
|
||||
strcpy(followercategories[numfollowercategories].name, va("Followercategory%d", numfollowercategories)); // this is lazy, so what
|
||||
}
|
||||
|
||||
CONS_Printf("Added follower category '%s'\n", followercategories[numfollowercategories].name);
|
||||
numfollowercategories++; // add 1 follower
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
void readweather(MYFILE *f, INT32 num)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ void clear_conditionsets(void);
|
|||
|
||||
void readcupheader(MYFILE *f, cupheader_t *cup);
|
||||
void readfollower(MYFILE *f);
|
||||
void readfollowercategory(MYFILE *f);
|
||||
preciptype_t get_precip(const char *word);
|
||||
void readweather(MYFILE *f, INT32 num);
|
||||
|
||||
|
|
|
|||
|
|
@ -235,6 +235,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
readfollower(f);
|
||||
continue;
|
||||
}
|
||||
else if (fastcmp(word, "FOLLOWERCATEGORY"))
|
||||
{
|
||||
// This is not a major mod.
|
||||
readfollowercategory(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
word2 = strtok(NULL, " ");
|
||||
if (word2) {
|
||||
|
|
|
|||
42
src/g_demo.c
42
src/g_demo.c
|
|
@ -313,11 +313,11 @@ void G_ReadDemoExtraData(void)
|
|||
demo_p += 16;
|
||||
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
|
||||
{
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, name))
|
||||
{
|
||||
players[p].followercolor = i;
|
||||
break;
|
||||
}
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, name))
|
||||
{
|
||||
players[p].followercolor = Followercolor_cons_t[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (extradata & DXD_PLAYSTATE)
|
||||
|
|
@ -407,7 +407,7 @@ void G_ReadDemoExtraData(void)
|
|||
|
||||
void G_WriteDemoExtraData(void)
|
||||
{
|
||||
INT32 i;
|
||||
INT32 i, j;
|
||||
char name[16];
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -453,13 +453,18 @@ void G_WriteDemoExtraData(void)
|
|||
if (players[i].followerskin == -1)
|
||||
strncpy(name, "None", 16);
|
||||
else
|
||||
strncpy(name, followers[players[i].followerskin].skinname, 16);
|
||||
strncpy(name, followers[players[i].followerskin].name, 16);
|
||||
M_Memcpy(demo_p, name, 16);
|
||||
demo_p += 16;
|
||||
|
||||
// write follower color
|
||||
memset(name, 0, 16);
|
||||
strncpy(name, Followercolor_cons_t[(UINT16)(players[i].followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
for (j = (numskincolors+2)-1; j > 0; j--)
|
||||
{
|
||||
if (Followercolor_cons_t[j].value == players[i].followercolor)
|
||||
break;
|
||||
}
|
||||
strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
M_Memcpy(demo_p,name,16);
|
||||
demo_p += 16;
|
||||
|
||||
|
|
@ -1951,7 +1956,7 @@ void G_RecordMetal(void)
|
|||
|
||||
void G_BeginRecording(void)
|
||||
{
|
||||
UINT8 i, p;
|
||||
UINT8 i, j, p;
|
||||
char name[MAXCOLORNAME+1];
|
||||
player_t *player = &players[consoleplayer];
|
||||
|
||||
|
|
@ -2088,7 +2093,7 @@ void G_BeginRecording(void)
|
|||
|
||||
memset(name, 0, 16);
|
||||
if (player->follower)
|
||||
strncpy(name, followers[player->followerskin].skinname, 16);
|
||||
strncpy(name, followers[player->followerskin].name, 16);
|
||||
else
|
||||
strncpy(name, "None", 16); // Say we don't have one, then.
|
||||
|
||||
|
|
@ -2097,7 +2102,12 @@ void G_BeginRecording(void)
|
|||
|
||||
// Save follower's colour
|
||||
memset(name, 0, 16);
|
||||
strncpy(name, Followercolor_cons_t[(UINT16)(player->followercolor+2)].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
for (j = (numskincolors+2)-1; j > 0; j--)
|
||||
{
|
||||
if (Followercolor_cons_t[j].value == players[i].followercolor)
|
||||
break;
|
||||
}
|
||||
strncpy(name, Followercolor_cons_t[j].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match"
|
||||
M_Memcpy(demo_p, name, 16);
|
||||
demo_p += 16;
|
||||
|
||||
|
|
@ -3073,11 +3083,11 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_p += 16;
|
||||
for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite
|
||||
{
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, color))
|
||||
{
|
||||
players[p].followercolor = i;
|
||||
break;
|
||||
}
|
||||
if (!stricmp(Followercolor_cons_t[i].strvalue, color))
|
||||
{
|
||||
players[p].followercolor = Followercolor_cons_t[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Score, since Kart uses this to determine where you start on the map
|
||||
|
|
|
|||
18
src/g_game.c
18
src/g_game.c
|
|
@ -4263,8 +4263,26 @@ void G_EndGame(void)
|
|||
// Sets a tad of default info we need.
|
||||
void G_LoadGameSettings(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
// initialize free sfx slots for skin sounds
|
||||
S_InitRuntimeSounds();
|
||||
|
||||
// Prepare skincolor material.
|
||||
for (i = 0; i < MAXSKINCOLORS; i++)
|
||||
{
|
||||
Color_cons_t[i].value = Followercolor_cons_t[i+2].value = i;
|
||||
Color_cons_t[i].strvalue = Followercolor_cons_t[i+2].strvalue = skincolors[i].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[0].value = FOLLOWERCOLOR_OPPOSITE;
|
||||
Followercolor_cons_t[0].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;
|
||||
}
|
||||
|
||||
#define GD_VERSIONCHECK 0xBA5ED444 // Change every major version, as usual
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
INT32 numfollowers = 0;
|
||||
follower_t followers[MAXSKINS];
|
||||
|
||||
INT32 numfollowercategories;
|
||||
followercategory_t followercategories[MAXFOLLOWERCATEGORIES];
|
||||
|
||||
CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for "Match", "Opposite" & NULL
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -28,7 +31,7 @@ INT32 K_FollowerAvailable(const char *name)
|
|||
|
||||
for (i = 0; i < numfollowers; i++)
|
||||
{
|
||||
if (stricmp(followers[i].skinname, name) == 0)
|
||||
if (stricmp(followers[i].name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +57,7 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname)
|
|||
for (i = 0; i < numfollowers; i++)
|
||||
{
|
||||
// search in the skin list
|
||||
if (stricmp(followers[i].skinname, skinname) == 0)
|
||||
if (stricmp(followers[i].name, skinname) == 0)
|
||||
{
|
||||
K_SetFollowerByNum(playernum, i);
|
||||
return true;
|
||||
|
|
@ -74,6 +77,31 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname)
|
|||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RemoveFollower(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_RemoveFollower(player_t *player)
|
||||
{
|
||||
mobj_t *bub, *tmp;
|
||||
if (player->follower && !P_MobjWasRemoved(player->follower)) // this is also called when we change colour so don't respawn the follower unless we changed skins
|
||||
{
|
||||
// Remove follower's possible hnext list (bubble)
|
||||
bub = player->follower->hnext;
|
||||
|
||||
while (bub && !P_MobjWasRemoved(bub))
|
||||
{
|
||||
tmp = bub->hnext;
|
||||
P_RemoveMobj(bub);
|
||||
bub = tmp;
|
||||
}
|
||||
|
||||
P_RemoveMobj(player->follower);
|
||||
P_SetTarget(&player->follower, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
||||
|
||||
|
|
@ -82,8 +110,6 @@ boolean K_SetFollowerByName(INT32 playernum, const char *skinname)
|
|||
void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
||||
{
|
||||
player_t *player = &players[playernum];
|
||||
mobj_t *bub;
|
||||
mobj_t *tmp;
|
||||
|
||||
player->followerready = true; // we are ready to perform follower related actions in the player thinker, now.
|
||||
|
||||
|
|
@ -94,21 +120,8 @@ void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
|||
However, we will despawn it right here if there's any to make it easy for the player thinker to replace it or delete it.
|
||||
*/
|
||||
|
||||
if (player->follower && skinnum != player->followerskin) // this is also called when we change colour so don't respawn the follower unless we changed skins
|
||||
{
|
||||
// Remove follower's possible hnext list (bubble)
|
||||
bub = player->follower->hnext;
|
||||
|
||||
while (bub && !P_MobjWasRemoved(bub))
|
||||
{
|
||||
tmp = bub->hnext;
|
||||
P_RemoveMobj(bub);
|
||||
bub = tmp;
|
||||
}
|
||||
|
||||
P_RemoveMobj(player->follower);
|
||||
P_SetTarget(&player->follower, NULL);
|
||||
}
|
||||
if (skinnum != player->followerskin)
|
||||
K_RemoveFollower(player);
|
||||
|
||||
player->followerskin = skinnum;
|
||||
|
||||
|
|
@ -253,18 +266,16 @@ void K_HandleFollower(player_t *player)
|
|||
{
|
||||
//CONS_Printf("Follower skin invlaid. Setting to -1.\n");
|
||||
player->followerskin = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// don't do anything if we can't have a follower to begin with.
|
||||
// (It gets removed under those conditions)
|
||||
if (player->spectator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->followerskin < 0)
|
||||
if (player->spectator || player->followerskin < 0)
|
||||
{
|
||||
if (player->follower)
|
||||
{
|
||||
K_RemoveFollower(player);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,10 +45,11 @@ typedef enum
|
|||
//
|
||||
typedef struct follower_s
|
||||
{
|
||||
char skinname[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything.
|
||||
char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
|
||||
char name[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything..
|
||||
char icon[8+1]; // Lump names are only 8 characters. (+1 for \0)
|
||||
|
||||
UINT8 category; // Category
|
||||
|
||||
skincolornum_t defaultcolor; // default color for menus.
|
||||
followermode_t mode; // Follower behavior modifier.
|
||||
|
||||
|
|
@ -85,6 +86,18 @@ typedef struct follower_s
|
|||
extern INT32 numfollowers;
|
||||
extern follower_t followers[MAXSKINS];
|
||||
|
||||
#define MAXFOLLOWERCATEGORIES 32
|
||||
|
||||
typedef struct followercategory_s
|
||||
{
|
||||
char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this.
|
||||
char icon[8+1]; // Lump names are only 8 characters. (+1 for \0)
|
||||
UINT8 numincategory;
|
||||
} followercategory_t;
|
||||
|
||||
extern INT32 numfollowercategories;
|
||||
extern followercategory_t followercategories[MAXFOLLOWERCATEGORIES];
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT32 K_FollowerAvailable(const char *name)
|
||||
|
||||
|
|
@ -168,5 +181,19 @@ UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor);
|
|||
|
||||
void K_HandleFollower(player_t *player);
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_RemoveFollower(player_t *player)
|
||||
|
||||
Removes Follower object
|
||||
|
||||
Input Arguments:-
|
||||
player - The player who we want to remove the follower of.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_RemoveFollower(player_t *player);
|
||||
|
||||
|
||||
#endif // __K_FOLLOWER__
|
||||
|
|
|
|||
|
|
@ -599,6 +599,7 @@ typedef enum
|
|||
CSSTEP_CHARS,
|
||||
CSSTEP_ALTS,
|
||||
CSSTEP_COLORS,
|
||||
CSSTEP_FOLLOWERCATEGORY,
|
||||
CSSTEP_FOLLOWER,
|
||||
CSSTEP_FOLLOWERCOLORS,
|
||||
CSSTEP_READY
|
||||
|
|
@ -614,6 +615,7 @@ typedef struct setup_player_s
|
|||
UINT8 delay;
|
||||
UINT16 color;
|
||||
UINT8 mdepth;
|
||||
boolean hitlag;
|
||||
|
||||
// Hack, save player 1's original device even if they init charsel with keyboard.
|
||||
// If they play ALONE, allow them to retain that original device, otherwise, ignore this.
|
||||
|
|
@ -622,7 +624,8 @@ typedef struct setup_player_s
|
|||
|
||||
UINT8 changeselect;
|
||||
|
||||
INT32 followern;
|
||||
INT16 followercategory;
|
||||
INT16 followern;
|
||||
UINT16 followercolor;
|
||||
tic_t follower_tics;
|
||||
tic_t follower_timer;
|
||||
|
|
|
|||
235
src/k_menudraw.c
235
src/k_menudraw.c
|
|
@ -969,7 +969,8 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
{
|
||||
angle_t angamt = ANGLE_MAX;
|
||||
UINT16 i, numoptions = 0;
|
||||
UINT16 l = 0, r = 0;
|
||||
INT16 l = 0, r = 0;
|
||||
INT16 subtractcheck;
|
||||
|
||||
switch (p->mdepth)
|
||||
{
|
||||
|
|
@ -979,8 +980,11 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
case CSSTEP_COLORS:
|
||||
numoptions = nummenucolors;
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
numoptions = numfollowercategories+1;
|
||||
break;
|
||||
case CSSTEP_FOLLOWER:
|
||||
numoptions = numfollowers+1;
|
||||
numoptions = followercategories[p->followercategory].numincategory;
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCOLORS:
|
||||
numoptions = nummenucolors+2;
|
||||
|
|
@ -994,17 +998,19 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
return;
|
||||
}
|
||||
|
||||
subtractcheck = 1 ^ (numoptions & 1);
|
||||
|
||||
angamt /= numoptions;
|
||||
|
||||
for (i = 0; i < numoptions; i++)
|
||||
{
|
||||
fixed_t cx = x << FRACBITS, cy = y << FRACBITS;
|
||||
boolean subtract = (i & 1);
|
||||
boolean subtract = (i & 1) == subtractcheck;
|
||||
angle_t ang = ((i+1)/2) * angamt;
|
||||
patch_t *patch = NULL;
|
||||
UINT8 *colormap = NULL;
|
||||
fixed_t radius = 28<<FRACBITS;
|
||||
UINT16 n = 0;
|
||||
INT16 n = 0;
|
||||
|
||||
switch (p->mdepth)
|
||||
{
|
||||
|
|
@ -1017,7 +1023,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
n -= ((i+1)/2);
|
||||
else
|
||||
n += ((i+1)/2);
|
||||
n %= numoptions;
|
||||
n = (n + numoptions) % numoptions;
|
||||
|
||||
skin = setup_chargrid[p->gridx][p->gridy].skinlist[n];
|
||||
patch = faceprefix[skin][FACE_RANK];
|
||||
|
|
@ -1061,16 +1067,16 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
break;
|
||||
}
|
||||
|
||||
case CSSTEP_FOLLOWER:
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
{
|
||||
follower_t *fl = NULL;
|
||||
followercategory_t *fc = NULL;
|
||||
|
||||
n = (p->followern + 1) + numoptions/2;
|
||||
n = (p->followercategory + 1) + numoptions/2;
|
||||
if (subtract)
|
||||
n -= ((i+1)/2);
|
||||
else
|
||||
n += ((i+1)/2);
|
||||
n %= numoptions;
|
||||
n = (n + numoptions) % numoptions;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
|
|
@ -1078,11 +1084,71 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
}
|
||||
else
|
||||
{
|
||||
fl = &followers[n - 1];
|
||||
fc = &followercategories[n - 1];
|
||||
patch = W_CachePatchName(fc->icon, PU_CACHE);
|
||||
}
|
||||
|
||||
radius = 24<<FRACBITS;
|
||||
|
||||
cx -= (SHORT(patch->width) << FRACBITS) >> 1;
|
||||
cy -= (SHORT(patch->height) << FRACBITS) >> 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case CSSTEP_FOLLOWER:
|
||||
{
|
||||
follower_t *fl = NULL;
|
||||
INT16 startfollowern = p->followern;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
n = p->followern;
|
||||
r = (numoptions+1)/2;
|
||||
while (r)
|
||||
{
|
||||
n--;
|
||||
if (n < 0)
|
||||
n = numfollowers-1;
|
||||
if (n == startfollowern)
|
||||
break;
|
||||
if (followers[n].category == p->followercategory)
|
||||
r--;
|
||||
}
|
||||
l = r = n;
|
||||
}
|
||||
else if (subtract)
|
||||
{
|
||||
do
|
||||
{
|
||||
l--;
|
||||
if (l < 0)
|
||||
l = numfollowers-1;
|
||||
if (l == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[l].category != p->followercategory);
|
||||
n = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
r++;
|
||||
if (r >= numfollowers)
|
||||
r = 0;
|
||||
if (r == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[r].category != p->followercategory);
|
||||
n = r;
|
||||
}
|
||||
|
||||
{
|
||||
fl = &followers[n];
|
||||
patch = W_CachePatchName(fl->icon, PU_CACHE);
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT,
|
||||
K_GetEffectiveFollowerColor(p->followercolor, p->color),
|
||||
K_GetEffectiveFollowerColor(fl->defaultcolor, p->color),
|
||||
GTC_MENUCACHE
|
||||
);
|
||||
}
|
||||
|
|
@ -1142,7 +1208,12 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
ang = (signed)(ang - (angamt/2));
|
||||
|
||||
if (p->rotate)
|
||||
ang = (signed)(ang + ((angamt / CSROTATETICS) * p->rotate));
|
||||
{
|
||||
SINT8 rotate = p->rotate;
|
||||
if ((p->hitlag == true) && (setup_animcounter & 1))
|
||||
rotate = -rotate;
|
||||
ang = (signed)(ang + ((angamt / CSROTATETICS) * rotate));
|
||||
}
|
||||
|
||||
cx += FixedMul(radius, FINECOSINE(ang >> ANGLETOFINESHIFT));
|
||||
cy -= FixedMul(radius, FINESINE(ang >> ANGLETOFINESHIFT)) / 3;
|
||||
|
|
@ -1154,41 +1225,40 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
}
|
||||
|
||||
// returns false if the character couldn't be rendered
|
||||
static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, INT32 addflags, UINT8 *colormap)
|
||||
static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, boolean charflip, boolean animate, INT32 addflags, UINT8 *colormap)
|
||||
{
|
||||
UINT8 spr;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
patch_t *sprpatch;
|
||||
UINT8 rotation = (charflip ? 1 : 7);
|
||||
UINT32 frame = animate ? setup_animcounter : 0;
|
||||
|
||||
UINT32 flags = 0;
|
||||
UINT32 frame;
|
||||
|
||||
spr = P_GetSkinSprite2(&skins[skin], SPR2_FSTN, NULL);
|
||||
spr = P_GetSkinSprite2(&skins[skin], SPR2_STIN, NULL);
|
||||
sprdef = &skins[skin].sprites[spr];
|
||||
|
||||
if (!sprdef->numframes) // No frames ??
|
||||
return false; // Can't render!
|
||||
|
||||
frame = states[S_KART_FAST].frame & FF_FRAMEMASK;
|
||||
if (frame >= sprdef->numframes) // Walking animation missing
|
||||
frame = 0; // Try to use standing frame
|
||||
frame %= sprdef->numframes;
|
||||
|
||||
sprframe = &sprdef->spriteframes[frame];
|
||||
sprpatch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
|
||||
sprpatch = W_CachePatchNum(sprframe->lumppat[rotation], PU_CACHE);
|
||||
|
||||
if (sprframe->flip & 1) // Only for first sprite
|
||||
flags |= V_FLIP; // This sprite is left/right flipped!
|
||||
if (sprframe->flip & (1<<rotation)) // Only for first sprite
|
||||
{
|
||||
addflags ^= V_FLIP; // This sprite is left/right flipped!
|
||||
}
|
||||
|
||||
if (skins[skin].flags & SF_HIRES)
|
||||
{
|
||||
V_DrawFixedPatch(x<<FRACBITS,
|
||||
y<<FRACBITS,
|
||||
skins[skin].highresscale,
|
||||
flags, sprpatch, colormap);
|
||||
addflags, sprpatch, colormap);
|
||||
}
|
||||
else
|
||||
V_DrawMappedPatch(x, y, addflags|flags, sprpatch, colormap);
|
||||
V_DrawMappedPatch(x, y, addflags, sprpatch, colormap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1196,7 +1266,7 @@ static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, INT32 addflag
|
|||
// Returns false is the follower shouldn't be rendered.
|
||||
// 'num' can be used to directly specify the follower number, but doing this will not animate it.
|
||||
// if a setup_player_t is specified instead, its data will be used to animate the follower sprite.
|
||||
static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags, UINT16 color, setup_player_t *p)
|
||||
static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, boolean charflip, INT32 addflags, UINT16 color, setup_player_t *p)
|
||||
{
|
||||
|
||||
spritedef_t *sprdef;
|
||||
|
|
@ -1207,6 +1277,7 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags,
|
|||
UINT32 useframe;
|
||||
follower_t fl;
|
||||
UINT8 *colormap = NULL;
|
||||
UINT8 rotation = (charflip ? 1 : 7);
|
||||
|
||||
if (p != NULL)
|
||||
followernum = p->followern;
|
||||
|
|
@ -1238,14 +1309,11 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags,
|
|||
useframe = 0; // frame doesn't exist, we went beyond it... what?
|
||||
|
||||
sprframe = &sprdef->spriteframes[useframe];
|
||||
patch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
|
||||
patch = W_CachePatchNum(sprframe->lumppat[rotation], PU_CACHE);
|
||||
|
||||
if (sprframe->flip & 2) // Only for first sprite
|
||||
if (sprframe->flip & (1<<rotation)) // Only for first sprite
|
||||
{
|
||||
if (addflags & V_FLIP)
|
||||
addflags &= ~V_FLIP;
|
||||
else
|
||||
addflags |= V_FLIP; // This sprite is left/right flipped!
|
||||
addflags ^= V_FLIP; // This sprite is left/right flipped!
|
||||
}
|
||||
|
||||
fixed_t sine = 0;
|
||||
|
|
@ -1253,35 +1321,33 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, INT32 addflags,
|
|||
if (p != NULL)
|
||||
{
|
||||
sine = FixedMul(fl.bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, fl.bobspeed) * p->follower_timer)>>ANGLETOFINESHIFT) & FINEMASK));
|
||||
color = K_GetEffectiveFollowerColor(p->followercolor, p->color);
|
||||
color = K_GetEffectiveFollowerColor(
|
||||
(p->mdepth < CSSTEP_FOLLOWERCOLORS) ? fl.defaultcolor : p->followercolor,
|
||||
p->color);
|
||||
}
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, color, GTC_MENUCACHE);
|
||||
V_DrawFixedPatch((x)*FRACUNIT, ((y-12)*FRACUNIT) + sine - fl.zoffs, fl.scale, addflags, patch, colormap);
|
||||
V_DrawFixedPatch((x*FRACUNIT), ((y-12)*FRACUNIT) + sine, fl.scale, addflags, patch, colormap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y)
|
||||
static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y, boolean charflip)
|
||||
{
|
||||
setup_player_t *p = &setup_player[num];
|
||||
UINT8 cnum = p->clonenum;
|
||||
UINT8 color;
|
||||
UINT8 *colormap;
|
||||
|
||||
// for p1 alone don't try to preview things on pages that don't exist lol.
|
||||
if (p->mdepth == CSSTEP_CHARS && setup_numplayers == 1)
|
||||
cnum = setup_page;
|
||||
if (p->skin < 0)
|
||||
return;
|
||||
|
||||
INT16 skin = setup_chargrid[p->gridx][p->gridy].skinlist[cnum];
|
||||
UINT8 color = p->color;
|
||||
UINT8 *colormap = R_GetTranslationColormap(skin, color, GTC_MENUCACHE);
|
||||
INT32 flags = 0;
|
||||
if (p->mdepth < CSSTEP_COLORS)
|
||||
color = skins[p->skin].prefcolor;
|
||||
else
|
||||
color = p->color;
|
||||
colormap = R_GetTranslationColormap(p->skin, color, GTC_MENUCACHE);
|
||||
|
||||
// Flip for left-side players
|
||||
if (!(num & 1))
|
||||
flags ^= V_FLIP;
|
||||
|
||||
if (skin >= 0)
|
||||
M_DrawCharacterSprite(x, y, skin, flags, colormap);
|
||||
M_DrawCharacterSprite(x, y, p->skin, charflip, (p->mdepth == CSSTEP_READY), 0, colormap);
|
||||
}
|
||||
|
||||
static void M_DrawCharSelectPreview(UINT8 num)
|
||||
|
|
@ -1289,6 +1355,7 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
INT16 x = 11, y = 5;
|
||||
char letter = 'A' + num;
|
||||
setup_player_t *p = &setup_player[num];
|
||||
boolean charflip = !!(num & 1);
|
||||
|
||||
if (num & 1)
|
||||
x += 233;
|
||||
|
|
@ -1300,28 +1367,10 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
|
||||
if (p->mdepth >= CSSTEP_CHARS)
|
||||
{
|
||||
M_DrawCharSelectSprite(num, x+32, y+75);
|
||||
|
||||
if (p->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
M_DrawFollowerSprite(x+16, y+75, -1, !(num & 1) ? V_FLIP : 0, 0, p);
|
||||
}
|
||||
|
||||
M_DrawCharSelectSprite(num, x+32, y+75, charflip);
|
||||
M_DrawCharSelectCircle(p, x+32, y+64);
|
||||
}
|
||||
|
||||
if ((setup_animcounter/10) & 1 && gamestate == GS_MENU) // Not drawn outside of GS_MENU.
|
||||
{
|
||||
if (p->mdepth == CSSTEP_NONE && num == setup_numplayers)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE));
|
||||
}
|
||||
else if (p->mdepth >= CSSTEP_READY)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PREADY", PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(x+9, y+2, 0, W_CachePatchName("FILEBACK", PU_CACHE));
|
||||
V_DrawScaledPatch(x, y+2, 0, W_CachePatchName(va("CHARSEL%c", letter), PU_CACHE));
|
||||
if (p->mdepth > CSSTEP_PROFILE)
|
||||
|
|
@ -1334,6 +1383,23 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
V_DrawFileString(x+16, y+2, 0, "PLAYER");
|
||||
}
|
||||
|
||||
if (p->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
M_DrawFollowerSprite(x+32+((charflip ? 1 : -1)*16), y+75, -1, charflip, 0, 0, p);
|
||||
}
|
||||
|
||||
if ((setup_animcounter/10) & 1 && gamestate == GS_MENU) // Not drawn outside of GS_MENU.
|
||||
{
|
||||
if (p->mdepth == CSSTEP_NONE && num == setup_numplayers)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE));
|
||||
}
|
||||
else if (p->mdepth >= CSSTEP_READY)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PREADY", PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
||||
// Profile selection
|
||||
if (p->mdepth == CSSTEP_PROFILE)
|
||||
{
|
||||
|
|
@ -1549,39 +1615,38 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
|
|||
// check what setup_player is doing in priority.
|
||||
if (sp->mdepth >= CSSTEP_CHARS)
|
||||
{
|
||||
|
||||
skinnum = setup_chargrid[sp->gridx][sp->gridy].skinlist[sp->clonenum];
|
||||
|
||||
if (skinnum >= 0)
|
||||
{
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, V_FLIP, colormap))
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, false, false, 0, colormap))
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], colormap);
|
||||
|
||||
if (sp->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
if (M_DrawFollowerSprite(x-44 +12, y+119, 0, V_FLIP, 0, sp))
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, sp->color);;
|
||||
patch_t *ico = W_CachePatchName(followers[sp->followern].icon, PU_CACHE);
|
||||
UINT8 *fcolormap;
|
||||
|
||||
fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M_DrawCharSelectCircle(sp, x-22, y+104);
|
||||
|
||||
if (sp->mdepth >= CSSTEP_FOLLOWER)
|
||||
{
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, 0, false, 0, 0, sp))
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, sp->color);;
|
||||
patch_t *ico = W_CachePatchName(followers[sp->followern].icon, PU_CACHE);
|
||||
UINT8 *fcolormap;
|
||||
|
||||
fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (skinnum > -1) // otherwise, read from profile.
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(p->followercolor, p->color);;
|
||||
UINT8 fln = K_FollowerAvailable(p->follower);
|
||||
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, V_FLIP, colormap))
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, false, false, 0, colormap))
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], colormap);
|
||||
|
||||
if (M_DrawFollowerSprite(x-44 +12, y+119, fln, V_FLIP, col, NULL))
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, fln, false, 0, col, NULL))
|
||||
{
|
||||
patch_t *ico = W_CachePatchName(followers[fln].icon, PU_CACHE);
|
||||
UINT8 *fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
|
|
|
|||
217
src/k_menufunc.c
217
src/k_menufunc.c
|
|
@ -1583,6 +1583,9 @@ void M_Ticker(void)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
if (!menuactive)
|
||||
return;
|
||||
|
||||
if (menutransition.tics != 0 || menutransition.dest != 0)
|
||||
{
|
||||
noFurtherInput = true;
|
||||
|
|
@ -2063,6 +2066,12 @@ static void M_SetupProfileGridPos(setup_player_t *p)
|
|||
|
||||
// While we're here, read follower values.
|
||||
p->followern = K_FollowerAvailable(pr->follower);
|
||||
|
||||
if (p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories)
|
||||
p->followercategory = -1;
|
||||
else
|
||||
p->followercategory = followers[p->followern].category;
|
||||
|
||||
p->followercolor = pr->followercolor;
|
||||
|
||||
// Now position the grid for skin
|
||||
|
|
@ -2150,6 +2159,7 @@ void M_CharacterSelectInit(void)
|
|||
{
|
||||
// Default to no follower / match colour.
|
||||
setup_player[i].followern = -1;
|
||||
setup_player[i].followercategory = -1;
|
||||
setup_player[i].followercolor = FOLLOWERCOLOR_MATCH;
|
||||
|
||||
// Set default selected profile to the last used profile for each player:
|
||||
|
|
@ -2486,6 +2496,16 @@ static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num)
|
|||
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
UINT8 yourprofile = min(cv_lastprofile[realnum].value, PR_GetNumProfiles());
|
||||
if (p->profilen == yourprofile)
|
||||
p->profilen = PROFILE_GUEST;
|
||||
else
|
||||
p->profilen = yourprofile;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
|
@ -2578,6 +2598,15 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
|
|||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
p->gridx /= 3;
|
||||
p->gridx = (3*p->gridx) + 1;
|
||||
p->gridy /= 3;
|
||||
p->gridy = (3*p->gridy) + 1;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
||||
// try to set the clone num to the page # if possible.
|
||||
p->clonenum = setup_page;
|
||||
|
|
@ -2692,6 +2721,14 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
|
|||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
p->clonenum = 0;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
||||
|
|
@ -2716,8 +2753,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
|
||||
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWER;
|
||||
M_GetFollowerState(p);
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
|
@ -2734,6 +2770,17 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
if (p->skin >= 0)
|
||||
{
|
||||
p->color = skins[p->skin].prefcolor;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void M_AnimateFollower(setup_player_t *p)
|
||||
|
|
@ -2764,16 +2811,103 @@ static void M_AnimateFollower(setup_player_t *p)
|
|||
p->follower_timer++;
|
||||
}
|
||||
|
||||
static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
||||
static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num)
|
||||
{
|
||||
if (cv_splitdevice.value)
|
||||
num = 0;
|
||||
|
||||
if (menucmd[num].dpad_lr > 0)
|
||||
{
|
||||
p->followern++;
|
||||
if (p->followern >= numfollowers)
|
||||
p->followercategory++;
|
||||
if (p->followercategory >= numfollowercategories)
|
||||
p->followercategory = -1;
|
||||
|
||||
p->rotate = CSROTATETICS;
|
||||
p->delay = CSROTATETICS;
|
||||
S_StartSound(NULL, sfx_s3kc3s);
|
||||
}
|
||||
else if (menucmd[num].dpad_lr < 0)
|
||||
{
|
||||
p->followercategory--;
|
||||
if (p->followercategory < -1)
|
||||
p->followercategory = numfollowercategories-1;
|
||||
|
||||
p->rotate = -CSROTATETICS;
|
||||
p->delay = CSROTATETICS;
|
||||
S_StartSound(NULL, sfx_s3kc3s);
|
||||
}
|
||||
|
||||
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
|
||||
{
|
||||
if (p->followercategory < 0)
|
||||
{
|
||||
p->followern = -1;
|
||||
p->mdepth = CSSTEP_READY;
|
||||
p->delay = TICRATE;
|
||||
M_SetupReadyExplosions(p);
|
||||
S_StartSound(NULL, sfx_s3k4e);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->followern < 0 || followers[p->followern].category != p->followercategory)
|
||||
{
|
||||
p->followern = 0;
|
||||
while (p->followern < numfollowers && followers[p->followern].category != p->followercategory)
|
||||
p->followern++;
|
||||
}
|
||||
|
||||
if (p->followern >= numfollowers)
|
||||
{
|
||||
p->followern = -1;
|
||||
S_StartSound(NULL, sfx_s3kb2);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_GetFollowerState(p);
|
||||
p->mdepth = CSSTEP_FOLLOWER;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
}
|
||||
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
if (p->followercategory >= 0 || p->followern < 0 || p->followern >= numfollowers || followers[p->followern].category >= numfollowercategories)
|
||||
p->followercategory = -1;
|
||||
else
|
||||
p->followercategory = followers[p->followern].category;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
||||
{
|
||||
INT16 startfollowern = p->followern;
|
||||
|
||||
if (cv_splitdevice.value)
|
||||
num = 0;
|
||||
|
||||
if (menucmd[num].dpad_lr > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
p->followern++;
|
||||
if (p->followern >= numfollowers)
|
||||
p->followern = 0;
|
||||
if (p->followern == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[p->followern].category != p->followercategory);
|
||||
|
||||
M_GetFollowerState(p);
|
||||
|
||||
|
|
@ -2783,9 +2917,17 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (menucmd[num].dpad_lr < 0)
|
||||
{
|
||||
p->followern--;
|
||||
if (p->followern < -1)
|
||||
p->followern = numfollowers-1;
|
||||
do
|
||||
{
|
||||
p->followern--;
|
||||
if (p->followern < 0)
|
||||
p->followern = numfollowers-1;
|
||||
if (p->followern == startfollowern)
|
||||
break;
|
||||
}
|
||||
while (followers[p->followern].category != p->followercategory);
|
||||
|
||||
M_GetFollowerState(p);
|
||||
|
||||
p->rotate = -CSROTATETICS;
|
||||
p->delay = CSROTATETICS;
|
||||
|
|
@ -2811,10 +2953,19 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
p->followercategory = -1;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
||||
|
|
@ -2849,10 +3000,24 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
|||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
M_GetFollowerState(p);
|
||||
p->mdepth = CSSTEP_FOLLOWER;
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
else if (M_MenuExtraPressed(num))
|
||||
{
|
||||
if (p->followercolor == FOLLOWERCOLOR_MATCH)
|
||||
p->followercolor = FOLLOWERCOLOR_OPPOSITE;
|
||||
else if (p->followercolor == followers[p->followern].defaultcolor)
|
||||
p->followercolor = FOLLOWERCOLOR_MATCH;
|
||||
else
|
||||
p->followercolor = followers[p->followern].defaultcolor;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
|
||||
boolean M_CharacterSelectHandler(INT32 choice)
|
||||
|
|
@ -2901,6 +3066,9 @@ boolean M_CharacterSelectHandler(INT32 choice)
|
|||
case CSSTEP_COLORS: // Select color
|
||||
M_HandleColorRotate(p, i);
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
M_HandleFollowerCategoryRotate(p, i);
|
||||
break;
|
||||
case CSSTEP_FOLLOWER:
|
||||
M_HandleFollowerRotate(p, i);
|
||||
break;
|
||||
|
|
@ -2956,33 +3124,27 @@ static void M_MPConfirmCharacterSelection(void)
|
|||
UINT8 i;
|
||||
INT16 col;
|
||||
|
||||
char commandnames[][MAXSTRINGLENGTH] = { "skin ", "skin2 ", "skin3 ", "skin4 "};
|
||||
// ^ laziness 100 (we append a space directly so that we don't have to do it later too!!!!)
|
||||
|
||||
for (i = 0; i < splitscreen +1; i++)
|
||||
{
|
||||
char cmd[MAXSTRINGLENGTH];
|
||||
|
||||
// colour
|
||||
// (convert the number that's saved to a string we can use)
|
||||
col = setup_player[i].color;
|
||||
CV_StealthSetValue(&cv_playercolor[i], col);
|
||||
|
||||
// follower
|
||||
CV_StealthSetValue(&cv_follower[i], setup_player[i].followern);
|
||||
|
||||
// follower color
|
||||
CV_StealthSetValue(&cv_followercolor[i], setup_player[i].followercolor);
|
||||
if (setup_player[i].followern < 0)
|
||||
CV_StealthSet(&cv_follower[i], "None");
|
||||
else
|
||||
CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name);
|
||||
|
||||
// finally, call the skin[x] console command.
|
||||
// This will call SendNameAndColor which will synch everything we sent here and apply the changes!
|
||||
|
||||
// This is a hack to make sure we call Skin[x]_OnChange afterwards
|
||||
CV_StealthSetValue(&cv_skin[i], -1);
|
||||
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name);
|
||||
|
||||
strcpy(cmd, commandnames[i]);
|
||||
strcat(cmd, skins[setup_player[i].skin].name);
|
||||
COM_ImmedExecute(cmd);
|
||||
// ...actually, let's do this last - Skin_OnChange has some return-early occasions
|
||||
// follower color
|
||||
CV_SetValue(&cv_followercolor[i], setup_player[i].followercolor);
|
||||
|
||||
}
|
||||
M_ClearMenus(true);
|
||||
|
|
@ -3004,6 +3166,8 @@ void M_CharacterSelectTick(void)
|
|||
setup_player[i].rotate--;
|
||||
else if (setup_player[i].rotate < 0)
|
||||
setup_player[i].rotate++;
|
||||
else
|
||||
setup_player[i].hitlag = false;
|
||||
|
||||
if (i >= setup_numplayers)
|
||||
continue;
|
||||
|
|
@ -3034,7 +3198,7 @@ void M_CharacterSelectTick(void)
|
|||
optionsmenu.profile->color = setup_player[0].color;
|
||||
|
||||
// save follower
|
||||
strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].skinname);
|
||||
strcpy(optionsmenu.profile->follower, followers[setup_player[0].followern].name);
|
||||
optionsmenu.profile->followercolor = setup_player[0].followercolor;
|
||||
|
||||
// reset setup_player
|
||||
|
|
@ -3051,7 +3215,10 @@ void M_CharacterSelectTick(void)
|
|||
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name);
|
||||
CV_StealthSetValue(&cv_playercolor[i], setup_player[i].color);
|
||||
|
||||
CV_StealthSetValue(&cv_follower[i], setup_player[i].followern);
|
||||
if (setup_player[i].followern < 0)
|
||||
CV_StealthSet(&cv_follower[i], "None");
|
||||
else
|
||||
CV_StealthSet(&cv_follower[i], followers[setup_player[i].followern].name);
|
||||
CV_StealthSetValue(&cv_followercolor[i], setup_player[i].followercolor);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue