- made the Skins array scripting friendly and exported it.

This commit is contained in:
Christoph Oelckers 2017-02-17 21:51:23 +01:00
parent 6a2525b737
commit 498da825a5
17 changed files with 136 additions and 118 deletions

View file

@ -729,7 +729,7 @@ void D_WriteUserInfoStrings (int pnum, BYTE **stream, bool compact)
break; break;
case NAME_Skin: case NAME_Skin:
*stream += sprintf(*((char **)stream), "\\%s", D_EscapeUserInfo(skins[info->GetSkin()].name).GetChars()); *stream += sprintf(*((char **)stream), "\\%s", D_EscapeUserInfo(Skins[info->GetSkin()].Name).GetChars());
break; break;
default: default:
@ -828,7 +828,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update)
players[pnum].mo->state->sprite == players[pnum].mo->state->sprite ==
GetDefaultByType (players[pnum].cls)->SpawnState->sprite) GetDefaultByType (players[pnum].cls)->SpawnState->sprite)
{ // Only change the sprite if the player is using a standard one { // Only change the sprite if the player is using a standard one
players[pnum].mo->sprite = skins[info->GetSkin()].sprite; players[pnum].mo->sprite = Skins[info->GetSkin()].sprite;
} }
} }
// Rebuild translation in case the new skin uses a different range // Rebuild translation in case the new skin uses a different range
@ -898,7 +898,7 @@ void WriteUserInfo(FSerializer &arc, userinfo_t &info)
switch (pair->Key.GetIndex()) switch (pair->Key.GetIndex())
{ {
case NAME_Skin: case NAME_Skin:
string = skins[info.GetSkin()].name; string = Skins[info.GetSkin()].Name;
break; break;
case NAME_PlayerClass: case NAME_PlayerClass:
@ -986,7 +986,7 @@ CCMD (playerinfo)
// Print special info // Print special info
Printf("%20s: %s\n", "Name", ui->GetName()); Printf("%20s: %s\n", "Name", ui->GetName());
Printf("%20s: %s (%d)\n", "Team", ui->GetTeam() == TEAM_NONE ? "None" : Teams[ui->GetTeam()].GetName(), ui->GetTeam()); Printf("%20s: %s (%d)\n", "Team", ui->GetTeam() == TEAM_NONE ? "None" : Teams[ui->GetTeam()].GetName(), ui->GetTeam());
Printf("%20s: %s (%d)\n", "Skin", skins[ui->GetSkin()].name, ui->GetSkin()); Printf("%20s: %s (%d)\n", "Skin", Skins[ui->GetSkin()].Name.GetChars(), ui->GetSkin());
Printf("%20s: %s (%d)\n", "Gender", GenderNames[ui->GetGender()], ui->GetGender()); Printf("%20s: %s (%d)\n", "Gender", GenderNames[ui->GetGender()], ui->GetGender());
Printf("%20s: %s (%d)\n", "PlayerClass", Printf("%20s: %s (%d)\n", "PlayerClass",
ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->DisplayName.GetChars(), ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->DisplayName.GetChars(),

View file

@ -1695,7 +1695,7 @@ static void G_QueueBody (AActor *body)
{ {
// Apply skin's scale to actor's scale, it will be lost otherwise // Apply skin's scale to actor's scale, it will be lost otherwise
const AActor *const defaultActor = body->GetDefault(); const AActor *const defaultActor = body->GetDefault();
const FPlayerSkin &skin = skins[skinidx]; const FPlayerSkin &skin = Skins[skinidx];
body->Scale.X *= skin.Scale.X / defaultActor->Scale.X; body->Scale.X *= skin.Scale.X / defaultActor->Scale.X;
body->Scale.Y *= skin.Scale.Y / defaultActor->Scale.Y; body->Scale.Y *= skin.Scale.Y / defaultActor->Scale.Y;

View file

@ -298,7 +298,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
// If a custom skin was in use, then reload it // If a custom skin was in use, then reload it
// or else the base skin for the player class. // or else the base skin for the player class.
if ((unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () && if ((unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () &&
(size_t)player->userinfo.GetSkin() < numskins) (unsigned)player->userinfo.GetSkin() < Skins.Size())
{ {
skinindex = player->userinfo.GetSkin(); skinindex = player->userinfo.GetSkin();

View file

@ -489,7 +489,7 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu
if (CurrentState != NULL) if (CurrentState != NULL)
{ {
int skin = player->userinfo.GetSkin(); int skin = player->userinfo.GetSkin();
const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? ((APlayerPawn*)GetDefaultByType(player->MorphedPlayerClass))->Face.GetChars() : skins[skin].face); const char *skin_face = (stateflags & FMugShot::CUSTOM) ? nullptr : (player->morphTics ? ((APlayerPawn*)GetDefaultByType(player->MorphedPlayerClass))->Face.GetChars() : Skins[skin].Face.GetChars());
return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle); return CurrentState->GetCurrentFrameTexture(default_face, skin_face, level, angle);
} }
return NULL; return NULL;

View file

@ -593,7 +593,7 @@ void DIntermissionScreenCast::Drawer ()
if (!(mDefaults->flags4 & MF4_NOSKIN) && if (!(mDefaults->flags4 & MF4_NOSKIN) &&
mDefaults->SpawnState != NULL && caststate->sprite == mDefaults->SpawnState->sprite && mDefaults->SpawnState != NULL && caststate->sprite == mDefaults->SpawnState->sprite &&
mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)) && mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)) &&
skins != NULL) Skins.Size() > 0)
{ {
// Only use the skin sprite if this class has not been removed from the // Only use the skin sprite if this class has not been removed from the
// PlayerClasses list. // PlayerClasses list.
@ -601,7 +601,7 @@ void DIntermissionScreenCast::Drawer ()
{ {
if (PlayerClasses[i].Type == mClass) if (PlayerClasses[i].Type == mClass)
{ {
FPlayerSkin *skin = &skins[players[consoleplayer].userinfo.GetSkin()]; FPlayerSkin *skin = &Skins[players[consoleplayer].userinfo.GetSkin()];
castsprite = skin->sprite; castsprite = skin->sprite;
if (!(mDefaults->flags4 & MF4_NOSKIN)) if (!(mDefaults->flags4 & MF4_NOSKIN))

View file

@ -260,9 +260,9 @@ void DPlayerMenu::UpdateTranslation()
if (PlayerClass != NULL) if (PlayerClass != NULL)
{ {
PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0])); PlayerSkin = R_FindSkin (Skins[PlayerSkin].Name, int(PlayerClass - &PlayerClasses[0]));
R_GetPlayerTranslation(PlayerColor, GetColorSet(PlayerClass->Type, PlayerColorset), R_GetPlayerTranslation(PlayerColor, GetColorSet(PlayerClass->Type, PlayerColorset),
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); &Skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
} }
} }
@ -368,12 +368,12 @@ void DPlayerMenu::UpdateSkins()
else else
{ {
PlayerSkins.Clear(); PlayerSkins.Clear();
for(int i=0;i<(int)numskins; i++) for (unsigned i = 0; i < Skins.Size(); i++)
{ {
if (PlayerClass->CheckSkin(i)) if (PlayerClass->CheckSkin(i))
{ {
int j = PlayerSkins.Push(i); int j = PlayerSkins.Push(i);
li->SetString(j, skins[i].name); li->SetString(j, Skins[i].Name);
if (players[consoleplayer].userinfo.GetSkin() == i) if (players[consoleplayer].userinfo.GetSkin() == i)
{ {
sel = j; sel = j;

View file

@ -3919,7 +3919,7 @@ DEFINE_ACTION_FUNCTION(AActor, PlayerSkinCheck)
PARAM_SELF_PROLOGUE(AActor); PARAM_SELF_PROLOGUE(AActor);
ACTION_RETURN_BOOL(self->player != NULL && ACTION_RETURN_BOOL(self->player != NULL &&
skins[self->player->userinfo.GetSkin()].othergame); Skins[self->player->userinfo.GetSkin()].othergame);
} }
// [KS] *** Start of my modifications *** // [KS] *** Start of my modifications ***

View file

@ -522,7 +522,7 @@ void AActor::PostSerialize()
!(flags4 & MF4_NOSKIN) && !(flags4 & MF4_NOSKIN) &&
state->sprite == GetDefaultByType(player->cls)->SpawnState->sprite) state->sprite == GetDefaultByType(player->cls)->SpawnState->sprite)
{ // Give player back the skin { // Give player back the skin
sprite = skins[player->userinfo.GetSkin()].sprite; sprite = Skins[player->userinfo.GetSkin()].sprite;
} }
if (Speed == 0) if (Speed == 0)
{ {
@ -666,9 +666,9 @@ bool AActor::SetState (FState *newstate, bool nofunction)
// for Dehacked, I would move sprite changing out of the states // for Dehacked, I would move sprite changing out of the states
// altogether, since actors rarely change their sprites after // altogether, since actors rarely change their sprites after
// spawning. // spawning.
if (player != NULL && skins != NULL) if (player != NULL && Skins.Size() > 0)
{ {
sprite = skins[player->userinfo.GetSkin()].sprite; sprite = Skins[player->userinfo.GetSkin()].sprite;
} }
else if (newsprite != prevsprite) else if (newsprite != prevsprite)
{ {
@ -5398,7 +5398,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
} }
// [GRB] Reset skin // [GRB] Reset skin
p->userinfo.SkinNumChanged(R_FindSkin (skins[p->userinfo.GetSkin()].name, p->CurrentPlayerClass)); p->userinfo.SkinNumChanged(R_FindSkin (Skins[p->userinfo.GetSkin()].Name, p->CurrentPlayerClass));
if (!(mobj->flags2 & MF2_DONTTRANSLATE)) if (!(mobj->flags2 & MF2_DONTTRANSLATE))
{ {
@ -5416,7 +5416,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
// [RH] Set player sprite based on skin // [RH] Set player sprite based on skin
if (!(mobj->flags4 & MF4_NOSKIN)) if (!(mobj->flags4 & MF4_NOSKIN))
{ {
mobj->sprite = skins[p->userinfo.GetSkin()].sprite; mobj->sprite = Skins[p->userinfo.GetSkin()].sprite;
} }
p->DesiredFOV = p->FOV = 90.f; p->DesiredFOV = p->FOV = 90.f;

View file

@ -837,7 +837,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name)
} }
// Validate the skin // Validate the skin
dst->userinfo.SkinNumChanged(R_FindSkin(skins[dst->userinfo.GetSkin()].name, dst->CurrentPlayerClass)); dst->userinfo.SkinNumChanged(R_FindSkin(Skins[dst->userinfo.GetSkin()].Name, dst->CurrentPlayerClass));
// Make sure the player pawn points to the proper player struct. // Make sure the player pawn points to the proper player struct.
if (dst->mo != nullptr) if (dst->mo != nullptr)

View file

@ -4203,7 +4203,6 @@ static void P_Shutdown ()
{ {
// [ZZ] delete global event handlers // [ZZ] delete global event handlers
E_Shutdown(false); E_Shutdown(false);
R_DeinitSpriteData ();
P_DeinitKeyMessages (); P_DeinitKeyMessages ();
P_FreeLevelData (); P_FreeLevelData ();
P_FreeExtraLevelData (); P_FreeExtraLevelData ();

View file

@ -74,9 +74,9 @@ DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture)
} }
else else
{ {
sprframe = &SpriteFrames[sprites[skins[skin].sprite].spriteframes + self->GetFrame()]; sprframe = &SpriteFrames[sprites[Skins[skin].sprite].spriteframes + self->GetFrame()];
scalex = skins[skin].Scale.X; scalex = Skins[skin].Scale.X;
scaley = skins[skin].Scale.Y; scaley = Skins[skin].Scale.Y;
} }
if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex()); if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex());
if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation))); if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation)));

View file

@ -1247,9 +1247,9 @@ const char *APlayerPawn::GetSoundClass() const
if (player != NULL && if (player != NULL &&
(player->mo == NULL || !(player->mo->flags4 &MF4_NOSKIN)) && (player->mo == NULL || !(player->mo->flags4 &MF4_NOSKIN)) &&
(unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () && (unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () &&
(size_t)player->userinfo.GetSkin() < numskins) (unsigned)player->userinfo.GetSkin() < Skins.Size())
{ {
return skins[player->userinfo.GetSkin()].name; return Skins[player->userinfo.GetSkin()].Name.GetChars();
} }
return SoundClass != NAME_None? SoundClass.GetChars() : "player"; return SoundClass != NAME_None? SoundClass.GetChars() : "player";
@ -1801,8 +1801,8 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale)
{ {
// Convert from default scale to skin scale. // Convert from default scale to skin scale.
DVector2 defscale = actor->GetDefault()->Scale; DVector2 defscale = actor->GetDefault()->Scale;
scale.X *= skins[player->userinfo.GetSkin()].Scale.X / defscale.X; scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / defscale.X;
scale.Y *= skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y; scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y;
} }
// Set the crouch sprite? // Set the crouch sprite?
@ -1813,10 +1813,10 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale)
crouchspriteno = player->mo->crouchsprite; crouchspriteno = player->mo->crouchsprite;
} }
else if (!(actor->flags4 & MF4_NOSKIN) && else if (!(actor->flags4 & MF4_NOSKIN) &&
(spritenum == skins[player->userinfo.GetSkin()].sprite || (spritenum == Skins[player->userinfo.GetSkin()].sprite ||
spritenum == skins[player->userinfo.GetSkin()].crouchsprite)) spritenum == Skins[player->userinfo.GetSkin()].crouchsprite))
{ {
crouchspriteno = skins[player->userinfo.GetSkin()].crouchsprite; crouchspriteno = Skins[player->userinfo.GetSkin()].crouchsprite;
} }
else else
{ // no sprite -> squash the existing one { // no sprite -> squash the existing one

View file

@ -1171,7 +1171,7 @@ void R_BuildPlayerTranslation (int player)
D_GetPlayerColor (player, &h, &s, &v, &colorset); D_GetPlayerColor (player, &h, &s, &v, &colorset);
R_CreatePlayerTranslation (h, s, v, colorset, R_CreatePlayerTranslation (h, s, v, colorset,
&skins[players[player].userinfo.GetSkin()], &Skins[players[player].userinfo.GetSkin()],
translationtables[TRANSLATION_Players][player], translationtables[TRANSLATION_Players][player],
translationtables[TRANSLATION_PlayersExtra][player], translationtables[TRANSLATION_PlayersExtra][player],
translationtables[TRANSLATION_RainPillar][player] translationtables[TRANSLATION_RainPillar][player]
@ -1218,9 +1218,9 @@ DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation)
if (cls != nullptr) if (cls != nullptr)
{ {
PlayerSkin = R_FindSkin(skins[PlayerSkin].name, int(cls - &PlayerClasses[0])); PlayerSkin = R_FindSkin(Skins[PlayerSkin].Name, int(cls - &PlayerClasses[0]));
R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset), R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset),
&skins[PlayerSkin], translationtables[tgroup][tnum]); &Skins[PlayerSkin], translationtables[tgroup][tnum]);
} }
ACTION_RETURN_BOOL(true); ACTION_RETURN_BOOL(true);
} }

