- major progress on the status bar code: SBARINFO's DrawGraphic has been ported into a generic function of the base statusbar class and put to use for a few items on the Strife status bar.

- decided to ditch the widget system I had started to lay out. As it turns out that would make things far more complicated and slower than they need to be.
This commit is contained in:
Christoph Oelckers 2017-03-23 15:18:09 +01:00
parent 74a2d58a52
commit a3ee3c287e
13 changed files with 653 additions and 809 deletions

View file

@ -803,6 +803,10 @@ void D_Display ()
V_RefreshViewBorder (); V_RefreshViewBorder ();
} }
// for timing the statusbar code.
//cycle_t stb;
//stb.Reset();
//stb.Clock();
if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10) if (hud_althud && viewheight == SCREENHEIGHT && screenblocks > 10)
{ {
StatusBar->DrawBottomStuff (HUD_AltHud); StatusBar->DrawBottomStuff (HUD_AltHud);
@ -828,6 +832,8 @@ void D_Display ()
StatusBar->CallDraw (HUD_StatusBar); StatusBar->CallDraw (HUD_StatusBar);
StatusBar->DrawTopStuff (HUD_StatusBar); StatusBar->DrawTopStuff (HUD_StatusBar);
} }
//stb.Unclock();
//Printf("Stbar = %f\n", stb.TimeMS());
CT_Drawer (); CT_Drawer ();
break; break;

View file

