2008-12-25 22:00:00 +01:00
|
|
|
/***
|
|
|
|
*
|
|
|
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
|
|
|
*
|
|
|
|
* This product contains software technology licensed from Id
|
|
|
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use, distribution, and modification of this source code and/or resulting
|
|
|
|
* object code is restricted to non-commercial enhancements to products from
|
|
|
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
|
|
* without written permission from Valve LLC.
|
|
|
|
*
|
|
|
|
****/
|
|
|
|
//
|
|
|
|
// Ammo.cpp
|
|
|
|
//
|
|
|
|
// implementation of CHudAmmo class
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "extdll.h"
|
2009-01-22 22:00:00 +01:00
|
|
|
#include "utils.h"
|
2008-12-25 22:00:00 +01:00
|
|
|
#include "hud.h"
|
|
|
|
#include "hud_ammohistory.h"
|
2010-08-12 22:00:00 +02:00
|
|
|
#include "pm_shared.h"
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise
|
|
|
|
WEAPON *gpLastSel; // Last weapon menu selection
|
2010-07-08 22:00:00 +02:00
|
|
|
client_sprite_t *GetSpriteList( client_sprite_t *pList, const char *psz, int iRes, int iCount );
|
2008-12-25 22:00:00 +01:00
|
|
|
WeaponsResource gWR;
|
2009-12-05 22:00:00 +01:00
|
|
|
int g_weaponselect = 0;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
void WeaponsResource :: LoadAllWeaponSprites( void )
|
|
|
|
{
|
2009-01-01 22:00:00 +01:00
|
|
|
for( int i = 0; i < MAX_WEAPONS; i++ )
|
2008-12-25 22:00:00 +01:00
|
|
|
{
|
|
|
|
if ( rgWeapons[i].iId ) LoadWeaponSprites( &rgWeapons[i] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int WeaponsResource :: CountAmmo( int iId )
|
|
|
|
{
|
|
|
|
if ( iId < 0 )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return riAmmo[iId];
|
|
|
|
}
|
|
|
|
|
|
|
|
int WeaponsResource :: HasAmmo( WEAPON *p )
|
|
|
|
{
|
|
|
|
if( !p )
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
// weapons with no max ammo can always be selected
|
|
|
|
if( p->iMax1 == -1 )
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return (p->iAmmoType == -1) || p->iClip > 0 || CountAmmo(p->iAmmoType)
|
|
|
|
|| CountAmmo(p->iAmmo2Type) || ( p->iFlags & WEAPON_FLAGS_SELECTONEMPTY );
|
|
|
|
}
|
|
|
|
|
|
|
|
void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
int i, iRes;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
if (ActualWidth < 640)
|
|
|
|
iRes = 320;
|
|
|
|
else
|
|
|
|
iRes = 640;
|
|
|
|
|
|
|
|
char sz[128];
|
|
|
|
|
|
|
|
if ( !pWeapon )
|
|
|
|
return;
|
2009-01-01 22:00:00 +01:00
|
|
|
|
2008-12-25 22:00:00 +01:00
|
|
|
memset( &pWeapon->rcActive, 0, sizeof( wrect_t ));
|
|
|
|
memset( &pWeapon->rcInactive, 0, sizeof( wrect_t ));
|
|
|
|
memset( &pWeapon->rcAmmo, 0, sizeof( wrect_t ));
|
|
|
|
memset( &pWeapon->rcAmmo2, 0, sizeof( wrect_t ));
|
|
|
|
pWeapon->hInactive = 0;
|
|
|
|
pWeapon->hActive = 0;
|
|
|
|
pWeapon->hAmmo = 0;
|
|
|
|
pWeapon->hAmmo2 = 0;
|
2009-01-01 22:00:00 +01:00
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf( sz, "sprites/%s.txt", pWeapon->szName );
|
2009-01-01 22:00:00 +01:00
|
|
|
client_sprite_t *pList = SPR_GetList( sz, &i );
|
|
|
|
|
|
|
|
if( !pList ) return;
|
|
|
|
|
|
|
|
client_sprite_t *p;
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "crosshair", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hCrosshair = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcCrosshair = p->rc;
|
|
|
|
}
|
|
|
|
else pWeapon->hCrosshair = 0;
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "autoaim", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hAutoaim = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcAutoaim = p->rc;
|
|
|
|
}
|
|
|
|
else pWeapon->hAutoaim = 0;
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "zoom", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hZoomedCrosshair = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcZoomedCrosshair = p->rc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pWeapon->hZoomedCrosshair = pWeapon->hCrosshair; // default to non-zoomed crosshair
|
|
|
|
pWeapon->rcZoomedCrosshair = pWeapon->rcCrosshair;
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "zoom_autoaim", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hZoomedAutoaim = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcZoomedAutoaim = p->rc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pWeapon->hZoomedAutoaim = pWeapon->hZoomedCrosshair; // default to zoomed crosshair
|
|
|
|
pWeapon->rcZoomedAutoaim = pWeapon->rcZoomedCrosshair;
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "weapon", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hInactive = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcInactive = p->rc;
|
|
|
|
gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pWeapon->hInactive = gHUD.m_hHudError;
|
|
|
|
pWeapon->rcInactive = gHUD.GetSpriteRect( gHUD.m_HUD_error );
|
|
|
|
gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top );
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "weapon_s", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hActive = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcActive = p->rc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pWeapon->hActive = gHUD.m_hHudError;
|
|
|
|
pWeapon->rcActive = gHUD.GetSpriteRect( gHUD.m_HUD_error );
|
|
|
|
}
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "ammo", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hAmmo = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcAmmo = p->rc;
|
|
|
|
gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top );
|
|
|
|
}
|
|
|
|
else pWeapon->hAmmo = 0;
|
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
p = GetSpriteList( pList, "ammo2", iRes, i );
|
2009-01-01 22:00:00 +01:00
|
|
|
if( p )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
sprintf(sz, "sprites/%s.spr", p->szSprite);
|
|
|
|
pWeapon->hAmmo2 = SPR_Load(sz);
|
2009-01-01 22:00:00 +01:00
|
|
|
pWeapon->rcAmmo2 = p->rc;
|
|
|
|
gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top );
|
|
|
|
}
|
|
|
|
else pWeapon->hAmmo2 = 0;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
2010-07-08 22:00:00 +02:00
|
|
|
// in original Half-Life this was a leak
|
|
|
|
FREE( pList );
|
2008-12-25 22:00:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the first weapon for a given slot.
|
|
|
|
WEAPON *WeaponsResource :: GetFirstPos( int iSlot )
|
|
|
|
{
|
|
|
|
WEAPON *pret = NULL;
|
|
|
|
|
|
|
|
for (int i = 0; i < MAX_WEAPON_POSITIONS; i++)
|
|
|
|
{
|
|
|
|
if( rgSlots[iSlot][i] && HasAmmo( rgSlots[iSlot][i] ))
|
|
|
|
{
|
|
|
|
pret = rgSlots[iSlot][i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pret;
|
|
|
|
}
|
|
|
|
|
|
|
|
WEAPON* WeaponsResource :: GetNextActivePos( int iSlot, int iSlotPos )
|
|
|
|
{
|
|
|
|
if ( iSlotPos >= MAX_WEAPON_POSITIONS || iSlot >= MAX_WEAPON_SLOTS )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
WEAPON *p = gWR.rgSlots[ iSlot ][ iSlotPos+1 ];
|
|
|
|
|
|
|
|
if ( !p || !gWR.HasAmmo(p) )
|
|
|
|
return GetNextActivePos( iSlot, iSlotPos + 1 );
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
int giBucketHeight, giBucketWidth, giABHeight, giABWidth; // Ammo Bar width and height
|
|
|
|
|
|
|
|
HSPRITE ghsprBuckets; // Sprite for top row of weapons menu
|
|
|
|
|
|
|
|
DECLARE_MESSAGE( m_Ammo, CurWeapon ); // Current weapon and clip
|
|
|
|
DECLARE_MESSAGE( m_Ammo, WeaponList ); // new weapon type
|
|
|
|
DECLARE_MESSAGE( m_Ammo, AmmoX ); // update known ammo type's count
|
|
|
|
DECLARE_MESSAGE( m_Ammo, AmmoPickup ); // flashes an ammo pickup record
|
|
|
|
DECLARE_MESSAGE( m_Ammo, WeapPickup ); // flashes a weapon pickup record
|
|
|
|
DECLARE_MESSAGE( m_Ammo, HideWeapon ); // hides the weapon, ammo, and crosshair displays temporarily
|
|
|
|
DECLARE_MESSAGE( m_Ammo, ItemPickup );
|
|
|
|
DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoVal );
|
|
|
|
DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoIcon );
|
|
|
|
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot1 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot2 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot3 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot4 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot5 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot6 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot7 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot8 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot9 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Slot10 );
|
|
|
|
DECLARE_COMMAND( m_Ammo, Close );
|
|
|
|
DECLARE_COMMAND( m_Ammo, NextWeapon );
|
|
|
|
DECLARE_COMMAND( m_Ammo, PrevWeapon );
|
|
|
|
|
|
|
|
// width of ammo fonts
|
|
|
|
#define AMMO_SMALL_WIDTH 10
|
|
|
|
#define AMMO_LARGE_WIDTH 20
|
|
|
|
|
|
|
|
#define HISTORY_DRAW_TIME "5"
|
|
|
|
|
|
|
|
int CHudAmmo::Init( void )
|
|
|
|
{
|
|
|
|
gHUD.AddHudElem(this);
|
|
|
|
|
|
|
|
HOOK_MESSAGE( CurWeapon );
|
|
|
|
HOOK_MESSAGE( WeaponList );
|
|
|
|
HOOK_MESSAGE( AmmoPickup );
|
|
|
|
HOOK_MESSAGE( WeapPickup );
|
|
|
|
HOOK_MESSAGE( ItemPickup );
|
|
|
|
HOOK_MESSAGE( HideWeapon );
|
|
|
|
HOOK_MESSAGE( AmmoX );
|
|
|
|
|
|
|
|
HOOK_COMMAND( "slot1", Slot1 );
|
|
|
|
HOOK_COMMAND( "slot2", Slot2 );
|
|
|
|
HOOK_COMMAND( "slot3", Slot3 );
|
|
|
|
HOOK_COMMAND( "slot4", Slot4 );
|
|
|
|
HOOK_COMMAND( "slot5", Slot5 );
|
|
|
|
HOOK_COMMAND( "slot6", Slot6 );
|
|
|
|
HOOK_COMMAND( "slot7", Slot7 );
|
|
|
|
HOOK_COMMAND( "slot8", Slot8 );
|
|
|
|
HOOK_COMMAND( "slot9", Slot9 );
|
|
|
|
HOOK_COMMAND( "slot10", Slot10 );
|
|
|
|
HOOK_COMMAND( "cancelselect", Close );
|
|
|
|
HOOK_COMMAND( "invnext", NextWeapon );
|
|
|
|
HOOK_COMMAND( "invprev", PrevWeapon );
|
|
|
|
|
|
|
|
Reset();
|
|
|
|
|
|
|
|
CVAR_REGISTER( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0, "weapons pickup history show time" );
|
2009-01-22 22:00:00 +01:00
|
|
|
CVAR_REGISTER( "hud_fastswitch", "0", FCVAR_ARCHIVE, "controls whether or not weapons can be selected in one keypress" );
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
m_iFlags |= HUD_ACTIVE; //!!!
|
|
|
|
|
|
|
|
gWR.Init();
|
|
|
|
gHR.Init();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo :: Reset( void )
|
|
|
|
{
|
|
|
|
m_fFade = 0;
|
|
|
|
m_iFlags |= HUD_ACTIVE; //!!!
|
|
|
|
|
|
|
|
gpActiveSel = NULL;
|
2009-01-17 22:00:00 +01:00
|
|
|
|
2009-02-01 22:00:00 +01:00
|
|
|
gHUD.m_iHideHUDDisplay = 0;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
gWR.Reset();
|
|
|
|
gHR.Reset();
|
|
|
|
|
|
|
|
static wrect_t nullrc;
|
|
|
|
SetCrosshair( 0, nullrc, 0, 0, 0 ); // reset crosshair
|
|
|
|
m_pWeapon = NULL;// reset last weapon
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmo :: VidInit( void )
|
|
|
|
{
|
|
|
|
// Load sprites for buckets (top row of weapon menu)
|
|
|
|
m_HUD_bucket0 = gHUD.GetSpriteIndex( "bucket1" );
|
|
|
|
m_HUD_selection = gHUD.GetSpriteIndex( "selection" );
|
|
|
|
|
|
|
|
ghsprBuckets = gHUD.GetSprite(m_HUD_bucket0);
|
|
|
|
giBucketWidth = gHUD.GetSpriteRect(m_HUD_bucket0).right - gHUD.GetSpriteRect(m_HUD_bucket0).left;
|
|
|
|
giBucketHeight = gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top;
|
|
|
|
|
|
|
|
gHR.iHistoryGap = max( gHR.iHistoryGap, gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top);
|
|
|
|
|
|
|
|
// If we've already loaded weapons, let's get new sprites
|
|
|
|
gWR.LoadAllWeaponSprites();
|
|
|
|
|
|
|
|
giABWidth = 20;
|
|
|
|
giABHeight = 4;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Think:
|
|
|
|
// Used for selection of weapon menu item.
|
|
|
|
//
|
|
|
|
void CHudAmmo :: Think( void )
|
|
|
|
{
|
|
|
|
if( gHUD.m_fPlayerDead )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( gHUD.m_iWeaponBits != gWR.iOldWeaponBits )
|
|
|
|
{
|
|
|
|
gWR.iOldWeaponBits = gHUD.m_iWeaponBits;
|
|
|
|
|
|
|
|
for (int i = MAX_WEAPONS-1; i > 0; i-- )
|
|
|
|
{
|
|
|
|
WEAPON *p = gWR.GetWeapon(i);
|
|
|
|
|
|
|
|
if( p )
|
|
|
|
{
|
|
|
|
if( gHUD.m_iWeaponBits & ( 1 << p->iId ))
|
|
|
|
gWR.PickupWeapon( p );
|
|
|
|
else gWR.DropWeapon( p );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-19 22:00:00 +02:00
|
|
|
if( Q_rint( gHUD.m_flFOV ) != gWR.iOldFOV )
|
|
|
|
{
|
|
|
|
if( m_pWeapon )
|
|
|
|
{
|
|
|
|
// update crosshairs
|
|
|
|
if( gHUD.m_flFOV >= 90 )
|
|
|
|
{
|
|
|
|
// normal crosshairs
|
|
|
|
if( m_pWeapon->iOnTarget && m_pWeapon->hAutoaim )
|
|
|
|
SetCrosshair(m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255 );
|
|
|
|
else SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
|
|
|
|
}
|
|
|
|
else
|
2009-12-05 22:00:00 +01:00
|
|
|
{
|
|
|
|
// zoomed crosshairs
|
2009-09-19 22:00:00 +02:00
|
|
|
if( m_pWeapon->iOnTarget && m_pWeapon->hZoomedAutoaim )
|
|
|
|
SetCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255 );
|
|
|
|
else SetCrosshair( m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gWR.iOldFOV = gHUD.m_flFOV;
|
|
|
|
}
|
|
|
|
|
2008-12-25 22:00:00 +01:00
|
|
|
if( !gpActiveSel ) return;
|
|
|
|
|
|
|
|
// has the player selected one?
|
|
|
|
if( gHUD.m_iKeyBits & IN_ATTACK )
|
|
|
|
{
|
|
|
|
if( gpActiveSel != (WEAPON *)1 )
|
2009-12-05 22:00:00 +01:00
|
|
|
{
|
2008-12-25 22:00:00 +01:00
|
|
|
SERVER_COMMAND( gpActiveSel->szName );
|
2009-12-05 22:00:00 +01:00
|
|
|
g_weaponselect = gpActiveSel->iId;
|
|
|
|
}
|
2008-12-25 22:00:00 +01:00
|
|
|
gpLastSel = gpActiveSel;
|
|
|
|
gpActiveSel = NULL;
|
|
|
|
gHUD.m_iKeyBits &= ~IN_ATTACK;
|
|
|
|
|
|
|
|
CL_PlaySound( "common/wpn_select.wav", 1.0f );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Helper function to return a Ammo pointer from id
|
|
|
|
//
|
|
|
|
HSPRITE* WeaponsResource :: GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect )
|
|
|
|
{
|
|
|
|
for ( int i = 0; i < MAX_WEAPONS; i++ )
|
|
|
|
{
|
|
|
|
if ( rgWeapons[i].iAmmoType == iAmmoId )
|
|
|
|
{
|
|
|
|
rect = rgWeapons[i].rcAmmo;
|
|
|
|
return &rgWeapons[i].hAmmo;
|
|
|
|
}
|
|
|
|
else if ( rgWeapons[i].iAmmo2Type == iAmmoId )
|
|
|
|
{
|
|
|
|
rect = rgWeapons[i].rcAmmo2;
|
|
|
|
return &rgWeapons[i].hAmmo2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Menu Selection Code
|
|
|
|
void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection )
|
|
|
|
{
|
|
|
|
if( gHUD.m_Menu.m_fMenuDisplayed && (fAdvance == FALSE) && (iDirection == 1) )
|
|
|
|
{
|
|
|
|
// menu is overriding slot use commands
|
|
|
|
gHUD.m_Menu.SelectMenuItem( iSlot + 1 ); // slots are one off the key numbers
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( iSlot > MAX_WEAPON_SLOTS )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( gHUD.m_fPlayerDead || gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS|HIDEHUD_ALL ))
|
|
|
|
return;
|
|
|
|
|
2010-08-15 22:00:00 +02:00
|
|
|
if(!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT))))
|
2008-12-25 22:00:00 +01:00
|
|
|
return;
|
|
|
|
|
2010-08-15 22:00:00 +02:00
|
|
|
if(!(gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT))))
|
2009-02-01 22:00:00 +01:00
|
|
|
return;
|
2009-01-05 22:00:00 +01:00
|
|
|
|
2008-12-25 22:00:00 +01:00
|
|
|
WEAPON *p = NULL;
|
|
|
|
bool fastSwitch = CVAR_GET_FLOAT( "hud_fastswitch" ) != 0;
|
|
|
|
|
|
|
|
if((gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot))
|
|
|
|
{
|
|
|
|
CL_PlaySound( "common/wpn_hudon.wav", 1.0f );
|
|
|
|
p = GetFirstPos( iSlot );
|
|
|
|
|
|
|
|
if( p && fastSwitch ) // check for fast weapon switch mode
|
|
|
|
{
|
|
|
|
// if fast weapon switch is on, then weapons can be selected in a single keypress
|
|
|
|
// but only if there is only one item in the bucket
|
|
|
|
WEAPON *p2 = GetNextActivePos( p->iSlot, p->iSlotPos );
|
|
|
|
if( !p2 )
|
2009-12-05 22:00:00 +01:00
|
|
|
{
|
|
|
|
// only one active item in bucket, so change directly to weapon
|
2008-12-25 22:00:00 +01:00
|
|
|
SERVER_COMMAND( p->szName );
|
2009-12-05 22:00:00 +01:00
|
|
|
g_weaponselect = p->iId;
|
2008-12-25 22:00:00 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CL_PlaySound( "common/wpn_moveselect.wav", 1.0f );
|
|
|
|
if( gpActiveSel )
|
|
|
|
p = GetNextActivePos( gpActiveSel->iSlot, gpActiveSel->iSlotPos );
|
|
|
|
if( !p ) p = GetFirstPos( iSlot );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( !p ) // no selection found
|
|
|
|
{
|
|
|
|
// just display the weapon list, unless fastswitch is on just ignore it
|
|
|
|
if( !fastSwitch )
|
|
|
|
gpActiveSel = (WEAPON *)1;
|
|
|
|
else gpActiveSel = NULL;
|
|
|
|
}
|
|
|
|
else gpActiveSel = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Message Handlers
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
// AmmoX -- Update the count of a known type of ammo
|
|
|
|
//
|
|
|
|
int CHudAmmo::MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf)
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
|
|
|
|
int iIndex = READ_BYTE();
|
|
|
|
int iCount = READ_BYTE();
|
|
|
|
|
|
|
|
gWR.SetAmmo( iIndex, abs(iCount) );
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmo::MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
int iIndex = READ_BYTE();
|
|
|
|
int iCount = READ_BYTE();
|
|
|
|
|
|
|
|
// Add ammo to the history
|
|
|
|
gHR.AddToHistory( HISTSLOT_AMMO, iIndex, abs(iCount) );
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmo::MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
int iIndex = READ_BYTE();
|
|
|
|
|
|
|
|
// Add the weapon to the history
|
|
|
|
gHR.AddToHistory( HISTSLOT_WEAP, iIndex );
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmo::MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
const char *szName = READ_STRING();
|
|
|
|
|
|
|
|
// Add the weapon to the history
|
|
|
|
gHR.AddToHistory( HISTSLOT_ITEM, szName );
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
|
|
|
|
gHUD.m_iHideHUDDisplay = READ_BYTE();
|
|
|
|
|
2009-12-05 22:00:00 +01:00
|
|
|
if ( IsSpectateOnly())
|
|
|
|
return 1;
|
|
|
|
|
2008-12-25 22:00:00 +01:00
|
|
|
if((m_pWeapon == NULL) || (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )))
|
|
|
|
{
|
|
|
|
static wrect_t nullrc;
|
|
|
|
gpActiveSel = NULL;
|
|
|
|
SetCrosshair( 0, nullrc, 0, 0, 0 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
|
|
|
|
}
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// CurWeapon: Update hud state with the current weapon and clip count. Ammo
|
|
|
|
// counts are updated with AmmoX. Server assures that the Weapon ammo type
|
|
|
|
// numbers match a real ammo type.
|
|
|
|
//
|
|
|
|
int CHudAmmo::MsgFunc_CurWeapon( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
static wrect_t nullrc;
|
|
|
|
int fOnTarget = FALSE;
|
|
|
|
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
|
|
|
|
int iState = READ_BYTE();
|
|
|
|
int iId = READ_CHAR();
|
|
|
|
int iClip = READ_CHAR();
|
|
|
|
|
|
|
|
// detect if we're also on target
|
|
|
|
if( iState > 1 )
|
|
|
|
{
|
|
|
|
fOnTarget = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( iId < 1 )
|
|
|
|
{
|
|
|
|
SetCrosshair(0, nullrc, 0, 0, 0);
|
|
|
|
m_pWeapon = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is player dead???
|
|
|
|
if((iId == -1) && (iClip == -1))
|
|
|
|
{
|
|
|
|
gHUD.m_fPlayerDead = TRUE;
|
|
|
|
gpActiveSel = NULL;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gHUD.m_fPlayerDead = FALSE;
|
|
|
|
WEAPON *pWeapon = gWR.GetWeapon( iId );
|
|
|
|
|
|
|
|
if( !pWeapon )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( iClip < -1 )
|
|
|
|
pWeapon->iClip = abs( iClip );
|
|
|
|
else pWeapon->iClip = iClip;
|
|
|
|
|
|
|
|
|
|
|
|
if( iState == 0 ) // we're not the current weapon, so update no more
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
m_pWeapon = pWeapon;
|
2009-09-19 22:00:00 +02:00
|
|
|
m_pWeapon->iOnTarget = fOnTarget;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
2009-09-19 22:00:00 +02:00
|
|
|
// update crosshairs
|
2009-01-04 22:00:00 +01:00
|
|
|
if( gHUD.m_flFOV >= 90 )
|
2008-12-25 22:00:00 +01:00
|
|
|
{
|
|
|
|
// normal crosshairs
|
2009-09-19 22:00:00 +02:00
|
|
|
if( m_pWeapon->iOnTarget && m_pWeapon->hAutoaim )
|
2008-12-25 22:00:00 +01:00
|
|
|
SetCrosshair(m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255 );
|
|
|
|
else SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // zoomed crosshairs
|
2009-09-19 22:00:00 +02:00
|
|
|
if( m_pWeapon->iOnTarget && m_pWeapon->hZoomedAutoaim )
|
2008-12-25 22:00:00 +01:00
|
|
|
SetCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255 );
|
|
|
|
else SetCrosshair( m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255 );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fFade = 200.0f; //!!!
|
|
|
|
m_iFlags |= HUD_ACTIVE;
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// WeaponList -- Tells the hud about a new weapon type.
|
|
|
|
//
|
|
|
|
int CHudAmmo::MsgFunc_WeaponList( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
|
|
|
|
WEAPON Weapon;
|
|
|
|
|
|
|
|
strcpy( Weapon.szName, READ_STRING() );
|
|
|
|
Weapon.iAmmoType = (int)READ_CHAR();
|
|
|
|
|
|
|
|
Weapon.iMax1 = READ_BYTE();
|
|
|
|
if( Weapon.iMax1 == 255 )
|
|
|
|
Weapon.iMax1 = -1;
|
|
|
|
|
|
|
|
Weapon.iAmmo2Type = READ_CHAR();
|
|
|
|
Weapon.iMax2 = READ_BYTE();
|
|
|
|
if( Weapon.iMax2 == 255 )
|
|
|
|
Weapon.iMax2 = -1;
|
|
|
|
|
|
|
|
Weapon.iSlot = READ_CHAR();
|
|
|
|
Weapon.iSlotPos = READ_CHAR();
|
|
|
|
Weapon.iId = READ_CHAR();
|
|
|
|
Weapon.iFlags = READ_BYTE();
|
|
|
|
Weapon.iClip = 0;
|
|
|
|
|
|
|
|
gWR.AddWeapon( &Weapon );
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Command Handlers
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Slot button pressed
|
|
|
|
void CHudAmmo::SlotInput( int iSlot )
|
|
|
|
{
|
|
|
|
gWR.SelectSlot( iSlot, FALSE, 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot1( void )
|
|
|
|
{
|
|
|
|
SlotInput( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot2( void )
|
|
|
|
{
|
|
|
|
SlotInput( 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot3( void )
|
|
|
|
{
|
|
|
|
SlotInput( 2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot4( void )
|
|
|
|
{
|
|
|
|
SlotInput( 3 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot5( void )
|
|
|
|
{
|
|
|
|
SlotInput( 4 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot6( void )
|
|
|
|
{
|
|
|
|
SlotInput( 5 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot7( void )
|
|
|
|
{
|
|
|
|
SlotInput( 6 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot8( void )
|
|
|
|
{
|
|
|
|
SlotInput( 7 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot9( void )
|
|
|
|
{
|
|
|
|
SlotInput( 8 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Slot10( void )
|
|
|
|
{
|
|
|
|
SlotInput( 9 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmo::UserCmd_Close( void )
|
|
|
|
{
|
|
|
|
if( gpActiveSel )
|
|
|
|
{
|
|
|
|
gpLastSel = gpActiveSel;
|
|
|
|
gpActiveSel = NULL;
|
|
|
|
CL_PlaySound( "common/wpn_hudoff.wav", 1.0f );
|
|
|
|
}
|
2010-02-02 22:00:00 +01:00
|
|
|
else CLIENT_COMMAND( "escape\n" );
|
2008-12-25 22:00:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Selects the next item in the weapon menu
|
|
|
|
void CHudAmmo::UserCmd_NextWeapon( void )
|
|
|
|
{
|
|
|
|
if( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS|HIDEHUD_ALL)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( !gpActiveSel || gpActiveSel == (WEAPON*)1 )
|
|
|
|
gpActiveSel = m_pWeapon;
|
|
|
|
|
|
|
|
int pos = 0;
|
|
|
|
int slot = 0;
|
|
|
|
if( gpActiveSel )
|
|
|
|
{
|
|
|
|
pos = gpActiveSel->iSlotPos + 1;
|
|
|
|
slot = gpActiveSel->iSlot;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int loop = 0; loop <= 1; loop++ )
|
|
|
|
{
|
|
|
|
for( ; slot < MAX_WEAPON_SLOTS; slot++ )
|
|
|
|
{
|
|
|
|
for( ; pos < MAX_WEAPON_POSITIONS; pos++ )
|
|
|
|
{
|
|
|
|
WEAPON *wsp = gWR.GetWeaponSlot( slot, pos );
|
|
|
|
|
|
|
|
if( wsp && gWR.HasAmmo( wsp ))
|
|
|
|
{
|
|
|
|
gpActiveSel = wsp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = 0;
|
|
|
|
}
|
|
|
|
slot = 0; // start looking from the first slot again
|
|
|
|
}
|
|
|
|
gpActiveSel = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Selects the previous item in the menu
|
|
|
|
void CHudAmmo :: UserCmd_PrevWeapon( void )
|
|
|
|
{
|
2009-10-16 22:00:00 +02:00
|
|
|
if( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS|HIDEHUD_ALL)))
|
2008-12-25 22:00:00 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
if( !gpActiveSel || gpActiveSel == (WEAPON*)1 )
|
|
|
|
gpActiveSel = m_pWeapon;
|
|
|
|
|
|
|
|
int pos = MAX_WEAPON_POSITIONS-1;
|
|
|
|
int slot = MAX_WEAPON_SLOTS-1;
|
|
|
|
if( gpActiveSel )
|
|
|
|
{
|
|
|
|
pos = gpActiveSel->iSlotPos - 1;
|
|
|
|
slot = gpActiveSel->iSlot;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( int loop = 0; loop <= 1; loop++ )
|
|
|
|
{
|
|
|
|
for( ; slot >= 0; slot-- )
|
|
|
|
{
|
|
|
|
for( ; pos >= 0; pos-- )
|
|
|
|
{
|
|
|
|
WEAPON *wsp = gWR.GetWeaponSlot( slot, pos );
|
|
|
|
|
|
|
|
if( wsp && gWR.HasAmmo( wsp ))
|
|
|
|
{
|
|
|
|
gpActiveSel = wsp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = MAX_WEAPON_POSITIONS-1;
|
|
|
|
}
|
|
|
|
slot = MAX_WEAPON_SLOTS-1;
|
|
|
|
}
|
|
|
|
gpActiveSel = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Drawing code
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int CHudAmmo::Draw( float flTime )
|
|
|
|
{
|
|
|
|
int a, x, y, r, g, b;
|
|
|
|
int AmmoWidth;
|
|
|
|
|
2010-08-15 22:00:00 +02:00
|
|
|
if(!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT))))
|
2008-12-25 22:00:00 +01:00
|
|
|
return 1;
|
|
|
|
|
2009-02-01 22:00:00 +01:00
|
|
|
if((gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS|HIDEHUD_ALL)))
|
2008-12-25 22:00:00 +01:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
// Draw Weapon Menu
|
|
|
|
DrawWList( flTime );
|
|
|
|
|
|
|
|
// Draw ammo pickup history
|
|
|
|
gHR.DrawAmmoHistory( flTime );
|
|
|
|
|
|
|
|
if(!( m_iFlags & HUD_ACTIVE ))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if( !m_pWeapon )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
WEAPON *pw = m_pWeapon; // shorthand
|
|
|
|
|
|
|
|
// SPR_Draw Ammo
|
|
|
|
if((pw->iAmmoType < 0) && (pw->iAmmo2Type < 0))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
int iFlags = DHN_DRAWZERO; // draw 0 values
|
|
|
|
|
|
|
|
AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
|
|
|
|
|
|
|
|
a = (int) max( MIN_ALPHA, m_fFade );
|
|
|
|
|
|
|
|
if( m_fFade > 0 )
|
|
|
|
m_fFade -= (gHUD.m_flTimeDelta * 20);
|
|
|
|
|
|
|
|
UnpackRGB( r,g,b, gHUD.m_iHUDColor );
|
|
|
|
|
|
|
|
ScaleColors(r, g, b, a );
|
|
|
|
|
|
|
|
// Does this weapon have a clip?
|
2008-12-29 22:00:00 +01:00
|
|
|
y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
// Does weapon have any ammo at all?
|
|
|
|
if( m_pWeapon->iAmmoType > 0 )
|
|
|
|
{
|
|
|
|
int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left;
|
|
|
|
|
|
|
|
if( pw->iClip >= 0 )
|
|
|
|
{
|
|
|
|
// room for the number and the '|' and the current ammo
|
|
|
|
|
2008-12-29 22:00:00 +01:00
|
|
|
x = ScreenWidth - (8 * AmmoWidth) - iIconWidth;
|
2008-12-25 22:00:00 +01:00
|
|
|
x = gHUD.DrawHudNumber(x, y, iFlags|DHN_3DIGITS, pw->iClip, r, g, b );
|
|
|
|
|
|
|
|
wrect_t rc;
|
|
|
|
rc.top = 0;
|
|
|
|
rc.left = 0;
|
|
|
|
rc.right = AmmoWidth;
|
|
|
|
rc.bottom = 100;
|
|
|
|
|
|
|
|
int iBarWidth = AmmoWidth/10;
|
|
|
|
|
|
|
|
x += AmmoWidth/2;
|
|
|
|
|
|
|
|
UnpackRGB(r,g,b, gHUD.m_iHUDColor);
|
|
|
|
|
|
|
|
// draw the | bar
|
|
|
|
FillRGBA( x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a );
|
|
|
|
|
|
|
|
x += iBarWidth + AmmoWidth / 2;
|
|
|
|
|
|
|
|
// GL Seems to need this
|
|
|
|
ScaleColors( r, g, b, a );
|
|
|
|
x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// SPR_Draw a bullets only line
|
2008-12-29 22:00:00 +01:00
|
|
|
x = ScreenWidth - 4 * AmmoWidth - iIconWidth;
|
2008-12-25 22:00:00 +01:00
|
|
|
x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw the ammo Icon
|
|
|
|
int iOffset = (m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top) / 8;
|
|
|
|
SPR_Set( m_pWeapon->hAmmo, r, g, b );
|
|
|
|
SPR_DrawAdditive( 0, x, y - iOffset, &m_pWeapon->rcAmmo );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Does weapon have secondary ammo?
|
|
|
|
if( pw->iAmmo2Type > 0 )
|
|
|
|
{
|
|
|
|
int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left;
|
|
|
|
|
|
|
|
// Do we have secondary ammo?
|
|
|
|
if((pw->iAmmo2Type != 0) && (gWR.CountAmmo(pw->iAmmo2Type) > 0))
|
|
|
|
{
|
|
|
|
y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight/4;
|
2008-12-29 22:00:00 +01:00
|
|
|
x = ScreenWidth - 4 * AmmoWidth - iIconWidth;
|
2008-12-25 22:00:00 +01:00
|
|
|
x = gHUD.DrawHudNumber(x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo(pw->iAmmo2Type), r, g, b);
|
|
|
|
|
|
|
|
// Draw the ammo Icon
|
|
|
|
SPR_Set(m_pWeapon->hAmmo2, r, g, b);
|
|
|
|
int iOffset = (m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top)/8;
|
|
|
|
SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Draws the ammo bar on the hud
|
|
|
|
//
|
|
|
|
int DrawBar( int x, int y, int width, int height, float f )
|
|
|
|
{
|
|
|
|
int r, g, b;
|
|
|
|
|
|
|
|
if( f < 0 ) f = 0;
|
|
|
|
if( f > 1 ) f = 1;
|
|
|
|
|
|
|
|
if( f )
|
|
|
|
{
|
|
|
|
int w = f * width;
|
|
|
|
|
|
|
|
// Always show at least one pixel if we have ammo.
|
|
|
|
if( w <= 0 ) w = 1;
|
|
|
|
UnpackRGB( r, g, b, RGB_GREENISH );
|
|
|
|
FillRGBA( x, y, w, height, r, g, b, 255 );
|
|
|
|
x += w;
|
|
|
|
width -= w;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnpackRGB( r, g, b, gHUD.m_iHUDColor );
|
|
|
|
|
|
|
|
FillRGBA( x, y, width, height, r, g, b, 128 );
|
|
|
|
return (x + width);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DrawAmmoBar( WEAPON *p, int x, int y, int width, int height )
|
|
|
|
{
|
|
|
|
if( !p ) return;
|
|
|
|
|
|
|
|
if( p->iAmmoType != -1 )
|
|
|
|
{
|
|
|
|
if( !gWR.CountAmmo( p->iAmmoType ))
|
|
|
|
return;
|
|
|
|
|
|
|
|
float f = (float)gWR.CountAmmo(p->iAmmoType)/(float)p->iMax1;
|
|
|
|
|
|
|
|
x = DrawBar(x, y, width, height, f);
|
|
|
|
|
|
|
|
// Do we have secondary ammo too?
|
|
|
|
if( p->iAmmo2Type != -1 )
|
|
|
|
{
|
|
|
|
f = (float)gWR.CountAmmo(p->iAmmo2Type) / (float)p->iMax2;
|
|
|
|
|
|
|
|
x += 5; //!!!
|
|
|
|
DrawBar( x, y, width, height, f );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Draw Weapon Menu
|
|
|
|
//
|
|
|
|
int CHudAmmo::DrawWList( float flTime )
|
|
|
|
{
|
|
|
|
int r,g,b,x,y,a,i;
|
|
|
|
|
|
|
|
if( !gpActiveSel )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int iActiveSlot;
|
|
|
|
|
|
|
|
if( gpActiveSel == (WEAPON *)1 )
|
|
|
|
iActiveSlot = -1; // current slot has no weapons
|
|
|
|
else iActiveSlot = gpActiveSel->iSlot;
|
|
|
|
|
|
|
|
x = 10; //!!!
|
|
|
|
y = 10; //!!!
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure that there are available choices in the active slot
|
|
|
|
if( iActiveSlot > 0 )
|
|
|
|
{
|
|
|
|
if( !gWR.GetFirstPos( iActiveSlot ) )
|
|
|
|
{
|
|
|
|
gpActiveSel = (WEAPON *)1;
|
|
|
|
iActiveSlot = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw top line
|
|
|
|
for( i = 0; i < MAX_WEAPON_SLOTS; i++ )
|
|
|
|
{
|
|
|
|
int iWidth;
|
|
|
|
|
|
|
|
UnpackRGB( r,g,b, gHUD.m_iHUDColor );
|
|
|
|
|
|
|
|
if( iActiveSlot == i )
|
|
|
|
a = 255;
|
|
|
|
else a = 192; // not used ???
|
|
|
|
|
|
|
|
ScaleColors( r, g, b, 255 );
|
2008-12-28 22:00:00 +01:00
|
|
|
SPR_Set( gHUD.GetSprite( m_HUD_bucket0 + i ), r, g, b );
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
// make active slot wide enough to accomodate gun pictures
|
|
|
|
if( i == iActiveSlot )
|
|
|
|
{
|
|
|
|
WEAPON *p = gWR.GetFirstPos(iActiveSlot);
|
|
|
|
if ( p )
|
|
|
|
iWidth = p->rcActive.right - p->rcActive.left;
|
|
|
|
else iWidth = giBucketWidth;
|
|
|
|
}
|
|
|
|
else iWidth = giBucketWidth;
|
|
|
|
|
2008-12-28 22:00:00 +01:00
|
|
|
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i));
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
x += iWidth + 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
a = 128; //!!!
|
|
|
|
x = 10;
|
|
|
|
|
|
|
|
// Draw all of the buckets
|
|
|
|
for( i = 0; i < MAX_WEAPON_SLOTS; i++ )
|
|
|
|
{
|
|
|
|
y = giBucketHeight + 10;
|
|
|
|
|
|
|
|
// If this is the active slot, draw the bigger pictures,
|
|
|
|
// otherwise just draw boxes
|
|
|
|
if( i == iActiveSlot )
|
|
|
|
{
|
|
|
|
WEAPON *p = gWR.GetFirstPos( i );
|
|
|
|
int iWidth = giBucketWidth;
|
|
|
|
if( p ) iWidth = p->rcActive.right - p->rcActive.left;
|
|
|
|
|
|
|
|
for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
|
|
|
|
{
|
|
|
|
p = gWR.GetWeaponSlot( i, iPos );
|
|
|
|
|
|
|
|
if( !p || !p->iId )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
UnpackRGB( r, g, b, gHUD.m_iHUDColor );
|
|
|
|
|
|
|
|
// if active, then we must have ammo.
|
|
|
|
if( gpActiveSel == p )
|
|
|
|
{
|
|
|
|
SPR_Set( p->hActive, r, g, b );
|
|
|
|
SPR_DrawAdditive( 0, x, y, &p->rcActive );
|
|
|
|
|
|
|
|
SPR_Set( gHUD.GetSprite(m_HUD_selection), r, g, b );
|
|
|
|
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect( m_HUD_selection ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Draw Weapon if Red if no ammo
|
|
|
|
|
|
|
|
if( gWR.HasAmmo( p ))
|
|
|
|
ScaleColors( r, g, b, 192 );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UnpackRGB( r, g, b, RGB_REDISH );
|
|
|
|
ScaleColors( r, g, b, 128 );
|
|
|
|
}
|
|
|
|
|
|
|
|
SPR_Set( p->hInactive, r, g, b );
|
|
|
|
SPR_DrawAdditive( 0, x, y, &p->rcInactive );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw Ammo Bar
|
|
|
|
DrawAmmoBar( p, x + giABWidth/2, y, giABWidth, giABHeight );
|
|
|
|
y += p->rcActive.bottom - p->rcActive.top + 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
x += iWidth + 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Draw Row of weapons.
|
|
|
|
UnpackRGB( r, g, b, gHUD.m_iHUDColor );
|
|
|
|
|
|
|
|
for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
|
|
|
|
{
|
|
|
|
WEAPON *p = gWR.GetWeaponSlot( i, iPos );
|
|
|
|
|
|
|
|
if( !p || !p->iId )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if( gWR.HasAmmo(p) )
|
|
|
|
{
|
|
|
|
UnpackRGB( r, g, b, gHUD.m_iHUDColor );
|
|
|
|
a = 128;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UnpackRGB( r, g, b, RGB_REDISH );
|
|
|
|
a = 96;
|
|
|
|
}
|
|
|
|
|
|
|
|
FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a );
|
|
|
|
y += giBucketHeight + 5;
|
|
|
|
}
|
|
|
|
x += giBucketWidth + 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmoSecondary :: Init( void )
|
|
|
|
{
|
|
|
|
HOOK_MESSAGE( SecAmmoVal );
|
|
|
|
HOOK_MESSAGE( SecAmmoIcon );
|
|
|
|
|
|
|
|
gHUD.AddHudElem( this );
|
|
|
|
m_HUD_ammoicon = 0;
|
|
|
|
|
|
|
|
for( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ )
|
|
|
|
m_iAmmoAmounts[i] = -1; // -1 means don't draw this value
|
|
|
|
Reset();
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHudAmmoSecondary :: Reset( void )
|
|
|
|
{
|
|
|
|
m_fFade = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmoSecondary :: VidInit( void )
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHudAmmoSecondary :: Draw( float flTime )
|
|
|
|
{
|
|
|
|
if(( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
// draw secondary ammo icons above normal ammo readout
|
|
|
|
int a, x, y, r, g, b, AmmoWidth;
|
|
|
|
UnpackRGB( r, g, b, gHUD.m_iHUDColor );
|
|
|
|
a = (int) max( MIN_ALPHA, m_fFade );
|
|
|
|
if( m_fFade > 0 )
|
|
|
|
m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons
|
|
|
|
ScaleColors( r, g, b, a );
|
|
|
|
|
|
|
|
AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left;
|
|
|
|
|
2008-12-29 22:00:00 +01:00
|
|
|
y = ScreenHeight - (gHUD.m_iFontHeight*4); // this is one font height higher than the weapon ammo values
|
|
|
|
x = ScreenWidth - AmmoWidth;
|
2008-12-25 22:00:00 +01:00
|
|
|
|
|
|
|
if( m_HUD_ammoicon )
|
|
|
|
{
|
|
|
|
// Draw the ammo icon
|
|
|
|
x -= (gHUD.GetSpriteRect(m_HUD_ammoicon).right - gHUD.GetSpriteRect(m_HUD_ammoicon).left);
|
|
|
|
y -= (gHUD.GetSpriteRect(m_HUD_ammoicon).top - gHUD.GetSpriteRect(m_HUD_ammoicon).bottom);
|
|
|
|
|
|
|
|
SPR_Set( gHUD.GetSprite(m_HUD_ammoicon), r, g, b );
|
|
|
|
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_ammoicon) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// move the cursor by the '0' char instead, since we don't have an icon to work with
|
|
|
|
x -= AmmoWidth;
|
|
|
|
y -= (gHUD.GetSpriteRect(gHUD.m_HUD_number_0).top - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw the ammo counts, in reverse order, from right to left
|
|
|
|
for( int i = MAX_SEC_AMMO_VALUES-1; i >= 0; i-- )
|
|
|
|
{
|
|
|
|
if( m_iAmmoAmounts[i] < 0 )
|
|
|
|
continue; // negative ammo amounts imply that they shouldn't be drawn
|
|
|
|
|
|
|
|
// half a char gap between the ammo number and the previous pic
|
|
|
|
x -= (AmmoWidth / 2);
|
|
|
|
|
|
|
|
// draw the number, right-aligned
|
|
|
|
x -= (gHUD.GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth);
|
|
|
|
gHUD.DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b );
|
|
|
|
|
|
|
|
if ( i != 0 )
|
|
|
|
{
|
|
|
|
// draw the divider bar
|
|
|
|
x -= (AmmoWidth / 2);
|
|
|
|
FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Message handler for Secondary Ammo Value
|
|
|
|
// accepts one value:
|
|
|
|
// string: sprite name
|
|
|
|
int CHudAmmoSecondary :: MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
|
|
|
|
m_HUD_ammoicon = gHUD.GetSpriteIndex( READ_STRING() );
|
|
|
|
|
|
|
|
END_READ();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Message handler for Secondary Ammo Icon
|
|
|
|
// Sets an ammo value
|
|
|
|
// takes two values:
|
|
|
|
// byte: ammo index
|
|
|
|
// byte: ammo value
|
|
|
|
int CHudAmmoSecondary :: MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf )
|
|
|
|
{
|
|
|
|
BEGIN_READ( pszName, iSize, pbuf );
|
|
|
|
|
|
|
|
int index = READ_BYTE();
|
|
|
|
if( index < 0 || index >= MAX_SEC_AMMO_VALUES )
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
m_iAmmoAmounts[index] = READ_BYTE();
|
|
|
|
m_iFlags |= HUD_ACTIVE;
|
|
|
|
|
|
|
|
// check to see if there is anything left to draw
|
|
|
|
int count = 0;
|
|
|
|
for( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ )
|
|
|
|
{
|
|
|
|
count += max( 0, m_iAmmoAmounts[i] );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( count == 0 )
|
|
|
|
{
|
|
|
|
// the ammo fields are all empty, so turn off this hud area
|
|
|
|
m_iFlags &= ~HUD_ACTIVE;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make the icons light up
|
|
|
|
m_fFade = 200.0f;
|
|
|
|
END_READ();
|
|
|
|
|
|
|
|
return 1;
|
2009-01-01 22:00:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================================
|
|
|
|
GetSpriteList
|
|
|
|
|
|
|
|
Finds and returns the matching
|
|
|
|
sprite name 'psz' in the given sprite list 'pList'
|
|
|
|
iCount is the number of items in the pList
|
|
|
|
=================================
|
|
|
|
*/
|
2010-07-08 22:00:00 +02:00
|
|
|
client_sprite_t *GetSpriteList( client_sprite_t *pList, const char *psz, int iRes, int iCount )
|
2009-01-01 22:00:00 +01:00
|
|
|
{
|
|
|
|
if( !pList ) return NULL;
|
|
|
|
|
|
|
|
int i = iCount;
|
|
|
|
client_sprite_t *p = pList;
|
|
|
|
|
|
|
|
while( i-- )
|
|
|
|
{
|
2010-07-08 22:00:00 +02:00
|
|
|
if ((!strcmp(psz, p->szName)) && (p->iRes == iRes))
|
2009-01-01 22:00:00 +01:00
|
|
|
return p;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
return NULL;
|
2008-12-25 22:00:00 +01:00
|
|
|
}
|