mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- 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:
parent
83c011740c
commit
aa32acae25
7 changed files with 186 additions and 162 deletions
|
@ -155,6 +155,7 @@ static Lock *locks[256]; // all valid locks
|
|||
static bool keysdone=false; // have the locks been initialized?
|
||||
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 TArray<PClassActor *> KeyTypes; // List of all keys sorted by lock.
|
||||
|
||||
static void ClearLocks();
|
||||
|
||||
|
@ -402,6 +403,52 @@ static void ClearLocks()
|
|||
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
|
||||
|
@ -436,6 +483,7 @@ void P_InitKeyMessages()
|
|||
}
|
||||
sc.Close();
|
||||
}
|
||||
CreateSortedKeyList();
|
||||
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;
|
||||
FSoundID *failsound;
|
||||
|
@ -517,15 +565,6 @@ bool P_CheckKeys (AActor *owner, int keynum, bool remote, bool quiet)
|
|||
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
|
||||
|
@ -558,3 +597,15 @@ int P_GetMapColorForKey (AInventory * key)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int P_GetKeyTypeCount()
|
||||
{
|
||||
return KeyTypes.Size();
|
||||
}
|
||||
|
||||
PClassActor *P_GetKeyType(int num)
|
||||
{
|
||||
if ((unsigned)num >= KeyTypes.Size()) return nullptr;
|
||||
return KeyTypes[num];
|
||||
}
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
|
||||
class AActor;
|
||||
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_DeinitKeyMessages ();
|
||||
int P_GetMapColorForLock (int lock);
|
||||
int P_GetMapColorForKey (AInventory *key);
|
||||
int P_GetKeyTypeCount();
|
||||
PClassActor *P_GetKeyType(int num);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,6 +116,7 @@ static FTexture * healthpic; // Health icon
|
|||
static FTexture * berserkpic; // Berserk icon (Doom only)
|
||||
static FTexture * fragpic; // Frags icon
|
||||
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 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
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
double GetBottomAlignOffset(FFont *font, int c);
|
||||
|
||||
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;
|
||||
for(int i=0;text[i];i++)
|
||||
{
|
||||
int width;
|
||||
FTexture *texc = font->GetChar(text[i], &width);
|
||||
if (texc != NULL)
|
||||
{
|
||||
double offset = texc->GetScaledTopOffsetDouble(0)
|
||||
- tex_zero->GetScaledTopOffsetDouble(0)
|
||||
+ tex_zero->GetScaledHeightDouble();
|
||||
int width = font->GetCharWidth(text[i]);
|
||||
double offset = GetBottomAlignOffset(font, text[i]);
|
||||
|
||||
screen->DrawChar(font, color, x, y, text[i],
|
||||
DTA_KeepRatio, true,
|
||||
DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans,
|
||||
DTA_LeftOffset, width/2, DTA_TopOffsetF, offset,
|
||||
/*DTA_CenterBottomOffset, 1,*/ TAG_DONE);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -441,6 +391,7 @@ static void DrawOneKey(int xo, int & x, int & y, int & c, AInventory * inv)
|
|||
{
|
||||
spritedef_t * sprdef = &sprites[state->sprite];
|
||||
spriteframe_t * sprframe = &SpriteFrames[sprdef->spriteframes + state->GetFrame()];
|
||||
if (sprframe->Texture[0] != tnt1a0)
|
||||
icon = sprframe->Texture[0];
|
||||
}
|
||||
}
|
||||
|
@ -470,26 +421,15 @@ static int DrawKeys(player_t * CPlayer, int x, int y)
|
|||
{
|
||||
int yo=y;
|
||||
int xo=x;
|
||||
int i;
|
||||
int c=0;
|
||||
AInventory *inv;
|
||||
|
||||
if (!deathmatch)
|
||||
{
|
||||
if (KeyTypes.Size() == 0) SetKeyTypes();
|
||||
|
||||
// First all keys that are assigned to locks (in reverse order of definition)
|
||||
for (i = KeyTypes.Size()-1; i >= 0; i--)
|
||||
int i = P_GetKeyTypeCount();
|
||||
for(i--; i >= 0; i--)
|
||||
{
|
||||
if ((inv = CPlayer->mo->FindInventory(KeyTypes[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])))
|
||||
if ((inv = CPlayer->mo->FindInventory(P_GetKeyType(i))))
|
||||
{
|
||||
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)
|
||||
{
|
||||
double trans;
|
||||
|
@ -1263,12 +1131,10 @@ void HUD_InitHud()
|
|||
|
||||
invgems[0] = TexMan.FindTexture("INVGEML1");
|
||||
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. :(
|
||||
|
||||
KeyTypes.Clear();
|
||||
UnassignedKeyTypes.Clear();
|
||||
|
||||
statspace = SmallFont->StringWidth("Ac:");
|
||||
|
||||
|
||||
|
|
|
@ -497,7 +497,7 @@ void ST_Clear();
|
|||
void ST_CreateStatusBar(bool bTitleLevel);
|
||||
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
|
||||
|
|
|
@ -2161,3 +2161,75 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetMugshot)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "p_local.h"
|
||||
#include "v_font.h"
|
||||
#include "gstrings.h"
|
||||
#include "a_keys.h"
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
|
@ -1578,6 +1579,34 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_PlaySound, A_PlaySound)
|
|||
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, ceilingplane)
|
||||
|
|
|
@ -37,6 +37,9 @@ class Key : Inventory
|
|||
Inventory.PickupSound "misc/k_pkup";
|
||||
}
|
||||
|
||||
static native clearscope int GetKeyTypeCount();
|
||||
static native clearscope class<Key> GetKeyType(int index);
|
||||
|
||||
override bool HandlePickup (Inventory item)
|
||||
{
|
||||
// In single player, you can pick up an infinite number of keys
|
||||
|
|
Loading…
Reference in a new issue