Dynamically allocate skins

This avoids an issue where the skins array takes up a fixed, but large
amount of memory at runtime. On x86_64 linux, that array is roughly 80
megabytes in memory, most of which is unused when the game is unmodded.
Instead, we treat `skins` as a dynamically resizing array, and it is an
array-of-pointers into separate allocated `skin_t`.

This is based on Lactozilla's skin limit MR for SRB2, but I've rewritten
it because RR has diverged quite a bit.

This was verified to check every access of `skins` by using clangd's
find-all-references function. However, I have only tested plain skins,
not Lua addons, so that could afford some extra checking.
This commit is contained in:
Eidolon 2025-08-01 21:22:39 -05:00
parent 294e60bf8d
commit 255570cfca
48 changed files with 244 additions and 256 deletions

View file

@ -1646,7 +1646,7 @@ bool CallFunc_PlayerSkin(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::
&& (info->mo->player != NULL))
{
UINT8 skin = info->mo->player->skin;
thread->dataStk.push(~env->getString( skins[skin].name )->idx);
thread->dataStk.push(~env->getString( skins[skin]->name )->idx);
return false;
}
@ -3698,11 +3698,11 @@ bool CallFunc_SetThingProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, A
#define PROP_SKIN(x, y) \
case x: \
{ \
INT32 newSkin = (mobj->skin != NULL) ? (static_cast<skin_t *>(mobj->skin)) - skins : -1; \
INT32 newSkin = (mobj->skin != NULL) ? (static_cast<skin_t *>(mobj->skin)->skinnum) : -1; \
bool success = ACS_GetSkinFromString(thread->scopeMap->getString( value )->str, &newSkin); \
if (success == true) \
{ \
mobj->y = (newSkin >= 0 && newSkin < numskins) ? &skins[ newSkin ] : NULL; \
mobj->y = (newSkin >= 0 && newSkin < numskins) ? skins[ newSkin ] : NULL; \
} \
break; \
}

View file

@ -2126,7 +2126,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;
strlcpy(val, tmpskin, SKINNAMESIZE+1);
}
else

View file

@ -2077,7 +2077,7 @@ void D_SRB2Main(void)
INT32 importskin = R_SkinAvailableEx(pr->skinname, false);
if (importskin != -1)
{
skins[importskin].records.wins = pr->wins;
skins[importskin]->records.wins = pr->wins;
cupheader_t *cup;
for (cup = kartcupheaders; cup; cup = cup->next)
@ -2103,7 +2103,7 @@ void D_SRB2Main(void)
}
}
CONS_Printf(" Wins for profile \"%s\" imported onto character \"%s\"\n", pr->profilename, skins[importskin].name);
CONS_Printf(" Wins for profile \"%s\" imported onto character \"%s\"\n", pr->profilename, skins[importskin]->name);
}
}

View file

@ -881,7 +881,7 @@ static void ForceAllSkins(INT32 forcedskin)
if (!playeringame[g_localplayers[i]])
continue;
CV_StealthSet(&cv_skin[i], skins[forcedskin].name);
CV_StealthSet(&cv_skin[i], skins[forcedskin]->name);
}
}
@ -975,7 +975,7 @@ static void SendNameAndColor(const UINT8 n)
// Don't change skin if the server doesn't want you to.
if (!CanChangeSkin(playernum))
{
CV_StealthSet(&cv_skin[n], skins[player->skin].name);
CV_StealthSet(&cv_skin[n], skins[player->skin]->name);
}
// check if player has the skin loaded (cv_skin may have
@ -996,7 +996,7 @@ static void SendNameAndColor(const UINT8 n)
if (sendColor == SKINCOLOR_NONE)
{
sendColor = skins[cv_skin[n].value].prefcolor;
sendColor = skins[cv_skin[n].value]->prefcolor;
}
if (sendFollowerColor == SKINCOLOR_NONE)
@ -1014,7 +1014,7 @@ static void SendNameAndColor(const UINT8 n)
// Don't send if everything was identical.
if (!strcmp(cv_playername[n].string, player_names[playernum])
&& sendColor == player->skincolor
&& !stricmp(cv_skin[n].string, skins[player->skin].name)
&& !stricmp(cv_skin[n].string, skins[player->skin]->name)
&& !stricmp(cv_follower[n].string,
(player->followerskin < 0 ? "None" : followers[player->followerskin].name))
&& sendFollowerColor == player->followercolor)
@ -1194,7 +1194,7 @@ static void Got_NameAndColor(const UINT8 **cp, INT32 playernum)
SetPlayerSkinByNum(playernum, forcedskin);
if (localplayer != -1)
CV_StealthSet(&cv_skin[localplayer], skins[forcedskin].name);
CV_StealthSet(&cv_skin[localplayer], skins[forcedskin]->name);
}
else
{
@ -7038,7 +7038,7 @@ static void Skin_OnChange(const UINT8 p)
if (!CV_CheatsEnabled() && !(netgame || K_CanChangeRules(false))
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
{
CV_StealthSet(&cv_skin[p], skins[players[g_localplayers[p]].skin].name);
CV_StealthSet(&cv_skin[p], skins[players[g_localplayers[p]].skin]->name);
return;
}
@ -7049,7 +7049,7 @@ static void Skin_OnChange(const UINT8 p)
else
{
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
CV_StealthSet(&cv_skin[p], skins[players[g_localplayers[p]].skin].name);
CV_StealthSet(&cv_skin[p], skins[players[g_localplayers[p]].skin]->name);
}
}

View file

@ -952,7 +952,7 @@ void DRPC_UpdatePresence(void)
// Character image
if ((unsigned)players[consoleplayer].skin < g_discord_skins) // Supported skins
{
snprintf(charimg, 32, "char_%s", skins[ players[consoleplayer].skin ].name);
snprintf(charimg, 32, "char_%s", skins[ players[consoleplayer].skin ]->name);
discordPresence.smallImageKey = charimg;
}
else
@ -961,7 +961,7 @@ void DRPC_UpdatePresence(void)
discordPresence.smallImageKey = "custom_char";
}
snprintf(charname, 128, "Character: %s", skins[players[consoleplayer].skin].realname);
snprintf(charname, 128, "Character: %s", skins[players[consoleplayer].skin]->realname);
discordPresence.smallImageText = charname; // Character name
}
}

View file