@ -672,6 +672,13 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale=NULL) // This function is also used by SBARINFO 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; FTextureID picnum, AltIcon = item->AltHUDIcon;
FState * state=NULL, *ReadyState; FState * state=NULL, *ReadyState;
@ -718,6 +725,17 @@ FTextureID GetInventoryIcon(AInventory *item, uint32_t flags, bool *applyscale=N
return picnum; 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, AWeapon * weapon) static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AWeapon * weapon)
{ {

View file

@ -373,6 +373,28 @@ public:
virtual bool MustDrawLog(EHudState state); virtual bool MustDrawLog(EHudState state);
virtual void SetMugShotState (const char *state_name, bool wait_till_done=false, bool reset=false); virtual void SetMugShotState (const char *state_name, bool wait_till_done=false, bool reset=false);
void DrawLog(); void DrawLog();
uint32_t GetTranslation() const;
enum EAlign
{
TOP = 0,
VCENTER = 1,
BOTTOM = 2,
VOFFSET = 3,
VMASK = 3,
LEFT = 0,
HCENTER = 4,
RIGHT = 8,
HOFFSET = 12,
HMASK = 12,
CENTER = VCENTER | HCENTER,
CENTER_BOTTOM = BOTTOM | HCENTER
};
void DBaseStatusBar::DrawGraphic(FTextureID texture, bool animate, double x, double y, double Alpha = 1., bool translatable = false, bool dim = false,
int imgAlign = TOP | LEFT, int screenalign = TOP | LEFT, bool alphamap = false, double width = -1, double height = -1, double scaleX = 1, double scaleY = 1, bool fullscreenoffsets = false);
void GetCoords(int &x, int &y) void GetCoords(int &x, int &y)
{ {

View file

@ -57,6 +57,7 @@
#include "cmdlib.h" #include "cmdlib.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "virtual.h" #include "virtual.h"
#include "r_data/r_translate.h"
#include "../version.h" #include "../version.h"
@ -624,9 +625,6 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, RefreshBackground)
void DBaseStatusBar::DrawCrosshair () void DBaseStatusBar::DrawCrosshair ()
{ {
static uint32_t prevcolor = 0xffffffff;
static int palettecolor = 0;
uint32_t color; uint32_t color;
double size; double size;
int w, h; int w, h;
@ -693,19 +691,13 @@ void DBaseStatusBar::DrawCrosshair ()
color = crosshaircolor; color = crosshaircolor;
} }
if (color != prevcolor)
{
prevcolor = color;
palettecolor = ColorMatcher.Pick (RPART(color), GPART(color), BPART(color));
}
screen->DrawTexture (CrosshairImage, screen->DrawTexture (CrosshairImage,
viewwidth / 2 + viewwindowx, viewwidth / 2 + viewwindowx,
viewheight / 2 + viewwindowy, viewheight / 2 + viewwindowy,
DTA_DestWidth, w, DTA_DestWidth, w,
DTA_DestHeight, h, DTA_DestHeight, h,
DTA_AlphaChannel, true, DTA_AlphaChannel, true,
DTA_FillColor, (palettecolor << 24) | (color & 0xFFFFFF), DTA_FillColor, color & 0xFFFFFF,
TAG_DONE); TAG_DONE);
} }
@ -1377,6 +1369,120 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, ValidateInvFirst)
} }
uint32_t DBaseStatusBar::GetTranslation() const
{
if (gameinfo.gametype & GAME_Raven)
return TRANSLATION(TRANSLATION_PlayersExtra, int(CPlayer - players));
return TRANSLATION(TRANSLATION_Players, int(CPlayer - players));
}
//============================================================================
//
// draw stuff
//
//============================================================================
EXTERN_CVAR(Bool, hud_scale)
EXTERN_CVAR(Bool, vid_fps)
void DBaseStatusBar::DrawGraphic(FTextureID texture, bool animate, double x, double y, double Alpha, bool translatable, bool dim,
int imgAlign, int screenalign, bool alphamap, double width, double height, double scaleX, double scaleY, bool fullscreenoffsets)
{
if (!texture.isValid())
return;
FTexture *tex = animate ? TexMan(texture) : TexMan[texture];
switch (imgAlign & HMASK)
{
case HCENTER: x -= width / 2; break;
case RIGHT: x -= width; break;
case HOFFSET: x -= tex->GetScaledLeftOffsetDouble() * width / tex->GetScaledWidthDouble(); break;
}
switch (imgAlign & VMASK)
{
case VCENTER: y -= height / 2; break;
case BOTTOM: y -= height; break;
case VOFFSET: y -= tex->GetScaledTopOffsetDouble() * height / tex->GetScaledHeightDouble(); break;
}
if (!fullscreenoffsets)
{
x += ST_X;
y += ST_Y;
// Todo: Allow other scaling values, too.
if (Scaled)
{
y += RelTop - VerticalResolution;
screen->VirtualToRealCoords(x, y, width, height, HorizontalResolution, VerticalResolution, true, true);
}
}
else
{
double orgx, orgy;
switch (screenalign & HMASK)
{
default: orgx = 0; break;
case HCENTER: orgx = screen->GetWidth() / 2; break;
case RIGHT: orgx = screen->GetWidth(); break;
}
switch (screenalign & VMASK)
{
default: orgy = 0; break;
case VCENTER: orgy = screen->GetHeight() / 2; break;
case BOTTOM: orgy = screen->GetHeight(); break;
}
if (screenalign == (RIGHT | TOP) && vid_fps) y += 10;
if (hud_scale)
{
x *= scaleX;
y *= scaleY;
width *= scaleX;
height *= scaleY;
}
x += orgx;
y += orgy;
}
screen->DrawTexture(tex, x, y,
DTA_TopOffset, 0,
DTA_LeftOffset, 0,
DTA_DestWidthF, width,
DTA_DestHeightF, height,
DTA_TranslationIndex, translatable ? GetTranslation() : 0,
DTA_ColorOverlay, dim ? PalEntry(170, 0, 0, 0) : 0,
DTA_Alpha, Alpha,
DTA_AlphaChannel, alphamap,
DTA_FillColor, alphamap ? 0 : -1);
}
DEFINE_ACTION_FUNCTION(DBaseStatusBar, DrawGraphic)
{
PARAM_SELF_PROLOGUE(DBaseStatusBar);
PARAM_INT(texid);
PARAM_BOOL(animate);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(alpha);
PARAM_BOOL(translatable);
PARAM_BOOL(dim);
PARAM_INT(ialign);
PARAM_INT(salign);
PARAM_BOOL(alphamap);
PARAM_FLOAT(w);
PARAM_FLOAT(h);
PARAM_FLOAT(sx);
PARAM_FLOAT(sy);
PARAM_BOOL(fso);
self->DrawGraphic(FSetTextureID(texid), animate, x, y, alpha, translatable, dim, ialign, salign, alphamap, w, h, sx, sy, fso);
return 0;
}
//============================================================================ //============================================================================
// //
// CCMD showpop // CCMD showpop
@ -1438,36 +1544,3 @@ static DObject *InitObject(PClass *type, int paramnum, VM_ARGS)
return obj; return obj;
} }
DEFINE_ACTION_FUNCTION(DStatusbarWidget, AppendWidget)
{
PARAM_SELF_PROLOGUE(DObject);
PARAM_CLASS(type, DObject);
if (!type->IsDescendantOf(NAME_StatusbarWidget) || type->IsDescendantOf(NAME_StatusbarCondition))
{
ThrowAbortException(X_OTHER, "Invalid class %s for AppendWidget", type->TypeName.GetChars());
}
auto obj = InitObject(type, paramnum, VM_ARGS_NAMES);
auto owner = self->PointerVar<DObject>(NAME_Owner);
self->PointerVar<DObject>(NAME_Next) = obj;
obj->PointerVar<DObject>(NAME_Prev) = self;
obj->PointerVar<DObject>(NAME_Owner) = owner;
ACTION_RETURN_POINTER(obj);
}
DEFINE_ACTION_FUNCTION(DStatusbarWidget, BeginCondition)
{
PARAM_SELF_PROLOGUE(DObject);
PARAM_CLASS(type, DObject);
if (!type->IsDescendantOf(NAME_StatusbarCondition))
{
ThrowAbortException(X_OTHER, "Invalid class %s for BeginCondition", type->TypeName.GetChars());
}
auto obj = InitObject(type, paramnum, VM_ARGS_NAMES);
auto head = PClass::FindClass(NAME_StatusbarWidget)->CreateNew();
head->PointerVar<DObject>(NAME_Owner) = self;
self->PointerVar<DObject>(NAME_Children) = head;
ACTION_RETURN_POINTER(head);
}

View file

@ -8674,6 +8674,11 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
return nullptr; return nullptr;
} }
if (Function->Variants[0].Implementation->PrintableName.CompareNoCase("CustomStatusBar.DrawTexture") == 0)
{
int a = 0;
}
CallingFunction = ctx.Function; CallingFunction = ctx.Function;
if (ArgList.Size() > 0) if (ArgList.Size() > 0)
{ {
@ -8736,6 +8741,12 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
delete old; delete old;
// now fill the gap with constants created from the default list so that we got a full list of arguments. // now fill the gap with constants created from the default list so that we got a full list of arguments.
int insert = j - i; int insert = j - i;
int skipdefs = 0;
// Defaults contain multiple entries for pointers so we need to calculate how much additional defaults we need to skip
for (unsigned k = 0; k < i + implicit; k++)
{
skipdefs += argtypes[k]->GetRegCount() - 1;
}
for (int k = 0; k < insert; k++) for (int k = 0; k < insert; k++)
{ {
auto ntype = argtypes[i + k + implicit]; auto ntype = argtypes[i + k + implicit];
@ -8745,9 +8756,24 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
assert(ntype->IsKindOf(RUNTIME_CLASS(PPointer))); assert(ntype->IsKindOf(RUNTIME_CLASS(PPointer)));
ntype = TypeNullPtr; // the default of a reference type can only be a null pointer ntype = TypeNullPtr; // the default of a reference type can only be a null pointer
} }
auto x = new FxConstant(ntype, defaults[i + k + implicit], ScriptPosition); if (ntype->GetRegCount() == 1)
{
auto x = new FxConstant(ntype, defaults[i + k + skipdefs + implicit], ScriptPosition);
ArgList.Insert(i + k, x); ArgList.Insert(i + k, x);
} }
else
{
// Vectors need special treatment because they are not normal constants
FxConstant *cs[3] = { nullptr };
for (int l = 0; l < ntype->GetRegCount(); l++)
{
cs[l] = new FxConstant(TypeFloat64, defaults[l + i + k + skipdefs + implicit], ScriptPosition);
}
FxExpression *x = new FxVectorValue(cs[0], cs[1], cs[2], ScriptPosition);
ArgList.Insert(i + k, x);
skipdefs += ntype->GetRegCount() - 1;
}
}
done = true; done = true;
break; break;
} }