View file

@ -30,8 +30,7 @@ struct spriteframewithrotate : public spriteframe_t
// [RH] skin globals // [RH] skin globals
FPlayerSkin *skins; TArray<FPlayerSkin> Skins;
size_t numskins;
BYTE OtherGameSkinRemap[256]; BYTE OtherGameSkinRemap[256];
PalEntry OtherGameSkinPalette[256]; PalEntry OtherGameSkinPalette[256];
@ -512,7 +511,7 @@ void R_InitSkins (void)
int sndlumps[NUMSKINSOUNDS]; int sndlumps[NUMSKINSOUNDS];
char key[65]; char key[65];
DWORD intname, crouchname; DWORD intname, crouchname;
size_t i; unsigned i;
int j, k, base; int j, k, base;
int lastlump; int lastlump;
int aliasid; int aliasid;
@ -538,7 +537,7 @@ void R_InitSkins (void)
i++; i++;
for (j = 0; j < NUMSKINSOUNDS; j++) for (j = 0; j < NUMSKINSOUNDS; j++)
sndlumps[j] = -1; sndlumps[j] = -1;
skins[i].namespc = Wads.GetLumpNamespace (base); Skins[i].namespc = Wads.GetLumpNamespace (base);
FScanner sc(base); FScanner sc(base);
intname = 0; intname = 0;
@ -560,14 +559,13 @@ void R_InitSkins (void)
sc.GetString (); sc.GetString ();
if (0 == stricmp (key, "name")) if (0 == stricmp (key, "name"))
{ {
strncpy (skins[i].name, sc.String, 16); Skins[i].Name = sc.String;
for (j = 0; (size_t)j < i; j++) for (j = 0; (unsigned)j < i; j++)
{ {
if (stricmp (skins[i].name, skins[j].name) == 0) if (Skins[i].Name.CompareNoCase(Skins[j].Name) == 0)
{ {
mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i); Skins[i].Name.Format("skin%u", i);
Printf (PRINT_BOLD, "Skin %s duplicated as %s\n", Printf (PRINT_BOLD, "Skin %s duplicated as %s\n", Skins[j].Name.GetChars(), Skins[i].Name.GetChars());
skins[j].name, skins[i].name);
break; break;
} }
} }
@ -586,18 +584,16 @@ void R_InitSkins (void)
} }
else if (0 == stricmp (key, "face")) else if (0 == stricmp (key, "face"))
{ {
for (j = 2; j >= 0; j--) Skins[i].Face = FString(sc.String, 3);
skins[i].face[j] = toupper (sc.String[j]);
skins[i].face[3] = '\0';
} }
else if (0 == stricmp (key, "gender")) else if (0 == stricmp (key, "gender"))
{ {
skins[i].gender = D_GenderToInt (sc.String); Skins[i].gender = D_GenderToInt (sc.String);
} }
else if (0 == stricmp (key, "scale")) else if (0 == stricmp (key, "scale"))
{ {
skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.); Skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.);
skins[i].Scale.Y = skins[i].Scale.X; Skins[i].Scale.Y = Skins[i].Scale.X;
} }
else if (0 == stricmp (key, "game")) else if (0 == stricmp (key, "game"))
{ {
@ -615,7 +611,7 @@ void R_InitSkins (void)
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.gametype & GAME_DoomChex)
{ {
transtype = PClass::FindActor(NAME_HereticPlayer); transtype = PClass::FindActor(NAME_HereticPlayer);
skins[i].othergame = true; Skins[i].othergame = true;
} }
else if (gameinfo.gametype != GAME_Heretic) else if (gameinfo.gametype != GAME_Heretic)
{ {
@ -634,7 +630,7 @@ void R_InitSkins (void)
if (gameinfo.gametype == GAME_Heretic) if (gameinfo.gametype == GAME_Heretic)
{ {
transtype = PClass::FindActor(NAME_DoomPlayer); transtype = PClass::FindActor(NAME_DoomPlayer);
skins[i].othergame = true; Skins[i].othergame = true;
} }
else if (!(gameinfo.gametype & GAME_DoomChex)) else if (!(gameinfo.gametype & GAME_DoomChex))
{ {
@ -659,7 +655,7 @@ void R_InitSkins (void)
} }
else if (key[0] == '*') else if (key[0] == '*')
{ // Player sound replacment (ZDoom extension) { // Player sound replacment (ZDoom extension)
int lump = Wads.CheckNumForName (sc.String, skins[i].namespc); int lump = Wads.CheckNumForName (sc.String, Skins[i].namespc);
if (lump == -1) if (lump == -1)
{ {
lump = Wads.CheckNumForFullName (sc.String, true, ns_sounds); lump = Wads.CheckNumForFullName (sc.String, true, ns_sounds);
@ -668,11 +664,11 @@ void R_InitSkins (void)
{ {
if (stricmp (key, "*pain") == 0) if (stricmp (key, "*pain") == 0)
{ // Replace all pain sounds in one go { // Replace all pain sounds in one go
aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender, aliasid = S_AddPlayerSound (Skins[i].Name, Skins[i].gender,
playersoundrefs[0], lump, true); playersoundrefs[0], lump, true);
for (int l = 3; l > 0; --l) for (int l = 3; l > 0; --l)
{ {
S_AddPlayerSoundExisting (skins[i].name, skins[i].gender, S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender,
playersoundrefs[l], aliasid, true); playersoundrefs[l], aliasid, true);
} }
} }
@ -681,7 +677,7 @@ void R_InitSkins (void)
int sndref = S_FindSoundNoHash (key); int sndref = S_FindSoundNoHash (key);
if (sndref != 0) if (sndref != 0)
{ {
S_AddPlayerSound (skins[i].name, skins[i].gender, sndref, lump, true); S_AddPlayerSound (Skins[i].Name, Skins[i].gender, sndref, lump, true);
} }
} }
} }
@ -692,7 +688,7 @@ void R_InitSkins (void)
{ {
if (stricmp (key, skinsoundnames[j][0]) == 0) if (stricmp (key, skinsoundnames[j][0]) == 0)
{ {
sndlumps[j] = Wads.CheckNumForName (sc.String, skins[i].namespc); sndlumps[j] = Wads.CheckNumForName (sc.String, Skins[i].namespc);
if (sndlumps[j] == -1) if (sndlumps[j] == -1)
{ // Replacement not found, try finding it in the global namespace { // Replacement not found, try finding it in the global namespace
sndlumps[j] = Wads.CheckNumForFullName (sc.String, true, ns_sounds); sndlumps[j] = Wads.CheckNumForFullName (sc.String, true, ns_sounds);
@ -715,7 +711,7 @@ void R_InitSkins (void)
{ {
basetype = PClass::FindActor(NAME_HereticPlayer); basetype = PClass::FindActor(NAME_HereticPlayer);
transtype = PClass::FindActor(NAME_DoomPlayer); transtype = PClass::FindActor(NAME_DoomPlayer);
skins[i].othergame = true; Skins[i].othergame = true;
} }
else else
{ {
@ -728,8 +724,8 @@ void R_InitSkins (void)
auto transdef = ((APlayerPawn*)GetDefaultByType(transtype)); auto transdef = ((APlayerPawn*)GetDefaultByType(transtype));
auto basedef = ((APlayerPawn*)GetDefaultByType(basetype)); auto basedef = ((APlayerPawn*)GetDefaultByType(basetype));
skins[i].range0start = transdef->ColorRangeStart; Skins[i].range0start = transdef->ColorRangeStart;
skins[i].range0end = transdef->ColorRangeEnd; Skins[i].range0end = transdef->ColorRangeEnd;
remove = true; remove = true;
for (j = 0; j < (int)PlayerClasses.Size (); j++) for (j = 0; j < (int)PlayerClasses.Size (); j++)
@ -750,8 +746,8 @@ void R_InitSkins (void)
if (!remove) if (!remove)
{ {
if (skins[i].name[0] == 0) if (Skins[i].Name.IsEmpty())
mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i); Skins[i].Name.Format("skin%u", i);
// Now collect the sprite frames for this skin. If the sprite name was not // Now collect the sprite frames for this skin. If the sprite name was not
// specified, use whatever immediately follows the specifier lump. // specified, use whatever immediately follows the specifier lump.
@ -783,7 +779,7 @@ void R_InitSkins (void)
} }
else else
{ {
skins[i].crouchsprite = -1; Skins[i].crouchsprite = -1;
break; break;
} }
} }
@ -806,7 +802,7 @@ void R_InitSkins (void)
if (spr == 0 && maxframe <= 0) if (spr == 0 && maxframe <= 0)
{ {
Printf (PRINT_BOLD, "Skin %s (#%d) has no frames. Removing.\n", skins[i].name, (int)i); Printf (PRINT_BOLD, "Skin %s (#%u) has no frames. Removing.\n", Skins[i].Name, i);
remove = true; remove = true;
break; break;
} }
@ -814,16 +810,18 @@ void R_InitSkins (void)
Wads.GetLumpName (temp.name, base+1); Wads.GetLumpName (temp.name, base+1);
temp.name[4] = 0; temp.name[4] = 0;
int sprno = (int)sprites.Push (temp); int sprno = (int)sprites.Push (temp);
if (spr==0) skins[i].sprite = sprno; if (spr==0) Skins[i].sprite = sprno;
else skins[i].crouchsprite = sprno; else Skins[i].crouchsprite = sprno;
R_InstallSprite (sprno, sprtemp, maxframe); R_InstallSprite (sprno, sprtemp, maxframe);
} }
} }
if (remove) if (remove)
{ {
if (i < numskins-1) if (i < Skins.Size() - 1)
memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1)); {
Skins.Delete(i);
}
i--; i--;
continue; continue;
} }
@ -836,25 +834,25 @@ void R_InitSkins (void)
{ {
if (j == 0 || sndlumps[j] != sndlumps[j-1]) if (j == 0 || sndlumps[j] != sndlumps[j-1])
{ {
aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender, aliasid = S_AddPlayerSound (Skins[i].Name, Skins[i].gender,
playersoundrefs[j], sndlumps[j], true); playersoundrefs[j], sndlumps[j], true);
} }
else else
{ {
S_AddPlayerSoundExisting (skins[i].name, skins[i].gender, S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender,
playersoundrefs[j], aliasid, true); playersoundrefs[j], aliasid, true);
} }
} }
} }
// Make sure face prefix is a full 3 chars // Make sure face prefix is a full 3 chars
if (skins[i].face[1] == 0 || skins[i].face[2] == 0) if (Skins[i].Face.Len() < 3)
{ {
skins[i].face[0] = 0; Skins[i].Face = "";
} }
} }
if (numskins > PlayerClasses.Size ()) if (Skins.Size() > PlayerClasses.Size ())
{ // The sound table may have changed, so rehash it. { // The sound table may have changed, so rehash it.
S_HashSounds (); S_HashSounds ();
S_ShrinkPlayerSoundLists (); S_ShrinkPlayerSoundLists ();
@ -869,9 +867,9 @@ int R_FindSkin (const char *name, int pclass)
return pclass; return pclass;
} }
for (unsigned i = PlayerClasses.Size(); i < numskins; i++) for (unsigned i = PlayerClasses.Size(); i < Skins.Size(); i++)
{ {
if (strnicmp (skins[i].name, name, 16) == 0) if (Skins[i].Name.CompareNoCase(name) == 0)
{ {
if (PlayerClasses[pclass].CheckSkin (i)) if (PlayerClasses[pclass].CheckSkin (i))
return i; return i;
@ -887,8 +885,8 @@ CCMD (skins)
{ {
int i; int i;
for (i = PlayerClasses.Size ()-1; i < (int)numskins; i++) for (i = PlayerClasses.Size() - 1; i < (int)Skins.Size(); i++)
Printf ("% 3d %s\n", i-PlayerClasses.Size ()+1, skins[i].name); Printf("% 3d %s\n", i - PlayerClasses.Size() + 1, Skins[i].Name.GetChars());
} }
@ -914,6 +912,7 @@ void R_InitSprites ()
{ {
int lump, lastlump; int lump, lastlump;
unsigned int i, j; unsigned int i, j;
unsigned numskins;
// [RH] Create a standard translation to map skins between Heretic and Doom // [RH] Create a standard translation to map skins between Heretic and Doom
if (gameinfo.gametype == GAME_DoomChex) if (gameinfo.gametype == GAME_DoomChex)
@ -934,15 +933,15 @@ void R_InitSprites ()
} }
// [RH] Do some preliminary setup // [RH] Do some preliminary setup
if (skins != NULL) delete [] skins; Skins.Clear();
skins = new FPlayerSkin[numskins]; Skins.Resize(numskins);
memset (skins, 0, sizeof(*skins) * numskins);
for (i = 0; i < numskins; i++) for (i = 0; i < numskins; i++)
{ // Assume Doom skin by default { // Assume Doom skin by default
auto type = ((APlayerPawn*)GetDefaultByType(PlayerClasses[0].Type)); auto type = ((APlayerPawn*)GetDefaultByType(PlayerClasses[0].Type));
skins[i].range0start = type->ColorRangeStart; Skins[i].range0start = type->ColorRangeStart;
skins[i].range0end = type->ColorRangeEnd; Skins[i].range0end = type->ColorRangeEnd;
skins[i].Scale = type->Scale; Skins[i].Scale = type->Scale;
} }
R_InitSpriteDefs (); R_InitSpriteDefs ();
@ -956,33 +955,30 @@ void R_InitSprites ()
{ {
auto basetype = ((APlayerPawn*)GetDefaultByType(PlayerClasses[i].Type)); auto basetype = ((APlayerPawn*)GetDefaultByType(PlayerClasses[i].Type));
strcpy (skins[i].name, "Base"); Skins[i].Name = "Base";
if (basetype->Face == NAME_None) if (basetype->Face == NAME_None)
{ {
skins[i].face[0] = 'S'; Skins[i].Face = "STF";
skins[i].face[1] = 'T';
skins[i].face[2] = 'F';
skins[i].face[3] = '\0';
} }
else else
{ {
strcpy(skins[i].face, basetype->Face); Skins[i].Face = basetype->Face;
} }
skins[i].range0start = basetype->ColorRangeStart; Skins[i].range0start = basetype->ColorRangeStart;
skins[i].range0end = basetype->ColorRangeEnd; Skins[i].range0end = basetype->ColorRangeEnd;
skins[i].Scale = basetype->Scale; Skins[i].Scale = basetype->Scale;
skins[i].sprite = basetype->SpawnState->sprite; Skins[i].sprite = basetype->SpawnState->sprite;
skins[i].namespc = ns_global; Skins[i].namespc = ns_global;
PlayerClasses[i].Skins.Push (i); PlayerClasses[i].Skins.Push (i);
if (memcmp (sprites[skins[i].sprite].name, "PLAY", 4) == 0) if (memcmp (sprites[Skins[i].sprite].name, "PLAY", 4) == 0)
{ {
for (j = 0; j < sprites.Size (); j++) for (j = 0; j < sprites.Size (); j++)
{ {
if (memcmp (sprites[j].name, deh.PlayerSprite, 4) == 0) if (memcmp (sprites[j].name, deh.PlayerSprite, 4) == 0)
{ {
skins[i].sprite = (int)j; Skins[i].sprite = (int)j;
break; break;
} }
} }
@ -995,12 +991,14 @@ void R_InitSprites ()
gl_InitModels(); gl_InitModels();
} }
void R_DeinitSpriteData()
{ DEFINE_FIELD(FPlayerSkin, Name);
// Free skins DEFINE_FIELD(FPlayerSkin, Face);
if (skins != NULL) DEFINE_FIELD(FPlayerSkin, gender);
{ DEFINE_FIELD(FPlayerSkin, range0start);
delete[] skins; DEFINE_FIELD(FPlayerSkin, range0end);
skins = NULL; DEFINE_FIELD(FPlayerSkin, othergame);
} DEFINE_FIELD(FPlayerSkin, Scale);
} DEFINE_FIELD(FPlayerSkin, sprite);
DEFINE_FIELD(FPlayerSkin, crouchsprite);
DEFINE_FIELD(FPlayerSkin, namespc);

View file

@ -47,25 +47,23 @@ extern TArray<spriteframe_t> SpriteFrames;
class FPlayerSkin class FPlayerSkin
{ {
public: public:
char name[17]; // 16 chars + NULL FString Name;
char face[4]; // 3 chars ([MH] + NULL so can use as a C string) FString Face;
BYTE gender; // This skin's gender (not really used) BYTE gender = 0; // This skin's gender (not really used)
BYTE range0start; BYTE range0start = 0;
BYTE range0end; BYTE range0end = 0;
bool othergame; // [GRB] bool othergame = 0; // [GRB]
DVector2 Scale; DVector2 Scale = { 1, 1 };
int sprite; int sprite = 0;
int crouchsprite; int crouchsprite = 0;
int namespc; // namespace for this skin int namespc = 0; // namespace for this skin
}; };
extern size_t numskins; // [RH] extern TArray<FPlayerSkin> Skins;
extern FPlayerSkin * skins; // [RH]
extern BYTE OtherGameSkinRemap[256]; extern BYTE OtherGameSkinRemap[256];
extern PalEntry OtherGameSkinPalette[256]; extern PalEntry OtherGameSkinPalette[256];
void R_InitSprites (); void R_InitSprites ();
void R_DeinitSpriteData ();
#endif #endif

View file

@ -57,6 +57,7 @@
#include "v_video.h" #include "v_video.h"
#include "c_bind.h" #include "c_bind.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "r_data/sprites.h"
static TArray<FPropertyInfo*> properties; static TArray<FPropertyInfo*> properties;
static TArray<AFuncDesc> AFTable; static TArray<AFuncDesc> AFTable;
@ -759,6 +760,10 @@ void InitThingdef()
playerclassstruct->Size = sizeof(FPlayerClass); playerclassstruct->Size = sizeof(FPlayerClass);
playerclassstruct->Align = alignof(FPlayerClass); playerclassstruct->Align = alignof(FPlayerClass);
auto playerskinstruct = NewNativeStruct("PlayerSkin", nullptr);
playerskinstruct->Size = sizeof(FPlayerSkin);
playerskinstruct->Align = alignof(FPlayerSkin);
// set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well... // set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well...
// As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up. // As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up.
sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native); sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native);
@ -798,6 +803,10 @@ void InitThingdef()
PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses); PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses);
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf); Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf);
auto plrskn = NewPointer(NewResizableArray(playerskinstruct), false);
PField *plrsknf = new PField("PlayerSkins", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&Skins);
Namespaces.GlobalNamespace->Symbols.AddSymbol(plrsknf);
auto bindcls = NewNativeStruct("KeyBindings", nullptr); auto bindcls = NewNativeStruct("KeyBindings", nullptr);
PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings); PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings);
Namespaces.GlobalNamespace->Symbols.AddSymbol(binding); Namespaces.GlobalNamespace->Symbols.AddSymbol(binding);

View file

@ -326,3 +326,17 @@ struct PlayerClass native
native bool CheckSkin(int skin); native bool CheckSkin(int skin);
} }
struct PlayerSkin native
{
native readonly String Name;
native readonly String Face;
native readonly uint8 gender;
native readonly uint8 range0start;
native readonly uint8 range0end;
native readonly bool othergame;
native readonly Vector2 Scale;
native readonly int sprite;
native readonly int crouchsprite;
native readonly int namespc;
};