@ -1371,7 +1371,7 @@ void F_GameEvaluationDrawer(void)
const char *rtatext, *cuttext;
rtatext = (marathonmode & MA_INGAME) ? "In-game timer" : "RTA timer";
cuttext = (marathonmode & MA_NOCUTSCENES) ? "" : " w/ cutscenes";
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);
}
@ -1886,13 +1886,13 @@ void F_TitleScreenDrawer(void)
if (eggSkin != -1)
{
eggColor = skins[eggSkin].prefcolor;
eggColor = skins[eggSkin]->prefcolor;
}
eggColormap = R_GetTranslationColormap(TC_DEFAULT, eggColor, GTC_MENUCACHE);
if (tailsSkin != -1)
{
tailsColor = skins[tailsSkin].prefcolor;
tailsColor = skins[tailsSkin]->prefcolor;
}
tailsColormap = R_GetTranslationColormap(TC_DEFAULT, tailsColor, GTC_MENUCACHE);
@ -2243,9 +2243,9 @@ void F_StartWaitingPlayers(void)
if (waitcolormap)
Z_Free(waitcolormap);
waitcolormap = R_GetTranslationColormap(randskin, skins[randskin].prefcolor, 0);
waitcolormap = R_GetTranslationColormap(randskin, skins[randskin]->prefcolor, 0);
sprdef = &skins[randskin].sprites[P_GetSkinSprite2(&skins[randskin], SPR2_FSTN, NULL)];
sprdef = &skins[randskin]->sprites[P_GetSkinSprite2(skins[randskin], SPR2_FSTN, NULL)];
for (i = 0; i < 2; i++)
{

View file

@ -922,14 +922,14 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
}
if (ghost->player && (
ghostext[playernum].skinid != (UINT8)(((skin_t *)ghost->skin)-skins) ||
ghostext[playernum].skinid != (UINT8)(((skin_t *)ghost->skin)->skinnum) ||
ghostext[playernum].kartspeed != ghost->player->kartspeed ||
ghostext[playernum].kartweight != ghost->player->kartweight ||
ghostext[playernum].charflags != ghost->player->charflags
))
{
ghostext[playernum].flags |= EZT_STATDATA;
ghostext[playernum].skinid = (UINT8)(((skin_t *)ghost->skin)-skins);
ghostext[playernum].skinid = (UINT8)(((skin_t *)ghost->skin)->skinnum);
ghostext[playernum].kartspeed = ghost->player->kartspeed;
ghostext[playernum].kartweight = ghost->player->kartweight;
ghostext[playernum].charflags = ghost->player->charflags;
@ -1013,7 +1013,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
if (ghost->player->followmobj->colorized)
followtic |= FZT_COLORIZED;
if (followtic & FZT_SKIN)
WRITEUINT8(demobuf.p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins));
WRITEUINT8(demobuf.p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))->skinnum));
oldghost[playernum].flags2 |= MF2_AMBUSH;
}
@ -1247,13 +1247,13 @@ void G_ConsGhostTic(INT32 playernum)
if (players[playernum].kartspeed != ghostext[playernum].kartspeed
|| players[playernum].kartweight != ghostext[playernum].kartweight
|| players[playernum].charflags != ghostext[playernum].charflags ||
demo.skinlist[ghostext[playernum].skinid].mapping != (UINT8)(((skin_t *)testmo->skin)-skins))
demo.skinlist[ghostext[playernum].skinid].mapping != (UINT8)(((skin_t *)testmo->skin)->skinnum))
{
if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced (Character/stats)!\n"));
demosynced = false;
testmo->skin = &skins[demo.skinlist[ghostext[playernum].skinid].mapping];
testmo->skin = skins[demo.skinlist[ghostext[playernum].skinid].mapping];
players[playernum].kartspeed = ghostext[playernum].kartspeed;
players[playernum].kartweight = ghostext[playernum].kartweight;
players[playernum].charflags = ghostext[playernum].charflags;
@ -1491,7 +1491,7 @@ readghosttic:
UINT8 skinid = READUINT8(g->p);
if (skinid >= g->numskins)
skinid = 0;
g->mo->skin = &skins[g->skinlist[skinid].mapping];
g->mo->skin = skins[g->skinlist[skinid].mapping];
g->p += 6; // kartspeed, kartweight, charflags
}
}
@ -1527,7 +1527,7 @@ readghosttic:
follow->colorized = true;
if (followtic & FZT_SKIN)
follow->skin = &skins[READUINT8(g->p)];
follow->skin = skins[READUINT8(g->p)];
}
if (follow)
{
@ -2066,12 +2066,12 @@ static void G_SaveDemoSkins(UINT8 **pp, const DemoBufferSizes &psizes)
for (i = 0; i < numskins; i++)
{
// Skinname, for first attempt at identification.
(*pp) += copy_fixed_buf((*pp), skins[i].name, psizes.skin_name);
(*pp) += copy_fixed_buf((*pp), skins[i]->name, psizes.skin_name);
// Backup information for second pass.
WRITEUINT8((*pp), skins[i].kartspeed);
WRITEUINT8((*pp), skins[i].kartweight);
WRITEUINT32((*pp), skins[i].flags);
WRITEUINT8((*pp), skins[i]->kartspeed);
WRITEUINT8((*pp), skins[i]->kartweight);
WRITEUINT32((*pp), skins[i]->flags);
}
for (i = 0; i < MAXAVAILABILITY; i++)
@ -3552,7 +3552,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
UINT8 *p;
mapthing_t *mthing;
UINT16 count, ghostversion;
skin_t *ghskin = &skins[0];
skin_t *ghskin = skins[0];
UINT8 worknumskins;
democharlist_t *skinlist = NULL;
@ -3705,7 +3705,7 @@ void G_AddGhost(savebuffer_t *buffer, const char *defdemoname)
// Skin
i = READUINT8(p);
if (i < worknumskins)
ghskin = &skins[skinlist[i].mapping];
ghskin = skins[skinlist[i].mapping];
p++; // lastfakeskin
// Color

View file

@ -2205,9 +2205,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
if (betweenmaps)
{
fakeskin = MAXSKINS;
kartspeed = skins[players[player].skin].kartspeed;
kartweight = skins[players[player].skin].kartweight;
charflags = skins[players[player].skin].flags;
kartspeed = skins[players[player].skin]->kartspeed;
kartweight = skins[players[player].skin]->kartweight;
charflags = skins[players[player].skin]->flags;
for (i = 0; i < LAP__MAX; i++)
{
@ -2218,7 +2218,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
{
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[player]].flags
: skins[players[player].skin].flags;
: skins[players[player].skin]->flags;
fakeskin = players[player].fakeskin;
kartspeed = players[player].kartspeed;
@ -5179,7 +5179,7 @@ void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar, UINT8 ss
}
SetPlayerSkinByNum(consoleplayer, pickedchar);
CV_StealthSet(&cv_skin[0], skins[pickedchar].name);
CV_StealthSet(&cv_skin[0], skins[pickedchar]->name);
if (color != SKINCOLOR_NONE)
{

View file

@ -118,7 +118,7 @@ void srb2::save_ng_gamedata()
for (int i = 0; i < numskins; i++)
{
srb2::GamedataSkinJson skin {};
skin_t& memskin = skins[i];
skin_t& memskin = *skins[i];
std::string name = std::string(memskin.name);
skin.records.wins = memskin.records.wins;
@ -239,7 +239,7 @@ void srb2::save_ng_gamedata()
}
else
{
newrecords.bestskin = std::string(skins[skinref.id].name);
newrecords.bestskin = std::string(skins[skinref.id]->name);
}
newrecords.gotemerald = cup->windata[i].got_emerald;
cupdata.records.emplace_back(std::move(newrecords));
@ -266,7 +266,7 @@ void srb2::save_ng_gamedata()
}
else
{
newrecords.bestskin = std::string(skins[skinref.id].name);
newrecords.bestskin = std::string(skins[skinref.id]->name);
}
newrecords.gotemerald = unloadedcup->windata[i].got_emerald;
cupdata.records.emplace_back(std::move(newrecords));
@ -591,7 +591,7 @@ void srb2::load_ng_gamedata()
if (skin != -1)
{
skins[skin].records = dummyrecord;
skins[skin]->records = dummyrecord;
}
else if (dummyrecord.wins)
{

View file

@ -4512,7 +4512,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].notfound || md2_playermodels[((skin_t*)(spr->mobj->skin))->skinnum].scale < 0.0f)
HWR_DrawSprite(spr);
else
{
@ -4725,7 +4725,7 @@ 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];
@ -5077,7 +5077,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
{
skinnum = (skin_t*)vis->mobj->skin-skins;
skinnum = ((skin_t*)vis->mobj->skin)->skinnum;
}
// Hide not-yet-unlocked characters in replays from other people

View file

@ -632,7 +632,7 @@ void HWR_AddPlayerModel(INT32 skin) // For skins that were added after startup
if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen))
skinname += prefixlen;
if (stricmp(skinname, skins[skin].name) == 0)
if (stricmp(skinname, skins[skin]->name) == 0)
{
md2_playermodels[skin].skin = skin;
md2_playermodels[skin].scale = scale;
@ -1448,10 +1448,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
// 1. load model+texture if not already loaded
// 2. draw model with correct position, rotation,...
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && !md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound) // Use the player MD2 list if the mobj has a skin and is using the player sprites
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && !md2_playermodels[((skin_t*)spr->mobj->skin)->skinnum].notfound) // 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;
md2 = &md2_playermodels[((skin_t*)spr->mobj->skin)->skinnum];
md2->skin = ((skin_t*)spr->mobj->skin)->skinnum;
}
else
{
@ -1525,7 +1525,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) // This thing is a player!
{
skinnum = (skin_t*)spr->mobj->skin-skins;
skinnum = ((skin_t*)spr->mobj->skin)->skinnum;
}
// Hide not-yet-unlocked characters in replays from other people

View file

@ -133,8 +133,8 @@ void K_SetBot(UINT8 newplayernum, UINT8 skinnum, UINT8 difficulty, botStyle_e st
// For each subsequent round of GP, K_UpdateGrandPrixBots will handle this.
players[newplayernum].spectator = grandprixinfo.gp && grandprixinfo.initalize && K_BotDefaultSpectator();
skincolornum_t color = static_cast<skincolornum_t>(skins[skinnum].prefcolor);
const char *realname = skins[skinnum].realname;
skincolornum_t color = static_cast<skincolornum_t>(skins[skinnum]->prefcolor);
const char *realname = skins[skinnum]->realname;
if (tutorialchallenge == TUTORIALSKIP_INPROGRESS)
{
// The ROYGBIV Rangers

View file

@ -264,7 +264,7 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, skincolornum_t
return;
}
starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum].starttranscolor : DEFAULT_STARTTRANSCOLOR;
starttranscolor = (skinnum != TC_DEFAULT) ? skins[skinnum]->starttranscolor : DEFAULT_STARTTRANSCOLOR;
// Fill in the entries of the palette that are fixed
for (i = 0; i < starttranscolor; i++)

View file

@ -187,7 +187,7 @@ void Dialogue::SetSpeaker(std::string skinName, int portraitID)
if (skinID >= 0 && skinID < numskins)
{
const skin_t *skin = &skins[skinID];
const skin_t *skin = skins[skinID];
const spritedef_t *sprdef = &skin->sprites[SPR2_TALK];
if (sprdef->numframes > 0)

View file

@ -273,7 +273,7 @@ UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, follower_t *follower, U
if (playerskin == NULL)
{
// Nothing from this line down is valid if playerskin is invalid, just guess Eggman?
playerskin = &skins[0];
playerskin = skins[0];
}
playercolor = playerskin->prefcolor;
@ -424,7 +424,7 @@ void K_HandleFollower(player_t *player)
if (player->followerskin < 0) // using a fallback follower
color = fl->defaultcolor;
else
color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, &skins[player->skin]);
color = K_GetEffectiveFollowerColor(player->followercolor, fl, player->skincolor, skins[player->skin]);
if (player->follower == NULL || P_MobjWasRemoved(player->follower)) // follower doesn't exist / isn't valid
{

View file

@ -213,7 +213,7 @@ void K_InitGrandPrixBots(void)
for (j = 0; j < numplayers; j++)
{
player_t *p = &players[competitors[j]];
const char *rivalname = skins[p->skin].rivals[i];
const char *rivalname = skins[p->skin]->rivals[i];
INT32 rivalnum = R_SkinAvailable(rivalname);
// Intentionally referenced before (currently dummied out) unlock check. Such a tease!
@ -792,8 +792,8 @@ void K_RetireBots(void)
bot->botvars.diffincrease = 0;
SetPlayerSkinByNum(i, skinnum);
bot->skincolor = skins[skinnum].prefcolor;
K_SetNameForBot(i, skins[skinnum].realname);
bot->skincolor = skins[skinnum]->prefcolor;
K_SetNameForBot(i, skins[skinnum]->realname);
bot->score = 0;
bot->pflags &= ~PF_NOCONTEST;

View file

@ -2508,7 +2508,7 @@ void PositionFacesInfo::draw_1p()
skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[rankplayer[i]]].flags
: skins[players[rankplayer[i]].skin].flags;
: skins[players[rankplayer[i]].skin]->flags;
// Flip SF_IRONMAN portraits, but only if they're transformed
if (skinflags & SF_IRONMAN
@ -2525,7 +2525,7 @@ void PositionFacesInfo::draw_1p()
if (players[rankplayer[i]].mo->color)
{
if ((skin_t*)players[rankplayer[i]].mo->skin)
workingskin = (skin_t*)players[rankplayer[i]].mo->skin - skins;
workingskin = ((skin_t*)players[rankplayer[i]].mo->skin)->skinnum;
else
workingskin = players[rankplayer[i]].skin;
@ -4569,7 +4569,7 @@ static void K_drawKartMinimap(void)
{
if (g->mo && !P_MobjWasRemoved(g->mo) && g->mo->skin)
{
skin = ((skin_t*)g->mo->skin)-skins;
skin = ((skin_t*)g->mo->skin)->skinnum;
workingPic = R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap;
@ -4646,7 +4646,7 @@ static void K_drawKartMinimap(void)
}
else
{
skin = ((skin_t*)mobj->skin)-skins;
skin = ((skin_t*)mobj->skin)->skinnum;
workingPic = R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap;
@ -4846,7 +4846,7 @@ static void K_drawKartMinimap(void)
}
else
{
skin = ((skin_t*)mobj->skin)-skins;
skin = ((skin_t*)mobj->skin)->skinnum;
workingPic = R_CanShowSkinInDemo(skin) ? faceprefix[skin][FACE_MINIMAP] : kp_unknownminimap;
@ -4882,7 +4882,7 @@ static void K_drawKartMinimap(void)
ang = ANGLE_180 - ang;
if (skin && mobj->color && !mobj->colorized // relevant to redo
&& skins[skin].starttranscolor != skins[0].starttranscolor) // redoing would have an affect
&& skins[skin]->starttranscolor != skins[0]->starttranscolor) // redoing would have an affect
{
colormap = R_GetTranslationColormap(TC_DEFAULT, static_cast<skincolornum_t>(mobj->color), GTC_CACHE);
}

View file

@ -2738,7 +2738,7 @@ static UINT8 K_ObjectToSkinIDForSounds(mobj_t *source)
if (!source->skin)
return MAXSKINS;
return ((skin_t *)source->skin)-skins;
return ((skin_t *)source->skin)->skinnum;
}
static void K_PlayGenericTastefulTaunt(mobj_t *source, sfxenum_t sfx_id)
@ -2825,7 +2825,7 @@ static void K_PlayGenericCombatSound(mobj_t *source, mobj_t *other, sfxenum_t sf
{
S_StartSound(
alwaysHear ? NULL : source,
skins[skinid].soundsid[S_sfx[sfx_id].skinsound]
skins[skinid]->soundsid[S_sfx[sfx_id].skinsound]
);
}
@ -8316,7 +8316,7 @@ void K_KartPlayerHUDUpdate(player_t *player)
if (player->skin >= 0 && player->skin < numskins)
{
skin_t *playerskin;
playerskin = &skins[player->skin];
playerskin = skins[player->skin];
playerskin->records.tumbletime++;
}
}

View file

@ -359,7 +359,7 @@ UINT16 M_GetCvPlayerColor(UINT8 pnum)
if (skin == -1)
return SKINCOLOR_NONE;
return skins[skin].prefcolor;
return skins[skin]->prefcolor;
}
static void M_DrawMenuParty(void)
@ -392,7 +392,7 @@ static void M_DrawMenuParty(void)
if (skin == -1) \
skin = 0; \
if (color == SKINCOLOR_NONE) \
color = skins[skin].prefcolor; \
color = skins[skin]->prefcolor; \
colormap = R_GetTranslationColormap(skin, color, GTC_MENUCACHE); \
}
@ -1618,7 +1618,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
skin = setup_chargrid[p->gridx][p->gridy].skinlist[n];
patch = faceprefix[skin][FACE_RANK];
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE);
radius = 24<<FRACBITS;
cx -= (SHORT(patch->width) << FRACBITS) >> 1;
@ -1643,7 +1643,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
n = r = M_GetColorAfter(&p->colors, r, 1);
}
colormap = R_GetTranslationColormap(TC_DEFAULT, (n == SKINCOLOR_NONE) ? skins[p->skin].prefcolor : n, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(TC_DEFAULT, (n == SKINCOLOR_NONE) ? skins[p->skin]->prefcolor : n, GTC_MENUCACHE);
diff = (numoptions - i) / 2; // only 0 when i == numoptions-1
@ -1742,7 +1742,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
patch = W_CachePatchName(fl->icon, PU_CACHE);
colormap = R_GetTranslationColormap(TC_DEFAULT,
K_GetEffectiveFollowerColor(fl->defaultcolor, fl, p->color, &skins[p->skin]),
K_GetEffectiveFollowerColor(fl->defaultcolor, fl, p->color, skins[p->skin]),
GTC_MENUCACHE
);
}
@ -1772,7 +1772,7 @@ static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
n = r = M_GetColorAfter(&p->colors, r, 1);
}
col = K_GetEffectiveFollowerColor(n, &followers[p->followern], p->color, &skins[p->skin]);
col = K_GetEffectiveFollowerColor(n, &followers[p->followern], p->color, skins[p->skin]);
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
@ -1826,8 +1826,8 @@ boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 ro
spriteframe_t *sprframe;
patch_t *sprpatch;
spr = P_GetSkinSprite2(&skins[skin], spr2, NULL);
sprdef = &skins[skin].sprites[spr];
spr = P_GetSkinSprite2(skins[skin], spr2, NULL);
sprdef = &skins[skin]->sprites[spr];
if (!sprdef->numframes) // No frames ??
return false; // Can't render!
@ -1842,11 +1842,11 @@ boolean M_DrawCharacterSprite(INT16 x, INT16 y, INT16 skin, UINT8 spr2, UINT8 ro
addflags ^= V_FLIP; // This sprite is left/right flipped!
}
if (skins[skin].highresscale != FRACUNIT)
if (skins[skin]->highresscale != FRACUNIT)
{
V_DrawFixedPatch(x<<FRACBITS,
y<<FRACBITS,
skins[skin].highresscale,
skins[skin]->highresscale,
addflags, sprpatch, colormap);
}
else
@ -1914,7 +1914,7 @@ static boolean M_DrawFollowerSprite(INT16 x, INT16 y, INT32 num, boolean charfli
(p->mdepth < CSSTEP_FOLLOWERCOLORS && p->mdepth != CSSTEP_ASKCHANGES) ? fl->defaultcolor : p->followercolor,
fl,
p->color,
&skins[p->skin]
skins[p->skin]
);
sine = FixedMul(fl->bobamp, FINESINE(((FixedMul(4 * M_TAU_FIXED, fl->bobspeed) * p->follower_timer)>>ANGLETOFINESHIFT) & FINEMASK));
colormap = R_GetTranslationColormap(TC_DEFAULT, color, GTC_MENUCACHE);
@ -1938,7 +1938,7 @@ static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y, boolean charflip
if (p->mdepth < CSSTEP_COLORS && p->mdepth != CSSTEP_ASKCHANGES)
{
color = skins[p->skin].prefcolor;
color = skins[p->skin]->prefcolor;
}
else
{
@ -1947,7 +1947,7 @@ static void M_DrawCharSelectSprite(UINT8 num, INT16 x, INT16 y, boolean charflip
if (color == SKINCOLOR_NONE)
{
color = skins[p->skin].prefcolor;
color = skins[p->skin]->prefcolor;
}
colormap = R_GetTranslationColormap(p->skin, color, GTC_MENUCACHE);
@ -2130,8 +2130,8 @@ static void M_DrawCharSelectPreview(UINT8 num)
&& setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum] < numskins)
{
V_DrawThinString(x-3, y+12, 0,
skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]].name);
randomskin = (skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]].flags & SF_IRONMAN);
skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]]->name);
randomskin = (skins[setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]]->flags & SF_IRONMAN);
}
else
{
@ -2283,7 +2283,7 @@ static void M_DrawCharSelectCursor(UINT8 num)
{
if (p->skin >= 0)
{
color = skins[p->skin].prefcolor;
color = skins[p->skin]->prefcolor;
}
else
{
@ -2347,7 +2347,7 @@ void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
{
if (skinnum >= 0)
{
truecol = skins[skinnum].prefcolor;
truecol = skins[skinnum]->prefcolor;
}
else
{
@ -2388,7 +2388,7 @@ void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
{
if (M_DrawFollowerSprite(x-22 - 16, y+119, 0, false, 0, 0, sp))
{
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, &followers[sp->followern], sp->color, &skins[sp->skin]);
UINT16 col = K_GetEffectiveFollowerColor(sp->followercolor, &followers[sp->followern], sp->color, skins[sp->skin]);
patch_t *ico = W_CachePatchName(followers[sp->followern].icon, PU_CACHE);
UINT8 *fcolormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
V_DrawMappedPatch(x+14+18, y+66, 0, ico, fcolormap);
@ -2416,7 +2416,7 @@ void M_DrawProfileCard(INT32 x, INT32 y, boolean greyedout, profile_t *p)
p->followercolor,
&followers[fln],
p->color,
&skins[skinnum]
skins[skinnum]
);
UINT8 *fcolormap = R_GetTranslationColormap(
(K_FollowerUsable(fln) ? TC_DEFAULT : TC_BLINK),
@ -2510,14 +2510,14 @@ void M_DrawCharacterSelect(void)
// Draw the icons now
for (i = 0; i < 9; i++)
{
if ((forceskin == true) && (i != skins[cv_forceskin.value].kartspeed-1))
if ((forceskin == true) && (i != skins[cv_forceskin.value]->kartspeed-1))
continue;
for (j = 0; j < 9; j++)
{
if (forceskin == true)
{
if (j != skins[cv_forceskin.value].kartweight-1)
if (j != skins[cv_forceskin.value]->kartweight-1)
continue;
skin = cv_forceskin.value;
}
@ -2545,7 +2545,7 @@ void M_DrawCharacterSelect(void)
if (k == setup_numplayers)
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE);
else
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE);
V_DrawMappedPatch(basex + 82 + (i*16) + quadx, 22 + (j*16) + quady, 0, faceprefix[skin][FACE_RANK], colormap);
@ -3063,7 +3063,7 @@ fixed_t M_DrawCupWinData(INT32 rankx, INT32 ranky, cupheader_t *cup, UINT8 diffi
{
UINT8 skin = windata->best_skin.id;
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE);
charPat = faceprefix[skin][FACE_MINIMAP];
}
@ -6648,7 +6648,7 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash
INT32 skin = M_UnlockableSkinNum(ref);
if (skin != -1)
{
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE);
pat = faceprefix[skin][(ref->majorunlock) ? FACE_WANTED : FACE_RANK];
}
break;
@ -6659,7 +6659,7 @@ static void M_DrawChallengeTile(INT16 i, INT16 j, INT32 x, INT32 y, UINT8 *flash
if (skin != -1)
{
INT32 psk = R_SkinAvailableEx(cv_skin[0].string, false);
UINT16 col = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, &followers[skin], cv_playercolor[0].value, (psk != -1) ? &skins[psk] : &skins[0]);
UINT16 col = K_GetEffectiveFollowerColor(followers[skin].defaultcolor, &followers[skin], cv_playercolor[0].value, (psk != -1) ? skins[psk] : skins[0]);
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
pat = W_CachePatchName(followers[skin].icon, PU_CACHE);
}
@ -6846,7 +6846,7 @@ void M_DrawCharacterIconAndEngine(INT32 x, INT32 y, UINT8 skin, UINT8 *colormap,
INT32 s, w;
if (skins[baseskin].flags & SF_IRONMAN)
if (skins[baseskin]->flags & SF_IRONMAN)
{
// this is the last thing i will do for rr pre-launhc ~toast 150424
// quoth tyron: "stat block rave holy shit"
@ -6879,8 +6879,8 @@ void M_DrawCharacterIconAndEngine(INT32 x, INT32 y, UINT8 skin, UINT8 *colormap,
{
// The following is a partial duplication of R_GetEngineClass
s = (skins[skin].kartspeed - 1)/3;
w = (skins[skin].kartweight - 1)/3;
s = (skins[skin]->kartspeed - 1)/3;
w = (skins[skin]->kartweight - 1)/3;
#define LOCKSTAT(stat) \
if (stat < 0) { stat = 0; } \
@ -6943,19 +6943,19 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
// Draw our character!
if (skin != -1)
{
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE);
M_DrawCharacterSprite(x, y, skin, SPR2_STIN, 7, 0, 0, colormap);
for (i = 0; i < skin; i++)
{
if (!R_SkinUsable(-1, i, false))
continue;
if (skins[i].kartspeed != skins[skin].kartspeed)
if (skins[i]->kartspeed != skins[skin]->kartspeed)
continue;
if (skins[i].kartweight != skins[skin].kartweight)
if (skins[i]->kartweight != skins[skin]->kartweight)
continue;
colormap = R_GetTranslationColormap(i, skins[i].prefcolor, GTC_MENUCACHE);
colormap = R_GetTranslationColormap(i, skins[i]->prefcolor, GTC_MENUCACHE);
break;
}
@ -6977,7 +6977,7 @@ static void M_DrawChallengePreview(INT32 x, INT32 y)
// Draw follower next to them
if (fskin != -1)
{
UINT16 col = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, &skins[skin]);
UINT16 col = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, skins[skin]);
colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_MENUCACHE);
M_DrawFollowerSprite(x - 16, y, fskin, false, 0, colormap, NULL);
@ -8366,14 +8366,14 @@ static void M_DrawStatsChars(void)
}
{
UINT8 *colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
UINT8 *colormap = R_GetTranslationColormap(skin, skins[skin]->prefcolor, GTC_MENUCACHE);
M_DrawCharacterIconAndEngine(24, y, skin, colormap, skin);
}
V_DrawThinString(24+32+2, y+3, 0, skins[skin].realname);
V_DrawThinString(24+32+2, y+3, 0, skins[skin]->realname);
V_DrawRightAlignedThinString(BASEVIDWIDTH/2 + 30, y+3, 0, va("%d/%d", skins[skin].records.wins, skins[skin].records.rounds));
V_DrawRightAlignedThinString(BASEVIDWIDTH/2 + 30, y+3, 0, va("%d/%d", skins[skin]->records.wins, skins[skin]->records.rounds));
y += STATSSTEP;
@ -8728,7 +8728,7 @@ static void M_DrawWrongPlayer(UINT8 i)
if (wrongpl.skin >= numskins)
return;
UINT8 *colormap = R_GetTranslationColormap(wrongpl.skin, skins[wrongpl.skin].prefcolor, GTC_MENUCACHE);
UINT8 *colormap = R_GetTranslationColormap(wrongpl.skin, skins[wrongpl.skin]->prefcolor, GTC_MENUCACHE);
M_DrawCharacterSprite(
wrongpl.across,

View file

@ -269,11 +269,11 @@ void podiumData_s::Init(void)
// but not this close to release
if (rank.position > RANK_NEUTRAL_POSITION || grade < GRADE_C)
{
gradeVoice = skins[rank.skin].soundsid[S_sfx[sfx_klose].skinsound];
gradeVoice = skins[rank.skin]->soundsid[S_sfx[sfx_klose].skinsound];
}
else
{
gradeVoice = skins[rank.skin].soundsid[S_sfx[sfx_kwin].skinsound];
gradeVoice = skins[rank.skin]->soundsid[S_sfx[sfx_kwin].skinsound];
}
}

View file

@ -426,7 +426,7 @@ void level_tally_t::Init(player_t *player)
{
snprintf(
header, sizeof header,
"%s", R_CanShowSkinInDemo(player->skin) ? skins[player->skin].realname : "???"
"%s", R_CanShowSkinInDemo(player->skin) ? skins[player->skin]->realname : "???"
);
}
@ -524,11 +524,11 @@ void level_tally_t::Init(player_t *player)
;
else if (rank < GRADE_C)
{
gradeVoice = skins[skinid].soundsid[S_sfx[sfx_klose].skinsound];
gradeVoice = skins[skinid]->soundsid[S_sfx[sfx_klose].skinsound];
}
else
{
gradeVoice = skins[skinid].soundsid[S_sfx[sfx_kwin].skinsound];
gradeVoice = skins[skinid]->soundsid[S_sfx[sfx_kwin].skinsound];
}
}

View file

@ -431,9 +431,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);
@ -461,7 +461,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), true, &skins[i].sprinfo[j], rot);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i]->sprinfo[j], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);

