- 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.
This commit is contained in:
Christoph Oelckers 2017-02-08 19:10:11 +01:00
parent dd102caf13
commit 68e9918ed5
10 changed files with 83 additions and 40 deletions

View file

@ -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

View file

@ -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)
{

View file

@ -66,8 +66,11 @@ struct FPlayerColorSet
ExtraRange Extra[6];
};
typedef TMap<int, FPlayerColorSet> FPlayerColorSetMap;
typedef TMap<FName, PalEntry> PainFlashList;
typedef TArray<std::tuple<PClass*, FName, PalEntry>> PainFlashList;
typedef TArray<std::tuple<PClass*, int, FPlayerColorSet>> 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<int> *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<int> *out);
FPlayerColorSet *GetColorSet(PClassActor *pc, int setnum);
inline void AActor::SetFriendPlayer(player_t *player)
{

View file

@ -41,6 +41,8 @@
#endif
#include <limits.h>
#include <tuple>
#include <algorithm>
#include "tarray.h"
#include "name.h"
#include "zstring.h"

View file

@ -20,3 +20,4 @@
#include <io.h>
#include <limits>
#include <memory>
#include <tuple>

View file

@ -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]);
}
}

View file

@ -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;i<PlayerColorSets.Size(); i++)
{
FPlayerColorSet *colorset = PlayerClass->Type->GetColorSet(PlayerColorSets[i]);
FPlayerColorSet *colorset = GetColorSet(PlayerClass->Type, PlayerColorSets[i]);
li->SetString(i+1, colorset->Name);
}
int mycolorset = players[consoleplayer].userinfo.GetColorSet();

View file

@ -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<PClassPlayerPawn *>(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<int> *out)
void EnumColorSets(PClassActor *cls, TArray<int> *out)
{
out->Clear();
FPlayerColorSetMap::Iterator it(ColorSets);
FPlayerColorSetMap::Pair *pair;
TArray<int> 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<int> *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<PClassPlayerPawn>(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)

View file

@ -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<PClassPlayerPawn *>(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<PClassPlayerPawn *>(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<PClassPlayerPawn *>(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<double>(a, 0.f, 1.f));
static_cast<PClassPlayerPawn *>(info)->PainFlashes.Insert(type, color);
PainFlashes.Push(std::make_tuple(info, type, color));
}
}

View file

@ -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)
{