View file

@ -2503,10 +2503,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
{ {
flags |= VARF_Optional; flags |= VARF_Optional;
hasoptionals = true; hasoptionals = true;
// The simplifier is not suited to convert the constant into something usable.
// All it does is reduce the expression to a constant but we still got to do proper type checking and conversion.
// It will also lose important type info about enums, once these get implemented
// The code generator can do this properly for us.
FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false); FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false);
FCompileContext ctx(OutNamespace, c->Type(), false); FCompileContext ctx(OutNamespace, c->Type(), false);
x = x->Resolve(ctx); x = x->Resolve(ctx);

View file

@ -104,6 +104,7 @@ void SWCanvas::DrawTexture(DCanvas *canvas, FTexture *img, DrawParms &parms)
drawerargs.SetTranslationMap(translation); drawerargs.SetTranslationMap(translation);
drawerargs.SetLight(basecolormap, 0.0f, shade); drawerargs.SetLight(basecolormap, 0.0f, shade);
bool visible = drawerargs.SetStyle(viewport, parms.style, parms.Alpha, -1, parms.fillcolor, basecolormap); bool visible = drawerargs.SetStyle(viewport, parms.style, parms.Alpha, -1, parms.fillcolor, basecolormap);
double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth; double x0 = parms.x - parms.left * parms.destwidth / parms.texwidth;

View file

@ -521,7 +521,15 @@ bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t t
case DTA_FillColor: case DTA_FillColor:
parms->fillcolor = ListGetInt(tags); parms->fillcolor = ListGetInt(tags);
if (parms->fillcolor != -1)
{
fillcolorset = true; fillcolorset = true;
}
else if (parms->fillcolor != 0)
{
// The crosshair is the only thing which uses a non-black fill color.
parms->fillcolor = PalEntry(ColorMatcher.Pick(parms->fillcolor), RPART(parms->fillcolor), GPART(parms->fillcolor), BPART(parms->fillcolor));
}
break; break;
case DTA_TranslationIndex: case DTA_TranslationIndex:

View file

@ -35,7 +35,6 @@ version "2.5"
#include "zscript/statusbar/statusbar.txt" #include "zscript/statusbar/statusbar.txt"
#include "zscript/statusbar/strife_sbar.txt" #include "zscript/statusbar/strife_sbar.txt"
#include "zscript/statusbar/sbarinfowrapper.txt" #include "zscript/statusbar/sbarinfowrapper.txt"
#include "zscript/statusbar/statusbarwidget.txt"
#include "zscript/inventory/inventory.txt" #include "zscript/inventory/inventory.txt"
#include "zscript/inventory/inv_misc.txt" #include "zscript/inventory/inv_misc.txt"

View file

@ -509,7 +509,7 @@ class Actor : Thinker native
native bool GiveBody (int num, int max=0); native bool GiveBody (int num, int max=0);
native bool HitFloor(); native bool HitFloor();
native clearscope bool isTeammate(Actor other) const; native clearscope bool isTeammate(Actor other) const;
native int PlayerNumber(); native clearscope int PlayerNumber() const;
native void SetFriendPlayer(PlayerInfo player); native void SetFriendPlayer(PlayerInfo player);
native void SoundAlert(Actor target, bool splash = false, double maxdist = 0); native void SoundAlert(Actor target, bool splash = false, double maxdist = 0);
native void DaggerAlert(Actor target); native void DaggerAlert(Actor target);

View file