View file

@ -725,7 +725,7 @@ static int mobj_set(lua_State *L)
{
if (demo.playback)
skin = demo.skinlist[skin].mapping;
mo->skin = &skins[skin];
mo->skin = skins[skin];
}
return 0;

View file

@ -137,7 +137,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;
}
@ -156,14 +156,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;
}
@ -183,7 +183,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;
}
@ -200,7 +200,7 @@ static int lib_getSkin(lua_State *L)
i = R_SkinAvailableEx(field, false);
if (i != -1)
{
LUA_PushUserdata(L, &skins[i], META_SKIN);
LUA_PushUserdata(L, skins[i], META_SKIN);
return 1;
}

View file

@ -671,7 +671,7 @@ void M_ClearStats(void)
for (i = 0; i < numskins; i++)
{
memset(&skins[i].records, 0, sizeof(skins[i].records));
memset(&skins[i]->records, 0, sizeof(skins[i]->records));
}
unloaded_skin_t *unloadedskin, *nextunloadedskin = NULL;
@ -1553,7 +1553,7 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
if (cn->requirement < 0)
return false;
return (skins[cn->requirement].records.wins >= (UINT32)cn->extrainfo1);
return (skins[cn->requirement]->records.wins >= (UINT32)cn->extrainfo1);
case UC_ALLCUPRECORDS:
{
@ -1765,9 +1765,9 @@ boolean M_CheckCondition(condition_t *cn, player_t *player)
return (player->roundconditions.switched_skin == false
&& player->skin < numskins
&& R_GetEngineClass(
skins[player->skin].kartspeed,
skins[player->skin].kartweight,
skins[player->skin].flags
skins[player->skin]->kartspeed,
skins[player->skin]->kartweight,
skins[player->skin]->flags
) == (unsigned)cn->requirement);
case UCRP_HASFOLLOWER:
return (cn->requirement != -1 && player->followerskin == cn->requirement);
@ -2184,7 +2184,7 @@ static const char *M_GetConditionCharacter(INT32 skin, boolean directlyrequires)
for (j = 0; j < SKINRIVALS; j++)
{
const char *rivalname = skins[i].rivals[j];
const char *rivalname = skins[i]->rivals[j];
INT32 rivalnum = R_SkinAvailableEx(rivalname, false);
if (rivalnum != skin)
@ -2207,7 +2207,7 @@ static const char *M_GetConditionCharacter(INT32 skin, boolean directlyrequires)
}
return (permitname)
? skins[skin].realname
? skins[skin]->realname
: "???";
}
@ -2346,7 +2346,7 @@ static const char *M_GetConditionString(condition_t *cn)
case UC_CHARACTERWINS:
{
if (cn->requirement < 0 || !skins[cn->requirement].realname[0])
if (cn->requirement < 0 || !skins[cn->requirement]->realname[0])
return va("INVALID CHAR CONDITION \"%d:%d:%d\"", cn->type, cn->requirement, cn->extrainfo1);
work = M_GetConditionCharacter(cn->requirement, true);
return va("win %d Round%s as %s",
@ -2667,7 +2667,7 @@ static const char *M_GetConditionString(condition_t *cn)
Z_Free(title);
return work;
case UCRP_ISCHARACTER:
if (cn->requirement < 0 || !skins[cn->requirement].realname[0])
if (cn->requirement < 0 || !skins[cn->requirement]->realname[0])
return va("INVALID CHAR CONDITION \"%d:%d\"", cn->type, cn->requirement);
work = M_GetConditionCharacter(cn->requirement, true);
return va("as %s", work);
@ -2800,7 +2800,7 @@ static const char *M_GetConditionString(condition_t *cn)
case UCRP_MAKERETIRE:
{
if (cn->requirement < 0 || !skins[cn->requirement].realname[0])
if (cn->requirement < 0 || !skins[cn->requirement]->realname[0])
return va("INVALID CHAR CONDITION \"%d:%d\"", cn->type, cn->requirement);
work = M_GetConditionCharacter(cn->requirement, false);

View file

@ -752,7 +752,7 @@ void M_ChallengesTick(void)
INT32 skin = M_UnlockableSkinNum(ref);
if (skin != -1)
{
bombcolor = skins[skin].prefcolor;
bombcolor = skins[skin]->prefcolor;
}
break;
}
@ -764,7 +764,7 @@ void M_ChallengesTick(void)
INT32 psk = R_SkinAvailableEx(cv_skin[0].string, false);
if (psk == -1)
psk = 0;
bombcolor = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, &skins[psk]);
bombcolor = K_GetEffectiveFollowerColor(followers[fskin].defaultcolor, &followers[fskin], cv_playercolor[0].value, skins[psk]);
}
break;
}

