mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-03 05:32:54 +00:00
Merge branch 'seeecret-colors' into 'master'
SECRET_COLOR See merge request KartKrew/Kart!1188
This commit is contained in:
commit
6f2befabc9
31 changed files with 977 additions and 724 deletions
|
|
@ -38,6 +38,7 @@
|
|||
#include "r_skins.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h" // P_ResetPlayerCheats
|
||||
#include "k_color.h"
|
||||
|
||||
//========
|
||||
// protos.
|
||||
|
|
@ -109,6 +110,8 @@ CV_PossibleValue_t gpdifficulty_cons_t[] = {
|
|||
{0, NULL}
|
||||
};
|
||||
|
||||
CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
|
||||
|
||||
// Filter consvars by EXECVERSION
|
||||
// First implementation is 2 (1.0.2), so earlier configs default at 1 (1.0.0)
|
||||
// Also set CV_HIDDEN during runtime, after config is loaded
|
||||
|
|
@ -909,17 +912,28 @@ static void COM_Help_f(void)
|
|||
CONS_Printf(" Yes or No (On or Off, 1 or 0)\n");
|
||||
else if (cvar->PossibleValue == CV_OnOff)
|
||||
CONS_Printf(" On or Off (Yes or No, 1 or 0)\n");
|
||||
else if (cvar->PossibleValue == Color_cons_t)
|
||||
else if (cvar->PossibleValue == Color_cons_t || cvar->PossibleValue == Followercolor_cons_t)
|
||||
{
|
||||
for (i = 1; i < numskincolors; ++i)
|
||||
boolean follower = (cvar->PossibleValue == Followercolor_cons_t);
|
||||
for (i = SKINCOLOR_NONE; i < numskincolors; ++i)
|
||||
{
|
||||
if (skincolors[i].accessible)
|
||||
if (K_ColorUsable(i, follower) == true)
|
||||
{
|
||||
CONS_Printf(" %-2d : %s\n", i, skincolors[i].name);
|
||||
CONS_Printf(" %-3d : %s\n", i, skincolors[i].name);
|
||||
if (i == cvar->value)
|
||||
cvalue = skincolors[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
if (follower)
|
||||
{
|
||||
CONS_Printf(" %-3d : %s\n", FOLLOWERCOLOR_MATCH, "Match");
|
||||
if (FOLLOWERCOLOR_MATCH == cvar->value)
|
||||
cvalue = "Match";
|
||||
CONS_Printf(" %-3d : %s\n", FOLLOWERCOLOR_MATCH, "Opposite");
|
||||
if (FOLLOWERCOLOR_OPPOSITE == cvar->value)
|
||||
cvalue = "Opposite";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2248,6 +2262,11 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
max = KARTSPEED_HARD+1;
|
||||
}
|
||||
}
|
||||
else if (var->PossibleValue == kartvoices_cons_t
|
||||
&& !M_SecretUnlocked(SECRET_MEMETAUNTS, true))
|
||||
{
|
||||
max--;
|
||||
}
|
||||
#ifdef PARANOIA
|
||||
if (currentindice == -1)
|
||||
I_Error("CV_AddValue: current value %d not found in possible value\n",
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ extern CV_PossibleValue_t CV_Natural[];
|
|||
// SRB2kart
|
||||
// the KARTSPEED and KARTGP were previously defined here, but moved to doomstat to avoid circular dependencies
|
||||
extern CV_PossibleValue_t kartspeed_cons_t[], dummykartspeed_cons_t[], gpdifficulty_cons_t[];
|
||||
extern CV_PossibleValue_t kartvoices_cons_t[];
|
||||
|
||||
extern consvar_t cv_execversion;
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ boolean digital_disabled = false;
|
|||
INT32 debugload = 0;
|
||||
#endif
|
||||
|
||||
UINT16 numskincolors;
|
||||
UINT16 numskincolors = SKINCOLOR_FIRSTFREESLOT;
|
||||
menucolor_t *menucolorhead, *menucolortail;
|
||||
|
||||
char savegamename[256];
|
||||
|
|
@ -1411,10 +1411,6 @@ void D_SRB2Main(void)
|
|||
if (M_CheckParm("-password") && M_IsNextParm())
|
||||
D_SetPassword(M_GetNextParm());
|
||||
|
||||
// player setup menu colors must be initialized before
|
||||
// any wad file is added, as they may contain colors themselves
|
||||
M_InitPlayerSetupColors();
|
||||
|
||||
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
|
||||
Z_Init();
|
||||
CON_SetLoadingProgress(LOADED_ZINIT);
|
||||
|
|
|
|||
390
src/d_netcmd.c
390
src/d_netcmd.c
|
|
@ -123,11 +123,11 @@ static void Lagless_OnChange (void);
|
|||
static void Gravity_OnChange(void);
|
||||
static void ForceSkin_OnChange(void);
|
||||
|
||||
static void Name_OnChange(void);
|
||||
static void Name1_OnChange(void);
|
||||
static void Name2_OnChange(void);
|
||||
static void Name3_OnChange(void);
|
||||
static void Name4_OnChange(void);
|
||||
static void Skin_OnChange(void);
|
||||
static void Skin1_OnChange(void);
|
||||
static void Skin2_OnChange(void);
|
||||
static void Skin3_OnChange(void);
|
||||
static void Skin4_OnChange(void);
|
||||
|
|
@ -141,7 +141,7 @@ static void Followercolor2_OnChange(void);
|
|||
static void Followercolor3_OnChange(void);
|
||||
static void Followercolor4_OnChange(void);
|
||||
|
||||
static void Color_OnChange(void);
|
||||
static void Color1_OnChange(void);
|
||||
static void Color2_OnChange(void);
|
||||
static void Color3_OnChange(void);
|
||||
static void Color4_OnChange(void);
|
||||
|
|
@ -280,7 +280,7 @@ consvar_t cv_seenames = CVAR_INIT ("seenames", "On", CV_SAVE, CV_OnOff, NULL);
|
|||
|
||||
// names
|
||||
consvar_t cv_playername[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("name", "Dr. Eggman", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange),
|
||||
CVAR_INIT ("name", "Dr. Eggman", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name1_OnChange),
|
||||
CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange),
|
||||
CVAR_INIT ("name3", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name3_OnChange),
|
||||
CVAR_INIT ("name4", "Knuckles", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name4_OnChange)
|
||||
|
|
@ -288,14 +288,14 @@ consvar_t cv_playername[MAXSPLITSCREENPLAYERS] = {
|
|||
// player colors
|
||||
UINT16 lastgoodcolor[MAXSPLITSCREENPLAYERS] = {SKINCOLOR_BLUE, SKINCOLOR_BLUE, SKINCOLOR_BLUE, SKINCOLOR_BLUE};
|
||||
consvar_t cv_playercolor[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("color", "Red", CV_SAVE|CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange),
|
||||
CVAR_INIT ("color", "Red", CV_SAVE|CV_CALL|CV_NOINIT, Color_cons_t, Color1_OnChange),
|
||||
CVAR_INIT ("color2", "Orange", CV_SAVE|CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange),
|
||||
CVAR_INIT ("color3", "Blue", CV_SAVE|CV_CALL|CV_NOINIT, Color_cons_t, Color3_OnChange),
|
||||
CVAR_INIT ("color4", "Red", CV_SAVE|CV_CALL|CV_NOINIT, Color_cons_t, Color4_OnChange)
|
||||
};
|
||||
// player's skin, saved for commodity, when using a favorite skins wad..
|
||||
consvar_t cv_skin[MAXSPLITSCREENPLAYERS] = {
|
||||
CVAR_INIT ("skin", DEFAULTSKIN, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin_OnChange),
|
||||
CVAR_INIT ("skin", DEFAULTSKIN, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin1_OnChange),
|
||||
CVAR_INIT ("skin2", DEFAULTSKIN2, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin2_OnChange),
|
||||
CVAR_INIT ("skin3", DEFAULTSKIN3, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin3_OnChange),
|
||||
CVAR_INIT ("skin4", DEFAULTSKIN4, CV_SAVE|CV_CALL|CV_NOINIT, NULL, Skin4_OnChange)
|
||||
|
|
@ -410,8 +410,8 @@ static CV_PossibleValue_t kartencore_cons_t[] = {{-1, "Auto"}, {0, "Off"}, {1, "
|
|||
consvar_t cv_kartencore = CVAR_INIT ("encore", "Auto", CV_NETVAR|CV_CALL|CV_NOINIT, kartencore_cons_t, KartEncore_OnChange);
|
||||
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Percentage"}, {2, "Kilometers"}, {3, "Miles"}, {4, "Fracunits"}, {0, NULL}};
|
||||
consvar_t cv_kartspeedometer = CVAR_INIT ("speedometer", "Percentage", CV_SAVE, kartspeedometer_cons_t, NULL); // use tics in display
|
||||
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
|
||||
consvar_t cv_kartvoices = CVAR_INIT ("tauntvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL);
|
||||
consvar_t cv_karthorns = CVAR_INIT ("taunthorns", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t kartbot_cons_t[] = {
|
||||
{0, "Off"},
|
||||
|
|
@ -1475,113 +1475,61 @@ static INT32 chmappending = 0;
|
|||
|
||||
// name, color, or skin has changed
|
||||
//
|
||||
static void SendNameAndColor(UINT8 n)
|
||||
static void SendNameAndColor(const UINT8 n)
|
||||
{
|
||||
const INT32 playernum = g_localplayers[n];
|
||||
player_t *player = &players[playernum];
|
||||
|
||||
char buf[MAXPLAYERNAME+12];
|
||||
char *p;
|
||||
|
||||
UINT16 i = 0;
|
||||
player_t *player = NULL;
|
||||
|
||||
if (splitscreen < n)
|
||||
{
|
||||
return; // can happen if skin4/color4/name4 changed
|
||||
}
|
||||
|
||||
if (playernum == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
player = &players[playernum];
|
||||
|
||||
UINT16 sendColor = cv_playercolor[n].value;
|
||||
UINT16 sendFollowerColor = cv_followercolor[n].value;
|
||||
|
||||
// don't allow inaccessible colors
|
||||
if (!skincolors[cv_playercolor[n].value].accessible)
|
||||
if (sendColor != SKINCOLOR_NONE && K_ColorUsable(sendColor, false) == false)
|
||||
{
|
||||
if (player->skincolor && skincolors[player->skincolor].accessible)
|
||||
if (player->skincolor && K_ColorUsable(player->skincolor, false) == true)
|
||||
{
|
||||
// Use our previous color
|
||||
CV_StealthSetValue(&cv_playercolor[n], player->skincolor);
|
||||
else if (skins[player->skin].prefcolor && skincolors[skins[player->skin].prefcolor].accessible)
|
||||
CV_StealthSetValue(&cv_playercolor[n], skins[player->skin].prefcolor);
|
||||
else if (skincolors[atoi(cv_playercolor[n].defaultvalue)].accessible)
|
||||
CV_StealthSet(&cv_playercolor[n], cv_playercolor[n].defaultvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i < numskincolors && !skincolors[i].accessible)
|
||||
i++;
|
||||
CV_StealthSetValue(&cv_playercolor[n], (i != numskincolors) ? i : SKINCOLOR_BLUE);
|
||||
// Use our default color
|
||||
CV_StealthSetValue(&cv_playercolor[n], SKINCOLOR_NONE);
|
||||
}
|
||||
|
||||
sendColor = cv_playercolor[n].value;
|
||||
}
|
||||
|
||||
// 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!
|
||||
|
||||
if (!strcmp(cv_playername[n].string, player_names[playernum])
|
||||
&& cv_playercolor[n].value == player->skincolor
|
||||
&& !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;
|
||||
if (sendFollowerColor != SKINCOLOR_NONE && K_ColorUsable(sendFollowerColor, true) == false)
|
||||
{
|
||||
CV_StealthSet(&cv_followercolor[n], "Default"); // set it to "Default". I don't care about your stupidity!
|
||||
sendFollowerColor = cv_followercolor[n].value;
|
||||
}
|
||||
|
||||
// We'll handle it later if we're not playing.
|
||||
if (!Playing())
|
||||
return;
|
||||
|
||||
// If you're not in a netgame, merely update the skin, color, and name.
|
||||
if (!netgame)
|
||||
{
|
||||
INT32 foundskin;
|
||||
|
||||
CleanupPlayerName(playernum, cv_playername[n].zstring);
|
||||
strcpy(player_names[playernum], cv_playername[n].zstring);
|
||||
|
||||
player->skincolor = cv_playercolor[n].value;
|
||||
|
||||
K_KartResetPlayerColor(player);
|
||||
|
||||
foundskin = R_SkinAvailable(cv_skin[n].string);
|
||||
if (foundskin != -1 && R_SkinUsable(playernum, foundskin, false))
|
||||
{
|
||||
SetPlayerSkin(playernum, cv_skin[n].string);
|
||||
CV_StealthSet(&cv_skin[n], skins[foundskin].name);
|
||||
cv_skin[n].value = foundskin;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
if (!K_FollowerUsable(foundskin))
|
||||
foundskin = -1;
|
||||
CV_StealthSet(&cv_follower[n], (foundskin == -1) ? "None" : followers[foundskin].name);
|
||||
cv_follower[n].value = foundskin;
|
||||
K_SetFollowerByNum(playernum, foundskin);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
snacpending[n]++;
|
||||
|
||||
// Don't change name if muted
|
||||
if (player_name_changes[playernum] >= MAXNAMECHANGES)
|
||||
{
|
||||
CV_StealthSet(&cv_playername[n], player_names[playernum]);
|
||||
HU_AddChatText("\x85*You must wait to change your name again", false);
|
||||
}
|
||||
else if (cv_mute.value && !(server || IsPlayerAdmin(playernum)))
|
||||
CV_StealthSet(&cv_playername[n], player_names[playernum]);
|
||||
else // Cleanup name if changing it
|
||||
CleanupPlayerName(playernum, cv_playername[n].zstring);
|
||||
|
||||
// Don't change skin if the server doesn't want you to.
|
||||
if (!CanChangeSkin(playernum))
|
||||
{
|
||||
CV_StealthSet(&cv_skin[n], skins[player->skin].name);
|
||||
}
|
||||
|
||||
// check if player has the skin loaded (cv_skin may have
|
||||
// the name of a skin that was available in the previous game)
|
||||
|
|
@ -1599,13 +1547,61 @@ static void SendNameAndColor(UINT8 n)
|
|||
cv_follower[n].value = -1;
|
||||
}
|
||||
|
||||
if (sendColor == SKINCOLOR_NONE)
|
||||
{
|
||||
sendColor = skins[cv_skin[n].value].prefcolor;
|
||||
}
|
||||
|
||||
if (sendFollowerColor == SKINCOLOR_NONE)
|
||||
{
|
||||
if (cv_follower[n].value >= 0)
|
||||
{
|
||||
sendFollowerColor = followers[cv_follower[n].value].defaultcolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
sendFollowerColor = SKINCOLOR_RED; // picked by dice roll, guaranteed to be random
|
||||
}
|
||||
}
|
||||
|
||||
// Don't send if everything was identical.
|
||||
if (!strcmp(cv_playername[n].string, player_names[playernum])
|
||||
&& sendColor == player->skincolor
|
||||
&& !stricmp(cv_skin[n].string, skins[player->skin].name)
|
||||
&& !stricmp(cv_follower[n].string,
|
||||
(player->followerskin < 0 ? "None" : followers[player->followerskin].name))
|
||||
&& sendFollowerColor == player->followercolor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
snacpending[n]++;
|
||||
|
||||
// Don't change name if muted
|
||||
if (player_name_changes[playernum] >= MAXNAMECHANGES)
|
||||
{
|
||||
CV_StealthSet(&cv_playername[n], player_names[playernum]);
|
||||
HU_AddChatText("\x85* You must wait to change your name again.", false);
|
||||
}
|
||||
else if (cv_mute.value && !(server || IsPlayerAdmin(playernum)))
|
||||
{
|
||||
CV_StealthSet(&cv_playername[n], player_names[playernum]);
|
||||
}
|
||||
else // Cleanup name if changing it
|
||||
{
|
||||
CleanupPlayerName(playernum, cv_playername[n].zstring);
|
||||
}
|
||||
|
||||
char buf[MAXPLAYERNAME+12];
|
||||
char *p = buf;
|
||||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME);
|
||||
WRITEUINT16(p, (UINT16)cv_playercolor[n].value);
|
||||
WRITEUINT16(p, sendColor);
|
||||
WRITEUINT8(p, (UINT8)cv_skin[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);
|
||||
WRITEUINT16(p, sendFollowerColor);
|
||||
|
||||
SendNetXCmdForPlayer(n, XD_NAMEANDCOLOR, buf, p - buf);
|
||||
}
|
||||
|
|
@ -1727,8 +1723,10 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
boolean kick = false;
|
||||
|
||||
// don't allow inaccessible colors
|
||||
if (skincolors[p->skincolor].accessible == false)
|
||||
if (K_ColorUsable(p->skincolor, false) == false)
|
||||
{
|
||||
kick = true;
|
||||
}
|
||||
|
||||
if (kick)
|
||||
{
|
||||
|
|
@ -6662,50 +6660,36 @@ static void ForceSkin_OnChange(void)
|
|||
}
|
||||
|
||||
//Allows the player's name to be changed if cv_mute is off.
|
||||
static void Name_OnChange(void)
|
||||
static void Name_OnChange(const UINT8 p)
|
||||
{
|
||||
if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
|
||||
if (cv_mute.value && !(server || IsPlayerAdmin(g_localplayers[p])))
|
||||
{
|
||||
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]);
|
||||
CV_StealthSet(&cv_playername[p], player_names[g_localplayers[p]]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
SendNameAndColor(0);
|
||||
|
||||
SendNameAndColor(p);
|
||||
}
|
||||
|
||||
static void Name1_OnChange(void)
|
||||
{
|
||||
Name_OnChange(0);
|
||||
}
|
||||
|
||||
static void Name2_OnChange(void)
|
||||
{
|
||||
if (cv_mute.value) //Secondary player can't be admin.
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
|
||||
CV_StealthSet(&cv_playername[1], player_names[g_localplayers[1]]);
|
||||
}
|
||||
else
|
||||
SendNameAndColor(1);
|
||||
Name_OnChange(1);
|
||||
}
|
||||
|
||||
static void Name3_OnChange(void)
|
||||
{
|
||||
if (cv_mute.value) //Third player can't be admin.
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
|
||||
CV_StealthSet(&cv_playername[2], player_names[g_localplayers[2]]);
|
||||
}
|
||||
else
|
||||
SendNameAndColor(2);
|
||||
Name_OnChange(2);
|
||||
}
|
||||
|
||||
static void Name4_OnChange(void)
|
||||
{
|
||||
if (cv_mute.value) //Secondary player can't be admin.
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
|
||||
CV_StealthSet(&cv_playername[3], player_names[g_localplayers[3]]);
|
||||
}
|
||||
else
|
||||
SendNameAndColor(3);
|
||||
Name_OnChange(3);
|
||||
}
|
||||
|
||||
// sends the follower change for players
|
||||
|
|
@ -6766,29 +6750,40 @@ static void Followercolor4_OnChange(void)
|
|||
* \sa cv_skin, Skin2_OnChange, Color_OnChange
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void Skin_OnChange(void)
|
||||
static void Skin_OnChange(const UINT8 p)
|
||||
{
|
||||
if (!Playing())
|
||||
return; // do whatever you want
|
||||
|
||||
if (!CV_CheatsEnabled() && !(multiplayer || netgame) // In single player.
|
||||
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
|
||||
if (!Playing() || splitscreen < p)
|
||||
{
|
||||
CV_StealthSet(&cv_skin[0], skins[players[consoleplayer].skin].name);
|
||||
// do whatever you want
|
||||
return;
|
||||
}
|
||||
|
||||
if (CanChangeSkin(consoleplayer))
|
||||
if (p == 0)
|
||||
{
|
||||
SendNameAndColor(0);
|
||||
if (!CV_CheatsEnabled() && !(multiplayer || netgame) // In single player.
|
||||
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
|
||||
{
|
||||
CV_StealthSet(&cv_skin[p], skins[players[g_localplayers[p]].skin].name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (CanChangeSkin(g_localplayers[p]))
|
||||
{
|
||||
SendNameAndColor(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
CV_StealthSet(&cv_skin[0], skins[players[consoleplayer].skin].name);
|
||||
CV_StealthSet(&cv_skin[p], skins[players[g_localplayers[p]].skin].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void Skin1_OnChange(void)
|
||||
{
|
||||
Skin_OnChange(0);
|
||||
}
|
||||
|
||||
/** Sends a skin change for the secondary splitscreen player, unless that
|
||||
* player is moving. Forces spectate the player if the change is done during gameplay.
|
||||
* \sa cv_skin2, Skin_OnChange, Color2_OnChange
|
||||
|
|
@ -6796,79 +6791,56 @@ static void Skin_OnChange(void)
|
|||
*/
|
||||
static void Skin2_OnChange(void)
|
||||
{
|
||||
if (!Playing() || !splitscreen)
|
||||
return; // do whatever you want
|
||||
|
||||
if (CanChangeSkin(g_localplayers[1]))
|
||||
SendNameAndColor(1);
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
CV_StealthSet(&cv_skin[1], skins[players[g_localplayers[1]].skin].name);
|
||||
}
|
||||
Skin_OnChange(1);
|
||||
}
|
||||
|
||||
static void Skin3_OnChange(void)
|
||||
{
|
||||
if (!Playing() || splitscreen < 2)
|
||||
return; // do whatever you want
|
||||
|
||||
if (CanChangeSkin(g_localplayers[2]))
|
||||
SendNameAndColor(2);
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
CV_StealthSet(&cv_skin[2], skins[players[g_localplayers[2]].skin].name);
|
||||
}
|
||||
Skin_OnChange(2);
|
||||
}
|
||||
|
||||
static void Skin4_OnChange(void)
|
||||
{
|
||||
if (!Playing() || splitscreen < 3)
|
||||
return; // do whatever you want
|
||||
|
||||
if (CanChangeSkin(g_localplayers[3]))
|
||||
SendNameAndColor(3);
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
CV_StealthSet(&cv_skin[3], skins[players[g_localplayers[3]].skin].name);
|
||||
}
|
||||
Skin_OnChange(3);
|
||||
}
|
||||
|
||||
/** Sends a color change for the console player, unless that player is moving.
|
||||
* \sa cv_playercolor, Color2_OnChange, Skin_OnChange
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void Color_OnChange(void)
|
||||
static void Color_OnChange(const UINT8 p)
|
||||
{
|
||||
if (!Playing())
|
||||
{
|
||||
if (!cv_playercolor[0].value || !skincolors[cv_playercolor[0].value].accessible)
|
||||
CV_StealthSetValue(&cv_playercolor[0], lastgoodcolor[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!CV_CheatsEnabled() && !(multiplayer || netgame)) // In single player.
|
||||
{
|
||||
CV_StealthSet(&cv_skin[0], skins[players[consoleplayer].skin].name);
|
||||
return;
|
||||
}
|
||||
I_Assert(p < MAXSPLITSCREENPLAYERS);
|
||||
|
||||
if (!P_PlayerMoving(consoleplayer) && skincolors[players[consoleplayer].skincolor].accessible == true)
|
||||
UINT16 color = cv_playercolor[p].value;
|
||||
boolean colorisgood = (color == SKINCOLOR_NONE || K_ColorUsable(color, false) == true);
|
||||
|
||||
if (Playing() && splitscreen < p)
|
||||
{
|
||||
if (P_PlayerMoving(g_localplayers[p]) == true)
|
||||
{
|
||||
colorisgood = false;
|
||||
}
|
||||
else if (colorisgood == true)
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor[0],
|
||||
players[consoleplayer].skincolor);
|
||||
SendNameAndColor(p);
|
||||
}
|
||||
}
|
||||
lastgoodcolor[0] = cv_playercolor[0].value;
|
||||
|
||||
G_SetPlayerGamepadIndicatorToPlayerColor(0);
|
||||
if (colorisgood == false)
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor[p], lastgoodcolor[p]);
|
||||
return;
|
||||
}
|
||||
|
||||
lastgoodcolor[p] = color;
|
||||
G_SetPlayerGamepadIndicatorToPlayerColor(p);
|
||||
}
|
||||
|
||||
static void Color1_OnChange(void)
|
||||
{
|
||||
Color_OnChange(0);
|
||||
}
|
||||
|
||||
/** Sends a color change for the secondary splitscreen player, unless that
|
||||
|
|
@ -6878,77 +6850,17 @@ static void Color_OnChange(void)
|
|||
*/
|
||||
static void Color2_OnChange(void)
|
||||
{
|
||||
if (!Playing() || splitscreen < 1)
|
||||
{
|
||||
if (!cv_playercolor[1].value || !skincolors[cv_playercolor[1].value].accessible)
|
||||
CV_StealthSetValue(&cv_playercolor[1], lastgoodcolor[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!P_PlayerMoving(g_localplayers[1]) && skincolors[players[g_localplayers[1]].skincolor].accessible == true)
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor[1],
|
||||
players[g_localplayers[1]].skincolor);
|
||||
}
|
||||
}
|
||||
lastgoodcolor[1] = cv_playercolor[1].value;
|
||||
|
||||
G_SetPlayerGamepadIndicatorToPlayerColor(1);
|
||||
Color_OnChange(1);
|
||||
}
|
||||
|
||||
static void Color3_OnChange(void)
|
||||
{
|
||||
if (!Playing() || splitscreen < 2)
|
||||
{
|
||||
if (!cv_playercolor[2].value || !skincolors[cv_playercolor[2].value].accessible)
|
||||
CV_StealthSetValue(&cv_playercolor[2], lastgoodcolor[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!P_PlayerMoving(g_localplayers[2]) && skincolors[players[g_localplayers[2]].skincolor].accessible == true)
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor[2],
|
||||
players[g_localplayers[2]].skincolor);
|
||||
}
|
||||
}
|
||||
lastgoodcolor[2] = cv_playercolor[2].value;
|
||||
|
||||
G_SetPlayerGamepadIndicatorToPlayerColor(2);
|
||||
Color_OnChange(2);
|
||||
}
|
||||
|
||||
static void Color4_OnChange(void)
|
||||
{
|
||||
if (!Playing() || splitscreen < 3)
|
||||
{
|
||||
if (!cv_playercolor[3].value || !skincolors[cv_playercolor[3].value].accessible)
|
||||
CV_StealthSetValue(&cv_playercolor[3], lastgoodcolor[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!P_PlayerMoving(g_localplayers[3]) && skincolors[players[g_localplayers[3]].skincolor].accessible == true)
|
||||
{
|
||||
// Color change menu scrolling fix is no longer necessary
|
||||
SendNameAndColor(3);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor[3],
|
||||
players[g_localplayers[3]].skincolor);
|
||||
}
|
||||
}
|
||||
lastgoodcolor[3] = cv_playercolor[3].value;
|
||||
|
||||
G_SetPlayerGamepadIndicatorToPlayerColor(3);
|
||||
Color_OnChange(3);
|
||||
}
|
||||
|
||||
/** Displays the result of the chat being muted or unmuted.
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ extern consvar_t cv_kartfrantic;
|
|||
extern consvar_t cv_kartencore;
|
||||
extern consvar_t cv_kartspeedometer;
|
||||
extern consvar_t cv_kartvoices;
|
||||
extern consvar_t cv_karthorns;
|
||||
extern consvar_t cv_kartbot;
|
||||
extern consvar_t cv_karteliminatelast;
|
||||
extern consvar_t cv_thunderdome;
|
||||
|
|
|
|||
|
|
@ -277,6 +277,7 @@ typedef enum
|
|||
khud_enginesnd, // Engine sound offset this player is using.
|
||||
khud_voices, // Used to stop the player saying more voices than it should
|
||||
khud_tauntvoices, // Used to specifically stop taunt voice spam
|
||||
khud_taunthorns, // Used to specifically stop taunt horn spam
|
||||
|
||||
// Battle
|
||||
khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ static inline int lib_freeslot(lua_State *L)
|
|||
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
|
||||
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||
strcpy(FREE_SKINCOLORS[i],word);
|
||||
M_AddMenuColor(numskincolors++);
|
||||
numskincolors++;
|
||||
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i);
|
||||
r++;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ void readfreeslots(MYFILE *f)
|
|||
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
|
||||
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
|
||||
strcpy(FREE_SKINCOLORS[i],word);
|
||||
M_AddMenuColor(numskincolors++);
|
||||
numskincolors++;
|
||||
break;
|
||||
}
|
||||
if (i == NUMCOLORFREESLOTS)
|
||||
|
|
@ -2338,6 +2338,8 @@ void readunlockable(MYFILE *f, INT32 num)
|
|||
unlockables[num].type = SECRET_SKIN;
|
||||
else if (fastcmp(word2, "FOLLOWER"))
|
||||
unlockables[num].type = SECRET_FOLLOWER;
|
||||
else if (fastcmp(word2, "COLOR"))
|
||||
unlockables[num].type = SECRET_COLOR;
|
||||
else if (fastcmp(word2, "HARDSPEED"))
|
||||
unlockables[num].type = SECRET_HARDSPEED;
|
||||
else if (fastcmp(word2, "MASTERMODE"))
|
||||
|
|
@ -2362,6 +2364,8 @@ void readunlockable(MYFILE *f, INT32 num)
|
|||
unlockables[num].type = SECRET_SOUNDTEST;
|
||||
else if (fastcmp(word2, "ALTTITLE"))
|
||||
unlockables[num].type = SECRET_ALTTITLE;
|
||||
else if (fastcmp(word2, "MEMETAUNTS"))
|
||||
unlockables[num].type = SECRET_MEMETAUNTS;
|
||||
else if (fastcmp(word2, "ITEMFINDER"))
|
||||
unlockables[num].type = SECRET_ITEMFINDER;
|
||||
else
|
||||
|
|
@ -3600,7 +3604,7 @@ void readfollower(MYFILE *f)
|
|||
INT32 res;
|
||||
INT32 i;
|
||||
|
||||
if (numfollowers >= MAXSKINS)
|
||||
if (numfollowers >= MAXFOLLOWERS)
|
||||
{
|
||||
I_Error("Out of Followers\nLoad less addons to fix this.");
|
||||
}
|
||||
|
|
@ -3623,6 +3627,7 @@ void readfollower(MYFILE *f)
|
|||
followers[numfollowers].hitconfirmtime = TICRATE;
|
||||
followers[numfollowers].defaultcolor = FOLLOWERCOLOR_MATCH;
|
||||
followers[numfollowers].category = UINT8_MAX;
|
||||
followers[numfollowers].hornsound = sfx_horn00;
|
||||
strcpy(followers[numfollowers].icon, "MISSING");
|
||||
|
||||
do
|
||||
|
|
@ -3708,6 +3713,10 @@ void readfollower(MYFILE *f)
|
|||
deh_warning("Follower %d: unknown follower color '%s'", numfollowers, word2);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "HORNSOUND"))
|
||||
{
|
||||
followers[numfollowers].hornsound = get_number(word2);
|
||||
}
|
||||
else if (fastcmp(word, "SCALE"))
|
||||
{
|
||||
followers[numfollowers].scale = (fixed_t)get_number(word2);
|
||||
|
|
|
|||
|
|
@ -3308,6 +3308,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
|
||||
"S_SERVANTHAND",
|
||||
|
||||
"S_HORNCODE",
|
||||
|
||||
// Signpost sparkles
|
||||
"S_SIGNSPARK1",
|
||||
"S_SIGNSPARK2",
|
||||
|
|
@ -5359,6 +5361,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
|
||||
"MT_SERVANTHAND",
|
||||
|
||||
"MT_HORNCODE",
|
||||
|
||||
"MT_SIGNSPARKLE",
|
||||
|
||||
"MT_FASTLINE",
|
||||
|
|
|
|||
|
|
@ -236,7 +236,7 @@ struct skincolor_t
|
|||
|
||||
#define FOLLOWERCOLOR_MATCH UINT16_MAX
|
||||
#define FOLLOWERCOLOR_OPPOSITE (UINT16_MAX-1)
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor);
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
|||
33
src/info.c
33
src/info.c
|
|
@ -563,6 +563,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
|
||||
"DHND", // Servant Hand
|
||||
|
||||
"HORN", // Horncode
|
||||
|
||||
"WIPD", // Wipeout dust trail
|
||||
"DRIF", // Drift Sparks
|
||||
"BDRF", // Brake drift sparks
|
||||
|
|
@ -3980,6 +3982,8 @@ state_t states[NUMSTATES] =
|
|||
|
||||
{SPR_DHND, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SERVANTHAND
|
||||
|
||||
{SPR_HORN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HORNCODE
|
||||
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3
|
||||
|
|
@ -22840,6 +22844,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_HORNCODE
|
||||
-1, // doomednum
|
||||
S_HORNCODE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
36*FRACUNIT, // radius
|
||||
36*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SIGNSPARKLE
|
||||
-1, // doomednum
|
||||
|
|
@ -29868,7 +29899,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
};
|
||||
|
||||
skincolor_t skincolors[MAXSKINCOLORS] = {
|
||||
{"None", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_NONE
|
||||
{"Default", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, SKINCOLOR_NONE, 0, 0, false}, // SKINCOLOR_NONE
|
||||
|
||||
{"White", { 0, 0, 0, 0, 1, 2, 5, 8, 9, 11, 14, 17, 20, 22, 25, 28}, SKINCOLOR_BLACK, 8, 0, true}, // SKINCOLOR_WHITE
|
||||
{"Silver", { 0, 1, 2, 3, 5, 7, 9, 12, 13, 15, 18, 20, 23, 25, 27, 30}, SKINCOLOR_NICKEL, 8, 0, true}, // SKINCOLOR_SILVER
|
||||
|
|
|
|||
|
|
@ -1114,6 +1114,8 @@ typedef enum sprite
|
|||
|
||||
SPR_DHND, // Servant Hand
|
||||
|
||||
SPR_HORN, // Horncode
|
||||
|
||||
SPR_WIPD, // Wipeout dust trail
|
||||
SPR_DRIF, // Drift Sparks
|
||||
SPR_BDRF, // Brake drift sparks
|
||||
|
|
@ -4390,6 +4392,8 @@ typedef enum state
|
|||
|
||||
S_SERVANTHAND,
|
||||
|
||||
S_HORNCODE,
|
||||
|
||||
// Signpost sparkles
|
||||
S_SIGNSPARK1,
|
||||
S_SIGNSPARK2,
|
||||
|
|
@ -6476,6 +6480,8 @@ typedef enum mobj_type
|
|||
|
||||
MT_SERVANTHAND,
|
||||
|
||||
MT_HORNCODE,
|
||||
|
||||
MT_SIGNSPARKLE,
|
||||
|
||||
MT_FASTLINE,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
#include "r_draw.h"
|
||||
#include "r_things.h"
|
||||
#include "v_video.h"
|
||||
#include "m_cond.h"
|
||||
#include "g_demo.h"
|
||||
#include "k_follower.h"
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b)
|
||||
|
|
@ -213,4 +216,63 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_ColorUsable(skincolornum_t color, boolean follower)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
boolean K_ColorUsable(skincolornum_t color, boolean follower)
|
||||
{
|
||||
INT32 i = MAXUNLOCKABLES;
|
||||
|
||||
if (color == FOLLOWERCOLOR_MATCH || color == FOLLOWERCOLOR_OPPOSITE)
|
||||
{
|
||||
// Special follower colors, always allow if follower.
|
||||
return follower;
|
||||
}
|
||||
|
||||
if (skincolors[color].accessible == false)
|
||||
{
|
||||
// Never intended to be used.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (demo.playback)
|
||||
{
|
||||
// Simplifies things elsewhere...
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if this follower is supposed to be unlockable or not
|
||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||
{
|
||||
skincolornum_t cid = SKINCOLOR_NONE;
|
||||
|
||||
if (unlockables[i].type != SECRET_COLOR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
cid = M_UnlockableColorNum(&unlockables[i]);
|
||||
|
||||
if (cid != color)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// i is now the unlockable index, we can use this later
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == MAXUNLOCKABLES)
|
||||
{
|
||||
// Didn't trip anything, so we can use this color.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use the unlockables table directly
|
||||
// DEFINITELY not M_CheckNetUnlockByID
|
||||
return (boolean)(gamedata->unlocked[i]);
|
||||
}
|
||||
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -112,8 +112,27 @@ void K_HitlagColormap(UINT8 *dest_colormap);
|
|||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_ColorUsable(skincolornum_t color, skin_t *skin, follower_t *follower);
|
||||
|
||||
Determines whenever or not we meet the unlockable conditions
|
||||
to use a certain color.
|
||||
|
||||
Input Arguments:-
|
||||
color - Color we want to use.
|
||||
follower - Set to include the special follower-only color options.
|
||||
|
||||
Return:-
|
||||
true if we can use it, otherwise false.
|
||||
--------------------------------------------------*/
|
||||
|
||||
boolean K_ColorUsable(skincolornum_t color, boolean follower);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
219
src/k_follower.c
219
src/k_follower.c
|
|
@ -11,10 +11,11 @@
|
|||
#include "r_skins.h"
|
||||
#include "p_local.h"
|
||||
#include "p_mobj.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_cond.h"
|
||||
|
||||
INT32 numfollowers = 0;
|
||||
follower_t followers[MAXSKINS];
|
||||
follower_t followers[MAXFOLLOWERS];
|
||||
|
||||
INT32 numfollowercategories;
|
||||
followercategory_t followercategories[MAXFOLLOWERCATEGORIES];
|
||||
|
|
@ -142,6 +143,11 @@ void K_RemoveFollower(player_t *player)
|
|||
bub = tmp;
|
||||
}
|
||||
|
||||
// And the honk.
|
||||
bub = player->follower->hprev;
|
||||
if (!P_MobjWasRemoved(bub))
|
||||
P_RemoveMobj(bub);
|
||||
|
||||
P_RemoveMobj(player->follower);
|
||||
P_SetTarget(&player->follower, NULL);
|
||||
}
|
||||
|
|
@ -234,19 +240,39 @@ static void K_SetFollowerState(mobj_t *f, statenum_t state)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor)
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor)
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin)
|
||||
{
|
||||
if (followercolor < numskincolors) // bog standard
|
||||
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;
|
||||
}
|
||||
|
||||
//if (followercolor == FOLLOWERCOLOR_MATCH) -- "Match"
|
||||
// "Match"
|
||||
return playercolor;
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +312,7 @@ static void K_UpdateFollowerState(mobj_t *f, statenum_t state, followerstate_t t
|
|||
--------------------------------------------------*/
|
||||
void K_HandleFollower(player_t *player)
|
||||
{
|
||||
follower_t fl;
|
||||
follower_t *fl;
|
||||
angle_t an;
|
||||
fixed_t zoffs;
|
||||
fixed_t ourheight;
|
||||
|
|
@ -326,22 +352,22 @@ void K_HandleFollower(player_t *player)
|
|||
}
|
||||
|
||||
// Before we do anything, let's be sure of where we're supposed to be
|
||||
fl = followers[player->followerskin];
|
||||
fl = &followers[player->followerskin];
|
||||
|
||||
an = player->mo->angle + fl.atangle;
|
||||
zoffs = fl.zoffs;
|
||||
bubble = fl.bubblescale; // 0 if no bubble to spawn.
|
||||
an = player->mo->angle + fl->atangle;
|
||||
zoffs = fl->zoffs;
|
||||
bubble = fl->bubblescale; // 0 if no bubble to spawn.
|
||||
|
||||
// do you like angle maths? I certainly don't...
|
||||
sx = player->mo->x + player->mo->momx + FixedMul(FixedMul(player->mo->scale, fl.dist), FINECOSINE((an) >> ANGLETOFINESHIFT));
|
||||
sy = player->mo->y + player->mo->momy + FixedMul(FixedMul(player->mo->scale, fl.dist), FINESINE((an) >> ANGLETOFINESHIFT));
|
||||
sx = player->mo->x + player->mo->momx + FixedMul(FixedMul(player->mo->scale, fl->dist), FINECOSINE((an) >> ANGLETOFINESHIFT));
|
||||
sy = player->mo->y + player->mo->momy + FixedMul(FixedMul(player->mo->scale, fl->dist), FINESINE((an) >> ANGLETOFINESHIFT));
|
||||
|
||||
// interp info helps with stretchy fix
|
||||
deltaz = (player->mo->z - player->mo->old_z);
|
||||
|
||||
// for the z coordinate, don't be a doof like Steel and forget that MFE_VERTICALFLIP exists :P
|
||||
sz = player->mo->z + player->mo->momz + FixedMul(player->mo->scale, zoffs * P_MobjFlip(player->mo));
|
||||
ourheight = FixedMul(fl.height, player->mo->scale);
|
||||
ourheight = FixedMul(fl->height, player->mo->scale);
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
sz += ourheight;
|
||||
|
|
@ -350,7 +376,7 @@ void K_HandleFollower(player_t *player)
|
|||
fh = player->mo->floorz;
|
||||
ch = player->mo->ceilingz - ourheight;
|
||||
|
||||
switch (fl.mode)
|
||||
switch (fl->mode)
|
||||
{
|
||||
case FOLLOWERMODE_GROUND:
|
||||
{
|
||||
|
|
@ -369,9 +395,9 @@ void K_HandleFollower(player_t *player)
|
|||
{
|
||||
// finally, add a cool floating effect to the z height.
|
||||
// not stolen from k_kart I swear!!
|
||||
fixed_t sine = FixedMul(fl.bobamp,
|
||||
fixed_t sine = FixedMul(fl->bobamp,
|
||||
FINESINE(((
|
||||
FixedMul(4 * M_TAU_FIXED, fl.bobspeed) * leveltime
|
||||
FixedMul(4 * M_TAU_FIXED, fl->bobspeed) * leveltime
|
||||
) >> ANGLETOFINESHIFT) & FINEMASK));
|
||||
sz += FixedMul(player->mo->scale, sine) * P_MobjFlip(player->mo);
|
||||
break;
|
||||
|
|
@ -379,7 +405,7 @@ void K_HandleFollower(player_t *player)
|
|||
}
|
||||
|
||||
// Set follower colour
|
||||
color = K_GetEffectiveFollowerColor(player->followercolor, player->skincolor);
|
||||
color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, &skins[player->skin]);
|
||||
|
||||
if (player->follower == NULL || P_MobjWasRemoved(player->follower)) // follower doesn't exist / isn't valid
|
||||
{
|
||||
|
|
@ -390,7 +416,7 @@ void K_HandleFollower(player_t *player)
|
|||
if (player->follower == NULL)
|
||||
return;
|
||||
|
||||
K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE);
|
||||
K_UpdateFollowerState(player->follower, fl->idlestate, FOLLOWERSTATE_IDLE);
|
||||
|
||||
P_SetTarget(&player->follower->target, player->mo); // we need that to know when we need to disappear
|
||||
player->follower->angle = player->follower->old_angle = player->mo->angle;
|
||||
|
|
@ -422,12 +448,12 @@ void K_HandleFollower(player_t *player)
|
|||
}
|
||||
|
||||
// move the follower next to us (yes, this is really basic maths but it looks pretty damn clean in practice)!
|
||||
player->follower->momx = FixedDiv(sx - player->follower->x, fl.horzlag);
|
||||
player->follower->momy = FixedDiv(sy - player->follower->y, fl.horzlag);
|
||||
player->follower->momx = FixedDiv(sx - player->follower->x, fl->horzlag);
|
||||
player->follower->momy = FixedDiv(sy - player->follower->y, fl->horzlag);
|
||||
|
||||
player->follower->z += FixedDiv(deltaz, fl.vertlag);
|
||||
player->follower->z += FixedDiv(deltaz, fl->vertlag);
|
||||
|
||||
if (fl.mode == FOLLOWERMODE_GROUND)
|
||||
if (fl->mode == FOLLOWERMODE_GROUND)
|
||||
{
|
||||
sector_t *sec = R_PointInSubsector(sx, sy)->sector;
|
||||
|
||||
|
|
@ -448,12 +474,12 @@ void K_HandleFollower(player_t *player)
|
|||
|
||||
// Player is on the ground ... try to get the follower
|
||||
// back to the ground also if it is above it.
|
||||
player->follower->momz += FixedDiv(fg * 6, fl.vertlag); // Scaled against the default value of vertlag
|
||||
player->follower->momz += FixedDiv(fg * 6, fl->vertlag); // Scaled against the default value of vertlag
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player->follower->momz = FixedDiv(sz - player->follower->z, fl.vertlag);
|
||||
player->follower->momz = FixedDiv(sz - player->follower->z, fl->vertlag);
|
||||
}
|
||||
|
||||
if (player->mo->colorized)
|
||||
|
|
@ -467,7 +493,7 @@ void K_HandleFollower(player_t *player)
|
|||
|
||||
player->follower->colorized = player->mo->colorized;
|
||||
|
||||
P_SetScale(player->follower, FixedMul(fl.scale, player->mo->scale));
|
||||
P_SetScale(player->follower, FixedMul(fl->scale, player->mo->scale));
|
||||
K_GenericExtraFlagsNoZAdjust(player->follower, player->mo); // Not K_MatchGenericExtraFlag because the Z adjust it has only works properly if master & mo have the same Z height.
|
||||
|
||||
// Match how the player is being drawn
|
||||
|
|
@ -501,20 +527,20 @@ void K_HandleFollower(player_t *player)
|
|||
|
||||
if (angleDiff != 0)
|
||||
{
|
||||
player->follower->angle += FixedDiv(angleDiff, fl.anglelag);
|
||||
player->follower->angle += FixedDiv(angleDiff, fl->anglelag);
|
||||
}
|
||||
|
||||
// Ground follower slope rotation
|
||||
if (fl.mode == FOLLOWERMODE_GROUND)
|
||||
if (fl->mode == FOLLOWERMODE_GROUND)
|
||||
{
|
||||
if (player->follower->z <= fh)
|
||||
{
|
||||
player->follower->z = fh;
|
||||
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP) && player->follower->momz <= 0 && fl.bobamp != 0)
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP) && player->follower->momz <= 0 && fl->bobamp != 0)
|
||||
{
|
||||
// Ground bounce
|
||||
player->follower->momz = P_GetMobjZMovement(player->mo) + FixedMul(fl.bobamp, player->follower->scale);
|
||||
player->follower->momz = P_GetMobjZMovement(player->mo) + FixedMul(fl->bobamp, player->follower->scale);
|
||||
player->follower->extravalue1 = FOLLOWERSTATE_RESET;
|
||||
}
|
||||
else if (player->follower->momz < 0)
|
||||
|
|
@ -527,10 +553,10 @@ void K_HandleFollower(player_t *player)
|
|||
{
|
||||
player->follower->z = ch;
|
||||
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) && player->follower->momz >= 0 && fl.bobamp != 0)
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) && player->follower->momz >= 0 && fl->bobamp != 0)
|
||||
{
|
||||
// Ground bounce
|
||||
player->follower->momz = P_GetMobjZMovement(player->mo) - FixedMul(fl.bobamp, player->follower->scale);
|
||||
player->follower->momz = P_GetMobjZMovement(player->mo) - FixedMul(fl->bobamp, player->follower->scale);
|
||||
player->follower->extravalue1 = FOLLOWERSTATE_RESET;
|
||||
}
|
||||
else if (player->follower->momz > 0)
|
||||
|
|
@ -559,7 +585,7 @@ void K_HandleFollower(player_t *player)
|
|||
// match follower's momentums and (e)flags(2).
|
||||
bmobj->momx = player->follower->momx;
|
||||
bmobj->momy = player->follower->momy;
|
||||
bmobj->z += FixedDiv(deltaz, fl.vertlag);
|
||||
bmobj->z += FixedDiv(deltaz, fl->vertlag);
|
||||
bmobj->momz = player->follower->momz;
|
||||
|
||||
P_SetScale(bmobj, FixedMul(bubble, player->mo->scale));
|
||||
|
|
@ -594,7 +620,7 @@ void K_HandleFollower(player_t *player)
|
|||
// spin out
|
||||
player->follower->angle = player->drawangle;
|
||||
|
||||
K_UpdateFollowerState(player->follower, fl.hurtstate, FOLLOWERSTATE_HURT);
|
||||
K_UpdateFollowerState(player->follower, fl->hurtstate, FOLLOWERSTATE_HURT);
|
||||
|
||||
if (player->mo->health <= 0)
|
||||
{
|
||||
|
|
@ -608,26 +634,70 @@ void K_HandleFollower(player_t *player)
|
|||
if (K_IsPlayerLosing(player))
|
||||
{
|
||||
// L
|
||||
K_UpdateFollowerState(player->follower, fl.losestate, FOLLOWERSTATE_LOSE);
|
||||
K_UpdateFollowerState(player->follower, fl->losestate, FOLLOWERSTATE_LOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// W
|
||||
K_UpdateFollowerState(player->follower, fl.winstate, FOLLOWERSTATE_WIN);
|
||||
K_UpdateFollowerState(player->follower, fl->winstate, FOLLOWERSTATE_WIN);
|
||||
}
|
||||
}
|
||||
else if (player->follower->movecount)
|
||||
{
|
||||
K_UpdateFollowerState(player->follower, fl.hitconfirmstate, FOLLOWERSTATE_HITCONFIRM);
|
||||
K_UpdateFollowerState(player->follower, fl->hitconfirmstate, FOLLOWERSTATE_HITCONFIRM);
|
||||
player->follower->movecount--;
|
||||
}
|
||||
else if (player->speed > 10*player->mo->scale) // animation for moving fast enough
|
||||
{
|
||||
K_UpdateFollowerState(player->follower, fl.followstate, FOLLOWERSTATE_FOLLOW);
|
||||
K_UpdateFollowerState(player->follower, fl->followstate, FOLLOWERSTATE_FOLLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE);
|
||||
K_UpdateFollowerState(player->follower, fl->idlestate, FOLLOWERSTATE_IDLE);
|
||||
}
|
||||
|
||||
// Horncode
|
||||
if (P_MobjWasRemoved(player->follower->hprev) == false)
|
||||
{
|
||||
mobj_t *honk = player->follower->hprev;
|
||||
|
||||
honk->flags2 &= ~MF2_AMBUSH;
|
||||
|
||||
honk->color = player->skincolor;
|
||||
|
||||
P_MoveOrigin(
|
||||
honk,
|
||||
player->follower->x,
|
||||
player->follower->y,
|
||||
player->follower->z + player->follower->height
|
||||
);
|
||||
|
||||
K_FlipFromObject(honk, player->follower);
|
||||
|
||||
honk->angle = R_PointToAngle2(
|
||||
player->mo->x,
|
||||
player->mo->y,
|
||||
player->follower->x,
|
||||
player->follower->y
|
||||
);
|
||||
|
||||
honk->destscale = (2*player->mo->scale)/3;
|
||||
|
||||
fixed_t offsetamount = 0;
|
||||
if (honk->fuse > 1)
|
||||
{
|
||||
offsetamount = (honk->fuse-1)*honk->destscale/2;
|
||||
if (leveltime & 1)
|
||||
offsetamount = -offsetamount;
|
||||
}
|
||||
else if (S_SoundPlaying(honk, fl->hornsound))
|
||||
{
|
||||
honk->fuse++;
|
||||
}
|
||||
|
||||
honk->sprxoff = P_ReturnThrustX(honk, honk->angle, offsetamount);
|
||||
honk->spryoff = P_ReturnThrustY(honk, honk->angle, offsetamount);
|
||||
honk->sprzoff = -honk->sprxoff;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -638,3 +708,76 @@ void K_HandleFollower(player_t *player)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim)
|
||||
{
|
||||
if (
|
||||
(cv_karthorns.value == 0)
|
||||
|| taunter == NULL
|
||||
|| victim == NULL
|
||||
|| taunter->followerskin < 0
|
||||
|| taunter->followerskin >= numfollowers
|
||||
|| (P_IsLocalPlayer(victim) == false && cv_karthorns.value != 2)
|
||||
|| P_MobjWasRemoved(taunter->mo) == true
|
||||
|| P_MobjWasRemoved(taunter->follower) == true
|
||||
)
|
||||
return;
|
||||
|
||||
const follower_t *fl = &followers[taunter->followerskin];
|
||||
|
||||
const boolean tasteful = (taunter->karthud[khud_taunthorns] == 0);
|
||||
|
||||
if (tasteful || cv_karthorns.value == 2)
|
||||
{
|
||||
mobj_t *honk = taunter->follower->hprev;
|
||||
const fixed_t desiredscale = (2*taunter->mo->scale)/3;
|
||||
|
||||
if (P_MobjWasRemoved(honk) == true)
|
||||
{
|
||||
honk = P_SpawnMobj(
|
||||
taunter->follower->x,
|
||||
taunter->follower->y,
|
||||
taunter->follower->z + taunter->follower->height,
|
||||
MT_HORNCODE
|
||||
);
|
||||
|
||||
if (P_MobjWasRemoved(honk) == true)
|
||||
return; // Permit lua override of horn production
|
||||
|
||||
P_SetTarget(&taunter->follower->hprev, honk);
|
||||
P_SetTarget(&honk->target, taunter->follower);
|
||||
|
||||
K_FlipFromObject(honk, taunter->follower);
|
||||
|
||||
honk->color = taunter->skincolor;
|
||||
|
||||
honk->angle = honk->old_angle = R_PointToAngle2(
|
||||
taunter->mo->x,
|
||||
taunter->mo->y,
|
||||
taunter->follower->x,
|
||||
taunter->follower->y
|
||||
);
|
||||
}
|
||||
|
||||
// Only do for the first activation this tic.
|
||||
if (!(honk->flags2 & MF2_AMBUSH))
|
||||
{
|
||||
honk->destscale = desiredscale;
|
||||
|
||||
P_SetScale(honk, (11*desiredscale)/10);
|
||||
honk->fuse = TICRATE/2;
|
||||
honk->renderflags |= RF_DONTDRAW;
|
||||
|
||||
S_StartSound(taunter->follower, fl->hornsound);
|
||||
|
||||
honk->flags2 |= MF2_AMBUSH;
|
||||
}
|
||||
|
||||
honk->renderflags &= ~K_GetPlayerDontDrawFlag(victim);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
// The important collorary to "Hornmod is universally hated in dev" is
|
||||
// the simple phrase "this is why" -- 1024 is obscene yet will fill up.
|
||||
// By the way, this comment will grow stronger and stronger every time
|
||||
// somebody comes here to double it, so I encourage you to leave a new
|
||||
// (dated) comment every time you do so. ~toast 280623
|
||||
#define MAXFOLLOWERS 1024
|
||||
|
||||
#define FOLLOWERCOLOR_MATCH UINT16_MAX
|
||||
#define FOLLOWERCOLOR_OPPOSITE (UINT16_MAX-1)
|
||||
|
||||
|
|
@ -85,12 +92,14 @@ struct follower_t
|
|||
statenum_t losestate; // state when the player has lost
|
||||
statenum_t hitconfirmstate; // state for hit confirm
|
||||
tic_t hitconfirmtime; // time to keep the above playing for
|
||||
|
||||
sfxenum_t hornsound; // Press (B) to announce you are pressing (B)
|
||||
};
|
||||
|
||||
extern INT32 numfollowers;
|
||||
extern follower_t followers[MAXSKINS];
|
||||
extern follower_t followers[MAXFOLLOWERS];
|
||||
|
||||
#define MAXFOLLOWERCATEGORIES 32
|
||||
#define MAXFOLLOWERCATEGORIES 64
|
||||
|
||||
struct followercategory_t
|
||||
{
|
||||
|
|
@ -170,20 +179,22 @@ void K_SetFollowerByNum(INT32 playernum, INT32 skinnum);
|
|||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor)
|
||||
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, UINT16 playercolor);
|
||||
UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, UINT16 playercolor, skin_t *playerskin);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -215,6 +226,21 @@ void K_HandleFollower(player_t *player);
|
|||
|
||||
void K_RemoveFollower(player_t *player);
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim)
|
||||
|
||||
Plays horn and spawns object (MOSTLY non-netsynced)
|
||||
|
||||
Input Arguments:-
|
||||
taunter - Source player with a follower
|
||||
victim - Player that hears and sees the honk
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
|
||||
void K_FollowerHornTaunt(player_t *taunter, player_t *victim);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
76
src/k_kart.c
76
src/k_kart.c
|
|
@ -359,6 +359,7 @@ void K_RegisterKartStuff(void)
|
|||
CV_RegisterVar(&cv_kartencore);
|
||||
CV_RegisterVar(&cv_kartspeedometer);
|
||||
CV_RegisterVar(&cv_kartvoices);
|
||||
CV_RegisterVar(&cv_karthorns);
|
||||
CV_RegisterVar(&cv_kartbot);
|
||||
CV_RegisterVar(&cv_karteliminatelast);
|
||||
CV_RegisterVar(&cv_thunderdome);
|
||||
|
|
@ -2055,13 +2056,29 @@ void K_SpawnMagicianParticles(mobj_t *mo, int spread)
|
|||
}
|
||||
}
|
||||
|
||||
static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
||||
static SINT8 K_GlanceAtPlayers(player_t *glancePlayer, boolean horn)
|
||||
{
|
||||
const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
const angle_t blindSpotSize = ANG10; // ANG5
|
||||
UINT8 i;
|
||||
SINT8 glanceDir = 0;
|
||||
SINT8 lastValidGlance = 0;
|
||||
boolean podiumspecial = (K_PodiumSequence() == true && glancePlayer->nextwaypoint == NULL && glancePlayer->speed == 0);
|
||||
|
||||
if (podiumspecial)
|
||||
{
|
||||
if (glancePlayer->position > 3)
|
||||
{
|
||||
// Loser valley, focused on the mountain.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (glancePlayer->position == 1)
|
||||
{
|
||||
// Sitting on the stand, I ammm thebest!
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// See if there's any players coming up behind us.
|
||||
// If so, your character will glance at 'em.
|
||||
|
|
@ -2099,9 +2116,17 @@ static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
|||
continue;
|
||||
}
|
||||
|
||||
distance = R_PointToDist2(glancePlayer->mo->x, glancePlayer->mo->y, p->mo->x, p->mo->y);
|
||||
if (!podiumspecial)
|
||||
{
|
||||
distance = R_PointToDist2(glancePlayer->mo->x, glancePlayer->mo->y, p->mo->x, p->mo->y);
|
||||
|
||||
if (distance > maxdistance)
|
||||
if (distance > maxdistance)
|
||||
{
|
||||
// Too far away
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (p->position >= glancePlayer->position)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2115,7 +2140,7 @@ static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
|||
dir = -dir;
|
||||
}
|
||||
|
||||
if (diff > ANGLE_90)
|
||||
if (diff > (podiumspecial ? (ANGLE_180 - blindSpotSize) : ANGLE_90))
|
||||
{
|
||||
// Not behind the player
|
||||
continue;
|
||||
|
|
@ -2127,16 +2152,33 @@ static SINT8 K_GlanceAtPlayers(player_t *glancePlayer)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (P_CheckSight(glancePlayer->mo, p->mo) == true)
|
||||
if (!podiumspecial && P_CheckSight(glancePlayer->mo, p->mo) == false)
|
||||
{
|
||||
// Not blocked by a wall, we can glance at 'em!
|
||||
// Adds, so that if there's more targets on one of your sides, it'll glance on that side.
|
||||
glanceDir += dir;
|
||||
|
||||
// That poses a limitation if there's an equal number of targets on both sides...
|
||||
// In that case, we'll pick the last chosen glance direction.
|
||||
lastValidGlance = dir;
|
||||
// Blocked by a wall, we can't glance at 'em!
|
||||
continue;
|
||||
}
|
||||
|
||||
// Adds, so that if there's more targets on one of your sides, it'll glance on that side.
|
||||
glanceDir += dir;
|
||||
|
||||
// That poses a limitation if there's an equal number of targets on both sides...
|
||||
// In that case, we'll pick the last chosen glance direction.
|
||||
lastValidGlance = dir;
|
||||
|
||||
if (horn == true)
|
||||
{
|
||||
K_FollowerHornTaunt(glancePlayer, p);
|
||||
}
|
||||
}
|
||||
|
||||
if (horn == true && lastValidGlance != 0)
|
||||
{
|
||||
const boolean tasteful = (glancePlayer->karthud[khud_taunthorns] == 0);
|
||||
|
||||
K_FollowerHornTaunt(glancePlayer, glancePlayer);
|
||||
|
||||
if (tasteful && glancePlayer->karthud[khud_taunthorns] < 2*TICRATE)
|
||||
glancePlayer->karthud[khud_taunthorns] = 2*TICRATE;
|
||||
}
|
||||
|
||||
if (glanceDir > 0)
|
||||
|
|
@ -2215,7 +2257,8 @@ void K_KartMoveAnimation(player_t *player)
|
|||
{
|
||||
// Only try glancing if you're driving straight.
|
||||
// This avoids all-players loops when we don't need it.
|
||||
destGlanceDir = K_GlanceAtPlayers(player);
|
||||
const boolean horn = lookback && !(player->pflags & PF_GAINAX);
|
||||
destGlanceDir = K_GlanceAtPlayers(player, horn);
|
||||
|
||||
if (lookback == true)
|
||||
{
|
||||
|
|
@ -2649,7 +2692,9 @@ void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker)
|
|||
attacker->player->confirmVictim = (victim->player - players);
|
||||
attacker->player->confirmVictimDelay = TICRATE/2;
|
||||
|
||||
if (attacker->player->follower != NULL)
|
||||
if (attacker->player->follower != NULL
|
||||
&& attacker->player->followerskin >= 0
|
||||
&& attacker->player->followerskin < numfollowers)
|
||||
{
|
||||
const follower_t *fl = &followers[attacker->player->followerskin];
|
||||
attacker->player->follower->movecount = fl->hitconfirmtime; // movecount is used to play the hitconfirm animation for followers.
|
||||
|
|
@ -7415,6 +7460,9 @@ void K_KartPlayerHUDUpdate(player_t *player)
|
|||
if (player->karthud[khud_tauntvoices])
|
||||
player->karthud[khud_tauntvoices]--;
|
||||
|
||||
if (player->karthud[khud_taunthorns])
|
||||
player->karthud[khud_taunthorns]--;
|
||||
|
||||
if (player->karthud[khud_trickcool])
|
||||
player->karthud[khud_trickcool]--;
|
||||
|
||||
|
|
|
|||
20
src/k_menu.h
20
src/k_menu.h
|
|
@ -642,17 +642,12 @@ void M_MenuTypingInput(INT32 key);
|
|||
void M_QuitResponse(INT32 ch);
|
||||
void M_QuitSRB2(INT32 choice);
|
||||
|
||||
extern UINT16 nummenucolors;
|
||||
void M_AddMenuColor(UINT16 color);
|
||||
void M_MoveColorBefore(UINT16 color, UINT16 targ);
|
||||
void M_MoveColorAfter(UINT16 color, UINT16 targ);
|
||||
UINT16 M_GetColorBefore(UINT16 color, UINT16 amount, boolean follower);
|
||||
UINT16 M_GetColorAfter(UINT16 color, UINT16 amount, boolean follower);
|
||||
void M_InitPlayerSetupColors(void);
|
||||
void M_FreePlayerSetupColors(void);
|
||||
UINT16 M_GetColorAfter(setup_player_colors_t *colors, UINT16 value, INT32 amount);
|
||||
#define M_GetColorBefore(a, b, c) M_GetColorAfter(a, b, -c)
|
||||
|
||||
// If you want to waste a bunch of memory for a limit no one will hit, feel free to boost this to MAXSKINS :P
|
||||
// I figure this will be enough clone characters to fit onto one grid space.
|
||||
// TODO: Dynamically allocate instead, you KNOW this limit will get hit by someone eventually
|
||||
#define MAXCLONES MAXSKINS/8
|
||||
|
||||
extern struct setup_chargrid_s {
|
||||
|
|
@ -677,6 +672,13 @@ typedef enum
|
|||
CSSTEP_READY
|
||||
} setup_mdepth_t;
|
||||
|
||||
struct setup_player_colors_t
|
||||
{
|
||||
UINT16 *list;
|
||||
size_t listLen;
|
||||
size_t listCap;
|
||||
};
|
||||
|
||||
struct setup_player_t
|
||||
{
|
||||
SINT8 gridx, gridy;
|
||||
|
|
@ -704,6 +706,8 @@ struct setup_player_t
|
|||
tic_t follower_timer;
|
||||
UINT8 follower_frame;
|
||||
state_t *follower_state;
|
||||
|
||||
setup_player_colors_t colors;
|
||||
};
|
||||
|
||||
extern setup_player_t setup_player[MAXSPLITSCREENPLAYERS];
|
||||
|
|
|
|||
194
src/k_menudraw.c
194
src/k_menudraw.c
|
|
@ -1226,7 +1226,8 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
numoptions = setup_chargrid[p->gridx][p->gridy].numskins;
|
||||
break;
|
||||
case CSSTEP_COLORS:
|
||||
numoptions = nummenucolors;
|
||||
case CSSTEP_FOLLOWERCOLORS:
|
||||
numoptions = p->colors.listLen;
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCATEGORY:
|
||||
numoptions = setup_numfollowercategories+1;
|
||||
|
|
@ -1234,9 +1235,6 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
case CSSTEP_FOLLOWER:
|
||||
numoptions = setup_followercategories[p->followercategory][0];
|
||||
break;
|
||||
case CSSTEP_FOLLOWERCOLORS:
|
||||
numoptions = nummenucolors+2;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
@ -1289,20 +1287,20 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
|
||||
if (i == 0)
|
||||
{
|
||||
n = l = r = M_GetColorBefore(p->color, numoptions/2, false);
|
||||
n = l = r = M_GetColorBefore(&p->colors, p->color, (numoptions/2) - 1);
|
||||
}
|
||||
else if (subtract)
|
||||
{
|
||||
n = l = M_GetColorBefore(l, 1, false);
|
||||
n = l = M_GetColorBefore(&p->colors, l, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = r = M_GetColorAfter(r, 1, false);
|
||||
n = r = M_GetColorAfter(&p->colors, r, 1);
|
||||
}
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, n, GTC_MENUCACHE);
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, (n == SKINCOLOR_NONE) ? skins[p->skin].prefcolor : n, GTC_MENUCACHE);
|
||||
|
||||
diff = (numoptions - i)/2; // only 0 when i == numoptions-1
|
||||
diff = (numoptions - i) / 2; // only 0 when i == numoptions-1
|
||||
|
||||
if (diff == 0)
|
||||
patch = W_CachePatchName("COLORSP2", PU_CACHE);
|
||||
|
|
@ -1399,7 +1397,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
patch = W_CachePatchName(fl->icon, PU_CACHE);
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT,
|
||||
K_GetEffectiveFollowerColor(fl->defaultcolor, p->color),
|
||||
K_GetEffectiveFollowerColor(fl->defaultcolor, fl, p->color, &skins[p->skin]),
|
||||
GTC_MENUCACHE
|
||||
);
|
||||
}
|
||||
|
|
@ -1418,18 +1416,18 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
|
|||
|
||||
if (i == 0)
|
||||
{
|
||||
n = l = r = M_GetColorBefore(p->followercolor, numoptions/2, true);
|
||||
n = l = r = M_GetColorBefore(&p->colors, p->followercolor, (numoptions/2) - 1);
|
||||
}
|
||||
else if (subtract)
|
||||
{
|
||||
n = l = M_GetColorBefore(l, 1, true);
|
||||
n = l = M_GetColorBefore(&p->colors, l, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = r = M_GetColorAfter(r, 1, true);
|
||||
n = r = M_GetColorAfter(&p->colors, r, 1);
|
||||
}
|
||||
|
||||
col = K_GetEffectiveFollowerColor(n, p->color);
|
||||
col = K_GetEffectiveFollowerColor(n, &followers[p->followern], p->color, &skins[p->skin]);
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
|
||||
|
|
@ -1517,14 +1515,13 @@ static boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, U
|
|||
// 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, boolean charflip, INT32 addflags, UINT8 *colormap, setup_player_t *p)
|
||||
{
|
||||
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
patch_t *patch;
|
||||
INT32 followernum;
|
||||
state_t *usestate;
|
||||
UINT32 useframe;
|
||||
follower_t fl;
|
||||
follower_t *fl;
|
||||
UINT8 rotation = (charflip ? 1 : 7);
|
||||
|
||||
if (p != NULL)
|
||||
|
|
@ -1536,7 +1533,7 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, boolean charfli
|
|||
if (followernum < 0 || followernum >= numfollowers)
|
||||
return false;
|
||||
|
||||
fl = followers[followernum];
|
||||
fl = &followers[followernum];
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
|
|
@ -1569,13 +1566,16 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, boolean charfli
|
|||
if (p != NULL)
|
||||
{
|
||||
UINT16 color = K_GetEffectiveFollowerColor(
|
||||
(p->mdepth < CSSTEP_FOLLOWERCOLORS) ? fl.defaultcolor : p->followercolor,
|
||||
p->color);
|
||||
sine = FixedMul(fl.bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, fl.bobspeed) * p->follower_timer)>>ANGLETOFINESHIFT) & FINEMASK));
|
||||
(p->mdepth < CSSTEP_FOLLOWERCOLORS) ? fl->defaultcolor : p->followercolor,
|
||||
fl,
|
||||
p->color,
|
||||
&skins[p->skin]
|
||||
);
|
||||
sine = FixedMul(fl->bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, fl->bobspeed) * p->follower_timer)>>ANGLETOFINESHIFT) & FINEMASK));
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, color, GTC_MENUCACHE);
|
||||
}
|
||||
|
||||
V_DrawFixedPatch((x*FRACUNIT), ((y-12)*FRACUNIT) + sine, fl.scale, addflags, patch, colormap);
|
||||
V_DrawFixedPatch((x*FRACUNIT), ((y-12)*FRACUNIT) + sine, fl->scale, addflags, patch, colormap);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1587,12 +1587,24 @@ static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y, boolean charflip
|
|||
UINT8 *colormap;
|
||||
|
||||
if (p->skin < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->mdepth < CSSTEP_COLORS)
|
||||
{
|
||||
color = skins[p->skin].prefcolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = p->color;
|
||||
}
|
||||
|
||||
if (color == SKINCOLOR_NONE)
|
||||
{
|
||||
color = skins[p->skin].prefcolor;
|
||||
}
|
||||
|
||||
colormap = R_GetTranslationColormap(p->skin, color, GTC_MENUCACHE);
|
||||
|
||||
M_DrawCharacterSprite(x, y, p->skin, SPR2_STIN, (charflip ? 1 : 7), ((p->mdepth == CSSTEP_READY) ? setup_animcounter : 0), 0, colormap);
|
||||
|
|
@ -1639,9 +1651,9 @@ static void M_DrawCharSelectPreview(UINT8 num)
|
|||
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 ((setup_animcounter/10) & 1)
|
||||
{
|
||||
if (p->mdepth == CSSTEP_NONE && num == setup_numplayers)
|
||||
if (p->mdepth == CSSTEP_NONE && num == setup_numplayers && gamestate == GS_MENU)
|
||||
{
|
||||
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE));
|
||||
}
|
||||
|
|
@ -1872,6 +1884,7 @@ static void M_DrawCharSelectCursor(UINT8 num)
|
|||
|
||||
setup_player_t *p = &setup_player[num];
|
||||
char letter = 'A' + num;
|
||||
UINT16 color = SKINCOLOR_NONE;
|
||||
UINT8 *colormap;
|
||||
INT16 x, y;
|
||||
INT16 quadx, quady;
|
||||
|
|
@ -1889,7 +1902,20 @@ static void M_DrawCharSelectCursor(UINT8 num)
|
|||
if (optionsmenu.profile)
|
||||
x += 64;
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, (p->color != SKINCOLOR_NONE ? p->color : SKINCOLOR_GREY), GTC_MENUCACHE);
|
||||
color = p->color;
|
||||
if (color == SKINCOLOR_NONE)
|
||||
{
|
||||
if (p->skin >= 0)
|
||||
{
|
||||
color = skins[p->skin].prefcolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = SKINCOLOR_GREY;
|
||||
}
|
||||
}
|
||||
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, color, GTC_MENUCACHE);
|
||||
|
||||
if (p->mdepth >= CSSTEP_READY)
|
||||
{
|
||||
|
|
@ -1930,22 +1956,34 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
|
|||
|
||||
if (p != NULL && p->version)
|
||||
{
|
||||
truecol = PR_GetProfileColor(p);
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, truecol, GTC_CACHE);
|
||||
strcpy(pname, p->profilename);
|
||||
truecol = p->color;
|
||||
skinnum = R_SkinAvailable(p->skinname);
|
||||
strcpy(pname, p->profilename);
|
||||
}
|
||||
|
||||
// check setup_player for colormap for the card.
|
||||
// we'll need to check again for drawing afterwards unfortunately.
|
||||
if (sp->mdepth >= CSSTEP_CHARS)
|
||||
{
|
||||
truecol = PR_GetProfileColor(p);
|
||||
colormap = R_GetTranslationColormap(skinnum, sp->color, GTC_MENUCACHE);
|
||||
truecol = sp->color;
|
||||
skinnum = setup_chargrid[sp->gridx][sp->gridy].skinlist[sp->clonenum];
|
||||
}
|
||||
|
||||
if (truecol == SKINCOLOR_NONE)
|
||||
{
|
||||
if (skinnum >= 0)
|
||||
{
|
||||
truecol = skins[skinnum].prefcolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
truecol = SKINCOLOR_RED;
|
||||
}
|
||||
}
|
||||
|
||||
// Card
|
||||
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, greyedout ? V_TRANSLUCENT : 0, card, colormap);
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, truecol, GTC_CACHE);
|
||||
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, greyedout ? V_TRANSLUCENT : 0, card, colormap);
|
||||
}
|
||||
|
||||
if (greyedout)
|
||||
return; // only used for profiles we can't select.
|
||||
|
|
@ -1960,12 +1998,12 @@ 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, SPR2_STIN, 7, 0, 0, colormap))
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], colormap);
|
||||
UINT8 *ccolormap = R_GetTranslationColormap(skinnum, truecol, GTC_MENUCACHE);
|
||||
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, SPR2_STIN, 7, 0, 0, ccolormap))
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], ccolormap);
|
||||
}
|
||||
|
||||
M_DrawCharSelectCircle(sp, x-22, y+104);
|
||||
|
|
@ -1974,7 +2012,7 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
|
|||
{
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, 0, false, 0, 0, sp))
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, sp->color);;
|
||||
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, &followers[sp->followern], sp->color, &skins[sp->skin]);
|
||||
patch_t *ico = W_CachePatchName(followers[sp->followern].icon, PU_CACHE);
|
||||
UINT8 *fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
|
|
@ -1983,28 +2021,36 @@ static void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
|
|||
}
|
||||
else if (skinnum > -1) // otherwise, read from profile.
|
||||
{
|
||||
UINT8 *ccolormap, *fcolormap;
|
||||
UINT16 col = K_GetEffectiveFollowerColor(p->followercolor, p->color);
|
||||
UINT8 fln = K_FollowerAvailable(p->follower);
|
||||
UINT8 *ccolormap;
|
||||
INT32 fln = K_FollowerAvailable(p->follower);
|
||||
|
||||
if (R_SkinUsable(g_localplayers[0], skinnum, false))
|
||||
ccolormap = colormap;
|
||||
ccolormap = R_GetTranslationColormap(skinnum, truecol, GTC_MENUCACHE);
|
||||
else
|
||||
ccolormap = R_GetTranslationColormap(TC_BLINK, truecol, GTC_MENUCACHE);
|
||||
|
||||
fcolormap = R_GetTranslationColormap(
|
||||
(K_FollowerUsable(fln) ? TC_DEFAULT : TC_BLINK),
|
||||
col, GTC_MENUCACHE);
|
||||
|
||||
if (M_DrawCharacterSprite(x-22, y+119, skinnum, SPR2_STIN, 7, 0, 0, ccolormap))
|
||||
{
|
||||
V_DrawMappedPatch(x+14, y+66, 0, faceprefix[skinnum][FACE_RANK], ccolormap);
|
||||
}
|
||||
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, fln, false, 0, fcolormap, NULL))
|
||||
if (fln >= 0)
|
||||
{
|
||||
patch_t *ico = W_CachePatchName(followers[fln].icon, PU_CACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
UINT16 fcol = K_GetEffectiveFollowerColor(
|
||||
p->followercolor,
|
||||
&followers[fln],
|
||||
p->color,
|
||||
&skins[skinnum]
|
||||
);
|
||||
UINT8 *fcolormap = R_GetTranslationColormap(
|
||||
(K_FollowerUsable(fln) ? TC_DEFAULT : TC_BLINK),
|
||||
fcol, GTC_MENUCACHE);
|
||||
|
||||
if (M_DrawFollowerSprite(x-22 - 16, y+119, fln, false, 0, fcolormap, NULL))
|
||||
{
|
||||
patch_t *ico = W_CachePatchName(followers[fln].icon, PU_CACHE);
|
||||
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5021,12 +5067,15 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili
|
|||
case SECRET_FOLLOWER:
|
||||
categoryid = '2';
|
||||
break;
|
||||
/*case SECRET_COLOR:
|
||||
case SECRET_COLOR:
|
||||
categoryid = '3';
|
||||
break;*/
|
||||
break;
|
||||
case SECRET_CUP:
|
||||
categoryid = '4';
|
||||
break;
|
||||
case SECRET_MAP:
|
||||
categoryid = '8';
|
||||
break;
|
||||
case SECRET_HARDSPEED:
|
||||
case SECRET_MASTERMODE:
|
||||
case SECRET_ENCORE:
|
||||
|
|
@ -5035,8 +5084,9 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili
|
|||
case SECRET_ONLINE:
|
||||
case SECRET_ADDONS:
|
||||
case SECRET_EGGTV:
|
||||
case SECRET_ALTTITLE:
|
||||
case SECRET_SOUNDTEST:
|
||||
case SECRET_ALTTITLE:
|
||||
case SECRET_MEMETAUNTS:
|
||||
categoryid = '6';
|
||||
break;
|
||||
case SECRET_TIMEATTACK:
|
||||
|
|
@ -5086,12 +5136,27 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili
|
|||
INT32 skin = M_UnlockableFollowerNum(ref);
|
||||
if (skin != -1)
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, cv_playercolor[0].value);
|
||||
INT32 psk = R_SkinAvailable(cv_skin[0].string);
|
||||
UINT16 col = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, &followers[skin], cv_playercolor[0].value, (psk != -1) ? &skins[psk] : &skins[0]);
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
pat = W_CachePatchName(followers[skin].icon, PU_CACHE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SECRET_COLOR:
|
||||
{
|
||||
INT32 colorid = M_UnlockableColorNum(ref);
|
||||
if (colorid != SKINCOLOR_NONE)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, colorid, GTC_MENUCACHE);
|
||||
}
|
||||
iconid = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case SECRET_MAP:
|
||||
iconid = 14;
|
||||
break;
|
||||
|
||||
case SECRET_HARDSPEED:
|
||||
iconid = 3;
|
||||
|
|
@ -5112,11 +5177,14 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili
|
|||
case SECRET_EGGTV:
|
||||
iconid = 11;
|
||||
break;
|
||||
case SECRET_SOUNDTEST:
|
||||
iconid = 1;
|
||||
break;
|
||||
case SECRET_ALTTITLE:
|
||||
iconid = 6;
|
||||
break;
|
||||
case SECRET_SOUNDTEST:
|
||||
iconid = 1;
|
||||
case SECRET_MEMETAUNTS:
|
||||
iconid = 13;
|
||||
break;
|
||||
|
||||
case SECRET_TIMEATTACK:
|
||||
|
|
@ -5129,7 +5197,7 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, boolean hili
|
|||
iconid = 9;
|
||||
break;
|
||||
case SECRET_SPBATTACK:
|
||||
iconid = 0; // TEMPORARY
|
||||
iconid = 15;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -5324,7 +5392,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
|
|||
// Draw follower next to them
|
||||
if (fskin != -1)
|
||||
{
|
||||
UINT16 col = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, cv_playercolor[0].value);
|
||||
UINT16 col = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, &skins[skin]);
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
|
||||
M_DrawFollowerSprite(x - 16, y, fskin, false, 0, colormap, NULL);
|
||||
|
||||
|
|
@ -5338,6 +5406,20 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SECRET_COLOR:
|
||||
{
|
||||
INT32 colorid = M_UnlockableColorNum(ref);
|
||||
if (colorid == SKINCOLOR_NONE)
|
||||
break;
|
||||
INT32 skin = R_SkinAvailable(cv_skin[0].string);
|
||||
if (skin == -1)
|
||||
skin = 0;
|
||||
colormap = R_GetTranslationColormap(skin, colorid, GTC_MENUCACHE);
|
||||
|
||||
// Draw reference for character bathed in coloured slime
|
||||
M_DrawCharacterSprite(x, y, skin, SPR2_STIN, 7, 0, 0, colormap);
|
||||
break;
|
||||
}
|
||||
case SECRET_CUP:
|
||||
{
|
||||
levelsearch_t templevelsearch;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "r_skins.h"
|
||||
#include "monocypher/monocypher.h"
|
||||
#include "stun.h"
|
||||
#include "k_color.h"
|
||||
|
||||
// List of all the profiles.
|
||||
static profile_t *profilesList[MAXPROFILES+1]; // +1 because we're gonna add a default "GUEST' profile.
|
||||
|
|
@ -372,7 +373,7 @@ void PR_LoadProfiles(void)
|
|||
; // Valid, even outside the bounds
|
||||
}
|
||||
else if (profilesList[i]->color >= numskincolors
|
||||
|| skincolors[profilesList[i]->color].accessible == false)
|
||||
|| K_ColorUsable(profilesList[i]->color, false) == false)
|
||||
{
|
||||
profilesList[i]->color = PROFILEDEFAULTCOLOR;
|
||||
}
|
||||
|
|
@ -388,7 +389,7 @@ void PR_LoadProfiles(void)
|
|||
}
|
||||
else if (profilesList[i]->followercolor >= numskincolors
|
||||
|| profilesList[i]->followercolor == SKINCOLOR_NONE
|
||||
|| skincolors[profilesList[i]->followercolor].accessible == false)
|
||||
|| K_ColorUsable(profilesList[i]->followercolor, true) == false)
|
||||
{
|
||||
profilesList[i]->followercolor = PROFILEDEFAULTFOLLOWERCOLOR;
|
||||
}
|
||||
|
|
@ -443,29 +444,10 @@ void PR_LoadProfiles(void)
|
|||
profilesList[PROFILE_GUEST] = dprofile;
|
||||
}
|
||||
|
||||
skincolornum_t PR_GetProfileColor(profile_t *p)
|
||||
{
|
||||
if (p->color == SKINCOLOR_NONE)
|
||||
{
|
||||
// Get skin's prefcolor.
|
||||
INT32 foundskin = R_SkinAvailable(p->skinname);
|
||||
if (foundskin == -1)
|
||||
{
|
||||
// Return random default value
|
||||
return SKINCOLOR_RED;
|
||||
}
|
||||
|
||||
return skins[foundskin].prefcolor;
|
||||
}
|
||||
|
||||
// Get exact color.
|
||||
return p->color;
|
||||
}
|
||||
|
||||
static void PR_ApplyProfile_Appearance(profile_t *p, UINT8 playernum)
|
||||
{
|
||||
CV_StealthSet(&cv_skin[playernum], p->skinname);
|
||||
CV_StealthSetValue(&cv_playercolor[playernum], PR_GetProfileColor(p));
|
||||
CV_StealthSetValue(&cv_playercolor[playernum], p->color);
|
||||
CV_StealthSet(&cv_playername[playernum], p->playername);
|
||||
|
||||
// Followers
|
||||
|
|
|
|||
|
|
@ -131,10 +131,6 @@ void PR_SaveProfiles(void);
|
|||
// This also loads
|
||||
void PR_LoadProfiles(void);
|
||||
|
||||
// PR_GetProfileColor(profile_t *p)
|
||||
// Returns the profile's color, or the skin's prefcolor if set to none.
|
||||
skincolornum_t PR_GetProfileColor(profile_t *p);
|
||||
|
||||
// PR_ApplyProfile(UINT8 profilenum, UINT8 playernum)
|
||||
// Applies the given profile's settings to the given player.
|
||||
void PR_ApplyProfile(UINT8 profilenum, UINT8 playernum);
|
||||
|
|
|
|||
|
|
@ -338,49 +338,11 @@ static int lib_reserveLuabanks(lua_State *L)
|
|||
// M_MENU
|
||||
//////////////
|
||||
|
||||
static int lib_pMoveColorBefore(lua_State *L)
|
||||
{
|
||||
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||
UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
|
||||
|
||||
NOHUD
|
||||
M_MoveColorBefore(color, targ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pMoveColorAfter(lua_State *L)
|
||||
{
|
||||
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||
UINT16 targ = (UINT16)luaL_checkinteger(L, 2);
|
||||
|
||||
NOHUD
|
||||
M_MoveColorAfter(color, targ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pGetColorBefore(lua_State *L)
|
||||
{
|
||||
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||
UINT16 amount = (UINT16)luaL_checkinteger(L, 2);
|
||||
boolean follower = lua_optboolean(L, 3);
|
||||
lua_pushinteger(L, M_GetColorBefore(color, amount, follower));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pGetColorAfter(lua_State *L)
|
||||
{
|
||||
UINT16 color = (UINT16)luaL_checkinteger(L, 1);
|
||||
UINT16 amount = (UINT16)luaL_checkinteger(L, 2);
|
||||
boolean follower = lua_optboolean(L, 3);
|
||||
lua_pushinteger(L, M_GetColorAfter(color, amount, follower));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pGetEffectiveFollowerColor(lua_State *L)
|
||||
{
|
||||
UINT16 followercolor = (UINT16)luaL_checkinteger(L, 1);
|
||||
UINT16 playercolor = (UINT16)luaL_checkinteger(L, 2);
|
||||
lua_pushinteger(L, K_GetEffectiveFollowerColor(followercolor, playercolor));
|
||||
lua_pushinteger(L, K_GetEffectiveFollowerColor(followercolor, NULL, playercolor, NULL)); // FIXME: follower / skin
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -3976,12 +3938,6 @@ static luaL_Reg lib[] = {
|
|||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||
{"reserveLuabanks", lib_reserveLuabanks},
|
||||
|
||||
// m_menu
|
||||
{"M_MoveColorAfter",lib_pMoveColorAfter},
|
||||
{"M_MoveColorBefore",lib_pMoveColorBefore},
|
||||
{"M_GetColorAfter",lib_pGetColorAfter},
|
||||
{"M_GetColorBefore",lib_pGetColorBefore},
|
||||
|
||||
// m_random
|
||||
{"P_RandomFixed",lib_pRandomFixed},
|
||||
{"P_RandomByte",lib_pRandomByte},
|
||||
|
|
|
|||
36
src/m_cond.c
36
src/m_cond.c
|
|
@ -2219,6 +2219,42 @@ INT32 M_UnlockableFollowerNum(unlockable_t *unlock)
|
|||
return -1;
|
||||
}
|
||||
|
||||
INT32 M_UnlockableColorNum(unlockable_t *unlock)
|
||||
{
|
||||
if (unlock->type != SECRET_COLOR)
|
||||
{
|
||||
// This isn't a color unlockable...
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlock->stringVar && unlock->stringVar[0])
|
||||
{
|
||||
skincolornum_t colornum = SKINCOLOR_NONE;
|
||||
|
||||
if (unlock->stringVarCache != -1)
|
||||
{
|
||||
return unlock->stringVarCache;
|
||||
}
|
||||
|
||||
// Get the skin from the string.
|
||||
colornum = R_GetColorByName(unlock->stringVar);
|
||||
if (colornum != SKINCOLOR_NONE)
|
||||
{
|
||||
unlock->stringVarCache = colornum;
|
||||
return colornum;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlock->variable > SKINCOLOR_NONE && unlock->variable < numskincolors)
|
||||
{
|
||||
// Use the number directly.
|
||||
return unlock->variable;
|
||||
}
|
||||
|
||||
// Invalid color unlockable.
|
||||
return -1;
|
||||
}
|
||||
|
||||
cupheader_t *M_UnlockableCup(unlockable_t *unlock)
|
||||
{
|
||||
cupheader_t *cup = kartcupheaders;
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ typedef enum
|
|||
// Player restrictions
|
||||
SECRET_SKIN, // Permit this character
|
||||
SECRET_FOLLOWER, // Permit this follower
|
||||
SECRET_COLOR, // Permit this color
|
||||
|
||||
// Difficulty restrictions
|
||||
SECRET_HARDSPEED, // Permit Hard gamespeed
|
||||
|
|
@ -202,6 +203,7 @@ typedef enum
|
|||
SECRET_EGGTV, // Permit replay playback menu
|
||||
SECRET_SOUNDTEST, // Permit Sound Test
|
||||
SECRET_ALTTITLE, // Permit alternate titlescreen
|
||||
SECRET_MEMETAUNTS, // Permit "Meme" for kartvoices_cons_t
|
||||
|
||||
// Assist restrictions
|
||||
SECRET_ITEMFINDER, // Permit locating in-level secrets
|
||||
|
|
@ -375,6 +377,7 @@ boolean M_GotLowEnoughTime(INT32 tictime);
|
|||
|
||||
INT32 M_UnlockableSkinNum(unlockable_t *unlock);
|
||||
INT32 M_UnlockableFollowerNum(unlockable_t *unlock);
|
||||
INT32 M_UnlockableColorNum(unlockable_t *unlock);
|
||||
cupheader_t *M_UnlockableCup(unlockable_t *unlock);
|
||||
UINT16 M_UnlockableMapNum(unlockable_t *unlock);
|
||||
|
||||
|
|
|
|||
|
|
@ -531,10 +531,13 @@ void M_ChallengesTick(void)
|
|||
}
|
||||
case SECRET_FOLLOWER:
|
||||
{
|
||||
INT32 skin = M_UnlockableFollowerNum(ref);
|
||||
if (skin != -1)
|
||||
INT32 fskin = M_UnlockableFollowerNum(ref);
|
||||
if (fskin != -1)
|
||||
{
|
||||
bombcolor = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, cv_playercolor[0].value);
|
||||
INT32 psk = R_SkinAvailable(cv_skin[0].string);
|
||||
if (psk == -1)
|
||||
psk = 0;
|
||||
bombcolor = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, &skins[psk]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -545,6 +548,13 @@ void M_ChallengesTick(void)
|
|||
if (bombcolor == SKINCOLOR_NONE)
|
||||
{
|
||||
bombcolor = cv_playercolor[0].value;
|
||||
if (bombcolor == SKINCOLOR_NONE)
|
||||
{
|
||||
INT32 psk = R_SkinAvailable(cv_skin[0].string);
|
||||
if (psk == -1)
|
||||
psk = 0;
|
||||
bombcolor = skins[psk].prefcolor;
|
||||
}
|
||||
}
|
||||
|
||||
i = (ref->majorunlock && M_RandomChance(FRACUNIT/2)) ? 1 : 0;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
#include "../s_sound.h"
|
||||
#include "../k_grandprix.h" // K_CanChangeRules
|
||||
#include "../m_cond.h" // Condition Sets
|
||||
#include "../k_color.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
//#define CHARSELECT_DEVICEDEBUG
|
||||
|
||||
|
|
@ -38,8 +40,6 @@ static void Splitplayers_OnChange(void);
|
|||
CV_PossibleValue_t splitplayers_cons_t[] = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}};
|
||||
consvar_t cv_splitplayers = CVAR_INIT ("splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange);
|
||||
|
||||
UINT16 nummenucolors = 0;
|
||||
|
||||
// Character Select!
|
||||
// @TODO: Splitscreen handling when profiles are added into the game. ...I probably won't be the one to handle this however. -Lat'
|
||||
|
||||
|
|
@ -55,261 +55,116 @@ tic_t setup_animcounter = 0;
|
|||
UINT8 setup_page = 0;
|
||||
UINT8 setup_maxpage = 0; // For charsel page to identify alts easier...
|
||||
|
||||
void M_AddMenuColor(UINT16 color) {
|
||||
menucolor_t *c;
|
||||
|
||||
if (color >= numskincolors) {
|
||||
CONS_Printf("M_AddMenuColor: color %d does not exist.",color);
|
||||
return;
|
||||
}
|
||||
|
||||
// SRB2Kart: I do not understand vanilla doesn't need this but WE do???!?!??!
|
||||
if (!skincolors[color].accessible) {
|
||||
return;
|
||||
}
|
||||
|
||||
c = (menucolor_t *)malloc(sizeof(menucolor_t));
|
||||
c->color = color;
|
||||
if (menucolorhead == NULL) {
|
||||
c->next = c;
|
||||
c->prev = c;
|
||||
menucolorhead = c;
|
||||
menucolortail = c;
|
||||
} else {
|
||||
c->next = menucolorhead;
|
||||
c->prev = menucolortail;
|
||||
menucolortail->next = c;
|
||||
menucolorhead->prev = c;
|
||||
menucolortail = c;
|
||||
}
|
||||
|
||||
nummenucolors++;
|
||||
}
|
||||
|
||||
void M_MoveColorBefore(UINT16 color, UINT16 targ) {
|
||||
menucolor_t *look, *c = NULL, *t = NULL;
|
||||
|
||||
if (color == targ)
|
||||
return;
|
||||
if (color >= numskincolors) {
|
||||
CONS_Printf("M_MoveColorBefore: color %d does not exist.",color);
|
||||
return;
|
||||
}
|
||||
if (targ >= numskincolors) {
|
||||
CONS_Printf("M_MoveColorBefore: target color %d does not exist.",targ);
|
||||
return;
|
||||
}
|
||||
|
||||
for (look=menucolorhead;;look=look->next) {
|
||||
if (look->color == color)
|
||||
c = look;
|
||||
else if (look->color == targ)
|
||||
t = look;
|
||||
if (c != NULL && t != NULL)
|
||||
break;
|
||||
if (look==menucolortail)
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == t->prev)
|
||||
return;
|
||||
|
||||
if (t==menucolorhead)
|
||||
menucolorhead = c;
|
||||
if (c==menucolortail)
|
||||
menucolortail = c->prev;
|
||||
|
||||
c->prev->next = c->next;
|
||||
c->next->prev = c->prev;
|
||||
|
||||
c->prev = t->prev;
|
||||
c->next = t;
|
||||
t->prev->next = c;
|
||||
t->prev = c;
|
||||
}
|
||||
|
||||
void M_MoveColorAfter(UINT16 color, UINT16 targ) {
|
||||
menucolor_t *look, *c = NULL, *t = NULL;
|
||||
|
||||
if (color == targ)
|
||||
return;
|
||||
if (color >= numskincolors) {
|
||||
CONS_Printf("M_MoveColorAfter: color %d does not exist.\n",color);
|
||||
return;
|
||||
}
|
||||
if (targ >= numskincolors) {
|
||||
CONS_Printf("M_MoveColorAfter: target color %d does not exist.\n",targ);
|
||||
return;
|
||||
}
|
||||
|
||||
for (look=menucolorhead;;look=look->next) {
|
||||
if (look->color == color)
|
||||
c = look;
|
||||
else if (look->color == targ)
|
||||
t = look;
|
||||
if (c != NULL && t != NULL)
|
||||
break;
|
||||
if (look==menucolortail)
|
||||
return;
|
||||
}
|
||||
|
||||
if (t == c->prev)
|
||||
return;
|
||||
|
||||
if (t==menucolortail)
|
||||
menucolortail = c;
|
||||
else if (c==menucolortail)
|
||||
menucolortail = c->prev;
|
||||
|
||||
c->prev->next = c->next;
|
||||
c->next->prev = c->prev;
|
||||
|
||||
c->next = t->next;
|
||||
c->prev = t;
|
||||
t->next->prev = c;
|
||||
t->next = c;
|
||||
}
|
||||
|
||||
UINT16 M_GetColorBefore(UINT16 color, UINT16 amount, boolean follower)
|
||||
static void M_PushMenuColor(setup_player_colors_t *colors, UINT16 newColor)
|
||||
{
|
||||
menucolor_t *look = NULL;
|
||||
|
||||
for (; amount > 0; amount--)
|
||||
if (colors->listLen >= colors->listCap)
|
||||
{
|
||||
if (follower == true)
|
||||
if (colors->listCap == 0)
|
||||
{
|
||||
if (color == FOLLOWERCOLOR_OPPOSITE)
|
||||
{
|
||||
look = menucolortail;
|
||||
color = menucolortail->color;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (color == FOLLOWERCOLOR_MATCH)
|
||||
{
|
||||
look = NULL;
|
||||
color = FOLLOWERCOLOR_OPPOSITE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (color == menucolorhead->color)
|
||||
{
|
||||
look = NULL;
|
||||
color = FOLLOWERCOLOR_MATCH;
|
||||
continue;
|
||||
}
|
||||
colors->listCap = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors->listCap *= 2;
|
||||
}
|
||||
|
||||
if (color == 0 || color >= numskincolors)
|
||||
{
|
||||
CONS_Printf("M_GetColorBefore: color %d does not exist.\n",color);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (look == NULL)
|
||||
{
|
||||
for (look = menucolorhead;; look = look->next)
|
||||
{
|
||||
if (look->color == color)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (look == menucolortail)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
look = look->prev;
|
||||
color = look->color;
|
||||
colors->list = Z_ReallocAlign(
|
||||
colors->list,
|
||||
sizeof(UINT16) * colors->listCap,
|
||||
PU_STATIC,
|
||||
NULL,
|
||||
sizeof(UINT16) * 8
|
||||
);
|
||||
}
|
||||
return color;
|
||||
|
||||
colors->list[colors->listLen] = newColor;
|
||||
colors->listLen++;
|
||||
}
|
||||
|
||||
UINT16 M_GetColorAfter(UINT16 color, UINT16 amount, boolean follower)
|
||||
static void M_ClearMenuColors(setup_player_colors_t *colors)
|
||||
{
|
||||
menucolor_t *look = NULL;
|
||||
|
||||
for (; amount > 0; amount--)
|
||||
if (colors->list != NULL)
|
||||
{
|
||||
if (follower == true)
|
||||
{
|
||||
if (color == menucolortail->color)
|
||||
{
|
||||
look = NULL;
|
||||
color = FOLLOWERCOLOR_OPPOSITE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (color == FOLLOWERCOLOR_OPPOSITE)
|
||||
{
|
||||
look = NULL;
|
||||
color = FOLLOWERCOLOR_MATCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (color == FOLLOWERCOLOR_MATCH)
|
||||
{
|
||||
look = menucolorhead;
|
||||
color = menucolorhead->color;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (color == 0 || color >= numskincolors)
|
||||
{
|
||||
CONS_Printf("M_GetColorAfter: color %d does not exist.\n",color);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (look == NULL)
|
||||
{
|
||||
for (look = menucolorhead;; look = look->next)
|
||||
{
|
||||
if (look->color == color)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (look == menucolortail)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
look = look->next;
|
||||
color = look->color;
|
||||
Z_Free(colors->list);
|
||||
colors->list = NULL;
|
||||
}
|
||||
return color;
|
||||
|
||||
colors->listLen = colors->listCap = 0;
|
||||
}
|
||||
|
||||
void M_InitPlayerSetupColors(void) {
|
||||
UINT8 i;
|
||||
numskincolors = SKINCOLOR_FIRSTFREESLOT;
|
||||
menucolorhead = menucolortail = NULL;
|
||||
for (i=0; i<numskincolors; i++)
|
||||
M_AddMenuColor(i);
|
||||
}
|
||||
UINT16 M_GetColorAfter(setup_player_colors_t *colors, UINT16 value, INT32 amount)
|
||||
{
|
||||
const INT32 sign = (amount < 0) ? -1 : 1;
|
||||
INT32 index = -1;
|
||||
size_t i = SIZE_MAX;
|
||||
|
||||
void M_FreePlayerSetupColors(void) {
|
||||
menucolor_t *look = menucolorhead, *tmp;
|
||||
if (amount == 0 || colors->listLen == 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (menucolorhead==NULL)
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
if (look != menucolortail) {
|
||||
tmp = look;
|
||||
look = look->next;
|
||||
free(tmp);
|
||||
} else {
|
||||
free(look);
|
||||
return;
|
||||
for (i = 0; i < colors->listLen; i++)
|
||||
{
|
||||
if (colors->list[i] == value)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
menucolorhead = menucolortail = NULL;
|
||||
if (index == -1)
|
||||
{
|
||||
// Not in list, so no real correct behavior here.
|
||||
// Just try to get back to the list.
|
||||
return colors->list[0];
|
||||
}
|
||||
|
||||
amount = abs(amount);
|
||||
|
||||
while (amount > 0)
|
||||
{
|
||||
index += sign;
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
index = colors->listLen - 1;
|
||||
}
|
||||
else if (index >= (INT32)colors->listLen)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
amount--;
|
||||
}
|
||||
|
||||
return colors->list[index];
|
||||
}
|
||||
|
||||
static void M_NewPlayerColors(setup_player_t *p)
|
||||
{
|
||||
const boolean follower = (p->mdepth >= CSSTEP_FOLLOWER);
|
||||
INT32 i = INT32_MAX;
|
||||
|
||||
M_ClearMenuColors(&p->colors);
|
||||
|
||||
// Add all unlocked colors
|
||||
for (i = SKINCOLOR_NONE+1; i < numskincolors; i++)
|
||||
{
|
||||
if (K_ColorUsable(i, follower) == true)
|
||||
{
|
||||
M_PushMenuColor(&p->colors, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Add special colors
|
||||
M_PushMenuColor(&p->colors, SKINCOLOR_NONE);
|
||||
|
||||
if (follower == true)
|
||||
{
|
||||
// Add special follower colors
|
||||
M_PushMenuColor(&p->colors, FOLLOWERCOLOR_MATCH);
|
||||
M_PushMenuColor(&p->colors, FOLLOWERCOLOR_OPPOSITE);
|
||||
}
|
||||
}
|
||||
|
||||
// sets up the grid pos for the skin used by the profile.
|
||||
|
|
@ -346,7 +201,7 @@ static void M_SetupProfileGridPos(setup_player_t *p)
|
|||
alt++;
|
||||
|
||||
p->clonenum = alt;
|
||||
p->color = PR_GetProfileColor(pr);
|
||||
p->color = pr->color;
|
||||
}
|
||||
|
||||
static void M_SetupMidGameGridPos(setup_player_t *p, UINT8 num)
|
||||
|
|
@ -403,7 +258,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;
|
||||
setup_player[i].followercolor = SKINCOLOR_NONE;
|
||||
|
||||
// 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.
|
||||
|
|
@ -876,6 +731,7 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
|
|||
else
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
M_NewPlayerColors(p);
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
}
|
||||
|
|
@ -889,9 +745,14 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
|
|||
else
|
||||
{
|
||||
if (setup_page+1 == setup_chargrid[p->gridx][p->gridy].numskins)
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS; // Skip clones menu if there are none on this page.
|
||||
M_NewPlayerColors(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->mdepth = CSSTEP_ALTS;
|
||||
}
|
||||
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
|
|
@ -964,8 +825,30 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
|
|||
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
M_NewPlayerColors(p);
|
||||
if (p->colors.listLen == 1)
|
||||
{
|
||||
p->color = p->colors.list[0];
|
||||
if (setup_numfollowercategories == 0)
|
||||
{
|
||||
p->followern = -1;
|
||||
p->mdepth = CSSTEP_READY;
|
||||
p->delay = TICRATE;
|
||||
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
|
||||
S_StartSound(NULL, sfx_s3k4e);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
|
|
@ -992,14 +875,14 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
|
||||
if (menucmd[num].dpad_lr > 0)
|
||||
{
|
||||
p->color = M_GetColorAfter(p->color, 1, false);
|
||||
p->color = M_GetColorAfter(&p->colors, p->color, 1);
|
||||
p->rotate = CSROTATETICS;
|
||||
M_SetMenuDelay(num); //CSROTATETICS
|
||||
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
|
||||
}
|
||||
else if (menucmd[num].dpad_lr < 0)
|
||||
{
|
||||
p->color = M_GetColorBefore(p->color, 1, false);
|
||||
p->color = M_GetColorBefore(&p->colors, p->color, 1);
|
||||
p->rotate = -CSROTATETICS;
|
||||
M_SetMenuDelay(num); //CSROTATETICS
|
||||
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
|
||||
|
|
@ -1007,9 +890,20 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
|
||||
if (M_MenuConfirmPressed(num) /*|| M_MenuButtonPressed(num, MBT_START)*/)
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
if (setup_numfollowercategories == 0)
|
||||
{
|
||||
p->followern = -1;
|
||||
p->mdepth = CSSTEP_READY;
|
||||
p->delay = TICRATE;
|
||||
M_SetupReadyExplosions(true, p->gridx, p->gridy, p->color);
|
||||
S_StartSound(NULL, sfx_s3k4e);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWERCATEGORY;
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
}
|
||||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
|
|
@ -1029,7 +923,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
|
|||
{
|
||||
if (p->skin >= 0)
|
||||
{
|
||||
p->color = skins[p->skin].prefcolor;
|
||||
p->color = SKINCOLOR_NONE;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
|
|
@ -1131,6 +1025,7 @@ static void M_HandleFollowerCategoryRotate(setup_player_t *p, UINT8 num)
|
|||
else if (M_MenuBackPressed(num))
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
M_NewPlayerColors(p);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(num);
|
||||
}
|
||||
|
|
@ -1196,6 +1091,7 @@ static void M_HandleFollowerRotate(setup_player_t *p, UINT8 num)
|
|||
if (p->followern > -1)
|
||||
{
|
||||
p->mdepth = CSSTEP_FOLLOWERCOLORS;
|
||||
M_NewPlayerColors(p);
|
||||
S_StartSound(NULL, sfx_s3k63);
|
||||
}
|
||||
else
|
||||
|
|
@ -1234,14 +1130,14 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
|||
|
||||
if (menucmd[num].dpad_lr > 0)
|
||||
{
|
||||
p->followercolor = M_GetColorAfter(p->followercolor, 1, true);
|
||||
p->followercolor = M_GetColorAfter(&p->colors, p->followercolor, 1);
|
||||
p->rotate = CSROTATETICS;
|
||||
M_SetMenuDelay(num); //CSROTATETICS
|
||||
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
|
||||
}
|
||||
else if (menucmd[num].dpad_lr < 0)
|
||||
{
|
||||
p->followercolor = M_GetColorBefore(p->followercolor, 1, true);
|
||||
p->followercolor = M_GetColorBefore(&p->colors, p->followercolor, 1);
|
||||
p->rotate = -CSROTATETICS;
|
||||
M_SetMenuDelay(num); //CSROTATETICS
|
||||
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
|
||||
|
|
@ -1266,10 +1162,10 @@ static void M_HandleFollowerColorRotate(setup_player_t *p, UINT8 num)
|
|||
{
|
||||
if (p->followercolor == FOLLOWERCOLOR_MATCH)
|
||||
p->followercolor = FOLLOWERCOLOR_OPPOSITE;
|
||||
else if (p->followercolor == followers[p->followern].defaultcolor)
|
||||
else if (p->followercolor == SKINCOLOR_NONE)
|
||||
p->followercolor = FOLLOWERCOLOR_MATCH;
|
||||
else
|
||||
p->followercolor = followers[p->followern].defaultcolor;
|
||||
p->followercolor = SKINCOLOR_NONE;
|
||||
p->rotate = CSROTATETICS;
|
||||
p->hitlag = true;
|
||||
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kc3s
|
||||
|
|
@ -1343,6 +1239,7 @@ boolean M_CharacterSelectHandler(INT32 choice)
|
|||
if (M_MenuBackPressed(i))
|
||||
{
|
||||
p->mdepth = CSSTEP_COLORS;
|
||||
M_NewPlayerColors(p);
|
||||
S_StartSound(NULL, sfx_s3k5b);
|
||||
M_SetMenuDelay(i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2466,6 +2466,31 @@ static UINT32 SaveSlope(const pslope_t *slope)
|
|||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static boolean TypeIsNetSynced(mobjtype_t type)
|
||||
{
|
||||
// Ignore stationary hoops - these will be respawned from mapthings.
|
||||
if (type == MT_HOOP)
|
||||
return false;
|
||||
|
||||
// These are NEVER saved.
|
||||
if (type == MT_HOOPCOLLIDE)
|
||||
return false;
|
||||
|
||||
// This hoop has already been collected.
|
||||
if (type == MT_HOOPCENTER)// && mobj->threshold == 4242)
|
||||
return false;
|
||||
|
||||
// MT_SPARK: used for debug stuff
|
||||
if (type == MT_SPARK)
|
||||
return false;
|
||||
|
||||
// MT_HORNCODE: So it turns out hornmod is fundamentally incompatible with netsync
|
||||
if (type == MT_HORNCODE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type)
|
||||
{
|
||||
const mobj_t *mobj = (const mobj_t *)th;
|
||||
|
|
@ -2473,20 +2498,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
|
|||
UINT32 diff2;
|
||||
size_t j;
|
||||
|
||||
// Ignore stationary hoops - these will be respawned from mapthings.
|
||||
if (mobj->type == MT_HOOP)
|
||||
return;
|
||||
|
||||
// These are NEVER saved.
|
||||
if (mobj->type == MT_HOOPCOLLIDE)
|
||||
return;
|
||||
|
||||
// This hoop has already been collected.
|
||||
if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
|
||||
return;
|
||||
|
||||
// MT_SPARK: used for debug stuff
|
||||
if (mobj->type == MT_SPARK)
|
||||
if (TypeIsNetSynced(mobj->type) == false)
|
||||
return;
|
||||
|
||||
diff2 = 0;
|
||||
|
|
@ -5117,9 +5129,7 @@ static void P_RelinkPointers(void)
|
|||
|
||||
mobj = (mobj_t *)currentthinker;
|
||||
|
||||
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER
|
||||
// MT_SPARK: used for debug stuff
|
||||
|| mobj->type == MT_SPARK)
|
||||
if (TypeIsNetSynced(mobj->type) == false)
|
||||
continue;
|
||||
|
||||
if (mobj->tracer)
|
||||
|
|
@ -6042,9 +6052,7 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending)
|
|||
continue;
|
||||
|
||||
mobj = (mobj_t *)th;
|
||||
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER
|
||||
// MT_SPARK: used for debug stuff
|
||||
|| mobj->type == MT_SPARK)
|
||||
if (TypeIsNetSynced(mobj->type) == false)
|
||||
continue;
|
||||
mobj->mobjnum = i++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1675,7 +1675,6 @@ void I_Quit(void)
|
|||
|
||||
D_QuitNetGame();
|
||||
CL_AbortDownloadResume();
|
||||
M_FreePlayerSetupColors();
|
||||
I_ShutdownMusic();
|
||||
I_ShutdownSound();
|
||||
// use this for 1.28 19990220 by Kin
|
||||
|
|
@ -1801,7 +1800,6 @@ void I_Error(const char *error, ...)
|
|||
|
||||
D_QuitNetGame();
|
||||
CL_AbortDownloadResume();
|
||||
M_FreePlayerSetupColors();
|
||||
|
||||
I_ShutdownMusic();
|
||||
I_ShutdownGraphics();
|
||||
|
|
|
|||
|
|
@ -1183,8 +1183,9 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"clawk1", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND
|
||||
{"clawk2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND
|
||||
|
||||
{"monch", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"etexpl", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Game crash"},
|
||||
{"horn00", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "/"}, // HORNCODE
|
||||
{"monch", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"etexpl", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Game crash"},
|
||||
|
||||
{"iwhp", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Instawhip attack
|
||||
{"gbrk", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Guard break!
|
||||
|
|
|
|||
|
|
@ -1252,6 +1252,7 @@ typedef enum
|
|||
sfx_clawk1,
|
||||
sfx_clawk2,
|
||||
|
||||
sfx_horn00,
|
||||
sfx_monch,
|
||||
sfx_etexpl,
|
||||
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ TYPEDEF (menucolor_t);
|
|||
TYPEDEF (menuitem_t);
|
||||
TYPEDEF (menu_t);
|
||||
TYPEDEF (menucmd_t);
|
||||
TYPEDEF (setup_player_colors_t);
|
||||
TYPEDEF (setup_player_t);
|
||||
TYPEDEF (modedesc_t);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue