From 9bffe4ee5089afa2b9a1c2f5e3ea0c0b067532f8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 21 Mar 2017 20:09:09 +0100 Subject: [PATCH] - scriptified the main statusbar interface and the Strife status bar. Note that the Strife status bar does not draw the health bars yet. I tried to replace the hacky custom texture with a single fill operation but had to find out that all the coordinate mangling for the status bar is being done deep in the video code. This needs to be fixed before this can be made to work. Currently this is not usable in mods because they cannot initialize custom status bars yet. --- src/CMakeLists.txt | 1 - src/am_map.cpp | 2 - src/b_game.cpp | 7 +- src/c_console.cpp | 1 - src/d_main.cpp | 12 +- src/d_netinfo.cpp | 4 +- src/g_game.cpp | 6 +- src/g_level.cpp | 5 +- src/g_statusbar/sbar.h | 17 +- src/g_statusbar/shared_sbar.cpp | 239 +++- src/g_statusbar/strife_sbar.cpp | 1049 ----------------- src/gl/system/gl_swframebuffer.cpp | 1 - src/m_cheat.cpp | 2 - src/menu/videomenu.cpp | 2 +- src/p_mobj.cpp | 4 +- src/p_tick.cpp | 2 +- src/scripting/vm/vm.h | 2 +- src/scripting/zscript/zcc_compile.cpp | 3 + src/stats.cpp | 5 - src/v_draw.cpp | 9 +- src/v_video.cpp | 6 +- src/win32/fb_d3d9.cpp | 1 - wadsrc/static/zscript.txt | 3 + wadsrc/static/zscript/base.txt | 5 +- wadsrc/static/zscript/compatibility.txt | 7 - wadsrc/static/zscript/inventory/inventory.txt | 19 + wadsrc/static/zscript/shared/player.txt | 8 +- wadsrc/static/zscript/statusbar/statusbar.txt | 79 ++ .../static/zscript/statusbar/strife_sbar.txt | 854 ++++++++++++++ 29 files changed, 1186 insertions(+), 1169 deletions(-) delete mode 100644 src/g_statusbar/strife_sbar.cpp create mode 100644 wadsrc/static/zscript/statusbar/statusbar.txt create mode 100644 wadsrc/static/zscript/statusbar/strife_sbar.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1896c3ab8..b9100ff28 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 e62142590..1922b967c 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 1f32182f6..f8c15b1a0 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 18e99af5f..e2ffe2ec6 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 26df11577..3dd1a4238 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 70413496c..99e5eb128 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 92ccc6555..deee68862 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 fec1050ad..c77c10fe9 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 689bdc4ac..fc8aec70b 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 7be5073ef..f8e6087b4 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 13410e8f8..000000000 --- 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 38f1b56c1..6ff2e0943 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 170effaf1..4559ca1c2 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 2c3abe52b..b23798727 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 a95e1a433..83150c9e3 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 990cdaf64..3ef1775f5 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 cd4c07351..f49bd76e8 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 8d8277a6d..e468e23a3 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 237436c41..d0d5d2f02 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 a040b80cf..3d896ed65 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 0a7c4614f..4cc77cf0e 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 df180587e..3c07b9c14 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 892d7087f..fddfd1378 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 2ae84704c..7cce7fbc6 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 3699a8f3a..eaf77e0a4 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 48a88bc32..d5c15e0b2 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 3f7bc1975..8851242b0 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 000000000..3972a616c --- /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 000000000..d5c21f1ed --- /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); + } + } +} +