mirror of
https://github.com/ZDoom/Raze.git
synced 2024-12-16 07:31:23 +00:00
1105 lines
33 KiB
C++
1105 lines
33 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
Shadow Warrior is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "ns.h"
|
|
|
|
#undef MAIN
|
|
#include "build.h"
|
|
|
|
#include "game.h"
|
|
#include "names.h"
|
|
#include "names2.h"
|
|
#include "panel.h"
|
|
#include "pal.h"
|
|
#include "misc.h"
|
|
#include "player.h"
|
|
#include "v_2ddrawer.h"
|
|
#include "statusbar.h"
|
|
#include "network.h"
|
|
#include "v_draw.h"
|
|
#include "menus.h"
|
|
#include "automap.h"
|
|
|
|
|
|
BEGIN_SW_NS
|
|
|
|
enum
|
|
{
|
|
ID_PanelMedkit = 2396,
|
|
ID_PanelRepairKit = 2399,
|
|
ID_PanelCloak = 2397, //2400
|
|
ID_PanelNightVision = 2398,
|
|
ID_PanelChemBomb = 2407,
|
|
ID_PanelFlashBomb = 2408,
|
|
ID_PanelCaltrops = 2409,
|
|
};
|
|
|
|
static const short icons[] = {
|
|
ID_PanelMedkit,
|
|
ID_PanelRepairKit,
|
|
ID_PanelCloak,
|
|
ID_PanelNightVision,
|
|
ID_PanelChemBomb,
|
|
ID_PanelFlashBomb,
|
|
ID_PanelCaltrops,
|
|
};
|
|
|
|
class DSWStatusBar : public DBaseStatusBar
|
|
{
|
|
DECLARE_CLASS(DSWStatusBar, DBaseStatusBar)
|
|
HAS_OBJECT_POINTERS
|
|
|
|
TObjPtr<DHUDFont*> miniFont, numberFont;
|
|
|
|
enum
|
|
{
|
|
PANEL_HEALTH_BOX_X = 20,
|
|
PANEL_BOX_Y = (174 - 6),
|
|
PANEL_HEALTH_XOFF = 2,
|
|
PANEL_HEALTH_YOFF = 4,
|
|
|
|
PANEL_AMMO_BOX_X = 197,
|
|
PANEL_AMMO_XOFF = 1,
|
|
PANEL_AMMO_YOFF = 4,
|
|
|
|
WSUM_X = 93,
|
|
WSUM_Y = PANEL_BOX_Y+1,
|
|
WSUM_XOFF = 25,
|
|
WSUM_YOFF = 6,
|
|
|
|
PANEL_KEYS_BOX_X = 276,
|
|
PANEL_KEYS_XOFF = 0,
|
|
PANEL_KEYS_YOFF = 2,
|
|
|
|
PANEL_ARMOR_BOX_X = 56,
|
|
PANEL_ARMOR_XOFF = 2,
|
|
PANEL_ARMOR_YOFF = 4,
|
|
|
|
FRAG_YOFF = 2,
|
|
|
|
INVENTORY_BOX_X = 231,
|
|
INVENTORY_BOX_Y = (176-8),
|
|
|
|
INVENTORY_PIC_XOFF = 1,
|
|
INVENTORY_PIC_YOFF = 1,
|
|
|
|
INVENTORY_PERCENT_XOFF = 19,
|
|
INVENTORY_PERCENT_YOFF = 13,
|
|
|
|
INVENTORY_STATE_XOFF = 19,
|
|
INVENTORY_STATE_YOFF = 1,
|
|
|
|
MINI_BAR_Y = 174 ,
|
|
MINI_BAR_HEALTH_BOX_X = 4,
|
|
MINI_BAR_AMMO_BOX_X = 32,
|
|
MINI_BAR_INVENTORY_BOX_X = 64,
|
|
MINI_BAR_INVENTORY_BOX_Y = MINI_BAR_Y,
|
|
|
|
};
|
|
|
|
enum
|
|
{
|
|
PANEL_FONT_G = 3636,
|
|
PANEL_FONT_Y = 3646,
|
|
PANEL_FONT_R = 3656,
|
|
|
|
PANEL_SM_FONT_G = 3601,
|
|
PANEL_SM_FONT_Y = 3613,
|
|
PANEL_SM_FONT_R = 3625,
|
|
|
|
PANEL_KEY_RED = 2392,
|
|
PANEL_KEY_GREEN = 2393,
|
|
PANEL_KEY_BLUE = 2394,
|
|
PANEL_KEY_YELLOW = 2395,
|
|
PANEL_SKELKEY_GOLD = 2448,
|
|
PANEL_SKELKEY_SILVER= 2449,
|
|
PANEL_SKELKEY_BRONZE= 2458,
|
|
PANEL_SKELKEY_RED = 2459,
|
|
|
|
MINI_BAR_HEALTH_BOX_PIC = 2437,
|
|
MINI_BAR_AMMO_BOX_PIC = 2437,
|
|
MINI_BAR_INVENTORY_BOX_PIC = 2438,
|
|
|
|
ID_SelectionBox = 2435,
|
|
};
|
|
|
|
|
|
public:
|
|
DSWStatusBar()
|
|
{
|
|
numberFont = Create<DHUDFont>( BigFont, 0, Off, 1, 1 );
|
|
miniFont = Create<DHUDFont>(SmallFont2, 0, Off, 1, 1 );
|
|
}
|
|
|
|
private:
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayPanelNumber(double xs, double ys, int number)
|
|
{
|
|
char buffer[32];
|
|
char* ptr;
|
|
double x;
|
|
|
|
mysnprintf(buffer, 32, "%03d", number);
|
|
|
|
for (ptr = buffer, x = xs; *ptr; ptr++)
|
|
{
|
|
if (!isdigit(*ptr))
|
|
{
|
|
continue;
|
|
}
|
|
int tex = PANEL_FONT_G + (*ptr - '0');
|
|
DrawGraphic(tileGetTexture(tex), x, ys, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1);
|
|
x += tileWidth(tex) + 1;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplaySummaryString(double xs, double ys, int color, int shade, const char* buffer)
|
|
{
|
|
double x;
|
|
const char* ptr;
|
|
char ch;
|
|
int font_pic;
|
|
static const short font_base[] = { PANEL_SM_FONT_G, PANEL_SM_FONT_Y, PANEL_SM_FONT_R };
|
|
|
|
assert(color < 3);
|
|
for (ptr = buffer, x = xs; *ptr; ptr++)
|
|
{
|
|
ch = *ptr;
|
|
if (ch == ' ')
|
|
{
|
|
x += 4;
|
|
continue;
|
|
}
|
|
|
|
switch (ch)
|
|
{
|
|
case '\\':
|
|
ch = '0' - 1; // one pic before 0
|
|
break;
|
|
case ':':
|
|
ch = '9' + 1; // one pic after nine
|
|
break;
|
|
}
|
|
|
|
font_pic = font_base[color] + (ch - '0');
|
|
DrawGraphic(tileGetTexture(font_pic), x, ys, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1, shadeToLight(shade));
|
|
x += tileWidth(font_pic) + 1;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayTimeLimit(PLAYERp pp)
|
|
{
|
|
int seconds = gNet.TimeLimitClock / 120;
|
|
sprintf(ds, "%03d:%02d", seconds / 60, seconds % 60);
|
|
DisplaySummaryString(PANEL_KEYS_BOX_X + 1, PANEL_BOX_Y + 6, 0, 0, ds);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// todo: migrate to FFont to support localization
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayTinyString(double xs, double ys, const char* buffer, int pal)
|
|
{
|
|
SBar_DrawString(this, miniFont, buffer, xs, ys, DI_ITEM_LEFT_TOP, CR_UNTRANSLATED, 1, -1, -1, 1, 1);
|
|
}
|
|
|
|
void DisplayFragString(PLAYERp pp, double xs, double ys, const char* buffer)
|
|
{
|
|
DisplayTinyString(xs, ys, buffer, User[pp->SpriteP - sprite]->spal);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayFragNumbers()
|
|
{
|
|
for (int pnum = 0; pnum < 4; pnum++)
|
|
{
|
|
char buffer[32];
|
|
short xs, ys;
|
|
short frag_bar;
|
|
|
|
static int xoffs[] =
|
|
{
|
|
69, 147, 225, 303
|
|
};
|
|
|
|
ys = FRAG_YOFF;
|
|
|
|
// frag bar 0 or 1
|
|
frag_bar = ((pnum) / 4);
|
|
// move y down according to frag bar number
|
|
ys = ys + (tileHeight(FRAG_BAR) - 2) * frag_bar;
|
|
|
|
// move x over according to the number of players
|
|
xs = xoffs[MOD4(pnum)];
|
|
|
|
mysnprintf(buffer, 32, "%03d", Player[pnum].Kills);
|
|
|
|
DisplayFragString(&Player[pnum], xs, ys, buffer);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayFragNames()
|
|
{
|
|
for (int pnum = 0; pnum < 4; pnum++)
|
|
{
|
|
short xs, ys;
|
|
short frag_bar;
|
|
|
|
static int xoffs[] =
|
|
{
|
|
7, 85, 163, 241
|
|
};
|
|
|
|
ys = FRAG_YOFF;
|
|
|
|
// frag bar 0 or 1
|
|
frag_bar = ((pnum) / 4);
|
|
// move y down according to frag bar number
|
|
ys = ys + (tileHeight(FRAG_BAR) - 2) * frag_bar;
|
|
|
|
// move x over according to the number of players
|
|
xs = xoffs[MOD4(pnum)];
|
|
|
|
DisplayFragString(&Player[pnum], xs, ys, Player[pnum].PlayerName);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayFragBar(PLAYERp pp)
|
|
{
|
|
// must draw this in HUD mode and align to the top center
|
|
short i, num_frag_bars;
|
|
int y;
|
|
|
|
if (numplayers <= 1)
|
|
return;
|
|
|
|
if (gNet.MultiGameType == MULTI_GAME_COOPERATIVE)
|
|
return;
|
|
|
|
// if player sprite has not been initialized we have no business
|
|
// sticking a frag bar up. Prevents processing from MenuLevel etc.
|
|
if (!pp->SpriteP)
|
|
return;
|
|
|
|
//num_frag_bars = ((numplayers-1)/4)+1;
|
|
num_frag_bars = ((OrigCommPlayers - 1) / 4) + 1;
|
|
|
|
for (i = windowxy1.x; i <= windowxy2.x; i++)
|
|
{
|
|
y = (tileHeight(FRAG_BAR) * num_frag_bars) - (2 * (num_frag_bars - 1));
|
|
y = y * (ydim / 200.0);
|
|
}
|
|
|
|
for (i = 0, y = 0; i < num_frag_bars; i++)
|
|
{
|
|
DrawGraphic(tileGetTexture(FRAG_BAR), 0, y, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1);
|
|
y += tileHeight(FRAG_BAR) - 2;
|
|
}
|
|
DisplayFragNames();
|
|
DisplayFragNumbers();
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void PlayerUpdateWeaponSummary(PLAYERp pp, int UpdateWeaponNum)
|
|
{
|
|
USERp u = User[pp->PlayerSprite].Data();
|
|
int x, y;
|
|
int pos;
|
|
int column;
|
|
int WeaponNum, wpntmp;
|
|
int color, shade;
|
|
char ds[32];
|
|
|
|
WeaponNum = UpdateWeaponNum;
|
|
|
|
if (DamageData[WeaponNum].with_weapon != -1)
|
|
{
|
|
WeaponNum = DamageData[WeaponNum].with_weapon;
|
|
}
|
|
|
|
static short wsum_xoff[3] = { 0,36,66 };
|
|
static const char* wsum_fmt2[3] = { "%3d/%-3d", "%2d/%-2d", "%2d/%-2d" };
|
|
|
|
pos = WeaponNum - 1;
|
|
column = pos / 3;
|
|
if (column > 2) column = 2;
|
|
x = WSUM_X + wsum_xoff[column];
|
|
y = WSUM_Y + (WSUM_YOFF * (pos % 3));
|
|
|
|
if (UpdateWeaponNum == u->WeaponNum)
|
|
{
|
|
shade = 0;
|
|
color = 0;
|
|
}
|
|
else
|
|
{
|
|
shade = 11;
|
|
color = 0;
|
|
}
|
|
|
|
wpntmp = WeaponNum + 1;
|
|
if (wpntmp > 9)
|
|
wpntmp = 0;
|
|
mysnprintf(ds, 32, "%d:", wpntmp);
|
|
|
|
if (TEST(pp->WpnFlags, BIT(WeaponNum)))
|
|
DisplaySummaryString(x, y, 1, shade, ds);
|
|
else
|
|
DisplaySummaryString(x, y, 2, shade + 6, ds);
|
|
|
|
mysnprintf(ds, 32, wsum_fmt2[column], pp->WpnAmmo[WeaponNum], DamageData[WeaponNum].max_ammo);
|
|
DisplaySummaryString(x + 6, y, color, shade, ds);
|
|
}
|
|
|
|
void PlayerUpdateWeaponSummaryAll(PLAYERp pp)
|
|
{
|
|
for (int i = WPN_STAR; i <= WPN_HEART; i++)
|
|
{
|
|
PlayerUpdateWeaponSummary(pp, i);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayKeys(PLAYERp pp, double xs, double ys, double scalex = 1, double scaley = 1)
|
|
{
|
|
double x, y;
|
|
int row, col;
|
|
int i, xsize, ysize;
|
|
|
|
static short StatusKeyPics[] =
|
|
{
|
|
PANEL_KEY_RED,
|
|
PANEL_KEY_BLUE,
|
|
PANEL_KEY_GREEN,
|
|
PANEL_KEY_YELLOW,
|
|
PANEL_SKELKEY_GOLD,
|
|
PANEL_SKELKEY_SILVER,
|
|
PANEL_SKELKEY_BRONZE,
|
|
PANEL_SKELKEY_RED
|
|
};
|
|
|
|
|
|
xsize = tileWidth(PANEL_KEY_RED) + 1;
|
|
ysize = tileHeight(PANEL_KEY_RED) + 2;
|
|
|
|
i = 0;
|
|
for (row = 0; row < 2; row++)
|
|
{
|
|
for (col = 0; col < 2; col++)
|
|
{
|
|
if (pp->HasKey[i])
|
|
{
|
|
x = xs + PANEL_KEYS_XOFF + (row * xsize);
|
|
y = ys + PANEL_KEYS_YOFF + (col * ysize);
|
|
DrawGraphic(tileGetTexture(StatusKeyPics[i]), x, y, DI_ITEM_LEFT_TOP, 1, -1, -1, scalex, scaley);
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// Check for skeleton keys
|
|
i = 0;
|
|
for (row = 0; row < 2; row++)
|
|
{
|
|
for (col = 0; col < 2; col++)
|
|
{
|
|
if (pp->HasKey[i + 4])
|
|
{
|
|
x = xs + PANEL_KEYS_XOFF + (row * xsize);
|
|
y = ys + PANEL_KEYS_YOFF + (col * ysize);
|
|
DrawGraphic(tileGetTexture(StatusKeyPics[i + 4]), x, y, DI_ITEM_LEFT_TOP, 1, -1, -1, scalex, scaley);
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void PlayerUpdateInventoryPercent(PLAYERp pp, int InventoryBoxX, int InventoryBoxY, int InventoryXoff, int InventoryYoff)
|
|
{
|
|
char ds[32];
|
|
INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
|
|
|
|
int x = InventoryBoxX + INVENTORY_PERCENT_XOFF + InventoryXoff;
|
|
int y = InventoryBoxY + INVENTORY_PERCENT_YOFF + InventoryYoff;
|
|
|
|
if (TEST(id->Flags, INVF_COUNT))
|
|
{
|
|
mysnprintf(ds, 32, "%d", pp->InventoryAmount[pp->InventoryNum]);
|
|
}
|
|
else
|
|
{
|
|
mysnprintf(ds, 32, "%d%c", pp->InventoryPercent[pp->InventoryNum], '%');
|
|
}
|
|
DisplayTinyString(x, y, ds, 0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void PlayerUpdateInventoryPic(PLAYERp pp, int InventoryBoxX, int InventoryBoxY, int InventoryXoff, int InventoryYoff)
|
|
{
|
|
INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
|
|
int x = InventoryBoxX + INVENTORY_PIC_XOFF + InventoryXoff;
|
|
int y = InventoryBoxY + INVENTORY_PIC_YOFF + InventoryYoff;
|
|
DrawGraphic(tileGetTexture(icons[pp->InventoryNum]), x, y, DI_ITEM_LEFT_TOP, 1, -1, -1, id->Scale/65536., id->Scale / 65536.);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void PlayerUpdateInventoryState(PLAYERp pp, double InventoryBoxX, double InventoryBoxY, int InventoryXoff, int InventoryYoff)
|
|
{
|
|
char ds[32];
|
|
INVENTORY_DATAp id = &InventoryData[pp->InventoryNum];
|
|
|
|
double x = InventoryBoxX + INVENTORY_STATE_XOFF + InventoryXoff;
|
|
double y = InventoryBoxY + INVENTORY_STATE_YOFF + InventoryYoff;
|
|
|
|
if (TEST(id->Flags, INVF_AUTO_USE))
|
|
{
|
|
DisplayTinyString(x, y, "AUTO", 0);
|
|
}
|
|
else if (TEST(id->Flags, INVF_TIMED))
|
|
{
|
|
DisplayTinyString(x, y, pp->InventoryActive[pp->InventoryNum] ? "ON" : "OFF", 0);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayBarInventory(PLAYERp pp)
|
|
{
|
|
int InventoryBoxX = INVENTORY_BOX_X;
|
|
int InventoryBoxY = INVENTORY_BOX_Y;
|
|
|
|
int InventoryXoff = -1;
|
|
int InventoryYoff = 0;
|
|
|
|
// put pic
|
|
if (pp->InventoryAmount[pp->InventoryNum])
|
|
{
|
|
PlayerUpdateInventoryPic(pp, InventoryBoxX, InventoryBoxY, 0, InventoryYoff);
|
|
// Auto/On/Off
|
|
PlayerUpdateInventoryState(pp, InventoryBoxX, InventoryBoxY, InventoryXoff, InventoryYoff);
|
|
// Percent count/Item count
|
|
PlayerUpdateInventoryPercent(pp, InventoryBoxX, InventoryBoxY, InventoryXoff, InventoryYoff);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DrawCompass(PLAYERp pp)
|
|
{
|
|
enum
|
|
{
|
|
COMPASS_TIC = 2380,
|
|
COMPASS_TIC2 = 2381,
|
|
|
|
COMPASS_NORTH = 2382,
|
|
COMPASS_NORTH2 = 2383,
|
|
|
|
COMPASS_SOUTH = 2384,
|
|
COMPASS_SOUTH2 = 2385,
|
|
|
|
COMPASS_EAST = 2386,
|
|
COMPASS_EAST2 = 2387,
|
|
|
|
COMPASS_WEST = 2388,
|
|
COMPASS_WEST2 = 2389,
|
|
|
|
COMPASS_MID_TIC = 2390,
|
|
COMPASS_MID_TIC2 = 2391,
|
|
|
|
COMPASS_X = 140,
|
|
COMPASS_Y = (162-5),
|
|
};
|
|
|
|
auto NORM_CANG = [](int ang) { return (((ang)+32) & 31); };
|
|
|
|
int start_ang, ang;
|
|
int x_size = tileWidth(COMPASS_NORTH);
|
|
int x;
|
|
int i;
|
|
|
|
static const short CompassPic[32] =
|
|
{
|
|
COMPASS_EAST, COMPASS_EAST2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
COMPASS_MID_TIC, COMPASS_MID_TIC2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
|
|
COMPASS_SOUTH, COMPASS_SOUTH2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
COMPASS_MID_TIC, COMPASS_MID_TIC2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
|
|
COMPASS_WEST, COMPASS_WEST2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
COMPASS_MID_TIC, COMPASS_MID_TIC2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
|
|
COMPASS_NORTH, COMPASS_NORTH2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
COMPASS_MID_TIC, COMPASS_MID_TIC2,
|
|
COMPASS_TIC, COMPASS_TIC2,
|
|
};
|
|
|
|
static const short CompassShade[10] =
|
|
{
|
|
//20, 16, 11, 6, 1, 1, 6, 11, 16, 20
|
|
25, 19, 15, 9, 1, 1, 9, 15, 19, 25
|
|
};
|
|
|
|
ang = pp->angle.ang.asbuild();
|
|
|
|
if (pp->sop_remote)
|
|
ang = 0;
|
|
|
|
start_ang = (ang + 32) >> 6;
|
|
|
|
start_ang = NORM_CANG(start_ang - 4);
|
|
|
|
for (i = 0, x = COMPASS_X; i < 10; i++)
|
|
{
|
|
DrawGraphic(tileGetTexture(CompassPic[NORM_CANG(start_ang + i)]), x, COMPASS_Y, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1, shadeToLight(CompassShade[i]));
|
|
x += x_size;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DrawStatusBar()
|
|
{
|
|
auto pp = Player + screenpeek;
|
|
USERp u = User[pp->PlayerSprite].Data();
|
|
BeginStatusBar(320, 200, tileHeight(STATUS_BAR));
|
|
|
|
if (hud_size == Hud_StbarOverlay) Set43ClipRect();
|
|
int left = (320 - tileWidth(STATUS_BAR)) / 2;
|
|
DrawGraphic(tileGetTexture(STATUS_BAR), left, 200, DI_ITEM_LEFT_BOTTOM, 1, -1, -1, 1, 1);
|
|
twod->ClearClipRect();
|
|
DisplayPanelNumber(PANEL_HEALTH_BOX_X + PANEL_HEALTH_XOFF, PANEL_BOX_Y + PANEL_HEALTH_YOFF, u->Health);
|
|
DisplayPanelNumber(PANEL_ARMOR_BOX_X + PANEL_ARMOR_XOFF, PANEL_BOX_Y + PANEL_ARMOR_YOFF, pp->Armor);
|
|
if (u->WeaponNum != WPN_FIST && u->WeaponNum != WPN_SWORD)
|
|
DisplayPanelNumber(PANEL_AMMO_BOX_X + PANEL_AMMO_XOFF, PANEL_BOX_Y + PANEL_AMMO_YOFF, pp->WpnAmmo[u->WeaponNum]);
|
|
PlayerUpdateWeaponSummaryAll(pp);
|
|
if (gNet.MultiGameType != MULTI_GAME_COMMBAT)
|
|
DisplayKeys(pp, PANEL_KEYS_BOX_X, PANEL_BOX_Y);
|
|
else if (gNet.TimeLimit)
|
|
DisplayTimeLimit(pp);
|
|
DisplayBarInventory(pp);
|
|
DrawCompass(pp);
|
|
PrintLevelStats(-3);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DisplayMinibarInventory(PLAYERp pp)
|
|
{
|
|
int InventoryBoxX = MINI_BAR_INVENTORY_BOX_X;
|
|
int InventoryBoxY = MINI_BAR_INVENTORY_BOX_Y - 200;
|
|
|
|
int InventoryXoff = 0;
|
|
int InventoryYoff = 1;
|
|
|
|
if (pp->InventoryAmount[pp->InventoryNum])
|
|
{
|
|
PlayerUpdateInventoryPic(pp, InventoryBoxX, InventoryBoxY, InventoryXoff+1, InventoryYoff);
|
|
// Auto/On/Off
|
|
PlayerUpdateInventoryState(pp, InventoryBoxX, InventoryBoxY, InventoryXoff, InventoryYoff);
|
|
// Percent count/Item count
|
|
PlayerUpdateInventoryPercent(pp, InventoryBoxX, InventoryBoxY, InventoryXoff, InventoryYoff);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Used in DrawHUD2() for determining whether a reloadable weapon is reloading.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
bool DoReloadStatus(char *reloadstate, int ammo)
|
|
{
|
|
bool reloading = ammo == 0 && *reloadstate != 2;
|
|
|
|
if (ammo == 0 && *reloadstate == 0)
|
|
{
|
|
*reloadstate = 1;
|
|
}
|
|
else if (ammo)
|
|
{
|
|
*reloadstate = 0;
|
|
}
|
|
|
|
return reloading;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DrawHUD1()
|
|
{
|
|
BeginHUD(320, 200, 1);
|
|
auto pp = Player + screenpeek;
|
|
USERp u = User[pp->PlayerSprite].Data();
|
|
int x, y;
|
|
INVENTORY_DATAp id;
|
|
|
|
x = MINI_BAR_HEALTH_BOX_X;
|
|
y = -26;
|
|
|
|
DrawGraphic(tileGetTexture(MINI_BAR_HEALTH_BOX_PIC), x, y, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1);
|
|
|
|
x = MINI_BAR_HEALTH_BOX_X + 3;
|
|
DisplayPanelNumber(x, y + 5, u->Health);
|
|
|
|
if (u->WeaponNum != WPN_SWORD && u->WeaponNum != WPN_FIST)
|
|
{
|
|
x = MINI_BAR_AMMO_BOX_X;
|
|
DrawGraphic(tileGetTexture(MINI_BAR_AMMO_BOX_PIC), x, y, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1);
|
|
|
|
x = MINI_BAR_AMMO_BOX_X + 3;
|
|
DisplayPanelNumber(x, y + 5, pp->WpnAmmo[u->WeaponNum]);
|
|
}
|
|
PrintLevelStats(30);
|
|
|
|
if (!pp->InventoryAmount[pp->InventoryNum])
|
|
return;
|
|
|
|
// Inventory Box
|
|
x = MINI_BAR_INVENTORY_BOX_X;
|
|
|
|
DrawGraphic(tileGetTexture(MINI_BAR_INVENTORY_BOX_PIC), x, y, DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1);
|
|
DisplayMinibarInventory(pp);
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// Fullscreen HUD variant #1
|
|
//
|
|
//==========================================================================
|
|
|
|
void DrawHUD2()
|
|
{
|
|
BeginHUD(320, 200, 1);
|
|
|
|
auto pp = Player + screenpeek;
|
|
USERp u = User[pp->PlayerSprite].Data();
|
|
|
|
FString format;
|
|
FGameTexture* img;
|
|
double imgScale;
|
|
double baseScale = numberFont->mFont->GetHeight() * 0.83125;
|
|
|
|
//
|
|
// Health
|
|
//
|
|
img = tileGetTexture(ICON_SM_MEDKIT);
|
|
imgScale = baseScale / img->GetDisplayHeight();
|
|
DrawGraphic(img, 1.5, -1, DI_ITEM_LEFT_BOTTOM, 1., -1, -1, imgScale, imgScale);
|
|
|
|
if (!althud_flashing || u->Health > (u->MaxHealth >> 2) || (PlayClock & 32))
|
|
{
|
|
int s = -8;
|
|
if (althud_flashing && u->Health > u->MaxHealth)
|
|
s += bsin(PlayClock << 5, -10);
|
|
int intens = clamp(255 - 4 * s, 0, 255);
|
|
auto pe = PalEntry(255, intens, intens, intens);
|
|
format.Format("%d", u->Health);
|
|
SBar_DrawString(this, numberFont, format, 24.25, -numberFont->mFont->GetHeight() + 2, DI_TEXT_ALIGN_LEFT, CR_UNTRANSLATED, 1, 0, 0, 1, 1);
|
|
}
|
|
|
|
//
|
|
// Armor
|
|
//
|
|
img = tileGetTexture(ICON_ARMOR);
|
|
imgScale = baseScale / img->GetDisplayHeight();
|
|
DrawGraphic(img, 80.75, -1, DI_ITEM_LEFT_BOTTOM, 1., -1, -1, imgScale, imgScale);
|
|
|
|
format.Format("%d", pp->Armor);
|
|
SBar_DrawString(this, numberFont, format, 108.5, -numberFont->mFont->GetHeight() + 2, DI_TEXT_ALIGN_LEFT, CR_UNTRANSLATED, 1, 0, 0, 1, 1);
|
|
|
|
//
|
|
// Weapon
|
|
//
|
|
const short ammo_sprites[] = { -1, ICON_STAR, ICON_LG_SHOTSHELL, ICON_LG_UZI_AMMO, ICON_MICRO_BATTERY, ICON_LG_GRENADE, ICON_LG_MINE, ICON_RAIL_AMMO,
|
|
ICON_FIREBALL_LG_AMMO, ICON_HEART_LG_AMMO, ICON_FIREBALL_LG_AMMO, ICON_FIREBALL_LG_AMMO,ICON_MICRO_BATTERY, -1 };
|
|
|
|
int weapon = u->WeaponNum;
|
|
int wicon = ammo_sprites[weapon];
|
|
if (wicon > 0)
|
|
{
|
|
int ammo = pp->WpnAmmo[weapon];
|
|
bool reloadableWeapon = weapon == WPN_SHOTGUN || weapon == WPN_UZI;
|
|
if (!reloadableWeapon || (reloadableWeapon && !cl_showmagamt))
|
|
{
|
|
format.Format("%d", ammo);
|
|
}
|
|
else
|
|
{
|
|
short capacity;
|
|
switch (weapon)
|
|
{
|
|
case WPN_SHOTGUN:
|
|
capacity = 4;
|
|
break;
|
|
case WPN_UZI:
|
|
capacity = pp->WpnUziType ? 50 : 100;
|
|
break;
|
|
}
|
|
short clip = CalcMagazineAmount(ammo, capacity, DoReloadStatus(&pp->WpnReloadState, ammo % capacity));
|
|
format.Format("%d/%d", clip, ammo - clip);
|
|
}
|
|
img = tileGetTexture(wicon);
|
|
imgScale = baseScale / img->GetDisplayHeight();
|
|
auto imgX = 21.125;
|
|
auto strlen = format.Len();
|
|
|
|
if (strlen > 1)
|
|
{
|
|
imgX += (imgX * 0.855) * (strlen - 1);
|
|
}
|
|
|
|
if ((!althud_flashing || PlayClock & 32 || ammo > (DamageData[weapon].max_ammo / 10)))
|
|
{
|
|
SBar_DrawString(this, numberFont, format, -1.5, -numberFont->mFont->GetHeight() + 2, DI_TEXT_ALIGN_RIGHT, CR_UNTRANSLATED, 1, 0, 0, 1, 1);
|
|
}
|
|
|
|
DrawGraphic(img, -imgX, -1, DI_ITEM_RIGHT_BOTTOM, 1, -1, -1, imgScale, imgScale);
|
|
}
|
|
|
|
//
|
|
// Selected inventory item
|
|
//
|
|
img = tileGetTexture(icons[pp->InventoryNum]);
|
|
imgScale = baseScale / img->GetDisplayHeight();
|
|
int x = 165;
|
|
DrawGraphic(img, x, -1, DI_ITEM_LEFT_BOTTOM, 1, -1, -1, imgScale, imgScale);
|
|
|
|
PlayerUpdateInventoryState(pp, x + 3.0, -18.0, 1, 1);
|
|
PlayerUpdateInventoryPercent(pp, x + 3.5, -20.5, 1, 1);
|
|
|
|
//
|
|
// keys
|
|
//
|
|
DisplayKeys(pp, -25, -38, 0.8625, 0.8625);
|
|
PrintLevelStats(int(baseScale + 4));
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DrawInventoryIcon(double xs, double ys, int align, int InventoryNum, int amount, bool selected)
|
|
{
|
|
double x, y;
|
|
const int INVENTORY_ICON_WIDTH = 28;
|
|
|
|
// check invalid value
|
|
assert(InventoryNum < MAX_INVENTORY);
|
|
|
|
x =xs + (InventoryNum * INVENTORY_ICON_WIDTH);
|
|
y = ys;
|
|
auto tex = icons[InventoryNum];
|
|
auto scale = InventoryData[InventoryNum].Scale / 65536.;
|
|
DrawGraphic(tileGetTexture(tex), x, y, align | DI_ITEM_LEFT_TOP, amount? 1. : 0.333, -1, -1, scale, scale);
|
|
if (selected)
|
|
{
|
|
DrawGraphic(tileGetTexture(ID_SelectionBox), x-5, y-5, align | DI_ITEM_LEFT_TOP, 1, -1, -1, 1, 1);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// INVENTORY BAR
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
void DrawInventory(double xs, double ys, int align)
|
|
{
|
|
auto pp = Player + screenpeek;
|
|
short inv = 0;
|
|
INVENTORY_DATAp id;
|
|
|
|
if (!pp->InventoryBarTics)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (id = InventoryData; id->Name; id++, inv++)
|
|
{
|
|
DrawInventoryIcon(xs, ys, align, inv, pp->InventoryAmount[inv], inv == pp->InventoryNum);
|
|
}
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// Statistics output
|
|
//
|
|
//==========================================================================
|
|
|
|
void PrintLevelStats(int bottomy)
|
|
{
|
|
FLevelStats stats{};
|
|
stats.fontscale = 1;
|
|
stats.spacing = 7;
|
|
stats.screenbottomspace = bottomy;
|
|
stats.font = SmallFont;
|
|
stats.time = Scale(PlayClock, 1000, 120);
|
|
|
|
if (automapMode == am_full)
|
|
{
|
|
stats.letterColor = CR_SAPPHIRE;
|
|
stats.standardColor = CR_UNTRANSLATED;
|
|
|
|
bool textfont = am_textfont;
|
|
if (!am_textfont)
|
|
{
|
|
// For non-English languages force use of the text font. The tiny one is simply too small to ever add localized characters to it.
|
|
auto p = GStrings["REQUIRED_CHARACTERS"];
|
|
if (p && *p) textfont = true;
|
|
}
|
|
|
|
if (!textfont)
|
|
{
|
|
stats.font = SmallFont2;
|
|
stats.spacing = 6;
|
|
}
|
|
else stats.spacing = SmallFont->GetHeight() + 1;
|
|
DBaseStatusBar::PrintAutomapInfo(stats, textfont);
|
|
}
|
|
// JBF 20040124: display level stats in screen corner
|
|
else if (hud_stats && !(CommEnabled || numplayers > 1))
|
|
{
|
|
auto pp = Player + screenpeek;
|
|
|
|
stats.kills = Player->Kills;
|
|
stats.maxkills = TotalKillable;
|
|
stats.frags = -1;
|
|
stats.secrets = Player->SecretsFound;
|
|
stats.maxsecrets = LevelSecrets;
|
|
|
|
stats.letterColor = CR_RED;
|
|
stats.standardColor = CR_TAN;
|
|
stats.completeColor = CR_FIRE;
|
|
|
|
DBaseStatusBar::PrintLevelStats(stats);
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
public:
|
|
void UpdateStatusBar()
|
|
{
|
|
int nPalette = 0;
|
|
double inv_x, inv_y;
|
|
int align;
|
|
|
|
if (hud_size == Hud_Nothing)
|
|
{
|
|
align = DI_SCREEN_RIGHT_BOTTOM;
|
|
inv_x = -210;
|
|
inv_y = -28;
|
|
PrintLevelStats(2);
|
|
}
|
|
else if (hud_size == Hud_full)
|
|
{
|
|
align = DI_SCREEN_CENTER_BOTTOM;
|
|
inv_x = -80;
|
|
inv_y = -40;
|
|
DrawHUD2();
|
|
}
|
|
else if (hud_size == Hud_Mini)
|
|
{
|
|
align = DI_SCREEN_RIGHT_BOTTOM;
|
|
inv_x = -210;
|
|
inv_y = -28;
|
|
DrawHUD1();
|
|
}
|
|
else
|
|
{
|
|
align = 0;
|
|
inv_x = 80;
|
|
inv_y = 130;
|
|
DrawStatusBar();
|
|
}
|
|
DrawInventory(inv_x, inv_y, align);
|
|
}
|
|
|
|
};
|
|
|
|
IMPLEMENT_CLASS(DSWStatusBar, false, true)
|
|
IMPLEMENT_POINTERS_START(DSWStatusBar)
|
|
IMPLEMENT_POINTER(miniFont)
|
|
IMPLEMENT_POINTER(numberFont)
|
|
IMPLEMENT_POINTERS_END
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
static void UpdateFrame(void)
|
|
{
|
|
static const int kBackTile = 51;
|
|
auto tex = tileGetTexture(kBackTile);
|
|
|
|
twod->AddFlatFill(0, 0, xdim, windowxy1.y - 3, tex);
|
|
twod->AddFlatFill(0, windowxy2.y + 4, xdim, ydim, tex);
|
|
twod->AddFlatFill(0, windowxy1.y - 3, windowxy1.x - 3, windowxy2.y + 4, tex);
|
|
twod->AddFlatFill(windowxy2.x + 4, windowxy1.y - 3, xdim, windowxy2.y + 4, tex);
|
|
|
|
twod->AddFlatFill(windowxy1.x - 3, windowxy1.y - 3, windowxy1.x, windowxy2.y + 1, tex, 0, 1, 0xff545454);
|
|
twod->AddFlatFill(windowxy1.x, windowxy1.y - 3, windowxy2.x + 4, windowxy1.y, tex, 0, 1, 0xff545454);
|
|
twod->AddFlatFill(windowxy2.x + 1, windowxy1.y, windowxy2.x + 4, windowxy2.y + 4, tex, 0, 1, 0xff2a2a2a);
|
|
twod->AddFlatFill(windowxy1.x - 3, windowxy2.y + 1, windowxy2.x + 1, windowxy2.y + 4, tex, 0, 1, 0xff2a2a2a);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void DrawConString(int x, int y, const char* string, double alpha)
|
|
{
|
|
x = x * 2 - SmallFont->StringWidth(string) / 2;
|
|
y *= 2;
|
|
DrawText(twod, SmallFont, CR_TAN, x, y, string, DTA_FullscreenScale, FSMode_Fit640x400, DTA_Alpha, alpha, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
|
void UpdateStatusBar()
|
|
{
|
|
if (hud_size <= Hud_Stbar)
|
|
{
|
|
UpdateFrame();
|
|
}
|
|
|
|
StatusBar->UpdateStatusBar();
|
|
PLAYERp pp = &Player[screenpeek];
|
|
if (pp->cookieTime > 0)
|
|
{
|
|
const int MESSAGE_LINE = 142; // Used to be 164
|
|
|
|
if (!SmallFont2->CanPrint(pp->cookieQuote))
|
|
DrawConString(160, MESSAGE_LINE, pp->cookieQuote, clamp(pp->cookieTime / 60., 0., 1.));
|
|
else
|
|
MNU_DrawSmallString(160, MESSAGE_LINE, pp->cookieQuote, 0, 0, 0, clamp(pp->cookieTime / 60., 0., 1.));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
END_SW_NS
|