mirror of
https://github.com/unknownworlds/NS.git
synced 2024-12-22 10:21:16 +00:00
88f1ac3034
o cvar cl_customcrosshair 0|1|2|3, default 0, any other value forces default o Option added to advanced options o Multiple resolutions supported, if an xhair isn't available for the configured resolution, the next lowest available sprite is used. o Fully backwards compatible with 3.1 crosshair files. git-svn-id: https://unknownworlds.svn.cloudforge.com/ns1@409 67975925-1194-0748-b3d5-c16f83f1a3a1
1494 lines
36 KiB
C++
1494 lines
36 KiB
C++
/***
|
|
*
|
|
* Copyright (c) 1999, 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 "hud.h"
|
|
#include "cl_util.h"
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ammohistory.h"
|
|
#include "vgui_TeamFortressViewport.h"
|
|
#include "mod/AvHClientVariables.h"
|
|
#include "mod/AvHSharedUtil.h"
|
|
#include "mod/AvHScrollHandler.h"
|
|
#include "mod/AvHNetworkMessages.h"
|
|
|
|
WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise
|
|
// this points to the active weapon menu item
|
|
WEAPON *gpLastSel; // Last weapon menu selection
|
|
|
|
bool HUD_GetWeaponEnabled(int inID);
|
|
client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
|
|
|
|
WeaponsResource gWR;
|
|
|
|
int g_weaponselect = 0;
|
|
|
|
void IN_AttackDownForced(void);
|
|
void IN_AttackUpForced(void);
|
|
void IN_Attack2Down(void);
|
|
void IN_Attack2Up(void);
|
|
void IN_ReloadDown();
|
|
void IN_ReloadUp();
|
|
bool CheckInAttack(void);
|
|
|
|
//Equivalent to DECLARE_COMMAND(lastinv,LastInv) except we use gWR instead of gHud
|
|
void __CmdFunc_LastInv(void)
|
|
{ gWR.UserCmd_LastInv(); }
|
|
|
|
// +movement
|
|
void __CmdFunc_MovementOn(void)
|
|
{ gWR.UserCmd_MovementOn(); }
|
|
void __CmdFunc_MovementOff(void)
|
|
{ gWR.UserCmd_MovementOff(); }
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
WeaponsResource::WeaponsResource(void) : lastWeapon(NULL), iOldWeaponBits(0) {}
|
|
WeaponsResource::~WeaponsResource(void) {}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::Init( void )
|
|
{
|
|
memset( rgWeapons, 0, sizeof(WEAPON)*MAX_WEAPONS );
|
|
Reset();
|
|
HOOK_COMMAND("lastinv", LastInv);
|
|
// +movement
|
|
HOOK_COMMAND("+movement", MovementOn);
|
|
HOOK_COMMAND("-movement", MovementOff);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::Reset( void )
|
|
{
|
|
lastWeapon = NULL;
|
|
iOldWeaponBits = 0;
|
|
memset( rgSlots, 0, sizeof(WEAPON*)*MAX_WEAPON_SLOTS*MAX_WEAPON_POSITIONS );
|
|
memset( riAmmo, 0, sizeof(int)*MAX_AMMO_TYPES );
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource :: LoadAllWeaponSprites( void )
|
|
{
|
|
for (int i = 0; i < MAX_WEAPONS; i++)
|
|
{
|
|
if ( rgWeapons[i].iId )
|
|
LoadWeaponSprites( &rgWeapons[i] );
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
inline void LoadWeaponSprite( client_sprite_t* ptr, HSPRITE& sprite, wrect_t& bounds )
|
|
{
|
|
if( ptr )
|
|
{
|
|
string name( "sprites/" );
|
|
name.append( ptr->szSprite );
|
|
name.append( ".spr" );
|
|
sprite = Safe_SPR_Load(name.c_str());
|
|
bounds = ptr->rc;
|
|
}
|
|
else
|
|
{
|
|
sprite = NULL;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon )
|
|
{
|
|
int resolutions[5] = { 320, 640, 800, 1024, 1280 };
|
|
const int numRes=5;
|
|
int i=0, j=0, iRes=320;
|
|
int screenWidth=ScreenWidth();
|
|
|
|
for ( j=0; j < numRes; j++ ) {
|
|
if ( screenWidth == resolutions[j] ) {
|
|
iRes=resolutions[j];
|
|
break;
|
|
}
|
|
if ( i > 0 && screenWidth > resolutions[j-1] && screenWidth < resolutions[j] ) {
|
|
iRes=resolutions[j-1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
char sz[128];
|
|
|
|
if ( !pWeapon )
|
|
return;
|
|
|
|
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;
|
|
|
|
sprintf(sz, "sprites/%s.txt", pWeapon->szName);
|
|
client_sprite_t *pList = SPR_GetList(sz, &i);
|
|
|
|
if (!pList)
|
|
{
|
|
ASSERT(pList);
|
|
return;
|
|
}
|
|
|
|
for ( j=numRes-1; j>=0; j-- ) {
|
|
if ( resolutions[j] <= iRes ) {
|
|
if( pWeapon->hCrosshair == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "crosshair", resolutions[j], i ), pWeapon->hCrosshair, pWeapon->rcCrosshair );
|
|
|
|
if( pWeapon->hCrosshair1 == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "crosshair_1", resolutions[j], i ), pWeapon->hCrosshair1, pWeapon->rcCrosshair1 );
|
|
|
|
if( pWeapon->hCrosshair2 == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "crosshair_2", resolutions[j], i ), pWeapon->hCrosshair2, pWeapon->rcCrosshair2 );
|
|
|
|
if( pWeapon->hCrosshair3 == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "crosshair_3", resolutions[j], i ), pWeapon->hCrosshair3, pWeapon->rcCrosshair3 );
|
|
|
|
if( pWeapon->hInactive == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "weapon", resolutions[j], i ), pWeapon->hInactive, pWeapon->rcInactive );
|
|
|
|
if( pWeapon->hActive == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "weapon_s", resolutions[j], i ), pWeapon->hActive, pWeapon->rcActive );
|
|
|
|
if( pWeapon->hAmmo == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "ammo", resolutions[j], i ), pWeapon->hAmmo, pWeapon->rcAmmo );
|
|
|
|
if( pWeapon->hAmmo2 == NULL )
|
|
LoadWeaponSprite( GetSpriteList( pList, "ammo2", resolutions[j], i ), pWeapon->hAmmo2, pWeapon->rcAmmo2 );
|
|
}
|
|
}
|
|
|
|
if( pWeapon->hCrosshair1 == NULL ) //default
|
|
{
|
|
pWeapon->hCrosshair1 = pWeapon->hCrosshair;
|
|
pWeapon->rcCrosshair1 = pWeapon->rcCrosshair;
|
|
}
|
|
|
|
if( pWeapon->hCrosshair2 == NULL ) //default
|
|
{
|
|
pWeapon->hCrosshair2 = pWeapon->hCrosshair;
|
|
pWeapon->rcCrosshair2 = pWeapon->rcCrosshair;
|
|
}
|
|
|
|
if( pWeapon->hCrosshair3 == NULL ) //default
|
|
{
|
|
pWeapon->hCrosshair3 = pWeapon->hCrosshair;
|
|
pWeapon->rcCrosshair3 = pWeapon->rcCrosshair;
|
|
}
|
|
|
|
if( pWeapon->hActive || pWeapon->hInactive || pWeapon->hAmmo || pWeapon->hAmmo2 )
|
|
{ gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); }
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
WEAPON* WeaponsResource::GetWeapon( int iId )
|
|
{
|
|
if( iId < 0 || iId >= MAX_WEAPONS ) { return NULL; }
|
|
return rgWeapons[iId].iId ? &rgWeapons[iId] : NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
WEAPON* WeaponsResource::GetWeaponSlot( int slot, int pos ) { return rgSlots[slot][pos]; }
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
WEAPON* WeaponsResource::GetFirstPos( int iSlot )
|
|
{
|
|
WEAPON *returnVal = NULL;
|
|
ASSERT( iSlot < MAX_WEAPON_SLOTS && iSlot >= 0 );
|
|
|
|
for( int counter = 0; counter < MAX_WEAPON_POSITIONS; ++counter )
|
|
{
|
|
if( this->IsSelectable(rgSlots[iSlot][counter]) )
|
|
{
|
|
returnVal = rgSlots[iSlot][counter];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return returnVal;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
WEAPON* WeaponsResource::GetNextActivePos( int iSlot, int iSlotPos )
|
|
{
|
|
WEAPON* returnVal = NULL;
|
|
ASSERT( iSlot < MAX_WEAPON_SLOTS && iSlot >= 0 );
|
|
ASSERT( iSlotPos >= 0 );
|
|
|
|
for( int counter = iSlotPos+1; counter < MAX_WEAPON_POSITIONS; ++counter )
|
|
{
|
|
if( this->IsSelectable(rgSlots[iSlot][counter]) )
|
|
{
|
|
returnVal = rgSlots[iSlot][counter];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return returnVal;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
bool WeaponsResource::IsEnabled(WEAPON* p)
|
|
{
|
|
if( p == NULL ) { return false; }
|
|
return HUD_GetWeaponEnabled(p->iId) && this->HasAmmo(p);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
bool WeaponsResource::IsSelectable(WEAPON* p)
|
|
{
|
|
if( p == NULL ) { return false; }
|
|
return HUD_GetWeaponEnabled(p->iId);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
bool WeaponsResource::HasAmmo( WEAPON* p )
|
|
{
|
|
if( p == NULL) { return false; }
|
|
//note : if max ammo capacity is -1, this has always returned true in spite of not
|
|
// having actual ammo -- KGP
|
|
return (p->iAmmoType == -1) || (p->iMax1 == -1) || p->iClip > 0 || CountAmmo(p->iAmmoType)
|
|
|| CountAmmo(p->iAmmo2Type) || (p->iFlags & WEAPON_FLAGS_SELECTIONEMPTY );
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
int WeaponsResource::CountAmmo( int iId )
|
|
{
|
|
ASSERT( iId < MAX_AMMO_TYPES );
|
|
if( iId < 0 ) return 0;
|
|
return riAmmo[iId];
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
int WeaponsResource::GetAmmo( int iId )
|
|
{
|
|
ASSERT( iId < MAX_AMMO_TYPES && iId > -1 );
|
|
return riAmmo[iId];
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::SetAmmo( int iId, int iCount )
|
|
{
|
|
ASSERT( iId < MAX_AMMO_TYPES && iId > -1 );
|
|
riAmmo[iId] = iCount;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
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;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::AddWeapon( WEAPON *wp )
|
|
{
|
|
rgWeapons[ wp->iId ] = *wp;
|
|
LoadWeaponSprites( &rgWeapons[ wp->iId ] );
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::PickupWeapon( WEAPON *wp )
|
|
{
|
|
rgSlots[ wp->iSlot ][ wp->iSlotPos ] = wp;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::DropWeapon( WEAPON *wp )
|
|
{
|
|
rgSlots[ wp->iSlot ][ wp->iSlotPos ] = NULL;
|
|
if(lastWeapon == wp) //dropped last weapon, remove it from the list
|
|
{ lastWeapon = NULL; }
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::DropAllWeapons( void )
|
|
{
|
|
for ( int i = 0; i < MAX_WEAPONS; i++ )
|
|
{
|
|
if ( rgWeapons[i].iId )
|
|
DropWeapon( &rgWeapons[i] );
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::UserCmd_LastInv(void)
|
|
{
|
|
if(this->IsSelectable(this->lastWeapon))
|
|
{
|
|
this->SetCurrentWeapon(lastWeapon);
|
|
// puzl: 764
|
|
//const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_ON);
|
|
//gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::UserCmd_MovementOn()
|
|
{
|
|
// Find out which weapon we want to trigger
|
|
AvHUser3 theUser3 = gHUD.GetHUDUser3();
|
|
int wID = -1;
|
|
switch(theUser3)
|
|
{
|
|
case AVH_USER3_ALIEN_PLAYER1:
|
|
wID = AVH_ABILITY_LEAP;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER3:
|
|
// TODO: Add flap
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER4:
|
|
wID = AVH_WEAPON_BLINK;
|
|
break;
|
|
case AVH_USER3_ALIEN_PLAYER5:
|
|
wID = AVH_ABILITY_CHARGE;
|
|
break;
|
|
default:
|
|
IN_ReloadDown();
|
|
return;
|
|
}
|
|
|
|
if (wID > -1)
|
|
{
|
|
// Fetch the needed movement weapon
|
|
WEAPON *p = this->GetWeapon(wID);
|
|
if (p != NULL && this->IsSelectable(p))
|
|
{
|
|
// Send activation of ability asap
|
|
IN_Attack2Down();
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::UserCmd_MovementOff()
|
|
{
|
|
// Ensure that we're not activating any weapons when selected
|
|
IN_Attack2Up();
|
|
IN_ReloadUp();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::SetValidWeapon(void)
|
|
{
|
|
WEAPON* p = this->GetFirstPos(0); //alien attack 1 or primary marine weapon
|
|
if(gHUD.GetIsAlien())
|
|
{
|
|
this->SetCurrentWeapon(p);
|
|
}
|
|
else
|
|
{
|
|
if(this->IsSelectable(p) && this->HasAmmo(p))
|
|
{
|
|
this->SetCurrentWeapon(p);
|
|
}
|
|
else
|
|
{
|
|
p = this->GetFirstPos(1); //pistol slot
|
|
if(this->IsSelectable(p) && this->HasAmmo(p))
|
|
{
|
|
this->SetCurrentWeapon(p);
|
|
}
|
|
else
|
|
{
|
|
p = this->GetFirstPos(2); //knife slot
|
|
this->SetCurrentWeapon(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
void WeaponsResource::SetCurrentWeapon(WEAPON* newWeapon)
|
|
{
|
|
WEAPON* currentWeapon = this->GetWeapon(gHUD.GetCurrentWeaponID());
|
|
// puzl: 497 - Because weapon state can get out of sync, we should allow this even if the weapons are the same
|
|
// && newWeapon != currentWeapon
|
|
if( newWeapon != NULL )
|
|
{
|
|
if( newWeapon != currentWeapon )
|
|
{ lastWeapon = currentWeapon; }
|
|
ServerCmd(newWeapon->szName);
|
|
g_weaponselect = newWeapon->iId;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
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;
|
|
|
|
if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) //require suit
|
|
return;
|
|
|
|
if ( ! ( gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT)) )) //require something besides suit
|
|
return;
|
|
|
|
WEAPON *p = NULL;
|
|
bool fastSwitch = CVAR_GET_FLOAT( "hud_fastswitch" ) != 0;
|
|
if ((gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot))
|
|
{
|
|
p = GetFirstPos(iSlot);
|
|
const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_ON);
|
|
gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
|
|
|
|
if (this->IsSelectable(p) && fastSwitch) //check to see if we can use fastSwitch
|
|
{
|
|
WEAPON *p2 = GetNextActivePos( p->iSlot, p->iSlotPos );
|
|
if (!this->IsSelectable(p2)) //only one target in the bucket
|
|
{
|
|
this->SetCurrentWeapon(p);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_MOVE_SELECT);
|
|
gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
|
|
|
|
if ( gpActiveSel )
|
|
p = GetNextActivePos( gpActiveSel->iSlot, gpActiveSel->iSlotPos );
|
|
if ( !p )
|
|
p = GetFirstPos( iSlot );
|
|
}
|
|
|
|
if (!this->IsSelectable(p)) // no valid selection found
|
|
{
|
|
// if fastSwitch is on, ignore, else turn on the menu
|
|
if ( !fastSwitch ) {
|
|
gpActiveSel = (WEAPON *)1;
|
|
}
|
|
else {
|
|
gpActiveSel = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gpActiveSel = 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_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_CREATE( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0 );
|
|
CVAR_CREATE( "hud_fastswitch", "0", FCVAR_ARCHIVE ); // controls whether or not weapons can be selected in one keypress
|
|
|
|
m_iFlags |= HUD_ACTIVE; //!!!
|
|
|
|
gWR.Init();
|
|
gHR.Init();
|
|
|
|
return 1;
|
|
};
|
|
|
|
void CHudAmmo::Reset(void)
|
|
{
|
|
m_fFade = 0;
|
|
m_iFlags |= HUD_ACTIVE; //!!!
|
|
|
|
gpActiveSel = NULL;
|
|
gHUD.m_iHideHUDDisplay = 0;
|
|
|
|
gWR.Reset();
|
|
gHR.Reset();
|
|
|
|
m_customCrosshair=0;
|
|
// VidInit();
|
|
|
|
}
|
|
|
|
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();
|
|
|
|
if (ScreenWidth() >= 640)
|
|
{
|
|
giABWidth = 20;
|
|
giABHeight = 4;
|
|
}
|
|
else
|
|
{
|
|
giABWidth = 10;
|
|
giABHeight = 2;
|
|
}
|
|
|
|
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;
|
|
bool droppedCurrent = false;
|
|
|
|
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 );
|
|
}
|
|
}
|
|
}
|
|
if ( (int)CVAR_GET_FLOAT(kvCustomCrosshair) != m_customCrosshair ) {
|
|
m_customCrosshair=(int)CVAR_GET_FLOAT(kvCustomCrosshair);
|
|
WEAPON* currentWeapon = gWR.GetWeapon(gHUD.GetCurrentWeaponID());
|
|
if ( currentWeapon ) {
|
|
switch (m_customCrosshair) {
|
|
case 0:
|
|
gHUD.SetCurrentCrosshair(currentWeapon->hCrosshair, currentWeapon->rcCrosshair, 255, 255, 255);
|
|
break;
|
|
case 1:
|
|
gHUD.SetCurrentCrosshair(currentWeapon->hCrosshair1, currentWeapon->rcCrosshair1, 255, 255, 255);
|
|
break;
|
|
case 2:
|
|
gHUD.SetCurrentCrosshair(currentWeapon->hCrosshair2, currentWeapon->rcCrosshair2, 255, 255, 255);
|
|
break;
|
|
case 3:
|
|
gHUD.SetCurrentCrosshair(currentWeapon->hCrosshair3, currentWeapon->rcCrosshair3, 255, 255, 255);
|
|
break;
|
|
default:
|
|
gHUD.SetCurrentCrosshair(currentWeapon->hCrosshair, currentWeapon->rcCrosshair, 255, 255, 255);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(gHUD.GetIsAlien()) //check for hive death causing loss of current weapon
|
|
{
|
|
WEAPON* currentWeapon = gWR.GetWeapon(gHUD.GetCurrentWeaponID());
|
|
if(!gWR.IsSelectable(currentWeapon)) //current weapon isn't valid
|
|
{
|
|
gWR.SetValidWeapon(); //get best option
|
|
}
|
|
}
|
|
|
|
if (!gpActiveSel)
|
|
return;
|
|
|
|
// has the player selected one?
|
|
if (gHUD.m_iKeyBits & IN_ATTACK)
|
|
{
|
|
if (gpActiveSel != (WEAPON *)1)
|
|
{
|
|
gWR.SetCurrentWeapon(gpActiveSel);
|
|
}
|
|
|
|
gpLastSel = gpActiveSel;
|
|
gpActiveSel = NULL;
|
|
gHUD.m_iKeyBits &= ~IN_ATTACK;
|
|
|
|
const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_SELECT);
|
|
gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// Message Handlers
|
|
//------------------------------------------------------------------------
|
|
|
|
//
|
|
// AmmoX -- Update the count of a known type of ammo
|
|
//
|
|
int CHudAmmo::MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf)
|
|
{
|
|
int iIndex, iCount;
|
|
NetMsg_AmmoX( pbuf, iSize, iIndex, iCount );
|
|
gWR.SetAmmo( iIndex, abs(iCount) );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int CHudAmmo::MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf )
|
|
{
|
|
int iIndex, iCount;
|
|
NetMsg_AmmoPickup( pbuf, iSize, iIndex, iCount );
|
|
|
|
// Add ammo to the history
|
|
gHR.AddToHistory( HISTSLOT_AMMO, iIndex, abs(iCount) );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int CHudAmmo::MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf )
|
|
{
|
|
int iIndex;
|
|
NetMsg_WeapPickup( pbuf, iSize, iIndex );
|
|
|
|
// Add the weapon to the history
|
|
gHR.AddToHistory( HISTSLOT_WEAP, iIndex );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int CHudAmmo::MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf )
|
|
{
|
|
string szName;
|
|
NetMsg_ItemPickup( pbuf, iSize, szName );
|
|
|
|
// Add the weapon to the history
|
|
gHR.AddToHistory( HISTSLOT_ITEM, szName.c_str() );
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf )
|
|
{
|
|
NetMsg_HideWeapon( pbuf, iSize, gHUD.m_iHideHUDDisplay );
|
|
|
|
if (gEngfuncs.IsSpectateOnly())
|
|
return 1;
|
|
if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) )
|
|
{
|
|
static wrect_t nullrc;
|
|
gpActiveSel = NULL;
|
|
gHUD.SetCurrentCrosshair( 0, nullrc, 0, 0, 0 );
|
|
}
|
|
else
|
|
{
|
|
if ( m_pWeapon )
|
|
gHUD.SetCurrentCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 );
|
|
}
|
|
|
|
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 iState, iId, iClip;
|
|
NetMsg_CurWeapon( pbuf, iSize, iState, iId, iClip );
|
|
|
|
if ( iId < 1 ) //signal kills crosshairs if this condition is met...
|
|
{
|
|
gHUD.SetCurrentCrosshair(0, nullrc, 0, 0, 0);
|
|
return 0;
|
|
}
|
|
|
|
if ( g_iUser1 != OBS_IN_EYE )
|
|
{
|
|
if ( iId == -1 && iClip == -1 ) //this conditional is never true due to iId < 1 check above!
|
|
{
|
|
gHUD.m_fPlayerDead = TRUE;
|
|
gpActiveSel = NULL;
|
|
return 1;
|
|
}
|
|
|
|
gHUD.m_fPlayerDead = FALSE;
|
|
}
|
|
|
|
WEAPON *pWeapon = gWR.GetWeapon( iId );
|
|
if( pWeapon == NULL ) //don't have the weapon described in our resource list
|
|
{ return 0; }
|
|
|
|
bool bOnTarget = (iState & WEAPON_ON_TARGET) != 0; //used to track autoaim state
|
|
bool bIsCurrent = (iState & WEAPON_IS_CURRENT) != 0;
|
|
pWeapon->iEnabled = (iState & WEAPON_IS_ENABLED) != 0 ? TRUE : FALSE;
|
|
pWeapon->iClip = abs(iClip);
|
|
|
|
if( !bIsCurrent )
|
|
{ return 1; }
|
|
|
|
m_pWeapon = pWeapon;
|
|
|
|
if ( !(gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
|
|
{
|
|
switch ((int)CVAR_GET_FLOAT(kvCustomCrosshair)) {
|
|
case 0:
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
|
|
break;
|
|
case 1:
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair1, m_pWeapon->rcCrosshair1, 255, 255, 255);
|
|
break;
|
|
case 2:
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair2, m_pWeapon->rcCrosshair2, 255, 255, 255);
|
|
break;
|
|
case 3:
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair3, m_pWeapon->rcCrosshair3, 255, 255, 255);
|
|
break;
|
|
default:
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
|
|
break;
|
|
}
|
|
|
|
/* if ( gHUD.m_iFOV >= 90 )
|
|
{ // normal crosshairs
|
|
if (bOnTarget && m_pWeapon->hAutoaim)
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hAutoaim, m_pWeapon->rcAutoaim, 255, 255, 255);
|
|
else
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255);
|
|
}
|
|
else
|
|
{ // zoomed crosshairs
|
|
if (bOnTarget && m_pWeapon->hZoomedAutoaim)
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255);
|
|
else
|
|
gHUD.SetCurrentCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255);
|
|
}*/
|
|
}
|
|
|
|
m_fFade = 200.0f; //!!!
|
|
m_iFlags |= HUD_ACTIVE;
|
|
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// WeaponList -- Tells the hud about a new weapon type.
|
|
//
|
|
int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
|
|
{
|
|
WeaponList weapon_data;
|
|
NetMsg_WeaponList( pbuf, iSize, weapon_data );
|
|
|
|
WEAPON Weapon;
|
|
memset( &Weapon, 0, sizeof(WEAPON) );
|
|
|
|
strcpy( Weapon.szName, weapon_data.weapon_name.c_str() );
|
|
Weapon.iAmmoType = weapon_data.ammo1_type;
|
|
Weapon.iMax1 = weapon_data.ammo1_max_amnt == 255 ? -1 : weapon_data.ammo1_max_amnt;
|
|
Weapon.iAmmo2Type = weapon_data.ammo2_type;
|
|
Weapon.iMax2 = weapon_data.ammo2_max_amnt == 255 ? -1 : weapon_data.ammo2_max_amnt;
|
|
Weapon.iSlot = weapon_data.bucket;
|
|
Weapon.iSlotPos = weapon_data.bucket_pos;
|
|
Weapon.iId = weapon_data.bit_index;
|
|
Weapon.iFlags = weapon_data.flags;
|
|
Weapon.iClip = 0;
|
|
// puzl: 497 - default value for enable state
|
|
Weapon.iEnabled = 0;
|
|
|
|
gWR.AddWeapon( &Weapon );
|
|
return 1;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// Command Handlers
|
|
//------------------------------------------------------------------------
|
|
// Slot button pressed
|
|
void CHudAmmo::SlotInput( int iSlot )
|
|
{
|
|
// Let the Viewport use it first, for menus
|
|
if ( gViewPort && gViewPort->SlotInput( iSlot ) )
|
|
return;
|
|
|
|
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;
|
|
|
|
const char* theSound = AvHSHUGetCommonSoundName(gHUD.GetIsAlien(), WEAPON_SOUND_HUD_OFF);
|
|
gHUD.PlayHUDSound(theSound, kHUDSoundVolume);
|
|
}
|
|
}
|
|
|
|
|
|
// Selects the next item in the weapon menu
|
|
void CHudAmmo::UserCmd_NextWeapon(void)
|
|
{
|
|
if(gHUD.GetInTopDownMode())
|
|
{
|
|
AvHScrollHandler::ScrollHeightUp();
|
|
}
|
|
|
|
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 (gWR.IsSelectable(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)
|
|
{
|
|
if(gHUD.GetInTopDownMode())
|
|
{
|
|
AvHScrollHandler::ScrollHeightDown();
|
|
}
|
|
|
|
if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) )
|
|
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 (gWR.IsSelectable(wsp))
|
|
{
|
|
gpActiveSel = wsp;
|
|
return;
|
|
}
|
|
}
|
|
|
|
pos = MAX_WEAPON_POSITIONS-1;
|
|
}
|
|
|
|
slot = MAX_WEAPON_SLOTS-1;
|
|
}
|
|
|
|
gpActiveSel = NULL;
|
|
}
|
|
|
|
void CHudAmmo::SetCurrentClip(int inClip)
|
|
{
|
|
if(this->m_pWeapon)
|
|
{
|
|
this->m_pWeapon->iClip = inClip;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Drawing code
|
|
//-------------------------------------------------------------------------
|
|
|
|
int CHudAmmo::Draw(float flTime)
|
|
{
|
|
int a, x, y, r, g, b;
|
|
int AmmoWidth;
|
|
|
|
if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) ))
|
|
return 1;
|
|
|
|
if (/*!gHUD.GetIsAlive() ||*/ (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) )
|
|
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);
|
|
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
|
|
ScaleColors(r, g, b, a );
|
|
|
|
int theViewport[4];
|
|
gHUD.GetViewport(theViewport);
|
|
|
|
// Does this weapon have a clip?
|
|
y = theViewport[1] + theViewport[3] - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2;
|
|
|
|
// 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
|
|
|
|
x = theViewport[0] + theViewport[2] - (8 * AmmoWidth) - iIconWidth;
|
|
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;
|
|
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
|
|
// 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
|
|
x = theViewport[0] + theViewport[2] - 4 * AmmoWidth - iIconWidth;
|
|
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 seconday 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;
|
|
x = theViewport[0] + theViewport[2] - 4 * AmmoWidth - iIconWidth;
|
|
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;
|
|
}
|
|
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
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 )
|
|
{
|
|
gHUD.SetSelectingWeaponID(-1);
|
|
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;
|
|
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
|
|
if ( iActiveSlot == i )
|
|
a = 255;
|
|
else
|
|
a = 192;
|
|
|
|
ScaleColors(r, g, b, 255);
|
|
SPR_Set(gHUD.GetSprite(m_HUD_bucket0 + i), r, g, b );
|
|
|
|
// 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;
|
|
|
|
SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i));
|
|
|
|
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;
|
|
|
|
// Preserve red/yellow depending on whether it has ammo or not
|
|
if(!gWR.IsEnabled(p))
|
|
{
|
|
UnpackRGB(r,g,b, RGB_REDISH);
|
|
ScaleColors(r, g, b, 128);
|
|
}
|
|
else
|
|
{
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
ScaleColors(r, g, b, 192);
|
|
}
|
|
|
|
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));
|
|
|
|
// Lookup iID for helptext
|
|
gHUD.SetSelectingWeaponID(p->iId, r, g, b);
|
|
}
|
|
else
|
|
{
|
|
// Draw Weapon if Red if no ammo
|
|
|
|
//if (gWR.IsSelectable(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.
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
|
|
for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
|
|
{
|
|
WEAPON *p = gWR.GetWeaponSlot( i, iPos );
|
|
|
|
if ( !p || !p->iId )
|
|
continue;
|
|
|
|
if ( gWR.IsEnabled(p) )
|
|
{
|
|
gHUD.GetPrimaryHudColor(r, g, b);
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
/* =================================
|
|
GetSpriteList
|
|
|
|
Finds and returns the matching
|
|
sprite name 'psz' and resolution 'iRes'
|
|
in the given sprite list 'pList'
|
|
iCount is the number of items in the pList
|
|
================================= */
|
|
client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount)
|
|
{
|
|
if (!pList)
|
|
return NULL;
|
|
|
|
int i = iCount;
|
|
client_sprite_t *p = pList;
|
|
|
|
while(i--)
|
|
{
|
|
if ((!strcmp(psz, p->szName)) && (p->iRes == iRes))
|
|
return p;
|
|
p++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|