- a bit of code reordering for adding direct native entry points.

- offloaded key list generation for alternative HUD to non-UI parts.

This change also revealed a problem with handling empty sprites in the key list so this got fixed, too.
This commit is contained in:
Christoph Oelckers 2018-12-01 14:01:03 +01:00
parent 83c011740c
commit aa32acae25
7 changed files with 186 additions and 162 deletions

View file

@ -155,6 +155,7 @@ static Lock *locks[256]; // all valid locks
static bool keysdone=false; // have the locks been initialized? static bool keysdone=false; // have the locks been initialized?
static int currentnumber; // number to be assigned to next key static int currentnumber; // number to be assigned to next key
static bool ignorekey; // set to true when the current lock is not being used static bool ignorekey; // set to true when the current lock is not being used
static TArray<PClassActor *> KeyTypes; // List of all keys sorted by lock.
static void ClearLocks(); static void ClearLocks();
@ -402,6 +403,52 @@ static void ClearLocks()
keysdone = false; keysdone = false;
} }
//---------------------------------------------------------------------------
//
// create a sorted list of the defined keys so
// this doesn't have to be done each frame
//
// For use by the HUD and statusbar code to get a consistent order.
//
//---------------------------------------------------------------------------
static int ktcmp(const void * a, const void * b)
{
auto key1 = GetDefaultByType(*(PClassActor **)a);
auto key2 = GetDefaultByType(*(PClassActor **)b);
return key1->special1 - key2->special1;
}
static void CreateSortedKeyList()
{
TArray<PClassActor *> UnassignedKeyTypes;
KeyTypes.Clear();
for (unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
{
PClassActor *ti = PClassActor::AllActorClasses[i];
auto kt = PClass::FindActor(NAME_Key);
if (ti->IsDescendantOf(kt))
{
AInventory *key = (AInventory*)(GetDefaultByType(ti));
if (key->Icon.isValid() && key->special1 > 0)
{
KeyTypes.Push(ti);
}
else
{
UnassignedKeyTypes.Push(ti);
}
}
}
if (KeyTypes.Size())
{
qsort(&KeyTypes[0], KeyTypes.Size(), sizeof(KeyTypes[0]), ktcmp);
}
KeyTypes.Append(UnassignedKeyTypes);
}
//=========================================================================== //===========================================================================
// //
// P_InitKeyMessages // P_InitKeyMessages
@ -436,6 +483,7 @@ void P_InitKeyMessages()
} }
sc.Close(); sc.Close();
} }
CreateSortedKeyList();
keysdone = true; keysdone = true;
} }
@ -460,7 +508,7 @@ void P_DeinitKeyMessages()
// //
//=========================================================================== //===========================================================================
bool P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet) int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
{ {
const char *failtext = NULL; const char *failtext = NULL;
FSoundID *failsound; FSoundID *failsound;
@ -517,15 +565,6 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
return false; return false;
} }
DEFINE_ACTION_FUNCTION(AActor, CheckKeys)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(locknum);
PARAM_BOOL(remote);
PARAM_BOOL(quiet);
ACTION_RETURN_BOOL(P_CheckKeys(self, locknum, remote, quiet));
}
//========================================================================== //==========================================================================
// //
// These functions can be used to get color information for // These functions can be used to get color information for
@ -558,3 +597,15 @@ int P_GetMapColorForKey (AInventory * key)
} }
return 0; return 0;
} }
int P_GetKeyTypeCount()
{
return KeyTypes.Size();
}
PClassActor *P_GetKeyType(int num)
{
if ((unsigned)num >= KeyTypes.Size()) return nullptr;
return KeyTypes[num];
}

View file

@ -3,11 +3,14 @@
class AActor; class AActor;
class AInventory; class AInventory;
class PClassActor;
bool P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false); int P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet = false);
void P_InitKeyMessages (); void P_InitKeyMessages ();
void P_DeinitKeyMessages (); void P_DeinitKeyMessages ();
int P_GetMapColorForLock (int lock); int P_GetMapColorForLock (int lock);
int P_GetMapColorForKey (AInventory *key); int P_GetMapColorForKey (AInventory *key);
int P_GetKeyTypeCount();
PClassActor *P_GetKeyType(int num);
#endif #endif

View file

