Queued skin/color changes

Instead of janky spectate on skin change, let the player finish their current round as their current skin.
This commit is contained in:
Sally Coolatta 2024-09-07 10:54:36 -04:00
parent e5f740f4a3
commit 0d3cc16403
10 changed files with 148 additions and 121 deletions

View file

@ -996,11 +996,6 @@ static void SendNameAndColor(const 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)
@ -1015,11 +1010,11 @@ static void SendNameAndColor(const UINT8 n)
// 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)
&& sendColor == player->prefcolor
&& !stricmp(cv_skin[n].string, skins[player->prefskin].name)
&& !stricmp(cv_follower[n].string,
(player->followerskin < 0 ? "None" : followers[player->followerskin].name))
&& sendFollowerColor == player->followercolor)
(player->preffollower < 0 ? "None" : followers[player->preffollower].name))
&& sendFollowerColor == player->preffollowercolor)
{
return;
}
@ -1123,7 +1118,6 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum)
UINT16 color, followercolor;
UINT8 skin;
INT16 follower;
SINT8 localplayer = -1;
UINT8 i;
#ifdef PARANOIA
@ -1145,8 +1139,6 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum)
I_Error("snacpending[%d] negative!", i);
}
#endif
localplayer = i;
break;
}
}
@ -1164,95 +1156,22 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum)
SetPlayerName(playernum, name);
}
// set color
p->skincolor = color % numskincolors;
if (p->mo)
p->mo->color = (UINT16)p->skincolor;
demo_extradata[playernum] |= DXD_COLOR;
// normal player colors
if (server && !P_IsMachineLocalPlayer(p))
// queue the rest for next round
p->prefcolor = color % numskincolors;
if (K_ColorUsable(p->prefcolor, false, false) == false)
{
boolean kick = false;
// don't allow inaccessible colors
if (K_ColorUsable(p->skincolor, false, false) == false)
{
kick = true;
}
if (kick)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s, color: %d)\n"), player_names[playernum], p->skincolor);
SendKick(playernum, KICK_MSG_CON_FAIL);
return;
}
p->prefcolor = SKINCOLOR_NONE;
}
// set skin
if (cv_forceskin.value >= 0 && K_CanChangeRules(true)) // Server wants everyone to use the same player
p->prefskin = skin;
p->preffollowercolor = followercolor;
p->preffollower = follower;
if (p->jointime < 1)
{
const INT32 forcedskin = cv_forceskin.value;
SetPlayerSkinByNum(playernum, forcedskin);
if (localplayer != -1)
CV_StealthSet(&cv_skin[localplayer], skins[forcedskin].name);
// Just entered, update preferences immediately
G_UpdatePlayerPreferences(p);
}
else
{
UINT8 oldskin = players[playernum].skin;
SetPlayerSkinByNum(playernum, skin);
// The following is a miniature subset of Got_Teamchange.
if ((gamestate == GS_LEVEL) // In a level?
&& (players[playernum].jointime > 1) // permit on join
&& (leveltime > introtime) // permit during intro turnaround
&& (players[playernum].skin != oldskin)) // a skin change actually happened?
{
players[playernum].roundconditions.switched_skin = true;
if (
cv_restrictskinchange.value // Skin changes are restricted?
&& G_GametypeHasSpectators() // not a spectator...
&& players[playernum].spectator == false // ...but could be?
)
{
for (i = 0; i < MAXPLAYERS; ++i)
{
if (i == playernum)
continue;
if (!playeringame[i])
continue;
if (players[i].spectator)
continue;
break;
}
if (i != MAXPLAYERS // Someone on your server who isn't you?
&& LUA_HookTeamSwitch(&players[playernum], 0, false, false, false)) // fiiiine, lua can except it
{
P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_SPECTATOR);
if (players[i].spectator)
{
HU_AddChatText(va("\x82*%s became a spectator.", player_names[playernum]), false);
FinalisePlaystateChange(playernum);
}
}
}
}
}
// set follower colour:
// Don't bother doing garbage and kicking if we receive None,
// this is both silly and a waste of time,
// this will be handled properly in K_HandleFollower.
p->followercolor = followercolor;
// set follower
K_SetFollowerByNum(playernum, follower);
}
enum {

View file

@ -671,6 +671,11 @@ struct player_t
UINT8 carry;
UINT16 dye;
INT32 prefskin; // Queued skin change
UINT16 prefcolor; // Queued color change
INT32 preffollower; // Queued follower change
UINT16 preffollowercolor; // Queued follower color change
// SRB2kart stuff
INT32 karthud[NUMKARTHUD];

View file

@ -1778,6 +1778,65 @@ void G_FixCamera(UINT8 view)
R_ResetViewInterpolation(view);
}
void G_UpdatePlayerPreferences(player_t *const player)
{
// set skin
INT32 new_skin = player->prefskin;
if (K_CanChangeRules(true) == true && cv_forceskin.value >= 0)
{
// Server wants everyone to use the same player
new_skin = cv_forceskin.value;
}
if (player->skin != new_skin)
{
SetPlayerSkinByNum(player - players, new_skin);
}
// set color
UINT16 new_color = player->prefcolor;
if (new_color == SKINCOLOR_NONE)
{
new_color = skins[player->skin].prefcolor;
}
if (player->skincolor != new_color)
{
player->skincolor = new_color;
K_KartResetPlayerColor(player);
}
// set follower
if (player->followerskin != player->preffollower)
{
K_SetFollowerByNum(player - players, player->preffollower);
}
// set follower color
if (player->followercolor != player->preffollowercolor)
{
// Don't bother doing garbage and kicking if we receive None,
// this is both silly and a waste of time,
// this will be handled properly in K_HandleFollower.
player->followercolor = player->preffollowercolor;
}
}
void G_UpdateAllPlayerPreferences(void)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] == false)
{
continue;
}
G_UpdatePlayerPreferences(&players[i]);
}
}
//
// G_Ticker
// Make ticcmd_ts for the players.
@ -1871,6 +1930,13 @@ void G_Ticker(boolean run)
K_UpdateAllPlayerPositions();
}
}
else
{
if (run)
{
G_UpdateAllPlayerPreferences();
}
}
P_MapEnd();
@ -2186,6 +2252,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
tic_t laptime[LAP__MAX];
UINT16 prefcolor;
INT32 prefskin;
UINT16 preffollowercolor;
INT32 preffollower;
INT32 i;
// This needs to be first, to permit it to wipe extra information
@ -2209,6 +2280,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
skincolor = players[player].skincolor;
skin = players[player].skin;
prefcolor = players[player].prefcolor;
prefskin = players[player].prefskin;
preffollower = players[player].preffollower;
preffollowercolor = players[player].preffollowercolor;
if (betweenmaps)
{
fakeskin = MAXSKINS;
@ -2463,6 +2539,11 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->skincolor = skincolor;
p->skin = skin;
p->prefcolor = prefcolor;
p->prefskin = prefskin;
p->preffollower = preffollower;
p->preffollowercolor = preffollowercolor;
p->fakeskin = fakeskin;
p->kartspeed = kartspeed;
p->kartweight = kartweight;

View file

@ -232,6 +232,9 @@ void G_UpdateTimeStickerMedals(UINT16 map, boolean showownrecord);
void G_TickTimeStickerMedals(void);
void G_UpdateRecords(void);
void G_UpdatePlayerPreferences(player_t *const player);
void G_UpdateAllPlayerPreferences(void);
void G_Ticker(boolean run);
boolean G_Responder(event_t *ev);

View file

@ -174,16 +174,18 @@ void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e st
break;
}
}
players[newplayernum].skincolor = color;
K_SetNameForBot(newplayernum, realname);
SetPlayerSkinByNum(newplayernum, skinnum);
K_SetNameForBot(newplayernum, realname);
for (UINT8 i = 0; i < PWRLV_NUMTYPES; i++)
{
clientpowerlevels[newplayernum][i] = 0;
}
players[newplayernum].prefcolor = color;
players[newplayernum].prefskin = skinnum;
G_UpdatePlayerPreferences(&players[newplayernum]);
if (netgame)
{
HU_AddChatText(va("\x82*Bot %d has been added to the game", newplayernum+1), false);

View file

@ -791,10 +791,12 @@ void K_RetireBots(void)
bot->botvars.difficulty = newDifficulty;
bot->botvars.diffincrease = 0;
SetPlayerSkinByNum(i, skinnum);
bot->skincolor = skins[skinnum].prefcolor;
K_SetNameForBot(i, skins[skinnum].realname);
bot->prefskin = skinnum;
bot->prefcolor = skins[skinnum].prefcolor;
G_UpdatePlayerPreferences(bot);
bot->score = 0;
bot->pflags &= ~PF_NOCONTEST;
}

