diff --git a/src/command.c b/src/command.c index d41a55153..5f6b1c21c 100644 --- a/src/command.c +++ b/src/command.c @@ -2056,7 +2056,7 @@ static void CV_SetValueMaybeStealth(consvar_t *var, INT32 value, boolean stealth if ((value < 0) || (value >= numskins)) tmpskin = "None"; else - tmpskin = skins[value].name; + tmpskin = skins[value]->name; strncpy(val, tmpskin, SKINNAMESIZE); } else diff --git a/src/d_main.c b/src/d_main.c index bc821cf71..a07f4a512 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1429,10 +1429,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_player.h b/src/d_player.h index 1409e28b3..62383f53a 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -451,10 +451,10 @@ typedef struct player_s UINT16 flashcount; UINT16 flashpal; - // Player skin colorshift, 0-15 for which color to draw player. + // Player skin colorshift, which color to draw player. UINT16 skincolor; - INT32 skin; + UINT8 skin; UINT32 availabilities; UINT32 score; // player score (total) diff --git a/src/deh_soc.c b/src/deh_soc.c index 6162034de..41eb28a90 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -188,25 +188,22 @@ void clear_levels(void) P_AllocMapHeader(gamemap-1); } -static boolean findFreeSlot(INT32 *num) +static boolean findCharacterSlot(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); } @@ -217,30 +214,43 @@ void readPlayer(MYFILE *f, INT32 num) char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word; char *word2; - char *displayname = ZZ_Alloc(MAXLINELEN+1); - INT32 i; boolean slotfound = false; + boolean failure = false; + INT32 i; + + if (num < 0 || num >= MAXCHARACTERSLOTS) + { + deh_warning("Character %d out of range (0 - %d)", num, MAXCHARACTERSLOTS-1); + failure = true; + } + + #define FINDSLOT \ + if (!failure && !slotfound && (slotfound = findCharacterSlot(&num)) == false) { \ + failure = true; \ + deh_warning("Too many characters, ignoring"); \ + } #define SLOTFOUND \ - if (!slotfound && (slotfound = findFreeSlot(&num)) == false) \ - goto done; - - displayname[MAXLINELEN] = '\0'; + FINDSLOT \ + if (failure) \ + continue; do { if (myfgets(s, MAXLINELEN, f)) { + char stringvalue[MAXLINELEN]; + if (s[0] == '\n') break; - for (i = 0; i < MAXLINELEN-3; i++) + stringvalue[0] = '\0'; + + for (i = 0; i < MAXLINELEN-3 && !failure; i++) { - char *tmp; if (s[i] == '=') { - tmp = &s[i+2]; - strncpy(displayname, tmp, SKINNAMESIZE); + strlcpy(stringvalue, &s[i+2], sizeof stringvalue); break; } } @@ -255,7 +265,13 @@ void readPlayer(MYFILE *f, INT32 num) { char *playertext = NULL; - SLOTFOUND + FINDSLOT + + if (failure) + { + ignorelinesuntilhash(f); + continue; + } // A friendly neighborhood alias for brevity's sake #define NOTE_SIZE sizeof(description[num].notes) @@ -275,7 +291,7 @@ void readPlayer(MYFILE *f, INT32 num) myhashfgets(playertext, NOTE_SIZE, f), NOTE_SIZE); } else - strcpy(description[num].notes, ""); + description[num].notes[0] = '\0'; // For some reason, cutting the string did not work above. Most likely due to strcpy or strcat... // It works down here, though. @@ -304,37 +320,32 @@ void readPlayer(MYFILE *f, INT32 num) if (word2[strlen(word2)-1] == '\n') word2[strlen(word2)-1] = '\0'; - i = atoi(word2); if (fastcmp(word, "PICNAME")) { SLOTFOUND strncpy(description[num].picname, word2, 8); } - // new character select else if (fastcmp(word, "DISPLAYNAME")) { + char *cur = NULL; + SLOTFOUND - // replace '#' with line breaks - // (also remove any '\n') + + // Remove any line breaks + cur = strchr(stringvalue, '\n'); + if (cur) + *cur = '\0'; + + // Turn '#' into line breaks + cur = strchr(stringvalue, '#'); + while (cur) { - char *cur = NULL; - - // remove '\n' - cur = strchr(displayname, '\n'); - if (cur) - *cur = '\0'; - - // turn '#' into '\n' - cur = strchr(displayname, '#'); - while (cur) - { - *cur = '\n'; - cur = strchr(cur, '#'); - } + *cur = '\n'; + cur = strchr(cur, '#'); } - // copy final string - strncpy(description[num].displayname, displayname, SKINNAMESIZE); + + strlcpy(description[num].displayname, stringvalue, sizeof description[num].displayname); } else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR")) { @@ -365,10 +376,12 @@ void readPlayer(MYFILE *f, INT32 num) Because of this, you are allowed to edit any previous entries you like, but only if you signal that you are purposely doing so by disabling and then reenabling the slot. */ - if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false) - goto done; + i = atoi(word2); + if (i && !slotfound && (slotfound = findCharacterSlot(&num)) == false) + failure = true; - description[num].used = (!!i); + if (!failure) + description[num].used = (!!i); } else if (fastcmp(word, "SKINNAME")) { @@ -377,13 +390,12 @@ void readPlayer(MYFILE *f, INT32 num) strlcpy(description[num].skinname, word2, sizeof description[num].skinname); strlwr(description[num].skinname); } - else + else if (!failure) deh_warning("readPlayer %d: unknown word '%s'", num, word); } } while (!myfeof(f)); // finish when the line is empty + #undef FINDSLOT #undef SLOTFOUND -done: - Z_Free(displayname); Z_Free(s); } @@ -933,7 +945,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) INT32 value; #endif char *lastline; - INT32 skinnumbers[MAXSKINS]; + UINT8 *skinnumbers = NULL; INT32 foundskins = 0; // allocate a spriteinfo @@ -1022,7 +1034,9 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) break; } - skinnumbers[foundskins] = skinnum; + if (skinnumbers == NULL) + skinnumbers = Z_Malloc(sizeof(UINT8) * numskins, PU_STATIC, NULL); + skinnumbers[foundskins] = (UINT8)skinnum; foundskins++; } else if (fastcmp(word, "DEFAULT")) @@ -1065,8 +1079,7 @@ void readspriteinfo(MYFILE *f, INT32 num, boolean sprite2) } for (i = 0; i < foundskins; i++) { - size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; + skin_t *skin = skins[skinnumbers[i]]; spriteinfo_t *sprinfo = skin->sprinfo; M_Memcpy(&sprinfo[num], info, sizeof(spriteinfo_t)); } @@ -1085,6 +1098,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) @@ -1130,7 +1145,6 @@ void readsprite2(MYFILE *f, INT32 num) Z_Free(s); } -// copypasted from readPlayer :] void readgametype(MYFILE *f, char *gtname) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); diff --git a/src/dehacked.c b/src/dehacked.c index fd2a70171..2050a117f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -169,6 +169,20 @@ static void ignorelines(MYFILE *f) Z_Free(s); } +void ignorelinesuntilhash(MYFILE *f) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '#') + break; + } + } while (!myfeof(f)); + Z_Free(s); +} + static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -226,13 +240,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) i = 0; if (fastcmp(word, "CHARACTER")) { - if (i >= 0 && i < 32) - readPlayer(f, i); - else - { - deh_warning("Character %d out of range (0 - 31)", i); - ignorelines(f); - } + readPlayer(f, i); continue; } else if (fastcmp(word, "EMBLEM")) diff --git a/src/dehacked.h b/src/dehacked.h index b39f09035..d985b14b0 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -61,4 +61,5 @@ typedef struct #define myfeof(a) (a->data + a->size <= a->curpos) char *myfgets(char *buf, size_t bufsize, MYFILE *f); char *myhashfgets(char *buf, size_t bufsize, MYFILE *f); +void ignorelinesuntilhash(MYFILE *f); #endif diff --git a/src/doomdef.h b/src/doomdef.h index 4e08b11bf..29cd4852f 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -233,9 +233,16 @@ extern char logfilename[1024]; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 32 -#define MAXSKINS 32 -#define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 +#define PLAYERSMASK (MAXPLAYERS-1) + +// Don't make MAXSKINS higher than 256, since skin numbers are used with an +// UINT8 in various parts of the codebase. If you do anyway, the data type +// of those variables will have to be changed into at least an UINT16. +// This change must affect code such as demo recording and playback, +// and the structure of some networking packets and commands. +#define MAXSKINS 256 +#define MAXCHARACTERSLOTS (MAXSKINS * 3) // Should be higher than MAXSKINS. #define COLORRAMPSIZE 16 #define MAXCOLORNAME 32 diff --git a/src/f_finale.c b/src/f_finale.c index 5dc18115c..cb6461853 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1603,9 +1603,9 @@ void F_GameEvaluationDrawer(void) rtatext = (marathonmode & MA_INGAME) ? "In-game timer" : "RTA timer"; cuttext = (marathonmode & MA_NOCUTSCENES) ? "" : " w/ cutscenes"; if (botskin) - endingtext = va("%s & %s, %s%s", skins[players[consoleplayer].skin].realname, skins[botskin-1].realname, rtatext, cuttext); + endingtext = va("%s & %s, %s%s", skins[players[consoleplayer].skin]->realname, skins[botskin-1]->realname, rtatext, cuttext); else - endingtext = va("%s, %s%s", skins[players[consoleplayer].skin].realname, rtatext, cuttext); + endingtext = va("%s, %s%s", skins[players[consoleplayer].skin]->realname, rtatext, cuttext); V_DrawCenteredString(BASEVIDWIDTH/2, 182, V_SNAPTOBOTTOM|(ultimatemode ? V_REDMAP : V_YELLOWMAP), endingtext); } } @@ -1719,9 +1719,9 @@ static void F_CacheEnding(void) UINT8 skinnum = players[consoleplayer].skin; spritedef_t *sprdef; spriteframe_t *sprframe; - if (skins[skinnum].sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2)) + if (skins[skinnum]->sprites[SPR2_XTRA].numframes > (XTRA_ENDING+2)) { - sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; // character head, skin specific sprframe = &sprdef->spriteframes[XTRA_ENDING]; endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH_LOWPRIORITY); @@ -2167,7 +2167,7 @@ void F_EndingDrawer(void) boolean donttouch = false; const char *str; if (goodending) - str = va("[S] %s: Engage.", skins[players[consoleplayer].skin].realname); + str = va("[S] %s: Engage.", skins[players[consoleplayer].skin]->realname); else str = "[S] Eggman: Abscond."; @@ -3554,7 +3554,7 @@ void F_StartContinue(void) S_ChangeMusicInternal("_conti", false); S_StopSounds(); - contskins[0] = &skins[players[consoleplayer].skin]; + contskins[0] = skins[players[consoleplayer].skin]; cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL); cont_spr2[0][2] = contskins[0]->contangle & 7; contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE); @@ -3570,7 +3570,7 @@ void F_StartContinue(void) else // HACK secondplaya = 1; - contskins[1] = &skins[players[secondplaya].skin]; + contskins[1] = skins[players[secondplaya].skin]; cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL); cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7; contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE); diff --git a/src/g_demo.c b/src/g_demo.c index 8a8ad1259..65fc90868 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -492,7 +492,7 @@ void G_WriteGhostTic(mobj_t *ghost) if (ghost->player->followmobj->colorized) followtic |= FZT_COLORIZED; if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins)); + WRITEUINT8(demo_p,(UINT8)(((skin_t *)ghost->player->followmobj->skin)->skinnum)); oldghost.flags2 |= MF2_AMBUSH; } @@ -761,7 +761,7 @@ void G_GhostTicker(void) g->mo->color = SKINCOLOR_WHITE; break; case GHC_NIGHTSSKIN: // not actually a colour - g->mo->skin = &skins[DEFAULTNIGHTSSKIN]; + g->mo->skin = skins[DEFAULTNIGHTSSKIN]; break; } } @@ -1387,7 +1387,7 @@ void G_WriteMetalTic(mobj_t *metal) if (metal->player->followmobj->colorized) followtic |= FZT_COLORIZED; if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins)); + WRITEUINT8(demo_p,(UINT8)(((skin_t *)metal->player->followmobj->skin)->skinnum)); oldmetal.flags2 |= MF2_AMBUSH; } @@ -1540,7 +1540,7 @@ void G_BeginRecording(void) demo_p += 16; // Skin - const char *skinname = skins[players[0].skin].name; + const char *skinname = skins[players[0].skin]->name; for (i = 0; i < 16 && skinname[i]; i++) name[i] = skinname[i]; for (; i < 16; i++) @@ -2289,7 +2289,7 @@ void G_DoPlayDemo(char *defdemoname) G_InitNew(false, G_BuildMapName(gamemap), true, true, false); // Set color - players[0].skincolor = skins[players[0].skin].prefcolor; + players[0].skincolor = skins[players[0].skin]->prefcolor; for (i = 0; i < numskincolors; i++) if (!stricmp(skincolors[i].name,color)) { @@ -2609,11 +2609,11 @@ void G_AddGhost(char *defdemoname) gh->oldmo.z = gh->mo->z; // Set skin - gh->mo->skin = &skins[0]; + gh->mo->skin = skins[0]; for (i = 0; i < numskins; i++) - if (!stricmp(skins[i].name,skin)) + if (!stricmp(skins[i]->name,skin)) { - gh->mo->skin = &skins[i]; + gh->mo->skin = skins[i]; break; } gh->oldmo.skin = gh->mo->skin; diff --git a/src/g_game.c b/src/g_game.c index 121672fa7..77d50b291 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -588,14 +588,14 @@ static void G_SetMainRecords(gamedata_t *data, player_t *player) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (FIL_FileExists(lastdemo)) { UINT8 *buf; size_t len = FIL_ReadFile(lastdemo, &buf); - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) { // Better time, save this demo. if (FIL_FileExists(bestdemo)) @@ -604,7 +604,7 @@ static void G_SetMainRecords(gamedata_t *data, player_t *player) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) { // Better score, save this demo. if (FIL_FileExists(bestdemo)) @@ -613,7 +613,7 @@ static void G_SetMainRecords(gamedata_t *data, player_t *player) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-rings-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<2))) { // Better rings, save this demo. if (FIL_FileExists(bestdemo)) @@ -726,14 +726,14 @@ static void G_SetNightsRecords(gamedata_t *data, player_t *player) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (FIL_FileExists(lastdemo)) { UINT8 *buf; size_t len = FIL_ReadFile(lastdemo, &buf); - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);; + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) { // Better time, save this demo. if (FIL_FileExists(bestdemo)) @@ -742,7 +742,7 @@ static void G_SetNightsRecords(gamedata_t *data, player_t *player) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name); + snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1]->name); if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) { // Better score, save this demo. if (FIL_FileExists(bestdemo)) @@ -2598,7 +2598,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) UINT8 laps; UINT8 mare; UINT16 skincolor; - INT32 skin; + UINT8 skin; UINT32 availabilities; tic_t jointime; tic_t quittime; @@ -5008,7 +5008,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, bo if (savedata.lives > 0) { if ((botingame = ((botskin = savedata.botskin) != 0))) - botcolor = skins[botskin-1].prefcolor; + botcolor = skins[botskin-1]->prefcolor; } else if (splitscreen != SSSG) { @@ -5138,7 +5138,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean players[consoleplayer].lives = savedata.lives; players[consoleplayer].score = savedata.score; if ((botingame = ((botskin = savedata.botskin) != 0))) - botcolor = skins[botskin-1].prefcolor; + botcolor = skins[botskin-1]->prefcolor; emeralds = savedata.emeralds; savedata.lives = 0; } diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c49375be1..9c44e0b37 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5011,7 +5011,7 @@ static void HWR_DrawSprites(void) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - if (!cv_glmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) + if (!cv_glmodels.value || !md2_playermodels[((skin_t*)spr->mobj->skin)->skinnum].found || md2_playermodels[((skin_t*)spr->mobj->skin)->skinnum].scale < 0.0f) HWR_DrawSprite(spr); else { @@ -5021,7 +5021,7 @@ static void HWR_DrawSprites(void) } else { - if (!cv_glmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + if (!cv_glmodels.value || !md2_models[spr->mobj->sprite].found || md2_models[spr->mobj->sprite].scale < 0.0f) HWR_DrawSprite(spr); else { @@ -5198,11 +5198,11 @@ static void HWR_ProjectSprite(mobj_t *thing) if (cv_glmodels.value) //Yellow: Only MD2's dont disappear { if (thing->skin && thing->sprite == SPR_PLAY) - md2 = &md2_playermodels[( (skin_t *)thing->skin - skins )]; + md2 = &md2_playermodels[((skin_t *)thing->skin)->skinnum]; else md2 = &md2_models[thing->sprite]; - if (md2->notfound || md2->scale < 0.0f) + if (!md2->found || md2->scale < 0.0f) return; } else @@ -5591,8 +5591,8 @@ static void HWR_ProjectSprite(mobj_t *thing) } else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { - size_t skinnum = (skin_t*)thing->skin-skins; - vis->colormap = R_GetTranslationColormap((INT32)skinnum, vis->color, GTC_CACHE); + UINT8 skinnum = ((skin_t*)thing->skin)->skinnum; + vis->colormap = R_GetTranslationColormap(skinnum, vis->color, GTC_CACHE); } else vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->color ? vis->color : SKINCOLOR_CYAN, GTC_CACHE); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 8bd784987..d097e1138 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -35,6 +35,7 @@ #include "../m_misc.h" #include "../w_wad.h" #include "../z_zone.h" +#include "../r_state.h" #include "../r_things.h" #include "../r_draw.h" #include "../p_tick.h" @@ -72,7 +73,8 @@ #endif md2_t md2_models[NUMSPRITES]; -md2_t md2_playermodels[MAXSKINS]; +md2_t *md2_playermodels = NULL; +size_t md2_numplayermodels = 0; /* @@ -488,24 +490,7 @@ static boolean nomd2s = false; void HWR_InitModels(void) { size_t i; - INT32 s; - FILE *f; - char name[26], filename[32]; - float scale, offset; - size_t prefixlen; - CONS_Printf("HWR_InitModels()...\n"); - for (s = 0; s < MAXSKINS; s++) - { - md2_playermodels[s].scale = -1.0f; - md2_playermodels[s].model = NULL; - md2_playermodels[s].grpatch = NULL; - md2_playermodels[s].notexturefile = false; - md2_playermodels[s].noblendfile = false; - md2_playermodels[s].skin = -1; - md2_playermodels[s].notfound = true; - md2_playermodels[s].error = false; - } for (i = 0; i < NUMSPRITES; i++) { md2_models[i].scale = -1.0f; @@ -513,11 +498,48 @@ void HWR_InitModels(void) md2_models[i].grpatch = NULL; md2_models[i].notexturefile = false; md2_models[i].noblendfile = false; - md2_models[i].skin = -1; - md2_models[i].notfound = true; + md2_models[i].found = false; md2_models[i].error = false; } + if (numsprites && numskins) + HWR_LoadModels(); +} + +void HWR_LoadModels(void) +{ + size_t i; + INT32 s; + FILE *f; + + char name[26], filename[32]; + // name[24] is used to check for names in the models.dat file that match with sprites or player skins + // sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long + // PLAYERMODELPREFIX is 6 characters long + float scale, offset; + size_t prefixlen; + + if (nomd2s) + return; + + // realloc player models table + if (numskins != (INT32)md2_numplayermodels) + { + md2_numplayermodels = (size_t)numskins; + md2_playermodels = Z_Realloc(md2_playermodels, sizeof(md2_t) * md2_numplayermodels, PU_STATIC, NULL); + + for (s = 0; s < numskins; s++) + { + md2_playermodels[s].scale = -1.0f; + md2_playermodels[s].model = NULL; + md2_playermodels[s].grpatch = NULL; + md2_playermodels[s].notexturefile = false; + md2_playermodels[s].noblendfile = false; + md2_playermodels[s].found = false; + md2_playermodels[s].error = false; + } + } + // read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); @@ -541,23 +563,24 @@ void HWR_InitModels(void) char *skinname = name; size_t len = strlen(name); - // check for the player model prefix. + // Check for the player model prefix. if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen)) { skinname += prefixlen; goto addskinmodel; } - // add sprite model - if (len == 4) // must be 4 characters long exactly. otherwise it's not a sprite name. + // Add sprite models. + // Must be 4 characters long exactly. Otherwise, it's not a sprite name. + if (len == 4) { - for (i = 0; i < NUMSPRITES; i++) + for (i = 0; i < numsprites; i++) { if (stricmp(name, sprnames[i]) == 0) { md2_models[i].scale = scale; md2_models[i].offset = offset; - md2_models[i].notfound = false; + md2_models[i].found = true; strcpy(md2_models[i].filename, filename); goto modelfound; } @@ -565,137 +588,24 @@ void HWR_InitModels(void) } addskinmodel: - // add player model - for (s = 0; s < MAXSKINS; s++) + // Add player models. + for (s = 0; s < numskins; s++) { - if (stricmp(skinname, skins[s].name) == 0) + if (stricmp(skinname, skins[s]->name) == 0) { - md2_playermodels[s].skin = s; md2_playermodels[s].scale = scale; md2_playermodels[s].offset = offset; - md2_playermodels[s].notfound = false; + md2_playermodels[s].found = true; strcpy(md2_playermodels[s].filename, filename); goto modelfound; } } modelfound: - // move on to next line... + // Move on to the next line... continue; } - fclose(f); -} -void HWR_AddPlayerModel(int skin) // For skins that were added after startup -{ - FILE *f; - char name[26], filename[32]; - float scale, offset; - size_t prefixlen; - - if (nomd2s) - return; - - //CONS_Printf("HWR_AddPlayerModel()...\n"); - - // read the models.dat file - //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); - - if (!f) - { - f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); - if (!f) - { - CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); - nomd2s = true; - return; - } - } - - // length of the player model prefix - prefixlen = strlen(PLAYERMODELPREFIX); - - // Check for any models that match the names of player skins! - while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) - { - char *skinname = name; - size_t len = strlen(name); - - // ignore the player model prefix. - if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen)) - skinname += prefixlen; - - if (stricmp(skinname, skins[skin].name) == 0) - { - md2_playermodels[skin].skin = skin; - md2_playermodels[skin].scale = scale; - md2_playermodels[skin].offset = offset; - md2_playermodels[skin].notfound = false; - strcpy(md2_playermodels[skin].filename, filename); - goto playermodelfound; - } - } - - md2_playermodels[skin].notfound = true; -playermodelfound: - fclose(f); -} - -void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after startup -{ - FILE *f; - // name[24] is used to check for names in the models.dat file that match with sprites or player skins - // sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long - // PLAYERMODELPREFIX is 6 characters long - char name[26], filename[32]; - float scale, offset; - - if (nomd2s) - return; - - if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check - return; - - // Read the models.dat file - //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); - - if (!f) - { - f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); - if (!f) - { - CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); - nomd2s = true; - return; - } - } - - // Check for any models that match the names of sprite names! - while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) - { - // length of the sprite name - size_t len = strlen(name); - if (len != 4) // must be 4 characters long exactly. otherwise it's not a sprite name. - continue; - - // check for the player model prefix. - if (!strnicmp(name, PLAYERMODELPREFIX, strlen(PLAYERMODELPREFIX))) - continue; // that's not a sprite... - - if (stricmp(name, sprnames[spritenum]) == 0) - { - md2_models[spritenum].scale = scale; - md2_models[spritenum].offset = offset; - md2_models[spritenum].notfound = false; - strcpy(md2_models[spritenum].filename, filename); - goto spritemodelfound; - } - } - - md2_models[spritenum].notfound = true; -spritemodelfound: fclose(f); } @@ -1384,8 +1294,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) // 2. draw model with correct position, rotation,... if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) // Use the player MD2 list if the mobj has a skin and is using the player sprites { - md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; - md2->skin = (skin_t*)spr->mobj->skin-skins; + UINT8 skinnum = ((skin_t*)spr->mobj->skin)->skinnum; + md2 = &md2_playermodels[skinnum]; } else { @@ -1480,7 +1390,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) skinnum = TC_RAINBOW; } else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); + skinnum = ((skin_t*)spr->mobj->skin)->skinnum; else skinnum = TC_DEFAULT; } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index f1cca763c..473f21cb7 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -31,17 +31,17 @@ typedef struct boolean notexturefile; // true if texture file was not found void *blendgrpatch; boolean noblendfile; // true if blend texture file was not found - boolean notfound; - INT32 skin; + boolean found; boolean error; } md2_t; extern md2_t md2_models[NUMSPRITES]; -extern md2_t md2_playermodels[MAXSKINS]; +extern md2_t *md2_playermodels; +extern size_t md2_numplayermodels; void HWR_InitModels(void); -void HWR_AddPlayerModel(INT32 skin); -void HWR_AddSpriteModel(size_t spritenum); +void HWR_LoadModels(void); + boolean HWR_DrawModel(gl_vissprite_t *spr); #define PLAYERMODELPREFIX "PLAYER" diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index fed81e411..ce8eb35f3 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -328,8 +328,8 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) texcoords = (md2texcoord_t*)&buffer[header->offsetST]; frames = (md2frame_t*)&buffer[header->offsetFrames]; - retModel->framenames = (char*)Z_Calloc(header->numFrames*16, ztag, 0); - fname = retModel->framenames; + retModel->frameNames = (char*)Z_Calloc(header->numFrames*16, ztag, 0); + fname = retModel->frameNames; for (i = 0; i < header->numFrames; i++) { md2frame_t *fr = (md2frame_t*)&buffer[header->offsetFrames + foffset]; diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index 87931d27b..eccc48424 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -230,8 +230,8 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0); frames = (md3Frame*)&buffer[mdh->offsetFrames]; - retModel->framenames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0); - fname = retModel->framenames; + retModel->frameNames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0); + fname = retModel->frameNames; for (i = 0; i < mdh->numFrames; i++) { memcpy(fname, frames->name, 16); diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 4b6bce6f7..0d656f35a 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -10,6 +10,8 @@ #include "../doomdef.h" #include "../doomtype.h" #include "../info.h" +#include "../r_skins.h" +#include "../r_state.h" #include "../z_zone.h" #include "hw_model.h" #include "hw_md2load.h" @@ -141,9 +143,7 @@ tag_t *GetTagByName(model_t *model, char *name, int frame) // // LoadModel // -// Load a model and -// convert it to the -// internal format. +// Load a model and convert it to the internal format. // model_t *LoadModel(const char *filename, int ztag) { @@ -193,9 +193,6 @@ model_t *LoadModel(const char *filename, int ztag) return NULL; } - model->mdlFilename = (char*)Z_Malloc(strlen(filename)+1, ztag, 0); - strcpy(model->mdlFilename, filename); - Optimize(model); GeneratePolygonNormals(model, ztag); LoadModelSprite2(model); @@ -236,15 +233,16 @@ model_t *LoadModel(const char *filename, int ztag) void HWR_ReloadModels(void) { size_t i; - INT32 s; - for (s = 0; s < MAXSKINS; s++) + HWR_LoadModels(); + + for (i = 0; i < md2_numplayermodels; i++) { - if (md2_playermodels[s].model) - LoadModelSprite2(md2_playermodels[s].model); + if (md2_playermodels[i].model) + LoadModelSprite2(md2_playermodels[i].model); } - for (i = 0; i < NUMSPRITES; i++) + for (i = 0; i < numsprites; i++) { if (md2_models[i].model) LoadModelInterpolationSettings(md2_models[i].model); @@ -255,7 +253,7 @@ void LoadModelInterpolationSettings(model_t *model) { INT32 i; INT32 numframes = model->meshes[0].numFrames; - char *framename = model->framenames; + char *framename = model->frameNames; if (!framename) return; @@ -295,7 +293,7 @@ void LoadModelSprite2(model_t *model) INT32 i; modelspr2frames_t *spr2frames = NULL; INT32 numframes = model->meshes[0].numFrames; - char *framename = model->framenames; + char *framename = model->frameNames; if (!framename) return; diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index 6b39eb24d..f057271df 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -91,17 +91,14 @@ typedef struct model_s { int maxNumFrames; - int numMaterials; - material_t *materials; int numMeshes; mesh_t *meshes; + int numMaterials; + material_t *materials; int numTags; tag_t *tags; - char *mdlFilename; - boolean unloaded; - - char *framenames; + char *frameNames; boolean interpolate[256]; modelspr2frames_t *spr2frames; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 0a2b71aec..4200e85ed 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2116,7 +2116,7 @@ void HU_Erase(void) // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== -#define supercheckdef (!(players[tab[i].num].charflags & SF_NOSUPERSPRITES) && ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER))) +#define supercheckdef (!(players[tab[i].num].charflags & SF_NOSUPERSPRITES) && ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin]->flags & SF_SUPER))) #define greycheckdef (players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD || (G_IsSpecialStage(gamemap) && players[tab[i].num].exiting)) // diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 8b23eb87b..85f4f63c5 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3764,10 +3764,10 @@ static int lib_gAddPlayer(lua_State *L) if (!lua_isnoneornil(L, 2)) newplayer->skincolor = R_GetColorByName(luaL_checkstring(L, 2)); else - newplayer->skincolor = skins[skinnum].prefcolor; + newplayer->skincolor = skins[skinnum]->prefcolor; // Set the bot default name as the skin - strcpy(player_names[newplayernum], skins[skinnum].realname); + strcpy(player_names[newplayernum], skins[skinnum]->realname); // Read the bot name, if given if (!lua_isnoneornil(L, 3)) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 2e6721a3a..eaa8301f9 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -557,7 +557,7 @@ static int libd_getSprite2Patch(lua_State *L) { const char *name = luaL_checkstring(L, 1); for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, name)) + if (fastcmp(skins[i]->name, name)) break; if (i >= numskins) return 0; @@ -599,9 +599,9 @@ static int libd_getSprite2Patch(lua_State *L) if (super) j |= FF_SPR2SUPER; - j = P_GetSkinSprite2(&skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary + j = P_GetSkinSprite2(skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary - sprdef = &skins[i].sprites[j]; + sprdef = &skins[i]->sprites[j]; // set frame number frame = luaL_optinteger(L, 2, 0); @@ -629,7 +629,7 @@ static int libd_getSprite2Patch(lua_State *L) INT32 rot = R_GetRollAngle(rollangle); if (rot) { - patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i].sprinfo[j], rot); + patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i]->sprinfo[j], rot); LUA_PushUserdata(L, rotsprite, META_PATCH); lua_pushboolean(L, false); lua_pushboolean(L, true); diff --git a/src/lua_infolib.c b/src/lua_infolib.c index ed78811ce..03888f32e 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -30,9 +30,6 @@ #include "lua_hud.h" // hud_running errors #include "lua_hook.h" // hook_cmd_running errors -extern CV_PossibleValue_t Color_cons_t[]; -extern UINT8 skincolor_modified[]; - boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor); state_t *astate; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index d38e85a21..b5c6c0329 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -679,10 +679,10 @@ static int mobj_set(lua_State *L) strlcpy(skin, luaL_checkstring(L, 3), sizeof skin); strlwr(skin); // all skin names are lowercase for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, skin)) + if (fastcmp(skins[i]->name, skin)) { if (!mo->player || R_SkinUsable(mo->player-players, i)) - mo->skin = &skins[i]; + mo->skin = skins[i]; return 0; } return luaL_error(L, "mobj.skin '%s' not found!", skin); diff --git a/src/lua_script.c b/src/lua_script.c index f90db7bc3..72e5a3f45 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1396,7 +1396,7 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex)); WRITEUINT8(save_p, ARCH_SKIN); - WRITEUINT8(save_p, skin - skins); // UINT8 because MAXSKINS is only 32 + WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256 break; } default: diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 3debd3746..4ede33f10 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -234,7 +234,7 @@ static int skin_num(lua_State *L) // skins are always valid, only added, never removed I_Assert(skin != NULL); - lua_pushinteger(L, skin-skins); + lua_pushinteger(L, skin->skinnum); return 1; } @@ -253,14 +253,14 @@ static int lib_iterateSkins(lua_State *L) lua_remove(L, 1); // state is unused. if (!lua_isnil(L, 1)) - i = (INT32)(*((skin_t **)luaL_checkudata(L, 1, META_SKIN)) - skins) + 1; + i = (INT32)((*((skin_t **)luaL_checkudata(L, 1, META_SKIN)))->skinnum) + 1; else i = 0; // skins are always valid, only added, never removed if (i < numskins) { - LUA_PushUserdata(L, &skins[i], META_SKIN); + LUA_PushUserdata(L, skins[i], META_SKIN); return 1; } @@ -280,7 +280,7 @@ static int lib_getSkin(lua_State *L) return luaL_error(L, "skins[] index %d out of range (0 - %d)", i, MAXSKINS-1); if (i >= numskins) return 0; - LUA_PushUserdata(L, &skins[i], META_SKIN); + LUA_PushUserdata(L, skins[i], META_SKIN); return 1; } @@ -295,9 +295,9 @@ static int lib_getSkin(lua_State *L) // find skin by name for (i = 0; i < numskins; i++) - if (fastcmp(skins[i].name, field)) + if (fastcmp(skins[i]->name, field)) { - LUA_PushUserdata(L, &skins[i], META_SKIN); + LUA_PushUserdata(L, skins[i], META_SKIN); return 1; } diff --git a/src/m_menu.c b/src/m_menu.c index c23839391..3ef1e196c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -132,7 +132,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; @@ -258,7 +260,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; @@ -2259,7 +2261,7 @@ void Nextmap_OnChange(void) SP_NightsAttackMenu[naghost].status = IT_DISABLED; // Check if file exists, if not, disable REPLAY option - sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name); + sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name); #ifdef OLDNREPLAYNAME sprintf(tabaseold,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); @@ -2330,7 +2332,7 @@ void Nextmap_OnChange(void) SP_TimeAttackMenu[taghost].status = IT_DISABLED; // Check if file exists, if not, disable REPLAY option - sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name); + sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name); for (i = 0; i < 5; i++) { SP_ReplayMenu[i].status = IT_DISABLED; SP_GuestReplayMenu[i].status = IT_DISABLED; @@ -3030,7 +3032,7 @@ static void M_ChangeCvar(INT32 choice) { SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); if (skinno != -1) - CV_SetValue(cv,skins[skinno].prefcolor); + CV_SetValue(cv,skins[skinno]->prefcolor); return; } CV_Set(cv,cv->defaultvalue); @@ -3937,24 +3939,32 @@ void M_Init(void) CV_RegisterVar(&cv_serversort); } -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); } // ========================================================================== @@ -5015,9 +5025,9 @@ 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].strvalue = skins[j]->realname; skins_cons_t[j].value = j+1; } else @@ -8493,7 +8503,7 @@ static void M_DrawLoadGameData(void) savetodraw--; if (savegameinfo[savetodraw].lives != 0) - charskin = &skins[savegameinfo[savetodraw].skinnum]; + charskin = skins[savegameinfo[savetodraw].skinnum]; // signpost background { @@ -8627,7 +8637,7 @@ static void M_DrawLoadGameData(void) // botskin first if (savegameinfo[savetodraw].botskin) { - skin_t *charbotskin = &skins[savegameinfo[savetodraw].botskin-1]; + skin_t *charbotskin = skins[savegameinfo[savetodraw].botskin-1]; sprdef = &charbotskin->sprites[SPR2_SIGN]; if (!sprdef->numframes) goto skipbot; @@ -9206,9 +9216,9 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) { if (!(description[i].picname[0])) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) + if (skins[skinnum]->sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; description[i].charpic = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); } @@ -9222,71 +9232,74 @@ 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, botskinnum; - UINT8 i; - UINT8 firstvalid = 255, lastvalid = 255; + UINT16 i; + INT32 firstvalid = INT32_MAX, lastvalid = INT32_MAX; 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); + } + 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))) + { + botskinnum = description[i].skinnum[1]; + if ((botskinnum != -1) && (!R_SkinUsable(-1, botskinnum))) { - 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); + // Bot skin isn't unlocked + continue; } + + // Handling order. + if (firstvalid == INT32_MAX) + 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))) - { - botskinnum = description[i].skinnum[1]; - if ((botskinnum != -1) && (!R_SkinUsable(-1, botskinnum))) - { - // Bot skin isn't unlocked - continue; - } + lastvalid = i; - // Handling order. - if (firstvalid == 255) - firstvalid = i; - else - { - description[i].prev = lastvalid; - description[lastvalid].next = 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; @@ -9295,7 +9308,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--) @@ -9303,13 +9316,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; @@ -9420,7 +9433,7 @@ static void M_DrawSetupChoosePlayerMenu(void) { const INT32 my = 16; - skin_t *charskin = &skins[0]; + skin_t *charskin = skins[0]; INT32 skinnum = 0; UINT16 col; UINT8 *colormap = NULL; @@ -9452,7 +9465,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Find skin number from description[] skinnum = description[char_on].skinnum[0]; - charskin = &skins[skinnum]; + charskin = skins[skinnum]; // Use the opposite of the character's skincolor col = description[char_on].oppositecolor; @@ -9555,7 +9568,7 @@ static void M_DrawSetupChoosePlayerMenu(void) prevoutlinecolor = description[prev].tagoutlinecolor; if (prevtext[0] == '\0') prevpatch = description[prev].namepic; - charskin = &skins[description[prev].skinnum[0]]; + charskin = skins[description[prev].skinnum[0]]; if (!prevtextcolor) prevtextcolor = charskin->prefcolor; if (!prevoutlinecolor) @@ -9585,7 +9598,7 @@ static void M_DrawSetupChoosePlayerMenu(void) nextoutlinecolor = description[next].tagoutlinecolor; if (nexttext[0] == '\0') nextpatch = description[next].namepic; - charskin = &skins[description[next].skinnum[0]]; + charskin = skins[description[next].skinnum[0]]; if (!nexttextcolor) nexttextcolor = charskin->prefcolor; if (!nextoutlinecolor) @@ -9630,7 +9643,7 @@ static void M_ChoosePlayer(INT32 choice) UINT8 skinnum; // skip this if forcecharacter or no characters available - if (choice == 255) + if (choice == INT32_MAX) { skinnum = botskin = 0; botingame = false; @@ -9643,7 +9656,7 @@ static void M_ChoosePlayer(INT32 choice) if ((botingame = (description[choice].skinnum[1] != -1))) { // this character has a second skin botskin = (UINT8)(description[choice].skinnum[1]+1); - botcolor = skins[description[choice].skinnum[1]].prefcolor; + botcolor = skins[description[choice].skinnum[1]]->prefcolor; } else botskin = botcolor = 0; @@ -9931,7 +9944,7 @@ void M_DrawTimeAttackMenu(void) gamedata_t *data = clientGamedata; INT32 i, x, y, empatx, empaty, cursory = 0; UINT16 dispstatus; - patch_t *PictureOfUrFace; // my WHAT + patch_t *PictureOfUrFace; patch_t *empatch; M_SetMenuCurBackground("RECATKBG"); @@ -10000,9 +10013,9 @@ void M_DrawTimeAttackMenu(void) // Character face! { - if (skins[cv_chooseskin.value-1].sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) + if (skins[cv_chooseskin.value-1]->sprites[SPR2_XTRA].numframes > XTRA_CHARSEL) { - spritedef_t *sprdef = &skins[cv_chooseskin.value-1].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[cv_chooseskin.value-1]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CHARSEL]; PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); } @@ -10448,7 +10461,7 @@ static void M_ChooseNightsAttack(INT32 choice) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value)); - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1].name); + snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1]->name); if (!cv_autorecord.value) remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); @@ -10477,7 +10490,7 @@ static void M_ChooseTimeAttack(INT32 choice) I_Error("Out of memory for replay filepath\n"); sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value)); - snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1].name); + snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1]->name); if (!cv_autorecord.value) remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); @@ -10530,7 +10543,7 @@ static void M_ReplayTimeAttack(INT32 choice) if (choice != 4) { // srb2/replay/main/map01-sonic-time-best.lmp - snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which); + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name, which); } } else if (currentMenu == &SP_NightsReplayDef) @@ -10553,7 +10566,7 @@ static void M_ReplayTimeAttack(INT32 choice) if (choice != 3) { - snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which); + snprintf(ra_demoname, 1024, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name, which); #ifdef OLDNREPLAYNAME // Check for old style named NiGHTS replay if a new style replay doesn't exist. if (!FIL_FileExists(ra_demoname)) @@ -10640,7 +10653,7 @@ static void M_OverwriteGuest(const char *which) char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); UINT8 *buf; size_t len; - len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which), &buf); + len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1]->name, which), &buf); if (!len) { return; @@ -10782,7 +10795,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)) @@ -10806,7 +10819,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) { @@ -12249,11 +12262,11 @@ static void M_DrawSetupMultiPlayerMenu(void) // draw skin string V_DrawRightAlignedString(BASEVIDWIDTH - x, y, ((MP_PlayerSetupMenu[1].status & IT_TYPE) == IT_SPACE ? V_TRANSLUCENT : 0)|(itemOn == 1 ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE, - skins[setupm_fakeskin].realname); + skins[setupm_fakeskin]->realname); if (itemOn == 1 && (MP_PlayerSetupMenu[1].status & IT_TYPE) != IT_SPACE) { - V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skins[setupm_fakeskin].realname, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, + V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(skins[setupm_fakeskin]->realname, V_ALLOWLOWERCASE) - (skullAnimCounter/5), y, '\x1C' | V_YELLOWMAP, false); V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y, '\x1D' | V_YELLOWMAP, false); @@ -12276,7 +12289,7 @@ static void M_DrawSetupMultiPlayerMenu(void) V_DrawFill(x-(charw/2), y, charw, 84, multi_invcolor ?skincolors[skincolors[setupm_fakecolor->color].invcolor].ramp[skincolors[setupm_fakecolor->color].invshade] : 159); - sprdef = &skins[setupm_fakeskin].sprites[multi_spr2]; + sprdef = &skins[setupm_fakeskin]->sprites[multi_spr2]; if (!setupm_fakecolor->color || !sprdef->numframes) // should never happen but hey, who knows goto faildraw; @@ -12297,7 +12310,7 @@ static void M_DrawSetupMultiPlayerMenu(void) V_DrawFixedPatch( x<<FRACBITS, chary<<FRACBITS, - FixedDiv(skins[setupm_fakeskin].highresscale, skins[setupm_fakeskin].shieldscale), + FixedDiv(skins[setupm_fakeskin]->highresscale, skins[setupm_fakeskin]->shieldscale), flags, patch, colormap); goto colordraw; @@ -12529,7 +12542,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) setupm_fakeskin = numskins-1; } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); } else if (itemOn == 2) // player color { @@ -12545,7 +12558,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) { S_StartSound(NULL,sfx_strpst); // you know what? always putting these in the buffer won't hurt anything. - COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin].name)); + COM_BufAddText (va("%s \"%s\"\n",setupm_cvdefaultskin->name,skins[setupm_fakeskin]->name)); COM_BufAddText (va("%s %d\n",setupm_cvdefaultcolor->name,setupm_fakecolor->color)); break; } @@ -12569,7 +12582,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) setupm_fakeskin = 0; } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); } else if (itemOn == 2) // player color { @@ -12625,7 +12638,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } else if (itemOn == 2) { - UINT16 col = skins[setupm_fakeskin].prefcolor; + UINT16 col = skins[setupm_fakeskin]->prefcolor; if ((setupm_fakecolor->color != col) && skincolors[col].accessible) { S_StartSound(NULL,sfx_menu1); // Tails @@ -12719,7 +12732,7 @@ static void M_SetupMultiPlayer(INT32 choice) MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -12760,7 +12773,7 @@ static void M_SetupMultiPlayer2(INT32 choice) MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); - multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL); + multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -12778,7 +12791,7 @@ static boolean M_QuitMultiPlayerMenu(void) setupm_name[l] =0; COM_BufAddText (va("%s \"%s\"\n",setupm_cvname->name,setupm_name)); } - COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name)); + COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin]->name)); // send color if changed if (setupm_fakecolor->color != setupm_cvcolor->value) COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor->color)); diff --git a/src/m_menu.h b/src/m_menu.h index b8fe3b808..3cd2f66d3 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. @@ -375,10 +375,8 @@ typedef struct patch_t *charpic; UINT8 prev; UINT8 next; - - // new character select char displayname[SKINNAMESIZE+1]; - SINT8 skinnum[2]; + INT16 skinnum[2]; UINT16 oppositecolor; char nametag[8]; patch_t *namepic; @@ -431,7 +429,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/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 0643f8cc0..5970db0d7 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -1259,8 +1259,8 @@ static void SendNameAndColor(void) CV_StealthSetValue(&cv_playercolor, players[consoleplayer].skincolor); else if (skincolors[atoi(cv_playercolor.defaultvalue)].accessible) CV_StealthSet(&cv_playercolor, cv_playercolor.defaultvalue); - else if (skins[players[consoleplayer].skin].prefcolor && skincolors[skins[players[consoleplayer].skin].prefcolor].accessible) - CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin].prefcolor); + else if (skins[players[consoleplayer].skin]->prefcolor && skincolors[skins[players[consoleplayer].skin]->prefcolor].accessible) + CV_StealthSetValue(&cv_playercolor, skins[players[consoleplayer].skin]->prefcolor); else { UINT16 i = 0; while (i<numskincolors && !skincolors[i].accessible) i++; @@ -1270,7 +1270,7 @@ static void SendNameAndColor(void) if (!strcmp(cv_playername.string, player_names[consoleplayer]) && cv_playercolor.value == players[consoleplayer].skincolor - && !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name)) + && !strcmp(cv_skin.string, skins[players[consoleplayer].skin]->name)) return; players[consoleplayer].availabilities = R_GetSkinAvailabilities(); @@ -1313,7 +1313,7 @@ static void SendNameAndColor(void) if ((cv_skin.value < 0) || !R_SkinUsable(consoleplayer, cv_skin.value)) { INT32 defaultSkinNum = GetPlayerDefaultSkin(consoleplayer); - CV_StealthSet(&cv_skin, skins[defaultSkinNum].name); + CV_StealthSet(&cv_skin, skins[defaultSkinNum]->name); cv_skin.value = defaultSkinNum; } @@ -1344,8 +1344,8 @@ static void SendNameAndColor2(void) CV_StealthSetValue(&cv_playercolor2, players[secondplaya].skincolor); else if (skincolors[atoi(cv_playercolor2.defaultvalue)].accessible) CV_StealthSet(&cv_playercolor, cv_playercolor2.defaultvalue); - else if (skins[players[secondplaya].skin].prefcolor && skincolors[skins[players[secondplaya].skin].prefcolor].accessible) - CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor); + else if (skins[players[secondplaya].skin]->prefcolor && skincolors[skins[players[secondplaya].skin]->prefcolor].accessible) + CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin]->prefcolor); else { UINT16 i = 0; while (i<numskincolors && !skincolors[i].accessible) i++; @@ -2079,7 +2079,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) if (modeattacking) { SetPlayerSkinByNum(0, cv_chooseskin.value-1); - players[0].skincolor = skins[players[0].skin].prefcolor; + players[0].skincolor = skins[players[0].skin]->prefcolor; } mapnumber = M_MapNumber(mapname[3], mapname[4]); @@ -4743,7 +4743,7 @@ static void ForceSkin_OnChange(void) } else { - CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name); + CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value]->name); if (Playing()) ForceAllSkins(cv_forceskin.value); } @@ -4789,7 +4789,7 @@ static void Skin_OnChange(void) if (!(cv_debug || devparm) && (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y { - CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin]->name); return; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 819f0dc1d..a038ee1e3 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3677,7 +3677,7 @@ void A_1upThinker(mobj_t *actor) } } - if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) + if (closestplayer == -1 || skins[players[closestplayer].skin]->sprites[SPR2_LIFE].numframes == 0) { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. if (actor->tracer) { @@ -3698,7 +3698,7 @@ void A_1upThinker(mobj_t *actor) return; P_SetTarget(&actor->tracer->target, actor); - actor->tracer->skin = &skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame + actor->tracer->skin = skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame P_SetMobjState(actor->tracer, actor->info->seestate); // The overlay is going to be one tic early turning off and on @@ -3708,7 +3708,7 @@ void A_1upThinker(mobj_t *actor) } actor->tracer->color = players[closestplayer].mo->color; - actor->tracer->skin = &skins[players[closestplayer].skin]; + actor->tracer->skin = skins[players[closestplayer].skin]; } // Function: A_MonitorPop @@ -3769,6 +3769,7 @@ void A_MonitorPop(mobj_t *actor) { P_SetTarget(&newmobj->target, actor->target); // Transfer target + if (item == MT_1UP_ICON) { if (!newmobj->target @@ -3857,7 +3858,6 @@ void A_GoldMonitorPop(mobj_t *actor) if (!P_MobjWasRemoved(newmobj)) { P_SetTarget(&newmobj->target, actor->target); // Transfer target - if (item == MT_1UP_ICON) { if (actor->tracer) // Remove the old lives icon. @@ -5349,7 +5349,7 @@ void A_SignPlayer(mobj_t *actor) if (!actor->target->player) return; - skin = &skins[actor->target->player->skin]; + skin = skins[actor->target->player->skin]; facecolor = P_GetPlayerColor(actor->target->player); if (signcolor) @@ -5380,10 +5380,10 @@ void A_SignPlayer(mobj_t *actor) if (!SignSkinCheck(player, skincount)) skinnum++; } - skin = &skins[skinnum]; + skin = skins[skinnum]; } else // specific skin - skin = &skins[locvar1]; + skin = skins[locvar1]; facecolor = skin->prefcolor; if (signcolor) diff --git a/src/p_mobj.c b/src/p_mobj.c index e7a3c4049..f16fef2f0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -212,7 +212,7 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) return P_SetPlayerMobjState(mobj, S_PLAY_FALL); // Catch swimming versus flying - if ((state == S_PLAY_FLY || (state == S_PLAY_GLIDE && skins[player->skin].sprites[SPR2_SWIM].numframes)) + if ((state == S_PLAY_FLY || (state == S_PLAY_GLIDE && skins[player->skin]->sprites[SPR2_SWIM].numframes)) && player->mo->eflags & MFE_UNDERWATER && !player->skidtime) return P_SetPlayerMobjState(player->mo, S_PLAY_SWIM); else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) @@ -11086,10 +11086,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) nummaprings++; break; case MT_METALSONIC_RACE: - mobj->skin = &skins[5]; + mobj->skin = skins[5]; /* FALLTHRU */ case MT_METALSONIC_BATTLE: - mobj->color = skins[5].prefcolor; + mobj->color = skins[5]->prefcolor; sc = 5; break; case MT_FANG: @@ -11794,7 +11794,7 @@ void P_SpawnPlayer(INT32 playernum) // set 'spritedef' override in mobj for player skins.. (see ProjectSprite) // (usefulness: when body mobj is detached from player (who respawns), // the dead body mobj retains the skin through the 'spritedef' override). - mobj->skin = &skins[p->skin]; + mobj->skin = skins[p->skin]; P_SetupStateAnimation(mobj, mobj->state); mobj->health = 1; @@ -11802,14 +11802,14 @@ void P_SpawnPlayer(INT32 playernum) p->bonustime = false; p->realtime = leveltime; - p->followitem = skins[p->skin].followitem; + p->followitem = skins[p->skin]->followitem; // Make sure player's stats are reset if they were in dashmode! if (p->dashmode) { p->dashmode = 0; - p->normalspeed = skins[p->skin].normalspeed; - p->jumpfactor = skins[p->skin].jumpfactor; + p->normalspeed = skins[p->skin]->normalspeed; + p->jumpfactor = skins[p->skin]->jumpfactor; } // Clear lastlinehit and lastsidehit @@ -11825,7 +11825,7 @@ void P_SpawnPlayer(INT32 playernum) P_FlashPal(p, 0, 0); // Resets // Set bounds accurately. - mobj->radius = FixedMul(skins[p->skin].radius, mobj->scale); + mobj->radius = FixedMul(skins[p->skin]->radius, mobj->scale); mobj->height = P_GetPlayerHeight(p); if (!leveltime && !p->spectator && ((maptol & TOL_NIGHTS) == TOL_NIGHTS) != (G_IsSpecialStage(gamemap))) // non-special NiGHTS stage or special non-NiGHTS stage diff --git a/src/p_saveg.c b/src/p_saveg.c index 8c74ebef4..0f3668f5a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -78,11 +78,11 @@ static inline void P_ArchivePlayer(void) // Write skin names, so that loading skins in different orders // doesn't change who the save file is for! - WRITESTRINGN(save_p, skins[player->skin].name, SKINNAMESIZE); + WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE); if (botskin != 0) { - WRITESTRINGN(save_p, skins[botskin-1].name, SKINNAMESIZE); + WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE); } else { @@ -2058,7 +2058,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (diff2 & MD2_CVMEM) WRITEINT32(save_p, mobj->cvmem); if (diff2 & MD2_SKIN) - WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins)); + WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); if (diff2 & MD2_COLOR) WRITEUINT16(save_p, mobj->color); if (diff2 & MD2_EXTVAL1) @@ -3112,7 +3112,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_CVMEM) mobj->cvmem = READINT32(save_p); if (diff2 & MD2_SKIN) - mobj->skin = &skins[READUINT8(save_p)]; + mobj->skin = skins[READUINT8(save_p)]; if (diff2 & MD2_COLOR) mobj->color = READUINT16(save_p); if (diff2 & MD2_EXTVAL1) diff --git a/src/p_setup.c b/src/p_setup.c index 6f5ec17dc..d2126b0fc 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -7267,7 +7267,7 @@ static void P_ForceCharacter(const char *forcecharskin) SetPlayerSkinByNum(i, skinnum); if (!netgame) - players[i].skincolor = skins[skinnum].prefcolor; + players[i].skincolor = skins[skinnum]->prefcolor; } } @@ -7310,8 +7310,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_bestscore.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i]->name)); } } @@ -7323,8 +7323,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i]->name)); } } @@ -7336,8 +7336,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_bestrings.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-rings-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-rings-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-rings-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-rings-best.lmp", gpath, skins[i]->name)); } } @@ -7349,8 +7349,8 @@ static void P_LoadRecordGhosts(void) if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i]->name)); } } @@ -7380,8 +7380,8 @@ static void P_LoadNightsGhosts(void) if (cv_ghost_bestscore.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i]->name)); } } @@ -7393,8 +7393,8 @@ static void P_LoadNightsGhosts(void) if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i]->name)); } } @@ -7406,8 +7406,8 @@ static void P_LoadNightsGhosts(void) if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i) continue; - if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name))) - G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name)); + if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i]->name))) + G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i]->name)); } } diff --git a/src/p_spec.c b/src/p_spec.c index 131a58d20..3dbbc5352 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1836,7 +1836,7 @@ void P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) return; if (!triggerline->stringargs[0]) return; - if (!(stricmp(triggerline->stringargs[0], skins[actor->player->skin].name) == 0) ^ !!(triggerline->args[1])) + if (!(stricmp(triggerline->stringargs[0], skins[actor->player->skin]->name) == 0) ^ !!(triggerline->args[1])) return; break; case 334: // object dye diff --git a/src/p_user.c b/src/p_user.c index f6e12ecfa..6517771d8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -685,8 +685,8 @@ static void P_DeNightserizePlayer(player_t *player) player->mo->flags &= ~MF_NOGRAVITY; - player->mo->skin = &skins[player->skin]; - player->followitem = skins[player->skin].followitem; + player->mo->skin = skins[player->skin]; + player->followitem = skins[player->skin]->followitem; player->mo->color = P_GetPlayerColor(player); G_GhostAddColor(GHC_RETURNSKIN); @@ -786,12 +786,12 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->mo->height = P_GetPlayerHeight(player); // Just to make sure jumping into the drone doesn't result in a squashed hitbox. player->oldscale = player->mo->scale; - if (skins[player->skin].sprites[SPR2_NFLY].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. + if (skins[player->skin]->sprites[SPR2_NFLY].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { - player->mo->skin = &skins[DEFAULTNIGHTSSKIN]; + player->mo->skin = skins[DEFAULTNIGHTSSKIN]; if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) - player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; - player->followitem = skins[DEFAULTNIGHTSSKIN].followitem; + player->mo->color = skins[DEFAULTNIGHTSSKIN]->prefcolor; + player->followitem = skins[DEFAULTNIGHTSSKIN]->followitem; G_GhostAddColor(GHC_NIGHTSSKIN); } } @@ -4417,7 +4417,7 @@ static void P_DoSuperStuff(player_t *player) player->mo->color = (player->pflags & PF_GODMODE && cv_debug == 0) ? (SKINCOLOR_SUPERSILVER1 + 5*(((signed)leveltime >> 1) % 7)) // A wholesome easter egg. - : skins[player->skin].supercolor + abs( ( (player->powers[pw_super] >> 1) % 9) - 4); // This is where super flashing is handled. + : skins[player->skin]->supercolor + abs( ( (player->powers[pw_super] >> 1) % 9) - 4); // This is where super flashing is handled. G_GhostAddColor(GHC_SUPER); @@ -11643,7 +11643,7 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (resetinterp) R_ResetMobjInterpolationState(fume); // If dashmode is high enough, spawn a trail - if (player->normalspeed >= skins[player->skin].normalspeed*2) + if (player->normalspeed >= skins[player->skin]->normalspeed*2) { mobj_t *ghost = P_SpawnGhostMobj(fume); if (!P_MobjWasRemoved(ghost)) @@ -12517,25 +12517,25 @@ void P_PlayerThink(player_t *player) { if (prevdashmode >= DASHMODE_THRESHOLD) { - player->normalspeed = skins[player->skin].normalspeed; // Reset to default if not capable of entering dash mode. - player->jumpfactor = skins[player->skin].jumpfactor; + player->normalspeed = skins[player->skin]->normalspeed; // Reset to default if not capable of entering dash mode. + player->jumpfactor = skins[player->skin]->jumpfactor; if (player->powers[pw_strong] & STR_DASH) player->powers[pw_strong] = STR_NONE; } } else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground. { - if (player->normalspeed < skins[player->skin].normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic + if (player->normalspeed < skins[player->skin]->normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic player->normalspeed += FRACUNIT/5; // Enter Dash Mode smoothly. - if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. + if (player->jumpfactor < FixedMul(skins[player->skin]->jumpfactor, 5*FRACUNIT/4)) // Boost jump height. player->jumpfactor += FRACUNIT/300; if ((player->charflags & SF_MACHINE) && (!(player->powers[pw_strong] == STR_METAL))) player->powers[pw_strong] = STR_METAL; } - if (player->normalspeed >= skins[player->skin].normalspeed*2) + if (player->normalspeed >= skins[player->skin]->normalspeed*2) { mobj_t *ghost = P_SpawnGhostMobj(player->mo); // Spawns afterimages if (!P_MobjWasRemoved(ghost)) @@ -12550,8 +12550,8 @@ void P_PlayerThink(player_t *player) { if (dashmode >= DASHMODE_THRESHOLD) // catch getting the flag! { - player->normalspeed = skins[player->skin].normalspeed; - player->jumpfactor = skins[player->skin].jumpfactor; + player->normalspeed = skins[player->skin]->normalspeed; + player->jumpfactor = skins[player->skin]->jumpfactor; S_StartSound(player->mo, sfx_kc65); if (player->powers[pw_strong] & STR_DASH) player->powers[pw_strong] = STR_NONE; diff --git a/src/r_draw.c b/src/r_draw.c index 643f843d3..6e7efd004 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -121,52 +121,53 @@ float focallengthf, zeroheight; UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; // ========================================================================= -// TRANSLATION COLORMAP CODE +// TRANSLATION COLORMAP CODE // ========================================================================= -#define DEFAULT_TT_CACHE_INDEX MAXSKINS -#define BOSS_TT_CACHE_INDEX (MAXSKINS + 1) -#define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2) -#define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3) -#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4) -#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5) -#define DASHMODE_TT_CACHE_INDEX (MAXSKINS + 6) - -static UINT8 **translationtablecache[MAXSKINS + 7] = {NULL}; -UINT8 skincolor_modified[MAXSKINCOLORS]; - -static INT32 SkinToCacheIndex(INT32 skinnum) +enum { - switch (skinnum) + DEFAULT_TT_CACHE_INDEX, + BOSS_TT_CACHE_INDEX, + METALSONIC_TT_CACHE_INDEX, + ALLWHITE_TT_CACHE_INDEX, + RAINBOW_TT_CACHE_INDEX, + BLINK_TT_CACHE_INDEX, + DASHMODE_TT_CACHE_INDEX, + + TT_CACHE_SIZE +}; + +static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL}; +static UINT8 **skintranslationcache[NUM_PALETTE_ENTRIES] = {NULL}; + +boolean skincolor_modified[MAXSKINCOLORS]; + +static INT32 TranslationToCacheIndex(INT32 translation) +{ + switch (translation) { - case TC_DEFAULT: return DEFAULT_TT_CACHE_INDEX; case TC_BOSS: return BOSS_TT_CACHE_INDEX; case TC_METALSONIC: return METALSONIC_TT_CACHE_INDEX; case TC_ALLWHITE: return ALLWHITE_TT_CACHE_INDEX; case TC_RAINBOW: return RAINBOW_TT_CACHE_INDEX; case TC_BLINK: return BLINK_TT_CACHE_INDEX; case TC_DASHMODE: return DASHMODE_TT_CACHE_INDEX; - default: break; + default: return DEFAULT_TT_CACHE_INDEX; } - - return skinnum; } -static INT32 CacheIndexToSkin(INT32 ttc) +static INT32 CacheIndexToTranslation(INT32 index) { - switch (ttc) + switch (index) { - case DEFAULT_TT_CACHE_INDEX: return TC_DEFAULT; case BOSS_TT_CACHE_INDEX: return TC_BOSS; case METALSONIC_TT_CACHE_INDEX: return TC_METALSONIC; case ALLWHITE_TT_CACHE_INDEX: return TC_ALLWHITE; case RAINBOW_TT_CACHE_INDEX: return TC_RAINBOW; case BLINK_TT_CACHE_INDEX: return TC_BLINK; case DASHMODE_TT_CACHE_INDEX: return TC_DASHMODE; - default: break; + default: return TC_DEFAULT; } - - return ttc; } CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; @@ -396,18 +397,18 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) RGBA_t color; UINT8 brightness; INT32 j; - UINT8 colorbrightnesses[16]; + UINT8 colorbrightnesses[COLORRAMPSIZE]; UINT16 brightdif; INT32 temp; // first generate the brightness of all the colours of that skincolour - for (i = 0; i < 16; i++) + for (i = 0; i < COLORRAMPSIZE; i++) { color = V_GetColor(skincolors[skincolor].ramp[i]); SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue); } - // next, for every colour in the palette, choose the transcolor that has the closest brightness + // next, for every colour in the palette, choose the translated colour that has the closest brightness for (i = 0; i < NUM_PALETTE_ENTRIES; i++) { if (i == 0 || i == 31) // pure black and pure white don't change @@ -418,7 +419,7 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) color = V_GetColor(i); SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue); brightdif = 256; - for (j = 0; j < 16; j++) + for (j = 0; j < COLORRAMPSIZE; j++) { temp = abs((INT16)brightness - (INT16)colorbrightnesses[j]); if (temp < brightdif) @@ -434,28 +435,29 @@ static void R_RainbowColormap(UINT8 *dest_colormap, UINT16 skincolor) /** \brief Generates a translation colormap. - \param dest_colormap colormap to populate - \param skinnum skin number, or a translation mode - \param color translation color + \param dest_colormap colormap to populate + \param translation translation mode + \param color translation color + \param starttranscolor starting point of the translation \return void */ -static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT16 color) +static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 translation, UINT16 color, INT32 starttranscolor) { - INT32 i, starttranscolor, skinramplength; + INT32 i, skinramplength; // Handle a couple of simple special cases - if (skinnum < TC_DEFAULT) + if (translation < TC_DEFAULT) { - switch (skinnum) + switch (translation) { case TC_ALLWHITE: memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8)); return; case TC_RAINBOW: if (color >= numskincolors) - I_Error("Invalid skin color #%hu.", (UINT16)color); - if (color != SKINCOLOR_NONE) + I_Error("Invalid skin color #%hu", (UINT16)color); + else if (color != SKINCOLOR_NONE) { R_RainbowColormap(dest_colormap, color); return; @@ -463,8 +465,8 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U break; case TC_BLINK: if (color >= numskincolors) - I_Error("Invalid skin color #%hu.", (UINT16)color); - if (color != SKINCOLOR_NONE) + I_Error("Invalid skin color #%hu", (UINT16)color); + else if (color != SKINCOLOR_NONE) { memset(dest_colormap, skincolors[color].ramp[3], NUM_PALETTE_ENTRIES * sizeof(UINT8)); return; @@ -478,26 +480,28 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U dest_colormap[i] = (UINT8)i; // White! - if (skinnum == TC_BOSS) + if (translation == TC_BOSS) { UINT8 *originalColormap = R_GetTranslationColormap(TC_DEFAULT, (skincolornum_t)color, GTC_CACHE); - for (i = 0; i < 16; i++) + if (starttranscolor >= NUM_PALETTE_ENTRIES) + I_Error("Invalid startcolor #%d", starttranscolor); + for (i = 0; i < COLORRAMPSIZE; i++) { - dest_colormap[DEFAULT_STARTTRANSCOLOR + i] = originalColormap[DEFAULT_STARTTRANSCOLOR + i]; + dest_colormap[starttranscolor + i] = originalColormap[starttranscolor + i]; dest_colormap[31-i] = i; } } - else if (skinnum == TC_METALSONIC) + else if (translation == TC_METALSONIC) { for (i = 0; i < 6; i++) { dest_colormap[skincolors[SKINCOLOR_BLUE].ramp[12-i]] = skincolors[SKINCOLOR_BLUE].ramp[i]; } dest_colormap[159] = dest_colormap[253] = dest_colormap[254] = 0; - for (i = 0; i < 16; i++) + for (i = 0; i < COLORRAMPSIZE; i++) dest_colormap[96+i] = dest_colormap[skincolors[SKINCOLOR_COBALT].ramp[i]]; } - else if (skinnum == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices + else if (translation == TC_DASHMODE) // This is a long one, because MotorRoach basically hand-picked the indices { // greens -> ketchups dest_colormap[96] = dest_colormap[97] = 48; @@ -541,26 +545,21 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U } if (color >= numskincolors) - I_Error("Invalid skin color #%hu.", (UINT16)color); - - if (skinnum < 0 && skinnum > TC_DEFAULT) - I_Error("Invalid translation colormap index %d.", skinnum); - - starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR; + I_Error("Invalid skin color #%hu", (UINT16)color); if (starttranscolor >= NUM_PALETTE_ENTRIES) - I_Error("Invalid startcolor #%d.", starttranscolor); + I_Error("Invalid startcolor #%d", starttranscolor); // Fill in the entries of the palette that are fixed for (i = 0; i < starttranscolor; i++) dest_colormap[i] = (UINT8)i; - i = starttranscolor + 16; + i = starttranscolor + COLORRAMPSIZE; if (i < NUM_PALETTE_ENTRIES) { for (i = (UINT8)i; i < NUM_PALETTE_ENTRIES; i++) dest_colormap[i] = (UINT8)i; - skinramplength = 16; + skinramplength = COLORRAMPSIZE; } else skinramplength = i - NUM_PALETTE_ENTRIES; // shouldn't this be NUM_PALETTE_ENTRIES - starttranscolor? @@ -573,7 +572,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U /** \brief Retrieves a translation colormap from the cache. - \param skinnum number of skin, TC_DEFAULT or TC_BOSS + \param skinnum number of skin, or translation modes \param color translation color \param flags set GTC_CACHE to use the cache @@ -581,25 +580,47 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U */ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags) { - UINT8* ret; - INT32 skintableindex = SkinToCacheIndex(skinnum); // Adjust if we want the default colormap - INT32 i; + UINT8 ***cache = NULL; + INT32 index, starttranscolor; + UINT8 *ret; + + // Adjust if we want the default colormap + if (skinnum >= numskins) + I_Error("Invalid skin number %d", skinnum); + else if (skinnum >= 0) + { + cache = skintranslationcache; + starttranscolor = index = skins[skinnum]->starttranscolor; + } + else if (skinnum <= TC_DEFAULT) + { + cache = translationtablecache; + starttranscolor = DEFAULT_STARTTRANSCOLOR; + index = TranslationToCacheIndex(skinnum); + } + else + I_Error("Invalid translation %d", skinnum); if (flags & GTC_CACHE) { // Allocate table for skin if necessary - if (!translationtablecache[skintableindex]) - translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); + if (!cache[index]) + cache[index] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); // Get colormap - ret = translationtablecache[skintableindex][color]; + ret = cache[index][color]; // Rebuild the cache if necessary if (skincolor_modified[color]) { - for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) + INT32 i; + + for (i = 0; i < TT_CACHE_SIZE; i++) if (translationtablecache[i] && translationtablecache[i][color]) - R_GenerateTranslationColormap(translationtablecache[i][color], CacheIndexToSkin(i), color); + R_GenerateTranslationColormap(translationtablecache[i][color], CacheIndexToTranslation(i), color, starttranscolor); + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + if (skintranslationcache[i] && skintranslationcache[i][color]) + R_GenerateTranslationColormap(skintranslationcache[i][color], 0, color, i); skincolor_modified[color] = false; } @@ -610,11 +631,11 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags if (!ret) { ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8); - R_GenerateTranslationColormap(ret, skinnum, color); + R_GenerateTranslationColormap(ret, skinnum, color, starttranscolor); // Cache the colormap if desired if (flags & GTC_CACHE) - translationtablecache[skintableindex][color] = ret; + cache[index][color] = ret; } return ret; @@ -632,9 +653,12 @@ void R_FlushTranslationColormapCache(void) { INT32 i; - for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) + for (i = 0; i < TT_CACHE_SIZE; i++) if (translationtablecache[i]) memset(translationtablecache[i], 0, MAXSKINCOLORS * sizeof(UINT8**)); + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + if (skintranslationcache[i]) + memset(skintranslationcache[i], 0, MAXSKINCOLORS * sizeof(UINT8**)); } UINT16 R_GetColorByName(const char *name) diff --git a/src/r_draw.h b/src/r_draw.h index 0f08a48bf..9cde3cf54 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -146,7 +146,7 @@ UINT8 *R_GetBlendTable(int style, INT32 alphalevel); boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); // Color ramp modification should force a recache -extern UINT8 skincolor_modified[]; +extern boolean skincolor_modified[]; void R_InitViewBuffer(INT32 width, INT32 height); void R_InitViewBorder(void); diff --git a/src/r_picformats.c b/src/r_picformats.c index 3e817f4a0..0de15b427 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -1489,7 +1489,7 @@ static void R_ParseSpriteInfo(boolean spr2) spritenum_t sprnum = NUMSPRITES; playersprite_t spr2num = NUMPLAYERSPRITES; INT32 i; - INT32 skinnumbers[MAXSKINS]; + UINT8 *skinnumbers = NULL; INT32 foundskins = 0; // Sprite name @@ -1587,7 +1587,9 @@ static void R_ParseSpriteInfo(boolean spr2) if (skinnum == -1) I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); - skinnumbers[foundskins] = skinnum; + if (skinnumbers == NULL) + skinnumbers = Z_Malloc(sizeof(UINT8) * numskins, PU_STATIC, NULL); + skinnumbers[foundskins] = (UINT8)skinnum; foundskins++; } else if (stricmp(sprinfoToken, "FRAME")==0) @@ -1600,8 +1602,7 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); for (i = 0; i < foundskins; i++) { - size_t skinnum = skinnumbers[i]; - skin_t *skin = &skins[skinnum]; + skin_t *skin = skins[skinnumbers[i]]; spriteinfo_t *sprinfo = skin->sprinfo; M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); } @@ -1625,8 +1626,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 fbc2a30e1..1605ca6c8 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 @@ -105,7 +100,7 @@ static void Sk_SetDefaultValue(skin_t *skin) // memset(skin, 0, sizeof (skin_t)); snprintf(skin->name, - sizeof skin->name, "skin %u", (UINT32)(skin-skins)); + sizeof skin->name, "skin %u", (UINT32)(skin->skinnum)); skin->name[sizeof skin->name - 1] = '\0'; skin->wadnum = INT16_MAX; @@ -159,16 +154,6 @@ 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; } @@ -291,7 +276,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) } } -// returns true if the skin name is found (loaded from pwad) +// returns the skin number if the skin name is found (loaded from pwad) // warning return -1 if not found INT32 R_SkinAvailable(const char *name) { @@ -300,7 +285,7 @@ INT32 R_SkinAvailable(const char *name) for (i = 0; i < numskins; i++) { // search in the skin list - if (stricmp(skins[i].name,name)==0) + if (!stricmp(skins[i]->name,name)) return i; } return -1; @@ -324,7 +309,7 @@ INT32 R_GetForcedSkin(INT32 playernum) // Auxillary function that actually sets the skin static void SetSkin(player_t *player, INT32 skinnum) { - skin_t *skin = &skins[skinnum]; + skin_t *skin = skins[skinnum]; UINT16 newcolor = 0; player->skin = skinnum; @@ -381,7 +366,7 @@ static void SetSkin(player_t *player, INT32 skinnum) fixed_t radius = FixedMul(skin->radius, player->mo->scale); if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { - skin = &skins[DEFAULTNIGHTSSKIN]; + skin = skins[DEFAULTNIGHTSSKIN]; player->followitem = skin->followitem; if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) newcolor = skin->prefcolor; // will be updated in thinker to flashing @@ -721,8 +706,10 @@ void R_AddSkins(UINT16 wadnum, boolean mainfile) buf2[size] = '\0'; // set defaults - skin = &skins[numskins]; + skins = Z_Realloc(skins, sizeof(skin_t*) * (numskins + 1), PU_STATIC, NULL); + skin = skins[numskins] = Z_Calloc(sizeof(skin_t), PU_STATIC, NULL); Sk_SetDefaultValue(skin); + skin->skinnum = numskins; skin->wadnum = wadnum; hudname = realname = supername = false; // parse @@ -836,15 +823,6 @@ next_token: if (mainfile == false) 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 - -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerModel(numskins); -#endif numskins++; } @@ -915,7 +893,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile) strlwr(value); skinnum = R_SkinAvailable(value); if (skinnum != -1) - skin = &skins[skinnum]; + skin = skins[skinnum]; else { CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); @@ -1066,7 +1044,7 @@ static void R_RefreshSprite2ForWad(UINT16 wadnum, UINT8 start_spr2) strlwr(value); skinnum = R_SkinAvailable(value); if (skinnum != -1) - skin = &skins[skinnum]; + skin = skins[skinnum]; else { CONS_Debug(DBG_SETUP, "R_RefreshSprite2ForWad: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); diff --git a/src/r_skins.h b/src/r_skins.h index bf2275a49..a97b24f96 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -31,7 +31,8 @@ /// The skin_t struct typedef struct { - char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin + char name[SKINNAMESIZE+1]; // name of the skin + UINT8 skinnum; UINT16 wadnum; skinflags_t flags; @@ -85,7 +86,7 @@ typedef struct /// Externs extern INT32 numskins; -extern skin_t skins[MAXSKINS]; +extern skin_t **skins; /// Function prototypes void R_InitSkins(void); diff --git a/src/r_things.c b/src/r_things.c index d49b8e317..9d2868d4c 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -509,10 +509,6 @@ void R_AddSpriteDefs(UINT16 wadnum) if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) { -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddSpriteModel(i); -#endif // if a new sprite was added (not just replaced) addsprites++; #ifndef ZDEBUG @@ -587,14 +583,10 @@ void R_InitSprites(void) } ST_ReloadSkinFaceGraphics(); - // - // check if all sprites have frames - // - /* - for (i = 0; i < numsprites; i++) - if (sprites[i].numframes < 1) - CONS_Debug(DBG_SETUP, "R_InitSprites: sprite %s has no frames at all\n", sprnames[i]); - */ +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_LoadModels(); +#endif } // @@ -806,8 +798,8 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) } else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - return R_GetTranslationColormap((INT32)skinnum, vis->color, GTC_CACHE); + UINT8 skinnum = ((skin_t*)vis->mobj->skin)->skinnum; + return R_GetTranslationColormap(skinnum, vis->color, GTC_CACHE); } else // Use the defaults return R_GetTranslationColormap(TC_DEFAULT, vis->color, GTC_CACHE); diff --git a/src/sounds.h b/src/sounds.h index 102881e99..bf9342768 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 556829c1d..01d5f4738 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -54,8 +54,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 @@ -135,8 +135,6 @@ static patch_t *gotrflag; static patch_t *gotbflag; static patch_t *fnshico; -static boolean facefreed[MAXPLAYERS]; - hudinfo_t hudinfo[NUMHUDITEMS] = { { 16, 176, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_LIVES @@ -368,14 +366,14 @@ void ST_LoadGraphics(void) // made separate so that skins code can reload custom face graphics void ST_LoadFaceGraphics(INT32 skinnum) { - if (skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_LIFEPIC) + if (skins[skinnum]->sprites[SPR2_XTRA].numframes > XTRA_LIFEPIC) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC]; faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); - if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC) + if (skins[skinnum]->sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC) { - sprdef = &skins[skinnum].sprites[SPR2_XTRA|FF_SPR2SUPER]; + sprdef = &skins[skinnum]->sprites[SPR2_XTRA|FF_SPR2SUPER]; sprframe = &sprdef->spriteframes[0]; superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); } @@ -384,13 +382,21 @@ void ST_LoadFaceGraphics(INT32 skinnum) } else faceprefix[skinnum] = superprefix[skinnum] = W_CachePatchName("MISSING", PU_HUDGFX); // ditto - facefreed[skinnum] = false; } void ST_ReloadSkinFaceGraphics(void) { INT32 i; + Z_Free(faceprefix); + 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); } @@ -433,11 +439,6 @@ lumpnum_t st_borderpatchnum; void ST_Init(void) { - INT32 i; - - for (i = 0; i < MAXPLAYERS; i++) - facefreed[i] = true; - if (dedicated) return; @@ -997,14 +998,14 @@ static void ST_drawLivesArea(void) // name v_colmap |= (V_HUDTRANS|hudinfo[HUD_LIVES].f|V_PERPLAYER); - if (strlen(skins[stplyr->skin].hudname) <= 5) - V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); - else if (V_StringWidth(skins[stplyr->skin].hudname, v_colmap) <= 48) - V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); - else if (V_ThinStringWidth(skins[stplyr->skin].hudname, v_colmap) <= 40) - V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); + if (strlen(skins[stplyr->skin]->hudname) <= 5) + V_DrawRightAlignedString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); + else if (V_StringWidth(skins[stplyr->skin]->hudname, v_colmap) <= 48) + V_DrawString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); + else if (V_ThinStringWidth(skins[stplyr->skin]->hudname, v_colmap) <= 40) + V_DrawRightAlignedThinString(hudinfo[HUD_LIVES].x+58, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); else - V_DrawThinString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname); + V_DrawThinString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin]->hudname); // Power Stones collected if (G_RingSlingerGametype() && LUA_HudEnabled(hud_powerstones)) diff --git a/src/st_stuff.h b/src/st_stuff.h index 603be3c30..07dfac3ec 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]; diff --git a/src/v_video.c b/src/v_video.c index bcf8529a4..9e1bac2e5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1060,9 +1060,9 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN // void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor) { - if (skinnum >= 0 && skinnum < numskins && skins[skinnum].sprites[SPR2_XTRA].numframes > XTRA_CONTINUE) + if (skinnum >= 0 && skinnum < numskins && skins[skinnum]->sprites[SPR2_XTRA].numframes > XTRA_CONTINUE) { - spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_CONTINUE]; patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); diff --git a/src/y_inter.c b/src/y_inter.c index cbe057582..1f008eaf0 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -97,7 +97,7 @@ typedef union // Continues UINT8 continues; patch_t *pcontinues; - INT32 *playerchar; // Continue HUD + UINT8 *playerchar; // Continue HUD UINT16 *playercolor; UINT8 gotlife; // Number of extra lives obtained @@ -108,7 +108,7 @@ typedef union UINT32 scores[MAXPLAYERS]; // Winner's score UINT16 *color[MAXPLAYERS]; // Winner's color # boolean spectator[MAXPLAYERS]; // Spectator list - INT32 *character[MAXPLAYERS]; // Winner's character # + UINT8 *character[MAXPLAYERS]; // Winner's character # INT32 num[MAXPLAYERS]; // Winner's player # char *name[MAXPLAYERS]; // Winner's name patch_t *result; // RESULT @@ -121,7 +121,7 @@ typedef union struct { UINT16 *color[MAXPLAYERS]; // Winner's color # - INT32 *character[MAXPLAYERS]; // Winner's character # + UINT8 *character[MAXPLAYERS]; // Winner's character # INT32 num[MAXPLAYERS]; // Winner's player # char name[MAXPLAYERS][9]; // Winner's name UINT32 times[MAXPLAYERS]; @@ -1382,22 +1382,22 @@ void Y_StartIntermission(void) else { // too long so just show "YOU GOT THROUGH THE ACT" - if (strlen(skins[players[consoleplayer].skin].realname) > 13) + if (strlen(skins[players[consoleplayer].skin]->realname) > 13) { strcpy(data.coop.passed1, "you got"); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); } // long enough that "X GOT" won't fit so use "X PASSED THE ACT" - else if (strlen(skins[players[consoleplayer].skin].realname) > 8) + else if (strlen(skins[players[consoleplayer].skin]->realname) > 8) { - strcpy(data.coop.passed1, skins[players[consoleplayer].skin].realname); + strcpy(data.coop.passed1, skins[players[consoleplayer].skin]->realname); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "passed act" : "passed the act"); } // length is okay for normal use else { snprintf(data.coop.passed1, sizeof data.coop.passed1, "%s got", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); strcpy(data.coop.passed2, (mapheaderinfo[gamemap-1]->actnum) ? "through act" : "through the act"); } } @@ -1469,26 +1469,26 @@ void Y_StartIntermission(void) { snprintf(data.spec.passed1, sizeof data.spec.passed1, "%s", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; strcpy(data.spec.passed2, "got them all!"); if (players[consoleplayer].charflags & SF_SUPER) { strcpy(data.spec.passed3, "can now become"); - if (strlen(skins[players[consoleplayer].skin].supername) > 20) //too long, use generic + if (strlen(skins[players[consoleplayer].skin]->supername) > 20) //too long, use generic strcpy(data.spec.passed4, "their super form"); else - strcpy(data.spec.passed4, skins[players[consoleplayer].skin].supername); + strcpy(data.spec.passed4, skins[players[consoleplayer].skin]->supername); } } else { - if (strlen(skins[players[consoleplayer].skin].realname) <= SKINNAMESIZE-5) + if (strlen(skins[players[consoleplayer].skin]->realname) <= SKINNAMESIZE-5) { snprintf(data.spec.passed1, sizeof data.spec.passed1, "%s got", - skins[players[consoleplayer].skin].realname); + skins[players[consoleplayer].skin]->realname); data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; } else