diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1896c3ab87..b9100ff28b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1096,7 +1096,6 @@ set (PCH_SOURCES g_statusbar/sbarinfo.cpp g_statusbar/sbar_mugshot.cpp g_statusbar/shared_sbar.cpp - g_statusbar/strife_sbar.cpp gl/compatibility/gl_20.cpp gl/data/gl_data.cpp gl/data/gl_portaldata.cpp diff --git a/src/am_map.cpp b/src/am_map.cpp index e621425903..1922b967c8 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -1452,7 +1452,6 @@ void AM_ToggleMap () if (dmflags2 & DF2_NO_AUTOMAP) return; - ST_SetNeedRefresh(); if (!automapactive) { AM_Start (); @@ -1463,7 +1462,6 @@ void AM_ToggleMap () if (am_overlay==1 && viewactive) { viewactive = false; - ST_SetNeedRefresh(); } else { diff --git a/src/b_game.cpp b/src/b_game.cpp index 1f32182f60..f8c15b1a05 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -387,11 +387,6 @@ bool FCajunMaster::DoAddBot (uint8_t *info, botskill_t skill) Printf ("%s joined the game\n", players[bnum].userinfo.GetName()); G_DoReborn (bnum, true); - if (StatusBar != NULL) - { - StatusBar->MultiplayerChanged (); - } - return true; } @@ -414,7 +409,7 @@ void FCajunMaster::RemoveAllBots (bool fromlist) players[j].camera = players[j].mo; if (j == consoleplayer) { - StatusBar->AttachToPlayer (players + j); + StatusBar->CallAttachToPlayer (players + j); } } } diff --git a/src/c_console.cpp b/src/c_console.cpp index 18e99af5f8..e2ffe2ec61 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1296,7 +1296,6 @@ void C_DrawConsole (bool hw2d) { screen->Dim (PalEntry ((unsigned char)(player->BlendR*255), (unsigned char)(player->BlendG*255), (unsigned char)(player->BlendB*255)), player->BlendA, 0, ConBottom, screen->GetWidth(), screen->GetHeight() - ConBottom); - ST_SetNeedRefresh(); V_SetBorderNeedRefresh(); } } diff --git a/src/d_main.cpp b/src/d_main.cpp index 26df11577e..3dd1a42384 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -473,7 +473,7 @@ CUSTOM_CVAR (Int, dmflags2, 0, CVAR_SERVERINFO) p->camera = p->mo; S_UpdateSounds (p->camera); - StatusBar->AttachToPlayer (p); + StatusBar->CallAttachToPlayer (p); if (demoplayback || multiplayer) StatusBar->ShowPlayerName (); @@ -686,7 +686,7 @@ void D_Display () // Let the status bar know the screen size changed if (StatusBar != NULL) { - StatusBar->ScreenSizeChanged (); + StatusBar->CallScreenSizeChanged (); } // Refresh the console. C_NewModeAdjust (); @@ -707,7 +707,6 @@ void D_Display () if (screen->Lock (false)) { - ST_SetNeedRefresh(); V_SetBorderNeedRefresh(); } @@ -785,7 +784,6 @@ void D_Display () if ((hw2d = screen->Begin2D(viewactive))) { // Redraw everything every frame when using 2D accel - ST_SetNeedRefresh(); V_SetBorderNeedRefresh(); } Renderer->DrawRemainingPlayerSprites(); @@ -813,7 +811,7 @@ void D_Display () { StatusBar->DrawCrosshair(); } - StatusBar->Draw (HUD_AltHud); + StatusBar->CallDraw (HUD_AltHud); StatusBar->DrawTopStuff (HUD_AltHud); } else @@ -821,13 +819,13 @@ void D_Display () { EHudState state = DrawFSHUD ? HUD_Fullscreen : HUD_None; StatusBar->DrawBottomStuff (state); - StatusBar->Draw (state); + StatusBar->CallDraw (state); StatusBar->DrawTopStuff (state); } else { StatusBar->DrawBottomStuff (HUD_StatusBar); - StatusBar->Draw (HUD_StatusBar); + StatusBar->CallDraw (HUD_StatusBar); StatusBar->DrawTopStuff (HUD_StatusBar); } CT_Drawer (); diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 70413496c4..99e5eb1289 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -342,7 +342,7 @@ static void UpdateTeam (int pnum, int team, bool update) R_BuildPlayerTranslation (pnum); if (StatusBar != NULL && StatusBar->GetPlayer() == pnum) { - StatusBar->AttachToPlayer (&players[pnum]); + StatusBar->CallAttachToPlayer (&players[pnum]); } // Double-check if (!TeamLibrary.IsValidTeam (team)) @@ -884,7 +884,7 @@ void D_ReadUserInfoStrings (int pnum, uint8_t **stream, bool update) R_BuildPlayerTranslation(pnum); if (StatusBar != NULL && pnum == StatusBar->GetPlayer()) { - StatusBar->AttachToPlayer(&players[pnum]); + StatusBar->CallAttachToPlayer(&players[pnum]); } } } diff --git a/src/g_game.cpp b/src/g_game.cpp index 92ccc65556..deee688628 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -923,7 +923,7 @@ static void ChangeSpy (int changespy) players[consoleplayer].camera = players[pnum].mo; S_UpdateSounds(players[consoleplayer].camera); - StatusBar->AttachToPlayer (&players[pnum]); + StatusBar->CallAttachToPlayer (&players[pnum]); if (demoplayback || multiplayer) { StatusBar->ShowPlayerName (); @@ -1823,7 +1823,7 @@ void G_DoPlayerPop(int playernum) players[ii].camera = players[ii].mo; if (ii == consoleplayer && StatusBar != NULL) { - StatusBar->AttachToPlayer(&players[ii]); + StatusBar->CallAttachToPlayer(&players[ii]); } } } @@ -2909,7 +2909,7 @@ bool G_CheckDemoStatus (void) players[0].camera = NULL; if (StatusBar != NULL) { - StatusBar->AttachToPlayer (&players[0]); + StatusBar->CallAttachToPlayer (&players[0]); } if (singledemo || timingdemo) { diff --git a/src/g_level.cpp b/src/g_level.cpp index fec1050ad3..c77c10fe98 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -328,7 +328,6 @@ void G_NewInit () } G_ClearSnapshots (); - ST_SetNeedRefresh(); netgame = false; multiplayer = multiplayernext; multiplayernext = false; @@ -485,7 +484,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) } } GC::WriteBarrier(StatusBar); - StatusBar->AttachToPlayer (&players[consoleplayer]); + StatusBar->CallAttachToPlayer (&players[consoleplayer]); StatusBar->NewGame (); setsizeneeded = true; @@ -1091,7 +1090,7 @@ void G_DoLoadLevel (int position, bool autosave) FBehavior::StaticStartTypedScripts(SCRIPT_Reopen, NULL, false); } - StatusBar->AttachToPlayer (&players[consoleplayer]); + StatusBar->CallAttachToPlayer (&players[consoleplayer]); // unsafe world load E_WorldLoadedUnsafe(); // regular world load (savegames are handled internally) diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 689bdc4ac8..fc8aec70bf 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -43,8 +43,6 @@ class player_t; struct FRemapTable; -extern int SB_state; - enum EHudState { HUD_StatusBar, @@ -56,8 +54,6 @@ enum EHudState class AWeapon; -void ST_SetNeedRefresh(); - bool ST_IsTimeVisible(); bool ST_IsLatencyVisible(); @@ -341,7 +337,7 @@ public: ST_DEADFACE = ST_GODFACE + 1 }; - DBaseStatusBar (int reltop, int hres=320, int vres=200); + DBaseStatusBar (int reltop = 32, int hres=320, int vres=200); void OnDestroy() override; void AttachMessage (DHUDMessage *msg, uint32_t id=0, int layer=HUDMSGLayer_Default); @@ -358,19 +354,23 @@ public: void SerializeMessages(FSerializer &arc); virtual void SetScaled(bool scale, bool force = false); + void CallSetScaled(bool scale, bool force = false); virtual void Tick (); + void CallTick(); virtual void Draw (EHudState state); + void CallDraw(EHudState state); void DrawBottomStuff (EHudState state); void DrawTopStuff (EHudState state); virtual void FlashItem (const PClass *itemtype); virtual void AttachToPlayer (player_t *player); + void CallAttachToPlayer(player_t *player); virtual void FlashCrosshair (); virtual void BlendView (float blend[4]); virtual void NewGame (); virtual void ScreenSizeChanged (); - virtual void MultiplayerChanged (); - virtual void SetInteger (int pname, int param); + void CallScreenSizeChanged(); virtual void ShowPop (int popnum); + void CallShowPop(int popnum); virtual void ReceivedWeapon (AWeapon *weapon); virtual bool MustDrawLog(EHudState state); virtual void SetMugShotState (const char *state_name, bool wait_till_done=false, bool reset=false); @@ -383,7 +383,7 @@ public: } -protected: +//protected: void DrawPowerups (); @@ -410,7 +410,6 @@ public: player_t *CPlayer; private: - DBaseStatusBar() {} bool RepositionCoords (int &x, int &y, int xo, int yo, const int w, const int h) const; void DrawMessages (int layer, int bottom); void DrawConsistancy () const; diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 7be5073ef1..f8e6087b4d 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -87,7 +87,6 @@ DBaseStatusBar *StatusBar; extern int setblocks; int gST_X, gST_Y; -int SB_state = 3; FTexture *CrosshairImage; static int CrosshairNum; @@ -107,7 +106,7 @@ CUSTOM_CVAR (Bool, st_scale, true, CVAR_ARCHIVE) { if (StatusBar) { - StatusBar->SetScaled (self); + StatusBar->CallSetScaled (self); setsizeneeded = true; } } @@ -219,17 +218,6 @@ void ST_Clear() CrosshairNum = 0; } -//--------------------------------------------------------------------------- -// -// ST_SetNeedRefresh -// -//--------------------------------------------------------------------------- - -void ST_SetNeedRefresh() -{ - SB_state = (StatusBar == NULL || screen == NULL) ? 0 : screen->GetPageCount(); -} - //--------------------------------------------------------------------------- // // Constructor @@ -250,7 +238,7 @@ DBaseStatusBar::DBaseStatusBar (int reltop, int hres, int vres) HorizontalResolution = hres; VerticalResolution = vres; - SetScaled (st_scale); + CallSetScaled (st_scale); } //--------------------------------------------------------------------------- @@ -319,7 +307,25 @@ void DBaseStatusBar::SetScaled (bool scale, bool force) Displacement = 0; } gST_X = ST_X; - ST_SetNeedRefresh(); +} + +DEFINE_ACTION_FUNCTION(DBaseStatusBar, SetScaled) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_BOOL(scale); + PARAM_BOOL_DEF(force); + self->SetScaled(scale, force); + return 0; +} + +void DBaseStatusBar::CallSetScaled(bool scale, bool force) +{ + IFVIRTUAL(DBaseStatusBar, SetScaled) + { + VMValue params[] = { (DObject*)this, scale, force }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } + else SetScaled(scale, force); } //--------------------------------------------------------------------------- @@ -331,7 +337,24 @@ void DBaseStatusBar::SetScaled (bool scale, bool force) void DBaseStatusBar::AttachToPlayer (player_t *player) { CPlayer = player; - ST_SetNeedRefresh(); +} + +DEFINE_ACTION_FUNCTION(DBaseStatusBar, AttachToPlayer) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_POINTER(player, player_t); + self->AttachToPlayer(player); + return 0; +} + +void DBaseStatusBar::CallAttachToPlayer(player_t *player) +{ + IFVIRTUAL(DBaseStatusBar, AttachToPlayer) + { + VMValue params[] = { (DObject*)this, player }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } + else AttachToPlayer(player); } //--------------------------------------------------------------------------- @@ -345,17 +368,6 @@ int DBaseStatusBar::GetPlayer () return int(CPlayer - players); } -//--------------------------------------------------------------------------- -// -// PROC MultiplayerChanged -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::MultiplayerChanged () -{ - ST_SetNeedRefresh(); -} - //--------------------------------------------------------------------------- // // PROC Tick @@ -397,6 +409,23 @@ void DBaseStatusBar::Tick () } } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, Tick) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + self->Tick(); + return 0; +} + +void DBaseStatusBar::CallTick() +{ + IFVIRTUAL(DBaseStatusBar, Tick) + { + VMValue params[] = { (DObject*)this }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } + else Tick(); +} + //--------------------------------------------------------------------------- // // PROC AttachMessage @@ -460,11 +489,6 @@ DHUDMessage *DBaseStatusBar::DetachMessage (DHUDMessage *msg) { *prev = probe->Next; probe->Next = NULL; - // Redraw the status bar in case it was covered - if (screen != NULL) - { - ST_SetNeedRefresh(); - } return probe; } } @@ -487,11 +511,6 @@ DHUDMessage *DBaseStatusBar::DetachMessage (uint32_t id) { *prev = probe->Next; probe->Next = NULL; - // Redraw the status bar in case it was covered - if (screen != NULL) - { - ST_SetNeedRefresh(); - } return probe; } } @@ -589,6 +608,13 @@ void DBaseStatusBar::RefreshBackground () const } } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, RefreshBackground) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + self->RefreshBackground(); + return 0; +} + //--------------------------------------------------------------------------- // // DrawCrosshair @@ -734,7 +760,7 @@ void DBaseStatusBar::Draw (EHudState state) char line[64+10]; - if ((SB_state != 0 || BorderNeedRefresh) && state == HUD_StatusBar) + if (state == HUD_StatusBar) { RefreshBackground (); } @@ -902,6 +928,25 @@ void DBaseStatusBar::Draw (EHudState state) } } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, Draw) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_INT(state); + self->Draw((EHudState)state); + return 0; +} + +void DBaseStatusBar::CallDraw(EHudState state) +{ + IFVIRTUAL(DBaseStatusBar, Draw) + { + VMValue params[] = { (DObject*)this, state, r_viewpoint.TicFrac }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } + else Draw(state); +} + + void DBaseStatusBar::DrawLog () { @@ -959,8 +1004,16 @@ void DBaseStatusBar::DrawLog () } } -bool DBaseStatusBar::MustDrawLog(EHudState) +bool DBaseStatusBar::MustDrawLog(EHudState state) { + IFVIRTUAL(DBaseStatusBar, MustDrawLog) + { + VMValue params[] = { (DObject*)this }; + int rv; + VMReturn ret(&rv); + GlobalVMStack.Call(func, params, countof(params), &ret, 1); + return !!rv; + } return true; } @@ -1154,14 +1207,20 @@ void DBaseStatusBar::DrawWaiting () const void DBaseStatusBar::FlashItem (const PClass *itemtype) { + IFVIRTUAL(DBaseStatusBar, FlashItem) + { + VMValue params[] = { (DObject*)this, (PClass*)itemtype }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } } void DBaseStatusBar::NewGame () { -} - -void DBaseStatusBar::SetInteger (int pname, int param) -{ + IFVIRTUAL(DBaseStatusBar, NewGame) + { + VMValue params[] = { (DObject*)this }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } } void DBaseStatusBar::ShowPop (int popnum) @@ -1169,15 +1228,35 @@ void DBaseStatusBar::ShowPop (int popnum) ShowLog = (popnum == POP_Log && !ShowLog); } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, ShowPop) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_INT(state); + self->ShowPop(state); + return 0; +} + +void DBaseStatusBar::CallShowPop(int pop) +{ + IFVIRTUAL(DBaseStatusBar, ShowPop) + { + VMValue params[] = { (DObject*)this, pop }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } + else ShowPop(pop); +} + + + void DBaseStatusBar::ReceivedWeapon (AWeapon *weapon) { } -DEFINE_ACTION_FUNCTION(_StatusBar, ReceivedWeapon) +DEFINE_ACTION_FUNCTION(DBaseStatusBar, ReceivedWeapon) { - PARAM_PROLOGUE; + PARAM_SELF_PROLOGUE(DBaseStatusBar); PARAM_POINTER(w, AWeapon); - StatusBar->ReceivedWeapon(w); + self->ReceivedWeapon(w); return 0; } @@ -1190,7 +1269,6 @@ void DBaseStatusBar::SerializeMessages(FSerializer &arc) void DBaseStatusBar::ScreenSizeChanged () { st_scale.Callback (); - ST_SetNeedRefresh(); for (size_t i = 0; i < countof(Messages); ++i) { @@ -1203,6 +1281,23 @@ void DBaseStatusBar::ScreenSizeChanged () } } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, ScreenSizeChanged) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + self->ScreenSizeChanged(); + return 0; +} + +void DBaseStatusBar::CallScreenSizeChanged() +{ + IFVIRTUAL(DBaseStatusBar, ScreenSizeChanged) + { + VMValue params[] = { (DObject*)this }; + GlobalVMStack.Call(func, params, countof(params), nullptr, 0); + } + else ScreenSizeChanged(); +} + //--------------------------------------------------------------------------- // // ValidateInvFirst @@ -1294,6 +1389,14 @@ AInventory *DBaseStatusBar::ValidateInvFirst (int numVisible) const } } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, ValidateInvFirst) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_INT(num); + ACTION_RETURN_POINTER(self->ValidateInvFirst(num)); +} + + //============================================================================ // // DBaseStatusBar :: GetCurrentAmmo @@ -1323,6 +1426,20 @@ void DBaseStatusBar::GetCurrentAmmo (AInventory *&ammo1, AInventory *&ammo2, int ammocount2 = ammo2 != NULL ? ammo2->Amount : 0; } +DEFINE_ACTION_FUNCTION(DBaseStatusBar, GetCurrentAmmo) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + AInventory *ammo1, *ammo2; + int ammocount1, ammocount2; + self->GetCurrentAmmo(ammo1, ammo2, ammocount1, ammocount2); + if (numret >= 1) ret[0].SetPointer(ammo1, ATAG_OBJECT); + if (numret >= 2) ret[1].SetPointer(ammo2, ATAG_OBJECT); + if (numret >= 3) ret[2].SetInt(ammocount1); + if (numret >= 4) ret[3].SetInt(ammocount2); + return MIN(numret, 4); +} + + //============================================================================ // // CCMD showpop @@ -1344,6 +1461,32 @@ CCMD (showpop) { popnum = 0; } - StatusBar->ShowPop (popnum); + StatusBar->CallShowPop (popnum); } } + +DEFINE_FIELD(DBaseStatusBar, ST_X); +DEFINE_FIELD(DBaseStatusBar, ST_Y); +DEFINE_FIELD(DBaseStatusBar, RelTop); +DEFINE_FIELD(DBaseStatusBar, HorizontalResolution); +DEFINE_FIELD(DBaseStatusBar, VerticalResolution); +DEFINE_FIELD(DBaseStatusBar, Scaled); +DEFINE_FIELD(DBaseStatusBar, Centering); +DEFINE_FIELD(DBaseStatusBar, FixedOrigin); +DEFINE_FIELD(DBaseStatusBar, CompleteBorder); +DEFINE_FIELD(DBaseStatusBar, CrosshairSize); +DEFINE_FIELD(DBaseStatusBar, Displacement); +DEFINE_FIELD(DBaseStatusBar, CPlayer); +DEFINE_GLOBAL(StatusBar); + + +DBaseStatusBar *CreateStrifeStatusBar() +{ + auto sb = (DBaseStatusBar *)PClass::FindClass("StrifeStatusBar")->CreateNew(); + IFVIRTUALPTR(sb, DBaseStatusBar, Init) + { + VMValue params[] = { sb }; + GlobalVMStack.Call(func, params, 1, nullptr, 0); + } + return sb; +} diff --git a/src/g_statusbar/strife_sbar.cpp b/src/g_statusbar/strife_sbar.cpp deleted file mode 100644 index 13410e8f86..0000000000 --- a/src/g_statusbar/strife_sbar.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -#include "doomtype.h" -#include "doomstat.h" -#include "v_font.h" -#include "v_video.h" -#include "sbar.h" -#include "r_defs.h" -#include "w_wad.h" -#include "m_random.h" -#include "d_player.h" -#include "st_stuff.h" -#include "r_utility.h" -#include "m_swap.h" -#include "templates.h" -#include "a_keys.h" -#include "gi.h" -#include "g_level.h" -#include "colormatcher.h" -#include "v_palette.h" -#include "cmdlib.h" -#include "g_levellocals.h" - -// Number of tics to move the popscreen up and down. -#define POP_TIME (TICRATE/8) - -// Popscreen height when fully extended -#define POP_HEIGHT 104 - -// Number of tics to scroll keys left -#define KEY_TIME (TICRATE/3) - -class FHealthBar : public FTexture -{ -public: - FHealthBar (); - - const uint8_t *GetColumn (unsigned int column, const Span **spans_out); - const uint8_t *GetPixels (); - bool CheckModified (); - - void SetVial (int level); - -protected: - uint8_t Pixels[200*2]; - uint8_t Colors[8]; - static const Span DummySpan[2]; - - int VialLevel; - bool NeedRefresh; - - void MakeTexture (); - void FillBar (int min, int max, uint8_t light, uint8_t dark); -}; - -const FTexture::Span FHealthBar::DummySpan[2] = { { 0, 2 }, { 0, 0 } }; - -FHealthBar::FHealthBar () -: VialLevel(0), NeedRefresh(false) -{ - int i; - - static const uint8_t rgbs[8*3] = - { - 180, 228, 128, // light green - 128, 180, 80, // dark green - - 196, 204, 252, // light blue - 148, 152, 200, // dark blue - - 224, 188, 0, // light gold - 208, 128, 0, // dark gold - - 216, 44, 44, // light red - 172, 28, 28 // dark red - }; - - Width = 200; - Height = 2; - WidthBits = 8; - HeightBits = 1; - WidthMask = 255; - - for (i = 0; i < 8; ++i) - { - Colors[i] = ColorMatcher.Pick (rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]); - } -} - -bool FHealthBar::CheckModified () -{ - return NeedRefresh; -} - -const uint8_t *FHealthBar::GetColumn (unsigned int column, const Span **spans_out) -{ - if (NeedRefresh) - { - MakeTexture (); - } - if (column > 199) - { - column = 199; - } - if (spans_out != NULL) - { - *spans_out = &DummySpan[column >= (unsigned int)VialLevel*2]; - } - return Pixels + column*2; -} - -const uint8_t *FHealthBar::GetPixels () -{ - if (NeedRefresh) - { - MakeTexture (); - } - return Pixels; -} - -void FHealthBar::SetVial (int level) -{ - if (level < 0) - { - level = 0; - } - else if (level > 200 && level != 999) - { - level = 200; - } - if (VialLevel != level) - { - VialLevel = level; - NeedRefresh = true; - } -} - -void FHealthBar::MakeTexture () -{ - if (VialLevel == 999) - { - FillBar (0, 100, Colors[4], Colors[5]); - } - else - { - if (VialLevel <= 100) - { - if (VialLevel <= 10) - { - FillBar (0, VialLevel, Colors[6], Colors[7]); - } - else if (VialLevel <= 20) - { - FillBar (0, VialLevel, Colors[4], Colors[5]); - } - else - { - FillBar (0, VialLevel, Colors[0], Colors[1]); - } - FillBar (VialLevel, 100, 0, 0); - } - else - { - int stop = 100 - (VialLevel - 100); - FillBar (0, stop, Colors[0], Colors[1]); - FillBar (stop, 100, Colors[2], Colors[3]); - } - } -} - -void FHealthBar::FillBar (int min, int max, uint8_t light, uint8_t dark) -{ - for (int i = min*2; i < max*2; i++) - { - Pixels[i * 2] = light; - Pixels[i * 2 + 1] = dark; - } -} - -class DStrifeStatusBar : public DBaseStatusBar -{ - DECLARE_CLASS(DStrifeStatusBar, DBaseStatusBar) -public: - DStrifeStatusBar () : DBaseStatusBar (32) - { - DoCommonInit (); - } - - ~DStrifeStatusBar () - { - } - - void NewGame () - { - Images.Uninit (); - DoCommonInit (); - if (CPlayer != NULL) - { - AttachToPlayer (CPlayer); - } - } - - void Draw (EHudState state) - { - DBaseStatusBar::Draw (state); - - if (state == HUD_StatusBar) - { - if (SB_state != 0) - { - SB_state--; - } - DrawMainBar (); - } - else - { - if (state == HUD_Fullscreen) - { - ST_SetNeedRefresh(); - DrawFullScreenStuff (); - } - - // Draw pop screen (log, keys, and status) - if (CurrentPop != POP_None && PopHeight < 0) - { - DrawPopScreen (screen->GetHeight()); - } - } - } - - void ShowPop (int popnum) - { - DBaseStatusBar::ShowPop(popnum); - if (popnum == CurrentPop) - { - if (popnum == POP_Keys) - { - AInventory *item; - int i; - - KeyPopPos += 10; - KeyPopScroll = 280; - - for (item = CPlayer->mo->Inventory, i = 0; - item != NULL; - item = item->Inventory) - { - if (item->IsKindOf (PClass::FindActor(NAME_Key))) - { - if (i == KeyPopPos) - { - return; - } - i++; - } - } - } - PendingPop = POP_None; - // Do not scroll keys horizontally when dropping the popscreen - KeyPopScroll = 0; - KeyPopPos -= 10; - } - else - { - KeyPopPos = 0; - PendingPop = popnum; - } - } - - bool MustDrawLog(EHudState state) - { - // Tell the base class to draw the log if the pop screen won't be displayed. - return false; - } - -private: - void DoCommonInit () - { - static const char *strifeLumpNames[] = - { - "INVCURS", "CURSOR01", "INVBACK", "INVTOP", "INVPOP", "INVPOP2", - "INVPBAK", "INVPBAK2", - "INVFONG0", "INVFONG1", "INVFONG2", "INVFONG3", "INVFONG4", - "INVFONG5", "INVFONG6", "INVFONG7", "INVFONG8", "INVFONG9", - "INVFONG%", - "INVFONY0", "INVFONY1", "INVFONY2", "INVFONY3", "INVFONY4", - "INVFONY5", "INVFONY6", "INVFONY7", "INVFONY8", "INVFONY9", - "INVFONY%", - "I_COMM", "I_MDKT", "I_ARM1", "I_ARM2", nullptr - - }; - - Images.Init (strifeLumpNames, countof(strifeLumpNames)); - - CursorImage = Images[imgINVCURS] != NULL ? imgINVCURS : imgCURSOR01; - - ST_SetNeedRefresh(); - - CurrentPop = POP_None; - PendingPop = POP_NoChange; - PopHeight = 0; - KeyPopPos = 0; - KeyPopScroll = 0; - ItemFlash = 0; - } - - void Tick () - { - DBaseStatusBar::Tick (); - - if (ItemFlash > 0) - { - ItemFlash -= 1/14.; - if (ItemFlash < 0) - { - ItemFlash = 0; - } - } - - PopHeightChange = 0; - if (PendingPop != POP_NoChange) - { - if (PopHeight < 0) - { - PopHeightChange = POP_HEIGHT / POP_TIME; - PopHeight += POP_HEIGHT / POP_TIME; - } - else - { - CurrentPop = PendingPop; - PendingPop = POP_NoChange; - } - } - else - { - if (CurrentPop == POP_None) - { - PopHeight = 0; - } - else if (PopHeight > -POP_HEIGHT) - { - PopHeight -= POP_HEIGHT / POP_TIME; - if (PopHeight < -POP_HEIGHT) - { - PopHeight = -POP_HEIGHT; - } - else - { - PopHeightChange = -POP_HEIGHT / POP_TIME; - } - } - if (KeyPopScroll > 0) - { - KeyPopScroll -= 280 / KEY_TIME; - if (KeyPopScroll < 0) - { - KeyPopScroll = 0; - } - } - } - } - - void FlashItem (const PClass *itemtype) - { - ItemFlash = 0.75; - } - - void DrawMainBar () - { - AInventory *item; - int i; - - // Pop screen (log, keys, and status) - if (CurrentPop != POP_None && PopHeight < 0) - { - DrawPopScreen (Scaled ? (ST_Y - 8) * screen->GetHeight() / 200 : ST_Y - 8); - } - - DrawImage (Images[imgINVBACK], 0, 0); - DrawImage (Images[imgINVTOP], 0, -8); - - // Health - DrINumber (CPlayer->health, 79, -6, imgFONG0); - if (CPlayer->cheats & CF_GODMODE) - { - HealthBar.SetVial (999); - } - else - { - HealthBar.SetVial (CPlayer->health); - } - DrawImage (&HealthBar, 49, 4); - DrawImage (&HealthBar, 49, 7); - - // Armor - item = CPlayer->mo->FindInventory(NAME_BasicArmor); - if (item != NULL && item->Amount > 0) - { - DrawImage (TexMan(item->Icon), 2, 9); - DrINumber (item->Amount, 27, 23, imgFONY0); - } - - // Ammo - AInventory *ammo1, *ammo2; - int ammocount1, ammocount2; - - GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2); - if (ammo1 != NULL) - { - DrINumber (ammo1->Amount, 311, -6, imgFONG0); - DrawImage (TexMan(ammo1->Icon), 290, 13); - if (ammo2 != NULL) - { -/* int y = MIN (-5 - BigHeight, -5 - TexMan(ammo1->Icon)->GetHeight()); - screen->DrawTexture (TexMan(ammo2->Icon), -14, y, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - DrBNumberOuterFont (ammo2->Amount, -67, y - BigHeight); -*/ } - } - - // Sigil - item = CPlayer->mo->FindInventory(NAME_Sigil); - if (item != NULL) - { - DrawImage (TexMan(item->Icon), 253, 7); - } - - // Inventory - CPlayer->inventorytics = 0; - CPlayer->mo->InvFirst = ValidateInvFirst (6); - for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 6; item = item->NextInv(), ++i) - { - if (item == CPlayer->mo->InvSel) - { - screen->DrawTexture (Images[CursorImage], - 42 + 35*i + ST_X, 12 + ST_Y, - DTA_Bottom320x200, Scaled, - DTA_Alpha, 1. - ItemFlash, - TAG_DONE); - } - if (item->Icon.isValid()) - { - DrawDimImage (TexMan(item->Icon), 48 + 35*i, 14, item->Amount <= 0); - } - DrINumber (item->Amount, 74 + 35*i, 23, imgFONY0); - } - } - - void DrawFullScreenStuff () - { - // Draw health - DrINumberOuter (CPlayer->health, 4, -10, false, 7); - screen->DrawTexture (Images[imgMEDI], 14, -17, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - - // Draw armor - auto armor = CPlayer->mo->FindInventory(NAME_BasicArmor); - if (armor != NULL && armor->Amount != 0) - { - DrINumberOuter (armor->Amount, 35, -10, false, 7); - screen->DrawTexture (TexMan(armor->Icon), 45, -17, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - } - - // Draw ammo - AInventory *ammo1, *ammo2; - int ammocount1, ammocount2; - - GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2); - if (ammo1 != NULL) - { - // Draw primary ammo in the bottom-right corner - DrINumberOuter (ammo1->Amount, -23, -10, false, 7); - screen->DrawTexture (TexMan(ammo1->Icon), -14, -17, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - if (ammo2 != NULL && ammo1!=ammo2) - { - // Draw secondary ammo just above the primary ammo - DrINumberOuter (ammo2->Amount, -23, -48, false, 7); - screen->DrawTexture (TexMan(ammo2->Icon), -14, -55, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - TAG_DONE); - } - } - - if (deathmatch) - { // Draw frags (in DM) - DrBNumberOuterFont (CPlayer->fragcount, -44, 1); - } - - // Draw inventory - if (CPlayer->inventorytics == 0) - { - if (CPlayer->mo->InvSel != 0) - { - if (ItemFlash > 0) - { - FTexture *cursor = Images[CursorImage]; - screen->DrawTexture (cursor, -28, -15, - DTA_HUDRules, HUD_Normal, - DTA_LeftOffset, cursor->GetWidth(), - DTA_TopOffset, cursor->GetHeight(), - DTA_Alpha, ItemFlash, - TAG_DONE); - } - DrINumberOuter (CPlayer->mo->InvSel->Amount, -51, -10, false, 7); - screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -42, -17, - DTA_HUDRules, HUD_Normal, - DTA_CenterBottomOffset, true, - DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, - TAG_DONE); - } - } - else - { - CPlayer->mo->InvFirst = ValidateInvFirst (6); - int i = 0; - AInventory *item; - if (CPlayer->mo->InvFirst != NULL) - { - for (item = CPlayer->mo->InvFirst; item != NULL && i < 6; item = item->NextInv(), ++i) - { - if (item == CPlayer->mo->InvSel) - { - screen->DrawTexture (Images[CursorImage], -100+i*35, -21, - DTA_HUDRules, HUD_HorizCenter, - DTA_Alpha, 0.75, - TAG_DONE); - } - if (item->Icon.isValid()) - { - screen->DrawTexture (TexMan(item->Icon), -94 + i*35, -19, - DTA_HUDRules, HUD_HorizCenter, - DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY, - TAG_DONE); - } - DrINumberOuter (item->Amount, -89 + i*35, -10, true, 7); - } - } - } - } - - void DrawPopScreen (int bottom) - { - char buff[64]; - const char *label; - int i; - AInventory *item; - int xscale, yscale, left, top; - int bars = (CurrentPop == POP_Status) ? imgINVPOP : imgINVPOP2; - int back = (CurrentPop == POP_Status) ? imgINVPBAK : imgINVPBAK2; - // Extrapolate the height of the popscreen for smoother movement - int height = clamp (PopHeight + int(r_viewpoint.TicFrac * PopHeightChange), -POP_HEIGHT, 0); - - xscale = CleanXfac; - yscale = CleanYfac; - left = screen->GetWidth()/2 - 160*CleanXfac; - top = bottom + height * yscale; - - screen->DrawTexture (Images[back], left, top, DTA_CleanNoMove, true, DTA_Alpha, 0.75, TAG_DONE); - screen->DrawTexture (Images[bars], left, top, DTA_CleanNoMove, true, TAG_DONE); - - - switch (CurrentPop) - { - case POP_Log: - { - int seconds = Tics2Seconds(level.time); - // Draw the latest log message. - mysnprintf(buff, countof(buff), "%02d:%02d:%02d", - seconds / 3600, - (seconds % 3600) / 60, - (seconds) % 60); - - screen->DrawText(SmallFont2, CR_UNTRANSLATED, left + 210 * xscale, top + 8 * yscale, buff, - DTA_CleanNoMove, true, TAG_DONE); - - if (CPlayer->LogText.IsNotEmpty()) - { - FBrokenLines *lines = V_BreakLines(SmallFont2, 272, CPlayer->LogText); - for (i = 0; lines[i].Width >= 0; ++i) - { - screen->DrawText(SmallFont2, CR_UNTRANSLATED, left + 24 * xscale, top + (18 + i * 12)*yscale, - lines[i].Text, DTA_CleanNoMove, true, TAG_DONE); - } - V_FreeBrokenLines(lines); - } - break; - } - - case POP_Keys: - // List the keys the player has. - int pos, endpos, leftcol; - int clipleft, clipright; - - pos = KeyPopPos; - endpos = pos + 10; - leftcol = 20; - clipleft = left + 17*xscale; - clipright = left + (320-17)*xscale; - if (KeyPopScroll > 0) - { - // Extrapolate the scroll position for smoother scrolling - int scroll = MAX (0,KeyPopScroll - int(r_viewpoint.TicFrac * (280./KEY_TIME))); - pos -= 10; - leftcol = leftcol - 280 + scroll; - } - for (i = 0, item = CPlayer->mo->Inventory; - i < endpos && item != NULL; - item = item->Inventory) - { - if (!item->IsKindOf (PClass::FindActor(NAME_Key))) - continue; - - if (i < pos) - { - i++; - continue; - } - - label = item->GetTag(); - - int colnum = ((i-pos) / 5) & (KeyPopScroll > 0 ? 3 : 1); - int rownum = (i % 5) * 18; - - screen->DrawTexture (TexMan(item->Icon), - left + (colnum * 140 + leftcol)*xscale, - top + (6 + rownum)*yscale, - DTA_CleanNoMove, true, - DTA_ClipLeft, clipleft, - DTA_ClipRight, clipright, - TAG_DONE); - screen->DrawText (SmallFont2, CR_UNTRANSLATED, - left + (colnum * 140 + leftcol + 17)*xscale, - top + (11 + rownum)*yscale, - label, - DTA_CleanNoMove, true, - DTA_ClipLeft, clipleft, - DTA_ClipRight, clipright, - TAG_DONE); - i++; - } - break; - - case POP_Status: - // Show miscellaneous status items. - - // Print stats - DrINumber2 (CPlayer->mo->accuracy, left+268*xscale, top+28*yscale, 7*xscale, imgFONY0); - DrINumber2 (CPlayer->mo->stamina, left+268*xscale, top+52*yscale, 7*xscale, imgFONY0); - - // How many keys does the player have? - for (i = 0, item = CPlayer->mo->Inventory; - item != NULL; - item = item->Inventory) - { - if (item->IsKindOf (PClass::FindActor(NAME_Key))) - { - i++; - } - } - DrINumber2 (i, left+268*xscale, top+76*yscale, 7*xscale, imgFONY0); - - // Does the player have a communicator? - item = CPlayer->mo->FindInventory (NAME_Communicator); - if (item != NULL) - { - screen->DrawTexture (TexMan(item->Icon), - left + 280*xscale, - top + 74*yscale, - DTA_CleanNoMove, true, TAG_DONE); - } - - // How much ammo does the player have? - static const struct - { - ENamedName AmmoType; - int Y; - } AmmoList[7] = - { - { NAME_ClipOfBullets, 19 }, - { NAME_PoisonBolts, 35 }, - { NAME_ElectricBolts, 43 }, - { NAME_HEGrenadeRounds, 59 }, - { NAME_PhosphorusGrenadeRounds, 67 }, - { NAME_MiniMissiles, 75 }, - { NAME_EnergyPod, 83 } - }; - for (i = 0; i < 7; ++i) - { - PClassActor *ammotype = PClass::FindActor(AmmoList[i].AmmoType); - item = CPlayer->mo->FindInventory (ammotype); - - if (item == NULL) - { - DrINumber2 (0, left+206*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); - DrINumber2 (((AInventory *)GetDefaultByType (ammotype))->MaxAmount, - left+239*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); - } - else - { - DrINumber2 (item->Amount, left+206*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); - DrINumber2 (item->MaxAmount, left+239*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); - } - } - - // What weapons does the player have? - static const struct - { - ENamedName TypeName; - int X, Y; - } WeaponList[6] = - { - { NAME_StrifeCrossbow, 23, 19 }, - { NAME_AssaultGun, 21, 41 }, - { NAME_FlameThrower, 57, 50 }, - { NAME_MiniMissileLauncher, 20, 64 }, - { NAME_StrifeGrenadeLauncher, 55, 20 }, - { NAME_Mauler, 52, 75 }, - }; - for (i = 0; i < 6; ++i) - { - item = CPlayer->mo->FindInventory (WeaponList[i].TypeName); - - if (item != NULL) - { - screen->DrawTexture (TexMan(item->Icon), - left + WeaponList[i].X*xscale, - top + WeaponList[i].Y*yscale, - DTA_CleanNoMove, true, - DTA_LeftOffset, 0, - DTA_TopOffset, 0, - TAG_DONE); - } - } - break; - } - } - - void DrINumber (signed int val, int x, int y, int imgBase) const - { - x -= 7; - - if (val == 0) - { - DrawImage (Images[imgBase], x, y); - } - else - { - while (val != 0) - { - DrawImage (Images[imgBase+val%10], x, y); - val /= 10; - x -= 7; - } - } - } - - void DrINumber2 (signed int val, int x, int y, int width, int imgBase) const - { - x -= width; - - if (val == 0) - { - screen->DrawTexture (Images[imgBase], x, y, DTA_CleanNoMove, true, TAG_DONE); - } - else - { - while (val != 0) - { - screen->DrawTexture (Images[imgBase+val%10], x, y, DTA_CleanNoMove, true, TAG_DONE); - val /= 10; - x -= width; - } - } - } - - enum - { - imgINVCURS, - imgCURSOR01, - imgINVBACK, - imgINVTOP, - imgINVPOP, - imgINVPOP2, - imgINVPBAK, - imgINVPBAK2, - imgFONG0, - imgFONG1, - imgFONG2, - imgFONG3, - imgFONG4, - imgFONG5, - imgFONG6, - imgFONG7, - imgFONG8, - imgFONG9, - imgFONG_PERCENT, - imgFONY0, - imgFONY1, - imgFONY2, - imgFONY3, - imgFONY4, - imgFONY5, - imgFONY6, - imgFONY7, - imgFONY8, - imgFONY9, - imgFONY_PERCENT, - imgCOMM, - imgMEDI, - imgARM1, - imgARM2, - imgNEGATIVE, - imgINumbers = imgFONG0, - }; - - FImageCollection Images; - FHealthBar HealthBar; - - int CursorImage; - int CurrentPop, PendingPop, PopHeight, PopHeightChange; - int KeyPopPos, KeyPopScroll; - double ItemFlash; - - void DrINumberOuter(signed int val, int x, int y, bool center = false, int w = 9) const; - void DrBNumberOuterFont(signed int val, int x, int y, int w = 3) const; - void DrawDimImage(FTexture *image, int x, int y, bool dimmed) const; - void DrawImage(FTexture *image, int x, int y/*, FRemapTable *translation = NULL*/) const; - -}; - -//--------------------------------------------------------------------------- -// -// PROC DrINumberOuter -// -// Draws a number outside the status bar, possibly scaled. -// -//--------------------------------------------------------------------------- - -void DStrifeStatusBar::DrINumberOuter(signed int val, int x, int y, bool center, int w) const -{ - bool negative = false; - - x += w * 2; - if (val < 0) - { - negative = true; - val = -val; - } - else if (val == 0) - { - screen->DrawTexture(Images[imgINumbers], x + 1, y + 1, - DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, - DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); - screen->DrawTexture(Images[imgINumbers], x, y, - DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); - return; - } - - int oval = val; - int ox = x; - - // First the shadow - while (val != 0) - { - screen->DrawTexture(Images[imgINumbers + val % 10], x + 1, y + 1, - DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, - DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); - x -= w; - val /= 10; - } - if (negative) - { - screen->DrawTexture(Images[imgNEGATIVE], x + 1, y + 1, - DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, - DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); - } - - // Then the real deal - val = oval; - x = ox; - while (val != 0) - { - screen->DrawTexture(Images[imgINumbers + val % 10], x, y, - DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); - x -= w; - val /= 10; - } - if (negative) - { - screen->DrawTexture(Images[imgNEGATIVE], x, y, - DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); - } -} - - -//--------------------------------------------------------------------------- -// -// PROC DrBNumberOuter -// -// Draws a three digit number using the real big font outside the status bar. -// -//--------------------------------------------------------------------------- - -void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size) const -{ - int xpos; - int w, v; - bool negative = false; - FTexture *pic; - - w = 0; - BigFont->GetChar('0', &w); - - if (w > 1) - { - w--; - } - xpos = x + w / 2 + (size - 1)*w; - - if (val == 0) - { - pic = BigFont->GetChar('0', &v); - screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, '0', - DTA_HUDRules, HUD_Normal, - DTA_Alpha, HR_SHADOW, - DTA_FillColor, 0, - TAG_DONE); - screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2, y, '0', - DTA_HUDRules, HUD_Normal, - TAG_DONE); - return; - } - else if (val < 0) - { - negative = true; - val = -val; - } - - int oval = val; - int oxpos = xpos; - - // First the shadow - while (val != 0) - { - pic = BigFont->GetChar('0' + val % 10, &v); - screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, - DTA_HUDRules, HUD_Normal, - DTA_Alpha, HR_SHADOW, - DTA_FillColor, 0, - TAG_DONE); - val /= 10; - xpos -= w; - } - if (negative) - { - pic = BigFont->GetChar('-', &v); - if (pic != NULL) - { - screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, '-', - DTA_HUDRules, HUD_Normal, - DTA_Alpha, HR_SHADOW, - DTA_FillColor, 0, - TAG_DONE); - } - } - - // Then the foreground number - val = oval; - xpos = oxpos; - while (val != 0) - { - pic = BigFont->GetChar('0' + val % 10, &v); - screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2, y, '0', - DTA_HUDRules, HUD_Normal, - TAG_DONE); - val /= 10; - xpos -= w; - } - if (negative) - { - pic = BigFont->GetChar('-', &v); - if (pic != NULL) - { - screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2, y, '-', - DTA_HUDRules, HUD_Normal, - TAG_DONE); - } - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawImage -// -// Draws an image with the status bar's upper-left corner as the origin. -// -//--------------------------------------------------------------------------- - -void DStrifeStatusBar::DrawImage(FTexture *img, - int x, int y) const -{ - if (img != NULL) - { - screen->DrawTexture(img, x + ST_X, y + ST_Y, - DTA_Bottom320x200, Scaled, - TAG_DONE); - } -} - -//--------------------------------------------------------------------------- -// -// PROC DrawImage -// -// Draws an optionally dimmed image with the status bar's upper-left corner -// as the origin. -// -//--------------------------------------------------------------------------- - -void DStrifeStatusBar::DrawDimImage(FTexture *img, - int x, int y, bool dimmed) const -{ - if (img != NULL) - { - screen->DrawTexture(img, x + ST_X, y + ST_Y, - DTA_ColorOverlay, dimmed ? DIM_OVERLAY : 0, - DTA_Bottom320x200, Scaled, - TAG_DONE); - } -} - - - - - -IMPLEMENT_CLASS(DStrifeStatusBar, false, false); - -DBaseStatusBar *CreateStrifeStatusBar () -{ - return new DStrifeStatusBar; -} diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 38f1b56c12..6ff2e09437 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -77,7 +77,6 @@ CVAR(Bool, vid_hwaalines, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(Bool, vid_hw2d, true, CVAR_NOINITCALL) { V_SetBorderNeedRefresh(); - ST_SetNeedRefresh(); } #else EXTERN_CVAR(Bool, vid_hwaalines) diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 170effaf18..4559ca1c25 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -109,7 +109,6 @@ void cht_DoCheat (player_t *player, int cheat) msg = GStrings("STSTR_DQDON"); else msg = GStrings("STSTR_DQDOFF"); - ST_SetNeedRefresh(); break; case CHT_BUDDHA: @@ -126,7 +125,6 @@ void cht_DoCheat (player_t *player, int cheat) msg = GStrings("STSTR_DQD2ON"); else msg = GStrings("STSTR_DQD2OFF"); - ST_SetNeedRefresh(); break; case CHT_BUDDHA2: diff --git a/src/menu/videomenu.cpp b/src/menu/videomenu.cpp index 2c3abe52b3..b23798727c 100644 --- a/src/menu/videomenu.cpp +++ b/src/menu/videomenu.cpp @@ -118,7 +118,7 @@ CUSTOM_CVAR (Bool, vid_tft, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) setsizeneeded = true; if (StatusBar != NULL) { - StatusBar->ScreenSizeChanged(); + StatusBar->CallScreenSizeChanged(); } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a95e1a4336..83150c9e36 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5584,7 +5584,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) if (StatusBar != NULL && (playernum == consoleplayer || StatusBar->GetPlayer() == playernum)) { - StatusBar->AttachToPlayer (p); + StatusBar->CallAttachToPlayer (p); } if (multiplayer) @@ -7740,7 +7740,7 @@ const char *AActor::GetTag(const char *def) const DEFINE_ACTION_FUNCTION(AActor, GetTag) { PARAM_SELF_PROLOGUE(AActor); - PARAM_STRING(def); + PARAM_STRING_DEF(def); ACTION_RETURN_STRING(self->GetTag(def.Len() == 0? nullptr : def.GetChars())); } diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 990cdaf64b..3ef1775f5f 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -128,7 +128,7 @@ void P_Ticker (void) // [ZZ] call the WorldTick hook E_WorldTick(); - StatusBar->Tick (); // [RH] moved this here + StatusBar->CallTick (); // [RH] moved this here level.Tick (); // [RH] let the level tick DThinker::RunThinkers (); diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index cd4c073516..f49bd76e83 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -942,7 +942,7 @@ void NullParam(const char *varname); #define PARAM_COLOR_DEF_AT(p,x) PalEntry x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; } #define PARAM_FLOAT_DEF_AT(p,x) double x; if (PARAM_EXISTS(p)) { ASSERTFLOAT(param[p]); x = param[p].f; } else { ASSERTFLOAT(defaultparam[p]); x = defaultparam[p].f; } #define PARAM_ANGLE_DEF_AT(p,x) DAngle x; if (PARAM_EXISTS(p)) { ASSERTFLOAT(param[p]); x = param[p].f; } else { ASSERTFLOAT(defaultparam[p]); x = defaultparam[p].f; } -#define PARAM_STRING_DEF_AT(p,x) FString x; if (PARAM_EXISTS(p)) { ASSERTSTRING(param[p]); x = param[p].s; } else { ASSERTSTRING(defaultparam[p]); x = defaultparam[p].s; } +#define PARAM_STRING_DEF_AT(p,x) FString x; if (PARAM_EXISTS(p)) { ASSERTSTRING(param[p]); x = param[p].s(); } else { ASSERTSTRING(defaultparam[p]); x = defaultparam[p].s(); } #define PARAM_STATE_DEF_AT(p,x) FState *x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = (FState*)StateLabels.GetState(param[p].i, self->GetClass()); } else { ASSERTINT(defaultparam[p]); x = (FState*)StateLabels.GetState(defaultparam[p].i, self->GetClass()); } #define PARAM_STATE_ACTION_DEF_AT(p,x) FState *x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = (FState*)StateLabels.GetState(param[p].i, stateowner->GetClass()); } else { ASSERTINT(defaultparam[p]); x = (FState*)StateLabels.GetState(defaultparam[p].i, stateowner->GetClass()); } #define PARAM_POINTER_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTPOINTER(param[p]); x = (t*)param[p].a; } else { ASSERTPOINTER(defaultparam[p]); x = (t*)defaultparam[p].a; } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 8d8277a6d2..e468e23a30 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1213,6 +1213,9 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override | ZCC_Meta | ZCC_Extension | ZCC_VirtualScope | ZCC_ClearScope : ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override | ZCC_Extension | ZCC_VirtualScope | ZCC_ClearScope; + // Some internal fields need to be set to clearscope. + if (Wads.GetLumpFile(Lump) == 0) notallowed &= ~ZCC_ClearScope; + if (field->Flags & notallowed) { Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed).GetChars()); diff --git a/src/stats.cpp b/src/stats.cpp index 237436c413..d0d5d2f022 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -85,7 +85,6 @@ void FStat::ToggleStat (const char *name) void FStat::ToggleStat () { m_Active = !m_Active; - ST_SetNeedRefresh(); } void FStat::PrintStat () @@ -113,10 +112,6 @@ void FStat::PrintStat () } } } - if (count) - { - ST_SetNeedRefresh(); - } } void FStat::DumpRegisteredStats () diff --git a/src/v_draw.cpp b/src/v_draw.cpp index a040b80cf0..3d896ed656 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -67,7 +67,7 @@ CUSTOM_CVAR(Int, uiscale, 2, CVAR_ARCHIVE | CVAR_NOINITCALL) { if (StatusBar != NULL) { - StatusBar->ScreenSizeChanged(); + StatusBar->CallScreenSizeChanged(); } } @@ -1169,13 +1169,6 @@ int BorderNeedRefresh; static void V_DrawViewBorder (void) { - // [RH] Redraw the status bar if SCREENWIDTH > status bar width. - // Will draw borders around itself, too. - if (SCREENWIDTH > 320) - { - ST_SetNeedRefresh(); - } - if (viewwidth == SCREENWIDTH) { return; diff --git a/src/v_video.cpp b/src/v_video.cpp index 0a7c4614fb..4cc77cf0ef 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1384,7 +1384,7 @@ void V_OutputResized (int width, int height) setsizeneeded = true; if (StatusBar != NULL) { - StatusBar->ScreenSizeChanged(); + StatusBar->CallScreenSizeChanged(); } C_NewModeAdjust(); } @@ -1634,7 +1634,7 @@ CUSTOM_CVAR (Bool, vid_nowidescreen, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) setsizeneeded = true; if (StatusBar != NULL) { - StatusBar->ScreenSizeChanged(); + StatusBar->CallScreenSizeChanged(); } } @@ -1643,7 +1643,7 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) setsizeneeded = true; if (StatusBar != NULL) { - StatusBar->ScreenSizeChanged(); + StatusBar->CallScreenSizeChanged(); } } diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index df180587eb..3c07b9c14c 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -228,7 +228,6 @@ const char *const D3DFB::ShaderNames[D3DFB::NUM_SHADERS] = CUSTOM_CVAR(Bool, vid_hw2d, true, CVAR_NOINITCALL) { V_SetBorderNeedRefresh(); - ST_SetNeedRefresh(); } CVAR(Bool, d3d_antilag, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 892d7087f9..fddfd13783 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -32,6 +32,9 @@ version "2.5" #include "zscript/statscreen/statscreen_dm.txt" #include "zscript/statscreen/statscreen_coop.txt" +#include "zscript/statusbar/statusbar.txt" +#include "zscript/statusbar/strife_sbar.txt" + #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" #include "zscript/inventory/stateprovider.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 2ae84704c6..7cce7fbc6e 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -39,6 +39,7 @@ struct _ native // These are the global variables, the struct is only here to av native ui int BackbuttonTime; native ui float BackbuttonAlpha; native readonly int Net_Arbitrator; + native ui BaseStatusBar StatusBar; } @@ -379,10 +380,10 @@ class Thinker : Object native play virtual native void PostBeginPlay(); virtual native void ChangeStatNum(int stat); - static int Tics2Seconds(int tics) + static clearscope int Tics2Seconds(int tics) { // This compensates for one tic being slightly less than 1/35 of a second. - return int(tics * (0.98 * TICRATE)); + return int(tics * (0.98 / TICRATE)); } } diff --git a/wadsrc/static/zscript/compatibility.txt b/wadsrc/static/zscript/compatibility.txt index 3699a8f3ae..eaf77e0a46 100644 --- a/wadsrc/static/zscript/compatibility.txt +++ b/wadsrc/static/zscript/compatibility.txt @@ -31,10 +31,3 @@ extend class StateProvider A_FireProjectile(missiletype, angle, useammo, spawnofs_xy, spawnheight, flags, -pitch); } } - -// this is just a placeholder until the statusbar gets properly exported. -struct StatusBar native -{ - native static void ReceivedWeapon(Weapon weap); -} - diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 48a88bc321..d5c15e0b2e 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -855,6 +855,25 @@ class Inventory : Actor native return false; } + //=========================================================================== + // + // AInventory :: NextInv + // + // Returns the next item with IF_INVBAR set. + // + //=========================================================================== + + clearscope Inventory NextInv () const + { + Inventory item = Inv; + + while (item != NULL && !item.bInvBar) + { + item = item.Inv; + } + return item; + } + } diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 3f7bc19752..8851242b05 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -7,8 +7,8 @@ class PlayerPawn : Actor native native int MugShotMaxHealth; native int RunHealth; native int PlayerFlags; - native Inventory InvFirst; // first inventory item displayed on inventory bar - native Inventory InvSel; // selected inventory item + native clearscope Inventory InvFirst; // first inventory item displayed on inventory bar + native clearscope Inventory InvSel; // selected inventory item native Name SoundClass; // Sound class native Name Face; // Doom status bar face (when used) native Name Portrait; @@ -179,7 +179,7 @@ class PlayerPawn : Actor native } return -1, -1; } - + native clearscope int GetMaxHealth(bool withupgrades = false) const; native bool ResetAirSupply (bool playgasp = false); native void CheckWeaponSwitch(class item); @@ -276,7 +276,7 @@ struct PlayerInfo native play // this is what internally is known as player_t native bool usedown; native uint oldbuttons; native int health; - native int inventorytics; + native clearscope int inventorytics; native uint8 CurrentPlayerClass; native int frags[MAXPLAYERS]; native int fragcount; diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt new file mode 100644 index 0000000000..3972a616cc --- /dev/null +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -0,0 +1,79 @@ + +class BaseStatusBar native ui +{ + enum EPop + { + POP_NoChange = -1, + POP_None, + POP_Log, + POP_Keys, + POP_Status + } + + // Status face stuff + enum EMug + { + ST_NUMPAINFACES = 5, + ST_NUMSTRAIGHTFACES = 3, + ST_NUMTURNFACES = 2, + ST_NUMSPECIALFACES = 3, + ST_NUMEXTRAFACES = 2, + ST_FACESTRIDE = ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES, + ST_NUMFACES = ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES, + + ST_TURNOFFSET = ST_NUMSTRAIGHTFACES, + ST_OUCHOFFSET = ST_TURNOFFSET + ST_NUMTURNFACES, + ST_EVILGRINOFFSET = ST_OUCHOFFSET + 1, + ST_RAMPAGEOFFSET = ST_EVILGRINOFFSET + 1, + ST_GODFACE = ST_NUMPAINFACES*ST_FACESTRIDE, + ST_DEADFACE = ST_GODFACE + 1 + } + + enum EHudState + { + HUD_StatusBar, + HUD_Fullscreen, + HUD_None, + + HUD_AltHud // Used for passing through popups to the alt hud + } + + + enum EHudDraw + { + HUD_Normal, + HUD_HorizCenter + } + + const XHAIRSHRINKSIZE =(1./18); + const XHAIRPICKUPSIZE = (2+XHAIRSHRINKSIZE); + + + native int ST_X, ST_Y; + native int RelTop; + native int HorizontalResolution, VerticalResolution; + native bool Scaled; + native bool Centering; + native bool FixedOrigin; + native bool CompleteBorder; + native double CrosshairSize; + native double Displacement; + native PlayerInfo CPlayer; + + virtual void Init() {} + native virtual void SetScaled(bool scale, bool force = false); + native virtual void Tick (); + native virtual void Draw (int state, double TicFrac); + virtual void FlashItem (class itemtype) {} + native virtual void AttachToPlayer (PlayerInfo player); + virtual void FlashCrosshair () { CrosshairSize = XHAIRPICKUPSIZE; } + virtual void NewGame () {} + native virtual void ScreenSizeChanged (); + native virtual void ShowPop (int popnum); + native virtual clearscope void ReceivedWeapon (Weapon weapn); + virtual bool MustDrawLog(int state) { return true; } +// native virtual void SetMugShotState (String state_name, bool wait_till_done=false, bool reset=false); later - at the moment the backing code is not accessible from the script side. + native void RefreshBackground () const; + native Inventory, Inventory, int, int GetCurrentAmmo () const; + native Inventory ValidateInvFirst (int numVisible) const; +} diff --git a/wadsrc/static/zscript/statusbar/strife_sbar.txt b/wadsrc/static/zscript/statusbar/strife_sbar.txt new file mode 100644 index 0000000000..d5c21f1edd --- /dev/null +++ b/wadsrc/static/zscript/statusbar/strife_sbar.txt @@ -0,0 +1,854 @@ + +class StrifeStatusBar : BaseStatusBar +{ + + // Number of tics to move the popscreen up and down. + const POP_TIME = (Thinker.TICRATE/8); + + // Popscreen height when fully extended + const POP_HEIGHT = 104; + + // Number of tics to scroll keys left + const KEY_TIME = (Thinker.TICRATE/3); + + enum eImg + { + imgINVCURS, + imgCURSOR01, + imgINVBACK, + imgINVTOP, + imgINVPOP, + imgINVPOP2, + imgINVPBAK, + imgINVPBAK2, + imgFONG0, + imgFONG1, + imgFONG2, + imgFONG3, + imgFONG4, + imgFONG5, + imgFONG6, + imgFONG7, + imgFONG8, + imgFONG9, + imgFONG_PERCENT, + imgFONY0, + imgFONY1, + imgFONY2, + imgFONY3, + imgFONY4, + imgFONY5, + imgFONY6, + imgFONY7, + imgFONY8, + imgFONY9, + imgFONY_PERCENT, + imgCOMM, + imgMEDI, + imgARM1, + imgARM2, + imgNEGATIVE, + imgINumbers = imgFONG0, + }; + + TextureID Images[imgNEGATIVE + 1]; + int CursorImage; + int CurrentPop, PendingPop, PopHeight, PopHeightChange; + int KeyPopPos, KeyPopScroll; + double ItemFlash; + + override void Init() + { + DoCommonInit(); + } + + override void NewGame () + { + DoCommonInit (); + if (CPlayer != NULL) + { + AttachToPlayer (CPlayer); + } + } + + override void Draw (int state, double TicFrac) + { + Super.Draw (state, TicFrac); + + if (state == HUD_StatusBar) + { + DrawMainBar (TicFrac); + } + else + { + if (state == HUD_Fullscreen) + { + DrawFullScreenStuff (); + } + + // Draw pop screen (log, keys, and status) + if (CurrentPop != POP_None && PopHeight < 0) + { + DrawPopScreen (screen.GetHeight(), TicFrac); + } + } + } + + override void ShowPop (int popnum) + { + Super.ShowPop(popnum); + if (popnum == CurrentPop) + { + if (popnum == POP_Keys) + { + Inventory item; + + KeyPopPos += 10; + KeyPopScroll = 280; + + int i = 0; + for (item = CPlayer.mo.Inv; item != NULL; item = item.Inv) + { + if (item is "Key") + { + if (i == KeyPopPos) + { + return; + } + i++; + } + } + } + PendingPop = POP_None; + // Do not scroll keys horizontally when dropping the popscreen + KeyPopScroll = 0; + KeyPopPos -= 10; + } + else + { + KeyPopPos = 0; + PendingPop = popnum; + } + } + + override bool MustDrawLog(int state) + { + // Tell the base class to draw the log if the pop screen won't be displayed. + return false; + } + + void DoCommonInit () + { + static const String strifeLumpNames[] = + { + "INVCURS", "CURSOR01", "INVBACK", "INVTOP", "INVPOP", "INVPOP2", + "INVPBAK", "INVPBAK2", + "INVFONG0", "INVFONG1", "INVFONG2", "INVFONG3", "INVFONG4", + "INVFONG5", "INVFONG6", "INVFONG7", "INVFONG8", "INVFONG9", + "INVFONG%", + "INVFONY0", "INVFONY1", "INVFONY2", "INVFONY3", "INVFONY4", + "INVFONY5", "INVFONY6", "INVFONY7", "INVFONY8", "INVFONY9", + "INVFONY%", + "I_COMM", "I_MDKT", "I_ARM1", "I_ARM2", "" + + }; + + for(int i = 0; i <= imgNEGATIVE; i++) + { + Images[i] = TexMan.CheckForTexture(strifeLumpNames[i], TexMan.TYPE_MiscPatch); + } + + CursorImage = Images[imgINVCURS].IsValid() ? imgINVCURS : imgCURSOR01; + + CurrentPop = POP_None; + PendingPop = POP_NoChange; + PopHeight = 0; + KeyPopPos = 0; + KeyPopScroll = 0; + ItemFlash = 0; + } + + override void Tick () + { + Super.Tick (); + + if (ItemFlash > 0) + { + ItemFlash -= 1/14.; + if (ItemFlash < 0) + { + ItemFlash = 0; + } + } + + PopHeightChange = 0; + if (PendingPop != POP_NoChange) + { + if (PopHeight < 0) + { + PopHeightChange = POP_HEIGHT / POP_TIME; + PopHeight += POP_HEIGHT / POP_TIME; + } + else + { + CurrentPop = PendingPop; + PendingPop = POP_NoChange; + } + } + else + { + if (CurrentPop == POP_None) + { + PopHeight = 0; + } + else if (PopHeight > -POP_HEIGHT) + { + PopHeight -= POP_HEIGHT / POP_TIME; + if (PopHeight < -POP_HEIGHT) + { + PopHeight = -POP_HEIGHT; + } + else + { + PopHeightChange = -POP_HEIGHT / POP_TIME; + } + } + if (KeyPopScroll > 0) + { + KeyPopScroll -= 280 / KEY_TIME; + if (KeyPopScroll < 0) + { + KeyPopScroll = 0; + } + } + } + } + + override void FlashItem (Class itemtype) + { + ItemFlash = 0.75; + } + + private void FillBar(int x, int y, int start, int stopp, Color color1, Color color2) + { + // right now there is no function to draw this. + // The old code used a crude texture hack to work arounf this omission. + } + + protected void DrawHealthBar(int health, int x, int y) + { + Color green1 = Color(180, 228, 128); // light green + Color green2 = Color(128, 180, 80); // dark green + + Color blue1 = Color(196, 204, 252); // light blue + Color blue2 = Color(148, 152, 200); // dark blue + + Color gold1 = Color(224, 188, 0); // light gold + Color gold2 = Color(208, 128, 0); // dark gold + + Color red1 = Color(216, 44, 44); // light red + Color red2 = Color(172, 28, 28); // dark red + + if (health == 999) + { + FillBar (x, y, 0, 200, gold1, gold2); + } + else + { + if (health <= 100) + { + if (health <= 10) + { + FillBar (x, y, 0, health*2, red1, red2); + } + else if (health <= 20) + { + FillBar (x, y, 0, health*2, gold1, gold2); + } + else + { + FillBar (x, y, 0, health, green1, green2); + } + FillBar (x, y, health, 200, 0, 0); + } + else + { + int stopp = 100 - (health - 100); + FillBar (x, y, 0, stopp*2, green1, green2); + FillBar (x, y, stopp*2, 200, blue1, blue2); + } + } + } + + protected void DrawMainBar (double TicFrac) + { + Inventory item; + int i; + + // Pop screen (log, keys, and status) + if (CurrentPop != POP_None && PopHeight < 0) + { + DrawPopScreen (Scaled ? (ST_Y - 8) * screen.GetHeight() / 200 : ST_Y - 8, TicFrac); + } + + DrawImage (Images[imgINVBACK], 0, 0); + DrawImage (Images[imgINVTOP], 0, -8); + + // Health + DrINumber (CPlayer.health, 79, -6, imgFONG0); + int points; + if (CPlayer.cheats & CF_GODMODE) + { + points = 999; + } + else + { + points = min(CPlayer.health, 200); + } + DrawHealthBar (points, 49, 4); + DrawHealthBar (points, 49, 7); + + // Armor + item = CPlayer.mo.FindInventory('BasicArmor'); + if (item != NULL && item.Amount > 0) + { + DrawImage (item.Icon, 2, 9); + DrINumber (item.Amount, 27, 23, imgFONY0); + } + + // Ammo + Inventory ammo1, ammo2; + int ammocount1, ammocount2; + + [ammo1, ammo2, ammocount1, ammocount2] = GetCurrentAmmo (); + if (ammo1 != NULL) + { + DrINumber (ammo1.Amount, 311, -6, imgFONG0); + DrawImage (ammo1.Icon, 290, 13); + } + + // Sigil + item = CPlayer.mo.FindInventory('Sigil'); + if (item != NULL) + { + DrawImage (item.Icon, 253, 7); + } + + // Inventory + CPlayer.inventorytics = 0; + CPlayer.mo.InvFirst = ValidateInvFirst (6); + i = 0; + for (item = CPlayer.mo.InvFirst; item != NULL && i < 6; item = item.NextInv()) + { + if (item == CPlayer.mo.InvSel) + { + screen.DrawTexture (Images[CursorImage], true, + 42 + 35*i + ST_X, 12 + ST_Y, + DTA_Bottom320x200, Scaled, + DTA_Alpha, 1. - ItemFlash); + } + if (item.Icon.isValid()) + { + DrawDimImage (item.Icon, 48 + 35*i, 14, item.Amount <= 0); + } + DrINumber (item.Amount, 74 + 35*i, 23, imgFONY0); + i++; + } + } + + protected void DrawFullScreenStuff () + { + // Draw health + DrINumberOuter (CPlayer.health, 4, -10, false, 7); + screen.DrawTexture (Images[imgMEDI], true, 14, -17, + DTA_HUDRules, HUD_Normal, + DTA_CenterBottomOffset, true); + + // Draw armor + let armor = CPlayer.mo.FindInventory('BasicArmor'); + if (armor != NULL && armor.Amount != 0) + { + DrINumberOuter (armor.Amount, 35, -10, false, 7); + screen.DrawTexture (armor.Icon, true, 45, -17, + DTA_HUDRules, HUD_Normal, + DTA_CenterBottomOffset, true); + } + + // Draw ammo + Inventory ammo1, ammo2; + int ammocount1, ammocount2; + + [ammo1, ammo2, ammocount1, ammocount2] = GetCurrentAmmo (); + if (ammo1 != NULL) + { + // Draw primary ammo in the bottom-right corner + DrINumberOuter (ammo1.Amount, -23, -10, false, 7); + screen.DrawTexture (ammo1.Icon, true, -14, -17, + DTA_HUDRules, HUD_Normal, + DTA_CenterBottomOffset, true); + if (ammo2 != NULL && ammo1!=ammo2) + { + // Draw secondary ammo just above the primary ammo + DrINumberOuter (ammo2.Amount, -23, -48, false, 7); + screen.DrawTexture (ammo2.Icon, -14, -55, + DTA_HUDRules, HUD_Normal, + DTA_CenterBottomOffset, true); + } + } + + if (deathmatch) + { // Draw frags (in DM) + DrBNumberOuterFont (CPlayer.fragcount, -44, 1); + } + + // Draw inventory + if (CPlayer.inventorytics == 0) + { + if (CPlayer.mo.InvSel != null) + { + if (ItemFlash > 0) + { + vector2 size = TexMan.GetScaledSize(Images[CursorImage]); + screen.DrawTexture (Images[CursorImage], true, -28, -15, + DTA_HUDRules, HUD_Normal, + DTA_LeftOffsetF, size.X, + DTA_TopOffsetF, size.Y, + DTA_Alpha, ItemFlash); + } + DrINumberOuter (CPlayer.mo.InvSel.Amount, -51, -10, false, 7); + screen.DrawTexture (CPlayer.mo.InvSel.Icon, true, -42, -17, + DTA_HUDRules, HUD_Normal, + DTA_CenterBottomOffset, true, + DTA_ColorOverlay, CPlayer.mo.InvSel.Amount > 0 ? 0 : Color(170, 0, 0, 0)); + } + } + else + { + CPlayer.mo.InvFirst = ValidateInvFirst (6); + int i = 0; + Inventory item; + if (CPlayer.mo.InvFirst != NULL) + { + for (item = CPlayer.mo.InvFirst; item != NULL && i < 6; item = item.NextInv()) + { + if (item == CPlayer.mo.InvSel) + { + screen.DrawTexture (Images[CursorImage], true, -100+i*35, -21, + DTA_HUDRules, HUD_HorizCenter, + DTA_Alpha, 0.75); + } + if (item.Icon.isValid()) + { + screen.DrawTexture (item.Icon, true, -94 + i*35, -19, + DTA_HUDRules, HUD_HorizCenter, + DTA_ColorOverlay, CPlayer.mo.InvSel.Amount > 0 ? 0 : Color(170, 0, 0, 0)); + } + DrINumberOuter (item.Amount, -89 + i*35, -10, true, 7); + ++i; + } + } + } + } + + protected void DrawPopScreen (int bottom, double TicFrac) + { + String buff; + String label; + int i; + Inventory item; + int xscale, yscale, left, top; + int bars = (CurrentPop == POP_Status) ? imgINVPOP : imgINVPOP2; + int back = (CurrentPop == POP_Status) ? imgINVPBAK : imgINVPBAK2; + // Extrapolate the height of the popscreen for smoother movement + int height = clamp (PopHeight + int(TicFrac * PopHeightChange), -POP_HEIGHT, 0); + + xscale = CleanXfac; + yscale = CleanYfac; + left = screen.GetWidth()/2 - 160*CleanXfac; + top = bottom + height * yscale; + + screen.DrawTexture (Images[back], true, left, top, DTA_CleanNoMove, true, DTA_Alpha, 0.75); + screen.DrawTexture (Images[bars], true, left, top, DTA_CleanNoMove, true); + + + switch (CurrentPop) + { + case POP_Log: + { + int seconds = Thinker.Tics2Seconds(level.time); + // Draw the latest log message. + buff = String.Format("%02d:%02d:%02d", + seconds / 3600, + (seconds % 3600) / 60, + (seconds) % 60); + + screen.DrawText(SmallFont2, Font.CR_UNTRANSLATED, left + 210 * xscale, top + 8 * yscale, buff, + DTA_CleanNoMove, true); + + if (CPlayer.LogText.Length() > 0) + { + BrokenLines lines = SmallFont2.BreakLines(CPlayer.LogText, 272); + for (i = 0; i < lines.Count(); ++i) + { + screen.DrawText(SmallFont2, Font.CR_UNTRANSLATED, left + 24 * xscale, top + (18 + i * 12)*yscale, + lines.StringAt(i), DTA_CleanNoMove, true); + } + } + break; + } + + case POP_Keys: + // List the keys the player has. + int pos, endpos, leftcol; + int clipleft, clipright; + + pos = KeyPopPos; + endpos = pos + 10; + leftcol = 20; + clipleft = left + 17*xscale; + clipright = left + (320-17)*xscale; + if (KeyPopScroll > 0) + { + // Extrapolate the scroll position for smoother scrolling + int scroll = MAX (0, KeyPopScroll - int(TicFrac * (280./KEY_TIME))); + pos -= 10; + leftcol = leftcol - 280 + scroll; + } + i = 0; + for (item = CPlayer.mo.Inv; i < endpos && item != NULL; item = item.Inv) + { + if (!(item is "Key")) + continue; + + if (i < pos) + { + i++; + continue; + } + + label = item.GetTag(); + + int colnum = ((i-pos) / 5) & (KeyPopScroll > 0 ? 3 : 1); + int rownum = (i % 5) * 18; + + screen.DrawTexture (item.Icon, true, + left + (colnum * 140 + leftcol)*xscale, + top + (6 + rownum)*yscale, + DTA_CleanNoMove, true, + DTA_ClipLeft, clipleft, + DTA_ClipRight, clipright); + screen.DrawText (SmallFont2, Font.CR_UNTRANSLATED, + left + (colnum * 140 + leftcol + 17)*xscale, + top + (11 + rownum)*yscale, + label, + DTA_CleanNoMove, true, + DTA_ClipLeft, clipleft, + DTA_ClipRight, clipright); + i++; + } + break; + + case POP_Status: + // Show miscellaneous status items. + + // Print stats + DrINumber2 (CPlayer.mo.accuracy, left+268*xscale, top+28*yscale, 7*xscale, imgFONY0); + DrINumber2 (CPlayer.mo.stamina, left+268*xscale, top+52*yscale, 7*xscale, imgFONY0); + + // How many keys does the player have? + i = 0; + for (item = CPlayer.mo.Inv; item != NULL; item = item.Inv) + { + if (item is "Key") + { + i++; + } + } + DrINumber2 (i, left+268*xscale, top+76*yscale, 7*xscale, imgFONY0); + + // Does the player have a communicator? + item = CPlayer.mo.FindInventory ("Communicator"); + if (item != NULL) + { + screen.DrawTexture (item.Icon, true, + left + 280*xscale, + top + 74*yscale, + DTA_CleanNoMove, true); + } + + // How much ammo does the player have? + static const class AmmoList[] = { + "ClipOfBullets", + "PoisonBolts", + "ElectricBolts", + "HEGrenadeRounds", + "PhosphorusGrenadeRounds", + "MiniMissiles", + "EnergyPod"}; + + static const int AmmoY[] = {19, 35, 43, 59, 67, 75, 83}; + + for (i = 0; i < 7; ++i) + { + item = CPlayer.mo.FindInventory (AmmoList[i]); + + if (item == NULL) + { + DrINumber2 (0, left+206*xscale, top+AmmoY[i] * yscale, 7*xscale, imgFONY0); + DrINumber2 (GetDefaultByType(AmmoList[i]).MaxAmount, left+239*xscale, top+AmmoY[i] * yscale, 7*xscale, imgFONY0); + } + else + { + DrINumber2 (item.Amount, left+206*xscale, top+AmmoY[i] * yscale, 7*xscale, imgFONY0); + DrINumber2 (item.MaxAmount, left+239*xscale, top+AmmoY[i] * yscale, 7*xscale, imgFONY0); + } + } + + + // What weapons does the player have? + static const class WeaponList[] = + { + "StrifeCrossbow", + "AssaultGun", + "FlameThrower", + "MiniMissileLauncher", + "StrifeGrenadeLauncher", + "Mauler" + }; + static const int WeaponX[] = {23, 21, 57, 20, 55, 52}; + static const int WeaponY[] = {19, 41, 50, 64, 20, 75}; + + for (i = 0; i < 6; ++i) + { + item = CPlayer.mo.FindInventory (WeaponList[i]); + if (item != NULL) + { + screen.DrawTexture (item.Icon, true, + left + WeaponX[i] * xscale, + top + WeaponY[i] * yscale, + DTA_CleanNoMove, true, + DTA_LeftOffset, 0, + DTA_TopOffset, 0); + } + } + break; + } + } + + void DrINumber (int val, int x, int y, int imgBase) const + { + x -= 7; + + if (val == 0) + { + DrawImage (Images[imgBase], x, y); + } + else + { + while (val != 0) + { + DrawImage (Images[imgBase+val%10], x, y); + val /= 10; + x -= 7; + } + } + } + + void DrINumber2 (int val, int x, int y, int width, int imgBase) const + { + x -= width; + + if (val == 0) + { + screen.DrawTexture (Images[imgBase], true, x, y, DTA_CleanNoMove, true); + } + else + { + while (val != 0) + { + screen.DrawTexture (Images[imgBase+val%10], true, x, y, DTA_CleanNoMove, true); + val /= 10; + x -= width; + } + } + } + + + //--------------------------------------------------------------------------- + // + // PROC DrINumberOuter + // + // Draws a number outside the status bar, possibly scaled. + // + //--------------------------------------------------------------------------- + + void DrINumberOuter(int val, int x, int y, bool center, int w) const + { + bool negative = false; + + x += w * 2; + if (val < 0) + { + negative = true; + val = -val; + } + else if (val == 0) + { + screen.DrawTexture(Images[imgINumbers], true, x + 1, y + 1, + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, + DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal); + screen.DrawTexture(Images[imgINumbers], true, x, y, + DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal); + return; + } + + int oval = val; + int ox = x; + + // First the shadow + while (val != 0) + { + screen.DrawTexture(Images[imgINumbers + val % 10], true, x + 1, y + 1, + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, + DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal); + x -= w; + val /= 10; + } + if (negative) + { + screen.DrawTexture(Images[imgNEGATIVE], true, x + 1, y + 1, + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, + DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal); + } + + // Then the real deal + val = oval; + x = ox; + while (val != 0) + { + screen.DrawTexture(Images[imgINumbers + val % 10], true, x, y, + DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal); + x -= w; + val /= 10; + } + if (negative) + { + screen.DrawTexture(Images[imgNEGATIVE], true, x, y, + DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal); + } + } + + + //--------------------------------------------------------------------------- + // + // PROC DrBNumberOuter + // + // Draws a three digit number using the real big font outside the status bar. + // + //--------------------------------------------------------------------------- + + void DrBNumberOuterFont(int val, int x, int y, int size = 3) const + { + int v; + bool negative = false; + TextureID pic; + + int w = BigFont.GetCharWidth("0"); + int ww = w; + + if (w > 1) + { + w--; + } + int xpos = x + w / 2 + (size - 1)*w; + + if (val == 0) + { + screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, "0", + DTA_HUDRules, HUD_Normal, + DTA_Alpha, HR_SHADOW, + DTA_FillColor, 0); + screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2, y, "0", + DTA_HUDRules, HUD_Normal); + return; + } + else if (val < 0) + { + negative = true; + val = -val; + } + + int oval = val; + int oxpos = xpos; + + // First the shadow + while (val != 0) + { + v = BigFont.GetCharWidth(int("0") + val % 10); + screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, + DTA_HUDRules, HUD_Normal, + DTA_Alpha, HR_SHADOW, + DTA_FillColor, 0); + val /= 10; + xpos -= w; + } + if (negative) + { + v = BigFont.GetCharWidth("-"); + screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, "-", + DTA_HUDRules, HUD_Normal, + DTA_Alpha, HR_SHADOW, + DTA_FillColor, 0); + } + + // Then the foreground number + val = oval; + xpos = oxpos; + while (val != 0) + { + v = BigFont.GetCharWidth(int("0") + val % 10); + screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2, y, "0", DTA_HUDRules, HUD_Normal); + val /= 10; + xpos -= w; + } + if (negative) + { + v = BigFont.GetCharWidth("-"); + screen.DrawChar(BigFont, Font.CR_UNTRANSLATED, xpos - v / 2, y, "-", DTA_HUDRules, HUD_Normal); + } + } + + //--------------------------------------------------------------------------- + // + // PROC DrawImage + // + // Draws an image with the status bar's upper-left corner as the origin. + // + //--------------------------------------------------------------------------- + + void DrawImage(TextureID img, int x, int y) const + { + if (img.IsValid()) + { + screen.DrawTexture(img, true, x + ST_X, y + ST_Y, DTA_Bottom320x200, Scaled); + } + } + + //--------------------------------------------------------------------------- + // + // PROC DrawImage + // + // Draws an optionally dimmed image with the status bar's upper-left corner + // as the origin. + // + //--------------------------------------------------------------------------- + + void DrawDimImage(TextureID img, int x, int y, bool dimmed) const + { + if (img.IsValid()) + { + screen.DrawTexture(img, true, x + ST_X, y + ST_Y, DTA_ColorOverlay, dimmed ? Color(170, 0, 0, 0) : 0, DTA_Bottom320x200, Scaled); + } + } +} +