View file

@ -131,16 +131,16 @@ static void M_StatisticsChars(void)
statisticsmenu.maplist[statisticsmenu.nummaps++] = i;
if (skins[i].records.wins == 0)
if (skins[i]->records.wins == 0)
continue;
// The following is a partial duplication of R_GetEngineClass
{
if (skins[i].flags & SF_IRONMAN)
if (skins[i]->flags & SF_IRONMAN)
continue; // does not add to any engine class
INT32 s = (skins[i].kartspeed - 1);
INT32 w = (skins[i].kartweight - 1);
INT32 s = (skins[i]->kartspeed - 1);
INT32 w = (skins[i]->kartweight - 1);
#define LOCKSTAT(stat) \
if (stat < 0) { continue; } \
@ -150,12 +150,12 @@ static void M_StatisticsChars(void)
#undef LOCKSTAT
if (
statisticsmenu.statgridplayed[s][w] > skins[i].records.wins
&& (UINT32_MAX - statisticsmenu.statgridplayed[s][w]) < skins[i].records.wins
statisticsmenu.statgridplayed[s][w] > skins[i]->records.wins
&& (UINT32_MAX - statisticsmenu.statgridplayed[s][w]) < skins[i]->records.wins
)
continue; // overflow protection
statisticsmenu.statgridplayed[s][w] += skins[i].records.wins;
statisticsmenu.statgridplayed[s][w] += skins[i]->records.wins;
if (beststat >= statisticsmenu.statgridplayed[s][w])
continue;
@ -170,9 +170,9 @@ static void M_StatisticsChars(void)
statisticsmenu.maplist,
statisticsmenu.maplist + statisticsmenu.nummaps,
[](UINT16 a, UINT16 b) {
if (skins[a].records.rounds > skins[b].records.rounds)
if (skins[a]->records.rounds > skins[b]->records.rounds)
return true;
if (skins[a].records.rounds != skins[b].records.rounds)
if (skins[a]->records.rounds != skins[b]->records.rounds)
return false;
// Stable for skin ID
return (a < b);

View file

@ -113,7 +113,7 @@ public:
return sfx_ktalk;
return skins[ skinID ]
.soundsid[ S_sfx[sfx_ktalk].skinsound ];
->soundsid[ S_sfx[sfx_ktalk].skinsound ];
};
int GetSkinID(void)
@ -1186,7 +1186,7 @@ static void M_GonerDrawer(void)
{
line = line
.xy(-16, -2)
.colormap(skinID, static_cast<skincolornum_t>(skins[skinID].prefcolor));
.colormap(skinID, static_cast<skincolornum_t>(skins[skinID]->prefcolor));
if (gamedata->gonerlevel > GDGONER_VIDEO)
line.patch(faceprefix[skinID][FACE_MINIMAP]);
else

View file

@ -235,12 +235,12 @@ static void M_SetupProfileGridPos(setup_player_t *p)
if (!R_SkinUsable(g_localplayers[0], i, false))
{
i = GetSkinNumClosestToStats(skins[i].kartspeed, skins[i].kartweight, skins[i].flags, false);
i = GetSkinNumClosestToStats(skins[i]->kartspeed, skins[i]->kartweight, skins[i]->flags, false);
}
// Now position the grid for skin
p->gridx = skins[i].kartspeed-1;
p->gridy = skins[i].kartweight-1;
p->gridx = skins[i]->kartspeed-1;
p->gridy = skins[i]->kartweight-1;
// Now this put our cursor on the good alt
while (alt < setup_chargrid[p->gridx][p->gridy].numskins && setup_chargrid[p->gridx][p->gridy].skinlist[alt] != i)
@ -273,8 +273,8 @@ static void M_SetupMidGameGridPos(setup_player_t *p, UINT8 num)
p->followern = -1;
// Now position the grid for skin
p->gridx = skins[i].kartspeed-1;
p->gridy = skins[i].kartweight-1;
p->gridx = skins[i]->kartspeed-1;
p->gridy = skins[i]->kartweight-1;
// Now this put our cursor on the good alt
while (alt < setup_chargrid[p->gridx][p->gridy].numskins && setup_chargrid[p->gridx][p->gridy].skinlist[alt] != i)
@ -347,8 +347,8 @@ void M_CharacterSelectInit(void)
for (i = 0; i < numskins; i++)
{
UINT8 x = skins[i].kartspeed-1;
UINT8 y = skins[i].kartweight-1;
UINT8 x = skins[i]->kartspeed-1;
UINT8 y = skins[i]->kartweight-1;
if (!R_SkinUsable(g_localplayers[0], i, false))
continue;
@ -778,7 +778,7 @@ static void M_HandleBeginningFollowers(setup_player_t *p)
static void M_HandleBeginningColorsOrFollowers(setup_player_t *p)
{
if (p->skin != -1)
S_StartSound(NULL, skins[p->skin].soundsid[S_sfx[sfx_kattk1].skinsound]);
S_StartSound(NULL, skins[p->skin]->soundsid[S_sfx[sfx_kattk1].skinsound]);
if (M_HandleBeginningColors(p))
S_StartSound(NULL, sfx_s3k63);
else
@ -851,8 +851,8 @@ static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
{
if (forceskin)
{
if ((p->gridx != skins[cv_forceskin.value].kartspeed-1)
|| (p->gridy != skins[cv_forceskin.value].kartweight-1))
if ((p->gridx != skins[cv_forceskin.value]->kartspeed-1)
|| (p->gridy != skins[cv_forceskin.value]->kartweight-1))
{
S_StartSound(NULL, sfx_s3k7b); //sfx_s3kb2
}
@ -1332,8 +1332,8 @@ boolean M_CharacterSelectHandler(INT32 choice)
// Just makes it easier to access later
if (forceskin)
{
if (p->gridx != skins[cv_forceskin.value].kartspeed-1
|| p->gridy != skins[cv_forceskin.value].kartweight-1)
if (p->gridx != skins[cv_forceskin.value]->kartspeed-1
|| p->gridy != skins[cv_forceskin.value]->kartweight-1)
p->skin = -1;
else
p->skin = cv_forceskin.value;
@ -1386,7 +1386,7 @@ static void M_MPConfirmCharacterSelection(void)
// finally, call the skin[x] console command.
// This will call SendNameAndColor which will synch everything we sent here and apply the changes!
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name);
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin]->name);
// ...actually, let's do this last - Skin_OnChange has some return-early occasions
// follower color
@ -1440,7 +1440,7 @@ void M_CharacterSelectTick(void)
if (optionsmenu.profile)
{
// save player
strcpy(optionsmenu.profile->skinname, skins[setup_player[0].skin].name);
strcpy(optionsmenu.profile->skinname, skins[setup_player[0].skin]->name);
optionsmenu.profile->color = setup_player[0].color;
// save follower
@ -1458,7 +1458,7 @@ void M_CharacterSelectTick(void)
{
for (i = 0; i < setup_numplayers; i++)
{
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin].name);
CV_StealthSet(&cv_skin[i], skins[setup_player[i].skin]->name);
CV_StealthSetValue(&cv_playercolor[i], setup_player[i].color);
if (setup_player[i].followern < 0)

View file

@ -119,7 +119,7 @@ static void M_StartCup(UINT8 entry)
// finally, call the skin[x] console command.
// This will call SendNameAndColor which will synch everything we sent here and apply the changes!
CV_StealthSet(&cv_skin[0], skins[savedata.skin].name);
CV_StealthSet(&cv_skin[0], skins[savedata.skin]->name);
// ...actually, let's do this last - Skin_OnChange has some return-early occasions
// follower color

View file

@ -317,11 +317,11 @@ struct Kart : Mobj
Mobj* p = player();
bool pValid = Mobj::valid(p) && p->player;
bool hasCustomHusk = pValid && skins[p->player->skin].sprites[SPR2_DKRT].numframes;
bool hasCustomHusk = pValid && skins[p->player->skin]->sprites[SPR2_DKRT].numframes;
if(hasCustomHusk)
{
skin = (void*)(&skins[p->player->skin]);
skin = (void*)(skins[p->player->skin]);
frame = 0;
}
@ -347,7 +347,7 @@ struct Kart : Mobj
if(pValid)
{
if((skins[p->player->skin].flags & SF_BADNIK))
if((skins[p->player->skin]->flags & SF_BADNIK))
{
P_SpawnBadnikExplosion(p);
p->spritescale({2*FRACUNIT, 2*FRACUNIT});

View file

@ -233,7 +233,7 @@ static void RingShooterCountdown(mobj_t *mo)
if (playeringame[rs_base_playerface(mo)] == true)
{
player_t *player = &players[ rs_base_playerid(mo) ];
part->skin = &skins[player->skin];
part->skin = skins[player->skin];
}
}
@ -779,9 +779,9 @@ void Obj_UpdateRingShooterFace(mobj_t *part)
// it's a good idea to set the actor's skin *before* it uses this action,
// but just in case, if it doesn't have the player's skin, set its skin then call the state again to get the correct sprite
if (part->skin != &skins[player->skin])
if (part->skin != skins[player->skin])
{
part->skin = &skins[player->skin];
part->skin = skins[player->skin];
P_SetMobjState(part, (statenum_t)(part->state - states));
return;
}

View file

@ -924,7 +924,7 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN
{
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[(source->player-players)]].flags
: skins[source->player->skin].flags;
: skins[source->player->skin]->flags;
if (skinflags & SF_IRONMAN)
SetRandomFakePlayerSkin(source->player, true, false);
}

View file

@ -2610,11 +2610,11 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
{
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[(player-players)]].flags
: skins[player->skin].flags;
: skins[player->skin]->flags;
if (skinflags & SF_IRONMAN)
{
player->mo->skin = &skins[player->skin];
player->mo->skin = skins[player->skin];
player->charflags = skinflags;
K_SpawnMagicianParticles(player->mo, 5);
S_StartSound(player->mo, sfx_slip);
@ -3234,7 +3234,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
UINT32 hurtskinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[(player-players)]].flags
: skins[player->skin].flags;
: skins[player->skin]->flags;
if (hurtskinflags & SF_IRONMAN)
{
if (gametyperules & GTR_BUMPERS)
@ -3249,11 +3249,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[(player-players)]].flags
: skins[player->skin].flags;
: skins[player->skin]->flags;
if (skinflags & SF_IRONMAN)
{
player->mo->skin = &skins[player->skin];
player->mo->skin = skins[player->skin];
player->charflags = skinflags;
K_SpawnMagicianParticles(player->mo, 5);
}

View file

@ -8881,7 +8881,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
UINT8 pnum = (newplayer-players);
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[pnum]].flags
: skins[newplayer->skin].flags;
: skins[newplayer->skin]->flags;
if (skinflags & SF_IRONMAN)
{
@ -8932,7 +8932,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (newplayer != NULL)
{
cur->skin = &skins[newplayer->skin];
cur->skin = skins[newplayer->skin];
cur->color = newplayer->skincolor;
// Even if we didn't have the Perfect Sign to consider,
@ -8940,7 +8940,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
P_SetMobjState(cur, (newperfect == true) ? S_KART_SIGL : S_KART_SIGN);
if (cv_shittysigns.value && cur->state != &states[S_KART_SIGL])
cur->sprite2 = P_GetSkinSprite2(&skins[newplayer->skin], SPR2_SSIG, NULL);;
cur->sprite2 = P_GetSkinSprite2(skins[newplayer->skin], SPR2_SSIG, NULL);;
}
}
else if (cur->state == &states[S_SIGN_ERROR])
@ -12102,7 +12102,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;
@ -12113,7 +12113,7 @@ void P_SpawnPlayer(INT32 playernum)
p->realtime = leveltime;
}
p->followitem = skins[p->skin].followitem;
p->followitem = skins[p->skin]->followitem;
if (p->jointime <= 1 || leveltime <= 1)
{
@ -13685,7 +13685,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
if (!playeringame[i] || players[i].spectator == true)
continue;
if (strcmp(skins[players[i].skin].name, "sakura") == 0)
if (strcmp(skins[players[i].skin]->name, "sakura") == 0)
{
state = mobj->info->spawnstate;
break;

View file

@ -105,7 +105,7 @@ static inline void P_ArchivePlayer(savebuffer_t *save)
if (skin > numskins)
skin = 0;
WRITESTRINGN(save->p, skins[skin].name, SKINNAMESIZE);
WRITESTRINGN(save->p, skins[skin]->name, SKINNAMESIZE);
if (player->followerskin < 0 || player->followerskin >= numfollowers)
WRITESTRINGN(save->p, "None", SKINNAMESIZE);
@ -130,7 +130,7 @@ static inline void P_ArchivePlayer(savebuffer_t *save)
if (skin > numskins)
skin = 0;
WRITESTRINGN(save->p, skins[skin].name, SKINNAMESIZE);
WRITESTRINGN(save->p, skins[skin]->name, SKINNAMESIZE);
WRITEUINT8(save->p, players[i].botvars.difficulty);
WRITEUINT8(save->p, (UINT8)players[i].botvars.rival);
@ -183,7 +183,7 @@ static boolean P_UnArchivePlayer(savebuffer_t *save)
{
// It is not worth destroying an otherwise good savedata over extra added skins.
// Let's just say they didn't show up to the rematch, so some Eggrobos subbed in.
CONS_Alert(CONS_WARNING, "P_UnArchivePlayer: Bot's character \"%s\" was not loaded, replacing with default \"%s\".\n", skinname, skins[defaultbotskin].name);
CONS_Alert(CONS_WARNING, "P_UnArchivePlayer: Bot's character \"%s\" was not loaded, replacing with default \"%s\".\n", skinname, skins[defaultbotskin]->name);
skin = defaultbotskin;
}
@ -3361,7 +3361,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
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)
@ -4635,7 +4635,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, 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)

View file

@ -7882,7 +7882,7 @@ static void P_LoadRecordGhosts(void)
if (allGhosts)
{
for (i = 0; i < numskins; ++i)
add_ghosts(fmt::format("{}-{}{}", gpath, skins[i].name, modeprefix), allGhosts);
add_ghosts(fmt::format("{}-{}{}", gpath, skins[i]->name, modeprefix), allGhosts);
}
if (sameGhosts)
@ -7890,7 +7890,7 @@ static void P_LoadRecordGhosts(void)
INT32 skin = R_SkinAvailableEx(cv_skin[0].string, false);
if (skin < 0 || !R_SkinUsable(-1, skin, false))
skin = 0; // use default skin
add_ghosts(fmt::format("{}-{}{}", gpath, skins[skin].name, modeprefix), sameGhosts);
add_ghosts(fmt::format("{}-{}{}", gpath, skins[skin]->name, modeprefix), sameGhosts);
}
// Guest ghost
@ -8026,7 +8026,7 @@ static void P_InitPlayers(void)
if (skin != -1)
{
SetPlayerSkinByNum(i, skin);
players[i].skincolor = skins[skin].prefcolor;
players[i].skincolor = skins[skin]->prefcolor;
players[i].followerskin = follower;
if (follower != -1)

View file

@ -1586,7 +1586,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
return false;
if (!triggerline->stringargs[0])
return false;
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 false;
break;
case 334: // object dye
@ -2015,7 +2015,7 @@ static void K_HandleLapIncrement(player_t *player)
{
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[(player-players)]].flags
: skins[player->skin].flags;
: skins[player->skin]->flags;
if (skinflags & SF_IRONMAN)
{
SetRandomFakePlayerSkin(player, true, false);

View file

@ -985,7 +985,7 @@ void P_Ticker(boolean run)
continue;
}
playerskin = &skins[players[i].skin];
playerskin = skins[players[i].skin];
playerskin->records.timeplayed++;
}
@ -1045,7 +1045,7 @@ void P_Ticker(boolean run)
continue;
}
playerskin = &skins[players[i].skin];
playerskin = skins[players[i].skin];
playerskin->records.modetimeplayed[mode]++;
}
}

