From 68e9918ed5b3b110bca97567a9000c5d59c38523 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 8 Feb 2017 19:10:11 +0100 Subject: [PATCH] - moved player color sets and pain flashes into global variables. There's simply never enough of them and they are used far too infrequently to justify the hassle of tagging along two TMaps per class. For what they provide, single global lists that handle all player classes at once are fully sufficient. --- src/d_main.cpp | 2 + src/d_netinfo.cpp | 4 +- src/d_player.h | 17 ++++--- src/doomtype.h | 2 + src/g_pch.h | 1 + src/menu/playerdisplay.cpp | 2 +- src/menu/playermenu.cpp | 6 +-- src/p_user.cpp | 73 ++++++++++++++++++++------- src/scripting/thingdef_properties.cpp | 14 ++--- src/v_blend.cpp | 2 +- 10 files changed, 83 insertions(+), 40 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index e91c2ccaa..e0cbcbefa 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2707,6 +2707,8 @@ void D_DoomMain (void) // delete all data that cannot be left until reinitialization V_ClearFonts(); // must clear global font pointers + ColorSets.Clear(); + PainFlashes.Clear(); R_DeinitTranslationTables(); // some tables are initialized from outside the translation code. gameinfo.~gameinfo_t(); new (&gameinfo) gameinfo_t; // Reset gameinfo diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index d3ce8c943..62beb5460 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -156,7 +156,7 @@ int D_PlayerClassToInt (const char *classname) { for (unsigned int i = 0; i < PlayerClasses.Size (); ++i) { - PClassPlayerPawn *type = PlayerClasses[i].Type; + auto type = PlayerClasses[i].Type; if (type->DisplayName.IsNotEmpty() && stricmp(type->DisplayName, classname) == 0) { @@ -180,7 +180,7 @@ void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet if (players[player].mo != NULL) { - colorset = players[player].mo->GetClass()->GetColorSet(info->GetColorSet()); + colorset = GetColorSet(players[player].mo->GetClass(), info->GetColorSet()); } if (colorset != NULL) { diff --git a/src/d_player.h b/src/d_player.h index f6009edec..8a5415bc6 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -66,8 +66,11 @@ struct FPlayerColorSet ExtraRange Extra[6]; }; -typedef TMap FPlayerColorSetMap; -typedef TMap PainFlashList; +typedef TArray> PainFlashList; +typedef TArray> ColorSetList; + +extern PainFlashList PainFlashes; +extern ColorSetList ColorSets; class PClassPlayerPawn : public PClassActor { @@ -76,14 +79,8 @@ protected: public: PClassPlayerPawn(); virtual void DeriveData(PClass *newclass); - void EnumColorSets(TArray *out); - FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); } - void SetPainFlash(FName type, PalEntry color); - bool GetPainFlash(FName type, PalEntry *color) const; FString DisplayName; // Display name (used in menus, etc.) - FPlayerColorSetMap ColorSets; - PainFlashList PainFlashes; }; FString GetPrintableDisplayName(PClassPlayerPawn *cls); @@ -541,12 +538,16 @@ public: // Make sure that a state is properly set after calling this unless // you are 100% sure the context already implies the layer exists. DPSprite *GetPSprite(PSPLayers layer); + + bool GetPainFlash(FName type, PalEntry *color) const; }; // Bookkeeping on players - state. extern player_t players[MAXPLAYERS]; void P_CheckPlayerSprite(AActor *mo, int &spritenum, DVector2 &scale); +void EnumColorSets(PClassActor *pc, TArray *out); +FPlayerColorSet *GetColorSet(PClassActor *pc, int setnum); inline void AActor::SetFriendPlayer(player_t *player) { diff --git a/src/doomtype.h b/src/doomtype.h index 11e4f96e2..c88ec842d 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -41,6 +41,8 @@ #endif #include +#include +#include #include "tarray.h" #include "name.h" #include "zstring.h" diff --git a/src/g_pch.h b/src/g_pch.h index 2c3676f5a..e5653796b 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -20,3 +20,4 @@ #include #include #include +#include diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp index 821c2ea70..ba99aba36 100644 --- a/src/menu/playerdisplay.cpp +++ b/src/menu/playerdisplay.cpp @@ -435,7 +435,7 @@ void DListMenuItemPlayerDisplay::UpdateTranslation() if (mPlayerClass != NULL) { PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(mPlayerClass - &PlayerClasses[0])); - R_GetPlayerTranslation(PlayerColor, mPlayerClass->Type->GetColorSet(PlayerColorset), + R_GetPlayerTranslation(PlayerColor, GetColorSet(mPlayerClass->Type, PlayerColorset), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } } diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index 7116608b3..4126bc80b 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -680,7 +680,7 @@ void DPlayerMenu::UpdateTranslation() if (PlayerClass != NULL) { PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0])); - R_GetPlayerTranslation(PlayerColor, PlayerClass->Type->GetColorSet(PlayerColorset), + R_GetPlayerTranslation(PlayerColor, GetColorSet(PlayerClass->Type, PlayerColorset), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } } @@ -749,11 +749,11 @@ void DPlayerMenu::UpdateColorsets() if (li != NULL) { int sel = 0; - PlayerClass->Type->EnumColorSets(&PlayerColorSets); + EnumColorSets(PlayerClass->Type, &PlayerColorSets); li->SetString(0, "Custom"); for(unsigned i=0;iType->GetColorSet(PlayerColorSets[i]); + FPlayerColorSet *colorset = GetColorSet(PlayerClass->Type, PlayerColorSets[i]); li->SetString(i+1, colorset->Name); } int mycolorset = players[consoleplayer].userinfo.GetColorSet(); diff --git a/src/p_user.cpp b/src/p_user.cpp index 98221de1f..161d15121 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -84,6 +84,9 @@ CUSTOM_CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCO P_PredictionLerpReset(); } +ColorSetList ColorSets; +PainFlashList PainFlashes; + struct PredictPos { int gametic; @@ -551,23 +554,38 @@ void PClassPlayerPawn::DeriveData(PClass *newclass) PClassPlayerPawn *newp = static_cast(newclass); newp->DisplayName = DisplayName; - newp->ColorSets = ColorSets; } +//=========================================================================== +// +// EnumColorsets +// +// Only used by the menu so it doesn't really matter that it's a bit +// inefficient. +// +//=========================================================================== + static int intcmp(const void *a, const void *b) { return *(const int *)a - *(const int *)b; } -void PClassPlayerPawn::EnumColorSets(TArray *out) +void EnumColorSets(PClassActor *cls, TArray *out) { - out->Clear(); - FPlayerColorSetMap::Iterator it(ColorSets); - FPlayerColorSetMap::Pair *pair; + TArray deleteds; - while (it.NextPair(pair)) + out->Clear(); + for (int i = ColorSets.Size() - 1; i >= 0; i--) { - out->Push(pair->Key); + if (std::get<0>(ColorSets[i])->IsAncestorOf(cls)) + { + int v = std::get<1>(ColorSets[i]); + if (out->Find(v) == out->Size() && deleteds.Find(v) == deleteds.Size()) + { + if (std::get<2>(ColorSets[i]).Name == NAME_None) deleteds.Push(v); + else out->Push(v); + } + } } qsort(&(*out)[0], out->Size(), sizeof(int), intcmp); } @@ -577,20 +595,41 @@ void PClassPlayerPawn::EnumColorSets(TArray *out) // //========================================================================== -bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const +FPlayerColorSet *GetColorSet(PClassActor *cls, int setnum) { - const PClassPlayerPawn *info = this; - - while (info != NULL) + for (int i = ColorSets.Size() - 1; i >= 0; i--) { - const PalEntry *flash = info->PainFlashes.CheckKey(type); - if (flash != NULL) + if (std::get<1>(ColorSets[i]) == setnum && + std::get<0>(ColorSets[i])->IsAncestorOf(cls)) { - *color = *flash; + auto c = &std::get<2>(ColorSets[i]); + return c->Name != NAME_None ? c : nullptr; + } + } + return nullptr; +} + +//========================================================================== +// +// +//========================================================================== + +bool player_t::GetPainFlash(FName type, PalEntry *color) const +{ + PClass *info = mo->GetClass(); + + // go backwards through the list and return the first item with a + // matching damage type for an ancestor of our class. + // This will always return the best fit because any parent class + // must be processed before its children. + for (int i = PainFlashes.Size() - 1; i >= 0; i--) + { + if (std::get<1>(PainFlashes[i]) == type && + std::get<0>(PainFlashes[i])->IsAncestorOf(info)) + { + *color = std::get<2>(PainFlashes[i]); return true; } - // Try parent class - info = dyn_cast(info->ParentClass); } return false; } @@ -3238,8 +3277,6 @@ DEFINE_FIELD(APlayerPawn, ColorRangeStart) DEFINE_FIELD(APlayerPawn, ColorRangeEnd) DEFINE_FIELD(PClassPlayerPawn, DisplayName) -DEFINE_FIELD(PClassPlayerPawn, ColorSets) -DEFINE_FIELD(PClassPlayerPawn, PainFlashes) DEFINE_FIELD_X(PlayerInfo, player_t, mo) DEFINE_FIELD_X(PlayerInfo, player_t, playerstate) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 7f363b623..33d97dccf 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -69,6 +69,7 @@ #include "backend/vmbuilder.h" #include "a_keys.h" #include "g_levellocals.h" +#include "d_player.h" //========================================================================== // @@ -2386,8 +2387,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorset, ISIIIiiiiiiiiiiiiiiiiiiiiiiii, Pl } else { - assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn))); - static_cast(info)->ColorSets.Insert(setnum, color); + ColorSets.Push(std::make_tuple(info, setnum, color)); } } @@ -2413,8 +2413,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorsetfile, ISSI, PlayerPawn) } else if (color.Lump >= 0) { - assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn))); - static_cast(info)->ColorSets.Insert(setnum, color); + ColorSets.Push(std::make_tuple(info, setnum, color)); } } @@ -2431,8 +2430,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, clearcolorset, I, PlayerPawn) } else { - assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn))); - static_cast(info)->ColorSets.Remove(setnum); + FPlayerColorSet color; + memset(&color, 0, sizeof(color)); + ColorSets.Push(std::make_tuple(info, setnum, color)); } } @@ -2666,7 +2666,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, Cfs, PlayerPawn) PROP_STRING_PARM(type, 3); color.a = BYTE(255 * clamp(a, 0.f, 1.f)); - static_cast(info)->PainFlashes.Insert(type, color); + PainFlashes.Push(std::make_tuple(info, type, color)); } } diff --git a/src/v_blend.cpp b/src/v_blend.cpp index ffc16cd5c..41e6fe7ff 100644 --- a/src/v_blend.cpp +++ b/src/v_blend.cpp @@ -123,7 +123,7 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int } PalEntry painFlash = CPlayer->mo->DamageFade; - CPlayer->mo->GetClass()->GetPainFlash(CPlayer->mo->DamageTypeReceived, &painFlash); + CPlayer->GetPainFlash(CPlayer->mo->DamageTypeReceived, &painFlash); if (painFlash.a != 0) {