@ -80,6 +80,11 @@ class BaseStatusBar native ui
native void RefreshBackground () const; native void RefreshBackground () const;
native Inventory ValidateInvFirst (int numVisible) const; native Inventory ValidateInvFirst (int numVisible) const;
native static TextureID, bool GetInventoryIcon(Inventory item, int flags);
native void DrawGraphic(TextureID texture, bool animate, Vector2 pos, double Alpha, bool translatable, bool dim,
int imgAlign, int screenalign, bool alphamap, Vector2 box, Vector2 scale, bool fso);
//============================================================================ //============================================================================
// //
@ -111,6 +116,444 @@ class BaseStatusBar native ui
let ammocount2 = ammo2 != NULL ? ammo2.Amount : 0; let ammocount2 = ammo2 != NULL ? ammo2.Amount : 0;
return ammo1, ammo2, ammocount1, ammocount2; return ammo1, ammo2, ammocount1, ammocount2;
} }
}
//============================================================================
//
// This is only needed to shadow the native base class because a native class
// cannot have scripted variables added.
//
//============================================================================
class CustomStatusBar : BaseStatusBar
{
enum DI_Flags
{
DI_SKIPICON = 0x1,
DI_SKIPALTICON = 0x2,
DI_SKIPSPAWN = 0x4,
DI_SKIPREADY = 0x8,
DI_ALTICONFIRST = 0x10,
DI_TRANSLATABLE = 0x20,
DI_FORCESCALE = 0x40
};
enum IconType
{
PLAYERICON = 1000,
AMMO1,
AMMO2,
ARMOR,
WEAPONICON,
SIGIL,
WEAPONSLOT,
SELECTEDINVENTORYICON,
HEXENARMOR_ARMOR,
HEXENARMOR_SHIELD,
HEXENARMOR_HELM,
HEXENARMOR_AMULET,
};
enum EAlign
{
TOP = 0,
VCENTER = 1,
BOTTOM = 2,
VOFFSET = 3,
VMASK = 3,
LEFT = 0,
HCENTER = 4,
RIGHT = 8,
HOFFSET = 12,
HMASK = 12,
CENTER = VCENTER|HCENTER,
CENTER_BOTTOM = BOTTOM|HCENTER
};
enum SBGameModes
{
SINGLEPLAYER = 0x1,
COOPERATIVE = 0x2,
DEATHMATCH = 0x4,
TEAMGAME = 0x8
};
enum AmmoModes
{
AMMO_PRIMARY,
AMMO_SECONDARY,
AMMO_ANY,
AMMO_BOTH
};
double Alpha;
Vector2 drawOffset; // can be set by subclasses to offset drawing operations
double drawClip[4]; // defines a clipping rectangle (not used yet)
bool fullscreenOffsets; // current screen is displayed with fullscreen behavior.
Vector2 cleanScale; // factor for scaled fullscreen display.
override void Init()
{
Super.Init();
Alpha = 1;
DrawOffset = (0, 0);
drawClip[0] = 0;
drawClip[1] = 0;
drawClip[2] = 0;
drawClip[3] = 0;
cleanScale = (CleanXfac, CleanYfac);
fullscreenOffsets = false;
}
//============================================================================
//
// Get an icon
//
//============================================================================
TextureID, Vector2 GetIcon(Inventory item, int flags, bool showdepleted = false)
{
TextureID icon;
Vector2 scale = (1,1);
icon.SetInvalid();
if (item != null)
{
bool applyscale;
[icon, applyscale] = GetInventoryIcon(item, flags);
if (item.Amount == 0 && !showdepleted) return icon;
if (applyscale)
scale = item.Scale;
}
return icon;
}
//============================================================================
//
// various checker functions, based on SBARINFOs condition nodes.
//
//============================================================================
//============================================================================
//
// checks current game mode against a flag mask
//
//============================================================================
bool CheckGameMode(int ValidModes)
{
return (!multiplayer && (ValidModes & SINGLEPLAYER)) ||
(deathmatch && (ValidModes & DEATHMATCH)) ||
(multiplayer && !deathmatch && (ValidModes & COOPERATIVE)) ||
(teamplay && (ValidModes & TEAMGAME));
}
//============================================================================
//
// checks ammo use of current weapon
//
//============================================================================
bool WeaponUsesAmmo(int ValidModes)
{
if (CPlayer == null) return false;
let w = CPlayer.ReadyWeapon;
if (w == null) return false;
bool usesammo1 = w.AmmoType1 != NULL;
bool usesammo2 = w.AmmoType2 != NULL;
if (ValidModes == AMMO_PRIMARY) return usesammo1;
if (ValidModes == AMMO_SECONDARY) return usesammo2;
if (ValidModes == AMMO_ANY) return (usesammo1 || usesammo2);
if (ValidModes == AMMO_BOTH) return (usesammo1 && usesammo2);
return false;
}
//============================================================================
//
// checks if inventory bar is visible
//
//============================================================================
bool isInventoryBarVisible()
{
if (CPlayer == null) return false;
return (CPlayer.inventorytics <= 0 || level.NoInventoryBar);
}
//============================================================================
//
// checks if aspect ratio is in a given range
//
//============================================================================
bool CheckAspectRatio(double min, double max)
{
if (CPlayer == null) return false;
double aspect = screen.GetAspectRatio();
return (aspect >= min && aspect < max);
}
//============================================================================
//
// checks if weapon is selected.
//
//============================================================================
bool CheckWeaponSelected(class<Weapon> weap, bool checksister = true)
{
if (CPlayer == null) return false;
let w = CPlayer.ReadyWeapon;
if (w == null) return false;
if (w.GetClass() == weap) return true;
if (checksister && w.SisterWeapon != null && w.SisterWeapon.GetClass() == weap) return true;
return false;
}
//============================================================================
//
// checks if player has the given display name
//
//============================================================================
bool CheckDiplayName(String displayname)
{
if (CPlayer == null) return false;
return displayname == PlayerPawn.GetPrintableDisplayName(CPlayer.mo.GetClass());
}
//============================================================================
//
// checks if player has the given weapon piece
//
//============================================================================
bool CheckWeaponPiece(class<Weapon> weap, int piecenum)
{
if (CPlayer == null) return false;
for(let inv = CPlayer.mo.Inv; inv != NULL; inv = inv.Inv)
{
let wh = WeaponHolder(inv);
if (wh != null && wh.PieceWeapon == weap)
{
return (!!(wh.PieceMask & (1 << (PieceNum-1))));
}
}
return false;
}
//============================================================================
//
// checks if player has the given weapon piece
//
//============================================================================
bool WeaponUsesAmmoType(class<Ammo> ammotype)
{
if (CPlayer == null) return false;
let w = CPlayer.ReadyWeapon;
if (w == NULL) return false;
return w.AmmoType1 == ammotype || w.AmmoType2 == ammotype;
}
//============================================================================
//
// checks if player has the required health
//
//============================================================================
bool CheckHealth(int Amount, bool percentage = false)
{
if (CPlayer == null) return false;
int phealth = percentage ? CPlayer.mo.health * 100 / CPlayer.mo.GetMaxHealth() : CPlayer.mo.health;
return (phealth >= Amount);
}
//============================================================================
//
// checks if player is invulnerable
//
//============================================================================
bool isInvulnerable()
{
if (CPlayer == null) return false;
return ((CPlayer.mo.bInvulnerable) || (CPlayer.cheats & (CF_GODMODE | CF_GODMODE2)));
}
//============================================================================
//
// checks if player owns enough of the item
//
//============================================================================
bool CheckInventory(class<Inventory> item, int amount = 1)
{
if (CPlayer == null) return false;
let it = CPlayer.mo.FindInventory(item);
return it != null && it.Amount >= amount;
}
//============================================================================
//
// draw stuff
//
//============================================================================
int GetTranslation() const
{
if(gameinfo.gametype & GAME_Raven)
return Translation.MakeID(TRANSLATION_PlayersExtra, CPlayer.mo.PlayerNumber());
else
return Translation.MakeID(TRANSLATION_Players, CPlayer.mo.PlayerNumber());
}
//============================================================================
//
// draw stuff
//
//============================================================================
void DrawTexture(TextureID texture, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0, Vector2 scale = (1., 1.) )
{
if (!texture.IsValid()) return; // nothing to draw
alpha *= self.alpha;
if (alpha <= 0) return; // invisible
Vector2 texsize = TexMan.GetScaledSize(texture);
texsize.X *= scale.X;
texsize.Y *= scale.Y;
if (boxsize.X > 0 || boxsize.Y > 0)
{
double scale1 = 1., scale2 = 1.;
if (boxsize.X != -1 && (boxsize.X < texsize.X || (flags & DI_FORCESCALE)))
{
scale1 = boxsize.X / texsize.X;
}
if (boxsize.Y != -1 && (boxsize.Y < texsize.Y || (flags & DI_FORCESCALE)))
{
scale2 = boxsize.Y / texsize.Y;
}
if (flags & DI_FORCESCALE)
{
if (boxsize.X == -1 || (boxsize.Y != -1 && scale2 < scale1))
scale1 = scale2;
}
else scale1 = min(scale1, scale2);
boxsize = texsize * scale1;
screenAlign = TOP|LEFT; // anything else makes no sense here.
}
else
{
boxsize = texsize;
}
DrawGraphic(texture, animated, pos + drawOffset, Alpha * self.Alpha, !!(flags & DI_TRANSLATABLE), false, itemAlign, screenAlign, false, boxsize, cleanscale, fullscreenoffsets);
}
//============================================================================
//
//
//
//============================================================================
void DrawImage(String imagename, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0, Vector2 scale = (1., 1.) )
{
let tex = TexMan.CheckForTexture(imagename, TexMan.TYPE_MiscPatch);
DrawTexture(tex, pos, animated, screenalign, alpha, boxsize, itemAlign, flags, scale);
}
//============================================================================
//
//
//
//============================================================================
void DrawIcon(int icontype, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0)
{
TextureID texture;
Vector2 applyscale = (1, 1);
Inventory atype1, atype2;
switch (icontype)
{
case PLAYERICON:
texture = CPlayer.mo.ScoreIcon;
break;
case AMMO1:
case AMMO2:
[atype1, atype2] = GetCurrentAmmo();
[texture, applyscale] = GetIcon(icontype == AMMO1? atype1 : atype2, flags, true);
break;
case ARMOR:
[texture, applyscale] = GetIcon(CPlayer.mo.FindInventory("BasicArmor"), flags, false);
break;
case WEAPONICON:
[texture, applyscale] = GetIcon(CPlayer.ReadyWeapon, flags, false);
break;
case SIGIL:
[texture, applyscale] = GetIcon(CPlayer.mo.FindInventory("Sigil"), flags, false);
break;
case SELECTEDINVENTORYICON:
if (CPlayer.mo.InvSel != NULL)
texture = CPlayer.mo.InvSel.Icon;
break;
}
DrawTexture(texture, pos, animated, screenalign, alpha, boxsize, itemAlign, flags, applyscale);
}
//============================================================================
//
//
//
//============================================================================
void DrawHexenArmor(int armortype, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0)
{
let harmor = HexenArmor(statusBar.CPlayer.mo.FindInventory("HexenArmor"));
if (harmor != NULL)
{
let slotval = harmor.Slots[armorType];
let slotincr = harmor.SlotsIncrement[armorType];
if (slotval > 0 && slotincr > 0)
{
//combine the alpha values
alpha *= MIN(1., slotval / slotincr);
}
else return;
}
DrawImage(image, pos, animated, screenalign, alpha, boxsize, itemAlign, flags);
}
//============================================================================
//
//
//
//============================================================================
void DrawInventoryIcon(class<Inventory> item, String image, Vector2 pos, bool animated = false, double alpha = 1.0, int screenalign = TOP|LEFT, Vector2 boxsize = (-1, -1), int itemAlign = TOP|LEFT, int flags = 0)
{
let texture = GetDefaultByType(item).Icon;
if (texture.IsValid())
{
DrawTexture(texture, pos, animated, screenalign, alpha, boxsize, itemAlign, flags);
}
}
} }