View file

@ -1335,7 +1335,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
// Skin records (saved to gamedata)
if (player->skin < numskins)
{
skin_t *playerskin = &skins[player->skin];
skin_t *playerskin = skins[player->skin];
if (!losing)
{
playerskin->records.wins++;
@ -4584,7 +4584,7 @@ void P_PlayerThink(player_t *player)
{
UINT32 skinflags = (demo.playback)
? demo.skinlist[demo.currentskinid[playeri]].flags
: skins[player->skin].flags;
: skins[player->skin]->flags;
if (skinflags & SF_IRONMAN) // we are Heavy Magician
{

View file

@ -1448,7 +1448,7 @@ static void R_ParseSpriteInfoSkin(struct ParseSpriteInfoState *parser)
static void copy_to_skin (struct ParseSpriteInfoState *parser, INT32 skinnum)
{
skin_t *skin = &skins[skinnum];
skin_t *skin = skins[skinnum];
spriteinfo_t *sprinfo = skin->sprinfo;
if (parser->any)

View file

@ -42,7 +42,7 @@
#endif
INT32 numskins = 0;
skin_t skins[MAXSKINS];
skin_t **skins;
unloaded_skin_t *unloadedskins = NULL;
@ -111,7 +111,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", skin->skinnum);
skin->name[sizeof skin->name - 1] = '\0';
skin->wadnum = INT16_MAX;
@ -168,16 +168,6 @@ void R_InitSkins(void)
{
size_t i;
// it can be is do before loading config for skin cvar possible value
// (... what the fuck did you just say to me? "it can be is do"?)
#ifdef SKINVALUES
for (i = 0; i <= MAXSKINS; i++)
{
skin_cons_t[i].value = 0;
skin_cons_t[i].strvalue = NULL;
}
#endif
// no default skin!
numskins = 0;
@ -334,7 +324,7 @@ UINT32 R_GetLocalRandomSkin(void)
return grabskins[M_RandomKey(usableskins)];
}
// 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)
{
@ -362,10 +352,10 @@ INT32 R_SkinAvailableEx(const char *name, boolean demoskins)
for (i = 0; i < numskins; i++)
{
if (skins[i].namehash != hash)
if (skins[i]->namehash != hash)
continue;
if (stricmp(skins[i].name,name)!=0)
if (stricmp(skins[i]->name,name)!=0)
continue;
return i;
@ -398,7 +388,7 @@ static void SetSkin(player_t *player, INT32 skinnum)
if (demo.playback)
skinnum = demo.skinlist[skinnum].mapping;
skin_t *skin = &skins[skinnum];
skin_t *skin = skins[skinnum];
player->skin = skinnum;
@ -523,9 +513,9 @@ void SetFakePlayerSkin(player_t* player, INT32 skinid)
}
else
{
player->kartspeed = skins[skinid].kartspeed;
player->kartweight = skins[skinid].kartweight;
player->charflags = skins[skinid].flags;
player->kartspeed = skins[skinid]->kartspeed;
player->kartweight = skins[skinid]->kartweight;
player->charflags = skins[skinid]->flags;
}
player->mo->skin = &skins[skinid];
@ -549,7 +539,7 @@ void SetRandomFakePlayerSkin(player_t* player, boolean fast, boolean instant)
if (demo.skinlist[i].flags & SF_IRONMAN)
continue;
}
else if (skins[i].flags & SF_IRONMAN)
else if (skins[i]->flags & SF_IRONMAN)
continue;
if (!R_SkinUsable(player-players, i, true))
continue;
@ -628,7 +618,7 @@ void ClearFakePlayerSkin(player_t* player)
else
{
skinid = player->skin;
flags = skins[player->skin].flags;
flags = skins[player->skin]->flags;
}
if ((flags & SF_IRONMAN) && !P_MobjWasRemoved(player->mo))
@ -661,8 +651,8 @@ flaglessretry:
{
continue;
}
stat_diff = abs(skins[i].kartspeed - kartspeed) + abs(skins[i].kartweight - kartweight);
if (doflagcheck && (skins[i].flags & flagcheck) != flagcheck)
stat_diff = abs(skins[i]->kartspeed - kartspeed) + abs(skins[i]->kartweight - kartweight);
if (doflagcheck && (skins[i]->flags & flagcheck) != flagcheck)
{
continue;
}
@ -969,8 +959,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;
realname = false;
// parse
@ -1045,14 +1037,9 @@ 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
// Update the forceskin possiblevalues
Forceskin_cons_t[numskins+1].value = numskins;
Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name;
Forceskin_cons_t[numskins+1].strvalue = skins[numskins]->name;
#ifdef HWRENDER
if (rendermode == render_opengl)
@ -1190,7 +1177,7 @@ void R_PatchSkins(UINT16 wadnum, boolean mainfile)
strlwr(value);
skinnum = R_SkinAvailableEx(value, false);
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);

View file

@ -38,7 +38,8 @@ extern "C" {
/// The skin_t struct
struct skin_t
{
char name[SKINNAMESIZE+1]; // descriptive name of the skin
char name[SKINNAMESIZE+1]; // name of skin
UINT8 skinnum;
UINT32 namehash; // quickncasehash(->name, SKINNAMESIZE)
UINT16 wadnum;
skinflags_t flags;
@ -100,7 +101,7 @@ engineclass_t R_GetEngineClass(SINT8 speed, SINT8 weight, skinflags_t flags);
/// Externs
extern INT32 numskins;
extern skin_t skins[MAXSKINS];
extern skin_t **skins;
extern CV_PossibleValue_t Forceskin_cons_t[];

View file

@ -45,7 +45,7 @@ INT32 R_ThingLightLevel(mobj_t* thing)
lightlevel -= 255;
}
if (!R_CanShowSkinInDemo((skin_t*)thing->skin-skins)
if (!R_CanShowSkinInDemo(((skin_t*)thing->skin)->skinnum)
&& !thing->colorized
&& !thing->hitlag)
{

View file

@ -848,7 +848,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
{
skinnum = (skin_t*)vis->mobj->skin-skins;
skinnum = ((skin_t*)vis->mobj->skin)->skinnum;
// Hide not-yet-unlocked characters in replays from other people
if (!R_CanShowSkinInDemo(skinnum))

View file

@ -511,8 +511,8 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (sfx->skinsound != -1 && origin && (origin->player || origin->skin))
{
// redirect player sound to the sound in the skin table
skin_t *skin = (origin->player ? &skins[origin->player->skin] : ((skin_t *)origin->skin));
if (R_CanShowSkinInDemo(skin-skins) == false)
skin_t *skin = (origin->player ? skins[origin->player->skin] : ((skin_t *)origin->skin));
if (R_CanShowSkinInDemo(skin->skinnum) == false)
return;
sfx_id = skin->soundsid[sfx->skinsound];
sfx = &S_sfx[sfx_id];

View file

@ -181,7 +181,7 @@ void ST_LoadGraphics(void)
void ST_LoadFaceGraphics(INT32 skinnum)
{
#define FACE_MAX (FACE_MINIMAP+1)
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA];
spriteframe_t *sprframe;
UINT8 i = 0, maxer = min(sprdef->numframes, FACE_MAX);
while (i < maxer)

View file

@ -393,7 +393,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
snprintf(data.headerstring,
sizeof data.headerstring,
"%s",
R_CanShowSkinInDemo(players[i].skin) ? skins[players[i].skin].realname : "???");
R_CanShowSkinInDemo(players[i].skin) ? skins[players[i].skin]->realname : "???");
}
data.showroundnum = true;