raze/wadsrc/static/zscript/games/blood/ui/sbar.zs
Christoph Oelckers 562c1a18c8 - integrate hud_althud into hud_size
This makes it easier to use and avoids rendering a fullscreen hud on a screen size with view border.
2022-10-30 16:51:39 +01:00

846 lines
26 KiB
Text

//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
Copyright (C) 2020-2021 Christoph Oelckers
This file is part of Raze.
This is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 2
as published by the Free Software Foundation.
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.
*/
//-------------------------------------------------------------------------
class BloodStatusBar : RazeStatusBar
{
static const String gAmmoIcons[] = { "", "AmmoIcon1", "AmmoIcon2", "AmmoIcon3", "AmmoIcon4", "AmmoIcon5", "AmmoIcon6", "AmmoIcon7", "AmmoIcon8", "AmmoIcon9", "AmmoIcon10", "AmmoIcon11" };
static const String gPackIcons[] = { "PackIcon1", "PackIcon2", "PackIcon3", "PackIcon4", "PackIcon5" };
static const String packIcons2[] = { "Pack2Icon1", "Pack2Icon2", "Pack2Icon3", "Pack2Icon4", "Pack2Icon5" };
HUDFont smallf, tinyf;
int team_score[2], team_ticker[2]; // placeholders for MP display
bool gBlueFlagDropped, gRedFlagDropped; // also placeholders until we know where MP will go.
override void Init()
{
smallf = HUDFont.Create(SmallFont, 0, Mono_Off, 0, 0);
tinyf = HUDFont.Create(Font.FindFont("DIGIFONT"), 4, Mono_CellRight, 0, 0);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int texWidth(String name)
{
let tex = TexMan.CheckForTexture(name, TexMan.Type_Any);
let siz = TexMan.GetScaledSize(tex);
return siz.x;
}
int texHeight(String name)
{
let tex = TexMan.CheckForTexture(name, TexMan.Type_Any);
let siz = TexMan.GetScaledSize(tex);
return siz.y;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DrawStatNumber(String pFormat, int nNumber, String nametemplate, double x, double y, int nShade, int nPalette, double nScale = 1, int align = 0)
{
String texname = String.Format("%s%d", nametemplate, 1);
double width = (texWidth(texname) + 1) * nScale;
String tempbuf = String.Format(pFormat, nNumber);
x += 0.5;
y += 0.5; // This is needed because due to using floating point math, this code rounds slightly differently which for the numbers can be a problem.
for (uint i = 0; i < tempbuf.length(); i++, x += width)
{
int c = tempbuf.ByteAt(i);
if (c < "0" || c > "9") continue;
texname = String.Format("%s%d", nametemplate, c - int("0"));
int flags = align | DI_ITEM_RELCENTER;
DrawImage(texname, (x, y), flags, 1, (-1, -1), (nScale, nScale), STYLE_Translucent, Raze.shadeToLight(nShade), Translation.MakeID(Translation_Remap, nPalette));
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DrawCharArray(String text, String nametemplate, double x, double y)
{
String texname = String.Format("%s%d", nametemplate, 1);
double width = (texWidth(texname) + 1);
x += 0.5;
y += 0.5; // This is needed because due to using floating point math, this code rounds slightly differently which for the numbers can be a problem.
for (uint i = 0; i < text.length(); i++, x += width)
{
int c = text.ByteAt(i);
// Hackasaurus rex to give me a slash when drawing the weapon count of a reloadable gun.
if (c == 47)
{
DrawImage("SBarSlash", (x, y), DI_ITEM_RELCENTER);
}
else
{
if (c < "0" || c > "9") continue;
texname = String.Format("%s%d", nametemplate, c - int("0"));
DrawImage(texname, (x, y), DI_ITEM_RELCENTER);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void TileHGauge(String nTile, double x, double y, double nMult, double nDiv, double sc = 1)
{
int w = texWidth(nTile);
double bx = w * sc * nMult / nDiv + x;
double scale = (bx - x) / w;
DrawImage(nTile, (x, y), DI_ITEM_LEFT_TOP, 1., (-1, -1), (sc, sc), clipwidth:scale);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DoLevelStats(BloodPlayer pPlayer, int bottomy, Summaryinfo summary)
{
StatsPrintInfo stats;
stats.fontscale = 1.;
stats.screenbottomspace = bottomy;
stats.letterColor = TEXTCOLOR_DARKRED;
stats.standardColor = TEXTCOLOR_DARKGRAY;
int y = -1;
int mask = 1;
if (automapMode == am_full)
{
stats.statfont = SmallFont2;
stats.spacing = 6;
stats.altspacing = SmallFont.GetHeight() + 2;
if (hud_size <= Hud_StbarOverlay) stats.screenbottomspace = 56;
y = PrintAutomapInfo(stats, summary, false);
mask = 2;
}
// Blood does not use am_overlay.
if (hud_stats & mask)
{
stats.statfont = SmallFont;
stats.completeColor = TEXTCOLOR_DARKGREEN;
stats.spacing = SmallFont.GetHeight() + 2;
PrintLevelStats(stats, summary, y);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
const nPowerUps = 11;
void drawPowerUps(BloodPlayer pPlayer)
{
static const float powerScale[] = { 0.4f, 0.4f, 0.3f, 0.3f, 0.4f, 0.3f, 0.4f, 0.5f, 0.3f, 0.4f, 0.4f };
static const int powerYoffs[] = { 0, 5, 9, 5, 9, 7, 4, 5, 9, 4, 4 };
static const int powerOrder[] = { Blood.kPwUpShadowCloak, Blood.kPwUpReflectShots, Blood.kPwUpDeathMask, Blood.kPwUpTwoGuns, Blood.kPwUpShadowCloakUseless, Blood.kPwUpFeatherFall,
Blood.kPwUpGasMask, Blood.kPwUpDoppleganger, Blood.kPwUpAsbestArmor, Blood.kPwUpGrowShroom, Blood.kPwUpShrinkShroom };
if (!hud_powerupduration)
return;
int powersort[nPowerUps];
for (int i = 0; i < nPowerUps; i++) powersort[i] = i;
for (int i = 0; i < nPowerUps; i++)
{
for (int j = i + 1; j < nPowerUps; j++)
{
int power1 = powersort[i];
int power2 = powersort[j];
if (pPlayer.pwUpTime[powerOrder[power1]] > pPlayer.pwUpTime[powerOrder[power2]])
{
powersort[i] = power2;
powersort[j] = power1;
}
}
}
int warningTime = 5;
int x = 15;
int y = -50;
for (int i = 0; i < nPowerUps; i++)
{
int order = powersort[i];
int power = powerOrder[order];
int time = pPlayer.pwUpTime[power];
if (time > 0)
{
int remainingSeconds = time / 100;
if (remainingSeconds > warningTime || (PlayClock & 32))
{
DrawTexture(Blood.PowerUpIcon(power), (x, y + powerYoffs[order]), DI_SCREEN_LEFT_CENTER | DI_ITEM_RELCENTER, scale:(powerScale[order], powerScale[order]));
}
DrawStatNumber("%d", remainingSeconds, "SBarNumberInv", x + 15, y, 0, remainingSeconds > warningTime ? 0 : Translation.MakeID(Translation_Remap, 2), 0.5, DI_SCREEN_LEFT_CENTER);
y += 20;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawInventory(BloodPlayer pPlayer, int x, int y)
{
int packs[5];
if (pPlayer.packItemTime)
{
int nPacks = 0;
int width = 0;
for (int i = 0; i < 5; i++)
{
if (pPlayer.packSlots[i].curAmount)
{
packs[nPacks++] = i;
width += texWidth(gPackIcons[i]) + 1;
}
}
width /= 2;
x -= width;
for (int i = 0; i < nPacks; i++)
{
int nPack = packs[i];
DrawImage("PackBG", (x + 1, y - 8), DI_ITEM_RELCENTER, style:STYLE_Normal);
DrawImage("PackBG", (x + 1, y - 6), DI_ITEM_RELCENTER, style:STYLE_Normal);
DrawImage(gPackIcons[nPack], (x + 1, y + 1), DI_ITEM_RELCENTER, style:STYLE_Normal);
if (nPack == pPlayer.packItemId)
DrawImage("PackSelect", (x + 1, y + 1), DI_ITEM_RELCENTER);
int nShade;
if (pPlayer.packSlots[nPack].isActive)
nShade = 4;
else
nShade = 24;
DrawStatNumber("%3d", pPlayer.packSlots[nPack].curAmount, "SBarPackAmount", x - 4, y - 13, nShade, 0);
x += texWidth(gPackIcons[nPack]) + 1;
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DrawPackItemInStatusBar(BloodPlayer pPlayer, int x, int y, int x2, int y2)
{
let id = pPlayer.packItemId;
//id = 0;
if (id < 0) return;
DrawImage(gPackIcons[id], (x, y), DI_ITEM_RELCENTER, style:STYLE_Normal);
DrawStatNumber("%3d", pPlayer.packSlots[id].curAmount, "SBarPackAmount", x2, y2, 0, 0);
}
void DrawPackItemInStatusBar2(BloodPlayer pPlayer, int x, int y, int x2, int y2, double nScale)
{
static const float packScale[] = { 0.5f, 0.3f, 0.6f, 0.5f, 0.4f };
static const int packYoffs[] = { 0, 0, 0, -4, 0 };
if (pPlayer.packItemId < 0) return;
let sc = packScale[pPlayer.packItemId];
DrawImage(packIcons2[pPlayer.packItemId], (x, y + packYoffs[pPlayer.packItemId]), DI_ITEM_RELCENTER, scale:(sc, sc), style:STYLE_Normal);
DrawStatNumber("%3d", pPlayer.packSlots[pPlayer.packItemId].curAmount, "SBarNumberInv", x2, y2, 0, 0, nScale);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawPlayerSlots(Array<BloodPlayer> players)
{
for (int nRows = (players.Size() - 1) / 4; nRows >= 0; nRows--)
{
for (int nCol = 0; nCol < 4; nCol++)
{
DrawImage("SBPlayerSlot", (-120 + nCol * 80, 4 + nRows * 9), DI_ITEM_RELCENTER|DI_SCREEN_CENTER_TOP, style:STYLE_Normal, col:0xffc0c0c0);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawPlayerFrags(Array<BloodPlayer> players)
{
drawPlayerSlots(players);
for (int i = 0; i < players.Size(); i++)
{
int x = -160 + 80 * (i & 3);
int y = 9 * (i / 4);
int col = players[i].teamId & 3;
int cr = col == 0? Font.CR_UNTRANSLATED : col == 1? Font.CR_BLUE : Font.CR_RED;
DrawString(tinyf, Raze.PlayerName(i), (x + 4, y), DI_SCREEN_CENTER_TOP, cr, 1., -1, -1);
String gTempStr = String.Format("%2d", players[i].fragCount);
DrawString(tinyf, gTempStr, (x + 76, y), DI_SCREEN_CENTER_TOP, cr, 1., -1, -1);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawPlayerFlags(Array<BloodPlayer> players)
{
String gTempStr;
drawPlayerSlots(players);
for (int i = 0; i < players.Size(); i++)
{
int x = -160 + 80 * (i & 3);
int y = 9 * (i / 4);
int col = players[i].teamId & 3;
gTempStr = String.Format("%s", Raze.PlayerName(i));
int cr = col == 0? Font.CR_UNTRANSLATED : col == 1? Font.CR_BLUE : Font.CR_RED;
DrawString(tinyf, gTempStr.MakeUpper(), (x + 4, y), DI_SCREEN_CENTER_TOP, cr, 1., -1, -1);
x += 76;
if (players[i].hasFlag & 2)
{
DrawString(tinyf, "F", (x, y), DI_SCREEN_CENTER_TOP, Font.CR_BLUE/*12*/, 1., -1, -1);
x -= 6;
}
if (players[i].hasFlag & 1)
DrawString(tinyf, "F", (x, y), DI_SCREEN_CENTER_TOP, Font.CR_RED/*11*/, 1., -1, -1);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawCtfHudVanilla(Array<BloodPlayer> players)
{
String gTempStr;
int x = 1, y = 1;
if (team_ticker[0] == 0 || (PlayClock & 8))
{
DrawString(smallf, "$TXT_COLOR_BLUE", (x, y), 0, Font.CR_LIGHTBLUE, 1., -1, -1);
gTempStr = String.Format("%-3d", team_score[0]);
DrawString(smallf, gTempStr, (x, y + 10), 0, Font.CR_LIGHTBLUE, 1., -1, -1);
}
x = -2;
if (team_ticker[1] == 0 || (PlayClock & 8))
{
DrawString(smallf, "$TXT_COLOR_RED", (x, y), DI_TEXT_ALIGN_RIGHT, Font.CR_BRICK, 1., -1, -1);
gTempStr = String.Format("%3d", team_score[1]);
DrawString(smallf, gTempStr, (x, y + 10), DI_TEXT_ALIGN_RIGHT, Font.CR_BRICK, 1., -1, -1);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void flashTeamScore(int team, bool show)
{
if (team_ticker[team] == 0 || (PlayClock & 8))
{
if (show)
DrawStatNumber("%d", team_score[team], "SBarNumberInv", -30, team ? 25 : -10, 0, team ? 2 : 10, 0.75, DI_SCREEN_RIGHT_CENTER);
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawCtfHud(BloodPlayer pPlayer, Array<BloodPlayer> players)
{
if (hud_size == Hud_Nothing)
{
flashTeamScore(0, false);
flashTeamScore(1, false);
return;
}
bool blueFlagTaken = false;
bool redFlagTaken = false;
int blueFlagCarrierColor = 0;
int redFlagCarrierColor = 0;
for (int i = 0; i < players.Size(); i++)
{
if ((players[i].hasFlag & 1) != 0)
{
blueFlagTaken = true;
blueFlagCarrierColor = players[i].teamId & 3;
}
if ((players[i].hasFlag & 2) != 0)
{
redFlagTaken = true;
redFlagCarrierColor = players[i].teamId & 3;
}
}
bool meHaveBlueFlag = pPlayer.hasFlag & 1;
int trans10 = Translation.MakeID(Translation_Remap, 10);
int trans2 = Translation.MakeID(Translation_Remap, 2);
DrawImage(meHaveBlueFlag ? "FlagHave" : "FlagHaveNot", (0, 75 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, scale:(0.35, 0.35), translation:trans10);
if (gBlueFlagDropped)
DrawImage("FlagDropped", (305 - 320, 83 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, translation:trans10);
else if (blueFlagTaken)
DrawImage("FlagTaken", (307 - 320, 77 - 100), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, translation:blueFlagCarrierColor ? trans2 : trans10);
flashTeamScore(0, true);
bool meHaveRedFlag = pPlayer.hasFlag & 2;
DrawImage(meHaveRedFlag ? "FlagHave" : "FlagHaveNot", (0, 10), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, scale:(0.35, 0.35), translation:trans2);
if (gRedFlagDropped)
DrawImage("FlagDropped", (305 - 320, 17), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, translation:trans2);
else if (redFlagTaken)
DrawImage("FlagTaken", (307 - 320, 11), DI_SCREEN_RIGHT_CENTER|DI_ITEM_RELCENTER, translation:redFlagCarrierColor ? trans2 : trans10);
flashTeamScore(1, true);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void drawMultiHUD(BloodPlayer pPlayer, int nGameType)
{
if (nGameType >= 1)
{
Array<BloodPlayer> players;
Blood.GetPlayers(players);
if (nGameType == 3)
{
if (hud_ctf_Vanilla)
{
drawCtfHudVanilla(players);
}
else
{
drawCtfHud(pPlayer, players);
drawPlayerFlags(players);
}
}
else
{
drawPlayerFrags(players);
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int DrawStatusBar(BloodPlayer pPlayer, int nPalette)
{
int th = texHeight("Statusbar");
BeginStatusBar(false, 320, 200, th);
int health = pPlayer.GetHealth();
DrawImage("Statusbar", (160, 200), DI_ITEM_CENTER_BOTTOM);
DrawPackItemInStatusBar(pPlayer, 265, 186, 260, 172);
if (health >= 16 || (PlayClock & 16) || health == 0)
{
DrawStatNumber("%3d", health >> 4, "SBarHealthAmount", 86, 183, 0, 0);
}
if (pPlayer.curWeapon && pPlayer.weaponAmmo != -1)
{
int num = pPlayer.ammoCount[pPlayer.weaponAmmo];
if (pPlayer.weaponAmmo == 6)
num /= 10;
DrawStatNumber("%3d", num, "SBarNumberAmmo", 216, 183, 0, 0);
}
for (int i = 9; i >= 1; i--)
{
int x = 135 + ((i - 1) / 3) * 23;
int y = 182 + ((i - 1) % 3) * 6;
int num = pPlayer.ammoCount[i];
if (i == 6)
num /= 10;
DrawStatNumber("%3d", num, "SBarAmmoAmount", x, y, i == pPlayer.weaponAmmo ? -128 : 32, 10);
}
DrawStatNumber("%2d", pPlayer.ammoCount[10], "SBarAmmoAmount", 291, 194, pPlayer.weaponAmmo == 10 ? -128 : 32, 10);
DrawStatNumber("%2d", pPlayer.ammoCount[11], "SBarAmmoAmount", 309, 194, pPlayer.weaponAmmo == 11 ? -128 : 32, 10);
if (pPlayer.armor[1])
{
TileHGauge("Armor1Gauge", 44, 174, pPlayer.armor[1], 3200);
DrawStatNumber("%3d", pPlayer.armor[1] >> 4, "SBarAmmoAmount", 50, 177, 0, 0);
}
if (pPlayer.armor[0])
{
TileHGauge("Armor3Gauge", 44, 182, pPlayer.armor[0], 3200);
DrawStatNumber("%3d", pPlayer.armor[0] >> 4, "SBarAmmoAmount", 50, 185, 0, 0);
}
if (pPlayer.armor[2])
{
TileHGauge("Armor2Gauge", 44, 190, pPlayer.armor[2], 3200);
DrawStatNumber("%3d", pPlayer.armor[2] >> 4, "SBarAmmoAmount", 50, 193, 0, 0);
}
for (int i = 0; i < 6; i++)
{
String nTile = String.Format("KEYICON%d", i + 1);
double x = 73.5 + (i & 1) * 173;
double y = 171.5 + (i >> 1) * 11;
if (pPlayer.hasKey[i + 1])
DrawImage(nTile, (x, y), DI_ITEM_RELCENTER, style:STYLE_Normal);
else
DrawImage(nTile, (x, y), DI_ITEM_RELCENTER, style:STYLE_Normal, col: 0xff606060, translation:Translation.MakeID(Translation_Remap, 5));
}
DrawImage("BlinkIcon", (118.5, 185.5), DI_ITEM_RELCENTER, col:Raze.shadeToLight(pPlayer.isRunning || cl_bloodvanillarun ? 16 : 40));
DrawImage("BlinkIcon", (201.5, 185.5), DI_ITEM_RELCENTER, col:Raze.shadeToLight(pPlayer.isRunning || cl_bloodvanillarun ? 16 : 40));
if (pPlayer.throwPower)
{
TileHGauge("ThrowGauge", 124, 175.5, pPlayer.throwPower, 1);
}
drawInventory(pPlayer, 166, 200 - th);
// Depending on the scale we can lower the stats display. This needs some tweaking but this catches the important default case already.
return (hud_statscale <= 0.501f || hud_scalefactor < 0.7) && screen.GetAspectRatio() > 1.6 ? 28 : 56;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int DrawHUD1(BloodPlayer pPlayer, int nPalette)
{
BeginHUD(1, false, 320, 200);
DrawImage("FullHUD", (34, 187 - 200), DI_ITEM_RELCENTER, style:STYLE_Normal, col:0xffc0c0c0, translation:nPalette);
int health = pPlayer.GetHealth();
if (health >= 16 || (PlayClock & 16) || health == 0)
{
DrawStatNumber("%3d", health >> 4, "SBarHealthAmount", 8, 183 - 200, 0, 0);
}
if (pPlayer.curWeapon && pPlayer.weaponAmmo != -1)
{
int num = pPlayer.ammoCount[pPlayer.weaponAmmo];
if (pPlayer.weaponAmmo == 6)
num /= 10;
DrawStatNumber("%3d", num, "SBarNumberAmmo", 42, 183 - 200, 0, 0);
}
DrawImage("ArmorBox", (284 - 320, 187 - 200), DI_ITEM_RELCENTER, style:STYLE_Normal, col:0xffc0c0c0, translation:nPalette);
if (pPlayer.armor[1])
{
TileHGauge("Armor1Gauge", 250 - 320, 175 - 200, pPlayer.armor[1], 3200);
DrawStatNumber("%3d", pPlayer.armor[1] >> 4, "SBarAmmoAmount", 255 - 320, 178 - 200, 0, 0);
}
if (pPlayer.armor[0])
{
TileHGauge("Armor3Gauge", 250 - 320, 183 - 200, pPlayer.armor[0], 3200);
DrawStatNumber("%3d", pPlayer.armor[0] >> 4, "SBarAmmoAmount", 255 - 320, 186 - 200, 0, 0);
}
if (pPlayer.armor[2])
{
TileHGauge("Armor2Gauge", 250 - 320, 191 - 200, pPlayer.armor[2], 3200);
DrawStatNumber("%3d", pPlayer.armor[2] >> 4, "SBarAmmoAmount", 255 - 320, 194 - 200, 0, 0);
}
DrawPackItemInStatusBar(pPlayer, 286 - 320, 186 - 200, 302 - 320, 183 - 200);
for (int i = 0; i < 6; i++)
{
String nTile = String.Format("KEYICON%d", i + 1);
int x;
int y = -6;
if (i & 1)
{
x = -(78 + (i >> 1) * 10);
}
else
{
x = 73 + (i >> 1) * 10;
}
if (pPlayer.hasKey[i + 1])
DrawImage(nTile, (x, y), DI_ITEM_RELCENTER, style:STYLE_Normal);
}
return 28;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int DrawHUD2(BloodPlayer pPlayer)
{
static const float ammoScale[] = { 0, 0.5f, 0.8f, 0.7f, 0.5f, 0.7f, 0.5f, 0.3f, 0.3f, 0.6f, 0.5f, 0.45f };
static const int ammoYoffs[] = { 0, 0, 0, 3, -6, 2, 4, -6, -6, -6, 2, 2 };
int health = pPlayer.GetHealth();
BeginHUD(1, false, 320, 200);
DrawImage("HealthIcon", (12, 195 - 200), 0, scale:(0.56, 0.56));
DrawStatNumber("%d", health >> 4, "SBarNumberHealth", 28, 187 - 200, 0, 0);
if (pPlayer.armor[1])
{
DrawImage("Armor1Icon", (70, 186 - 200), DI_ITEM_RELCENTER, scale:(0.5, 0.5));
DrawStatNumber("%3d", pPlayer.armor[1] >> 4, "SBarNumberArmor2_", 83, 187 - 200, 0, 0, 0.65);
}
if (pPlayer.armor[0])
{
DrawImage("Armor3Icon", (112, 195 - 200), DI_ITEM_RELCENTER, scale:(0.5, 0.5));
DrawStatNumber("%3d", pPlayer.armor[0] >> 4, "SBarNumberArmor1_", 125, 187 - 200, 0, 0, 0.65);
}
if (pPlayer.armor[2])
{
DrawImage("Armor2Icon", (155, 196 - 200), DI_ITEM_RELCENTER, scale:(0.5, 0.5));
DrawStatNumber("%3d", pPlayer.armor[2] >> 4, "SBarNumberArmor3_", 170, 187 - 200, 0, 0, 0.65);
}
DrawPackItemInStatusBar2(pPlayer, 216 - 320, 194 - 200, 231 - 320, 187 - 200, 0.7);
if (pPlayer.curWeapon && pPlayer.weaponAmmo != -1)
{
int num = pPlayer.ammoCount[pPlayer.weaponAmmo];
if (pPlayer.weaponAmmo == 6)
num /= 10;
if (gAmmoIcons[pPlayer.weaponAmmo])
{
let scale = ammoScale[pPlayer.weaponAmmo];
DrawImage(gAmmoIcons[pPlayer.weaponAmmo], (304 - 320, -8 + ammoYoffs[pPlayer.weaponAmmo]), DI_ITEM_RELCENTER, scale:(scale, scale));
}
bool reloadableWeapon = pPlayer.curWeapon == 3 && !pPlayer.powerupCheck(Blood.kPwUpTwoGuns);
if (!reloadableWeapon || (reloadableWeapon && !cl_showmagamt))
{
DrawStatNumber("%3d", num, "SBarNumberAmmo", 267 - 320, 187 - 200, 0, 0);
}
else
{
int clip = CalcMagazineAmount(num, 2, pPlayer.weaponState == 1);
int total = num - clip;
String format = String.Format("%d/%d", clip, num - clip);
DrawCharArray(format, "SBarNumberAmmo", (total < 10 ? 267 : 258) - 320, 187 - 200);
}
}
int k7 = pPlayer.hasKey[7]? -10 : 0;
for (int i = 0; i < 7; i++)
{
if (pPlayer.hasKey[i + 1])
{
let tile = String.Format("HUDKEYICON%d", i + 1);
DrawImage(tile, (-60 + 10 * i + k7, 170 - 200), DI_ITEM_RELCENTER, scale:(0.25, 0.25));
}
}
BeginStatusBar(false, 320, 200, 28);
if (pPlayer.throwPower)
TileHGauge("ThrowGauge", 124, 175, pPlayer.throwPower, 1);
else
drawInventory(pPlayer, 166, 200 - texHeight("FULLHUD") / 2 - 30);
return 28;
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
override void UpdateStatusBar(SummaryInfo summary)
{
int nPalette = 0;
let pPlayer = Blood.GetViewPlayer();
int y = 0;
int nGameType = Blood.getGameType();
if (nGameType == 3)
{
if (pPlayer.teamId & 1)
nPalette = 7;
else
nPalette = 10;
nPalette = Translation.MakeID(Translation_Remap, nPalette);
}
if (hud_size == Hud_Full)
{
y = DrawHUD2(pPlayer);
}
else if (hud_size > Hud_Stbar)
{
BeginStatusBar(false, 320, 200, 28);
if (pPlayer.throwPower)
TileHGauge("ThrowGauge", 124, 175, pPlayer.throwPower, 1);
else if (hud_size > Hud_StbarOverlay)
drawInventory(pPlayer, 166, 200 - texHeight("FullHUD") / 2);
}
if (hud_size == Hud_Mini)
{
y = DrawHUD1(pPlayer, nPalette);
}
else if (hud_size <= Hud_StbarOverlay)
{
y = DrawStatusBar(pPlayer, nPalette);
}
DoLevelStats(pPlayer, y, summary);
// All remaining parts must be done with HUD alignment rules, even when showing a status bar.
BeginHUD(1, false, 320, 200);
drawPowerUps(pPlayer);
drawMultiHUD(pPlayer, nGameType);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
override void GetAllStats(HudStats stats)
{
stats.Clear();
stats.info.fontscale = 1.0;
stats.info.screenbottomspace = 200;
stats.info.letterColor = TEXTCOLOR_DARKRED;
stats.info.standardColor = TEXTCOLOR_DARKGRAY;
stats.info.statfont = SmallFont;
stats.info.completeColor = TEXTCOLOR_DARKGREEN;
stats.info.spacing = SmallFont.GetHeight() + 2;
let pPlayer = Blood.GetViewPlayer();
stats.healthicon = "HealthIcon";
stats.healthvalue = pPlayer.GetHealth() >> 4;
if (pPlayer.armor[1])
{
stats.armoricons.Push("Armor1Icon");
stats.armorvalues.Push(pPlayer.armor[1] >> 4);
}
if (pPlayer.armor[0])
{
stats.armoricons.Push("Armor3Icon");
stats.armorvalues.Push(pPlayer.armor[0] >> 4);
}
if (pPlayer.armor[2])
{
stats.armoricons.Push("Armor2Icon");
stats.armorvalues.Push(pPlayer.armor[2] >> 4);
}
for (int i = 0; i < 7; i++)
{
if (pPlayer.hasKey[i + 1])
{
stats.keyicons.Push(String.Format("HUDKEYICON%d", i + 1));
}
}
for (int i = 0; i < 5; i++)
{
if (i == pPlayer.packItemId) stats.inventoryselect = stats.inventoryicons.Size();
stats.inventoryicons.Push(packIcons2[i]);
stats.inventoryamounts.Push(pPlayer.packSlots[i].curAmount);
}
// only show those weapons which are not their same ammo.
static const String weaponIcons[] = { "", "" /* pitchfork */, "#00524", "#00559", "#00558", "", "", "#00539", "#00800", "", "", "" };
for(int i = 0; i < 11; i++)
{
int weaponnum = i + 1;
if (pPlayer.hasweapon[weaponnum] && weaponIcons[weaponnum] != "")
{
if (pPlayer.curweapon == weaponnum)
{
stats.weaponselect = stats.weaponicons.Size();
}
stats.weaponicons.Push(weaponIcons[weaponnum]);
}
}
static const int ammoOrder[] = { 1, 2, 3, 4, 5, 10, 11, 6, 7, 8, 9 };
static const int maxammocount[] = { 0, 100, 100, 500, 100, 50, 288, 250, 100, 100, 50, 50 };
for(int i = 0; i < 11; i++)
{
int ammonum = ammoorder[i];
if (pPlayer.weaponammo == ammonum)
{
stats.ammoselect = stats.ammoicons.Size();
}
stats.ammoicons.Push(gAmmoIcons[ammonum]);
int num = pPlayer.ammoCount[ammonum];
if (ammonum == 6)
num /= 10;
stats.ammovalues.Push(num);
stats.ammomaxvalues.Push(maxammocount[ammonum]);
}
}
}