From f93b1b8d7b5e6f4b73e73513e74f6e84c377dfaa Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Mon, 19 Apr 2021 04:01:49 -0300 Subject: [PATCH] Raise the skin limit to 256. --- src/d_clisrv.c | 6 +- src/d_main.c | 7 +- src/d_netcmd.c | 18 +++-- src/d_player.h | 2 +- src/deh_soc.c | 31 ++++----- src/dehacked.c | 2 +- src/doomdef.h | 3 +- src/g_game.c | 2 +- src/hardware/hw_md2.c | 16 +++-- src/hardware/hw_md2.h | 2 +- src/hardware/hw_model.c | 3 +- src/lua_playerlib.c | 3 +- src/m_cond.c | 3 +- src/m_menu.c | 141 ++++++++++++++++++++++------------------ src/m_menu.h | 7 +- src/p_saveg.c | 4 +- src/r_picformats.c | 9 ++- src/r_skins.c | 55 ++++++++-------- src/r_skins.h | 5 +- src/sounds.h | 4 +- src/st_stuff.c | 15 ++++- src/st_stuff.h | 6 +- 22 files changed, 195 insertions(+), 149 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7c2dec6a1..f1c24fe5a 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2463,6 +2463,8 @@ void CL_ClearPlayer(INT32 playernum) { if (players[playernum].mo) P_RemoveMobj(players[playernum].mo); + if (players[playernum].availabilities) + Z_Free(players[playernum].availabilities); memset(&players[playernum], 0, sizeof (player_t)); memset(playeraddress[playernum], 0, sizeof(*playeraddress)); } @@ -4486,9 +4488,9 @@ static INT16 Consistancy(void) { if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - + mo = (mobj_t *)th; - + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) { ret -= mo->type; diff --git a/src/d_main.c b/src/d_main.c index 23a2c0133..e9d236a9b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -813,7 +813,8 @@ void D_StartTitle(void) for (i = 0; i < MAXPLAYERS; i++) CL_ClearPlayer(i); - players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); + R_GetSkinAvailabilities(&players[1].availabilities); // players[1] is supposed to be for 2p splitscreen = false; SplitScreen_OnChange(); @@ -1216,10 +1217,6 @@ void D_SRB2Main(void) // Make backups of some SOCcable tables. P_BackupTables(); - // Setup character tables - // Have to be done here before files are loaded - M_InitCharacterTables(); - mainwads = 3; // doesn't include music.dta #ifdef USE_PATCH_DTA mainwads++; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 09f9d4651..14349d559 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1235,7 +1235,7 @@ static void SendNameAndColor(void) && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) return; - players[consoleplayer].availabilities = R_GetSkinAvailabilities(); + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); // We'll handle it later if we're not playing. if (!Playing()) @@ -1319,9 +1319,9 @@ static void SendNameAndColor(void) // Finally write out the complete packet and send it off. WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME); - WRITEUINT32(p, (UINT32)players[consoleplayer].availabilities); WRITEUINT16(p, (UINT16)cv_playercolor.value); WRITEUINT8(p, (UINT8)cv_skin.value); + WRITEMEM(p, players[consoleplayer].availabilities, sizeof(bitarray_t) * numskins); SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf); } @@ -1363,7 +1363,7 @@ static void SendNameAndColor2(void) } } - players[secondplaya].availabilities = R_GetSkinAvailabilities(); + R_GetSkinAvailabilities(&players[secondplaya].availabilities); // We'll handle it later if we're not playing. if (!Playing()) @@ -1455,10 +1455,13 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) #endif READSTRINGN(*cp, name, MAXPLAYERNAME); - p->availabilities = READUINT32(*cp); color = READUINT16(*cp); skin = READUINT8(*cp); + if (p->availabilities == NULL) + p->availabilities = Z_Malloc(sizeof(bitarray_t) * numskins, PU_STATIC, NULL); + READMEM(*cp, p->availabilities, sizeof(bitarray_t) * numskins); + // set name if (player_name_changes[playernum] < MAXNAMECHANGES) { @@ -1491,9 +1494,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) kick = true; // availabilities - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < numskins; s++) { - if (!skins[s].availability && (p->availabilities & (1 << s))) + if (!skins[s].availability && in_bit_array(p->availabilities, s)) { kick = true; break; @@ -4278,7 +4281,8 @@ void Command_ExitGame_f(void) for (i = 0; i < MAXPLAYERS; i++) CL_ClearPlayer(i); - players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); + R_GetSkinAvailabilities(&players[1].availabilities); // players[1] is supposed to be for 2p splitscreen = false; SplitScreen_OnChange(); diff --git a/src/d_player.h b/src/d_player.h index 2e7afed88..d90dd79ff 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -379,7 +379,7 @@ typedef struct player_s UINT16 skincolor; INT32 skin; - UINT32 availabilities; + bitarray_t *availabilities; UINT32 score; // player score fixed_t dashspeed; // dashing speed diff --git a/src/deh_soc.c b/src/deh_soc.c index 5b12ea1b0..046ed885a 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -162,23 +162,20 @@ void clear_levels(void) static boolean findFreeSlot(INT32 *num) { - // Send the character select entry to a free slot. - while (*num < MAXSKINS && (description[*num].used)) - *num = *num+1; + if (description) + { + // Send the character select entry to a free slot. + while (*num < numdescriptions && (description[*num].used)) + (*num)++; + } - // No more free slots. :( - if (*num >= MAXSKINS) + // No more free slots. + if (*num >= MAXCHARACTERSLOTS) return false; + else if (*num >= numdescriptions) + M_InitCharacterTables((*num) + 1); - // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...) - description[*num].picname[0] = '\0'; - description[*num].nametag[0] = '\0'; - description[*num].displayname[0] = '\0'; - description[*num].oppositecolor = SKINCOLOR_NONE; - description[*num].tagtextcolor = SKINCOLOR_NONE; - description[*num].tagoutlinecolor = SKINCOLOR_NONE; - - // Found one! ^_^ + // Found one! return (description[*num].used = true); } @@ -891,7 +888,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) INT32 value; #endif char *lastline; - INT32 skinnumbers[MAXSKINS]; + INT32 *skinnumbers = NULL; INT32 foundskins = 0; // allocate a spriteinfo @@ -980,6 +977,8 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) break; } + if (skinnumbers == NULL) + skinnumbers = Z_Malloc(sizeof(INT32) * numskins, PU_STATIC, NULL); skinnumbers[foundskins] = skinnum; foundskins++; } @@ -1043,6 +1042,8 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) Z_Free(s); Z_Free(info); + if (skinnumbers) + Z_Free(skinnumbers); } void readsprite2(MYFILE *f, INT32 num) diff --git a/src/dehacked.c b/src/dehacked.c index c2ea28d27..8d3c5725f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -241,7 +241,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) i = 0; if (fastcmp(word, "CHARACTER")) { - if (i >= 0 && i < 32) + if (i >= 0 && i < MAXCHARACTERSLOTS) readPlayer(f, i); else { diff --git a/src/doomdef.h b/src/doomdef.h index 52abc9597..e7831f689 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -220,7 +220,8 @@ extern char logfilename[1024]; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 32 -#define MAXSKINS 32 +#define MAXSKINS 256 +#define MAXCHARACTERSLOTS (MAXSKINS * 2) #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 diff --git a/src/g_game.c b/src/g_game.c index 13423ce77..7f48556ff 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2486,7 +2486,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT8 mare; UINT16 skincolor; INT32 skin; - UINT32 availabilities; + bitarray_t *availabilities; tic_t jointime; tic_t quittime; boolean spectator; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5caf344f7..cba322b2a 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -71,7 +71,7 @@ #endif md2_t md2_models[NUMSPRITES]; -md2_t md2_playermodels[MAXSKINS]; +md2_t *md2_playermodels = NULL; /* @@ -490,7 +490,11 @@ void HWR_InitModels(void) size_t prefixlen; CONS_Printf("HWR_InitModels()...\n"); - for (s = 0; s < MAXSKINS; s++) + + if (numskins && md2_playermodels == NULL) + md2_playermodels = Z_Malloc(sizeof(md2_t), PU_STATIC, NULL); + + for (s = 0; s < numskins; s++) { md2_playermodels[s].scale = -1.0f; md2_playermodels[s].model = NULL; @@ -501,6 +505,7 @@ void HWR_InitModels(void) md2_playermodels[s].notfound = true; md2_playermodels[s].error = false; } + for (i = 0; i < NUMSPRITES; i++) { md2_models[i].scale = -1.0f; @@ -561,7 +566,7 @@ void HWR_InitModels(void) addskinmodel: // add player model - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < numskins; s++) { if (stricmp(skinname, skins[s].name) == 0) { @@ -581,7 +586,7 @@ modelfound: fclose(f); } -void HWR_AddPlayerModel(int skin) // For skins that were added after startup +void HWR_AddPlayerModel(INT32 skin) // For skins that were added after startup { FILE *f; char name[24], filename[32]; @@ -608,6 +613,9 @@ void HWR_AddPlayerModel(int skin) // For skins that were added after startup } } + // realloc player models table + md2_playermodels = Z_Realloc(md2_playermodels, sizeof(md2_t) * numskins, PU_STATIC, NULL); + // length of the player model prefix prefixlen = strlen(PLAYERMODELPREFIX); diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 0f4d2c7bc..42787115a 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -37,7 +37,7 @@ typedef struct } md2_t; extern md2_t md2_models[NUMSPRITES]; -extern md2_t md2_playermodels[MAXSKINS]; +extern md2_t *md2_playermodels; void HWR_InitModels(void); void HWR_AddPlayerModel(INT32 skin); diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 4ed03744b..86e2a0c70 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -10,6 +10,7 @@ #include "../doomdef.h" #include "../doomtype.h" #include "../info.h" +#include "../r_skins.h" #include "../z_zone.h" #include "hw_model.h" #include "hw_md2load.h" @@ -238,7 +239,7 @@ void HWR_ReloadModels(void) size_t i; INT32 s; - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < numskins; s++) { if (md2_playermodels[s].model) LoadModelSprite2(md2_playermodels[s].model); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0eb54808f..b05e21ca9 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -16,6 +16,7 @@ #include "d_player.h" #include "g_game.h" #include "p_local.h" +#include "r_skins.h" #include "lua_script.h" #include "lua_libs.h" @@ -161,7 +162,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"skin")) lua_pushinteger(L, plr->skin); else if (fastcmp(field,"availabilities")) - lua_pushinteger(L, plr->availabilities); + lua_pushinteger(L, R_GetAvailabilitiesBits(plr->availabilities)); else if (fastcmp(field,"score")) lua_pushinteger(L, plr->score); else if (fastcmp(field,"dashspeed")) diff --git a/src/m_cond.c b/src/m_cond.c index 36fcd7cf2..44ac94373 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -285,7 +285,8 @@ void M_SilentUpdateUnlockablesAndEmblems(void) unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1); } - players[consoleplayer].availabilities = players[1].availabilities = R_GetSkinAvailabilities(); // players[1] is supposed to be for 2p + R_GetSkinAvailabilities(&players[consoleplayer].availabilities); + R_GetSkinAvailabilities(&players[1].availabilities); // players[1] is supposed to be for 2p } // Emblem unlocking shit diff --git a/src/m_menu.c b/src/m_menu.c index 0fca39801..0c5c706a8 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -126,7 +126,9 @@ M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 -description_t description[MAXSKINS]; +description_t *description = NULL; +INT32 numdescriptions = 0; + INT16 char_on = -1, startchar = 0; static char *char_notes = NULL; @@ -255,7 +257,7 @@ static void M_ConfirmTeamScramble(INT32 choice); static void M_ConfirmTeamChange(INT32 choice); static void M_SecretsMenu(INT32 choice); static void M_SetupChoosePlayer(INT32 choice); -static UINT8 M_SetupChoosePlayerDirect(INT32 choice); +static UINT16 M_SetupChoosePlayerDirect(INT32 choice); static void M_QuitSRB2(INT32 choice); menu_t SP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; @@ -3970,24 +3972,32 @@ void M_Init(void) #endif } -void M_InitCharacterTables(void) +static void M_InitCharacterDescription(INT32 i) { - UINT8 i; - // Setup description table - for (i = 0; i < MAXSKINS; i++) - { - description[i].used = false; - strcpy(description[i].notes, "???"); - strcpy(description[i].picname, ""); - strcpy(description[i].nametag, ""); - strcpy(description[i].skinname, ""); - strcpy(description[i].displayname, ""); - description[i].prev = description[i].next = 0; - description[i].charpic = NULL; - description[i].namepic = NULL; - description[i].oppositecolor = description[i].tagtextcolor = description[i].tagoutlinecolor = 0; - } + description_t *desc = &description[i]; + desc->picname[0] = '\0'; + desc->nametag[0] = '\0'; + desc->skinname[0] = '\0'; + desc->displayname[0] = '\0'; + desc->prev = desc->next = 0; + desc->charpic = NULL; + desc->namepic = NULL; + desc->oppositecolor = SKINCOLOR_NONE; + desc->tagtextcolor = SKINCOLOR_NONE; + desc->tagoutlinecolor = SKINCOLOR_NONE; + strcpy(desc->notes, "???"); +} + +void M_InitCharacterTables(INT32 num) +{ + INT32 i = numdescriptions; + + description = Z_Realloc(description, sizeof(description_t) * num, PU_STATIC, NULL); + numdescriptions = num; + + for (; i < numdescriptions; i++) + M_InitCharacterDescription(i); } // ========================================================================== @@ -4981,7 +4991,7 @@ static void M_PatchSkinNameTable(void) for (j = 0; j < MAXSKINS; j++) { - if (skins[j].name[0] != '\0' && R_SkinUsable(-1, j)) + if (j < numskins && skins[j].name[0] != '\0' && R_SkinUsable(-1, j)) { skins_cons_t[j].strvalue = skins[j].realname; skins_cons_t[j].value = j+1; @@ -8961,64 +8971,67 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); } -static UINT8 M_SetupChoosePlayerDirect(INT32 choice) +static UINT16 M_SetupChoosePlayerDirect(INT32 choice) { INT32 skinnum; - UINT8 i; - UINT8 firstvalid = 255, lastvalid = 255; + UINT16 i; + UINT16 firstvalid = 65535, lastvalid = 65535; boolean allowed = false; - char *and; (void)choice; if (!mapheaderinfo[startmap-1] || mapheaderinfo[startmap-1]->forcecharacter[0] == '\0') { - for (i = 0; i < MAXSKINS; i++) // Handle charsels, availability, and unlocks. + for (i = 0; i < numdescriptions; i++) // Handle charsels, availability, and unlocks. { - if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. + char *and; + + // If the character's disabled through SOC, there's nothing we can do for it. + if (!description[i].used) + continue; + + and = strchr(description[i].skinname, '&'); + + if (and) { - and = strchr(description[i].skinname, '&'); - if (and) - { - char firstskin[SKINNAMESIZE+1]; - if (mapheaderinfo[startmap-1] && mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS) // skip tagteam characters for NiGHTS levels - continue; - strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); - firstskin[(and - description[i].skinname)] = '\0'; - description[i].skinnum[0] = R_SkinAvailable(firstskin); - description[i].skinnum[1] = R_SkinAvailable(and+1); - } + char firstskin[SKINNAMESIZE+1]; + if (mapheaderinfo[startmap-1] && mapheaderinfo[startmap-1]->typeoflevel & TOL_NIGHTS) // skip tagteam characters for NiGHTS levels + continue; + strncpy(firstskin, description[i].skinname, (and - description[i].skinname)); + firstskin[(and - description[i].skinname)] = '\0'; + description[i].skinnum[0] = R_SkinAvailable(firstskin); + description[i].skinnum[1] = R_SkinAvailable(and+1); + } + else + { + description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); + description[i].skinnum[1] = -1; + } + + skinnum = description[i].skinnum[0]; + + if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) + { + // Handling order. + if (firstvalid == 65535) + firstvalid = i; else { - description[i].skinnum[0] = R_SkinAvailable(description[i].skinname); - description[i].skinnum[1] = -1; + description[i].prev = lastvalid; + description[lastvalid].next = i; } - skinnum = description[i].skinnum[0]; - if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) - { - // Handling order. - if (firstvalid == 255) - firstvalid = i; - else - { - description[i].prev = lastvalid; - description[lastvalid].next = i; - } - lastvalid = i; + lastvalid = i; - if (i == char_on) - allowed = true; + if (i == char_on) + allowed = true; - M_CacheCharacterSelectEntry(i, skinnum); - } - // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. + M_CacheCharacterSelectEntry(i, skinnum); } + // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. } } if (firstvalid == lastvalid) // We're being forced into a specific character, so might as well just skip it. - { return firstvalid; - } // One last bit of order we can't do in the iteration above. description[firstvalid].prev = lastvalid; @@ -9027,7 +9040,7 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) if (!allowed) { char_on = firstvalid; - if (startchar > 0 && startchar < MAXSKINS) + if (startchar > 0 && startchar < numdescriptions) { INT16 workchar = startchar; while (workchar--) @@ -9035,13 +9048,13 @@ static UINT8 M_SetupChoosePlayerDirect(INT32 choice) } } - return MAXSKINS; + return MAXCHARACTERSLOTS; } static void M_SetupChoosePlayer(INT32 choice) { - UINT8 skinset = M_SetupChoosePlayerDirect(choice); - if (skinset != MAXSKINS) + UINT16 skinset = M_SetupChoosePlayerDirect(choice); + if (skinset != MAXCHARACTERSLOTS) { M_ChoosePlayer(skinset); return; @@ -9362,7 +9375,7 @@ static void M_ChoosePlayer(INT32 choice) UINT8 skinnum; // skip this if forcecharacter or no characters available - if (choice == 255) + if (choice == 65535) { skinnum = botskin = 0; botingame = false; @@ -10431,7 +10444,7 @@ static void M_MarathonLiveEventBackup(INT32 choice) // Going to Marathon menu... static void M_Marathon(INT32 choice) { - UINT8 skinset; + UINT16 skinset; INT32 mapnum = 0; if (choice != -1 && FIL_FileExists(liveeventbackup)) @@ -10454,7 +10467,7 @@ static void M_Marathon(INT32 choice) skinset = M_SetupChoosePlayerDirect(-1); - SP_MarathonMenu[marathonplayer].status = (skinset == MAXSKINS) ? IT_KEYHANDLER|IT_STRING : IT_NOTHING|IT_DISABLED; + SP_MarathonMenu[marathonplayer].status = (skinset == MAXCHARACTERSLOTS) ? IT_KEYHANDLER|IT_STRING : IT_NOTHING|IT_DISABLED; while (mapnum < NUMMAPS) { diff --git a/src/m_menu.h b/src/m_menu.h index 0465128ef..018d5c7e7 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -200,8 +200,8 @@ void M_Drawer(void); // Called by D_SRB2Main, loads the config file. void M_Init(void); -// Called by D_SRB2Main also, sets up the playermenu and description tables. -void M_InitCharacterTables(void); +// Called by deh_soc.c, sets up the playermenu and description tables. +void M_InitCharacterTables(INT32 num); // Called by intro code to force menu up upon a keypress, // does nothing if menu is already up. @@ -431,7 +431,8 @@ typedef struct INT32 gamemap; } saveinfo_t; -extern description_t description[MAXSKINS]; +extern description_t *description; +extern INT32 numdescriptions; extern consvar_t cv_showfocuslost; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; diff --git a/src/p_saveg.c b/src/p_saveg.c index 03229e740..80bdfa09e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -139,7 +139,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].skincolor); WRITEINT32(save_p, players[i].skin); - WRITEUINT32(save_p, players[i].availabilities); + WRITEMEM(save_p, players[i].availabilities, sizeof(bitarray_t) * numskins); WRITEUINT32(save_p, players[i].score); WRITEFIXED(save_p, players[i].dashspeed); WRITESINT8(save_p, players[i].lives); @@ -353,7 +353,7 @@ static void P_NetUnArchivePlayers(void) players[i].skincolor = READUINT8(save_p); players[i].skin = READINT32(save_p); - players[i].availabilities = READUINT32(save_p); + READMEM(save_p, players[i].availabilities, sizeof(bitarray_t) * numskins); players[i].score = READUINT32(save_p); players[i].dashspeed = READFIXED(save_p); // dashing speed players[i].lives = READSINT8(save_p); diff --git a/src/r_picformats.c b/src/r_picformats.c index f87362c76..ff2b9f15a 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2018-2021 by Jaime "Lactozilla" Passos. // Copyright (C) 2019-2020 by Sonic Team Junior. // // This program is free software distributed under the @@ -1494,7 +1494,7 @@ static void R_ParseSpriteInfo(boolean spr2) spritenum_t sprnum = NUMSPRITES; playersprite_t spr2num = NUMPLAYERSPRITES; INT32 i; - INT32 skinnumbers[MAXSKINS]; + INT32 *skinnumbers = NULL; INT32 foundskins = 0; // Sprite name @@ -1592,6 +1592,8 @@ static void R_ParseSpriteInfo(boolean spr2) if (skinnum == -1) I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + if (skinnumbers == NULL) + skinnumbers = Z_Malloc(sizeof(INT32) * numskins, PU_STATIC, NULL); skinnumbers[foundskins] = skinnum; foundskins++; } @@ -1630,8 +1632,11 @@ static void R_ParseSpriteInfo(boolean spr2) { I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); } + Z_Free(sprinfoToken); Z_Free(info); + if (skinnumbers) + Z_Free(skinnumbers); } // diff --git a/src/r_skins.c b/src/r_skins.c index 6f150f234..bfbc3e18f 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -18,6 +18,7 @@ #include "st_stuff.h" #include "w_wad.h" #include "z_zone.h" +#include "m_menu.h" #include "m_misc.h" #include "info.h" // spr2names #include "i_video.h" // rendermode @@ -32,13 +33,7 @@ #endif INT32 numskins = 0; -skin_t skins[MAXSKINS]; - -// FIXTHIS: don't work because it must be inistilised before the config load -//#define SKINVALUES -#ifdef SKINVALUES -CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; -#endif +skin_t *skins = NULL; // // P_GetSkinSprite2 @@ -160,30 +155,37 @@ static void Sk_SetDefaultValue(skin_t *skin) // void R_InitSkins(void) { -#ifdef SKINVALUES - INT32 i; - - for (i = 0; i <= MAXSKINS; i++) - { - skin_cons_t[i].value = 0; - skin_cons_t[i].strvalue = NULL; - } -#endif - // no default skin! numskins = 0; } -UINT32 R_GetSkinAvailabilities(void) +void R_GetSkinAvailabilities(bitarray_t **response) +{ + INT32 s; + + if (*response == NULL) + (*response) = Z_Calloc(sizeof(bitarray_t) * numskins, PU_STATIC, NULL); + + for (s = 0; s < numskins; s++) + { + if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) + set_bit_array((*response), s); + else + unset_bit_array((*response), s); + } +} + +UINT32 R_GetAvailabilitiesBits(bitarray_t *availabilities) { INT32 s; UINT32 response = 0; - for (s = 0; s < MAXSKINS; s++) + for (s = 0; s < min(numskins, 32); s++) { - if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) + if (in_bit_array(availabilities, s)) response |= (1 << s); } + return response; } @@ -193,7 +195,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... || (!skins[skinnum].availability) - || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) + || (((netgame || multiplayer) && playernum != -1) ? (in_bit_array(players[playernum].availabilities, skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. @@ -594,6 +596,7 @@ void R_AddSkins(UINT16 wadnum) buf2[size] = '\0'; // set defaults + skins = Z_Realloc(skins, sizeof(skin_t) * (numskins + 1), PU_STATIC, NULL); skin = &skins[numskins]; Sk_SetDefaultValue(skin); skin->wadnum = wadnum; @@ -695,17 +698,13 @@ next_token: if (!skin->availability) // Safe to print... CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); -#ifdef SKINVALUES - skin_cons_t[numskins].value = numskins; - skin_cons_t[numskins].strvalue = skin->name; -#endif + + numskins++; #ifdef HWRENDER if (rendermode == render_opengl) - HWR_AddPlayerModel(numskins); + HWR_AddPlayerModel(numskins-1); #endif - - numskins++; } return; } diff --git a/src/r_skins.h b/src/r_skins.h index fbbb38743..f2e76afcb 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -86,7 +86,7 @@ typedef struct /// Externs extern INT32 numskins; -extern skin_t skins[MAXSKINS]; +extern skin_t *skins; /// Function prototypes void R_InitSkins(void); @@ -94,7 +94,8 @@ void R_InitSkins(void); 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); +void R_GetSkinAvailabilities(bitarray_t **response); +UINT32 R_GetAvailabilitiesBits(bitarray_t *availabilities); INT32 R_SkinAvailable(const char *name); void R_PatchSkins(UINT16 wadnum); void R_AddSkins(UINT16 wadnum); diff --git a/src/sounds.h b/src/sounds.h index e49dd2f3e..7a2e3bc25 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -43,7 +43,7 @@ typedef enum // free sfx for S_AddSoundFx() #define NUMSFXFREESLOTS 1600 // Matches SOC Editor. -#define NUMSKINSFXSLOTS (MAXSKINS*NUMSKINSOUNDS) +#define NUMSKINSFXSLOTS (128*NUMSKINSOUNDS) // // SoundFX struct. @@ -874,7 +874,7 @@ typedef enum // free slots for S_AddSoundFx() at run-time -------------------- sfx_freeslot0, // - // ... 60 free sounds here ... + // ... 1600 free sounds here ... // sfx_lastfreeslot = sfx_freeslot0 + NUMSFXFREESLOTS-1, // end of freeslots --------------------------------------------- diff --git a/src/st_stuff.c b/src/st_stuff.c index a1fbbec03..cd4582f6d 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -50,8 +50,8 @@ UINT16 objectsdrawn = 0; // STATUS BAR DATA // -patch_t *faceprefix[MAXSKINS]; // face status patches -patch_t *superprefix[MAXSKINS]; // super face status patches +patch_t **faceprefix; // face status patches +patch_t **superprefix; // super face status patches // ------------------------------------------ // status bar overlay @@ -368,6 +368,17 @@ void ST_ReloadSkinFaceGraphics(void) { INT32 i; + if (faceprefix) + Z_Free(faceprefix); + if (superprefix) + Z_Free(superprefix); + + if (!numskins) + return; + + faceprefix = Z_Malloc(sizeof(patch_t *) * numskins, PU_STATIC, NULL); + superprefix = Z_Malloc(sizeof(patch_t *) * numskins, PU_STATIC, NULL); + for (i = 0; i < numskins; i++) ST_LoadFaceGraphics(i); } diff --git a/src/st_stuff.h b/src/st_stuff.h index 4ea307d2b..c31651cd5 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -42,7 +42,7 @@ void ST_UnloadGraphics(void); void ST_LoadGraphics(void); // face load graphics, called when skin changes -void ST_LoadFaceGraphics(INT32 playernum); +void ST_LoadFaceGraphics(INT32 skinnum); void ST_ReloadSkinFaceGraphics(void); void ST_doPaletteStuff(void); @@ -76,8 +76,8 @@ extern patch_t *sboscore; extern patch_t *sbotime; extern patch_t *sbocolon; extern patch_t *sboperiod; -extern patch_t *faceprefix[MAXSKINS]; // face status patches -extern patch_t *superprefix[MAXSKINS]; // super face status patches +extern patch_t **faceprefix; // face status patches +extern patch_t **superprefix; // super face status patches extern patch_t *livesback; extern patch_t *stlivex; extern patch_t *ngradeletters[7];