@ -116,6 +116,7 @@ static FTexture * healthpic; // Health icon
static FTexture * berserkpic; // Berserk icon (Doom only) static FTexture * berserkpic; // Berserk icon (Doom only)
static FTexture * fragpic; // Frags icon static FTexture * fragpic; // Frags icon
static FTexture * invgems[2]; // Inventory arrows static FTexture * invgems[2]; // Inventory arrows
static FTextureID tnt1a0; // We need this to check for empty sprites.
static int hudwidth, hudheight; // current width/height for HUD display static int hudwidth, hudheight; // current width/height for HUD display
static int statspace; static int statspace;
@ -163,6 +164,7 @@ static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, double tr
// Draws a text but uses a fixed width for all characters // Draws a text but uses a fixed width for all characters
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
double GetBottomAlignOffset(FFont *font, int c);
static void DrawHudText(FFont *font, int color, char * text, int x, int y, double trans = 0.75) static void DrawHudText(FFont *font, int color, char * text, int x, int y, double trans = 0.75)
{ {
@ -172,20 +174,15 @@ static void DrawHudText(FFont *font, int color, char * text, int x, int y, doubl
x+=zerowidth/2; x+=zerowidth/2;
for(int i=0;text[i];i++) for(int i=0;text[i];i++)
{ {
int width; int width = font->GetCharWidth(text[i]);
FTexture *texc = font->GetChar(text[i], &width); double offset = GetBottomAlignOffset(font, text[i]);
if (texc != NULL)
{
double offset = texc->GetScaledTopOffsetDouble(0)
- tex_zero->GetScaledTopOffsetDouble(0)
+ tex_zero->GetScaledHeightDouble();
screen->DrawChar(font, color, x, y, text[i], screen->DrawChar(font, color, x, y, text[i],
DTA_KeepRatio, true, DTA_KeepRatio, true,
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans, DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans,
DTA_LeftOffset, width/2, DTA_TopOffsetF, offset, DTA_LeftOffset, width/2, DTA_TopOffsetF, offset,
/*DTA_CenterBottomOffset, 1,*/ TAG_DONE); /*DTA_CenterBottomOffset, 1,*/ TAG_DONE);
}
x += zerowidth; x += zerowidth;
} }
} }
@ -365,53 +362,6 @@ static void DrawArmor(AInventory * barmor, AInventory * harmor, int x, int y)
// //
//=========================================================================== //===========================================================================
//---------------------------------------------------------------------------
//
// create a sorted list of the defined keys so
// this doesn't have to be done each frame
//
//---------------------------------------------------------------------------
static TArray<PClassActor *> KeyTypes, UnassignedKeyTypes;
static int ktcmp(const void * a, const void * b)
{
auto key1 = GetDefaultByType ( *(PClassActor **)a );
auto key2 = GetDefaultByType ( *(PClassActor **)b );
return key1->special1 - key2->special1;
}
static void SetKeyTypes()
{
for(unsigned int i = 0; i < PClassActor::AllActorClasses.Size(); i++)
{
PClassActor *ti = PClassActor::AllActorClasses[i];
auto kt = PClass::FindActor(NAME_Key);
if (ti->IsDescendantOf(kt))
{
AInventory *key = (AInventory*)(GetDefaultByType(ti));
if (key->Icon.isValid() && key->special1 > 0)
{
KeyTypes.Push(ti);
}
else
{
UnassignedKeyTypes.Push(ti);
}
}
}
if (KeyTypes.Size())
{
qsort(&KeyTypes[0], KeyTypes.Size(), sizeof(KeyTypes[0]), ktcmp);
}
else
{
// Don't leave the list empty
KeyTypes.Push(PClass::FindActor(NAME_Key));
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Draw one key // Draw one key
@ -441,6 +391,7 @@ static void DrawOneKey(int xo, int & x, int & y, int & c, AInventory * inv)
{ {
spritedef_t * sprdef = &sprites[state->sprite]; spritedef_t * sprdef = &sprites[state->sprite];
spriteframe_t * sprframe = &SpriteFrames[sprdef->spriteframes + state->GetFrame()]; spriteframe_t * sprframe = &SpriteFrames[sprdef->spriteframes + state->GetFrame()];
if (sprframe->Texture[0] != tnt1a0)
icon = sprframe->Texture[0]; icon = sprframe->Texture[0];
} }
} }
@ -470,26 +421,15 @@ static int DrawKeys(player_t * CPlayer, int x, int y)
{ {
int yo=y; int yo=y;
int xo=x; int xo=x;
int i;
int c=0; int c=0;
AInventory *inv; AInventory *inv;
if (!deathmatch) if (!deathmatch)
{ {
if (KeyTypes.Size() == 0) SetKeyTypes(); int i = P_GetKeyTypeCount();
for(i--; i >= 0; i--)
// First all keys that are assigned to locks (in reverse order of definition)
for (i = KeyTypes.Size()-1; i >= 0; i--)
{ {
if ((inv = CPlayer->mo->FindInventory(KeyTypes[i]))) if ((inv = CPlayer->mo->FindInventory(P_GetKeyType(i))))
{
DrawOneKey(xo, x, y, c, inv);
}
}
// And now the rest
for (i = UnassignedKeyTypes.Size()-1; i >= 0; i--)
{
if ((inv = CPlayer->mo->FindInventory(UnassignedKeyTypes[i])))
{ {
DrawOneKey(xo, x, y, c, inv); DrawOneKey(xo, x, y, c, inv);
} }
@ -664,78 +604,6 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
} }
//---------------------------------------------------------------------------
//
// Weapons List
//
//---------------------------------------------------------------------------
FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale=NULL) // This function is also used by SBARINFO
{
if (applyscale != NULL)
{
*applyscale = false;
}
if (item == nullptr) return FNullTextureID();
FTextureID picnum, AltIcon = item->AltHUDIcon;
FState * state=NULL, *ReadyState;
picnum.SetNull();
if (flags & DI_ALTICONFIRST)
{
if (!(flags & DI_SKIPALTICON) && AltIcon.isValid())
picnum = AltIcon;
else if (!(flags & DI_SKIPICON))
picnum = item->Icon;
}
else
{
if (!(flags & DI_SKIPICON) && item->Icon.isValid())
picnum = item->Icon;
else if (!(flags & DI_SKIPALTICON))
picnum = AltIcon;
}
if (!picnum.isValid()) //isNull() is bad for checking, because picnum could be also invalid (-1)
{
if (!(flags & DI_SKIPSPAWN) && item->SpawnState && item->SpawnState->sprite!=0)
{
state = item->SpawnState;
if (applyscale != NULL && !(flags & DI_FORCESCALE))
{
*applyscale = true;
}
}
// no spawn state - now try the ready state if it's weapon
else if (!(flags & DI_SKIPREADY) && item->GetClass()->IsDescendantOf(NAME_Weapon) && (ReadyState = item->FindState(NAME_Ready)) && ReadyState->sprite!=0)
{
state = ReadyState;
}
if (state && (unsigned)state->sprite < (unsigned)sprites.Size ())
{
spritedef_t * sprdef = &sprites[state->sprite];
spriteframe_t * sprframe = &SpriteFrames[sprdef->spriteframes + state->GetFrame()];
picnum = sprframe->Texture[0];
}
}
return picnum;
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetInventoryIcon)
{
PARAM_PROLOGUE;
PARAM_OBJECT(item, AInventory);
PARAM_INT(flags);
bool applyscale;
FTextureID icon = GetInventoryIcon(item, flags, &applyscale);
if (numret >= 1) ret[0].SetInt(icon.GetIndex());
if (numret >= 2) ret[1].SetInt(applyscale);
return MIN(numret, 2);
}
static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AInventory * weapon) static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AInventory * weapon)
{ {
double trans; double trans;
@ -1263,12 +1131,10 @@ void HUD_InitHud()
invgems[0] = TexMan.FindTexture("INVGEML1"); invgems[0] = TexMan.FindTexture("INVGEML1");
invgems[1] = TexMan.FindTexture("INVGEMR1"); invgems[1] = TexMan.FindTexture("INVGEMR1");
tnt1a0 = TexMan.CheckForTexture("TNT1A0", ETextureType::Sprite);
fragpic = TexMan.FindTexture("HU_FRAGS"); // Sadly, I don't have anything usable for this. :( fragpic = TexMan.FindTexture("HU_FRAGS"); // Sadly, I don't have anything usable for this. :(
KeyTypes.Clear();
UnassignedKeyTypes.Clear();
statspace = SmallFont->StringWidth("Ac:"); statspace = SmallFont->StringWidth("Ac:");

View file

@ -497,7 +497,7 @@ void ST_Clear();
void ST_CreateStatusBar(bool bTitleLevel); void ST_CreateStatusBar(bool bTitleLevel);
extern FTexture *CrosshairImage; extern FTexture *CrosshairImage;
FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale); FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale = nullptr);
enum DI_Flags enum DI_Flags

View file

@ -2161,3 +2161,75 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetMugshot)
ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1); ACTION_RETURN_INT(tex ? tex->id.GetIndex() : -1);
} }
//---------------------------------------------------------------------------
//
// Weapons List
//
//---------------------------------------------------------------------------
FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale)
{
if (applyscale != NULL)
{
*applyscale = false;
}
if (item == nullptr) return FNullTextureID();
FTextureID picnum, Icon = item->Icon, AltIcon = item->AltHUDIcon;
FState * state = NULL, *ReadyState;
picnum.SetNull();
if (flags & DI_ALTICONFIRST)
{
if (!(flags & DI_SKIPALTICON) && AltIcon.isValid())
picnum = AltIcon;
else if (!(flags & DI_SKIPICON))
picnum = Icon;
}
else
{
if (!(flags & DI_SKIPICON) && item->Icon.isValid())
picnum = Icon;
else if (!(flags & DI_SKIPALTICON))
picnum = AltIcon;
}
if (!picnum.isValid()) //isNull() is bad for checking, because picnum could be also invalid (-1)
{
if (!(flags & DI_SKIPSPAWN) && item->SpawnState && item->SpawnState->sprite != 0)
{
state = item->SpawnState;
if (applyscale != NULL && !(flags & DI_FORCESCALE))
{
*applyscale = true;
}
}
// no spawn state - now try the ready state if it's weapon
else if (!(flags & DI_SKIPREADY) && item->GetClass()->IsDescendantOf(NAME_Weapon) && (ReadyState = item->FindState(NAME_Ready)) && ReadyState->sprite != 0)
{
state = ReadyState;
}
if (state && (unsigned)state->sprite < (unsigned)sprites.Size())
{
spritedef_t * sprdef = &sprites[state->sprite];
spriteframe_t * sprframe = &SpriteFrames[sprdef->spriteframes + state->GetFrame()];
picnum = sprframe->Texture[0];
}
}
return picnum;
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetInventoryIcon)
{
PARAM_PROLOGUE;
PARAM_OBJECT(item, AInventory);
PARAM_INT(flags);
bool applyscale;
FTextureID icon = GetInventoryIcon(item, flags, &applyscale);
if (numret >= 1) ret[0].SetInt(icon.GetIndex());
if (numret >= 2) ret[1].SetInt(applyscale);
return MIN(numret, 2);
}