View file

@ -1,744 +0,0 @@
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class StatusbarWidget ui
{
enum EAlign
{
TOP = 0x1,
VMIDDLE = 0x2,
BOTTOM = 0x4,
LEFT = 0x10,
RIGHT = 0x20,
HMIDDLE = 0x40,
CENTER = VMIDDLE|HMIDDLE,
CENTER_BOTTOM = BOTTOM|HMIDDLE
};
StatusbarWidget Next;
StatusbarWidget Prev;
StatusbarWidget Owner;
native vararg StatusbarWidget AppendWidget(class<StatusbarWidget> cls, ...);
native vararg StatusbarWidget BeginCondition(class<StatusbarCondition> cls, ...);
void Init()
{
}
StatusbarCondition EndCondition()
{
if (owner == null || !(owner is "StatusbarCondition"))
{
ThrowAbortException("No matching BeginCondition found for EndCondition");
}
return StatusbarCondition(owner);
}
StatusbarWidget ElseCondition()
{
let condi = StatusbarCondition(owner);
if (condi == null)
{
ThrowAbortException("No matching BeginCondition found for EndCondition");
}
if (condi.FalseChildren != null)
{
ThrowAbortException("Duplicate ElseCondition()");
}
condi.FalseChildren = new("StatusbarWidget");
condi.FalseChildren.Owner = condi;
return condi.FalseChildren;
}
StatusbarHead Finish()
{
if (owner == null || !(Owner is "StatusbarHead"))
{
ThrowAbortException("No matching Begin found for Finish");
}
return StatusbarHead(owner);
}
virtual void Draw(WidgetStatusBar stbar) {}
virtual void Reset() {}
virtual void Tick(WidgetStatusBar stbar, bool change) {}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class StatusbarHead : StatusbarWidget
{
StatusbarWidget Children;
override void Draw(WidgetStatusBar stbar)
{
for(let p = Children; p != null; p = p.Next)
{
p.Draw(stbar);
}
}
override void Reset()
{
for(let p = Children; p != null; p = p.Next)
{
p.Reset();
}
}
override void Tick(WidgetStatusBar stbar, bool change)
{
for(let p = Children; p != null; p = p.Next)
{
p.Tick(stbar, change);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class StatusbarCondition : StatusbarWidget
{
StatusbarWidget TrueChildren;
StatusbarWidget FalseChildren;
bool LastCondition;
virtual int Condition(WidgetStatusBar stbar) { return -1; }
void Init()
{
LastCondition = true;
}
override void Draw(WidgetStatusBar stbar)
{
for(let p = LastCondition? TrueChildren : FalseChildren; p != null; p = p.Next)
{
p.Draw(stbar);
}
}
override void Reset()
{
for(let p = TrueChildren; p != null; p = p.Next)
{
p.Reset();
}
for(let p = FalseChildren; p != null; p = p.Next)
{
p.Reset();
}
}
override void Tick(WidgetStatusBar stbar, bool change)
{
for(let p = LastCondition? TrueChildren : FalseChildren; p != null; p = p.Next)
{
p.Tick(stbar, change);
}
int i = Condition(stbar);
if (i >= 0 && LastCondition != !!i)
{
LastCondition = !!i;
for(let p = LastCondition? TrueChildren : FalseChildren; p != null; p = p.Next)
{
p.Tick(stbar, true);
}
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionGamemode : StatusbarCondition
{
enum GameModes
{
SINGLEPLAYER = 0x1,
COOPERATIVE = 0x2,
DEATHMATCH = 0x4,
TEAMGAME = 0x8
};
private int ValidModes;
void Init(int modemask)
{
ValidModes = modemask;
}
override int Condition(WidgetStatusBar stbar)
{
return (!multiplayer && (ValidModes & SINGLEPLAYER)) ||
(deathmatch && (ValidModes & DEATHMATCH)) ||
(multiplayer && !deathmatch && (ValidModes & COOPERATIVE)) ||
(teamplay && (ValidModes & TEAMGAME));
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionUsesAmmo : StatusbarCondition
{
enum AmmoModes
{
AMMO1,
AMMO2,
AMMO_ANY,
AMMO_BOTH
};
private int ValidModes;
private bool Negate;
void Init(int modemask, bool neg = false)
{
ValidModes = modemask;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
let w = stbar.CPlayer.ReadyWeapon;
if (w == null) return false;
bool usesammo1 = w.AmmoType1 != NULL;
bool usesammo2 = w.AmmoType2 != NULL;
if (ValidModes == AMMO1) return usesammo1 ^ Negate;
else if (ValidModes == AMMO2) return usesammo2 ^ Negate;
if (ValidModes == AMMO_ANY) return (usesammo1 || usesammo2) ^ Negate;
if (ValidModes == AMMO_BOTH) return (usesammo1 && usesammo2) ^ Negate;
return -1;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionInventoryBarVisible : StatusbarCondition
{
private bool Negate;
void Init(bool neg = false)
{
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
return (stbar.CPlayer.inventorytics <= 0 || level.NoInventoryBar) ^ Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionAspectRatio : StatusbarCondition
{
private double MinValid, MaxValid;
private bool Negate;
void Init(double min, double max, bool neg = false)
{
MinValid = min;
MaxValid = max;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
double aspect = screen.GetAspectRatio();
return (aspect >= MinValid && aspect < MaxValid) ^ Negate;
}
}
//---------------------------------------------------------------------------
//
// uses two names, like SBARINFO
//
//---------------------------------------------------------------------------
class SBConditionWeaponSelected : StatusbarCondition
{
private class<Weapon> Weap1, Weap2;
private bool Negate;
private bool CheckSister;
void Init(class<Weapon> w1, class<Weapon> w2, bool sister = false, bool neg = false)
{
Weap1 = w1;
Weap2 = w2;
CheckSister = sister;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
let w = stbar.CPlayer.ReadyWeapon;
return (w != null && ((w.GetClass() == Weap1 || w.GetClass() == Weap2) || (CheckSister && w.SisterWeapon != null && (w.SisterWeapon.GetClass() == Weap1 || w.SisterWeapon.GetClass() == Weap2)))) ^ Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionPlayerclass : StatusbarCondition
{
private Name PlayerClasses[6];
private bool Negate;
void Init(Name p1, Name p2 = 'none', Name p3 = 'none', Name p4 = 'none', Name p5 = 'none', Name p6 = 'none', bool neg = false)
{
PlayerClasses[0] = p1;
PlayerClasses[1] = p2;
PlayerClasses[2] = p3;
PlayerClasses[3] = p4;
PlayerClasses[4] = p5;
PlayerClasses[5] = p6;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
Name dn = PlayerPawn.GetPrintableDisplayName(stbar.CPlayer.mo.GetClass());
for(int i=0; i<6; i++)
{
if (PlayerClasses[i] != 'none' && dn == PlayerPawn.GetPrintableDisplayName(PlayerClasses[i])) return !Negate;
}
return Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionPlayerType : StatusbarCondition
{
private class<PlayerPawn> PlayerClasses[6];
private bool Negate;
void Init(class<PlayerPawn> p1, class<PlayerPawn> p2, class<PlayerPawn> p3, class<PlayerPawn> p4, class<PlayerPawn> p5, class<PlayerPawn> p6, bool neg = false)
{
PlayerClasses[0] = p1;
PlayerClasses[1] = p2;
PlayerClasses[2] = p3;
PlayerClasses[3] = p4;
PlayerClasses[4] = p5;
PlayerClasses[5] = p6;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
for(int i=0; i<6; i++)
{
if (PlayerClasses[i] != null && stbar.CPlayer.mo is PlayerClasses[i]) return !Negate;
}
return Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionHasWeaponPiece : StatusbarCondition
{
private class<Weapon> Weap1;
private int PieceNum;
private bool Negate;
void Init(class<Weapon> w1, int piecenum, bool neg = false)
{
Weap1 = w1;
PieceNum = piecenum - 1;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
for(let inv = stbar.CPlayer.mo.Inv; inv != NULL; inv = inv.Inv)
{
let wh = WeaponHolder(inv);
if (wh.PieceWeapon == Weap1)
{
return (!!(wh.PieceMask & (1 << PieceNum))) ^ Negate;
}
}
return Negate;
}
}
//---------------------------------------------------------------------------
//
// Checks if the current weapon uses the given ammo types.
//
//---------------------------------------------------------------------------
class SBConditionWeaponUsesAmmo : StatusbarCondition
{
enum AmmoModes
{
AMMO1,
AMMO2,
AMMO_ANY,
AMMO_BOTH
};
private class<Ammo> AmmoType1, AmmoType2;
private int ValidModes;
private bool Negate;
void Init(class<Ammo> ammotype_1, class<Ammo> ammotype_2, int modemask, bool neg = false)
{
AmmoType1 = ammotype_1;
AmmoType2 = ammotype_2;
ValidModes = modemask;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
let w = stbar.CPlayer.ReadyWeapon;
if (w == NULL) return false;
let WeapType1 = w.AmmoType1;
let WeapType2 = w.AmmoType2;
bool usesammo1 = WeapType1 != NULL;
bool usesammo2 = WeapType2 != NULL;
if(AmmoType2 != NULL)
{
bool match1 = ((usesammo1 && (AmmoType1 == WeapType1 || AmmoType2 == WeapType1)) || !usesammo1);
bool match2 = ((usesammo1 && (AmmoType1 == WeapType2 || AmmoType2 == WeapType2)) || !usesammo2);
if (ValidModes == AMMO1) return match1 ^ Negate;
if (ValidModes == AMMO2) return match2 ^ Negate;
if (ValidModes == AMMO_ANY) return (match1 || match2) ^ Negate;
if (ValidModes == AMMO_BOTH) return (match1 && match2) ^ Negate;
return -1;
}
else
{
if((usesammo1 && (WeapType1 == AmmoType1)) || (usesammo2 && (WeapType2 == AmmoType1)))
{
return !Negate;
}
}
return Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionHealth : StatusbarCondition
{
private int amount;
private bool Negate;
private bool percentage;
void Init(int amt, bool percent, bool neg = false)
{
amount = amt;
percentage = percent;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
int phealth = percentage ? stbar.CPlayer.mo.health * 100 / stbar.CPlayer.mo.GetMaxHealth() : stbar.CPlayer.mo.health;
return (phealth >= Amount) ^ Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionInvulnerable : StatusbarCondition
{
private bool Negate;
void Init(bool neg = false)
{
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
return ((stbar.CPlayer.mo.bInvulnerable) || (stbar.CPlayer.cheats & (CF_GODMODE | CF_GODMODE2))) ^ Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionWaterLevel : StatusbarCondition
{
private int amount;
private bool Negate;
void Init(int amt, bool neg = false)
{
amount = amt;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
return (stbar.CPlayer.mo.waterlevel >= amount) ^ Negate;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionCVarNumeric : StatusbarCondition
{
enum EOp
{
LESS,
LESSEQ,
EQ,
NEQ,
GREATEREQ,
GREATER
};
private String cv;
private int Operator;
private double Value;
void Init(String cvname, int op, double val)
{
cv = cvname;
Operator = op;
Value = val;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
let cvr = CVar.FindCVar(cv, stbar.CPlayer);
if (cvr == null) return -1;
double val = cvr.GetFloat();
switch (Operator)
{
case LESS:
return val < Value;
case LESSEQ:
return val <= Value;
case EQ:
return val ~== Value;
case NEQ:
return !(val ~== Value);
case GREATEREQ:
return val >= Value;
case GREATER:
return val > Value;
}
return -1;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class SBConditionInInventory : StatusbarCondition
{
enum AmmoModes
{
ITEM1,
ITEM2,
ITEM_ANY,
ITEM_BOTH
};
private class<Inventory> InventoryType1, InventoryType2;
private int Amount1, Amount2;
private int ValidModes;
private bool Negate;
void Init(class<Inventory> Inventorytype_1, int am1, class<Inventory> Inventorytype_2, int am2, int modemask, bool neg = false)
{
InventoryType1 = Inventorytype_1;
InventoryType2 = Inventorytype_2;
Amount1 = am1;
Amount2 = am2;
ValidModes = modemask;
Negate = neg;
}
override int Condition(WidgetStatusBar stbar)
{
if (stbar.CPlayer == null) return -1;
let it1 = stbar.CPlayer.mo.FindInventory(InventoryType1);
let it2 = stbar.CPlayer.mo.FindInventory(InventoryType2);
if (it1 != NULL && amount1 > 0 && it1.Amount < amount1) it1 = NULL;
if (it2 != NULL && amount2 > 0 && it2.Amount < amount2) it2 = NULL;
if (ValidModes == ITEM1) return (!!it1) ^ Negate;
if (ValidModes == ITEM2) return (!!it2) ^ Negate;
if (ValidModes == ITEM_ANY) return (it1 || it2) ^ Negate;
if (ValidModes == ITEM_BOTH) return (it1 && it2) ^ Negate;
return -1;
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class WidgetStatusBar : BaseStatusBar
{
private StatusbarHead Head;
StatusbarWidget Begin()
{
Head = new("StatusbarHead");
Head.Owner = Head;
Head.Children = new ("StatusbarWidget");
Head.Children.Owner = Head;
return Head.Children;
}
// this is just copied from SBARINFO. We may need it.
static Vector2 adjustRelCenter(bool relX, bool relY, Vector2 pos, Vector3 scale)
{
Vector2 outvec;
if(relX)
outvec.X = pos.X + (screen.GetWidth()/(hud_scale ? Scale.X*2 : 2));
else
outvec.X = pos.X;
if(relY)
outvec.Y = pos.y + (screen.GetHeight()/(hud_scale ? Scale.Y*2 : 2));
else
outvec.Y = pos.y;
return outvec;
}
}
/* for testing the above. This block compiles.
class TestWidgets : WidgetStatusBar
{
override void Init()
{
Begin()
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.BeginCondition("StatusbarCondition")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.EndCondition()
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.BeginCondition("StatusbarCondition")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.BeginCondition("StatusbarCondition")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.EndCondition()
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.EndCondition()
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.BeginCondition("StatusbarCondition")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.AppendWidget("StatusbarWidget")
.EndCondition()
.AppendWidget("StatusbarWidget")
.Finish();
}
}
*/

View file

@ -1,5 +1,5 @@
class StrifeStatusBar : BaseStatusBar class StrifeStatusBar : CustomStatusBar
{ {
// Number of tics to move the popscreen up and down. // Number of tics to move the popscreen up and down.
@ -59,6 +59,7 @@ class StrifeStatusBar : BaseStatusBar
override void Init() override void Init()
{ {
Super.Init();
SetSize(32, 320, 200); SetSize(32, 320, 200);
DoCommonInit(); DoCommonInit();
} }
@ -368,20 +369,17 @@ class StrifeStatusBar : BaseStatusBar
protected void DrawFullScreenStuff () protected void DrawFullScreenStuff ()
{ {
fullscreenoffsets = true;
// Draw health // Draw health
DrINumberOuter (CPlayer.health, 4, -10, false, 7); DrINumberOuter (CPlayer.health, 4, -10, false, 7);
screen.DrawTexture (Images[imgMEDI], true, 14, -17, DrawTexture(Images[imgMEDI], (14, -17), false, 1.0, BOTTOM|LEFT, itemalign: BOTTOM|HCENTER);
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true);
// Draw armor // Draw armor
let armor = CPlayer.mo.FindInventory('BasicArmor'); let armor = CPlayer.mo.FindInventory('BasicArmor');
if (armor != NULL && armor.Amount != 0) if (armor != NULL && armor.Amount != 0)
{ {
DrINumberOuter (armor.Amount, 35, -10, false, 7); DrINumberOuter (armor.Amount, 35, -10, false, 7);
screen.DrawTexture (armor.Icon, true, 45, -17, DrawTexture(armor.Icon, (45, -17), false, 1.0, BOTTOM|LEFT, itemalign: BOTTOM|HCENTER);
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true);
} }
// Draw ammo // Draw ammo
@ -393,16 +391,12 @@ class StrifeStatusBar : BaseStatusBar
{ {
// Draw primary ammo in the bottom-right corner // Draw primary ammo in the bottom-right corner
DrINumberOuter (ammo1.Amount, -23, -10, false, 7); DrINumberOuter (ammo1.Amount, -23, -10, false, 7);
screen.DrawTexture (ammo1.Icon, true, -14, -17, DrawTexture(ammo1.Icon, (-14, -17), false, 1.0, BOTTOM|RIGHT, itemalign: BOTTOM|HCENTER);
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true);
if (ammo2 != NULL && ammo1!=ammo2) if (ammo2 != NULL && ammo1!=ammo2)
{ {
// Draw secondary ammo just above the primary ammo // Draw secondary ammo just above the primary ammo
DrINumberOuter (ammo2.Amount, -23, -48, false, 7); DrINumberOuter (ammo2.Amount, -23, -48, false, 7);
screen.DrawTexture (ammo2.Icon, -14, -55, DrawTexture(ammo1.Icon, (-14, -55), false, 1.0, BOTTOM|RIGHT, itemalign: BOTTOM|HCENTER);
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true);
} }
} }
@ -458,6 +452,7 @@ class StrifeStatusBar : BaseStatusBar
} }
} }
} }
fullscreenoffsets = false;
} }
protected void DrawPopScreen (int bottom, double TicFrac) protected void DrawPopScreen (int bottom, double TicFrac)