vkdoom_m/src/g_doom/doom_sbar.cpp
Christoph Oelckers 35ea94c014 May 18, 2008 (SBarInfo Update #20)
- Added: hasweaponpiece command to check for custom weapon pieces.
- Added: usessecondaryammo command to check if the current weapon has a second
  ammo type.
- Most of SBarInfo's mugshot scripting can be used with the default Doom status
  bar.
- Fixed: By default drawmugshot would never come out of normal god mode state.
  In addition the state change to and from god mode was not quite as responsive
  as the original code.

SVN r980 (trunk)
2008-05-18 15:48:03 +00:00

1069 lines
25 KiB
C++

#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_local.h"
#include "m_swap.h"
#include "a_keys.h"
#include "templates.h"
#include "i_system.h"
#include "r_translate.h"
#include "sbarinfo.h"
#define ST_EVILGRINCOUNT (2*TICRATE)
#define ST_STRAIGHTFACECOUNT (TICRATE/2)
#define ST_TURNCOUNT (1*TICRATE)
#define ST_OUCHCOUNT (1*TICRATE)
#define ST_RAMPAGEDELAY (2*TICRATE)
#define ST_MUCHPAIN 20
EXTERN_CVAR (Bool, vid_fps)
class DDoomStatusBar : public DBaseStatusBar
{
DECLARE_CLASS(DDoomStatusBar, DBaseStatusBar)
public:
DDoomStatusBar () : DBaseStatusBar (32)
{
static const char *sharedLumpNames[] =
{
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, "STTMINUS", "STTNUM0", "STTNUM1",
"STTNUM2", "STTNUM3", "STTNUM4", "STTNUM5", "STTNUM6",
"STTNUM7", "STTNUM8", "STTNUM9", "STYSNUM0", "STYSNUM1",
"STYSNUM2", "STYSNUM3", "STYSNUM4", "STYSNUM5", "STYSNUM6",
"STYSNUM7", "STYSNUM8", "STYSNUM9"
};
FTexture *tex;
DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES);
tex = DBaseStatusBar::Images[imgBNumbers];
BigWidth = tex->GetWidth();
BigHeight = tex->GetHeight();
DoCommonInit ();
bEvilGrin = false;
bDamageFaceActive = false;
CurrentState = NULL;
RampageTimer = 0;
LastDamageAngle = 1;
}
~DDoomStatusBar ()
{
}
void NewGame ()
{
Images.Uninit ();
DoCommonInit ();
if (CPlayer != NULL)
{
AttachToPlayer (CPlayer);
}
}
void AddFaceToImageCollection (void *skn, FImageCollection *images)
{
AddFaceToImageCollectionActual (skn, images, true);
}
void MultiplayerChanged ()
{
DBaseStatusBar::MultiplayerChanged ();
if (multiplayer)
{
// set face background color
StatusBarTex.SetPlayerRemap(translationtables[TRANSLATION_Players][int(CPlayer - players)]);
}
}
void AttachToPlayer (player_t *player)
{
player_t *oldplayer = CPlayer;
DBaseStatusBar::AttachToPlayer (player);
if (oldplayer != CPlayer || savegamerestore/*added for morphing*/)
{
SetFace (&skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin]);
}
if (multiplayer)
{
// set face background color
StatusBarTex.SetPlayerRemap(translationtables[TRANSLATION_Players][int(CPlayer - players)]);
}
bEvilGrin = false;
}
void Tick ()
{
DBaseStatusBar::Tick ();
RandomNumber = M_Random ();
//Do some stuff related to the mug shot that has to be done at 35fps
if(CurrentState != NULL)
{
CurrentState->tick();
if(CurrentState->finished)
CurrentState = NULL;
}
if((CPlayer->cmd.ucmd.buttons & (BT_ATTACK|BT_ALTATTACK)) && !(CPlayer->cheats & (CF_FROZEN | CF_TOTALLYFROZEN)))
{
if(RampageTimer != ST_RAMPAGEDELAY)
{
RampageTimer++;
}
}
else
{
RampageTimer = 0;
}
FaceHealth = CPlayer->health;
}
void Draw (EHudState state)
{
DBaseStatusBar::Draw (state);
if (state == HUD_Fullscreen)
{
SB_state = screen->GetPageCount ();
DrawFullScreenStuff ();
}
else if (state == HUD_StatusBar)
{
if (SB_state != 0)
{
SB_state--;
DrawImage (&StatusBarTex, 0, 0);
memset (OldArms, 255, sizeof(OldArms));
OldKeys = -1;
memset (OldAmmo, 255, sizeof(OldAmmo));
memset (OldMaxAmmo, 255, sizeof(OldMaxAmmo));
OldHealth = -1;
OldArmor = -1;
OldActiveAmmo = -1;
OldFrags = -9999;
FaceHealth = -9999;
}
DrawMainBar ();
if (CPlayer->inventorytics > 0 && !(level.flags & LEVEL_NOINVENTORYBAR))
{
DrawInventoryBar ();
SB_state = screen->GetPageCount ();
}
}
}
//See sbarinfo_display.cpp
void SetMugShotState (const char* stateName, bool waitTillDone=false)
{
MugShotState *state = (MugShotState *) FindMugShotState(stateName);
if(state != CurrentState)
{
if(!waitTillDone || CurrentState == NULL || CurrentState->finished)
{
CurrentState = state;
state->reset();
}
}
}
private:
struct FDoomStatusBarTexture : public FTexture
{
void DrawToBar (const char *name, int x, int y, const BYTE *colormap_in = NULL);
public:
FDoomStatusBarTexture ();
const BYTE *GetColumn (unsigned int column, const Span **spans_out);
const BYTE *GetPixels ();
void Unload ();
~FDoomStatusBarTexture ();
void SetPlayerRemap(FRemapTable *remap);
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf = NULL);
FTextureFormat GetFormat()
{
return TEX_RGB;
}
protected:
void MakeTexture ();
FTexture *BaseTexture;
BYTE *Pixels;
FRemapTable *STFBRemap;
}
StatusBarTex;
void DoCommonInit ()
{
static const char *doomLumpNames[] =
{
"STKEYS0", "STKEYS1", "STKEYS2", "STKEYS3", "STKEYS4",
"STKEYS5", "STKEYS6", "STKEYS7", "STKEYS8",
"STGNUM2", "STGNUM3", "STGNUM4", "STGNUM5", "STGNUM6",
"STGNUM7", "MEDIA0", "ARTIBOX", "SELECTBO", "INVGEML1",
"INVGEML2", "INVGEMR1", "INVGEMR2",
};
Images.Init (doomLumpNames, NUM_DOOMSB_IMAGES);
// In case somebody wants to use the Heretic status bar graphics...
{
FTexture *artibox = Images[imgARTIBOX];
FTexture *selectbox = Images[imgSELECTBOX];
if (artibox != NULL && selectbox != NULL)
{
selectbox->LeftOffset = artibox->LeftOffset;
selectbox->TopOffset = artibox->TopOffset;
}
}
StatusBarTex.Unload ();
SB_state = screen->GetPageCount ();
}
void DrawMainBar ()
{
int amount;
DrawAmmoStats ();
DrawFace ();
DrawKeys ();
if (!deathmatch)
{
DrawArms ();
}
else
{
if (OldFrags != CPlayer->fragcount)
{
OldFrags = CPlayer->fragcount;
FragsRefresh = screen->GetPageCount ();
}
if (FragsRefresh)
{
FragsRefresh--;
DrawNumber (OldFrags, 138/*110*/, 3, 2);
}
}
if (CPlayer->health != OldHealth)
{
OldHealth = CPlayer->health;
HealthRefresh = screen->GetPageCount ();
}
if (HealthRefresh)
{
HealthRefresh--;
DrawNumber (OldHealth, 90/*48*/, 3);
}
AInventory *armor = CPlayer->mo->FindInventory<ABasicArmor>();
int armorpoints = armor != NULL ? armor->Amount : 0;
if (armorpoints != OldArmor)
{
OldArmor = armorpoints;
ArmorRefresh = screen->GetPageCount ();
}
if (ArmorRefresh)
{
ArmorRefresh--;
DrawNumber (OldArmor, 221/*179*/, 3);
}
if (CPlayer->ReadyWeapon != NULL)
{
AAmmo *ammo = CPlayer->ReadyWeapon->Ammo1;
amount = ammo != NULL ? ammo->Amount : -9999;
}
else
{
amount = -9999;
}
if (amount != OldActiveAmmo)
{
OldActiveAmmo = amount;
ActiveAmmoRefresh = screen->GetPageCount ();
}
if (ActiveAmmoRefresh)
{
ActiveAmmoRefresh--;
if (OldActiveAmmo != -9999)
{
DrawNumber (OldActiveAmmo, 44/*2*/, 3);
}
else
{
DrawPartialImage (&StatusBarTex, 2, BigWidth*3);
}
}
}
void DrawArms ()
{
BYTE arms[6];
int i, j;
// Catalog the weapons the player owns
memset (arms, 0, sizeof(arms));
for (i = 0; i < 6; i++)
{
for (j = 0; j < MAX_WEAPONS_PER_SLOT; j++)
{
const PClass *weap = LocalWeapons.Slots[i+2].GetWeapon (j);
if (weap != NULL && CPlayer->mo->FindInventory (weap) != NULL)
{
arms[i] = 1;
break;
}
}
}
// Draw slots that have changed ownership since last time
for (i = 0; i < 6; i++)
{
if (arms[i] != OldArms[i])
{
ArmsRefresh[i%3] = screen->GetPageCount ();
}
}
// Remember the arms state for next time
memcpy (OldArms, arms, sizeof(arms));
for (i = 0; i < 3; i++)
{
if (ArmsRefresh[i])
{
ArmsRefresh[i]--;
int x = 111 + i * 12;
DrawArm (arms[i], i, x, 4, true);
DrawArm (arms[i+3], i+3, x, 14, false);
}
}
}
void DrawArm (int on, int picnum, int x, int y, bool drawBackground)
{
int w;
FTexture *pic = on ? DBaseStatusBar::Images[imgSmNumbers + 2 + picnum] : Images[imgGNUM2 + picnum];
if (pic != NULL)
{
w = pic->GetWidth();
x -= pic->LeftOffset;
y -= pic->TopOffset;
if (drawBackground)
{
DrawPartialImage (&StatusBarTex, x, w);
}
DrawImage (pic, x, y);
}
}
void DrawAmmoStats ()
{
static const ENamedName ammoTypes[4] =
{
NAME_Clip,
NAME_Shell,
NAME_RocketAmmo,
NAME_Cell
};
int ammo[4], maxammo[4];
int i;
// Catalog the player's ammo
for (i = 0; i < 4; i++)
{
const PClass *type = PClass::FindClass (ammoTypes[i]);
AInventory *item = CPlayer->mo->FindInventory (type);
if (item != NULL)
{
ammo[i] = item->Amount;
maxammo[i] = item->MaxAmount;
}
else
{
ammo[i] = 0;
maxammo[i] = ((AInventory *)GetDefaultByType (type))->MaxAmount;
}
}
// Draw ammo amounts that have changed since last time
for (i = 0; i < 4; i++)
{
if (ammo[i] != OldAmmo[i])
{
AmmoRefresh = screen->GetPageCount ();
}
if (maxammo[i] != OldMaxAmmo[i])
{
MaxAmmoRefresh = screen->GetPageCount ();
}
}
// Remember ammo counts for next time
memcpy (OldAmmo, ammo, sizeof(ammo));
memcpy (OldMaxAmmo, maxammo, sizeof(ammo));
if (AmmoRefresh)
{
AmmoRefresh--;
DrawPartialImage (&StatusBarTex, 276, 4*3);
for (i = 0; i < 4; i++)
{
DrSmallNumber (ammo[i], 276, 5 + 6*i);
}
}
if (MaxAmmoRefresh)
{
MaxAmmoRefresh--;
DrawPartialImage (&StatusBarTex, 302, 4*3);
for (i = 0; i < 4; i++)
{
DrSmallNumber (maxammo[i], 302, 5 + 6*i);
}
}
}
void DrawKeys ()
{
AInventory *item;
int keys;
// Catalog the player's current keys
keys = 0;
for (item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory)
{
if (item->IsKindOf (RUNTIME_CLASS(AKey)))
{
int keynum = static_cast<AKey*>(item)->KeyNumber;
if (keynum >= 1 && keynum <= 6)
{
keys |= 1 << (keynum-1);
}
}
}
// Remember keys for next time
if (OldKeys != keys)
{
OldKeys = keys;
KeysRefresh = screen->GetPageCount ();
}
// Draw keys that have changed since last time
if (KeysRefresh)
{
KeysRefresh--;
DrawPartialImage (&StatusBarTex, 239, 8);
// Blue Keys
switch (keys & (2|16))
{
case 2: DrawImage (Images[imgKEYS0], 239, 3); break;
case 16: DrawImage (Images[imgKEYS3], 239, 3); break;
case 18: DrawImage (Images[imgKEYS6], 239, 3); break;
}
// Yellow Keys
switch (keys & (4|32))
{
case 4: DrawImage (Images[imgKEYS1], 239, 13); break;
case 32: DrawImage (Images[imgKEYS4], 239, 13); break;
case 36: DrawImage (Images[imgKEYS7], 239, 13); break;
}
// Red Keys
switch (keys & (1|8))
{
case 1: DrawImage (Images[imgKEYS2], 239, 23); break;
case 8: DrawImage (Images[imgKEYS5], 239, 23); break;
case 9: DrawImage (Images[imgKEYS8], 239, 23); break;
}
}
}
//---------------------------------------------------------------------------
//
// PROC DrawInventoryBar
//
//---------------------------------------------------------------------------
void DrawInventoryBar ()
{
AInventory *item;
int i;
// If the player has no artifacts, don't draw the bar
CPlayer->mo->InvFirst = ValidateInvFirst (7);
if (CPlayer->mo->InvFirst != NULL)
{
for (item = CPlayer->mo->InvFirst, i = 0; item != NULL && i < 7; item = item->NextInv(), ++i)
{
DrawImage (Images[imgARTIBOX], 50+i*31, 2);
DrawDimImage (TexMan(item->Icon), 50+i*31, 2, item->Amount <= 0);
if (item->Amount != 1)
{
DrSmallNumber (item->Amount, 66+i*31, 24);
}
if (item == CPlayer->mo->InvSel)
{
DrawImage (Images[imgSELECTBOX], 50+i*31, 2);
}
}
for (; i < 7; ++i)
{
DrawImage (Images[imgARTIBOX], 50+i*31, 2);
}
// Is there something to the left?
if (CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
{
DrawImage (Images[!(gametic & 4) ?
imgINVLFGEM1 : imgINVLFGEM2], 38, 2);
}
// Is there something to the right?
if (item != NULL)
{
DrawImage (Images[!(gametic & 4) ?
imgINVRTGEM1 : imgINVRTGEM2], 269, 2);
}
}
}
void DrawNumber (int val, int x, int y, int size=3)
{
DrawPartialImage (&StatusBarTex, x-BigWidth*size, size*BigWidth);
DrBNumber (val, x, y, size);
}
void DrawFullScreenStuff ()
{
AInventory *item;
int i;
int ammotop;
// Draw health
screen->DrawTexture (Images[imgMEDI], 20, -2,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
TAG_DONE);
DrBNumberOuter (CPlayer->health, 40, -BigHeight-4);
// Draw armor
ABasicArmor *armor = CPlayer->mo->FindInventory<ABasicArmor>();
if (armor != NULL && armor->Amount != 0)
{
screen->DrawTexture (TexMan(armor->Icon), 20, -24,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
TAG_DONE);
DrBNumberOuter (armor->Amount, 40, -39);
}
// Draw ammo
AAmmo *ammo1, *ammo2;
int ammocount1, ammocount2;
GetCurrentAmmo (ammo1, ammo2, ammocount1, ammocount2);
ammotop = -1;
if (ammo1 != NULL)
{
FTexture *ammoIcon = TexMan(ammo1->Icon);
// Draw primary ammo in the bottom-right corner
screen->DrawTexture (ammoIcon, -14, -4,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
TAG_DONE);
DrBNumberOuter (ammo1->Amount, -67, -4 - BigHeight);
ammotop = -4 - BigHeight;
if (ammo2 != NULL && ammo2!=ammo1)
{
// Draw secondary ammo just above the primary ammo
int y = MIN (-6 - BigHeight, -6 - (ammoIcon != NULL ? ammoIcon->GetHeight() : 0));
screen->DrawTexture (TexMan(ammo2->Icon), -14, y,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
TAG_DONE);
DrBNumberOuter (ammo2->Amount, -67, y - BigHeight);
ammotop = y - BigHeight;
}
}
if (deathmatch)
{ // Draw frags (in DM)
DrBNumberOuter (CPlayer->fragcount, -44, 1);
}
else
{ // Draw keys (not DM)
int maxw = 0;
int count = 0;
int x = -2;
int y = vid_fps? 12 : 2;
for (item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory)
{
if (item->Icon > 0 && item->IsKindOf (RUNTIME_CLASS(AKey)))
{
FTexture *keypic = TexMan(item->Icon);
if (keypic != NULL)
{
int w = keypic->GetWidth ();
int h = keypic->GetHeight ();
if (w > maxw)
{
maxw = w;
}
screen->DrawTexture (keypic, x, y,
DTA_LeftOffset, w,
DTA_TopOffset, 0,
DTA_HUDRules, HUD_Normal,
TAG_DONE);
if (++count == 3)
{
count = 0;
y = vid_fps? 12 : 2;
x -= maxw + 2;
maxw = 0;
}
else
{
y += h + 2;
}
}
}
}
}
// Draw inventory
if (!(level.flags & LEVEL_NOINVENTORYBAR))
{
if (CPlayer->inventorytics == 0)
{
if (CPlayer->mo->InvSel != NULL)
{
screen->DrawTexture (TexMan(CPlayer->mo->InvSel->Icon), -14, ammotop - 1/*-24*/,
DTA_HUDRules, HUD_Normal,
DTA_CenterBottomOffset, true,
DTA_ColorOverlay, CPlayer->mo->InvSel->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
DrBNumberOuter (CPlayer->mo->InvSel->Amount, -68, ammotop - 18/*-41*/);
}
}
else
{
CPlayer->mo->InvFirst = ValidateInvFirst (7);
i = 0;
if (CPlayer->mo->InvFirst != NULL)
{
for (item = CPlayer->mo->InvFirst; item != NULL && i < 7; item = item->NextInv(), ++i)
{
screen->DrawTexture (Images[imgARTIBOX], -106+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_Alpha, HX_SHADOW,
TAG_DONE);
screen->DrawTexture (TexMan(item->Icon), -105+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_ColorOverlay, item->Amount > 0 ? 0 : DIM_OVERLAY,
TAG_DONE);
if (item->Amount != 1)
{
DrSmallNumberOuter (item->Amount, -90+i*31, -10, true);
}
if (item == CPlayer->mo->InvSel)
{
screen->DrawTexture (Images[imgSELECTBOX], -91+i*31, -2,
DTA_HUDRules, HUD_HorizCenter,
DTA_CenterBottomOffset, true,
TAG_DONE);
}
}
for (; i < 7; i++)
{
screen->DrawTexture (Images[imgARTIBOX], -106+i*31, -32,
DTA_HUDRules, HUD_HorizCenter,
DTA_Alpha, HX_SHADOW,
TAG_DONE);
}
// Is there something to the left?
if (CPlayer->mo->FirstInv() != CPlayer->mo->InvFirst)
{
screen->DrawTexture (Images[!(gametic & 4) ?
imgINVLFGEM1 : imgINVLFGEM2], -118, -33,
DTA_HUDRules, HUD_HorizCenter,
TAG_DONE);
}
// Is there something to the right?
if (item != NULL)
{
screen->DrawTexture (Images[!(gametic & 4) ?
imgINVRTGEM1 : imgINVRTGEM2], 113, -33,
DTA_HUDRules, HUD_HorizCenter,
TAG_DONE);
}
}
}
}
}
int CalcPainOffset ()
{
int health;
static int lastcalc;
static int oldhealth = -1;
health = CPlayer->health > 100 ? 100 : CPlayer->health;
if (health != oldhealth)
{
lastcalc = ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101);
oldhealth = health;
}
return lastcalc;
}
void ReceivedWeapon (AWeapon *weapon)
{
bEvilGrin = true;
}
int UpdateState ()
{
int i;
angle_t badguyangle;
angle_t diffang;
if(CPlayer->health > 0)
{
if(bEvilGrin)
{
if(CurrentState == NULL)
bEvilGrin = false;
else if(CPlayer->bonuscount)
{
SetMugShotState("grin", false);
return 0;
}
}
if (CPlayer->damagecount)
{
int damageAngle = 1;
if(CPlayer->attacker && CPlayer->attacker != CPlayer->mo)
{
if(CPlayer->mo != NULL)
{
//The next 12 lines is from the Doom statusbar code.
badguyangle = R_PointToAngle2(CPlayer->mo->x, CPlayer->mo->y, CPlayer->attacker->x, CPlayer->attacker->y);
if(badguyangle > CPlayer->mo->angle)
{
// whether right or left
diffang = badguyangle - CPlayer->mo->angle;
i = diffang > ANG180;
}
else
{
// whether left or right
diffang = CPlayer->mo->angle - badguyangle;
i = diffang <= ANG180;
} // confusing, aint it?
if(i && diffang >= ANG45)
{
damageAngle = 0;
}
else if(!i && diffang >= ANG45)
{
damageAngle = 2;
}
}
}
const char* stateName = new char[5];
if (FaceHealth != -1 && CPlayer->health - FaceHealth > 20)
stateName = "ouch";
else
stateName = "pain";
char* fullStateName = new char[sizeof(stateName)+sizeof((const char*) CPlayer->LastDamageType) + 1];
sprintf(fullStateName, "%s.%s", stateName, (const char*) CPlayer->LastDamageType);
if(FindMugShotState(fullStateName) != NULL)
SetMugShotState(fullStateName);
else
SetMugShotState(stateName);
bDamageFaceActive = !(CurrentState == NULL);
LastDamageAngle = damageAngle;
return damageAngle;
}
if(bDamageFaceActive)
{
if(CurrentState == NULL)
bDamageFaceActive = false;
else
{
const char* stateName = new char[5];
if (FaceHealth != -1 && CPlayer->health - FaceHealth > 20)
stateName = "ouch";
else
stateName = "pain";
char* fullStateName = new char[sizeof(stateName)+sizeof((const char*) CPlayer->LastDamageType) + 1];
sprintf(fullStateName, "%s.%s", stateName, (const char*) CPlayer->LastDamageType);
if(FindMugShotState(fullStateName) != NULL)
SetMugShotState(fullStateName);
else
SetMugShotState(stateName);
return LastDamageAngle;
}
}
if(RampageTimer == ST_RAMPAGEDELAY)
{
SetMugShotState("rampage", true);
return 0;
}
if(!bEvilGrin)
{
if((CPlayer->cheats & CF_GODMODE) || (CPlayer->mo != NULL && CPlayer->mo->flags2 & MF2_INVULNERABLE))
SetMugShotState("god");
else
SetMugShotState("normal");
}
}
else
{
const char* stateName = new char[7];
stateName = "death";
//new string the size of stateName and the damage type put together
char* fullStateName = new char[sizeof(stateName)+sizeof((const char*) CPlayer->LastDamageType) + 1];
sprintf(fullStateName, "%s.%s", stateName, (const char*) CPlayer->LastDamageType);
if(FindMugShotState(fullStateName) != NULL)
SetMugShotState(fullStateName);
else
SetMugShotState(stateName);
}
return 0;
}
void DrawFace ()
{
if (CPlayer->mo->InvSel == NULL || (level.flags & LEVEL_NOINVENTORYBAR))
{
int angle = UpdateState();
int level = 0;
for(level = 0;CPlayer->health < (4-level)*(CPlayer->mo->GetMaxHealth()/5);level++);
if(CurrentState != NULL)
{
FString defaultFace = "STF";
FPlayerSkin *skin = &skins[CPlayer->morphTics ? CPlayer->MorphedPlayerClass : CPlayer->userinfo.skin];
FTexture *face = CurrentState->getCurrentFrameTexture(defaultFace, skin, level, angle);
if (face != NULL)
{
DrawPartialImage (&StatusBarTex, 142, 37);
DrawImage (face, 143, 0);
}
}
}
else
{
DrawDimImage (TexMan(CPlayer->mo->InvSel->Icon), 144, 0, CPlayer->mo->InvSel->Amount <= 0);
if (CPlayer->mo->InvSel->Amount != 1)
{
DrSmallNumber (CPlayer->mo->InvSel->Amount, 165, 24);
}
}
}
enum
{
imgKEYS0,
imgKEYS1,
imgKEYS2,
imgKEYS3,
imgKEYS4,
imgKEYS5,
imgKEYS6,
imgKEYS7,
imgKEYS8,
imgGNUM2,
imgGNUM3,
imgGNUM4,
imgGNUM5,
imgGNUM6,
imgGNUM7,
imgMEDI,
imgARTIBOX,
imgSELECTBOX,
imgINVLFGEM1,
imgINVLFGEM2,
imgINVRTGEM1,
imgINVRTGEM2,
NUM_DOOMSB_IMAGES
};
FImageCollection Images;
int BigWidth;
int BigHeight;
int RandomNumber;
BYTE OldArms[6];
int OldKeys;
int OldAmmo[4];
int OldMaxAmmo[4];
int OldHealth;
int OldArmor;
int OldActiveAmmo;
int OldFrags;
char HealthRefresh;
char ArmorRefresh;
char ActiveAmmoRefresh;
char FragsRefresh;
char ArmsRefresh[3];
char AmmoRefresh;
char MaxAmmoRefresh;
char FaceRefresh;
char KeysRefresh;
//Mugshot
MugShotState *CurrentState;
int RampageTimer;
int LastDamageAngle;
int FaceHealth;
bool bEvilGrin;
bool bDamageFaceActive;
};
IMPLEMENT_CLASS(DDoomStatusBar)
DDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture ()
{
BaseTexture = TexMan["STBAR"];
if (BaseTexture==NULL)
{
I_Error("Fatal error: STBAR not found");
}
UseType = FTexture::TEX_MiscPatch;
Name[0]=0; // doesn't need a name
// now copy all the properties from the base texture
CopySize(BaseTexture);
Pixels = NULL;
STFBRemap = NULL;
}
const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out)
{
if (Pixels == NULL)
{
MakeTexture ();
}
BaseTexture->GetColumn(column, spans_out);
return Pixels + column*Height;
}
const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetPixels ()
{
if (Pixels == NULL)
{
MakeTexture ();
}
return Pixels;
}
void DDoomStatusBar::FDoomStatusBarTexture::Unload ()
{
if (Pixels != NULL)
{
delete[] Pixels;
Pixels = NULL;
}
}
DDoomStatusBar::FDoomStatusBarTexture::~FDoomStatusBarTexture ()
{
Unload ();
}
void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture ()
{
Pixels = new BYTE[Width*Height];
const BYTE *pix = BaseTexture->GetPixels();
memcpy(Pixels, pix, Width*Height);
if (!deathmatch) DrawToBar("STARMS", 104, 0, NULL);
DrawToBar("STTPRCNT", 90, 3, NULL);
DrawToBar("STTPRCNT", 221, 3, NULL);
if (multiplayer) DrawToBar("STFBANY", 143, 1, STFBRemap? STFBRemap->Remap : NULL);
}
int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf)
{
FTexture *tex;
// rotate and inf are never used here
BaseTexture->CopyTrueColorPixels(bmp, x, y);
if (!deathmatch)
{
tex = TexMan["STARMS"];
if (tex != NULL)
{
tex->CopyTrueColorPixels(bmp, x+104, y);
}
}
tex = TexMan["STTPRCNT"];
if (tex != NULL)
{
tex->CopyTrueColorPixels(bmp, x+90, y+3);
tex->CopyTrueColorPixels(bmp, x+221, y+3);
}
if (multiplayer)
{
tex = TexMan["STFBANY"];
if (tex != NULL)
{
tex->CopyTrueColorTranslated(bmp, x+143, y+1, 0, STFBRemap);
}
}
return -1;
}
void DDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, const BYTE *colormap)
{
FTexture *pic = TexMan[name];
if (pic != NULL)
{
x -= pic->LeftOffset;
pic->CopyToBlock (Pixels, Width, Height, x, y, colormap);
}
}
void DDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap)
{
Unload();
KillNative();
STFBRemap = remap;
}
DBaseStatusBar *CreateDoomStatusBar ()
{
return new DDoomStatusBar;
}