View file

@ -35,6 +35,7 @@
#include "p_local.h" #include "p_local.h"
#include "v_font.h" #include "v_font.h"
#include "gstrings.h" #include "gstrings.h"
#include "a_keys.h"
//===================================================================================== //=====================================================================================
// //
@ -1578,6 +1579,34 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound)
return 0; return 0;
} }
DEFINE_ACTION_FUNCTION_NATIVE(AActor, CheckKeys, P_CheckKeys)
{
PARAM_SELF_PROLOGUE(AActor);
PARAM_INT(locknum);
PARAM_BOOL(remote);
PARAM_BOOL(quiet);
ACTION_RETURN_BOOL(P_CheckKeys(self, locknum, remote, quiet));
}
//=====================================================================================
//
// Key exports
//
//=====================================================================================
DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyTypeCount, P_GetKeyTypeCount)
{
PARAM_PROLOGUE;
ACTION_RETURN_INT(P_GetKeyTypeCount());
}
DEFINE_ACTION_FUNCTION_NATIVE(AKey, GetKeyType, P_GetKeyType)
{
PARAM_PROLOGUE;
PARAM_INT(num);
ACTION_RETURN_POINTER(P_GetKeyType(num));
}
DEFINE_FIELD_X(Sector, sector_t, floorplane) DEFINE_FIELD_X(Sector, sector_t, floorplane)
DEFINE_FIELD_X(Sector, sector_t, ceilingplane) DEFINE_FIELD_X(Sector, sector_t, ceilingplane)

View file

@ -37,6 +37,9 @@ class Key : Inventory
Inventory.PickupSound "misc/k_pkup"; Inventory.PickupSound "misc/k_pkup";
} }
static native clearscope int GetKeyTypeCount();
static native clearscope class<Key> GetKeyType(int index);
override bool HandlePickup (Inventory item) override bool HandlePickup (Inventory item)
{ {
// In single player, you can pick up an infinite number of keys // In single player, you can pick up an infinite number of keys