From 498da825a514ea2ba2b9916d8305ba874ad46ce2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 17 Feb 2017 21:51:23 +0100 Subject: [PATCH] - made the Skins array scripting friendly and exported it. --- src/d_netinfo.cpp | 8 +- src/g_game.cpp | 2 +- src/g_shared/a_morph.cpp | 2 +- src/g_statusbar/sbar_mugshot.cpp | 2 +- src/intermission/intermission.cpp | 4 +- src/menu/playermenu.cpp | 8 +- src/p_actionfunctions.cpp | 2 +- src/p_mobj.cpp | 10 +- src/p_saveg.cpp | 2 +- src/p_setup.cpp | 1 - src/p_states.cpp | 6 +- src/p_user.cpp | 14 +-- src/r_data/r_translate.cpp | 6 +- src/r_data/sprites.cpp | 140 ++++++++++++------------ src/r_data/sprites.h | 24 ++-- src/scripting/thingdef_data.cpp | 9 ++ wadsrc/static/zscript/shared/player.txt | 14 +++ 17 files changed, 136 insertions(+), 118 deletions(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 62beb5460..8a856b44b 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -729,7 +729,7 @@ void D_WriteUserInfoStrings (int pnum, BYTE **stream, bool compact) break; 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; default: @@ -828,7 +828,7 @@ void D_ReadUserInfoStrings (int pnum, BYTE **stream, bool update) players[pnum].mo->state->sprite == GetDefaultByType (players[pnum].cls)->SpawnState->sprite) { // 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 @@ -898,7 +898,7 @@ void WriteUserInfo(FSerializer &arc, userinfo_t &info) switch (pair->Key.GetIndex()) { case NAME_Skin: - string = skins[info.GetSkin()].name; + string = Skins[info.GetSkin()].Name; break; case NAME_PlayerClass: @@ -986,7 +986,7 @@ CCMD (playerinfo) // Print special info 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", "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", "PlayerClass", ui->GetPlayerClassNum() == -1 ? "Random" : ui->GetPlayerClassType()->DisplayName.GetChars(), diff --git a/src/g_game.cpp b/src/g_game.cpp index 627d51f04..dcd36b041 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1695,7 +1695,7 @@ static void G_QueueBody (AActor *body) { // Apply skin's scale to actor's scale, it will be lost otherwise 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.Y *= skin.Scale.Y / defaultActor->Scale.Y; diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 359e8a174..1ae3c4b5e 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -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 // or else the base skin for the player class. if ((unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () && - (size_t)player->userinfo.GetSkin() < numskins) + (unsigned)player->userinfo.GetSkin() < Skins.Size()) { skinindex = player->userinfo.GetSkin(); diff --git a/src/g_statusbar/sbar_mugshot.cpp b/src/g_statusbar/sbar_mugshot.cpp index d24298b94..18e0fec42 100644 --- a/src/g_statusbar/sbar_mugshot.cpp +++ b/src/g_statusbar/sbar_mugshot.cpp @@ -489,7 +489,7 @@ FTexture *FMugShot::GetFace(player_t *player, const char *default_face, int accu if (CurrentState != NULL) { 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 NULL; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 8310914be..27532e7e9 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -593,7 +593,7 @@ void DIntermissionScreenCast::Drawer () if (!(mDefaults->flags4 & MF4_NOSKIN) && mDefaults->SpawnState != NULL && caststate->sprite == mDefaults->SpawnState->sprite && mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn)) && - skins != NULL) + Skins.Size() > 0) { // Only use the skin sprite if this class has not been removed from the // PlayerClasses list. @@ -601,7 +601,7 @@ void DIntermissionScreenCast::Drawer () { if (PlayerClasses[i].Type == mClass) { - FPlayerSkin *skin = &skins[players[consoleplayer].userinfo.GetSkin()]; + FPlayerSkin *skin = &Skins[players[consoleplayer].userinfo.GetSkin()]; castsprite = skin->sprite; if (!(mDefaults->flags4 & MF4_NOSKIN)) diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index daa18d57b..ec2d76a5c 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -260,9 +260,9 @@ void DPlayerMenu::UpdateTranslation() 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), - &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); + &Skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } } @@ -368,12 +368,12 @@ void DPlayerMenu::UpdateSkins() else { PlayerSkins.Clear(); - for(int i=0;i<(int)numskins; i++) + for (unsigned i = 0; i < Skins.Size(); i++) { if (PlayerClass->CheckSkin(i)) { int j = PlayerSkins.Push(i); - li->SetString(j, skins[i].name); + li->SetString(j, Skins[i].Name); if (players[consoleplayer].userinfo.GetSkin() == i) { sel = j; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 15e82a56c..8a062cd18 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -3919,7 +3919,7 @@ DEFINE_ACTION_FUNCTION(AActor, PlayerSkinCheck) PARAM_SELF_PROLOGUE(AActor); ACTION_RETURN_BOOL(self->player != NULL && - skins[self->player->userinfo.GetSkin()].othergame); + Skins[self->player->userinfo.GetSkin()].othergame); } // [KS] *** Start of my modifications *** diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5bf611800..2508f50f2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -522,7 +522,7 @@ void AActor::PostSerialize() !(flags4 & MF4_NOSKIN) && state->sprite == GetDefaultByType(player->cls)->SpawnState->sprite) { // Give player back the skin - sprite = skins[player->userinfo.GetSkin()].sprite; + sprite = Skins[player->userinfo.GetSkin()].sprite; } 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 // altogether, since actors rarely change their sprites after // 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) { @@ -5398,7 +5398,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) } // [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)) { @@ -5416,7 +5416,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) // [RH] Set player sprite based on skin 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; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index a3208598d..8f06b7809 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -837,7 +837,7 @@ void CopyPlayer(player_t *dst, player_t *src, const char *name) } // 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. if (dst->mo != nullptr) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 875d3fbc0..ac7faea76 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -4203,7 +4203,6 @@ static void P_Shutdown () { // [ZZ] delete global event handlers E_Shutdown(false); - R_DeinitSpriteData (); P_DeinitKeyMessages (); P_FreeLevelData (); P_FreeExtraLevelData (); diff --git a/src/p_states.cpp b/src/p_states.cpp index 3602cfc81..d6f43aabe 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -74,9 +74,9 @@ DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture) } else { - sprframe = &SpriteFrames[sprites[skins[skin].sprite].spriteframes + self->GetFrame()]; - scalex = skins[skin].Scale.X; - scaley = skins[skin].Scale.Y; + sprframe = &SpriteFrames[sprites[Skins[skin].sprite].spriteframes + self->GetFrame()]; + scalex = Skins[skin].Scale.X; + scaley = Skins[skin].Scale.Y; } if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex()); if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation))); diff --git a/src/p_user.cpp b/src/p_user.cpp index 5816a9689..bd6b2be4e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1247,9 +1247,9 @@ const char *APlayerPawn::GetSoundClass() const if (player != NULL && (player->mo == NULL || !(player->mo->flags4 &MF4_NOSKIN)) && (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"; @@ -1801,8 +1801,8 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale) { // Convert from default scale to skin scale. DVector2 defscale = actor->GetDefault()->Scale; - scale.X *= skins[player->userinfo.GetSkin()].Scale.X / defscale.X; - scale.Y *= skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y; + scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / defscale.X; + scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y; } // Set the crouch sprite? @@ -1813,10 +1813,10 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale) crouchspriteno = player->mo->crouchsprite; } else if (!(actor->flags4 & MF4_NOSKIN) && - (spritenum == skins[player->userinfo.GetSkin()].sprite || - spritenum == skins[player->userinfo.GetSkin()].crouchsprite)) + (spritenum == Skins[player->userinfo.GetSkin()].sprite || + spritenum == Skins[player->userinfo.GetSkin()].crouchsprite)) { - crouchspriteno = skins[player->userinfo.GetSkin()].crouchsprite; + crouchspriteno = Skins[player->userinfo.GetSkin()].crouchsprite; } else { // no sprite -> squash the existing one diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 0f4d58e6d..fd1bf5d21 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1171,7 +1171,7 @@ void R_BuildPlayerTranslation (int player) D_GetPlayerColor (player, &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_PlayersExtra][player], translationtables[TRANSLATION_RainPillar][player] @@ -1218,9 +1218,9 @@ DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation) 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), - &skins[PlayerSkin], translationtables[tgroup][tnum]); + &Skins[PlayerSkin], translationtables[tgroup][tnum]); } ACTION_RETURN_BOOL(true); } diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index c3f73760d..72199cece 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -30,8 +30,7 @@ struct spriteframewithrotate : public spriteframe_t // [RH] skin globals -FPlayerSkin *skins; -size_t numskins; +TArray Skins; BYTE OtherGameSkinRemap[256]; PalEntry OtherGameSkinPalette[256]; @@ -512,7 +511,7 @@ void R_InitSkins (void) int sndlumps[NUMSKINSOUNDS]; char key[65]; DWORD intname, crouchname; - size_t i; + unsigned i; int j, k, base; int lastlump; int aliasid; @@ -538,7 +537,7 @@ void R_InitSkins (void) i++; for (j = 0; j < NUMSKINSOUNDS; j++) sndlumps[j] = -1; - skins[i].namespc = Wads.GetLumpNamespace (base); + Skins[i].namespc = Wads.GetLumpNamespace (base); FScanner sc(base); intname = 0; @@ -560,14 +559,13 @@ void R_InitSkins (void) sc.GetString (); if (0 == stricmp (key, "name")) { - strncpy (skins[i].name, sc.String, 16); - for (j = 0; (size_t)j < i; j++) + Skins[i].Name = sc.String; + 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); - Printf (PRINT_BOLD, "Skin %s duplicated as %s\n", - skins[j].name, skins[i].name); + Skins[i].Name.Format("skin%u", i); + Printf (PRINT_BOLD, "Skin %s duplicated as %s\n", Skins[j].Name.GetChars(), Skins[i].Name.GetChars()); break; } } @@ -586,18 +584,16 @@ void R_InitSkins (void) } else if (0 == stricmp (key, "face")) { - for (j = 2; j >= 0; j--) - skins[i].face[j] = toupper (sc.String[j]); - skins[i].face[3] = '\0'; + Skins[i].Face = FString(sc.String, 3); } 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")) { - skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.); - skins[i].Scale.Y = skins[i].Scale.X; + Skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.); + Skins[i].Scale.Y = Skins[i].Scale.X; } else if (0 == stricmp (key, "game")) { @@ -615,7 +611,7 @@ void R_InitSkins (void) if (gameinfo.gametype & GAME_DoomChex) { transtype = PClass::FindActor(NAME_HereticPlayer); - skins[i].othergame = true; + Skins[i].othergame = true; } else if (gameinfo.gametype != GAME_Heretic) { @@ -634,7 +630,7 @@ void R_InitSkins (void) if (gameinfo.gametype == GAME_Heretic) { transtype = PClass::FindActor(NAME_DoomPlayer); - skins[i].othergame = true; + Skins[i].othergame = true; } else if (!(gameinfo.gametype & GAME_DoomChex)) { @@ -659,7 +655,7 @@ void R_InitSkins (void) } else if (key[0] == '*') { // 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) { lump = Wads.CheckNumForFullName (sc.String, true, ns_sounds); @@ -668,11 +664,11 @@ void R_InitSkins (void) { if (stricmp (key, "*pain") == 0) { // 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); 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); } } @@ -681,7 +677,7 @@ void R_InitSkins (void) int sndref = S_FindSoundNoHash (key); 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) { - sndlumps[j] = Wads.CheckNumForName (sc.String, skins[i].namespc); + sndlumps[j] = Wads.CheckNumForName (sc.String, Skins[i].namespc); if (sndlumps[j] == -1) { // Replacement not found, try finding it in the global namespace sndlumps[j] = Wads.CheckNumForFullName (sc.String, true, ns_sounds); @@ -715,7 +711,7 @@ void R_InitSkins (void) { basetype = PClass::FindActor(NAME_HereticPlayer); transtype = PClass::FindActor(NAME_DoomPlayer); - skins[i].othergame = true; + Skins[i].othergame = true; } else { @@ -728,8 +724,8 @@ void R_InitSkins (void) auto transdef = ((APlayerPawn*)GetDefaultByType(transtype)); auto basedef = ((APlayerPawn*)GetDefaultByType(basetype)); - skins[i].range0start = transdef->ColorRangeStart; - skins[i].range0end = transdef->ColorRangeEnd; + Skins[i].range0start = transdef->ColorRangeStart; + Skins[i].range0end = transdef->ColorRangeEnd; remove = true; for (j = 0; j < (int)PlayerClasses.Size (); j++) @@ -750,8 +746,8 @@ void R_InitSkins (void) if (!remove) { - if (skins[i].name[0] == 0) - mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i); + if (Skins[i].Name.IsEmpty()) + Skins[i].Name.Format("skin%u", i); // Now collect the sprite frames for this skin. If the sprite name was not // specified, use whatever immediately follows the specifier lump. @@ -783,7 +779,7 @@ void R_InitSkins (void) } else { - skins[i].crouchsprite = -1; + Skins[i].crouchsprite = -1; break; } } @@ -806,7 +802,7 @@ void R_InitSkins (void) 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; break; } @@ -814,16 +810,18 @@ void R_InitSkins (void) Wads.GetLumpName (temp.name, base+1); temp.name[4] = 0; int sprno = (int)sprites.Push (temp); - if (spr==0) skins[i].sprite = sprno; - else skins[i].crouchsprite = sprno; + if (spr==0) Skins[i].sprite = sprno; + else Skins[i].crouchsprite = sprno; R_InstallSprite (sprno, sprtemp, maxframe); } } if (remove) { - if (i < numskins-1) - memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1)); + if (i < Skins.Size() - 1) + { + Skins.Delete(i); + } i--; continue; } @@ -836,25 +834,25 @@ void R_InitSkins (void) { 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); } else { - S_AddPlayerSoundExisting (skins[i].name, skins[i].gender, + S_AddPlayerSoundExisting (Skins[i].Name, Skins[i].gender, playersoundrefs[j], aliasid, true); } } } // 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. S_HashSounds (); S_ShrinkPlayerSoundLists (); @@ -869,9 +867,9 @@ int R_FindSkin (const char *name, int 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)) return i; @@ -887,8 +885,8 @@ CCMD (skins) { int i; - for (i = PlayerClasses.Size ()-1; i < (int)numskins; i++) - Printf ("% 3d %s\n", i-PlayerClasses.Size ()+1, skins[i].name); + for (i = PlayerClasses.Size() - 1; i < (int)Skins.Size(); i++) + Printf("% 3d %s\n", i - PlayerClasses.Size() + 1, Skins[i].Name.GetChars()); } @@ -914,6 +912,7 @@ void R_InitSprites () { int lump, lastlump; unsigned int i, j; + unsigned numskins; // [RH] Create a standard translation to map skins between Heretic and Doom if (gameinfo.gametype == GAME_DoomChex) @@ -934,15 +933,15 @@ void R_InitSprites () } // [RH] Do some preliminary setup - if (skins != NULL) delete [] skins; - skins = new FPlayerSkin[numskins]; - memset (skins, 0, sizeof(*skins) * numskins); + Skins.Clear(); + Skins.Resize(numskins); + for (i = 0; i < numskins; i++) { // Assume Doom skin by default auto type = ((APlayerPawn*)GetDefaultByType(PlayerClasses[0].Type)); - skins[i].range0start = type->ColorRangeStart; - skins[i].range0end = type->ColorRangeEnd; - skins[i].Scale = type->Scale; + Skins[i].range0start = type->ColorRangeStart; + Skins[i].range0end = type->ColorRangeEnd; + Skins[i].Scale = type->Scale; } R_InitSpriteDefs (); @@ -956,33 +955,30 @@ void R_InitSprites () { auto basetype = ((APlayerPawn*)GetDefaultByType(PlayerClasses[i].Type)); - strcpy (skins[i].name, "Base"); + Skins[i].Name = "Base"; if (basetype->Face == NAME_None) { - skins[i].face[0] = 'S'; - skins[i].face[1] = 'T'; - skins[i].face[2] = 'F'; - skins[i].face[3] = '\0'; + Skins[i].Face = "STF"; } else { - strcpy(skins[i].face, basetype->Face); + Skins[i].Face = basetype->Face; } - skins[i].range0start = basetype->ColorRangeStart; - skins[i].range0end = basetype->ColorRangeEnd; - skins[i].Scale = basetype->Scale; - skins[i].sprite = basetype->SpawnState->sprite; - skins[i].namespc = ns_global; + Skins[i].range0start = basetype->ColorRangeStart; + Skins[i].range0end = basetype->ColorRangeEnd; + Skins[i].Scale = basetype->Scale; + Skins[i].sprite = basetype->SpawnState->sprite; + Skins[i].namespc = ns_global; 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++) { if (memcmp (sprites[j].name, deh.PlayerSprite, 4) == 0) { - skins[i].sprite = (int)j; + Skins[i].sprite = (int)j; break; } } @@ -995,12 +991,14 @@ void R_InitSprites () gl_InitModels(); } -void R_DeinitSpriteData() -{ - // Free skins - if (skins != NULL) - { - delete[] skins; - skins = NULL; - } -} + +DEFINE_FIELD(FPlayerSkin, Name); +DEFINE_FIELD(FPlayerSkin, Face); +DEFINE_FIELD(FPlayerSkin, gender); +DEFINE_FIELD(FPlayerSkin, range0start); +DEFINE_FIELD(FPlayerSkin, range0end); +DEFINE_FIELD(FPlayerSkin, othergame); +DEFINE_FIELD(FPlayerSkin, Scale); +DEFINE_FIELD(FPlayerSkin, sprite); +DEFINE_FIELD(FPlayerSkin, crouchsprite); +DEFINE_FIELD(FPlayerSkin, namespc); diff --git a/src/r_data/sprites.h b/src/r_data/sprites.h index d882ee981..9e7d9392e 100644 --- a/src/r_data/sprites.h +++ b/src/r_data/sprites.h @@ -47,25 +47,23 @@ extern TArray SpriteFrames; class FPlayerSkin { public: - char name[17]; // 16 chars + NULL - char face[4]; // 3 chars ([MH] + NULL so can use as a C string) - BYTE gender; // This skin's gender (not really used) - BYTE range0start; - BYTE range0end; - bool othergame; // [GRB] - DVector2 Scale; - int sprite; - int crouchsprite; - int namespc; // namespace for this skin + FString Name; + FString Face; + BYTE gender = 0; // This skin's gender (not really used) + BYTE range0start = 0; + BYTE range0end = 0; + bool othergame = 0; // [GRB] + DVector2 Scale = { 1, 1 }; + int sprite = 0; + int crouchsprite = 0; + int namespc = 0; // namespace for this skin }; -extern size_t numskins; // [RH] -extern FPlayerSkin * skins; // [RH] +extern TArray Skins; extern BYTE OtherGameSkinRemap[256]; extern PalEntry OtherGameSkinPalette[256]; void R_InitSprites (); -void R_DeinitSpriteData (); #endif diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index f257c7c2d..c9679c4b2 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -57,6 +57,7 @@ #include "v_video.h" #include "c_bind.h" #include "menu/menu.h" +#include "r_data/sprites.h" static TArray properties; static TArray AFTable; @@ -759,6 +760,10 @@ void InitThingdef() playerclassstruct->Size = sizeof(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... // 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); @@ -798,6 +803,10 @@ void InitThingdef() PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses); 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); PField *binding = new PField("Bindings", bindcls, VARF_Native | VARF_Static, (intptr_t)&Bindings); Namespaces.GlobalNamespace->Symbols.AddSymbol(binding); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 24bfa51c6..ab3019dcd 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -326,3 +326,17 @@ struct PlayerClass native 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; +};