View file

@ -557,6 +557,14 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->followercolor);
else if (fastcmp(field,"follower"))
LUA_PushUserdata(L, plr->follower, META_MOBJ);
else if (fastcmp(field,"prefskin"))
lua_pushinteger(L, plr->prefskin);
else if (fastcmp(field,"prefcolor"))
lua_pushinteger(L, plr->prefcolor);
else if (fastcmp(field,"preffollower"))
lua_pushinteger(L, plr->preffollower);
else if (fastcmp(field,"preffollowercolor"))
lua_pushinteger(L, plr->preffollowercolor);
//
// rideroids
@ -1122,8 +1130,16 @@ static int player_set(lua_State *L)
plr->followercolor = luaL_checkinteger(L, 3);
else if (fastcmp(field,"followerready"))
plr->followerready = luaL_checkboolean(L, 3);
else if (fastcmp(field,"follower")) // it's probably best we don't allow the follower mobj to change.
return NOSET;
else if (fastcmp(field,"follower"))
return NOSET; // it's probably best we don't allow the follower mobj to change.
else if (fastcmp(field,"prefskin"))
return NOSET; // don't allow changing user preferences
else if (fastcmp(field,"prefcolor"))
return NOSET; // don't allow changing user preferences
else if (fastcmp(field,"preffollower"))
return NOSET; // don't allow changing user preferences
else if (fastcmp(field,"preffollowercolor"))
return NOSET; // don't allow changing user preferences
// time to add to the endless elseif list!!!!
// rideroids

