Port most of SECRET_SKIN and player->availabilities changes from RR
based on 6d0637d39d
This commit is contained in:
parent
9eebf2ae67
commit
3028839f2f
18 changed files with 269 additions and 124 deletions
|
|
@ -894,6 +894,9 @@ static boolean CL_SendJoin(void)
|
|||
for (; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
strncpy(netbuffer->u.clientcfg.names[i], va("Player %c", 'A' + i), MAXPLAYERNAME);
|
||||
|
||||
memcpy(&netbuffer->u.clientcfg.availabilities, R_GetSkinAvailabilities(), MAXAVAILABILITY*sizeof(UINT8));
|
||||
|
||||
|
||||
return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak));
|
||||
}
|
||||
|
||||
|
|
@ -3759,8 +3762,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
node = (UINT8)READUINT8(*p);
|
||||
newplayernum = (UINT8)READUINT8(*p);
|
||||
node = READUINT8(*p);
|
||||
newplayernum = READUINT8(*p);
|
||||
|
||||
if (newplayernum+1 > doomcom->numslots)
|
||||
doomcom->numslots = (INT16)(newplayernum+1);
|
||||
|
|
@ -3771,8 +3774,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
|
|||
|
||||
READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME);
|
||||
|
||||
console = (UINT8)READUINT8(*p);
|
||||
splitscreenplayer = (UINT8)READUINT8(*p);
|
||||
console = READUINT8(*p);
|
||||
splitscreenplayer = READUINT8(*p);
|
||||
|
||||
for (i = 0; i < MAXAVAILABILITY; i++)
|
||||
{
|
||||
newplayer->availabilities[i] = READUINT8(*p);
|
||||
}
|
||||
|
||||
G_AddPlayer(newplayernum, console);
|
||||
|
||||
|
|
@ -3892,10 +3900,10 @@ static void Got_AddBot(UINT8 **p, INT32 playernum)
|
|||
K_SetBot(newplayernum, skinnum, difficulty, style);
|
||||
}
|
||||
|
||||
static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *name2, const char *name3, const char *name4)
|
||||
static boolean SV_AddWaitingPlayers(SINT8 node, UINT8 *availabilities, const char *name, const char *name2, const char *name3, const char *name4)
|
||||
{
|
||||
INT32 n, newplayernum;
|
||||
UINT8 buf[4 + MAXPLAYERNAME];
|
||||
INT32 n, newplayernum, i;
|
||||
UINT8 buf[4 + MAXPLAYERNAME + MAXAVAILABILITY];
|
||||
UINT8 *buf_p = buf;
|
||||
boolean newplayer = false;
|
||||
|
||||
|
|
@ -3978,6 +3986,11 @@ static boolean SV_AddWaitingPlayers(SINT8 node, const char *name, const char *na
|
|||
WRITEUINT8(buf_p, nodetoplayer[node]); // consoleplayer
|
||||
WRITEUINT8(buf_p, playerpernode[node]); // splitscreen num
|
||||
|
||||
for (i = 0; i < MAXAVAILABILITY; i++)
|
||||
{
|
||||
WRITEUINT8(buf_p, availabilities[i]);
|
||||
}
|
||||
|
||||
playerpernode[node]++;
|
||||
|
||||
SendNetXCmd(XD_ADDPLAYER, buf, buf_p - buf);
|
||||
|
|
@ -4121,9 +4134,11 @@ boolean SV_SpawnServer(void)
|
|||
// strictly speaking, i'm not convinced the following is necessary
|
||||
// but I'm not confident enough to remove it entirely in case it breaks something
|
||||
{
|
||||
UINT8 *availabilitiesbuffer = R_GetSkinAvailabilities();
|
||||
|
||||
SINT8 node = 0;
|
||||
for (; node < MAXNETNODES; node++)
|
||||
result |= SV_AddWaitingPlayers(node, cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring);
|
||||
result |= SV_AddWaitingPlayers(node, availabilitiesbuffer, cv_playername[0].zstring, cv_playername[1].zstring, cv_playername[2].zstring, cv_playername[3].zstring);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -4217,6 +4232,7 @@ static void HandleConnect(SINT8 node)
|
|||
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
|
||||
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
|
||||
INT32 i;
|
||||
UINT8 availabilitiesbuffer[MAXAVAILABILITY];
|
||||
|
||||
// Sal: Dedicated mode is INCREDIBLY hacked together.
|
||||
// If a server filled out, then it'd overwrite the host and turn everyone into weird husks.....
|
||||
|
|
@ -4341,6 +4357,8 @@ static void HandleConnect(SINT8 node)
|
|||
}
|
||||
}
|
||||
|
||||
memcpy(availabilitiesbuffer, netbuffer->u.clientcfg.availabilities, sizeof(availabilitiesbuffer));
|
||||
|
||||
// client authorised to join
|
||||
nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]);
|
||||
if (!nodeingame[node])
|
||||
|
|
@ -4375,7 +4393,7 @@ static void HandleConnect(SINT8 node)
|
|||
SV_SendSaveGame(node, false); // send a complete game state
|
||||
DEBFILE("send savegame\n");
|
||||
}
|
||||
SV_AddWaitingPlayers(node, names[0], names[1], names[2], names[3]);
|
||||
SV_AddWaitingPlayers(node, availabilitiesbuffer, names[0], names[1], names[2], names[3]);
|
||||
joindelay += cv_joindelay.value * TICRATE;
|
||||
player_joining = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ struct clientconfig_pak
|
|||
UINT8 localplayers; // number of splitscreen players
|
||||
UINT8 mode;
|
||||
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
|
||||
UINT8 availabilities[MAXAVAILABILITY];
|
||||
} ATTRPACK;
|
||||
|
||||
#define SV_SPEEDMASK 0x03 // used to send kartspeed
|
||||
|
|
|
|||
|
|
@ -1174,11 +1174,6 @@ void D_StartTitle(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
CL_ClearPlayer(i);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
players[g_localplayers[i]].availabilities = R_GetSkinAvailabilities();
|
||||
}
|
||||
|
||||
splitscreen = 0;
|
||||
SplitScreen_OnChange();
|
||||
|
||||
|
|
|
|||
|
|
@ -1723,6 +1723,10 @@ UINT8 CanChangeSkin(INT32 playernum)
|
|||
static void ForceAllSkins(INT32 forcedskin)
|
||||
{
|
||||
INT32 i, j;
|
||||
|
||||
if (demo.playback)
|
||||
return; // DXD_SKIN should handle all changes for us
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
|
|
@ -1793,6 +1797,8 @@ static void SendNameAndColor(UINT8 n)
|
|||
char buf[MAXPLAYERNAME+12];
|
||||
char *p;
|
||||
|
||||
UINT16 i = 0;
|
||||
|
||||
if (splitscreen < n)
|
||||
return; // can happen if skin4/color4/name4 changed
|
||||
|
||||
|
|
@ -1810,9 +1816,10 @@ static void SendNameAndColor(UINT8 n)
|
|||
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 {
|
||||
UINT16 i = 0;
|
||||
while (i<numskincolors && !skincolors[i].accessible) i++;
|
||||
else
|
||||
{
|
||||
while (i<numskincolors && !skincolors[i].accessible)
|
||||
i++;
|
||||
CV_StealthSetValue(&cv_playercolor[n], (i != numskincolors) ? i : SKINCOLOR_BLUE);
|
||||
}
|
||||
}
|
||||
|
|
@ -1842,8 +1849,6 @@ static void SendNameAndColor(UINT8 n)
|
|||
&& fasticmp(cv_voice[n].string, voice->name))
|
||||
return;
|
||||
|
||||
player->availabilities = R_GetSkinAvailabilities();
|
||||
|
||||
// We'll handle it later if we're not playing.
|
||||
if (!Playing())
|
||||
return;
|
||||
|
|
@ -2063,7 +2068,6 @@ static void SendNameAndColor(UINT8 n)
|
|||
|
||||
// Finally write out the complete packet and send it off.
|
||||
WRITESTRINGN(p, cv_playername[n].zstring, MAXPLAYERNAME);
|
||||
WRITEUINT32(p, (UINT32)player->availabilities);
|
||||
WRITEUINT16(p, (UINT16)cv_playercolor[n].value);
|
||||
WRITEUINT16(p, (UINT16)cv_skin[n].value);
|
||||
WRITEINT32(p, (INT32)cv_follower[n].value);
|
||||
|
|
@ -2105,7 +2109,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
}
|
||||
|
||||
READSTRINGN(*cp, name, MAXPLAYERNAME);
|
||||
p->availabilities = READUINT32(*cp);
|
||||
color = READUINT16(*cp);
|
||||
skin = READUINT16(*cp);
|
||||
follower = READINT32(*cp);
|
||||
|
|
@ -2143,36 +2146,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
if (skincolors[p->skincolor].accessible == false)
|
||||
kick = true;
|
||||
|
||||
// availabilities
|
||||
// TODO: Port commit from RR: 6d0637d3
|
||||
/*
|
||||
for (i = 0; i < MAXSKINS; i++)
|
||||
{
|
||||
UINT32 playerhasunlocked = (p->availabilities & (1 << i));
|
||||
boolean islocked = false;
|
||||
UINT8 j;
|
||||
|
||||
for (j = 0; j < MAXUNLOCKABLES; j++)
|
||||
{
|
||||
if (unlockables[j].type != SECRET_SKIN)
|
||||
continue;
|
||||
|
||||
if (unlockables[j].variable == i)
|
||||
{
|
||||
islocked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (islocked == false && playerhasunlocked == true)
|
||||
{
|
||||
// hacked client that enabled every bit
|
||||
kick = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (kick)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal color change received from %s (team: %d), color: %d)\n"), player_names[playernum], p->ctfteam, p->skincolor);
|
||||
|
|
@ -2182,7 +2155,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
}
|
||||
|
||||
// set skin
|
||||
if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player
|
||||
if (cv_forceskin.value >= 0 && K_CanChangeRules(true)) // Server wants everyone to use the same player
|
||||
{
|
||||
const INT32 forcedskin = cv_forceskin.value;
|
||||
SetPlayerSkinByNum(playernum, forcedskin);
|
||||
|
|
@ -6631,11 +6604,6 @@ void Command_ExitGame_f(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
CL_ClearPlayer(i);
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
players[g_localplayers[i]].availabilities = R_GetSkinAvailabilities();
|
||||
}
|
||||
|
||||
splitscreen = 0;
|
||||
SplitScreen_OnChange();
|
||||
|
||||
|
|
|
|||
|
|
@ -498,7 +498,7 @@ struct player_t
|
|||
|
||||
INT32 skin;
|
||||
UINT16 voice_id;
|
||||
UINT32 availabilities;
|
||||
UINT8 availabilities[MAXAVAILABILITY];
|
||||
|
||||
UINT8 kartspeed; // Kart speed stat between 1 and 9
|
||||
UINT8 kartweight; // Kart weight stat between 1 and 9
|
||||
|
|
|
|||
|
|
@ -134,6 +134,36 @@ static float searchfvalue(const char *s)
|
|||
#endif
|
||||
|
||||
// These are for clearing all of various things
|
||||
void clear_emblems(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXEMBLEMS; ++i)
|
||||
{
|
||||
Z_Free(emblemlocations[i].level);
|
||||
emblemlocations[i].level = NULL;
|
||||
|
||||
Z_Free(emblemlocations[i].stringVar);
|
||||
emblemlocations[i].stringVar = NULL;
|
||||
}
|
||||
|
||||
memset(&emblemlocations, 0, sizeof(emblemlocations));
|
||||
numemblems = 0;
|
||||
}
|
||||
|
||||
void clear_unlockables(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXUNLOCKABLES; ++i)
|
||||
{
|
||||
Z_Free(unlockables[i].stringVar);
|
||||
unlockables[i].stringVar = NULL;
|
||||
}
|
||||
|
||||
memset(&unlockables, 0, sizeof(unlockables));
|
||||
}
|
||||
|
||||
void clear_conditionsets(void)
|
||||
{
|
||||
UINT8 i;
|
||||
|
|
@ -2679,7 +2709,12 @@ void reademblemdata(MYFILE *f, INT32 num)
|
|||
else if (fastcmp(word, "COLOR"))
|
||||
emblemlocations[num-1].color = get_number(word2);
|
||||
else if (fastcmp(word, "VAR"))
|
||||
{
|
||||
Z_Free(emblemlocations[num-1].stringVar);
|
||||
emblemlocations[num-1].stringVar = Z_StrDup(word2);
|
||||
|
||||
emblemlocations[num-1].var = get_number(word2);
|
||||
}
|
||||
else
|
||||
deh_warning("Emblem %d: unknown word '%s'", num, word);
|
||||
}
|
||||
|
|
@ -2883,7 +2918,8 @@ void readunlockable(MYFILE *f, INT32 num)
|
|||
}
|
||||
else if (fastcmp(word, "VAR"))
|
||||
{
|
||||
// TODO: different field for level name string
|
||||
Z_Free(unlockables[num].stringVar);
|
||||
unlockables[num].stringVar = Z_StrDup(word2);
|
||||
unlockables[num].variable = (INT16)G_MapNumber(word2);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ void readlight(MYFILE *f, INT32 num);
|
|||
void readskincolor(MYFILE *f, INT32 num, boolean mainfile);
|
||||
void readthing(MYFILE *f, INT32 num);
|
||||
void readfreeslots(MYFILE *f);
|
||||
void clear_emblems(void);
|
||||
void clear_unlockables(void);
|
||||
void clear_levels(void);
|
||||
void clear_conditionsets(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -846,12 +846,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
}
|
||||
|
||||
if (clearall || fastcmp(word2, "UNLOCKABLES"))
|
||||
memset(&unlockables, 0, sizeof(unlockables));
|
||||
{
|
||||
clear_unlockables();
|
||||
}
|
||||
|
||||
if (clearall || fastcmp(word2, "EMBLEMS"))
|
||||
{
|
||||
memset(&emblemlocations, 0, sizeof(emblemlocations));
|
||||
numemblems = 0;
|
||||
clear_emblems();
|
||||
}
|
||||
|
||||
if (clearall || fastcmp(word2, "EXTRAEMBLEMS"))
|
||||
|
|
|
|||
|
|
@ -199,6 +199,8 @@ extern char logfilename[1024];
|
|||
|
||||
#define MAXSKINS 4096
|
||||
#define MAXFOLLOWERS UINT16_MAX
|
||||
#define MAXSKINUNAVAILABLE 128
|
||||
#define MAXAVAILABILITY MAXSKINUNAVAILABLE/8
|
||||
|
||||
#define COLORRAMPSIZE 16
|
||||
#define MAXCOLORNAME 32
|
||||
|
|
|
|||
46
src/g_demo.c
46
src/g_demo.c
|
|
@ -110,7 +110,7 @@ demoghost *ghosts = NULL;
|
|||
// DEMO RECORDING
|
||||
//
|
||||
|
||||
#define DEMOVERSION 0x000E
|
||||
#define DEMOVERSION 0x000F
|
||||
#define DEMOHEADER "\xF0" "BlanReplay" "\x0F"
|
||||
|
||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||
|
|
@ -228,6 +228,7 @@ typedef struct
|
|||
UINT8 kartspeed;
|
||||
UINT8 kartweight;
|
||||
mobjtype_t followitem;
|
||||
UINT8 availabilities[MAXAVAILABILITY];
|
||||
} demoplayer_t;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -550,6 +551,7 @@ static void G_FreeExtraZipTic(ziptic_t *zt)
|
|||
|
||||
static UINT8 *G_ReadRawExtraData(extradata_t *extra, UINT8 *dp, UINT16 version)
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 extradata;
|
||||
extra->playernum = READUINT8(dp);
|
||||
boolean kart = version <= 0x0002;
|
||||
|
|
@ -591,6 +593,14 @@ static UINT8 *G_ReadRawExtraData(extradata_t *extra, UINT8 *dp, UINT16 version)
|
|||
|
||||
if (extradata & DXD_JOINDATA)
|
||||
{
|
||||
if (version >= 0x000F)
|
||||
{
|
||||
for (i = 0; i < MAXAVAILABILITY; i++)
|
||||
{
|
||||
players[extra->playernum].availabilities[i] = READUINT8(dp);
|
||||
}
|
||||
}
|
||||
|
||||
extra->joindata.bot = !!(READUINT8(dp));
|
||||
if (extra->joindata.bot)
|
||||
{
|
||||
|
|
@ -693,6 +703,8 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
|
|||
boolean serverinfo = true;
|
||||
boolean rapreset = true; // + extended serverinfo length
|
||||
boolean dubs = true; // Multiple voices
|
||||
boolean availabilities = true; // Store player availabilities
|
||||
INT32 i;
|
||||
|
||||
// these may not be present in old demo formats, so initialize them
|
||||
// also initialize them so the header can be free'd without issues
|
||||
|
|
@ -730,6 +742,8 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
|
|||
/* FALLTHRU */
|
||||
case 0x000D:
|
||||
dubs = false;
|
||||
case 0x000E:
|
||||
availabilities = false;
|
||||
break;
|
||||
|
||||
default: // too old, cannot support.
|
||||
|
|
@ -739,7 +753,7 @@ static headerstatus_e G_ReadDemoHeader(UINT8 *dp, demoheader_t *header)
|
|||
else if (!memcmp(startdp, "\xF0" "KartReplay" "\x0F", 12))
|
||||
{
|
||||
dubs = rapreset = raflag = false;
|
||||
serverinfo = false;
|
||||
serverinfo = availabilities = false;
|
||||
switch (header->demoversion)
|
||||
{
|
||||
case 0x0001: // SRB2Kart 1.0.x (only staff ghosts supported)
|
||||
|
|
@ -832,7 +846,7 @@ readfiles:
|
|||
header->numfiles = READUINT8(dp);
|
||||
if (header->numfiles)
|
||||
header->files = malloc(sizeof(demofile_t) * header->numfiles);
|
||||
for (UINT8 i = 0; i < header->numfiles; i++)
|
||||
for (i = 0; i < header->numfiles; i++)
|
||||
{
|
||||
char filename[MAX_WADPATH];
|
||||
READSTRINGL(dp, filename, MAX_WADPATH);
|
||||
|
|
@ -891,7 +905,7 @@ skipfiles:
|
|||
header->numcvars = READUINT16(dp);
|
||||
if (header->numcvars)
|
||||
header->cvars = malloc(sizeof(democvar_t) * header->numcvars);
|
||||
for (UINT16 i = 0; i < header->numcvars; i++)
|
||||
for (i = 0; i < header->numcvars; i++)
|
||||
{
|
||||
if (kart)
|
||||
{
|
||||
|
|
@ -994,6 +1008,11 @@ skipfiles:
|
|||
plr->kartspeed = READUINT8(dp);
|
||||
plr->kartweight = READUINT8(dp);
|
||||
plr->followitem = !kart ? READUINT32(dp) : MT_NULL;
|
||||
|
||||
for (i = 0; i < MAXAVAILABILITY; i++)
|
||||
{
|
||||
plr->availabilities[i] = availabilities ? READUINT8(dp) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Sigh ... it's an empty demo. Again.
|
||||
|
|
@ -1342,7 +1361,7 @@ void G_ReadDemoExtraData(void)
|
|||
|
||||
void G_WriteDemoExtraData(void)
|
||||
{
|
||||
INT32 i;
|
||||
INT32 i, j;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (demo_extradata[i])
|
||||
|
|
@ -1352,6 +1371,11 @@ void G_WriteDemoExtraData(void)
|
|||
|
||||
if (demo_extradata[i] & DXD_JOINDATA)
|
||||
{
|
||||
for (j = 0; j < MAXAVAILABILITY; j++)
|
||||
{
|
||||
WRITEUINT8(demobuf.p, players[i].availabilities[i]);
|
||||
}
|
||||
|
||||
WRITEUINT8(demobuf.p, (UINT8)players[i].bot);
|
||||
if (players[i].bot)
|
||||
{
|
||||
|
|
@ -2821,7 +2845,7 @@ void G_RecordMetal(void)
|
|||
|
||||
void G_BeginRecording(void)
|
||||
{
|
||||
UINT8 i, p;
|
||||
UINT8 i, j, p;
|
||||
char name[MAXCOLORNAME+1];
|
||||
player_t *player = &players[consoleplayer];
|
||||
|
||||
|
|
@ -3005,6 +3029,11 @@ void G_BeginRecording(void)
|
|||
|
||||
// And mobjtype_t is best with UINT32 too...
|
||||
WRITEUINT32(demobuf.p, player->followitem);
|
||||
|
||||
for (j = 0; j < MAXAVAILABILITY; j++)
|
||||
{
|
||||
WRITEUINT8(demobuf.p, player->availabilities[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3895,6 +3924,11 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
// Followitem
|
||||
player->followitem = plr->followitem;
|
||||
|
||||
for (i = 0; i < MAXAVAILABILITY; i++)
|
||||
{
|
||||
player->availabilities[i] = plr->availabilities[i];
|
||||
}
|
||||
}
|
||||
|
||||
// end of player read (the 0xFF marker)
|
||||
|
|
|
|||
|
|
@ -2713,7 +2713,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
UINT16 skincolor;
|
||||
INT32 skin;
|
||||
UINT16 voice;
|
||||
UINT32 availabilities;
|
||||
UINT8 availabilities[MAXAVAILABILITY];
|
||||
|
||||
tic_t jointime;
|
||||
|
||||
|
|
@ -2783,7 +2783,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
|
||||
jitterlegacy = players[player].jitterlegacy;
|
||||
|
||||
availabilities = players[player].availabilities;
|
||||
memcpy(availabilities, players[player].availabilities, sizeof(availabilities));
|
||||
|
||||
charflags = players[player].charflags;
|
||||
|
||||
|
|
@ -2967,7 +2967,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->kartweight = kartweight;
|
||||
//
|
||||
p->charflags = charflags;
|
||||
p->availabilities = availabilities;
|
||||
memcpy(players[player].availabilities, availabilities, sizeof(availabilities));
|
||||
p->followitem = followitem;
|
||||
|
||||
p->starpostx = starpostx;
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ void K_SetNameForBot(UINT8 newplayernum, const char *realname)
|
|||
--------------------------------------------------*/
|
||||
void K_SetBot(UINT8 newplayernum, UINT16 skinnum, UINT8 difficulty, botStyle_e style)
|
||||
{
|
||||
INT32 i;
|
||||
CONS_Debug(DBG_NETPLAY, "addbot: %d\n", newplayernum);
|
||||
|
||||
G_AddPlayer(newplayernum, newplayernum);
|
||||
|
|
@ -154,6 +155,15 @@ void K_SetBot(UINT8 newplayernum, UINT16 skinnum, UINT8 difficulty, botStyle_e s
|
|||
if (newplayernum+1 > doomcom->numslots)
|
||||
doomcom->numslots = (INT16)(newplayernum+1);
|
||||
|
||||
// todo find a way to have all auto unlocked for dedicated
|
||||
if (playeringame[0])
|
||||
{
|
||||
for (i = 0; i < MAXAVAILABILITY; i++)
|
||||
{
|
||||
players[newplayernum].availabilities[i] = players[0].availabilities[i];
|
||||
}
|
||||
}
|
||||
|
||||
playernode[newplayernum] = servernode;
|
||||
|
||||
players[newplayernum].splitscreenindex = 0;
|
||||
|
|
|
|||
|
|
@ -1191,9 +1191,9 @@ static int player_get(lua_State *L)
|
|||
case player_voice_id:
|
||||
lua_pushinteger(L, plr->voice_id);
|
||||
break;
|
||||
case player_availabilities:
|
||||
/*case player_availabilities:
|
||||
lua_pushinteger(L, plr->availabilities);
|
||||
break;
|
||||
break;*/
|
||||
case player_score:
|
||||
lua_pushinteger(L, plr->score);
|
||||
break;
|
||||
|
|
@ -1518,8 +1518,8 @@ static int player_set(lua_State *L)
|
|||
return NOSET;
|
||||
case player_voice_id:
|
||||
return NOSET;
|
||||
case player_availabilities:
|
||||
return NOSET;
|
||||
/*case player_availabilities:
|
||||
return NOSET;*/
|
||||
case player_score:
|
||||
plr->score = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
|
|
|||
52
src/m_cond.c
52
src/m_cond.c
|
|
@ -48,17 +48,17 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] =
|
|||
// Default Unlockables
|
||||
unlockable_t unlockables[MAXUNLOCKABLES] =
|
||||
{
|
||||
// Name, Objective, Showing Conditionset, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist
|
||||
/* 01 */ {"Egg Cup", "", -1, 1, SECRET_NONE, 0, false, false, 0},
|
||||
/* 02 */ {"Chao Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0},
|
||||
/* 03 */ {"SMK Cup", "", 2, 3, SECRET_NONE, 0, false, false, 0},
|
||||
// Name, Objective, Showing Conditionset, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist, Unlocked
|
||||
/* 01 */ {"Egg Cup", "", -1, 1, SECRET_NONE, 0, "", false, false, 0},
|
||||
/* 02 */ {"Chao Cup", "", -1, 2, SECRET_NONE, 0, "", false, false, 0},
|
||||
/* 03 */ {"SMK Cup", "", 2, 3, SECRET_NONE, 0, "", false, false, 0},
|
||||
|
||||
/* 04 */ {"Hard Game Speed", "", -1, 4, SECRET_HARDSPEED, 0, false, false, 0},
|
||||
/* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0},
|
||||
/* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0},
|
||||
/* 04 */ {"Hard Game Speed", "", -1, 4, SECRET_HARDSPEED, 0, "", false, false, 0},
|
||||
/* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, "", false, false, 0},
|
||||
/* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, "", false, false, 0},
|
||||
|
||||
/* 07 */ {"Record Attack", "", -1, -1, SECRET_TIMEATTACK, 0, true, true, 0},
|
||||
/* 08 */ {"Capsule Attack", "", -1, -1, SECRET_ITEMBREAKER, 0, true, true, 0},
|
||||
/* 07 */ {"Record Attack", "", -1, -1, SECRET_TIMEATTACK, 0, "" ,true, true, 0},
|
||||
/* 08 */ {"Capsule Attack", "", -1, -1, SECRET_ITEMBREAKER, 0, "", true, true, 0},
|
||||
};
|
||||
|
||||
// Number of emblems and extra emblems
|
||||
|
|
@ -344,11 +344,6 @@ void M_SilentUpdateUnlockablesAndEmblems(void)
|
|||
continue;
|
||||
unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
players[g_localplayers[i]].availabilities = R_GetSkinAvailabilities();
|
||||
}
|
||||
}
|
||||
|
||||
// Emblem unlocking shit
|
||||
|
|
@ -555,6 +550,35 @@ UINT8 M_GotLowEnoughTime(INT32 tictime)
|
|||
*/
|
||||
}
|
||||
|
||||
// Gets the skin number for a SECRET_SKIN unlockable.
|
||||
INT32 M_UnlockableSkinNum(unlockable_t *unlock)
|
||||
{
|
||||
if (unlock->type != SECRET_SKIN)
|
||||
{
|
||||
// This isn't a skin unlockable...
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlock->stringVar && strcmp(unlock->stringVar, ""))
|
||||
{
|
||||
// Get the skin from the string.
|
||||
INT32 skinnum = R_SkinAvailable(unlock->stringVar);
|
||||
if (skinnum != -1)
|
||||
{
|
||||
return skinnum;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlock->variable >= 0 && unlock->variable < numskins)
|
||||
{
|
||||
// Use the number directly.
|
||||
return unlock->variable;
|
||||
}
|
||||
|
||||
// Invalid skin unlockable.
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ----------------
|
||||
// Misc Emblem shit
|
||||
// ----------------
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ struct emblem_t
|
|||
UINT8 sprite; ///< emblem sprite to use, 0 - 25
|
||||
UINT16 color; ///< skincolor to use
|
||||
INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin)
|
||||
char *stringVar; ///< String version
|
||||
char hint[110]; ///< Hint for emblem hints menu
|
||||
UINT8 collected; ///< Do you have this emblem?
|
||||
};
|
||||
|
|
@ -107,6 +108,7 @@ struct unlockable_t
|
|||
UINT8 showconditionset;
|
||||
INT16 type;
|
||||
INT16 variable;
|
||||
char *stringVar;
|
||||
UINT8 nocecho;
|
||||
UINT8 nochecklist;
|
||||
UINT8 unlocked;
|
||||
|
|
@ -185,6 +187,9 @@ const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big);
|
|||
UINT8 M_GotEnoughEmblems(INT32 number);
|
||||
UINT8 M_GotLowEnoughTime(INT32 tictime);
|
||||
|
||||
INT32 M_UnlockableSkinNum(unlockable_t *unlock);
|
||||
INT32 M_EmblemSkinNum(emblem_t *emblem);
|
||||
|
||||
// vvvvvvvvvv anti-integer promotion, do not remove
|
||||
#define M_Achieved(a) ((unsigned)(a) >= MAXCONDITIONSETS || conditionSets[a].achieved)
|
||||
|
||||
|
|
|
|||
|
|
@ -477,7 +477,12 @@ static void P_NetSyncPlayers(savebuffer_t *save)
|
|||
SYNC(players[i].skincolor);
|
||||
SYNC(players[i].skin);
|
||||
SYNC(players[i].voice_id);
|
||||
SYNC(players[i].availabilities);
|
||||
|
||||
for (j = 0; j < MAXAVAILABILITY; j++)
|
||||
{
|
||||
SYNC(players[i].availabilities[j]);
|
||||
}
|
||||
|
||||
SYNC(players[i].score);
|
||||
SYNC(players[i].lives);
|
||||
SYNC(players[i].xtralife);
|
||||
|
|
|
|||
110
src/r_skins.c
110
src/r_skins.c
|
|
@ -36,6 +36,8 @@
|
|||
#include "hardware/hw_md2.h"
|
||||
#endif
|
||||
|
||||
#include "k_grandprix.h"
|
||||
|
||||
#include "discord.h"
|
||||
|
||||
INT32 numskins = 0;
|
||||
|
|
@ -305,21 +307,34 @@ void R_InitSkins(void)
|
|||
ST_ReloadSkinFaceGraphics();
|
||||
}
|
||||
|
||||
UINT32 R_GetSkinAvailabilities(void)
|
||||
UINT8 *R_GetSkinAvailabilities(void)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT32 response = 0;
|
||||
UINT8 i, shif, byte;
|
||||
INT32 skinid;
|
||||
static UINT8 responsebuffer[MAXAVAILABILITY];
|
||||
|
||||
memset(&responsebuffer, 0, sizeof(responsebuffer));
|
||||
|
||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||
{
|
||||
if (unlockables[i].type == SECRET_SKIN && unlockables[i].unlocked)
|
||||
{
|
||||
UINT16 s = min(unlockables[i].variable, MAXSKINS);
|
||||
response |= (1 << s);
|
||||
}
|
||||
if (unlockables[i].type != SECRET_SKIN)
|
||||
continue;
|
||||
|
||||
if (unlockables[i].unlocked != true)
|
||||
continue;
|
||||
|
||||
skinid = M_UnlockableSkinNum(&unlockables[i]);
|
||||
|
||||
if (skinid < 0 || skinid >= MAXSKINUNAVAILABLE)
|
||||
continue;
|
||||
|
||||
shif = (skinid % 8);
|
||||
byte = (skinid / 8);
|
||||
|
||||
responsebuffer[byte] |= (1 << shif);
|
||||
}
|
||||
|
||||
return response;
|
||||
return responsebuffer;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -461,7 +476,9 @@ INT32 FindSortedSkinIndex(INT32 skinnum)
|
|||
boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
|
||||
{
|
||||
boolean needsunlocked = false;
|
||||
boolean useplayerstruct = (Playing() && playernum != -1);
|
||||
UINT8 i;
|
||||
INT32 skinid;
|
||||
|
||||
if (skinnum == -1)
|
||||
{
|
||||
|
|
@ -475,7 +492,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (netgame && (cv_forceskin.value == skinnum))
|
||||
if (K_CanChangeRules(true) && (cv_forceskin.value == skinnum))
|
||||
{
|
||||
// Being forced to play as this character by the server
|
||||
return true;
|
||||
|
|
@ -488,36 +505,45 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
|
|||
return (skinnum == metalskin);
|
||||
}
|
||||
|
||||
if (skinnum >= MAXSKINUNAVAILABLE)
|
||||
{
|
||||
// Keeping our packet size nice and sane in the wake of MAXSKINS increase, as suggested by toaster
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if this character is supposed to be unlockable or not
|
||||
for (i = 0; i < MAXUNLOCKABLES; i++)
|
||||
{
|
||||
if (unlockables[i].type == SECRET_SKIN && unlockables[i].variable == skinnum)
|
||||
{
|
||||
// i is now the unlockable index, we can use this later
|
||||
needsunlocked = true;
|
||||
break;
|
||||
}
|
||||
if (unlockables[i].type != SECRET_SKIN)
|
||||
continue;
|
||||
|
||||
skinid = M_UnlockableSkinNum(&unlockables[i]);
|
||||
|
||||
if (skinid != skinnum)
|
||||
continue;
|
||||
|
||||
// i is now the unlockable index, we can use this later
|
||||
needsunlocked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (needsunlocked == true)
|
||||
{
|
||||
// You can use this character IF you have it unlocked.
|
||||
if ((netgame || multiplayer) && playernum != -1)
|
||||
{
|
||||
// Use the netgame synchronized unlocks.
|
||||
return (boolean)(!(players[playernum].availabilities & (1 << skinnum)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the unlockables table directly
|
||||
return (boolean)(unlockables[i].unlocked);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (needsunlocked == false)
|
||||
{
|
||||
// Didn't trip anything, so we can use this character.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ok, you can use this character IF you have it unlocked.
|
||||
if (useplayerstruct)
|
||||
{
|
||||
// Use the netgame synchronized unlocks.
|
||||
UINT8 shif = (skinnum % 8);
|
||||
UINT8 byte = (skinnum / 8);
|
||||
return !!(players[playernum].availabilities[byte] & (1 << shif));
|
||||
}
|
||||
|
||||
// Use the unlockables table directly
|
||||
return (boolean)(unlockables[i].unlocked);
|
||||
}
|
||||
|
||||
// returns true if the skin name is found (loaded from pwad)
|
||||
|
|
@ -535,6 +561,24 @@ INT32 R_SkinAvailable(const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Gets the player to the first usuable skin in the game.
|
||||
// (If your mod locked them all, then you kinda stupid)
|
||||
static INT32 GetPlayerDefaultSkin(INT32 playernum)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
{
|
||||
if (R_SkinUsable(playernum, i))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
I_Error("All characters are locked!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// network code calls this when a 'skin change' is received
|
||||
void SetPlayerSkin(INT32 playernum, const char *skinname)
|
||||
{
|
||||
|
|
@ -552,7 +596,7 @@ void SetPlayerSkin(INT32 playernum, const char *skinname)
|
|||
else if(server || IsPlayerAdmin(consoleplayer))
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname);
|
||||
|
||||
SetPlayerSkinByNum(playernum, 0);
|
||||
SetPlayerSkinByNum(playernum, GetPlayerDefaultSkin(playernum));
|
||||
}
|
||||
|
||||
// Same as SetPlayerSkin, but uses the skin #.
|
||||
|
|
@ -621,7 +665,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
else if(server || IsPlayerAdmin(consoleplayer))
|
||||
CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum);
|
||||
|
||||
SetPlayerSkinByNum(playernum, 0); // not found, put in the default skin
|
||||
SetPlayerSkinByNum(playernum, GetPlayerDefaultSkin(playernum)); // not found, put in the default skin
|
||||
}
|
||||
|
||||
// Gets the corresponding voice ID for a given voice's name.
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ INT32 FindSortedSkinIndex(INT32 skinnum);
|
|||
void SetPlayerSkin(INT32 playernum,const char *skinname);
|
||||
void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
|
||||
boolean R_SkinUsable(INT32 playernum, INT32 skinnum);
|
||||
UINT32 R_GetSkinAvailabilities(void);
|
||||
UINT8 *R_GetSkinAvailabilities(void);
|
||||
INT32 R_SkinAvailable(const char *name);
|
||||
void R_PatchSkins(UINT16 wadnum);
|
||||
void R_AddSkins(UINT16 wadnum);
|
||||
|
|
|
|||
Loading…
Reference in a new issue