View file

@ -247,7 +247,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT16(save->p, players[i].flashpal);
WRITEUINT16(save->p, players[i].flashcount);
WRITEUINT8(save->p, players[i].skincolor);
WRITEUINT16(save->p, players[i].skincolor);
WRITEINT32(save->p, players[i].skin);
for (j = 0; j < MAXAVAILABILITY; j++)
@ -257,6 +257,12 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT8(save->p, players[i].fakeskin);
WRITEUINT8(save->p, players[i].lastfakeskin);
WRITEUINT16(save->p, players[i].prefcolor);
WRITEINT32(save->p, players[i].prefskin);
WRITEUINT16(save->p, players[i].preffollowercolor);
WRITEINT32(save->p, players[i].preffollower);
WRITEUINT32(save->p, players[i].score);
WRITESINT8(save->p, players[i].lives);
WRITESINT8(save->p, players[i].xtralife);
@ -919,7 +925,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].flashpal = READUINT16(save->p);
players[i].flashcount = READUINT16(save->p);
players[i].skincolor = READUINT8(save->p);
players[i].skincolor = READUINT16(save->p);
players[i].skin = READINT32(save->p);
for (j = 0; j < MAXAVAILABILITY; j++)
@ -929,6 +935,12 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].fakeskin = READUINT8(save->p);
players[i].lastfakeskin = READUINT8(save->p);
players[i].prefcolor = READUINT16(save->p);
players[i].prefskin = READINT32(save->p);
players[i].preffollowercolor = READUINT16(save->p);
players[i].preffollower = READINT32(save->p);
players[i].score = READUINT32(save->p);
players[i].lives = READSINT8(save->p);
players[i].xtralife = READSINT8(save->p); // Ring Extra Life counter

View file

@ -7978,6 +7978,9 @@ static void P_InitPlayers(void)
// Make sure objectplace is OFF when you first start the level!
OP_ResetObjectplace();
// Update skins / colors between levels.
G_UpdateAllPlayerPreferences();
// Are we forcing a character?
if (gametype == GT_TUTORIAL)
{

View file

@ -408,22 +408,6 @@ static void SetSkin(player_t *player, INT32 skinnum)
player->kartweight = skin->kartweight;
player->charflags = skin->flags;
#if 0
if (!CV_CheatsEnabled() && !(netgame || multiplayer || demo.playback))
{
for (i = 0; i <= r_splitscreen; i++)
{
if (playernum == g_localplayers[i])
{
CV_StealthSetValue(&cv_playercolor[i], skin->prefcolor);
}
}
player->skincolor = skin->prefcolor;
K_KartResetPlayerColor(player);
}
#endif
if (player->followmobj)
{
P_RemoveMobj(player->followmobj);