as released 2000-06-05

This commit is contained in:
archive 2000-06-05 00:00:00 +00:00
parent b443b4420e
commit 7e9f0c84ab
367 changed files with 38976 additions and 2127 deletions

2
Network/Delta.txt Normal file
View File

@ -0,0 +1,2 @@
Place delta.lst in the valve\ folder ( or a customized copy can be placed in your game directory's folder )

234
Network/delta.lst Normal file
View File

@ -0,0 +1,234 @@
// structure name
// none == no conditional encode routine
// gamedll routine_name : before transmitting data, invoke the named function from the game .dll to reset fields as needed
// clientdll routine_name : same as above, except the routine is called via the client.dll
clientdata_t none
{
DEFINE_DELTA( flTimeStepSound, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 21, 128.0 ),
DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 21, 128.0 ),
DEFINE_DELTA( velocity[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( velocity[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( m_flNextAttack, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 21, 128.0 ),
DEFINE_DELTA( velocity[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( ammo_nails, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( ammo_shells, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( ammo_cells, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( ammo_rockets, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( m_iId, DT_INTEGER, 5, 1.0 ),
DEFINE_DELTA( punchangle[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( flags, DT_INTEGER, 32, 1.0 ), // Cut to 3 bits?
DEFINE_DELTA( weaponanim, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( health, DT_SIGNED | DT_FLOAT, 10, 1.0 ), // Cut # of bits?
DEFINE_DELTA( maxspeed, DT_FLOAT, 16, 10.0 ),
DEFINE_DELTA( flDuckTime, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( view_ofs[2], DT_SIGNED | DT_FLOAT, 10, 4.0 ),
DEFINE_DELTA( punchangle[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( punchangle[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( viewmodel, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( weapons, DT_INTEGER, 32, 1.0 ),
DEFINE_DELTA( pushmsec, DT_INTEGER, 11, 1.0 ),
DEFINE_DELTA( deadflag, DT_INTEGER, 3, 1.0 ),
DEFINE_DELTA( fov, DT_FLOAT, 8, 1.0 ),
DEFINE_DELTA( physinfo, DT_STRING, 1, 1.0 ),
DEFINE_DELTA( bInDuck, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( flSwimTime, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( waterjumptime, DT_INTEGER, 15, 1.0 ),
DEFINE_DELTA( waterlevel, DT_INTEGER, 2, 1.0 )
}
entity_state_t gamedll Entity_Encode
{
DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( angles[0], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( angles[1], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( sequence, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( modelindex, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( movetype, DT_INTEGER, 4, 1.0 ),
DEFINE_DELTA( solid, DT_SHORT, 3, 1.0 ),
DEFINE_DELTA( mins[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( mins[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( mins[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( maxs[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( maxs[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( maxs[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( endpos[0], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
DEFINE_DELTA( endpos[1], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
DEFINE_DELTA( endpos[2], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
DEFINE_DELTA( startpos[0], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
DEFINE_DELTA( startpos[1], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
DEFINE_DELTA( startpos[2], DT_SIGNED | DT_FLOAT, 13, 1.0 ),
DEFINE_DELTA( impacttime, DT_TIMEWINDOW_BIG, 13, 100.0 ),
DEFINE_DELTA( starttime, DT_TIMEWINDOW_BIG, 13, 100.0 ),
DEFINE_DELTA( weaponmodel, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( owner, DT_INTEGER, 5, 1.0 ),
DEFINE_DELTA( effects, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( eflags, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( angles[2], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( colormap, DT_INTEGER, 16, 1.0 ),
DEFINE_DELTA( framerate, DT_SIGNED | DT_FLOAT, 8, 16.0 ),
DEFINE_DELTA( skin, DT_SHORT | DT_SIGNED, 9, 1.0 ),
DEFINE_DELTA( controller[0], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( controller[1], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( controller[2], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( controller[3], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( blending[0], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( blending[1], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( body, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( rendermode, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( renderamt, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( renderfx, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( scale, DT_FLOAT, 16, 256.0 ),
DEFINE_DELTA( rendercolor.r, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( rendercolor.g, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( rendercolor.b, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( aiment, DT_INTEGER, 11, 1.0 ),
DEFINE_DELTA( basevelocity[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( basevelocity[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( basevelocity[2], DT_SIGNED | DT_FLOAT, 16, 8.0 )
}
entity_state_player_t gamedll Player_Encode
{
DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 18, 32.0 ),
DEFINE_DELTA( angles[0], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( angles[1], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 18, 32.0 ),
DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 18, 32.0 ),
DEFINE_DELTA( gaitsequence, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( sequence, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( modelindex, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( movetype, DT_INTEGER, 4, 1.0 ),
DEFINE_DELTA( solid, DT_SHORT, 3, 1.0 ),
DEFINE_DELTA( mins[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( mins[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( mins[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( maxs[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( maxs[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( maxs[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( weaponmodel, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( team, DT_INTEGER, 4, 1.0 )
DEFINE_DELTA( playerclass, DT_INTEGER, 4, 1.0 )
DEFINE_DELTA( owner, DT_INTEGER, 5, 1.0 ),
DEFINE_DELTA( effects, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( angles[2], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( colormap, DT_INTEGER, 16, 1.0 ),
DEFINE_DELTA( framerate, DT_SIGNED | DT_FLOAT, 8, 16.0 ),
DEFINE_DELTA( skin, DT_SHORT | DT_SIGNED, 9, 1.0 ),
DEFINE_DELTA( controller[0], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( controller[1], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( controller[2], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( controller[3], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( blending[0], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( blending[1], DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( body, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( rendermode, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( renderamt, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( renderfx, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( scale, DT_FLOAT, 16, 256.0 ),
DEFINE_DELTA( rendercolor.r, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( rendercolor.g, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( rendercolor.b, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( friction, DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( usehull, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( gravity, DT_SIGNED | DT_FLOAT, 16, 32.0 ),
DEFINE_DELTA( aiment, DT_INTEGER, 11, 1.0 ),
DEFINE_DELTA( basevelocity[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( basevelocity[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( basevelocity[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( spectator, DT_INTEGER, 1, 1.0 )
}
custom_entity_state_t gamedll Custom_Encode
{
DEFINE_DELTA( rendermode, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
DEFINE_DELTA( angles[0], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
DEFINE_DELTA( angles[1], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
DEFINE_DELTA( angles[2], DT_SIGNED | DT_FLOAT, 17, 8.0 ),
DEFINE_DELTA( sequence, DT_INTEGER, 16, 1.0 ),
DEFINE_DELTA( skin, DT_INTEGER, 16, 1.0 ),
DEFINE_DELTA( modelindex, DT_INTEGER, 16, 1.0 ),
DEFINE_DELTA_POST( scale, DT_FLOAT, 8, 1.0, 0.1 ),
DEFINE_DELTA( body, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( rendercolor.r, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( rendercolor.g, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( rendercolor.b, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( renderfx, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( renderamt, DT_INTEGER, 8, 1.0 ),
DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
DEFINE_DELTA_POST( animtime, DT_FLOAT, 8, 1.0, 0.1 )
}
usercmd_t none
{
DEFINE_DELTA( lerp_msec, DT_SHORT, 9, 1.0 ),
DEFINE_DELTA( msec, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( viewangles[1], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( viewangles[0], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( buttons, DT_SHORT, 16, 1.0 ),
DEFINE_DELTA( forwardmove, DT_SIGNED | DT_FLOAT, 12, 1.0 ),
DEFINE_DELTA( lightlevel, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( sidemove, DT_SIGNED | DT_FLOAT, 12, 1.0 ),
DEFINE_DELTA( upmove, DT_SIGNED | DT_FLOAT, 12, 1.0 ),
DEFINE_DELTA( impulse, DT_BYTE, 8, 1.0 ),
DEFINE_DELTA( viewangles[2], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( impact_index, DT_INTEGER, 6, 1.0 ),
DEFINE_DELTA( impact_position[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( impact_position[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( impact_position[2], DT_SIGNED | DT_FLOAT, 16, 8.0 )
}
weapon_data_t none
{
DEFINE_DELTA( m_flTimeWeaponIdle, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( m_flNextPrimaryAttack, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( m_flNextReload, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( m_fNextAimBonus, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( m_flNextSecondaryAttack, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( m_iClip, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( m_flPumpTime, DT_FLOAT | DT_SIGNED, 22, 1000.0 ),
DEFINE_DELTA( m_fInSpecialReload, DT_INTEGER, 2, 1.0 ),
DEFINE_DELTA( m_fReloadTime, DT_FLOAT, 16, 100.0 ),
DEFINE_DELTA( m_fInReload, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( m_fAimedDamage, DT_FLOAT, 6, 0.1 ),
DEFINE_DELTA( m_fInZoom, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( m_iWeaponState, DT_INTEGER, 2, 1.0 ),
DEFINE_DELTA( m_iId, DT_INTEGER, 5, 1.0 )
}
event_t none
{
DEFINE_DELTA( entindex, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( bparam1, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( bparam2, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( origin[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( origin[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( fparam1, DT_FLOAT | DT_SIGNED, 20, 100.0 ),
DEFINE_DELTA( fparam2, DT_FLOAT | DT_SIGNED, 20, 100.0 ),
DEFINE_DELTA( iparam1, DT_INTEGER | DT_SIGNED, 16, 1.0 ),
DEFINE_DELTA( iparam2, DT_INTEGER | DT_SIGNED, 16, 1.0 ),
DEFINE_DELTA( angles[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( angles[1], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( angles[2], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( ducking, DT_INTEGER, 1, 1.0 )
}

View File

@ -1,141 +0,0 @@
/***
*
* 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.
*
****/
//
// MOTD.cpp
//
// for displaying a server-sent message of the day
//
#include "hud.h"
#include "util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
DECLARE_MESSAGE( m_MOTD, MOTD );
int CHudMOTD::MOTD_DISPLAY_TIME;
int CHudMOTD :: Init( void )
{
gHUD.AddHudElem( this );
HOOK_MESSAGE( MOTD );
CVAR_CREATE( "motd_display_time", "6", 0 );
m_iFlags &= ~HUD_ACTIVE; // start out inactive
m_szMOTD[0] = 0;
return 1;
}
int CHudMOTD :: VidInit( void )
{
// Load sprites here
return 1;
}
void CHudMOTD :: Reset( void )
{
m_iFlags &= ~HUD_ACTIVE; // start out inactive
m_szMOTD[0] = 0;
m_iLines = 0;
m_flActiveTill = 0;
}
#define LINE_HEIGHT 13
int CHudMOTD :: Draw( float fTime )
{
// Draw MOTD line-by-line
if ( m_flActiveTill < gHUD.m_flTime )
{ // finished with MOTD, disable it
m_szMOTD[0] = 0;
m_iLines = 0;
m_iFlags &= ~HUD_ACTIVE;
return 1;
}
// cap activetill time to the display time
m_flActiveTill = min( gHUD.m_flTime + MOTD_DISPLAY_TIME, m_flActiveTill );
// find the top of where the MOTD should be drawn, so the whole thing is centered in the screen
int ypos = max(((ScreenHeight - (m_iLines * LINE_HEIGHT)) / 2) - 40, 30 ); // shift it up slightly
char *ch = m_szMOTD;
while ( *ch )
{
int line_length = 0; // count the length of the current line
for ( char *next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ )
line_length += gHUD.m_scrinfo.charWidths[ *next_line ];
char *top = next_line;
if ( *top == '\n' )
*top = 0;
else
top = NULL;
// find where to start drawing the line
int xpos = (ScreenWidth - line_length) / 2;
gHUD.DrawHudString( xpos, ypos, ScreenWidth, ch, 255, 180, 0 );
ypos += LINE_HEIGHT;
if ( top ) // restore
*top = '\n';
ch = next_line;
if ( *ch == '\n' )
ch++;
if ( ypos > (ScreenHeight - 20) )
break; // don't let it draw too low
}
return 1;
}
int CHudMOTD :: MsgFunc_MOTD( const char *pszName, int iSize, void *pbuf )
{
if ( m_iFlags & HUD_ACTIVE )
{
Reset(); // clear the current MOTD in prep for this one
}
BEGIN_READ( pbuf, iSize );
int is_finished = READ_BYTE();
strcat( m_szMOTD, READ_STRING() );
if ( is_finished )
{
m_iFlags |= HUD_ACTIVE;
MOTD_DISPLAY_TIME = CVAR_GET_FLOAT( "motd_display_time" );
m_flActiveTill = gHUD.m_flTime + MOTD_DISPLAY_TIME;
for ( char *sz = m_szMOTD; *sz != 0; sz++ ) // count the number of lines in the MOTD
{
if ( *sz == '\n' )
m_iLines++;
}
}
return 1;
}

View File

@ -19,13 +19,14 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
#include "ammohistory.h"
#include "vgui_TeamFortressViewport.h"
WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise
// this points to the active weapon menu item
@ -35,6 +36,8 @@ client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes
WeaponsResource gWR;
int g_weaponselect = 0;
void WeaponsResource :: LoadAllWeaponSprites( void )
{
for (int i = 0; i < MAX_WEAPONS; i++)
@ -372,7 +375,10 @@ void CHudAmmo::Think(void)
if (gHUD.m_iKeyBits & IN_ATTACK)
{
if (gpActiveSel != (WEAPON *)1)
{
ServerCmd(gpActiveSel->szName);
g_weaponselect = gpActiveSel->iId;
}
gpLastSel = gpActiveSel;
gpActiveSel = NULL;
@ -430,13 +436,14 @@ void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection )
return;
WEAPON *p = NULL;
bool fastSwitch = CVAR_GET_FLOAT( "hud_fastswitch" ) != 0;
if ( (gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot) )
{
PlaySound( "common/wpn_hudon.wav", 1 );
p = GetFirstPos( iSlot );
if ( p && CVAR_GET_FLOAT( "hud_fastswitch" ) > 0 ) // check for fast weapon switch mode
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
@ -444,6 +451,7 @@ void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection )
if ( !p2 )
{ // only one active item in bucket, so change directly to weapon
ServerCmd( p->szName );
g_weaponselect = p->iId;
return;
}
}
@ -458,13 +466,18 @@ void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection )
}
if ( !p ) // if no selection found, just display the weapon list
gpActiveSel = (WEAPON *)1;
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
//------------------------------------------------------------------------
@ -653,55 +666,64 @@ int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf )
//------------------------------------------------------------------------
// 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)
{
gWR.SelectSlot(0, FALSE, 1);
SlotInput( 0 );
}
void CHudAmmo::UserCmd_Slot2(void)
{
gWR.SelectSlot(1, FALSE, 1);
SlotInput( 1 );
}
void CHudAmmo::UserCmd_Slot3(void)
{
gWR.SelectSlot(2, FALSE, 1);
SlotInput( 2 );
}
void CHudAmmo::UserCmd_Slot4(void)
{
gWR.SelectSlot(3, FALSE, 1);
SlotInput( 3 );
}
void CHudAmmo::UserCmd_Slot5(void)
{
gWR.SelectSlot(4, FALSE, 1);
SlotInput( 4 );
}
void CHudAmmo::UserCmd_Slot6(void)
{
gWR.SelectSlot(5, FALSE, 1);
SlotInput( 5 );
}
void CHudAmmo::UserCmd_Slot7(void)
{
gWR.SelectSlot(6, FALSE, 1);
SlotInput( 6 );
}
void CHudAmmo::UserCmd_Slot8(void)
{
gWR.SelectSlot(7, FALSE, 1);
SlotInput( 7 );
}
void CHudAmmo::UserCmd_Slot9(void)
{
gWR.SelectSlot(8, FALSE, 1);
SlotInput( 8 );
}
void CHudAmmo::UserCmd_Slot10(void)
{
gWR.SelectSlot(9, FALSE, 1);
SlotInput( 9 );
}
void CHudAmmo::UserCmd_Close(void)

View File

@ -19,7 +19,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#include <stdio.h>
#include "parsemsg.h"

View File

@ -18,7 +18,7 @@
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>

View File

@ -90,7 +90,6 @@ public:
int CountAmmo( int iId );
HSPRITE* GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect );
};
extern WeaponsResource gWR;

View File

@ -19,7 +19,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>

17
cl_dll/camera.h Normal file
View File

@ -0,0 +1,17 @@
// Camera.h -- defines and such for a 3rd person camera
// NOTE: must include quakedef.h first
#ifndef _CAMERA_H_
#define _CAMEA_H_
// pitch, yaw, dist
extern vec3_t cam_ofs;
// Using third person camera
extern int cam_thirdperson;
void CAM_Init( void );
void CAM_ClearStates( void );
void CAM_StartMouseMove(void);
void CAM_EndMouseMove(void);
#endif // _CAMERA_H_

View File

@ -19,14 +19,28 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "netadr.h"
#include "vgui_schememanager.h"
extern "C"
{
#include "pm_shared.h"
}
#include <string.h>
#include "hud_servers.h"
#include "vgui_int.h"
#define DLLEXPORT __declspec( dllexport )
cl_enginefunc_t gEngfuncs;
CHud gHUD;
TeamFortressViewport *gViewPort = NULL;
void InitInput (void);
void EV_HookEvents( void );
void IN_Commands( void );
/*
==========================
@ -43,8 +57,83 @@ int DLLEXPORT HUD_Init( void );
int DLLEXPORT HUD_Redraw( float flTime, int intermission );
int DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime );
int DLLEXPORT HUD_Reset ( void );
void DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server );
void DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove );
char DLLEXPORT HUD_PlayerMoveTexture( char *name );
int DLLEXPORT HUD_ConnectionlessPacket( struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs );
void DLLEXPORT HUD_Frame( double time );
}
/*
================================
HUD_GetHullBounds
Engine calls this to enumerate player collision hulls, for prediction. Return 0 if the hullnumber doesn't exist.
================================
*/
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs )
{
int iret = 0;
switch ( hullnumber )
{
case 0: // Normal player
mins = Vector(-16, -16, -36);
maxs = Vector(16, 16, 36);
iret = 1;
break;
case 1: // Crouched player
mins = Vector(-16, -16, -18 );
maxs = Vector(16, 16, 18 );
iret = 1;
break;
case 2: // Point based hull
mins = Vector( 0, 0, 0 );
maxs = Vector( 0, 0, 0 );
iret = 1;
break;
}
return iret;
}
/*
================================
HUD_ConnectionlessPacket
Return 1 if the packet is valid. Set response_buffer_size if you want to send a response packet. Incoming, it holds the max
size of the response_buffer, so you must zero it out if you choose not to respond.
================================
*/
int DLLEXPORT HUD_ConnectionlessPacket( struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size )
{
// Parse stuff from args
int max_buffer_size = *response_buffer_size;
// Zero it out since we aren't going to respond.
// If we wanted to response, we'd write data into response_buffer
*response_buffer_size = 0;
// Since we don't listen for anything here, just respond that it's a bogus message
// If we didn't reject the message, we'd return 1 for success instead.
return 0;
}
void DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove )
{
PM_Init( ppmove );
}
char DLLEXPORT HUD_PlayerMoveTexture( char *name )
{
return PM_FindTextureType( name );
}
void DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server )
{
PM_Move( ppmove, server );
}
int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion )
{
@ -59,6 +148,8 @@ int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion )
memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t));
EV_HookEvents();
return 1;
}
@ -76,6 +167,9 @@ so the HUD can reinitialize itself.
int DLLEXPORT HUD_VidInit( void )
{
gHUD.VidInit();
VGui_Startup();
return 1;
}
@ -91,7 +185,9 @@ the hud variables.
int DLLEXPORT HUD_Init( void )
{
InitInput();
gHUD.Init();
Scheme_Init();
return 1;
}
@ -129,6 +225,8 @@ returns 1 if anything has been changed, 0 otherwise.
int DLLEXPORT HUD_UpdateClientData(client_data_t *pcldata, float flTime )
{
IN_Commands();
return gHUD.UpdateClientData(pcldata, flTime );
}
@ -144,4 +242,17 @@ int DLLEXPORT HUD_Reset( void )
{
gHUD.VidInit();
return 1;
}
/*
==========================
HUD_Frame
Called by engine every frame that client .dll is loaded
==========================
*/
void DLLEXPORT HUD_Frame( double time )
{
ServersThink( time );
}

View File

@ -40,9 +40,10 @@ RSC=rc.exe
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ".\Release"
# PROP Intermediate_Dir ".\Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\utils\vgui\include" /I "..\dlls" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -52,14 +53,14 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:".\Release\client.dll"
# Begin Custom Build - Copying to \half-life\mp\cl_dlls
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:".\Release\client.dll"
# Begin Custom Build - Copying to \quiver\valve\cl_dlls
TargetDir=.\Release
InputPath=.\Release\client.dll
SOURCE="$(InputPath)"
"\half-life\mp\cl_dlls\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\client.dll \half-life\mp\cl_dlls
"\quiver\valve\cl_dlls\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\client.dll \quiver\valve\cl_dlls
# End Custom Build
@ -74,9 +75,10 @@ SOURCE="$(InputPath)"
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ".\Debug"
# PROP Intermediate_Dir ".\Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\utils\vgui\include" /I "..\dlls" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
@ -86,7 +88,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\client.dll"
# ADD LINK32 oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\client.dll"
# Begin Custom Build - Copying to \half-life\mp\cl_dlls
TargetDir=.\Debug
InputPath=.\Debug\client.dll
@ -106,6 +108,34 @@ SOURCE="$(InputPath)"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
# Begin Group "hl"
# PROP Default_Filter "*.cpp"
# Begin Source File
SOURCE=.\ev_hldm.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_baseentity.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_events.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_objects.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_weapons.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\wpn_shared\hl_wpn_glock.cpp
# End Source File
# End Group
# Begin Source File
SOURCE=.\ammo.cpp
@ -128,10 +158,30 @@ SOURCE=.\cdll_int.cpp
# End Source File
# Begin Source File
SOURCE=.\com_weapons.cpp
# End Source File
# Begin Source File
SOURCE=.\death.cpp
# End Source File
# Begin Source File
SOURCE=.\demo.cpp
# End Source File
# Begin Source File
SOURCE=.\entity.cpp
# End Source File
# Begin Source File
SOURCE=.\ev_common.cpp
# End Source File
# Begin Source File
SOURCE=.\events.cpp
# End Source File
# Begin Source File
SOURCE=.\flashlight.cpp
# End Source File
# Begin Source File
@ -156,10 +206,26 @@ SOURCE=.\hud_redraw.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_servers.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_update.cpp
# End Source File
# Begin Source File
SOURCE=.\in_camera.cpp
# End Source File
# Begin Source File
SOURCE=.\input.cpp
# End Source File
# Begin Source File
SOURCE=.\inputw32.cpp
# End Source File
# Begin Source File
SOURCE=.\menu.cpp
# End Source File
# Begin Source File
@ -168,10 +234,6 @@ SOURCE=.\message.cpp
# End Source File
# Begin Source File
SOURCE=.\MOTD.cpp
# End Source File
# Begin Source File
SOURCE=.\parsemsg.cpp
# End Source File
# Begin Source File
@ -180,11 +242,19 @@ SOURCE=.\parsemsg.h
# End Source File
# Begin Source File
SOURCE=.\saytext.cpp
SOURCE=..\pm_shared\pm_debug.c
# End Source File
# Begin Source File
SOURCE=.\scoreboard.cpp
SOURCE=..\pm_shared\pm_math.c
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_shared.c
# End Source File
# Begin Source File
SOURCE=.\saytext.cpp
# End Source File
# Begin Source File
@ -204,8 +274,60 @@ SOURCE=.\train.cpp
# End Source File
# Begin Source File
SOURCE=.\tri.cpp
# End Source File
# Begin Source File
SOURCE=.\util.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ClassMenu.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ConsolePanel.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ControlConfigPanel.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_CustomObjects.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_int.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_MOTDWindow.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_SchemeManager.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ScorePanel.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ServerBrowser.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_TeamFortressViewport.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_teammenu.cpp
# End Source File
# Begin Source File
SOURCE=.\view.cpp
# End Source File
# End Group
# Begin Group "Header Files"
@ -220,10 +342,30 @@ SOURCE=.\ammohistory.h
# End Source File
# Begin Source File
SOURCE=.\camera.h
# End Source File
# Begin Source File
SOURCE=.\cl_dll.h
# End Source File
# Begin Source File
SOURCE=.\com_weapons.h
# End Source File
# Begin Source File
SOURCE=.\demo.h
# End Source File
# Begin Source File
SOURCE=.\ev_hldm.h
# End Source File
# Begin Source File
SOURCE=.\eventscripts.h
# End Source File
# Begin Source File
SOURCE=.\health.h
# End Source File
# Begin Source File
@ -232,12 +374,92 @@ SOURCE=.\hud.h
# End Source File
# Begin Source File
SOURCE=.\hud_iface.h
# End Source File
# Begin Source File
SOURCE=.\hud_servers.h
# End Source File
# Begin Source File
SOURCE=.\hud_servers_priv.h
# End Source File
# Begin Source File
SOURCE=.\in_defs.h
# End Source File
# Begin Source File
SOURCE=.\kbutton.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_debug.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_defs.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_info.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_materials.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_movevars.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_shared.h
# End Source File
# Begin Source File
SOURCE=.\util.h
# End Source File
# Begin Source File
SOURCE=.\util_vector.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ConsolePanel.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ControlConfigPanel.h
# End Source File
# Begin Source File
SOURCE=.\vgui_int.h
# End Source File
# Begin Source File
SOURCE=.\vgui_SchemeManager.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ScorePanel.h
# End Source File
# Begin Source File
SOURCE=.\vgui_ServerBrowser.h
# End Source File
# Begin Source File
SOURCE=.\vgui_TeamFortressViewport.h
# End Source File
# Begin Source File
SOURCE=.\view.h
# End Source File
# Begin Source File
SOURCE=.\wrect.h
# End Source File
# End Group
# Begin Group "Resource Files"

View File

@ -8,7 +8,7 @@ Project: "cl_dll"=.\cl_dll.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/GoldSrc/cl_dll", HGEBAAAA
"$/HLStandardSDK/SourceCode/cl_dll", NUWHAAAA
.
end source code control
}}}
@ -23,10 +23,6 @@ Global:
Package=<5>
{{{
begin source code control
"$/GoldSrc/cl_dll", HGEBAAAA
.
end source code control
}}}
Package=<3>

View File

@ -13,12 +13,15 @@
*
****/
//
// util.h
// cl_util.h
//
#include <windows.h>
#include "cvardef.h"
#include "../engine/cvardef.h"
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
// Macros to hook function calls into the HUD object
#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x );
@ -37,7 +40,7 @@
inline float CVAR_GET_FLOAT( const char *x ) { return gEngfuncs.pfnGetCvarFloat( (char*)x ); }
inline char* CVAR_GET_STRING( const char *x ) { return gEngfuncs.pfnGetCvarString( (char*)x ); }
inline void CVAR_CREATE( const char *cv, const char *val, const int flags ) { gEngfuncs.pfnRegisterVariable( (char*)cv, (char*)val, flags ); }
inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int flags ) { return gEngfuncs.pfnRegisterVariable( (char*)cv, (char*)val, flags ); }
#define SPR_Load (*gEngfuncs.pfnSPR_Load)
#define SPR_Set (*gEngfuncs.pfnSPR_Set)
@ -125,6 +128,14 @@ void ScaleColors( int &r, int &g, int &b, int a );
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
#define VectorClear(a) { a[0]=0.0;a[1]=0.0;a[2]=0.0;}
float Length(const float *v);
void VectorMA (const float *veca, float scale, const float *vecb, float *vecc);
void VectorScale (const float *in, float scale, float *out);
float VectorNormalize (float *v);
void VectorInverse ( float *v );
extern vec3_t vec3_origin;
// disable 'possible loss of data converting float to int' warning message
#pragma warning( disable: 4244 )

277
cl_dll/com_weapons.cpp Normal file
View File

@ -0,0 +1,277 @@
/***
*
* 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.
*
****/
// Com_Weapons.cpp
// Shared weapons common/shared functions
#include <stdarg.h>
#include "hud.h"
#include "cl_util.h"
#include "com_weapons.h"
#include "const.h"
#include "entity_state.h"
#include "r_efx.h"
// g_runfuncs is true if this is the first time we've "predicated" a particular movement/firing
// command. If it is 1, then we should play events/sounds etc., otherwise, we just will be
// updating state info, but not firing events
int g_runfuncs = 0;
// During our weapon prediction processing, we'll need to reference some data that is part of
// the final state passed into the postthink functionality. We'll set this pointer and then
// reset it to NULL as appropriate
struct local_state_s *g_finalstate = NULL;
/*
====================
COM_Log
Log debug messages to file ( appends )
====================
*/
void COM_Log( char *pszFile, char *fmt, ...)
{
va_list argptr;
char string[1024];
FILE *fp;
char *pfilename;
if ( !pszFile )
{
pfilename = "c:\\hllog.txt";
}
else
{
pfilename = pszFile;
}
va_start (argptr,fmt);
vsprintf (string, fmt,argptr);
va_end (argptr);
fp = fopen( pfilename, "a+t");
if (fp)
{
fprintf(fp, "%s", string);
fclose(fp);
}
}
// remember the current animation for the view model, in case we get out of sync with
// server.
static int g_currentanim;
/*
=====================
HUD_SendWeaponAnim
Change weapon model animation
=====================
*/
void HUD_SendWeaponAnim( int iAnim, int body, int force )
{
// Don't actually change it.
if ( !g_runfuncs && !force )
return;
g_currentanim = iAnim;
// Tell animation system new info
gEngfuncs.pfnWeaponAnim( iAnim, body );
}
/*
=====================
HUD_GetWeaponAnim
Retrieve current predicted weapon animation
=====================
*/
int HUD_GetWeaponAnim( void )
{
return g_currentanim;
}
/*
=====================
HUD_PlaySound
Play a sound, if we are seeing this command for the first time
=====================
*/
void HUD_PlaySound( char *sound, float volume )
{
if ( !g_runfuncs || !g_finalstate )
return;
gEngfuncs.pfnPlaySoundByNameAtLocation( sound, volume, (float *)&g_finalstate->playerstate.origin );
}
/*
=====================
HUD_PlaybackEvent
Directly queue up an event on the client
=====================
*/
void HUD_PlaybackEvent( int flags, const edict_t *pInvoker, unsigned short eventindex, float delay,
float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 )
{
vec3_t org;
vec3_t ang;
if ( !g_runfuncs || !g_finalstate )
return;
// Weapon prediction events are assumed to occur at the player's origin
org = g_finalstate->playerstate.origin;
ang = v_angles;
gEngfuncs.pfnPlaybackEvent( flags, pInvoker, eventindex, delay, (float *)&org, (float *)&ang, fparam1, fparam2, iparam1, iparam2, bparam1, bparam2 );
}
/*
=====================
HUD_SetMaxSpeed
=====================
*/
void HUD_SetMaxSpeed( const edict_t *ed, float speed )
{
}
/*
=====================
UTIL_WeaponTimeBase
Always 0.0 on client, even if not predicting weapons ( won't get called
in that case )
=====================
*/
float UTIL_WeaponTimeBase( void )
{
return 0.0;
}
static unsigned int glSeed = 0;
unsigned int seed_table[ 256 ] =
{
28985, 27138, 26457, 9451, 17764, 10909, 28790, 8716, 6361, 4853, 17798, 21977, 19643, 20662, 10834, 20103,
27067, 28634, 18623, 25849, 8576, 26234, 23887, 18228, 32587, 4836, 3306, 1811, 3035, 24559, 18399, 315,
26766, 907, 24102, 12370, 9674, 2972, 10472, 16492, 22683, 11529, 27968, 30406, 13213, 2319, 23620, 16823,
10013, 23772, 21567, 1251, 19579, 20313, 18241, 30130, 8402, 20807, 27354, 7169, 21211, 17293, 5410, 19223,
10255, 22480, 27388, 9946, 15628, 24389, 17308, 2370, 9530, 31683, 25927, 23567, 11694, 26397, 32602, 15031,
18255, 17582, 1422, 28835, 23607, 12597, 20602, 10138, 5212, 1252, 10074, 23166, 19823, 31667, 5902, 24630,
18948, 14330, 14950, 8939, 23540, 21311, 22428, 22391, 3583, 29004, 30498, 18714, 4278, 2437, 22430, 3439,
28313, 23161, 25396, 13471, 19324, 15287, 2563, 18901, 13103, 16867, 9714, 14322, 15197, 26889, 19372, 26241,
31925, 14640, 11497, 8941, 10056, 6451, 28656, 10737, 13874, 17356, 8281, 25937, 1661, 4850, 7448, 12744,
21826, 5477, 10167, 16705, 26897, 8839, 30947, 27978, 27283, 24685, 32298, 3525, 12398, 28726, 9475, 10208,
617, 13467, 22287, 2376, 6097, 26312, 2974, 9114, 21787, 28010, 4725, 15387, 3274, 10762, 31695, 17320,
18324, 12441, 16801, 27376, 22464, 7500, 5666, 18144, 15314, 31914, 31627, 6495, 5226, 31203, 2331, 4668,
12650, 18275, 351, 7268, 31319, 30119, 7600, 2905, 13826, 11343, 13053, 15583, 30055, 31093, 5067, 761,
9685, 11070, 21369, 27155, 3663, 26542, 20169, 12161, 15411, 30401, 7580, 31784, 8985, 29367, 20989, 14203,
29694, 21167, 10337, 1706, 28578, 887, 3373, 19477, 14382, 675, 7033, 15111, 26138, 12252, 30996, 21409,
25678, 18555, 13256, 23316, 22407, 16727, 991, 9236, 5373, 29402, 6117, 15241, 27715, 19291, 19888, 19847
};
unsigned int U_Random( void )
{
glSeed *= 69069;
glSeed += seed_table[ glSeed & 0xff ];
return ( ++glSeed & 0x0fffffff );
}
void U_Srand( unsigned int seed )
{
glSeed = seed_table[ seed & 0xff ];
}
/*
=====================
UTIL_SharedRandomLong
=====================
*/
int UTIL_SharedRandomLong( unsigned int seed, int low, int high )
{
unsigned int range;
U_Srand( (int)seed + low + high );
range = high - low + 1;
if ( !(range - 1) )
{
return low;
}
else
{
int offset;
int rnum;
rnum = U_Random();
offset = rnum % range;
return (low + offset);
}
}
/*
=====================
UTIL_SharedRandomFloat
=====================
*/
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high )
{
//
unsigned int range;
U_Srand( (int)seed + *(int *)&low + *(int *)&high );
U_Random();
U_Random();
range = high - low;
if ( !range )
{
return low;
}
else
{
int tensixrand;
float offset;
tensixrand = U_Random() & 65535;
offset = (float)tensixrand / 65536.0;
return (low + offset * range );
}
}
/*
======================
stub_*
stub functions for such things as precaching. So we don't have to modify weapons code that
is compiled into both game and client .dlls.
======================
*/
int stub_PrecacheModel ( char* s ) { return 0; }
int stub_PrecacheSound ( char* s ) { return 0; }
unsigned short stub_PrecacheEvent ( int type, const char *s ) { return 0; }
const char *stub_NameForFunction ( unsigned long function ) { return "func"; }
void stub_SetModel ( edict_t *e, const char *m ) {}

41
cl_dll/com_weapons.h Normal file
View File

@ -0,0 +1,41 @@
// com_weapons.h
// Shared weapons common function prototypes
#if !defined( COM_WEAPONSH )
#define COM_WEAPONSH
#ifdef _WIN32
#pragma once
#endif
#include "hud_iface.h"
extern "C"
{
void _DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed );
}
void COM_Log( char *pszFile, char *fmt, ...);
int CL_IsDead( void );
float UTIL_SharedRandomFloat( unsigned int seed, float low, float high );
int UTIL_SharedRandomLong( unsigned int seed, int low, int high );
int HUD_GetWeaponAnim( void );
void HUD_SendWeaponAnim( int iAnim, int body, int force );
void HUD_PlaySound( char *sound, float volume );
void HUD_PlaybackEvent( int flags, const struct edict_s *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
void HUD_SetMaxSpeed( const struct edict_s *ed, float speed );
int stub_PrecacheModel( char* s );
int stub_PrecacheSound( char* s );
unsigned short stub_PrecacheEvent( int type, const char *s );
const char *stub_NameForFunction ( unsigned long function );
void stub_SetModel ( struct edict_s *e, const char *m );
extern cvar_t *cl_lw;
extern int g_runfuncs;
extern vec3_t v_angles;
extern float g_lastFOV;
extern struct local_state_s *g_finalstate;
#endif

View File

@ -16,22 +16,26 @@
// death notice
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
#include "vgui_TeamFortressViewport.h"
DECLARE_MESSAGE( m_DeathNotice, DeathMsg );
struct DeathNoticeItem {
char szKiller[MAX_PLAYER_NAME_LENGTH];
char szVictim[MAX_PLAYER_NAME_LENGTH];
char szKiller[MAX_PLAYER_NAME_LENGTH*2];
char szVictim[MAX_PLAYER_NAME_LENGTH*2];
int iId; // the index number of the associated sprite
int iSuicide;
int iTeamKill;
int iNonPlayerKill;
float flDisplayTime;
float *KillerColor;
float *VictimColor;
};
#define MAX_DEATHNOTICES 4
@ -41,6 +45,23 @@ static int DEATHNOTICE_DISPLAY_TIME = 6;
DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ];
float g_ColorBlue[3] = { 0.6, 0.8, 1.0 };
float g_ColorRed[3] = { 1.0, 0.25, 0.25 };
float g_ColorGreen[3] = { 0.6, 1.0, 0.6 };
float g_ColorYellow[3] = { 1.0, 0.7, 0.0 };
float *GetClientColor( int clientIndex )
{
switch ( g_PlayerExtraInfo[clientIndex].teamnumber )
{
case 1: return g_ColorBlue;
case 2: return g_ColorRed;
case 3: return g_ColorYellow;
case 4: return g_ColorGreen;
}
return NULL;
}
int CHudDeathNotice :: Init( void )
{
@ -86,35 +107,45 @@ int CHudDeathNotice :: Draw( float flTime )
rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME );
// Draw the death notice
y = DEATHNOTICE_TOP + (20 * i); //!!!
int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
if ( !rgDeathNoticeList[i].iSuicide )
// Only draw if the viewport will let me
if ( gViewPort && gViewPort->AllowedToPrintText() )
{
x -= (5 + ConsoleStringLen( rgDeathNoticeList[i].szKiller ) );
// Draw the death notice
y = DEATHNOTICE_TOP + (20 * i); //!!!
// Draw killers name
x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId;
x = ScreenWidth - ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
if ( !rgDeathNoticeList[i].iSuicide )
{
x -= (5 + ConsoleStringLen( rgDeathNoticeList[i].szKiller ) );
// Draw killers name
if ( rgDeathNoticeList[i].KillerColor )
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] );
x = 5 + DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller );
}
r = 255; g = 80; b = 0;
if ( rgDeathNoticeList[i].iTeamKill )
{
r = 10; g = 240; b = 10; // display it in sickly green
}
// Draw death weapon
SPR_Set( gHUD.GetSprite(id), r, g, b );
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(id) );
x += (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
// Draw victims name (if it was a player that was killed)
if (rgDeathNoticeList[i].iNonPlayerKill == FALSE)
{
if ( rgDeathNoticeList[i].VictimColor )
gEngfuncs.pfnDrawSetTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] );
x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
}
}
r = 255; g = 80; b = 0;
if ( rgDeathNoticeList[i].iTeamKill )
{
r = 10; g = 240; b = 10; // display it in sickly green
}
// Draw death weapon
SPR_Set( gHUD.GetSprite(id), r, g, b );
SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(id) );
x += (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left);
// Draw victims name
x = DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim );
}
return 1;
@ -134,7 +165,8 @@ int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *p
strcpy( killedwith, "d_" );
strncat( killedwith, READ_STRING(), 32 );
gHUD.m_Scoreboard.DeathMsg( killer, victim );
if (gViewPort)
gViewPort->DeathMsg( killer, victim );
for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
{
@ -147,23 +179,56 @@ int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *p
i = MAX_DEATHNOTICES - 1;
}
gHUD.m_Scoreboard.GetAllPlayersInfo();
if (gViewPort)
gViewPort->GetAllPlayersInfo();
char *killer_name = gHUD.m_Scoreboard.m_PlayerInfoList[ killer ].name;
char *victim_name = gHUD.m_Scoreboard.m_PlayerInfoList[ victim ].name;
// Get the Killer's name
char *killer_name = g_PlayerInfoList[ killer ].name;
if ( !killer_name )
{
killer_name = "";
rgDeathNoticeList[i].szKiller[0] = 0;
}
else
{
rgDeathNoticeList[i].KillerColor = GetClientColor( killer );
strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
rgDeathNoticeList[i].szKiller[MAX_PLAYER_NAME_LENGTH-1] = 0;
}
// Get the Victim's name
char *victim_name = NULL;
// If victim is -1, the killer killed a specific, non-player object (like a sentrygun)
if ( ((char)victim) != -1 )
victim_name = g_PlayerInfoList[ victim ].name;
if ( !victim_name )
{
victim_name = "";
rgDeathNoticeList[i].szVictim[0] = 0;
}
else
{
rgDeathNoticeList[i].VictimColor = GetClientColor( victim );
strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
rgDeathNoticeList[i].szVictim[MAX_PLAYER_NAME_LENGTH-1] = 0;
}
strncpy( rgDeathNoticeList[i].szKiller, killer_name, MAX_PLAYER_NAME_LENGTH );
strncpy( rgDeathNoticeList[i].szVictim, victim_name, MAX_PLAYER_NAME_LENGTH );
// Is it a non-player object kill?
if ( ((char)victim) == -1 )
{
rgDeathNoticeList[i].iNonPlayerKill = TRUE;
if ( killer == victim || killer == 0 )
rgDeathNoticeList[i].iSuicide = TRUE;
// Store the object's name in the Victim slot (skip the d_ bit)
strcpy( rgDeathNoticeList[i].szVictim, killedwith+2 );
}
else
{
if ( killer == victim || killer == 0 )
rgDeathNoticeList[i].iSuicide = TRUE;
if ( !strcmp( killedwith, "d_teammate" ) )
rgDeathNoticeList[i].iTeamKill = TRUE;
if ( !strcmp( killedwith, "d_teammate" ) )
rgDeathNoticeList[i].iTeamKill = TRUE;
}
// Find the sprite in the list
int spr = gHUD.GetSpriteIndex( killedwith );
@ -173,48 +238,58 @@ int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *p
DEATHNOTICE_DISPLAY_TIME = CVAR_GET_FLOAT( "hud_deathnotice_time" );
rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME;
// record the death notice in the console
if ( rgDeathNoticeList[i].iSuicide )
{
ConsolePrint( rgDeathNoticeList[i].szVictim );
if ( !strcmp( killedwith, "d_world" ) )
{
ConsolePrint( " died" );
}
else
{
ConsolePrint( " killed self" );
}
}
else if ( rgDeathNoticeList[i].iTeamKill )
if (rgDeathNoticeList[i].iNonPlayerKill)
{
ConsolePrint( rgDeathNoticeList[i].szKiller );
ConsolePrint( " killed his teammate " );
ConsolePrint( " killed a " );
ConsolePrint( rgDeathNoticeList[i].szVictim );
ConsolePrint( "\n" );
}
else
{
ConsolePrint( rgDeathNoticeList[i].szKiller );
ConsolePrint( " killed " );
ConsolePrint( rgDeathNoticeList[i].szVictim );
// record the death notice in the console
if ( rgDeathNoticeList[i].iSuicide )
{
ConsolePrint( rgDeathNoticeList[i].szVictim );
if ( !strcmp( killedwith, "d_world" ) )
{
ConsolePrint( " died" );
}
else
{
ConsolePrint( " killed self" );
}
}
else if ( rgDeathNoticeList[i].iTeamKill )
{
ConsolePrint( rgDeathNoticeList[i].szKiller );
ConsolePrint( " killed his teammate " );
ConsolePrint( rgDeathNoticeList[i].szVictim );
}
else
{
ConsolePrint( rgDeathNoticeList[i].szKiller );
ConsolePrint( " killed " );
ConsolePrint( rgDeathNoticeList[i].szVictim );
}
if ( killedwith && *killedwith && (*killedwith > 13 ) && strcmp( killedwith, "d_world" ) && !rgDeathNoticeList[i].iTeamKill )
{
ConsolePrint( " with " );
// replace the code names with the 'real' names
if ( !strcmp( killedwith+2, "egon" ) )
strcpy( killedwith, "d_gluon gun" );
if ( !strcmp( killedwith+2, "gauss" ) )
strcpy( killedwith, "d_tau cannon" );
ConsolePrint( killedwith+2 ); // skip over the "d_" part
}
ConsolePrint( "\n" );
}
if ( killedwith && *killedwith && (*killedwith > 13 ) && strcmp( killedwith, "d_world" ) && !rgDeathNoticeList[i].iTeamKill )
{
ConsolePrint( " with " );
// replace the code names with the 'real' names
if ( !strcmp( killedwith+2, "egon" ) )
strcpy( killedwith, "d_gluon gun" );
if ( !strcmp( killedwith+2, "gauss" ) )
strcpy( killedwith, "d_tau cannon" );
ConsolePrint( killedwith+2 ); // skip over the "d_" part
}
ConsolePrint( "\n" );
return 1;
}

103
cl_dll/demo.cpp Normal file
View File

@ -0,0 +1,103 @@
/***
*
* 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.
*
****/
#include "hud.h"
#include "cl_util.h"
#include "demo.h"
#include "demo_api.h"
#include <memory.h>
#define DLLEXPORT __declspec( dllexport )
int g_demosniper = 0;
int g_demosniperdamage = 0;
float g_demosniperorg[3];
float g_demosniperangles[3];
float g_demozoom;
// FIXME: There should be buffer helper functions to avoid all of the *(int *)& crap.
extern "C"
{
void DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer );
}
/*
=====================
Demo_WriteBuffer
Write some data to the demo stream
=====================
*/
void Demo_WriteBuffer( int type, int size, unsigned char *buffer )
{
int pos = 0;
unsigned char buf[ 32 * 1024 ];
*( int * )&buf[pos] = type;
pos+=sizeof( int );
memcpy( &buf[pos], buffer, size );
// Write full buffer out
gEngfuncs.pDemoAPI->WriteBuffer( size + sizeof( int ), buf );
}
/*
=====================
Demo_ReadBuffer
Engine wants us to parse some data from the demo stream
=====================
*/
void DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer )
{
int type;
int i = 0;
type = *( int * )buffer;
i += sizeof( int );
switch ( type )
{
case TYPE_SNIPERDOT:
g_demosniper = *(int * )&buffer[ i ];
i += sizeof( int );
if ( g_demosniper )
{
g_demosniperdamage = *( int * )&buffer[ i ];
i += sizeof( int );
g_demosniperangles[ 0 ] = *(float *)&buffer[i];
i += sizeof( float );
g_demosniperangles[ 1 ] = *(float *)&buffer[i];
i += sizeof( float );
g_demosniperangles[ 2 ] = *(float *)&buffer[i];
i += sizeof( float );
g_demosniperorg[ 0 ] = *(float *)&buffer[i];
i += sizeof( float );
g_demosniperorg[ 1 ] = *(float *)&buffer[i];
i += sizeof( float );
g_demosniperorg[ 2 ] = *(float *)&buffer[i];
i += sizeof( float );
}
break;
case TYPE_ZOOM:
g_demozoom = *(float * )&buffer[ i ];
i += sizeof( float );
break;
default:
gEngfuncs.Con_DPrintf( "Unknown demo buffer type, skipping.\n" );
break;
}
}

20
cl_dll/demo.h Normal file
View File

@ -0,0 +1,20 @@
#if !defined( DEMOH )
#define DEMOH
#pragma once
// Types of demo messages we can write/parse
enum
{
TYPE_SNIPERDOT = 0,
TYPE_ZOOM
};
void Demo_WriteBuffer( int type, int size, unsigned char *buffer );
extern int g_demosniper;
extern int g_demosniperdamage;
extern float g_demosniperorg[3];
extern float g_demosniperangles[3];
extern float g_demozoom;
#endif

914
cl_dll/entity.cpp Normal file
View File

@ -0,0 +1,914 @@
// Client side entity management functions
#include <memory.h>
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "entity_types.h"
#include "studio_event.h" // def. of mstudioevent_t
#include "r_efx.h"
#include "event_api.h"
#include "pm_defs.h"
#include "pmtrace.h"
#define DLLEXPORT __declspec( dllexport )
void Game_AddObjects( void );
extern vec3_t v_origin;
extern "C"
{
int DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname );
void DLLEXPORT HUD_CreateEntities( void );
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
void DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client );
void DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src );
void DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd );
void DLLEXPORT HUD_TempEntUpdate( double frametime, double client_time, double cl_gravity, struct tempent_s **ppTempEntFree, struct tempent_s **ppTempEntActive, int ( *Callback_AddVisibleEntity )( struct cl_entity_s *pEntity ), void ( *Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp ) );
struct cl_entity_s DLLEXPORT *HUD_GetUserEntity( int index );
}
/*
========================
HUD_AddEntity
Return 0 to filter entity from visible list for rendering
========================
*/
int DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname )
{
switch ( type )
{
case ET_NORMAL:
case ET_PLAYER:
case ET_BEAM:
case ET_TEMPENTITY:
case ET_FRAGMENTED:
default:
break;
}
return 1;
}
/*
=========================
HUD_TxferLocalOverrides
The server sends us our origin with extra precision as part of the clientdata structure, not during the normal
playerstate update in entity_state_t. In order for these overrides to eventually get to the appropriate playerstate
structure, we need to copy them into the state structure at this point.
=========================
*/
void DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client )
{
VectorCopy( client->origin, state->origin );
// Spectator
state->iuser1 = client->iuser1;
state->iuser2 = client->iuser2;
}
/*
=========================
HUD_ProcessPlayerState
We have received entity_state_t for this player over the network. We need to copy appropriate fields to the
playerstate structure
=========================
*/
void DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src )
{
// Copy in network data
VectorCopy( src->origin, dst->origin );
VectorCopy( src->angles, dst->angles );
VectorCopy( src->velocity, dst->velocity );
dst->frame = src->frame;
dst->modelindex = src->modelindex;
dst->skin = src->skin;
dst->effects = src->effects;
dst->weaponmodel = src->weaponmodel;
dst->movetype = src->movetype;
dst->sequence = src->sequence;
dst->animtime = src->animtime;
dst->solid = src->solid;
dst->rendermode = src->rendermode;
dst->renderamt = src->renderamt;
dst->rendercolor.r = src->rendercolor.r;
dst->rendercolor.g = src->rendercolor.g;
dst->rendercolor.b = src->rendercolor.b;
dst->renderfx = src->renderfx;
dst->framerate = src->framerate;
dst->body = src->body;
memcpy( &dst->controller[0], &src->controller[0], 4 * sizeof( byte ) );
memcpy( &dst->blending[0], &src->blending[0], 2 * sizeof( byte ) );
VectorCopy( src->basevelocity, dst->basevelocity );
dst->friction = src->friction;
dst->gravity = src->gravity;
dst->gaitsequence = src->gaitsequence;
dst->spectator = src->spectator;
dst->usehull = src->usehull;
dst->playerclass = src->playerclass;
dst->team = src->team;
dst->colormap = src->colormap;
// Save off some data so other areas of the Client DLL can get to it
cl_entity_t *player = gEngfuncs.GetLocalPlayer(); // Get the local player's index
if ( dst->number == player->index )
{
g_iPlayerClass = dst->playerclass;
g_iTeamNumber = dst->team;
g_iUser1 = src->iuser1;
g_iUser2 = src->iuser2;
}
}
/*
=========================
HUD_TxferPredictionData
Because we can predict an arbitrary number of frames before the server responds with an update, we need to be able to copy client side prediction data in
from the state that the server ack'd receiving, which can be anywhere along the predicted frame path ( i.e., we could predict 20 frames into the future and the server ack's
up through 10 of those frames, so we need to copy persistent client-side only state from the 10th predicted frame to the slot the server
update is occupying.
=========================
*/
void DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd )
{
ps->oldbuttons = pps->oldbuttons;
ps->flFallVelocity = pps->flFallVelocity;
ps->iStepLeft = pps->iStepLeft;
ps->playerclass = pps->playerclass;
pcd->viewmodel = ppcd->viewmodel;
pcd->m_iId = ppcd->m_iId;
pcd->ammo_shells = ppcd->ammo_shells;
pcd->ammo_nails = ppcd->ammo_nails;
pcd->ammo_cells = ppcd->ammo_cells;
pcd->ammo_rockets = ppcd->ammo_rockets;
pcd->m_flNextAttack = ppcd->m_flNextAttack;
pcd->fov = ppcd->fov;
pcd->weaponanim = ppcd->weaponanim;
pcd->tfstate = ppcd->tfstate;
pcd->maxspeed = ppcd->maxspeed;
pcd->deadflag = ppcd->deadflag;
// Spectator
pcd->iuser1 = ppcd->iuser1;
pcd->iuser2 = ppcd->iuser2;
memcpy( wd, pwd, 32 * sizeof( weapon_data_t ) );
}
/*
//#define TEST_IT
#if defined( TEST_IT )
cl_entity_t mymodel[9];
void MoveModel( void )
{
cl_entity_t *player;
int i, j;
int modelindex;
struct model_s *mod;
// Load it up with some bogus data
player = gEngfuncs.GetLocalPlayer();
if ( !player )
return;
mod = gEngfuncs.CL_LoadModel( "models/sentry3.mdl", &modelindex );
for ( i = 0; i < 3; i++ )
{
for ( j = 0; j < 3; j++ )
{
// Don't draw over ourself...
if ( ( i == 1 ) && ( j == 1 ) )
continue;
mymodel[ i * 3 + j ] = *player;
mymodel[ i * 3 + j ].player = 0;
mymodel[ i * 3 + j ].model = mod;
mymodel[ i * 3 + j ].curstate.modelindex = modelindex;
// Move it out a bit
mymodel[ i * 3 + j ].origin[0] = player->origin[0] + 50 * ( 1 - i );
mymodel[ i * 3 + j ].origin[1] = player->origin[1] + 50 * ( 1 - j );
gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, &mymodel[i*3+j] );
}
}
}
#endif
//#define TRACE_TEST
#if defined( TRACE_TEST )
extern int hitent;
cl_entity_t hit;
void TraceModel( void )
{
cl_entity_t *ent;
if ( hitent <= 0 )
return;
// Load it up with some bogus data
ent = gEngfuncs.GetEntityByIndex( hitent );
if ( !ent )
return;
hit = *ent;
//hit.curstate.rendermode = kRenderTransTexture;
//hit.curstate.renderfx = kRenderFxGlowShell;
//hit.curstate.renderamt = 100;
hit.origin[2] += 40;
gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, &hit );
}
#endif
*/
/*
void ParticleCallback( struct particle_s *particle, float frametime )
{
int i;
for ( i = 0; i < 3; i++ )
{
particle->org[ i ] += particle->vel[ i ] * frametime;
}
}
cvar_t *color = NULL;
void Particles( void )
{
static float lasttime;
float curtime;
curtime = gEngfuncs.GetClientTime();
if ( ( curtime - lasttime ) < 2.0 )
return;
if ( !color )
{
color = gEngfuncs.pfnRegisterVariable ( "color","255 0 0", 0 );
}
lasttime = curtime;
// Create a few particles
particle_t *p;
int i, j;
for ( i = 0; i < 1000; i++ )
{
int r, g, b;
p = gEngfuncs.pEfxAPI->R_AllocParticle( ParticleCallback );
if ( !p )
break;
for ( j = 0; j < 3; j++ )
{
p->org[ j ] = v_origin[ j ] + gEngfuncs.pfnRandomFloat( -32.0, 32.0 );;
p->vel[ j ] = gEngfuncs.pfnRandomFloat( -100.0, 100.0 );
}
if ( color )
{
sscanf( color->string, "%i %i %i", &r, &g, &b );
}
else
{
r = 192;
g = 0;
b = 0;
}
p->color = gEngfuncs.pEfxAPI->R_LookupColor( r, g, b );
gEngfuncs.pEfxAPI->R_GetPackedColor( &p->packedColor, p->color );
// p->die is set to current time so all you have to do is add an additional time to it
p->die += 3.0;
}
}
*/
/*
void TempEntCallback ( struct tempent_s *ent, float frametime, float currenttime )
{
int i;
for ( i = 0; i < 3; i++ )
{
ent->entity.curstate.origin[ i ] += ent->entity.baseline.origin[ i ] * frametime;
}
}
void TempEnts( void )
{
static float lasttime;
float curtime;
curtime = gEngfuncs.GetClientTime();
if ( ( curtime - lasttime ) < 10.0 )
return;
lasttime = curtime;
TEMPENTITY *p;
int i, j;
struct model_s *mod;
vec3_t origin;
int index;
mod = gEngfuncs.CL_LoadModel( "sprites/laserdot.spr", &index );
for ( i = 0; i < 100; i++ )
{
for ( j = 0; j < 3; j++ )
{
origin[ j ] = v_origin[ j ];
if ( j != 2 )
{
origin[ j ] += 75;
}
}
p = gEngfuncs.pEfxAPI->CL_TentEntAllocCustom( (float *)&origin, mod, 0, TempEntCallback );
if ( !p )
break;
for ( j = 0; j < 3; j++ )
{
p->entity.curstate.origin[ j ] = origin[ j ];
// Store velocity in baseline origin
p->entity.baseline.origin[ j ] = gEngfuncs.pfnRandomFloat( -100, 100 );
}
// p->die is set to current time so all you have to do is add an additional time to it
p->die += 10.0;
}
}
*/
#if defined( BEAM_TEST )
// Note can't index beam[ 0 ] in Beam callback, so don't use that index
// Room for 1 beam ( 0 can't be used )
static cl_entity_t beams[ 2 ];
void BeamEndModel( void )
{
cl_entity_t *player, *model;
int modelindex;
struct model_s *mod;
// Load it up with some bogus data
player = gEngfuncs.GetLocalPlayer();
if ( !player )
return;
mod = gEngfuncs.CL_LoadModel( "models/sentry3.mdl", &modelindex );
if ( !mod )
return;
// Slot 1
model = &beams[ 1 ];
*model = *player;
model->player = 0;
model->model = mod;
model->curstate.modelindex = modelindex;
// Move it out a bit
model->origin[0] = player->origin[0] - 100;
model->origin[1] = player->origin[1];
model->attachment[0] = model->origin;
model->attachment[1] = model->origin;
model->attachment[2] = model->origin;
model->attachment[3] = model->origin;
gEngfuncs.CL_CreateVisibleEntity( ET_NORMAL, model );
}
void Beams( void )
{
static float lasttime;
float curtime;
struct model_s *mod;
int index;
BeamEndModel();
curtime = gEngfuncs.GetClientTime();
float end[ 3 ];
if ( ( curtime - lasttime ) < 10.0 )
return;
mod = gEngfuncs.CL_LoadModel( "sprites/laserbeam.spr", &index );
if ( !mod )
return;
lasttime = curtime;
end [ 0 ] = v_origin.x + 100;
end [ 1 ] = v_origin.y + 100;
end [ 2 ] = v_origin.z;
BEAM *p1;
p1 = gEngfuncs.pEfxAPI->R_BeamEntPoint( -1, end, index,
10.0, 2.0, 0.3, 1.0, 5.0, 0.0, 1.0, 1.0, 1.0, 1.0 );
}
#endif
/*
=========================
HUD_CreateEntities
Gives us a chance to add additional entities to the render this frame
=========================
*/
void DLLEXPORT HUD_CreateEntities( void )
{
// e.g., create a persistent cl_entity_t somewhere.
// Load an appropriate model into it ( gEngfuncs.CL_LoadModel )
// Call gEngfuncs.CL_CreateVisibleEntity to add it to the visedicts list
/*
#if defined( TEST_IT )
MoveModel();
#endif
#if defined( TRACE_TEST )
TraceModel();
#endif
*/
/*
Particles();
*/
/*
TempEnts();
*/
#if defined( BEAM_TEST )
Beams();
#endif
// Add in any game specific objects
Game_AddObjects();
}
/*
=========================
HUD_StudioEvent
The entity's studio model description indicated an event was
fired during this frame, handle the event by it's tag ( e.g., muzzleflash, sound )
=========================
*/
void DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity )
{
switch( event->event )
{
case 5001:
gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[0], atoi( event->options) );
break;
case 5011:
gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[1], atoi( event->options) );
break;
case 5021:
gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[2], atoi( event->options) );
break;
case 5031:
gEngfuncs.pEfxAPI->R_MuzzleFlash( (float *)&entity->attachment[3], atoi( event->options) );
break;
case 5002:
gEngfuncs.pEfxAPI->R_SparkEffect( (float *)&entity->attachment[0], atoi( event->options), -100, 100 );
break;
// Client side sound
case 5004:
gEngfuncs.pfnPlaySoundByNameAtLocation( (char *)event->options, 1.0, (float *)&entity->attachment[0] );
break;
default:
break;
}
}
/*
=================
CL_UpdateTEnts
Simulation and cleanup of temporary entities
=================
*/
void DLLEXPORT HUD_TempEntUpdate (
double frametime, // Simulation time
double client_time, // Absolute time on client
double cl_gravity, // True gravity on client
TEMPENTITY **ppTempEntFree, // List of freed temporary ents
TEMPENTITY **ppTempEntActive, // List
int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ),
void ( *Callback_TempEntPlaySound )( TEMPENTITY *pTemp, float damp ) )
{
static int gTempEntFrame = 0;
int i;
TEMPENTITY *pTemp, *pnext, *pprev;
float freq, gravity, gravitySlow, life, fastFreq;
// Nothing to simulate
if ( !*ppTempEntActive )
return;
// in order to have tents collide with players, we have to run the player prediction code so
// that the client has the player list. We run this code once when we detect any COLLIDEALL
// tent, then set this BOOL to true so the code doesn't get run again if there's more than
// one COLLIDEALL ent for this update. (often are).
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( -1 );
// !!!BUGBUG -- This needs to be time based
gTempEntFrame = (gTempEntFrame+1) & 31;
pTemp = *ppTempEntActive;
// !!! Don't simulate while paused.... This is sort of a hack, revisit.
if ( frametime <= 0 )
{
while ( pTemp )
{
if ( !(pTemp->flags & FTENT_NOMODEL ) )
{
Callback_AddVisibleEntity( &pTemp->entity );
}
pTemp = pTemp->next;
}
goto finish;
}
pprev = NULL;
freq = client_time * 0.01;
fastFreq = client_time * 5.5;
gravity = -frametime * cl_gravity;
gravitySlow = gravity * 0.5;
while ( pTemp )
{
int active;
active = 1;
life = pTemp->die - client_time;
pnext = pTemp->next;
if ( life < 0 )
{
if ( pTemp->flags & FTENT_FADEOUT )
{
if (pTemp->entity.curstate.rendermode == kRenderNormal)
pTemp->entity.curstate.rendermode = kRenderTransTexture;
pTemp->entity.curstate.renderamt = pTemp->entity.baseline.renderamt * ( 1 + life * pTemp->fadeSpeed );
if ( pTemp->entity.curstate.renderamt <= 0 )
active = 0;
}
else
active = 0;
}
if ( !active ) // Kill it
{
pTemp->next = *ppTempEntFree;
*ppTempEntFree = pTemp;
if ( !pprev ) // Deleting at head of list
*ppTempEntActive = pnext;
else
pprev->next = pnext;
}
else
{
pprev = pTemp;
VectorCopy( pTemp->entity.origin, pTemp->entity.prevstate.origin );
if ( pTemp->flags & FTENT_SPARKSHOWER )
{
// Adjust speed if it's time
// Scale is next think time
if ( client_time > pTemp->entity.baseline.scale )
{
// Show Sparks
gEngfuncs.pEfxAPI->R_SparkEffect( pTemp->entity.origin, 8, -200, 200 );
// Reduce life
pTemp->entity.baseline.framerate -= 0.1;
if ( pTemp->entity.baseline.framerate <= 0.0 )
{
pTemp->die = client_time;
}
else
{
// So it will die no matter what
pTemp->die = client_time + 0.5;
// Next think
pTemp->entity.baseline.scale = client_time + 0.1;
}
}
}
else if ( pTemp->flags & FTENT_PLYRATTACHMENT )
{
cl_entity_t *pClient;
pClient = gEngfuncs.GetEntityByIndex( pTemp->clientIndex );
VectorAdd( pClient->origin, pTemp->tentOffset, pTemp->entity.origin );
}
else if ( pTemp->flags & FTENT_SINEWAVE )
{
pTemp->x += pTemp->entity.baseline.origin[0] * frametime;
pTemp->y += pTemp->entity.baseline.origin[1] * frametime;
pTemp->entity.origin[0] = pTemp->x + sin( pTemp->entity.baseline.origin[2] + client_time * pTemp->entity.prevstate.frame ) * (10*pTemp->entity.curstate.framerate);
pTemp->entity.origin[1] = pTemp->y + sin( pTemp->entity.baseline.origin[2] + fastFreq + 0.7 ) * (8*pTemp->entity.curstate.framerate);
pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
}
else if ( pTemp->flags & FTENT_SPIRAL )
{
float s, c;
s = sin( pTemp->entity.baseline.origin[2] + fastFreq );
c = cos( pTemp->entity.baseline.origin[2] + fastFreq );
pTemp->entity.origin[0] += pTemp->entity.baseline.origin[0] * frametime + 8 * sin( client_time * 20 + (int)pTemp );
pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (int)pTemp );
pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
}
else
{
for ( i = 0; i < 3; i++ )
pTemp->entity.origin[i] += pTemp->entity.baseline.origin[i] * frametime;
}
if ( pTemp->flags & FTENT_SPRANIMATE )
{
pTemp->entity.curstate.frame += frametime * pTemp->entity.curstate.framerate;
if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
{
pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
if ( !(pTemp->flags & FTENT_SPRANIMATELOOP) )
{
// this animating sprite isn't set to loop, so destroy it.
pTemp->die = client_time;
pTemp = pnext;
continue;
}
}
}
else if ( pTemp->flags & FTENT_SPRCYCLE )
{
pTemp->entity.curstate.frame += frametime * 10;
if ( pTemp->entity.curstate.frame >= pTemp->frameMax )
{
pTemp->entity.curstate.frame = pTemp->entity.curstate.frame - (int)(pTemp->entity.curstate.frame);
}
}
// Experiment
#if 0
if ( pTemp->flags & FTENT_SCALE )
pTemp->entity.curstate.framerate += 20.0 * (frametime / pTemp->entity.curstate.framerate);
#endif
if ( pTemp->flags & FTENT_ROTATE )
{
pTemp->entity.angles[0] += pTemp->entity.baseline.angles[0] * frametime;
pTemp->entity.angles[1] += pTemp->entity.baseline.angles[1] * frametime;
pTemp->entity.angles[2] += pTemp->entity.baseline.angles[2] * frametime;
VectorCopy( pTemp->entity.angles, pTemp->entity.latched.prevangles );
}
if ( pTemp->flags & (FTENT_COLLIDEALL | FTENT_COLLIDEWORLD) )
{
vec3_t traceNormal;
float traceFraction = 1;
if ( pTemp->flags & FTENT_COLLIDEALL )
{
pmtrace_t pmtrace;
physent_t *pe;
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX, -1, &pmtrace );
if ( pmtrace.fraction != 1 )
{
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pmtrace.ent );
if ( !pmtrace.ent || ( pe->info != pTemp->clientIndex ) )
{
traceFraction = pmtrace.fraction;
VectorCopy( pmtrace.plane.normal, traceNormal );
if ( pTemp->hitcallback )
{
(*pTemp->hitcallback)( pTemp, &pmtrace );
}
}
}
}
else if ( pTemp->flags & FTENT_COLLIDEWORLD )
{
pmtrace_t pmtrace;
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( pTemp->entity.prevstate.origin, pTemp->entity.origin, PM_STUDIO_BOX | PM_WORLD_ONLY, -1, &pmtrace );
if ( pmtrace.fraction != 1 )
{
traceFraction = pmtrace.fraction;
VectorCopy( pmtrace.plane.normal, traceNormal );
if ( pTemp->flags & FTENT_SPARKSHOWER )
{
// Chop spark speeds a bit more
//
VectorScale( pTemp->entity.baseline.origin, 0.6, pTemp->entity.baseline.origin );
if ( Length( pTemp->entity.baseline.origin ) < 10 )
{
pTemp->entity.baseline.framerate = 0.0;
}
}
if ( pTemp->hitcallback )
{
(*pTemp->hitcallback)( pTemp, &pmtrace );
}
}
}
if ( traceFraction != 1 ) // Decent collision now, and damping works
{
float proj, damp;
// Place at contact point
VectorMA( pTemp->entity.prevstate.origin, traceFraction*frametime, pTemp->entity.baseline.origin, pTemp->entity.origin );
// Damp velocity
damp = pTemp->bounceFactor;
if ( pTemp->flags & (FTENT_GRAVITY|FTENT_SLOWGRAVITY) )
{
damp *= 0.5;
if ( traceNormal[2] > 0.9 ) // Hit floor?
{
if ( pTemp->entity.baseline.origin[2] <= 0 && pTemp->entity.baseline.origin[2] >= gravity*3 )
{
damp = 0; // Stop
pTemp->flags &= ~(FTENT_ROTATE|FTENT_GRAVITY|FTENT_SLOWGRAVITY|FTENT_COLLIDEWORLD|FTENT_SMOKETRAIL);
pTemp->entity.angles[0] = 0;
pTemp->entity.angles[2] = 0;
}
}
}
if (pTemp->hitSound)
{
Callback_TempEntPlaySound(pTemp, damp);
}
if (pTemp->flags & FTENT_COLLIDEKILL)
{
// die on impact
pTemp->flags &= ~FTENT_FADEOUT;
pTemp->die = client_time;
}
else
{
// Reflect velocity
if ( damp != 0 )
{
proj = DotProduct( pTemp->entity.baseline.origin, traceNormal );
VectorMA( pTemp->entity.baseline.origin, -proj*2, traceNormal, pTemp->entity.baseline.origin );
// Reflect rotation (fake)
pTemp->entity.angles[1] = -pTemp->entity.angles[1];
}
if ( damp != 1 )
{
VectorScale( pTemp->entity.baseline.origin, damp, pTemp->entity.baseline.origin );
VectorScale( pTemp->entity.angles, 0.9, pTemp->entity.angles );
}
}
}
}
if ( (pTemp->flags & FTENT_FLICKER) && gTempEntFrame == pTemp->entity.curstate.effects )
{
dlight_t *dl = gEngfuncs.pEfxAPI->CL_AllocDlight (0);
VectorCopy (pTemp->entity.origin, dl->origin);
dl->radius = 60;
dl->color.r = 255;
dl->color.g = 120;
dl->color.b = 0;
dl->die = client_time + 0.01;
}
if ( pTemp->flags & FTENT_SMOKETRAIL )
{
gEngfuncs.pEfxAPI->R_RocketTrail (pTemp->entity.prevstate.origin, pTemp->entity.origin, 1);
}
if ( pTemp->flags & FTENT_GRAVITY )
pTemp->entity.baseline.origin[2] += gravity;
else if ( pTemp->flags & FTENT_SLOWGRAVITY )
pTemp->entity.baseline.origin[2] += gravitySlow;
if ( pTemp->flags & FTENT_CLIENTCUSTOM )
{
if ( pTemp->callback )
{
( *pTemp->callback )( pTemp, frametime, client_time );
}
}
// Cull to PVS (not frustum cull, just PVS)
if ( !(pTemp->flags & FTENT_NOMODEL ) )
{
if ( !Callback_AddVisibleEntity( &pTemp->entity ) )
{
if ( !(pTemp->flags & FTENT_PERSIST) )
{
pTemp->die = client_time; // If we can't draw it this frame, just dump it.
pTemp->flags &= ~FTENT_FADEOUT; // Don't fade out, just die
}
}
}
}
pTemp = pnext;
}
finish:
// Restore state info
gEngfuncs.pEventAPI->EV_PopPMStates();
}
/*
=================
HUD_GetUserEntity
If you specify negative numbers for beam start and end point entities, then
the engine will call back into this function requesting a pointer to a cl_entity_t
object that describes the entity to attach the beam onto.
Indices must start at 1, not zero.
=================
*/
cl_entity_t DLLEXPORT *HUD_GetUserEntity( int index )
{
#if defined( BEAM_TEST )
// None by default, you would return a valic pointer if you create a client side
// beam and attach it to a client side entity.
if ( index > 0 && index <= 1 )
{
return &beams[ index ];
}
else
{
return NULL;
}
#else
return NULL;
#endif
}

198
cl_dll/ev_common.cpp Normal file
View File

@ -0,0 +1,198 @@
/***
*
* 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.
*
****/
// shared event functions
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "r_efx.h"
#include "eventscripts.h"
#include "event_api.h"
/*
=================
GetEntity
Return's the requested cl_entity_t
=================
*/
struct cl_entity_s *GetEntity( int idx )
{
return gEngfuncs.GetEntityByIndex( idx );
}
/*
=================
GetViewEntity
Return's the current weapon/view model
=================
*/
struct cl_entity_s *GetViewEntity( void )
{
return gEngfuncs.GetViewModel();
}
/*
=================
EV_CreateTracer
Creates a tracer effect
=================
*/
void EV_CreateTracer( float *start, float *end )
{
gEngfuncs.pEfxAPI->R_TracerEffect( start, end );
}
/*
=================
EV_IsPlayer
Is the entity's index in the player range?
=================
*/
qboolean EV_IsPlayer( int idx )
{
if ( idx >= 1 && idx <= gEngfuncs.GetMaxClients() )
return true;
return false;
}
/*
=================
EV_IsLocal
Is the entity == the local player
=================
*/
qboolean EV_IsLocal( int idx )
{
return gEngfuncs.pEventAPI->EV_IsLocal( idx - 1 ) ? true : false;
}
/*
=================
EV_GetGunPosition
Figure out the height of the gun
=================
*/
void EV_GetGunPosition( event_args_t *args, float *pos, float *origin )
{
int idx;
vec3_t view_ofs;
idx = args->entindex;
VectorClear( view_ofs );
view_ofs[2] = DEFAULT_VIEWHEIGHT;
if ( EV_IsPlayer( idx ) )
{
if ( EV_IsLocal( idx ) )
{
// Grab predicted result for local player
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
}
else if ( args->ducking == 1 )
{
view_ofs[2] = VEC_DUCK_VIEW;
}
}
VectorAdd( origin, view_ofs, pos );
}
/*
=================
EV_EjectBrass
Bullet shell casings
=================
*/
void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype )
{
vec3_t endpos;
VectorClear( endpos );
endpos[1] = rotation;
gEngfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, 2.5, model, soundtype );
}
/*
=================
EV_GetDefaultShellInfo
Determine where to eject shells from
=================
*/
void EV_GetDefaultShellInfo( event_args_t *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale )
{
int i;
vec3_t view_ofs;
float fR, fU;
int idx;
idx = args->entindex;
VectorClear( view_ofs );
view_ofs[2] = DEFAULT_VIEWHEIGHT;
if ( EV_IsPlayer( idx ) )
{
if ( EV_IsLocal( idx ) )
{
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
}
else if ( args->ducking == 1 )
{
view_ofs[2] = VEC_DUCK_VIEW;
}
}
fR = gEngfuncs.pfnRandomFloat( 50, 70 );
fU = gEngfuncs.pfnRandomFloat( 100, 150 );
for ( i = 0; i < 3; i++ )
{
ShellVelocity[i] = velocity[i] + right[i] * fR + up[i] * fU + forward[i] * 25;
ShellOrigin[i] = origin[i] + view_ofs[i] + up[i] * upScale + forward[i] * forwardScale + right[i] * rightScale;
}
}
/*
=================
EV_MuzzleFlash
Flag weapon/view model for muzzle flash
=================
*/
void EV_MuzzleFlash( void )
{
// Add muzzle flash to current weapon model
cl_entity_t *ent = GetViewEntity();
if ( !ent )
{
return;
}
// Or in the muzzle flash
ent->curstate.effects |= EF_MUZZLEFLASH;
}

1112
cl_dll/ev_hldm.cpp Normal file

File diff suppressed because it is too large Load Diff

88
cl_dll/ev_hldm.h Normal file
View File

@ -0,0 +1,88 @@
#if !defined ( EV_HLDMH )
#define EV_HLDMH
// bullet types
typedef enum
{
BULLET_NONE = 0,
BULLET_PLAYER_9MM, // glock
BULLET_PLAYER_MP5, // mp5
BULLET_PLAYER_357, // python
BULLET_PLAYER_BUCKSHOT, // shotgun
BULLET_PLAYER_CROWBAR, // crowbar swipe
BULLET_MONSTER_9MM,
BULLET_MONSTER_MP5,
BULLET_MONSTER_12MM,
} Bullet;
enum glock_e {
GLOCK_IDLE1 = 0,
GLOCK_IDLE2,
GLOCK_IDLE3,
GLOCK_SHOOT,
GLOCK_SHOOT_EMPTY,
GLOCK_RELOAD,
GLOCK_RELOAD_NOT_EMPTY,
GLOCK_DRAW,
GLOCK_HOLSTER,
GLOCK_ADD_SILENCER
};
enum shotgun_e {
SHOTGUN_IDLE = 0,
SHOTGUN_FIRE,
SHOTGUN_FIRE2,
SHOTGUN_RELOAD,
SHOTGUN_PUMP,
SHOTGUN_START_RELOAD,
SHOTGUN_DRAW,
SHOTGUN_HOLSTER,
SHOTGUN_IDLE4,
SHOTGUN_IDLE_DEEP
};
enum mp5_e
{
MP5_LONGIDLE = 0,
MP5_IDLE1,
MP5_LAUNCH,
MP5_RELOAD,
MP5_DEPLOY,
MP5_FIRE1,
MP5_FIRE2,
MP5_FIRE3,
};
enum python_e {
PYTHON_IDLE1 = 0,
PYTHON_FIDGET,
PYTHON_FIRE1,
PYTHON_RELOAD,
PYTHON_HOLSTER,
PYTHON_DRAW,
PYTHON_IDLE2,
PYTHON_IDLE3
};
#define GAUSS_PRIMARY_CHARGE_VOLUME 256// how loud gauss is while charging
#define GAUSS_PRIMARY_FIRE_VOLUME 450// how loud gauss is when discharged
enum gauss_e {
GAUSS_IDLE = 0,
GAUSS_IDLE2,
GAUSS_FIDGET,
GAUSS_SPINUP,
GAUSS_SPIN,
GAUSS_FIRE,
GAUSS_FIRE2,
GAUSS_HOLSTER,
GAUSS_DRAW
};
void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName );
void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType );
int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount );
void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float *vecSpread, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount );
#endif // EV_HLDMH

16
cl_dll/events.cpp Normal file
View File

@ -0,0 +1,16 @@
#include "hud.h"
#include "cl_util.h"
void Game_HookEvents( void );
/*
===================
EV_HookEvents
See if game specific code wants to hook any events.
===================
*/
void EV_HookEvents( void )
{
Game_HookEvents();
}

66
cl_dll/eventscripts.h Normal file
View File

@ -0,0 +1,66 @@
// eventscripts.h
#if !defined ( EVENTSCRIPTSH )
#define EVENTSCRIPTSH
// defaults for clientinfo messages
#define DEFAULT_VIEWHEIGHT 28
#define VEC_DUCK_VIEW 12
#define FTENT_FADEOUT 0x00000080
#define DMG_GENERIC 0 // generic damage was done
#define DMG_CRUSH (1 << 0) // crushed by falling or moving object
#define DMG_BULLET (1 << 1) // shot
#define DMG_SLASH (1 << 2) // cut, clawed, stabbed
#define DMG_BURN (1 << 3) // heat burned
#define DMG_FREEZE (1 << 4) // frozen
#define DMG_FALL (1 << 5) // fell too far
#define DMG_BLAST (1 << 6) // explosive blast damage
#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt
#define DMG_SHOCK (1 << 8) // electric shock
#define DMG_SONIC (1 << 9) // sound pulse shockwave
#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam
#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death
#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death.
// time-based damage
//mask off TF-specific stuff too
#define DMG_TIMEBASED (~(0xff003fff)) // mask for time-based damage
#define DMG_DROWN (1 << 14) // Drowning
#define DMG_FIRSTTIMEBASED DMG_DROWN
#define DMG_PARALYZE (1 << 15) // slows affected creature down
#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
#define DMG_POISON (1 << 17) // blood poisioning
#define DMG_RADIATION (1 << 18) // radiation exposure
#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
#define DMG_SLOWBURN (1 << 21) // in an oven
#define DMG_SLOWFREEZE (1 << 22) // in a subzero freezer
#define DMG_MORTAR (1 << 23) // Hit by air raid (done to distinguish grenade from mortar)
//TF ADDITIONS
#define DMG_IGNITE (1 << 24) // Players hit by this begin to burn
#define DMG_RADIUS_MAX (1 << 25) // Radius damage with this flag doesn't decrease over distance
#define DMG_RADIUS_QUAKE (1 << 26) // Radius damage is done like Quake. 1/2 damage at 1/2 radius.
#define DMG_IGNOREARMOR (1 << 27) // Damage ignores target's armor
#define DMG_AIMED (1 << 28) // Does Hit location damage
#define DMG_WALLPIERCING (1 << 29) // Blast Damages ents through walls
#define DMG_CALTROP (1<<30)
#define DMG_HALLUC (1<<31)
// Some of these are HL/TFC specific?
void EV_EjectBrass( float *origin, float *velocity, float rotation, int model, int soundtype );
void EV_GetGunPosition( struct event_args_s *args, float *pos, float *origin );
void EV_GetDefaultShellInfo( struct event_args_s *args, float *origin, float *velocity, float *ShellVelocity, float *ShellOrigin, float *forward, float *right, float *up, float forwardScale, float upScale, float rightScale );
qboolean EV_IsLocal( int idx );
qboolean EV_IsPlayer( int idx );
void EV_CreateTracer( float *start, float *end );
struct cl_entity_s *GetEntity( int idx );
struct cl_entity_s *GetViewEntity( void );
void EV_MuzzleFlash( void );
#endif // EVENTSCRIPTSH

View File

@ -19,7 +19,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>

View File

@ -19,7 +19,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#include <time.h>
#include <stdio.h>

View File

@ -23,7 +23,7 @@
#include "MATH.H"
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>

View File

@ -110,6 +110,9 @@ public:
int m_iHealth;
int m_HUD_dmg_bio;
int m_HUD_cross;
float m_fAttackFront, m_fAttackRear, m_fAttackLeft, m_fAttackRight;
void GetPainColor( int &r, int &g, int &b );
float m_fFade;
private:
HSPRITE m_hSprite;
@ -117,11 +120,8 @@ private:
DAMAGE_IMAGE m_dmg[NUM_DMG_TYPES];
int m_bitsDamage;
float m_fFade;
void GetPainColor( int &r, int &g, int &b );
int DrawPain(float fTime);
int DrawDamage(float fTime);
float m_fAttackFront, m_fAttackRear, m_fAttackLeft, m_fAttackRight;
void CalcDamageDirection(vec3_t vecFrom);
void UpdateTiles(float fTime, long bits);
};

250
cl_dll/hl/hl_baseentity.cpp Normal file
View File

@ -0,0 +1,250 @@
/***
*
* 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.
*
****/
/*
==========================
This file contains "stubs" of class member implementations so that we can predict certain
weapons client side. From time to time you might find that you need to implement part of the
these functions. If so, cut it from here, paste it in hl_weapons.cpp or somewhere else and
add in the functionality you need.
==========================
*/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "nodes.h"
// Globals used by game logic
const Vector g_vecZero = Vector( 0, 0, 0 );
int gmsgWeapPickup = 0;
enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals;
ItemInfo CBasePlayerItem::ItemInfoArray[MAX_WEAPONS];
void EMIT_SOUND_DYN(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int flags, int pitch) { }
// CBaseEntity Stubs
int CBaseEntity :: TakeHealth( float flHealth, int bitsDamageType ) { return 1; }
int CBaseEntity :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType ) { return 1; }
CBaseEntity *CBaseEntity::GetNextTarget( void ) { return NULL; }
int CBaseEntity::Save( CSave &save ) { return 1; }
int CBaseEntity::Restore( CRestore &restore ) { return 1; }
void CBaseEntity::SetObjectCollisionBox( void ) { }
int CBaseEntity :: Intersects( CBaseEntity *pOther ) { return 0; }
void CBaseEntity :: MakeDormant( void ) { }
int CBaseEntity :: IsDormant( void ) { return 0; }
BOOL CBaseEntity :: IsInWorld( void ) { return TRUE; }
int CBaseEntity::ShouldToggle( USE_TYPE useType, BOOL currentState ) { return 0; }
int CBaseEntity :: DamageDecal( int bitsDamageType ) { return -1; }
CBaseEntity * CBaseEntity::Create( char *szName, const Vector &vecOrigin, const Vector &vecAngles, edict_t *pentOwner ) { return NULL; }
void CBaseEntity::SUB_Remove( void ) { }
// CBaseDelay Stubs
void CBaseDelay :: KeyValue( struct KeyValueData_s * ) { }
int CBaseDelay::Restore( class CRestore & ) { return 1; }
int CBaseDelay::Save( class CSave & ) { return 1; }
// CBaseAnimating Stubs
int CBaseAnimating::Restore( class CRestore & ) { return 1; }
int CBaseAnimating::Save( class CSave & ) { return 1; }
// DEBUG Stubs
edict_t *DBG_EntOfVars( const entvars_t *pev ) { return NULL; }
void DBG_AssertFunction(BOOL fExpr, const char* szExpr, const char* szFile, int szLine, const char* szMessage) { }
// UTIL_* Stubs
void UTIL_PrecacheOther( const char *szClassname ) { }
void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ) { }
void UTIL_DecalTrace( TraceResult *pTrace, int decalNumber ) { }
void UTIL_GunshotDecalTrace( TraceResult *pTrace, int decalNumber ) { }
void UTIL_MakeVectors( const Vector &vecAngles ) { }
BOOL UTIL_IsValidEntity( edict_t *pent ) { return TRUE; }
void UTIL_SetOrigin( entvars_t *, const Vector &org ) { }
BOOL UTIL_GetNextBestWeapon( CBasePlayer *pPlayer, CBasePlayerItem *pCurrentWeapon ) { return TRUE; }
void UTIL_LogPrintf(char *,...) { }
void UTIL_ClientPrintAll( int,char const *,char const *,char const *,char const *,char const *) { }
void ClientPrint( entvars_t *client, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) { }
// CBaseToggle Stubs
int CBaseToggle::Restore( class CRestore & ) { return 1; }
int CBaseToggle::Save( class CSave & ) { return 1; }
void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { }
// CGrenade Stubs
void CGrenade::BounceSound( void ) { }
void CGrenade::Explode( Vector, Vector ) { }
void CGrenade::Explode( TraceResult *, int ) { }
void CGrenade::Killed( entvars_t *, int ) { }
void CGrenade::Spawn( void ) { }
CBaseEntity* CBaseMonster :: CheckTraceHullAttack( float flDist, int iDamage, int iDmgType ) { return NULL; }
void CBaseMonster :: Look ( int iDistance ) { }
float CBaseAnimating :: StudioFrameAdvance ( float flInterval ) { return 0.0; }
int CBaseMonster::IRelationship ( CBaseEntity *pTarget ) { return 0; }
CBaseEntity *CBaseMonster :: BestVisibleEnemy ( void ) { return NULL; }
BOOL CBaseMonster :: FInViewCone ( CBaseEntity *pEntity ) { return FALSE; }
BOOL CBaseMonster :: FInViewCone ( Vector *pOrigin ) { return FALSE; }
BOOL CBaseEntity :: FVisible ( CBaseEntity *pEntity ) { return FALSE; }
BOOL CBaseEntity :: FVisible ( const Vector &vecOrigin ) { return FALSE; }
void CBaseMonster :: MakeIdealYaw( Vector vecTarget ) { }
float CBaseMonster::ChangeYaw ( int yawSpeed ) { return 0; }
int CBaseAnimating :: LookupActivity ( int activity ) { return 0; }
int CBaseAnimating :: LookupActivityHeaviest ( int activity ) { return 0; }
int CBaseAnimating :: LookupSequence ( const char *label ) { return 0; }
void CBaseAnimating :: ResetSequenceInfo ( ) { }
BOOL CBaseAnimating :: GetSequenceFlags( ) { return FALSE; }
void CBaseAnimating :: DispatchAnimEvents ( float flInterval ) { }
float CBaseAnimating :: SetBoneController ( int iController, float flValue ) { return 0.0; }
void CBaseAnimating :: InitBoneControllers ( void ) { }
float CBaseAnimating :: SetBlending ( int iBlender, float flValue ) { return 0; }
void CBaseAnimating :: GetBonePosition ( int iBone, Vector &origin, Vector &angles ) { }
void CBaseAnimating :: GetAttachment ( int iAttachment, Vector &origin, Vector &angles ) { }
int CBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, int *piDir ) { return -1; }
void CBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval ) { }
void CBaseAnimating :: SetBodygroup( int iGroup, int iValue ) { }
int CBaseAnimating :: GetBodygroup( int iGroup ) { return 0; }
void CBaseEntity::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker ) { }
void CBaseEntity :: TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { }
void CBaseMonster :: MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir ) { }
void CBaseMonster::ReportAIState( void ) { }
void CBaseMonster :: KeyValue( KeyValueData *pkvd ) { }
BOOL CBaseMonster :: FCheckAITrigger ( void ) { return FALSE; }
void CBaseMonster::CorpseFallThink( void ) { }
void CBaseMonster :: MonsterInitDead( void ) { }
void CBaseMonster :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
BOOL CBaseMonster :: ShouldFadeOnDeath( void ) { return FALSE; }
void CBaseMonster :: RadiusDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { }
void CBaseMonster :: RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType ) { }
void CBaseMonster::FadeMonster( void ) { }
void CBaseMonster :: GibMonster( void ) { }
BOOL CBaseMonster :: HasHumanGibs( void ) { return FALSE; }
BOOL CBaseMonster :: HasAlienGibs( void ) { return FALSE; }
Activity CBaseMonster :: GetDeathActivity ( void ) { return ACT_DIE_HEADSHOT; }
void CBaseMonster::BecomeDead( void ) {}
void CBaseMonster :: Killed( entvars_t *pevAttacker, int iGib ) {}
int CBaseMonster :: TakeHealth (float flHealth, int bitsDamageType) { return 0; }
int CBaseMonster :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
int TrainSpeed(int iSpeed, int iMax) { return 0; }
void CBasePlayer :: DeathSound( void ) { }
int CBasePlayer :: TakeHealth( float flHealth, int bitsDamageType ) { return 0; }
void CBasePlayer :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
int CBasePlayer :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
void CBasePlayer::RemoveAllItems( BOOL removeSuit ) { }
void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) { }
void CBasePlayer::WaterMove() { }
BOOL CBasePlayer::IsOnLadder( void ) { return FALSE; }
void CBasePlayer::PlayerDeathThink(void) { }
void CBasePlayer::StartDeathCam( void ) { }
void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle ) { }
void CBasePlayer::PlayerUse ( void ) { }
void CBasePlayer::Jump() { }
void CBasePlayer::Duck( ) { }
int CBasePlayer::Classify ( void ) { return 0; }
void CBasePlayer :: PlayStepSound(int step, float fvol) { }
void CBasePlayer :: UpdateStepSound( void ) { }
void CBasePlayer::PreThink(void) { }
void CBasePlayer::CheckTimeBasedDamage() { }
void CBasePlayer :: UpdateGeigerCounter( void ) { }
void CBasePlayer::CheckSuitUpdate() { }
void CBasePlayer::SetSuitUpdate(char *name, int fgroup, int iNoRepeatTime) { }
void CBasePlayer :: UpdatePlayerSound ( void ) { }
void CBasePlayer::PostThink() { }
void CBasePlayer :: Precache( void ) { }
int CBasePlayer::Save( CSave &save ) { return 0; }
void CBasePlayer::RenewItems(void) { }
int CBasePlayer::Restore( CRestore &restore ) { return 0; }
void CBasePlayer::SelectNextItem( int iItem ) { }
BOOL CBasePlayer::HasWeapons( void ) { return FALSE; }
void CBasePlayer::SelectPrevItem( int iItem ) { }
CBaseEntity *FindEntityForward( CBaseEntity *pMe ) { return NULL; }
BOOL CBasePlayer :: FlashlightIsOn( void ) { return FALSE; }
void CBasePlayer :: FlashlightTurnOn( void ) { }
void CBasePlayer :: FlashlightTurnOff( void ) { }
void CBasePlayer :: ForceClientDllUpdate( void ) { }
void CBasePlayer::ImpulseCommands( ) { }
void CBasePlayer::CheatImpulseCommands( int iImpulse ) { }
int CBasePlayer::AddPlayerItem( CBasePlayerItem *pItem ) { return FALSE; }
int CBasePlayer::RemovePlayerItem( CBasePlayerItem *pItem ) { return FALSE; }
void CBasePlayer::ItemPreFrame() { }
void CBasePlayer::ItemPostFrame() { }
int CBasePlayer::AmmoInventory( int iAmmoIndex ) { return -1; }
int CBasePlayer::GetAmmoIndex(const char *psz) { return -1; }
void CBasePlayer::SendAmmoUpdate(void) { }
void CBasePlayer :: UpdateClientData( void ) { }
BOOL CBasePlayer :: FBecomeProne ( void ) { return TRUE; }
void CBasePlayer :: BarnacleVictimBitten ( entvars_t *pevBarnacle ) { }
void CBasePlayer :: BarnacleVictimReleased ( void ) { }
int CBasePlayer :: Illumination( void ) { return 0; }
void CBasePlayer :: EnableControl(BOOL fControl) { }
Vector CBasePlayer :: GetAutoaimVector( float flDelta ) { return g_vecZero; }
Vector CBasePlayer :: AutoaimDeflection( Vector &vecSrc, float flDist, float flDelta ) { return g_vecZero; }
void CBasePlayer :: ResetAutoaim( ) { }
void CBasePlayer :: SetCustomDecalFrames( int nFrames ) { }
int CBasePlayer :: GetCustomDecalFrames( void ) { return -1; }
void CBasePlayer::DropPlayerItem ( char *pszItemName ) { }
BOOL CBasePlayer::HasPlayerItem( CBasePlayerItem *pCheckItem ) { return FALSE; }
BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) { return FALSE; }
Vector CBasePlayer :: GetGunPosition( void ) { return g_vecZero; }
const char *CBasePlayer::TeamID( void ) { return ""; }
int CBasePlayer :: GiveAmmo( int iCount, char *szName, int iMax ) { return 0; }
void CBasePlayer::AddPoints( int score, BOOL bAllowNegativeScore ) { }
void CBasePlayer::AddPointsToTeam( int score, BOOL bAllowNegativeScore ) { }
void ClearMultiDamage(void) { }
void ApplyMultiDamage(entvars_t *pevInflictor, entvars_t *pevAttacker ) { }
void AddMultiDamage( entvars_t *pevInflictor, CBaseEntity *pEntity, float flDamage, int bitsDamageType) { }
void SpawnBlood(Vector vecSpot, int bloodColor, float flDamage) { }
int DamageDecal( CBaseEntity *pEntity, int bitsDamageType ) { return 0; }
void DecalGunshot( TraceResult *pTrace, int iBulletType ) { }
void EjectBrass ( const Vector &vecOrigin, const Vector &vecVelocity, float rotation, int model, int soundtype ) { }
void AddAmmoNameToAmmoRegistry( const char *szAmmoname ) { }
int CBasePlayerItem::Restore( class CRestore & ) { return 1; }
int CBasePlayerItem::Save( class CSave & ) { return 1; }
int CBasePlayerWeapon::Restore( class CRestore & ) { return 1; }
int CBasePlayerWeapon::Save( class CSave & ) { return 1; }
void CBasePlayerItem :: SetObjectCollisionBox( void ) { }
void CBasePlayerItem :: FallInit( void ) { }
void CBasePlayerItem::FallThink ( void ) { }
void CBasePlayerItem::Materialize( void ) { }
void CBasePlayerItem::AttemptToMaterialize( void ) { }
void CBasePlayerItem :: CheckRespawn ( void ) { }
CBaseEntity* CBasePlayerItem::Respawn( void ) { return NULL; }
void CBasePlayerItem::DefaultTouch( CBaseEntity *pOther ) { }
void CBasePlayerItem::DestroyItem( void ) { }
int CBasePlayerItem::AddToPlayer( CBasePlayer *pPlayer ) { return TRUE; }
void CBasePlayerItem::Drop( void ) { }
void CBasePlayerItem::Kill( void ) { }
void CBasePlayerItem::Holster( int skiplocal ) { }
void CBasePlayerItem::AttachToPlayer ( CBasePlayer *pPlayer ) { }
int CBasePlayerWeapon::AddDuplicate( CBasePlayerItem *pOriginal ) { return 0; }
int CBasePlayerWeapon::AddToPlayer( CBasePlayer *pPlayer ) { return FALSE; }
int CBasePlayerWeapon::UpdateClientData( CBasePlayer *pPlayer ) { return 0; }
BOOL CBasePlayerWeapon :: AddPrimaryAmmo( int iCount, char *szName, int iMaxClip, int iMaxCarry ) { return TRUE; }
BOOL CBasePlayerWeapon :: AddSecondaryAmmo( int iCount, char *szName, int iMax ) { return TRUE; }
BOOL CBasePlayerWeapon :: IsUseable( void ) { return TRUE; }
int CBasePlayerWeapon::PrimaryAmmoIndex( void ) { return -1; }
int CBasePlayerWeapon::SecondaryAmmoIndex( void ) { return -1; }
void CBasePlayerAmmo::Spawn( void ) { }
CBaseEntity* CBasePlayerAmmo::Respawn( void ) { return this; }
void CBasePlayerAmmo::Materialize( void ) { }
void CBasePlayerAmmo :: DefaultTouch( CBaseEntity *pOther ) { }
int CBasePlayerWeapon::ExtractAmmo( CBasePlayerWeapon *pWeapon ) { return 0; }
int CBasePlayerWeapon::ExtractClipAmmo( CBasePlayerWeapon *pWeapon ) { return 0; }
void CBasePlayerWeapon::RetireWeapon( void ) { }

57
cl_dll/hl/hl_events.cpp Normal file
View File

@ -0,0 +1,57 @@
/***
*
* 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.
*
****/
#include "../hud.h"
#include "../cl_util.h"
#include "event_api.h"
extern "C"
{
// HLDM
void EV_FireGlock1( struct event_args_s *args );
void EV_FireGlock2( struct event_args_s *args );
void EV_FireShotGunSingle( struct event_args_s *args );
void EV_FireShotGunDouble( struct event_args_s *args );
void EV_FireMP5( struct event_args_s *args );
void EV_FirePython( struct event_args_s *args );
void EV_FireGauss( struct event_args_s *args );
void EV_SpinGauss( struct event_args_s *args );
void EV_TrainPitchAdjust( struct event_args_s *args );
}
/*
======================
Game_HookEvents
Associate script file name with callback functions. Callback's must be extern "C" so
the engine doesn't get confused about name mangling stuff. Note that the format is
always the same. Of course, a clever mod team could actually embed parameters, behavior
into the actual .sc files and create a .sc file parser and hook their functionality through
that.. i.e., a scripting system.
That was what we were going to do, but we ran out of time...oh well.
======================
*/
void Game_HookEvents( void )
{
gEngfuncs.pfnHookEvent( "events/glock1.sc", EV_FireGlock1 );
gEngfuncs.pfnHookEvent( "events/glock2.sc", EV_FireGlock2 );
gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
}

28
cl_dll/hl/hl_objects.cpp Normal file
View File

@ -0,0 +1,28 @@
/***
*
* 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.
*
****/
#include "../hud.h"
#include "../cl_util.h"
#include "../demo.h"
/*
=====================
Game_AddObjects
Add game specific, client-side objects here
=====================
*/
void Game_AddObjects( void )
{
}

822
cl_dll/hl/hl_weapons.cpp Normal file
View File

@ -0,0 +1,822 @@
/***
*
* 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.
*
****/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "usercmd.h"
#include "entity_state.h"
#include "demo_api.h"
#include "pm_defs.h"
#include "event_api.h"
#include "r_efx.h"
#include "../hud_iface.h"
#include "../com_weapons.h"
#include "../demo.h"
extern globalvars_t *gpGlobals;
// Pool of client side entities/entvars_t
static entvars_t ev[ 32 ];
static int num_ents = 0;
// The entity we'll use to represent the local client
static CBasePlayer player;
// Local version of game .dll global variables ( time, etc. )
static globalvars_t Globals;
static CBasePlayerWeapon *g_pWpns[ 32 ];
// HLDM Weapon placeholder entities.
CGlock g_Glock;
/*
======================
AlertMessage
Print debug messages to console
======================
*/
void AlertMessage( ALERT_TYPE atype, char *szFmt, ... )
{
va_list argptr;
static char string[1024];
va_start (argptr, szFmt);
vsprintf (string, szFmt,argptr);
va_end (argptr);
gEngfuncs.Con_Printf( "cl: " );
gEngfuncs.Con_Printf( string );
}
/*
=====================
HUD_PrepEntity
Links the raw entity to an entvars_s holder. If a player is passed in as the owner, then
we set up the m_pPlayer field.
=====================
*/
void HUD_PrepEntity( CBaseEntity *pEntity, CBasePlayer *pWeaponOwner )
{
memset( &ev[ num_ents ], 0, sizeof( entvars_t ) );
pEntity->pev = &ev[ num_ents++ ];
pEntity->Precache();
pEntity->Spawn();
if ( pWeaponOwner )
{
ItemInfo info;
((CBasePlayerWeapon *)pEntity)->m_pPlayer = pWeaponOwner;
((CBasePlayerWeapon *)pEntity)->GetItemInfo( &info );
g_pWpns[ info.iId ] = (CBasePlayerWeapon *)pEntity;
}
}
/*
=====================
CBaseEntity :: Killed
If weapons code "kills" an entity, just set its effects to EF_NODRAW
=====================
*/
void CBaseEntity :: Killed( entvars_t *pevAttacker, int iGib )
{
pev->effects |= EF_NODRAW;
}
/*
=====================
CBasePlayerWeapon :: DefaultReload
=====================
*/
BOOL CBasePlayerWeapon :: DefaultReload( int iClipSize, int iAnim, float fDelay )
{
#if 0 // FIXME, need to know primary ammo to get this right
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
return FALSE;
int j = min(iClipSize - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
if (j == 0)
return FALSE;
#endif
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay;
//!!UNDONE -- reload sound goes here !!!
SendWeaponAnim( iAnim );
m_fInReload = TRUE;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 3;
return TRUE;
}
/*
=====================
CBasePlayerWeapon :: CanDeploy
=====================
*/
BOOL CBasePlayerWeapon :: CanDeploy( void )
{
BOOL bHasAmmo = 0;
if ( !pszAmmo1() )
{
// this weapon doesn't use ammo, can always deploy.
return TRUE;
}
if ( pszAmmo1() )
{
bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] != 0);
}
if ( pszAmmo2() )
{
bHasAmmo |= (m_pPlayer->m_rgAmmo[m_iSecondaryAmmoType] != 0);
}
if (m_iClip > 0)
{
bHasAmmo |= 1;
}
if (!bHasAmmo)
{
return FALSE;
}
return TRUE;
}
/*
=====================
CBasePlayerWeapon :: DefaultDeploy
=====================
*/
BOOL CBasePlayerWeapon :: DefaultDeploy( char *szViewModel, char *szWeaponModel, int iAnim, char *szAnimExt, int skiplocal )
{
if ( !CanDeploy() )
return FALSE;
gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel );
SendWeaponAnim( iAnim );
m_pPlayer->m_flNextAttack = 0.5;
m_flTimeWeaponIdle = 1.0;
return TRUE;
}
/*
=====================
CBasePlayerWeapon :: PlayEmptySound
=====================
*/
BOOL CBasePlayerWeapon :: PlayEmptySound( void )
{
if (m_iPlayEmptySound)
{
HUD_PlaySound( "weapons/357_cock1.wav", 0.8 );
m_iPlayEmptySound = 0;
return 0;
}
return 0;
}
/*
=====================
CBasePlayerWeapon :: ResetEmptySound
=====================
*/
void CBasePlayerWeapon :: ResetEmptySound( void )
{
m_iPlayEmptySound = 1;
}
/*
=====================
CBasePlayerWeapon::Holster
Put away weapon
=====================
*/
void CBasePlayerWeapon::Holster( int skiplocal /* = 0 */ )
{
m_fInReload = FALSE; // cancel any reload in progress.
m_pPlayer->pev->viewmodel = 0;
}
/*
=====================
CBasePlayerWeapon::SendWeaponAnim
Animate weapon model
=====================
*/
void CBasePlayerWeapon::SendWeaponAnim( int iAnim, int skiplocal )
{
m_pPlayer->pev->weaponanim = iAnim;
int body = 0;
HUD_SendWeaponAnim( iAnim, body, 0 );
}
/*
=====================
CBasePlayerWeapon::ItemPostFrame
Handles weapon firing, reloading, etc.
=====================
*/
void CBasePlayerWeapon::ItemPostFrame( void )
{
if ((m_fInReload) && (m_pPlayer->m_flNextAttack <= 0.0))
{
#if 0 // FIXME, need ammo on client to make this work right
// complete the reload.
int j = min( iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]);
// Add them to the clip
m_iClip += j;
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j;
#else
m_iClip += 10;
#endif
m_fInReload = FALSE;
}
if ((m_pPlayer->pev->button & IN_ATTACK2) && (m_flNextSecondaryAttack <= 0.0))
{
if ( pszAmmo2() && !m_pPlayer->m_rgAmmo[SecondaryAmmoIndex()] )
{
m_fFireOnEmpty = TRUE;
}
SecondaryAttack();
m_pPlayer->pev->button &= ~IN_ATTACK2;
}
else if ((m_pPlayer->pev->button & IN_ATTACK) && (m_flNextPrimaryAttack <= 0.0))
{
if ( (m_iClip == 0 && pszAmmo1()) || (iMaxClip() == -1 && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()] ) )
{
m_fFireOnEmpty = TRUE;
}
PrimaryAttack();
}
else if ( m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload )
{
// reload when reload is pressed, or if no buttons are down and weapon is empty.
Reload();
}
else if ( !(m_pPlayer->pev->button & (IN_ATTACK|IN_ATTACK2) ) )
{
// no fire buttons down
m_fFireOnEmpty = FALSE;
// weapon is useable. Reload if empty and weapon has waited as long as it has to after firing
if ( m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < 0.0 )
{
Reload();
return;
}
WeaponIdle( );
return;
}
// catch all
if ( ShouldWeaponIdle() )
{
WeaponIdle();
}
}
/*
=====================
CBasePlayer::SelectItem
Switch weapons
=====================
*/
void CBasePlayer::SelectItem(const char *pstr)
{
if (!pstr)
return;
CBasePlayerItem *pItem = NULL;
if (!pItem)
return;
if (pItem == m_pActiveItem)
return;
if (m_pActiveItem)
m_pActiveItem->Holster( );
m_pLastItem = m_pActiveItem;
m_pActiveItem = pItem;
if (m_pActiveItem)
{
m_pActiveItem->Deploy( );
}
}
/*
=====================
CBasePlayer::SelectLastItem
=====================
*/
void CBasePlayer::SelectLastItem(void)
{
if (!m_pLastItem)
{
return;
}
if ( m_pActiveItem && !m_pActiveItem->CanHolster() )
{
return;
}
if (m_pActiveItem)
m_pActiveItem->Holster( );
CBasePlayerItem *pTemp = m_pActiveItem;
m_pActiveItem = m_pLastItem;
m_pLastItem = pTemp;
m_pActiveItem->Deploy( );
}
/*
=====================
CBasePlayer::Killed
=====================
*/
void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
{
// Holster weapon immediately, to allow it to cleanup
if (m_pActiveItem)
m_pActiveItem->Holster( );
}
/*
=====================
CBasePlayer::Spawn
=====================
*/
void CBasePlayer::Spawn( void )
{
if (m_pActiveItem)
m_pActiveItem->Deploy( );
}
/*
=====================
UTIL_TraceLine
Don't actually trace, but act like the trace didn't hit anything.
=====================
*/
void UTIL_TraceLine( const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, edict_t *pentIgnore, TraceResult *ptr )
{
memset( ptr, 0, sizeof( *ptr ) );
ptr->flFraction = 1.0;
}
/*
=====================
UTIL_ParticleBox
For debugging, draw a box around a player made out of particles
=====================
*/
void UTIL_ParticleBox( CBasePlayer *player, float *mins, float *maxs, float life, unsigned char r, unsigned char g, unsigned char b )
{
int i;
vec3_t mmin, mmax;
for ( i = 0; i < 3; i++ )
{
mmin[ i ] = player->pev->origin[ i ] + mins[ i ];
mmax[ i ] = player->pev->origin[ i ] + maxs[ i ];
}
gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&mmin, (float *)&mmax, 5.0, 0, 255, 0 );
}
/*
=====================
UTIL_ParticleBoxes
For debugging, draw boxes for other collidable players
=====================
*/
void UTIL_ParticleBoxes( void )
{
int idx;
physent_t *pe;
cl_entity_t *player;
vec3_t mins, maxs;
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
player = gEngfuncs.GetLocalPlayer();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( player->index - 1 );
for ( idx = 1; idx < 100; idx++ )
{
pe = gEngfuncs.pEventAPI->EV_GetPhysent( idx );
if ( !pe )
break;
if ( pe->info >= 1 && pe->info <= gEngfuncs.GetMaxClients() )
{
mins = pe->origin + pe->mins;
maxs = pe->origin + pe->maxs;
gEngfuncs.pEfxAPI->R_ParticleBox( (float *)&mins, (float *)&maxs, 0, 0, 255, 2.0 );
}
}
gEngfuncs.pEventAPI->EV_PopPMStates();
}
/*
=====================
UTIL_ParticleLine
For debugging, draw a line made out of particles
=====================
*/
void UTIL_ParticleLine( CBasePlayer *player, float *start, float *end, float life, unsigned char r, unsigned char g, unsigned char b )
{
gEngfuncs.pEfxAPI->R_ParticleLine( start, end, r, g, b, life );
}
/*
=====================
CBasePlayerWeapon::PrintState
For debugging, print out state variables to log file
=====================
*/
void CBasePlayerWeapon::PrintState( void )
{
COM_Log( "c:\\hl.log", "%.4f ", gpGlobals->time );
COM_Log( "c:\\hl.log", "%.4f ", m_pPlayer->m_flNextAttack );
COM_Log( "c:\\hl.log", "%.4f ", m_flNextPrimaryAttack );
COM_Log( "c:\\hl.log", "%.4f ", m_flTimeWeaponIdle - gpGlobals->time);
COM_Log( "c:\\hl.log", "%i ", m_iClip );
}
/*
=====================
HUD_InitClientWeapons
Set up weapons, player and functions needed to run weapons code client-side.
=====================
*/
void HUD_InitClientWeapons( void )
{
static int initialized = 0;
if ( initialized )
return;
initialized = 1;
// Set up pointer ( dummy object )
gpGlobals = &Globals;
// Fill in current time ( probably not needed )
gpGlobals->time = gEngfuncs.GetClientTime();
// Fake functions
g_engfuncs.pfnPrecacheModel = stub_PrecacheModel;
g_engfuncs.pfnPrecacheSound = stub_PrecacheSound;
g_engfuncs.pfnPrecacheEvent = stub_PrecacheEvent;
g_engfuncs.pfnNameForFunction = stub_NameForFunction;
g_engfuncs.pfnSetModel = stub_SetModel;
g_engfuncs.pfnSetClientMaxspeed = HUD_SetMaxSpeed;
// Handled locally
g_engfuncs.pfnPlaybackEvent = HUD_PlaybackEvent;
g_engfuncs.pfnAlertMessage = AlertMessage;
// Pass through to engine
g_engfuncs.pfnPrecacheEvent = gEngfuncs.pfnPrecacheEvent;
g_engfuncs.pfnRandomFloat = gEngfuncs.pfnRandomFloat;
g_engfuncs.pfnRandomLong = gEngfuncs.pfnRandomLong;
// Allocate a slot for the local player
HUD_PrepEntity( &player , NULL );
// Allocate slot(s) for each weapon that we are going to be predicting
HUD_PrepEntity( &g_Glock , &player );
}
/*
=====================
HUD_WeaponsPostThink
Run Weapon firing code on client
=====================
*/
void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cmd, double time, unsigned int random_seed )
{
int i;
int buttonsChanged;
CBasePlayerWeapon *pWeapon = NULL;
CBasePlayerWeapon *pCurrent;
weapon_data_t nulldata, *pfrom, *pto;
static int lasthealth;
memset( &nulldata, 0, sizeof( nulldata ) );
HUD_InitClientWeapons();
// Get current clock
gpGlobals->time = time;
// Fill in data based on selected weapon
// FIXME, make this a method in each weapon? where you pass in an entity_state_t *?
switch ( from->client.m_iId )
{
case WEAPON_GLOCK:
pWeapon = &g_Glock;
break;
}
// We are not predicting the current weapon, just bow out here.
if ( !pWeapon )
return;
for ( i = 0; i < 32; i++ )
{
pCurrent = g_pWpns[ i ];
if ( !pCurrent )
{
continue;
}
pfrom = &from->weapondata[ i ];
pCurrent->m_fInReload = pfrom->m_fInReload;
pCurrent->m_iClip = pfrom->m_iClip;
pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack;
pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack;
pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle;
}
// For random weapon events, use this seed to seed random # generator
player.random_seed = random_seed;
// Get old buttons from previous state.
player.m_afButtonLast = from->playerstate.oldbuttons;
// Which buttsons chave changed
buttonsChanged = (player.m_afButtonLast ^ cmd->buttons); // These buttons have changed this frame
// Debounced button codes for pressed/released
// The changed ones still down are "pressed"
player.m_afButtonPressed = buttonsChanged & cmd->buttons;
// The ones not down are "released"
player.m_afButtonReleased = buttonsChanged & (~cmd->buttons);
// Set player variables that weapons code might check/alter
player.pev->button = cmd->buttons;
player.pev->velocity = from->client.velocity;
player.pev->flags = from->client.flags;
player.pev->deadflag = from->client.deadflag;
player.pev->waterlevel = from->client.waterlevel;
player.pev->maxspeed = from->client.maxspeed;
player.pev->fov = from->client.fov;
player.pev->weaponanim = from->client.weaponanim;
player.pev->viewmodel = from->client.viewmodel;
player.m_flNextAttack = from->client.m_flNextAttack;
// Point to current weapon object
if ( from->client.m_iId )
{
player.m_pActiveItem = g_pWpns[ from->client.m_iId ];
}
// Store pointer to our destination entity_state_t so we can get our origin, etc. from it
// for setting up events on the client
g_finalstate = to;
// Don't go firing anything if we have died.
// Or if we don't have a weapon model deployed
if ( ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) && !CL_IsDead() && player.pev->viewmodel )
{
if ( player.m_flNextAttack <= 0 )
{
pWeapon->ItemPostFrame();
}
}
// If we are running events/etc. go ahead and see if we
// managed to die between last frame and this one
// If so, run the appropriate player killed or spawn function
if ( g_runfuncs )
{
if ( to->client.health <= 0 && lasthealth > 0 )
{
player.Killed( NULL, 0 );
}
else if ( to->client.health > 0 && lasthealth <= 0 )
{
player.Spawn();
}
lasthealth = to->client.health;
}
// Assume that we are not going to switch weapons
to->client.m_iId = from->client.m_iId;
// Now see if we issued a changeweapon command ( and we're not dead )
if ( cmd->weaponselect && ( player.pev->deadflag != ( DEAD_DISCARDBODY + 1 ) ) )
{
// Switched to a different weapon?
if ( from->weapondata[ cmd->weaponselect ].m_iId == cmd->weaponselect )
{
CBasePlayerWeapon *pNew = g_pWpns[ cmd->weaponselect ];
if ( pNew && ( pNew != pWeapon ) )
{
// Put away old weapon
if (player.m_pActiveItem)
player.m_pActiveItem->Holster( );
player.m_pLastItem = player.m_pActiveItem;
player.m_pActiveItem = pNew;
// Deploy new weapon
if (player.m_pActiveItem)
{
player.m_pActiveItem->Deploy( );
}
// Update weapon id so we can predict things correctly.
to->client.m_iId = cmd->weaponselect;
}
}
}
// Copy in results of predcition code
to->client.viewmodel = player.pev->viewmodel;
to->client.fov = player.pev->fov;
to->client.weaponanim = player.pev->weaponanim;
to->client.m_flNextAttack = player.m_flNextAttack;
to->client.maxspeed = player.pev->maxspeed;
// Make sure that weapon animation matches what the game .dll is telling us
// over the wire ( fixes some animation glitches )
if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) )
{
int body = 2;
// Force a fixed anim down to viewmodel
HUD_SendWeaponAnim( to->client.weaponanim, body, 1 );
}
for ( i = 0; i < 32; i++ )
{
pCurrent = g_pWpns[ i ];
pto = &to->weapondata[ i ];
if ( !pCurrent )
{
memset( pto, 0, sizeof( weapon_data_t ) );
continue;
}
pto->m_fInReload = pCurrent->m_fInReload;
pto->m_iClip = pCurrent->m_iClip;
pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack;
pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack;
pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle;
// Decrement weapon counters, server does this at same time ( during post think, after doing everything else )
pto->m_flNextReload -= cmd->msec / 1000.0;
pto->m_fNextAimBonus -= cmd->msec / 1000.0;
pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0;
pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0;
pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0;
if ( pto->m_flPumpTime != -9999 )
{
pto->m_flPumpTime -= cmd->msec / 1000.0;
if ( pto->m_flPumpTime < -0.001 )
pto->m_flPumpTime = -0.001;
}
if ( pto->m_fNextAimBonus < -1.0 )
{
pto->m_fNextAimBonus = -1.0;
}
if ( pto->m_flNextPrimaryAttack < -1.0 )
{
pto->m_flNextPrimaryAttack = -1.0;
}
if ( pto->m_flNextSecondaryAttack < -0.001 )
{
pto->m_flNextSecondaryAttack = -0.001;
}
if ( pto->m_flTimeWeaponIdle < -0.001 )
{
pto->m_flTimeWeaponIdle = -0.001;
}
if ( pto->m_flNextReload < -0.001 )
{
pto->m_flNextReload = -0.001;
}
}
// m_flNextAttack is now part of the weapons, but is part of the player instead
to->client.m_flNextAttack -= cmd->msec / 1000.0;
if ( to->client.m_flNextAttack < -0.001 )
{
to->client.m_flNextAttack = -0.001;
}
// Wipe it so we can't use it after this frame
g_finalstate = NULL;
}
/*
=====================
HUD_PostRunCmd
Client calls this during prediction, after it has moved the player and updated any info changed into to->
time is the current client clock based on prediction
cmd is the command that caused the movement, etc
runfuncs is 1 if this is the first time we've predicted this command. If so, sounds and effects should play, otherwise, they should
be ignored
=====================
*/
void _DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed )
{
g_runfuncs = runfuncs;
// Only run post think stuff for glock for the sample
// implementation
#if defined( CLIENT_WEAPONS )
if ( cl_lw && cl_lw->value &&
from->client.m_iId == WEAPON_GLOCK )
{
HUD_WeaponsPostThink( from, to, cmd, time, random_seed );
}
else
#endif
{
to->client.fov = g_lastFOV;
}
// All games can use FOV state
g_lastFOV = to->client.fov;
}

View File

@ -19,13 +19,23 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#include <stdio.h>
#include "parsemsg.h"
#include "hud_servers.h"
#include "vgui_TeamFortressViewport.h"
#include "demo.h"
#include "demo_api.h"
extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
extern cvar_t *sensitivity;
cvar_t *cl_lw = NULL;
void ShutdownInput (void);
//DECLARE_MESSAGE(m_Logo, Logo)
int __MsgFunc_Logo(const char *pszName, int iSize, void *pbuf)
{
@ -59,7 +69,147 @@ int __MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf )
return gHUD.MsgFunc_GameMode( pszName, iSize, pbuf );
}
// TFFree Command Menu
void __CmdFunc_OpenCommandMenu(void)
{
if ( gViewPort )
{
gViewPort->ShowCommandMenu();
}
}
// TFC "special" command
void __CmdFunc_InputPlayerSpecial(void)
{
if ( gViewPort )
{
gViewPort->InputPlayerSpecial();
}
}
void __CmdFunc_CloseCommandMenu(void)
{
if ( gViewPort )
{
gViewPort->InputSignalHideCommandMenu();
}
}
void __CmdFunc_ForceCloseCommandMenu( void )
{
if ( gViewPort )
{
gViewPort->HideCommandMenu();
}
}
void __CmdFunc_ToggleServerBrowser( void )
{
if ( gViewPort )
{
gViewPort->ToggleServerBrowser();
}
}
// TFFree Command Menu Message Handlers
int __MsgFunc_ValClass(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_ValClass( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_TeamNames(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_TeamNames( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_Feign(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_Feign( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_Detpack(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_Detpack( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_VGUIMenu(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_VGUIMenu( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_MOTD(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_MOTD( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_BuildSt(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_BuildSt( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_RandomPC(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_RandomPC( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_ServerName(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_ServerName( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_ScoreInfo(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_ScoreInfo( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_TeamScore(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_TeamScore( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_TeamInfo(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_TeamInfo( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_Spectator(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_Spectator( pszName, iSize, pbuf );
return 0;
}
int __MsgFunc_AllowSpec(const char *pszName, int iSize, void *pbuf)
{
if (gViewPort)
return gViewPort->MsgFunc_AllowSpec( pszName, iSize, pbuf );
return 0;
}
// This is called every time the DLL is loaded
void CHud :: Init( void )
{
@ -70,11 +220,39 @@ void CHud :: Init( void )
HOOK_MESSAGE( SetFOV );
HOOK_MESSAGE( Concuss );
// TFFree CommandMenu
HOOK_COMMAND( "+commandmenu", OpenCommandMenu );
HOOK_COMMAND( "-commandmenu", CloseCommandMenu );
HOOK_COMMAND( "ForceCloseCommandMenu", ForceCloseCommandMenu );
HOOK_COMMAND( "special", InputPlayerSpecial );
HOOK_COMMAND( "togglebrowser", ToggleServerBrowser );
HOOK_MESSAGE( ValClass );
HOOK_MESSAGE( TeamNames );
HOOK_MESSAGE( Feign );
HOOK_MESSAGE( Detpack );
HOOK_MESSAGE( MOTD );
HOOK_MESSAGE( BuildSt );
HOOK_MESSAGE( RandomPC );
HOOK_MESSAGE( ServerName );
HOOK_MESSAGE( ScoreInfo );
HOOK_MESSAGE( TeamScore );
HOOK_MESSAGE( TeamInfo );
HOOK_MESSAGE( Spectator );
HOOK_MESSAGE( AllowSpec );
// VGUI Menus
HOOK_MESSAGE( VGUIMenu );
m_iLogo = 0;
m_iFOV = 0;
CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 );
CVAR_CREATE( "default_fov", "90", 0 );
default_fov = CVAR_CREATE( "default_fov", "90", 0 );
m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE );
cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" );
m_pSpriteList = NULL;
@ -101,8 +279,6 @@ void CHud :: Init( void )
m_Battery.Init();
m_Flash.Init();
m_Message.Init();
m_Scoreboard.Init();
m_MOTD.Init();
m_StatusBar.Init();
m_DeathNotice.Init();
m_AmmoSecondary.Init();
@ -111,6 +287,8 @@ void CHud :: Init( void )
m_SayText.Init();
m_Menu.Init();
ServersInit();
MsgFunc_ResetHUD(0, 0, NULL );
}
@ -122,6 +300,20 @@ CHud :: ~CHud()
delete [] m_rghSprites;
delete [] m_rgrcRects;
delete [] m_rgszSpriteNames;
if ( m_pHudList )
{
HUDLIST *pList;
while ( m_pHudList )
{
pList = m_pHudList;
m_pHudList = m_pHudList->pNext;
free( pList );
}
m_pHudList = NULL;
}
ServersShutdown();
}
// GetSpriteIndex()
@ -151,6 +343,7 @@ void CHud :: VidInit( void )
// m_hsprFont = LoadSprite("sprites/%d_font.spr");
m_hsprLogo = 0;
m_hsprCursor = 0;
if (ScreenWidth < 640)
m_iRes = 320;
@ -231,8 +424,6 @@ void CHud :: VidInit( void )
m_Battery.VidInit();
m_Flash.VidInit();
m_Message.VidInit();
m_Scoreboard.VidInit();
m_MOTD.VidInit();
m_StatusBar.VidInit();
m_DeathNotice.VidInit();
m_SayText.VidInit();
@ -252,6 +443,100 @@ int CHud::MsgFunc_Logo(const char *pszName, int iSize, void *pbuf)
return 1;
}
float g_lastFOV = 0.0;
/*
============
COM_FileBase
============
*/
// Extracts the base name of a file (no path, no extension, assumes '/' as path separator)
void COM_FileBase ( const char *in, char *out)
{
int len, start, end;
len = strlen( in );
// scan backward for '.'
end = len - 1;
while ( end && in[end] != '.' && in[end] != '/' && in[end] != '\\' )
end--;
if ( in[end] != '.' ) // no '.', copy to end
end = len-1;
else
end--; // Found ',', copy to left of '.'
// Scan backward for '/'
start = len-1;
while ( start >= 0 && in[start] != '/' && in[start] != '\\' )
start--;
if ( in[start] != '/' && in[start] != '\\' )
start = 0;
else
start++;
// Length of new sting
len = end - start + 1;
// Copy partial string
strncpy( out, &in[start], len );
// Terminate it
out[len] = 0;
}
/*
=================
HUD_IsGame
=================
*/
int HUD_IsGame( const char *game )
{
const char *gamedir;
char gd[ 1024 ];
gamedir = gEngfuncs.pfnGetGameDirectory();
if ( gamedir && gamedir[0] )
{
COM_FileBase( gamedir, gd );
if ( !stricmp( gd, game ) )
return 1;
}
return 0;
}
/*
=====================
HUD_GetFOV
Returns last FOV
=====================
*/
float HUD_GetFOV( void )
{
if ( gEngfuncs.pDemoAPI->IsRecording() )
{
// Write it
int i = 0;
unsigned char buf[ 100 ];
// Active
*( float * )&buf[ i ] = g_lastFOV;
i += sizeof( float );
Demo_WriteBuffer( TYPE_ZOOM, i, buf );
}
if ( gEngfuncs.pDemoAPI->IsPlayingback() )
{
g_lastFOV = g_demozoom;
}
return g_lastFOV;
}
int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
{
BEGIN_READ( pbuf, iSize );
@ -259,6 +544,14 @@ int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
int newfov = READ_BYTE();
int def_fov = CVAR_GET_FLOAT( "default_fov" );
int tfc = 0;
tfc = HUD_IsGame( "tfc" );
if ( tfc && cl_lw && cl_lw->value )
return 1;
g_lastFOV = newfov;
if ( newfov == 0 )
{
m_iFOV = def_fov;
@ -279,7 +572,7 @@ int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
else
{
// set a new sensitivity that is proportional to the change from the FOV default
m_flMouseSensitivity = CVAR_GET_FLOAT("sensitivity") * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
}
return 1;
@ -316,4 +609,9 @@ void CHud::AddHudElem(CHudBase *phudelem)
ptemp->pNext = pdl;
}
float CHud::GetSensitivity( void )
{
return m_flMouseSensitivity;
}

View File

@ -25,11 +25,7 @@
#define RGB_REDISH 0x00FF1010 //255,160,0
#define RGB_GREENISH 0x0000A000 //0,160,0
typedef struct rect_s
{
int left, right, top, bottom;
} wrect_t;
#include "wrect.h"
#include "cl_dll.h"
#include "ammo.h"
@ -54,6 +50,8 @@ typedef struct {
#define MAX_PLAYER_NAME_LENGTH 32
#define MAX_MOTD_LENGTH 1024
//
//-----------------------------------------------------
//
@ -98,6 +96,7 @@ public:
int MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf );
int MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf );
void SlotInput( int iSlot );
void _cdecl UserCmd_Slot1( void );
void _cdecl UserCmd_Slot2( void );
void _cdecl UserCmd_Slot3( void );
@ -189,6 +188,9 @@ private:
//
//-----------------------------------------------------
//
// REMOVED: Vgui has replaced this.
//
/*
class CHudMOTD : public CHudBase
{
public:
@ -200,12 +202,12 @@ public:
int MsgFunc_MOTD( const char *pszName, int iSize, void *pbuf );
protected:
enum { MAX_MOTD_LENGTH = 241, };
static int MOTD_DISPLAY_TIME;
char m_szMOTD[ MAX_MOTD_LENGTH ];
float m_flActiveTill;
float m_flActiveRemaining;
int m_iLines;
};
*/
//
//-----------------------------------------------------
@ -239,6 +241,9 @@ protected:
//
//-----------------------------------------------------
//
// REMOVED: Vgui has replaced this.
//
/*
class CHudScoreboard: public CHudBase
{
public:
@ -254,34 +259,6 @@ public:
int MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf );
void DeathMsg( int killer, int victim );
enum {
MAX_PLAYERS = 64,
MAX_TEAMS = 64,
MAX_TEAM_NAME = 16,
};
struct extra_player_info_t {
short frags;
short deaths;
char teamname[MAX_TEAM_NAME];
};
struct team_info_t {
char name[MAX_TEAM_NAME];
short frags;
short deaths;
short ping;
short packetloss;
short ownteam;
short players;
int already_drawn;
int scores_overriden;
};
hud_player_info_t m_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine
extra_player_info_t m_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll
team_info_t m_TeamInfo[MAX_TEAMS+1];
int m_iNumTeams;
int m_iLastKilledBy;
@ -290,7 +267,47 @@ public:
int m_iShowscoresHeld;
void GetAllPlayersInfo( void );
private:
struct cvar_s *cl_showpacketloss;
};
*/
enum
{
MAX_PLAYERS = 64,
MAX_TEAMS = 64,
MAX_TEAM_NAME = 16,
};
struct extra_player_info_t
{
short frags;
short deaths;
short playerclass;
short teamnumber;
char teamname[MAX_TEAM_NAME];
};
struct team_info_t
{
char name[MAX_TEAM_NAME];
short frags;
short deaths;
short ping;
short packetloss;
short ownteam;
short players;
int already_drawn;
int scores_overriden;
int teamnumber;
};
extern hud_player_info_t g_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine
extern extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll
extern team_info_t g_TeamInfo[MAX_TEAMS+1];
extern int g_IsSpectator[MAX_PLAYERS+1];
//
//-----------------------------------------------------
@ -340,7 +357,7 @@ public:
int VidInit( void );
int Draw( float flTime );
int MsgFunc_SayText( const char *pszName, int iSize, void *pbuf );
void SayTextPrint( const char *pszBuf, int iBufSize );
void SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex = -1 );
void EnsureTextFitsInOneLineAndWrapIfHaveTo( int line );
};
@ -422,8 +439,8 @@ class CHudTextMessage: public CHudBase
{
public:
int Init( void );
char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size );
char *BufferedLocaliseTextString( const char *msg );
static char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size );
static char *BufferedLocaliseTextString( const char *msg );
char *LookupString( const char *msg_name, int *msg_dest = NULL );
int MsgFunc_TextMsg(const char *pszName, int iSize, void *pbuf);
};
@ -501,11 +518,12 @@ private:
};
//
//-----------------------------------------------------
//
typedef struct cvar_s cvar_t;
class CHud
{
private:
@ -520,6 +538,7 @@ private:
public:
HSPRITE m_hsprCursor;
float m_flTime; // the current client time
float m_fOldTime; // the time at which the HUD was last redrawn
double m_flTimeDelta; // the difference between flTime and fOldTime
@ -530,6 +549,7 @@ public:
int m_iFOV;
int m_Teamplay;
int m_iRes;
cvar_t *m_pCvarStealMouse;
int m_iFontHeight;
int DrawHudNumber(int x, int y, int iFlags, int iNumber, int r, int g, int b );
@ -545,6 +565,7 @@ private:
wrect_t *m_rgrcRects; /*[HUD_SPRITE_COUNT]*/
char *m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/
struct cvar_s *default_fov;
public:
HSPRITE GetSprite( int index )
{
@ -566,8 +587,6 @@ public:
CHudTrain m_Train;
CHudFlashlight m_Flash;
CHudMessage m_Message;
CHudScoreboard m_Scoreboard;
CHudMOTD m_MOTD;
CHudStatusBar m_StatusBar;
CHudDeathNotice m_DeathNotice;
CHudSayText m_SayText;
@ -606,6 +625,17 @@ public:
void AddHudElem(CHudBase *p);
float GetSensitivity();
};
class TeamFortressViewport;
extern CHud gHUD;
extern TeamFortressViewport *gViewPort;
extern int g_iPlayerClass;
extern int g_iTeamNumber;
extern int g_iUser1;
extern int g_iUser2;

13
cl_dll/hud_iface.h Normal file
View File

@ -0,0 +1,13 @@
#if !defined( HUD_IFACEH )
#define HUD_IFACEH
#pragma once
#define EXPORT _declspec( dllexport )
#define _DLLEXPORT __declspec( dllexport )
typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf);
#include "wrect.h"
#include "../engine/cdll_int.h"
extern cl_enginefunc_t gEngfuncs;
#endif

View File

@ -17,7 +17,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
/// USER-DEFINED SERVER MESSAGE HANDLERS

View File

@ -17,8 +17,9 @@
//
#include <math.h>
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "vgui_TeamFortressViewport.h"
#define MAX_LOGO_FRAMES 56
@ -30,10 +31,18 @@ int grgLogoFrame[MAX_LOGO_FRAMES] =
};
extern int g_iVisibleMouse;
float HUD_GetFOV( void );
extern cvar_t *sensitivity;
// Think
void CHud::Think(void)
{
int newfov;
HUDLIST *pList = m_pHudList;
while (pList)
{
if (pList->p->m_iFlags & HUD_ACTIVE)
@ -41,10 +50,34 @@ void CHud::Think(void)
pList = pList->pNext;
}
newfov = HUD_GetFOV();
if ( newfov == 0 )
{
m_iFOV = default_fov->value;
}
else
{
m_iFOV = newfov;
}
// the clients fov is actually set in the client data update section of the hud
// Set a new sensitivity
if ( m_iFOV == default_fov->value )
{
// reset to saved sensitivity
m_flMouseSensitivity = 0;
}
else
{
// set a new sensitivity that is proportional to the change from the FOV default
m_flMouseSensitivity = sensitivity->value * ((float)newfov / (float)default_fov->value) * CVAR_GET_FLOAT("zoom_sensitivity_ratio");
}
// think about default fov
if ( m_iFOV == 0 )
{ // only let players adjust up in fov, and only if they are not overriden by something else
m_iFOV = max( CVAR_GET_FLOAT( "default_fov" ), 90 );
m_iFOV = max( default_fov->value, 90 );
}
}
@ -56,11 +89,39 @@ int CHud :: Redraw( float flTime, int intermission )
m_fOldTime = m_flTime; // save time of previous redraw
m_flTime = flTime;
m_flTimeDelta = (double)m_flTime - m_fOldTime;
static m_flShotTime = 0;
// Clock was reset, reset delta
if ( m_flTimeDelta < 0 )
m_flTimeDelta = 0;
// Bring up the scoreboard during intermission
if (gViewPort)
{
if ( m_iIntermission && !intermission )
{
// Have to do this here so the scoreboard goes away
m_iIntermission = intermission;
gViewPort->HideCommandMenu();
gViewPort->HideScoreBoard();
}
else if ( !m_iIntermission && intermission )
{
gViewPort->HideCommandMenu();
gViewPort->ShowScoreBoard();
// Take a screenshot if the client's got the cvar set
if ( CVAR_GET_FLOAT( "hud_takesshots" ) != 0 )
m_flShotTime = flTime + 1.0; // Take a screenshot in a second
}
}
if (m_flShotTime && m_flShotTime < flTime)
{
gEngfuncs.pfnClientCmd("snapshot\n");
m_flShotTime = 0;
}
m_iIntermission = intermission;
// if no redrawing is necessary
@ -72,7 +133,7 @@ int CHud :: Redraw( float flTime, int intermission )
{
if ( !intermission )
{
if ((pList->p->m_iFlags & HUD_ACTIVE) && !(m_iHideHUDDisplay & HIDEHUD_ALL))
if ( (pList->p->m_iFlags & HUD_ACTIVE) && !(m_iHideHUDDisplay & HIDEHUD_ALL) )
pList->p->Draw(flTime);
}
else
@ -105,6 +166,28 @@ int CHud :: Redraw( float flTime, int intermission )
SPR_DrawAdditive(i, x, y, NULL);
}
/*
if ( g_iVisibleMouse )
{
void IN_GetMousePos( int *mx, int *my );
int mx, my;
IN_GetMousePos( &mx, &my );
if (m_hsprCursor == 0)
{
char sz[256];
sprintf( sz, "sprites/cursor.spr" );
m_hsprCursor = SPR_Load( sz );
}
SPR_Set(m_hsprCursor, 250, 250, 250 );
// Draw the logo at 20 fps
SPR_DrawAdditive( 0, mx, my, NULL );
}
*/
return 1;
}

1223
cl_dll/hud_servers.cpp Normal file

File diff suppressed because it is too large Load Diff

34
cl_dll/hud_servers.h Normal file
View File

@ -0,0 +1,34 @@
#if !defined( HUD_SERVERSH )
#define HUD_SERVERSH
#pragma once
#define NET_CALLBACK /* */
// Dispatchers
void NET_CALLBACK ListResponse( struct net_response_s *response );
void NET_CALLBACK ServerResponse( struct net_response_s *response );
void NET_CALLBACK PingResponse( struct net_response_s *response );
void NET_CALLBACK RulesResponse( struct net_response_s *response );
void NET_CALLBACK PlayersResponse( struct net_response_s *response );
void ServersInit( void );
void ServersShutdown( void );
void ServersThink( double time );
void ServersCancel( void );
// Get list and get server info from each
void ServersList( void );
// Query for IP / IPX LAN servers
void BroadcastServersList( int clearpending );
void ServerPing( int server );
void ServerRules( int server );
void ServerPlayers( int server );
int ServersGetCount( void );
const char *ServersGetInfo( int server );
int ServersIsQuerying( void );
void SortServers( const char *fieldname );
#endif // HUD_SERVERSH

91
cl_dll/hud_servers_priv.h Normal file
View File

@ -0,0 +1,91 @@
#if !defined( HUD_SERVERS_PRIVH )
#define HUD_SERVERS_PRIVH
#pragma once
#include "netadr.h"
class CHudServers
{
public:
typedef struct request_s
{
struct request_s *next;
netadr_t remote_address;
int context;
} request_t;
typedef struct server_s
{
struct server_s *next;
netadr_t remote_address;
char *info;
int ping;
} server_t;
CHudServers();
~CHudServers();
void Think( double time );
void QueryThink( void );
int isQuerying( void );
int LoadMasterAddresses( int maxservers, int *count, netadr_t *padr );
void RequestList( void );
void RequestBroadcastList( int clearpending );
void ServerPing( int server );
void ServerRules( int server );
void ServerPlayers( int server );
void CancelRequest( void );
int CompareServers( server_t *p1, server_t *p2 );
void ClearServerList( server_t **ppList );
void ClearRequestList( request_t **ppList );
void AddServer( server_t **ppList, server_t *p );
void RemoveServerFromList( request_t **ppList, request_t *item );
request_t *FindRequest( int context, request_t *pList );
int ServerListSize( void );
char *GetServerInfo( int server );
int GetServerCount( void );
void SortServers( const char *fieldname );
void ListResponse( struct net_response_s *response );
void ServerResponse( struct net_response_s *response );
void PingResponse( struct net_response_s *response );
void RulesResponse( struct net_response_s *response );
void PlayersResponse( struct net_response_s *response );
private:
server_t *GetServer( int server );
//
char m_szToken[ 1024 ];
int m_nRequesting;
int m_nDone;
double m_dStarted;
request_t *m_pServerList;
request_t *m_pActiveList;
server_t *m_pServers;
int m_nServerCount;
int m_nActiveQueries;
int m_nQuerying;
double m_fElapsed;
request_t *m_pPingRequest;
request_t *m_pRulesRequest;
request_t *m_pPlayersRequest;
};
#endif // HUD_SERVERS_PRIVH

View File

@ -18,25 +18,34 @@
#include <math.h>
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <stdlib.h>
#include <memory.h>
int CL_ButtonBits( int );
void CL_ResetButtonBits( int bits );
extern float v_idlescale;
float in_fov;
extern void HUD_SetCmdBits( int bits );
int CHud::UpdateClientData(client_data_t *cdata, float time)
{
memcpy(m_vecOrigin, cdata->origin, sizeof(vec3_t));
memcpy(m_vecAngles, cdata->viewangles, sizeof(vec3_t));
m_iKeyBits = cdata->iKeyBits;
m_iKeyBits = CL_ButtonBits( 0 );
m_iWeaponBits = cdata->iWeaponBits;
gHUD.Think();
cdata->iKeyBits = m_iKeyBits;
in_fov = cdata->fov;
Think();
cdata->fov = m_iFOV;
cdata->view_idlescale = m_iConcussionEffect;
v_idlescale = m_iConcussionEffect;
if ( m_flMouseSensitivity )
cdata->mouse_sensitivity = m_flMouseSensitivity;
CL_ResetButtonBits( m_iKeyBits );
// return 1 if in anything in the client_data struct has been changed, 0 otherwise
return 1;

614
cl_dll/in_camera.cpp Normal file
View File

@ -0,0 +1,614 @@
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
#include "kbutton.h"
#include "cvardef.h"
#include "usercmd.h"
#include "const.h"
#include "camera.h"
#include "in_defs.h"
#include "windows.h"
float CL_KeyState (kbutton_t *key);
extern "C"
{
void DLLEXPORT CAM_Think( void );
int DLLEXPORT CL_IsThirdPerson( void );
void DLLEXPORT CL_CameraOffset( float *ofs );
}
extern cl_enginefunc_t gEngfuncs;
//-------------------------------------------------- Constants
#define CAM_DIST_DELTA 1.0
#define CAM_ANGLE_DELTA 2.5
#define CAM_ANGLE_SPEED 2.5
#define CAM_MIN_DIST 30.0
#define CAM_ANGLE_MOVE .5
#define MAX_ANGLE_DIFF 10.0
#define PITCH_MAX 90.0
#define PITCH_MIN 0
#define YAW_MAX 135.0
#define YAW_MIN -135.0
enum ECAM_Command
{
CAM_COMMAND_NONE = 0,
CAM_COMMAND_TOTHIRDPERSON = 1,
CAM_COMMAND_TOFIRSTPERSON = 2
};
//-------------------------------------------------- Global Variables
cvar_t *cam_command;
cvar_t *cam_snapto;
cvar_t *cam_idealyaw;
cvar_t *cam_idealpitch;
cvar_t *cam_idealdist;
cvar_t *cam_contain;
cvar_t *c_maxpitch;
cvar_t *c_minpitch;
cvar_t *c_maxyaw;
cvar_t *c_minyaw;
cvar_t *c_maxdistance;
cvar_t *c_mindistance;
// pitch, yaw, dist
vec3_t cam_ofs;
// In third person
int cam_thirdperson;
int cam_mousemove; //true if we are moving the cam with the mouse, False if not
int iMouseInUse=0;
int cam_distancemove;
extern int mouse_x, mouse_y; //used to determine what the current x and y values are
int cam_old_mouse_x, cam_old_mouse_y; //holds the last ticks mouse movement
POINT cam_mouse;
//-------------------------------------------------- Local Variables
static kbutton_t cam_pitchup, cam_pitchdown, cam_yawleft, cam_yawright;
static kbutton_t cam_in, cam_out, cam_move;
//-------------------------------------------------- Prototypes
void CAM_ToThirdPerson(void);
void CAM_ToFirstPerson(void);
void CAM_StartDistance(void);
void CAM_EndDistance(void);
//-------------------------------------------------- Local Functions
float MoveToward( float cur, float goal, float maxspeed )
{
if( cur != goal )
{
if( abs( cur - goal ) > 180.0 )
{
if( cur < goal )
cur += 360.0;
else
cur -= 360.0;
}
if( cur < goal )
{
if( cur < goal - 1.0 )
cur += ( goal - cur ) / 4.0;
else
cur = goal;
}
else
{
if( cur > goal + 1.0 )
cur -= ( cur - goal ) / 4.0;
else
cur = goal;
}
}
// bring cur back into range
if( cur < 0 )
cur += 360.0;
else if( cur >= 360 )
cur -= 360;
return cur;
}
//-------------------------------------------------- Gobal Functions
typedef struct
{
vec3_t boxmins, boxmaxs;// enclose the test object along entire move
float *mins, *maxs; // size of the moving object
vec3_t mins2, maxs2; // size when clipping against mosnters
float *start, *end;
trace_t trace;
int type;
edict_t *passedict;
qboolean monsterclip;
} moveclip_t;
extern trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end);
void DLLEXPORT CAM_Think( void )
{
vec3_t origin;
vec3_t ext, pnt, camForward, camRight, camUp;
moveclip_t clip;
float dist;
vec3_t camAngles;
float flSensitivity;
#ifdef LATER
int i;
#endif
vec3_t viewangles;
switch( (int) cam_command->value )
{
case CAM_COMMAND_TOTHIRDPERSON:
CAM_ToThirdPerson();
break;
case CAM_COMMAND_TOFIRSTPERSON:
CAM_ToFirstPerson();
break;
case CAM_COMMAND_NONE:
default:
break;
}
if( !cam_thirdperson )
return;
#ifdef LATER
if ( cam_contain->value )
{
gEngfuncs.GetClientOrigin( origin );
ext[0] = ext[1] = ext[2] = 0.0;
}
#endif
camAngles[ PITCH ] = cam_idealpitch->value;
camAngles[ YAW ] = cam_idealyaw->value;
dist = cam_idealdist->value;
//
//movement of the camera with the mouse
//
if (cam_mousemove)
{
//get windows cursor position
GetCursorPos (&cam_mouse);
//check for X delta values and adjust accordingly
//eventually adjust YAW based on amount of movement
//don't do any movement of the cam using YAW/PITCH if we are zooming in/out the camera
if (!cam_distancemove)
{
//keep the camera within certain limits around the player (ie avoid certain bad viewing angles)
if (cam_mouse.x>gEngfuncs.GetWindowCenterX())
{
//if ((camAngles[YAW]>=225.0)||(camAngles[YAW]<135.0))
if (camAngles[YAW]<c_maxyaw->value)
{
camAngles[ YAW ] += (CAM_ANGLE_MOVE)*((cam_mouse.x-gEngfuncs.GetWindowCenterX())/2);
}
if (camAngles[YAW]>c_maxyaw->value)
{
camAngles[YAW]=c_maxyaw->value;
}
}
else if (cam_mouse.x<gEngfuncs.GetWindowCenterX())
{
//if ((camAngles[YAW]<=135.0)||(camAngles[YAW]>225.0))
if (camAngles[YAW]>c_minyaw->value)
{
camAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((gEngfuncs.GetWindowCenterX()-cam_mouse.x)/2);
}
if (camAngles[YAW]<c_minyaw->value)
{
camAngles[YAW]=c_minyaw->value;
}
}
//check for y delta values and adjust accordingly
//eventually adjust PITCH based on amount of movement
//also make sure camera is within bounds
if (cam_mouse.y>gEngfuncs.GetWindowCenterY())
{
if(camAngles[PITCH]<c_maxpitch->value)
{
camAngles[PITCH] +=(CAM_ANGLE_MOVE)* ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2);
}
if (camAngles[PITCH]>c_maxpitch->value)
{
camAngles[PITCH]=c_maxpitch->value;
}
}
else if (cam_mouse.y<gEngfuncs.GetWindowCenterY())
{
if (camAngles[PITCH]>c_minpitch->value)
{
camAngles[PITCH] -= (CAM_ANGLE_MOVE)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2);
}
if (camAngles[PITCH]<c_minpitch->value)
{
camAngles[PITCH]=c_minpitch->value;
}
}
//set old mouse coordinates to current mouse coordinates
//since we are done with the mouse
if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 )
{
cam_old_mouse_x=cam_mouse.x*flSensitivity;
cam_old_mouse_y=cam_mouse.y*flSensitivity;
}
else
{
cam_old_mouse_x=cam_mouse.x;
cam_old_mouse_y=cam_mouse.y;
}
SetCursorPos (gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY());
}
}
//Nathan code here
if( CL_KeyState( &cam_pitchup ) )
camAngles[ PITCH ] += CAM_ANGLE_DELTA;
else if( CL_KeyState( &cam_pitchdown ) )
camAngles[ PITCH ] -= CAM_ANGLE_DELTA;
if( CL_KeyState( &cam_yawleft ) )
camAngles[ YAW ] -= CAM_ANGLE_DELTA;
else if( CL_KeyState( &cam_yawright ) )
camAngles[ YAW ] += CAM_ANGLE_DELTA;
if( CL_KeyState( &cam_in ) )
{
dist -= CAM_DIST_DELTA;
if( dist < CAM_MIN_DIST )
{
// If we go back into first person, reset the angle
camAngles[ PITCH ] = 0;
camAngles[ YAW ] = 0;
dist = CAM_MIN_DIST;
}
}
else if( CL_KeyState( &cam_out ) )
dist += CAM_DIST_DELTA;
if (cam_distancemove)
{
if (cam_mouse.y>gEngfuncs.GetWindowCenterY())
{
if(dist<c_maxdistance->value)
{
dist +=CAM_DIST_DELTA * ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2);
}
if (dist>c_maxdistance->value)
{
dist=c_maxdistance->value;
}
}
else if (cam_mouse.y<gEngfuncs.GetWindowCenterY())
{
if (dist>c_mindistance->value)
{
dist -= (CAM_DIST_DELTA)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2);
}
if (dist<c_mindistance->value)
{
dist=c_mindistance->value;
}
}
//set old mouse coordinates to current mouse coordinates
//since we are done with the mouse
cam_old_mouse_x=cam_mouse.x*gHUD.GetSensitivity();
cam_old_mouse_y=cam_mouse.y*gHUD.GetSensitivity();
SetCursorPos (gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY());
}
#ifdef LATER
if( cam_contain->value )
{
// check new ideal
VectorCopy( origin, pnt );
AngleVectors( camAngles, camForward, camRight, camUp );
for (i=0 ; i<3 ; i++)
pnt[i] += -dist*camForward[i];
// check line from r_refdef.vieworg to pnt
memset ( &clip, 0, sizeof ( moveclip_t ) );
clip.trace = SV_ClipMoveToEntity( sv.edicts, r_refdef.vieworg, ext, ext, pnt );
if( clip.trace.fraction == 1.0 )
{
// update ideal
cam_idealpitch->value = camAngles[ PITCH ];
cam_idealyaw->value = camAngles[ YAW ];
cam_idealdist->value = dist;
}
}
else
#endif
{
// update ideal
cam_idealpitch->value = camAngles[ PITCH ];
cam_idealyaw->value = camAngles[ YAW ];
cam_idealdist->value = dist;
}
// Move towards ideal
VectorCopy( cam_ofs, camAngles );
gEngfuncs.GetViewAngles( (float *)viewangles );
if( cam_snapto->value )
{
camAngles[ YAW ] = cam_idealyaw->value + viewangles[ YAW ];
camAngles[ PITCH ] = cam_idealpitch->value + viewangles[ PITCH ];
camAngles[ 2 ] = cam_idealdist->value;
}
else
{
if( camAngles[ YAW ] - viewangles[ YAW ] != cam_idealyaw->value )
camAngles[ YAW ] = MoveToward( camAngles[ YAW ], cam_idealyaw->value + viewangles[ YAW ], CAM_ANGLE_SPEED );
if( camAngles[ PITCH ] - viewangles[ PITCH ] != cam_idealpitch->value )
camAngles[ PITCH ] = MoveToward( camAngles[ PITCH ], cam_idealpitch->value + viewangles[ PITCH ], CAM_ANGLE_SPEED );
if( abs( camAngles[ 2 ] - cam_idealdist->value ) < 2.0 )
camAngles[ 2 ] = cam_idealdist->value;
else
camAngles[ 2 ] += ( cam_idealdist->value - camAngles[ 2 ] ) / 4.0;
}
#ifdef LATER
if( cam_contain->value )
{
// Test new position
dist = camAngles[ ROLL ];
camAngles[ ROLL ] = 0;
VectorCopy( origin, pnt );
AngleVectors( camAngles, camForward, camRight, camUp );
for (i=0 ; i<3 ; i++)
pnt[i] += -dist*camForward[i];
// check line from r_refdef.vieworg to pnt
memset ( &clip, 0, sizeof ( moveclip_t ) );
ext[0] = ext[1] = ext[2] = 0.0;
clip.trace = SV_ClipMoveToEntity( sv.edicts, r_refdef.vieworg, ext, ext, pnt );
if( clip.trace.fraction != 1.0 )
return;
}
#endif
cam_ofs[ 0 ] = camAngles[ 0 ];
cam_ofs[ 1 ] = camAngles[ 1 ];
cam_ofs[ 2 ] = dist;
}
extern void KeyDown (kbutton_t *b); // HACK
extern void KeyUp (kbutton_t *b); // HACK
void CAM_PitchUpDown(void) { KeyDown( &cam_pitchup ); }
void CAM_PitchUpUp(void) { KeyUp( &cam_pitchup ); }
void CAM_PitchDownDown(void) { KeyDown( &cam_pitchdown ); }
void CAM_PitchDownUp(void) { KeyUp( &cam_pitchdown ); }
void CAM_YawLeftDown(void) { KeyDown( &cam_yawleft ); }
void CAM_YawLeftUp(void) { KeyUp( &cam_yawleft ); }
void CAM_YawRightDown(void) { KeyDown( &cam_yawright ); }
void CAM_YawRightUp(void) { KeyUp( &cam_yawright ); }
void CAM_InDown(void) { KeyDown( &cam_in ); }
void CAM_InUp(void) { KeyUp( &cam_in ); }
void CAM_OutDown(void) { KeyDown( &cam_out ); }
void CAM_OutUp(void) { KeyUp( &cam_out ); }
void CAM_ToThirdPerson(void)
{
vec3_t viewangles;
#if !defined( _DEBUG )
if ( gEngfuncs.GetMaxClients() > 1 )
{
// no thirdperson in multiplayer.
return;
}
#endif
gEngfuncs.GetViewAngles( (float *)viewangles );
if( !cam_thirdperson )
{
cam_thirdperson = 1;
cam_ofs[ YAW ] = viewangles[ YAW ];
cam_ofs[ PITCH ] = viewangles[ PITCH ];
cam_ofs[ 2 ] = CAM_MIN_DIST;
}
gEngfuncs.Cvar_SetValue( "cam_command", 0 );
}
void CAM_ToFirstPerson(void)
{
cam_thirdperson = 0;
gEngfuncs.Cvar_SetValue( "cam_command", 0 );
}
void CAM_ToggleSnapto( void )
{
cam_snapto->value = !cam_snapto->value;
}
void CAM_Init( void )
{
gEngfuncs.pfnAddCommand( "+campitchup", CAM_PitchUpDown );
gEngfuncs.pfnAddCommand( "-campitchup", CAM_PitchUpUp );
gEngfuncs.pfnAddCommand( "+campitchdown", CAM_PitchDownDown );
gEngfuncs.pfnAddCommand( "-campitchdown", CAM_PitchDownUp );
gEngfuncs.pfnAddCommand( "+camyawleft", CAM_YawLeftDown );
gEngfuncs.pfnAddCommand( "-camyawleft", CAM_YawLeftUp );
gEngfuncs.pfnAddCommand( "+camyawright", CAM_YawRightDown );
gEngfuncs.pfnAddCommand( "-camyawright", CAM_YawRightUp );
gEngfuncs.pfnAddCommand( "+camin", CAM_InDown );
gEngfuncs.pfnAddCommand( "-camin", CAM_InUp );
gEngfuncs.pfnAddCommand( "+camout", CAM_OutDown );
gEngfuncs.pfnAddCommand( "-camout", CAM_OutUp );
gEngfuncs.pfnAddCommand( "thirdperson", CAM_ToThirdPerson );
gEngfuncs.pfnAddCommand( "firstperson", CAM_ToFirstPerson );
gEngfuncs.pfnAddCommand( "+cammousemove",CAM_StartMouseMove);
gEngfuncs.pfnAddCommand( "-cammousemove",CAM_EndMouseMove);
gEngfuncs.pfnAddCommand( "+camdistance", CAM_StartDistance );
gEngfuncs.pfnAddCommand( "-camdistance", CAM_EndDistance );
gEngfuncs.pfnAddCommand( "snapto", CAM_ToggleSnapto );
cam_command = gEngfuncs.pfnRegisterVariable ( "cam_command", "0", 0 ); // tells camera to go to thirdperson
cam_snapto = gEngfuncs.pfnRegisterVariable ( "cam_snapto", "0", 0 ); // snap to thirdperson view
cam_idealyaw = gEngfuncs.pfnRegisterVariable ( "cam_idealyaw", "90", 0 ); // thirdperson yaw
cam_idealpitch = gEngfuncs.pfnRegisterVariable ( "cam_idealpitch", "0", 0 ); // thirperson pitch
cam_idealdist = gEngfuncs.pfnRegisterVariable ( "cam_idealdist", "64", 0 ); // thirdperson distance
cam_contain = gEngfuncs.pfnRegisterVariable ( "cam_contain", "0", 0 ); // contain camera to world
c_maxpitch = gEngfuncs.pfnRegisterVariable ( "c_maxpitch", "90.0", 0 );
c_minpitch = gEngfuncs.pfnRegisterVariable ( "c_minpitch", "0.0", 0 );
c_maxyaw = gEngfuncs.pfnRegisterVariable ( "c_maxyaw", "135.0", 0 );
c_minyaw = gEngfuncs.pfnRegisterVariable ( "c_minyaw", "-135.0", 0 );
c_maxdistance = gEngfuncs.pfnRegisterVariable ( "c_maxdistance", "200.0", 0 );
c_mindistance = gEngfuncs.pfnRegisterVariable ( "c_mindistance", "30.0", 0 );
}
void CAM_ClearStates( void )
{
vec3_t viewangles;
gEngfuncs.GetViewAngles( (float *)viewangles );
cam_pitchup.state = 0;
cam_pitchdown.state = 0;
cam_yawleft.state = 0;
cam_yawright.state = 0;
cam_in.state = 0;
cam_out.state = 0;
cam_thirdperson = 0;
cam_command->value = 0;
cam_mousemove=0;
cam_snapto->value = 0;
cam_distancemove = 0;
cam_ofs[ 0 ] = 0.0;
cam_ofs[ 1 ] = 0.0;
cam_ofs[ 2 ] = CAM_MIN_DIST;
cam_idealpitch->value = viewangles[ PITCH ];
cam_idealyaw->value = viewangles[ YAW ];
cam_idealdist->value = CAM_MIN_DIST;
}
void CAM_StartMouseMove(void)
{
float flSensitivity;
//only move the cam with mouse if we are in third person.
if (cam_thirdperson)
{
//set appropriate flags and initialize the old mouse position
//variables for mouse camera movement
if (!cam_mousemove)
{
cam_mousemove=1;
iMouseInUse=1;
GetCursorPos (&cam_mouse);
if ( ( flSensitivity = gHUD.GetSensitivity() ) != 0 )
{
cam_old_mouse_x=cam_mouse.x*flSensitivity;
cam_old_mouse_y=cam_mouse.y*flSensitivity;
}
else
{
cam_old_mouse_x=cam_mouse.x;
cam_old_mouse_y=cam_mouse.y;
}
}
}
//we are not in 3rd person view..therefore do not allow camera movement
else
{
cam_mousemove=0;
iMouseInUse=0;
}
}
//the key has been released for camera movement
//tell the engine that mouse camera movement is off
void CAM_EndMouseMove(void)
{
cam_mousemove=0;
iMouseInUse=0;
}
//----------------------------------------------------------
//routines to start the process of moving the cam in or out
//using the mouse
//----------------------------------------------------------
void CAM_StartDistance(void)
{
//only move the cam with mouse if we are in third person.
if (cam_thirdperson)
{
//set appropriate flags and initialize the old mouse position
//variables for mouse camera movement
if (!cam_distancemove)
{
cam_distancemove=1;
cam_mousemove=1;
iMouseInUse=1;
GetCursorPos (&cam_mouse);
cam_old_mouse_x=cam_mouse.x*gHUD.GetSensitivity();
cam_old_mouse_y=cam_mouse.y*gHUD.GetSensitivity();
}
}
//we are not in 3rd person view..therefore do not allow camera movement
else
{
cam_distancemove=0;
cam_mousemove=0;
iMouseInUse=0;
}
}
//the key has been released for camera movement
//tell the engine that mouse camera movement is off
void CAM_EndDistance(void)
{
cam_distancemove=0;
cam_mousemove=0;
iMouseInUse=0;
}
int DLLEXPORT CL_IsThirdPerson( void )
{
return cam_thirdperson ? 1 : 0;
}
void DLLEXPORT CL_CameraOffset( float *ofs )
{
VectorCopy( cam_ofs, ofs );
}

14
cl_dll/in_defs.h Normal file
View File

@ -0,0 +1,14 @@
#if !defined( IN_DEFSH )
#define IN_DEFSH
#pragma once
// up / down
#define PITCH 0
// left / right
#define YAW 1
// fall over
#define ROLL 2
#define DLLEXPORT __declspec( dllexport )
#endif

957
cl_dll/input.cpp Normal file
View File

@ -0,0 +1,957 @@
// cl.input.c -- builds an intended movement command to send to the server
//xxxxxx Move bob and pitch drifting code here and other stuff from view if needed
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
// rights reserved.
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
extern "C"
{
#include "kbutton.h"
}
#include "cvardef.h"
#include "usercmd.h"
#include "const.h"
#include "camera.h"
#include "in_defs.h"
#include "view.h"
#include <string.h>
#include <ctype.h>
#include "vgui_TeamFortressViewport.h"
extern "C"
{
struct kbutton_s DLLEXPORT *KB_Find( const char *name );
void DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int active );
void DLLEXPORT HUD_Shutdown( void );
int DLLEXPORT HUD_Key_Event( int eventcode, int keynum, const char *pszCurrentBinding );
}
extern int g_weaponselect;
extern cl_enginefunc_t gEngfuncs;
// Defined in pm_math.c
extern "C" float anglemod( float a );
void IN_Init (void);
void IN_Move ( float frametime, usercmd_t *cmd);
void IN_Shutdown( void );
void V_Init( void );
void VectorAngles( const float *forward, float *angles );
int CL_ButtonBits( int );
// xxx need client dll function to get and clear impuse
extern cvar_t *in_joystick;
int in_impulse = 0;
int in_cancel = 0;
cvar_t *m_pitch;
cvar_t *m_yaw;
cvar_t *m_forward;
cvar_t *m_side;
cvar_t *lookstrafe;
cvar_t *lookspring;
cvar_t *cl_pitchup;
cvar_t *cl_pitchdown;
cvar_t *cl_upspeed;
cvar_t *cl_forwardspeed;
cvar_t *cl_backspeed;
cvar_t *cl_sidespeed;
cvar_t *cl_movespeedkey;
cvar_t *cl_yawspeed;
cvar_t *cl_pitchspeed;
cvar_t *cl_anglespeedkey;
cvar_t *cl_vsmoothing;
/*
===============================================================================
KEY BUTTONS
Continuous button event tracking is complicated by the fact that two different
input sources (say, mouse button 1 and the control key) can both press the
same button, but the button should only be released when both of the
pressing key have been released.
When a key event issues a button command (+forward, +attack, etc), it appends
its key number as a parameter to the command so it can be matched up with
the release.
state bit 0 is the current state of the key
state bit 1 is edge triggered on the up to down transition
state bit 2 is edge triggered on the down to up transition
===============================================================================
*/
kbutton_t in_mlook;
kbutton_t in_klook;
kbutton_t in_jlook;
kbutton_t in_left;
kbutton_t in_right;
kbutton_t in_forward;
kbutton_t in_back;
kbutton_t in_lookup;
kbutton_t in_lookdown;
kbutton_t in_moveleft;
kbutton_t in_moveright;
kbutton_t in_strafe;
kbutton_t in_speed;
kbutton_t in_use;
kbutton_t in_jump;
kbutton_t in_attack;
kbutton_t in_attack2;
kbutton_t in_up;
kbutton_t in_down;
kbutton_t in_duck;
kbutton_t in_reload;
kbutton_t in_alt1;
kbutton_t in_score;
kbutton_t in_break;
kbutton_t in_graph; // Display the netgraph
typedef struct kblist_s
{
struct kblist_s *next;
kbutton_t *pkey;
char name[32];
} kblist_t;
kblist_t *g_kbkeys = NULL;
/*
============
KB_ConvertString
Removes references to +use and replaces them with the keyname in the output string. If
a binding is unfound, then the original text is retained.
NOTE: Only works for text with +word in it.
============
*/
int KB_ConvertString( char *in, char **ppout )
{
char sz[ 4096 ];
char binding[ 64 ];
char *p;
char *pOut;
char *pEnd;
const char *pBinding;
if ( !ppout )
return 0;
*ppout = NULL;
p = in;
pOut = sz;
while ( *p )
{
if ( *p == '+' )
{
pEnd = binding;
while ( *p && ( isalnum( *p ) || ( pEnd == binding ) ) && ( ( pEnd - binding ) < 63 ) )
{
*pEnd++ = *p++;
}
*pEnd = '\0';
pBinding = NULL;
if ( strlen( binding + 1 ) > 0 )
{
// See if there is a binding for binding?
pBinding = gEngfuncs.Key_LookupBinding( binding + 1 );
}
if ( pBinding )
{
*pOut++ = '[';
pEnd = (char *)pBinding;
}
else
{
pEnd = binding;
}
while ( *pEnd )
{
*pOut++ = *pEnd++;
}
if ( pBinding )
{
*pOut++ = ']';
}
}
else
{
*pOut++ = *p++;
}
}
*pOut = '\0';
pOut = ( char * )malloc( strlen( sz ) + 1 );
strcpy( pOut, sz );
*ppout = pOut;
return 1;
}
/*
============
KB_Find
Allows the engine to get a kbutton_t directly ( so it can check +mlook state, etc ) for saving out to .cfg files
============
*/
struct kbutton_s DLLEXPORT *KB_Find( const char *name )
{
kblist_t *p;
p = g_kbkeys;
while ( p )
{
if ( !stricmp( name, p->name ) )
return p->pkey;
p = p->next;
}
return NULL;
}
/*
============
KB_Add
Add a kbutton_t * to the list of pointers the engine can retrieve via KB_Find
============
*/
void KB_Add( const char *name, kbutton_t *pkb )
{
kblist_t *p;
kbutton_t *kb;
kb = KB_Find( name );
if ( kb )
return;
p = ( kblist_t * )malloc( sizeof( kblist_t ) );
memset( p, 0, sizeof( *p ) );
strcpy( p->name, name );
p->pkey = pkb;
p->next = g_kbkeys;
g_kbkeys = p;
}
/*
============
KB_Init
Add kbutton_t definitions that the engine can query if needed
============
*/
void KB_Init( void )
{
g_kbkeys = NULL;
KB_Add( "in_graph", &in_graph );
KB_Add( "in_mlook", &in_mlook );
KB_Add( "in_jlook", &in_jlook );
}
/*
============
KB_Shutdown
Clear kblist
============
*/
void KB_Shutdown( void )
{
kblist_t *p, *n;
p = g_kbkeys;
while ( p )
{
n = p->next;
free( p );
p = n;
}
g_kbkeys = NULL;
}
/*
============
KeyDown
============
*/
void KeyDown (kbutton_t *b)
{
int k;
char *c;
c = gEngfuncs.Cmd_Argv(1);
if (c[0])
k = atoi(c);
else
k = -1; // typed manually at the console for continuous down
if (k == b->down[0] || k == b->down[1])
return; // repeating key
if (!b->down[0])
b->down[0] = k;
else if (!b->down[1])
b->down[1] = k;
else
{
gEngfuncs.Con_DPrintf ("Three keys down for a button '%c' '%c' '%c'!\n", b->down[0], b->down[1], c);
return;
}
if (b->state & 1)
return; // still down
b->state |= 1 + 2; // down + impulse down
}
/*
============
KeyUp
============
*/
void KeyUp (kbutton_t *b)
{
int k;
char *c;
c = gEngfuncs.Cmd_Argv(1);
if (c[0])
k = atoi(c);
else
{ // typed manually at the console, assume for unsticking, so clear all
b->down[0] = b->down[1] = 0;
b->state = 4; // impulse up
return;
}
if (b->down[0] == k)
b->down[0] = 0;
else if (b->down[1] == k)
b->down[1] = 0;
else
return; // key up without coresponding down (menu pass through)
if (b->down[0] || b->down[1])
{
//Con_Printf ("Keys down for button: '%c' '%c' '%c' (%d,%d,%d)!\n", b->down[0], b->down[1], c, b->down[0], b->down[1], c);
return; // some other key is still holding it down
}
if (!(b->state & 1))
return; // still up (this should not happen)
b->state &= ~1; // now up
b->state |= 4; // impulse up
}
/*
============
HUD_Key_Event
Return 1 to allow engine to process the key, otherwise, act on it as needed
============
*/
int DLLEXPORT HUD_Key_Event( int down, int keynum, const char *pszCurrentBinding )
{
if (gViewPort)
return gViewPort->KeyInput(down, keynum, pszCurrentBinding);
return 1;
}
void IN_BreakDown( void ) { KeyDown( &in_break );};
void IN_BreakUp( void ) { KeyUp( &in_break ); };
void IN_KLookDown (void) {KeyDown(&in_klook);}
void IN_KLookUp (void) {KeyUp(&in_klook);}
void IN_JLookDown (void) {KeyDown(&in_jlook);}
void IN_JLookUp (void) {KeyUp(&in_jlook);}
void IN_MLookDown (void) {KeyDown(&in_mlook);}
void IN_UpDown(void) {KeyDown(&in_up);}
void IN_UpUp(void) {KeyUp(&in_up);}
void IN_DownDown(void) {KeyDown(&in_down);}
void IN_DownUp(void) {KeyUp(&in_down);}
void IN_LeftDown(void) {KeyDown(&in_left);}
void IN_LeftUp(void) {KeyUp(&in_left);}
void IN_RightDown(void) {KeyDown(&in_right);}
void IN_RightUp(void) {KeyUp(&in_right);}
void IN_ForwardDown(void) {KeyDown(&in_forward);}
void IN_ForwardUp(void) {KeyUp(&in_forward);}
void IN_BackDown(void) {KeyDown(&in_back);}
void IN_BackUp(void) {KeyUp(&in_back);}
void IN_LookupDown(void) {KeyDown(&in_lookup);}
void IN_LookupUp(void) {KeyUp(&in_lookup);}
void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
void IN_MoverightDown(void) {KeyDown(&in_moveright);}
void IN_MoverightUp(void) {KeyUp(&in_moveright);}
void IN_SpeedDown(void) {KeyDown(&in_speed);}
void IN_SpeedUp(void) {KeyUp(&in_speed);}
void IN_StrafeDown(void) {KeyDown(&in_strafe);}
void IN_StrafeUp(void) {KeyUp(&in_strafe);}
// needs capture by hud/vgui also
extern void __CmdFunc_InputPlayerSpecial(void);
void IN_Attack2Down(void)
{
KeyDown(&in_attack2);
__CmdFunc_InputPlayerSpecial();
}
void IN_Attack2Up(void) {KeyUp(&in_attack2);}
void IN_UseDown (void) {KeyDown(&in_use);}
void IN_UseUp (void) {KeyUp(&in_use);}
void IN_JumpDown (void) {KeyDown(&in_jump);}
void IN_JumpUp (void) {KeyUp(&in_jump);}
void IN_DuckDown(void) {KeyDown(&in_duck);}
void IN_DuckUp(void) {KeyUp(&in_duck);}
void IN_ReloadDown(void) {KeyDown(&in_reload);}
void IN_ReloadUp(void) {KeyUp(&in_reload);}
void IN_Alt1Down(void) {KeyDown(&in_alt1);}
void IN_Alt1Up(void) {KeyUp(&in_alt1);}
void IN_GraphDown(void) {KeyDown(&in_graph);}
void IN_GraphUp(void) {KeyUp(&in_graph);}
void IN_AttackDown(void)
{
KeyDown( &in_attack );
}
void IN_AttackUp(void)
{
KeyUp( &in_attack );
in_cancel = 0;
}
// Special handling
void IN_Cancel(void)
{
in_cancel = 1;
}
void IN_Impulse (void)
{
in_impulse = atoi( gEngfuncs.Cmd_Argv(1) );
}
void IN_ScoreDown(void)
{
KeyDown(&in_score);
if ( gViewPort )
{
gViewPort->ShowScoreBoard();
}
}
void IN_ScoreUp(void)
{
KeyUp(&in_score);
if ( gViewPort )
{
gViewPort->HideScoreBoard();
}
}
void IN_MLookUp (void)
{
KeyUp( &in_mlook );
if ( !( in_mlook.state & 1 ) && lookspring->value )
{
V_StartPitchDrift();
}
}
/*
===============
CL_KeyState
Returns 0.25 if a key was pressed and released during the frame,
0.5 if it was pressed and held
0 if held then released, and
1.0 if held for the entire time
===============
*/
float CL_KeyState (kbutton_t *key)
{
float val = 0.0;
int impulsedown, impulseup, down;
impulsedown = key->state & 2;
impulseup = key->state & 4;
down = key->state & 1;
if ( impulsedown && !impulseup )
{
// pressed and held this frame?
val = down ? 0.5 : 0.0;
}
if ( impulseup && !impulsedown )
{
// released this frame?
val = down ? 0.0 : 0.0;
}
if ( !impulsedown && !impulseup )
{
// held the entire frame?
val = down ? 1.0 : 0.0;
}
if ( impulsedown && impulseup )
{
if ( down )
{
// released and re-pressed this frame
val = 0.75;
}
else
{
// pressed and released this frame
val = 0.25;
}
}
// clear impulses
key->state &= 1;
return val;
}
/*
================
CL_AdjustAngles
Moves the local angle positions
================
*/
void CL_AdjustAngles ( float frametime, float *viewangles )
{
float speed;
float up, down;
if (in_speed.state & 1)
{
speed = frametime * cl_anglespeedkey->value;
}
else
{
speed = frametime;
}
if (!(in_strafe.state & 1))
{
viewangles[YAW] -= speed*cl_yawspeed->value*CL_KeyState (&in_right);
viewangles[YAW] += speed*cl_yawspeed->value*CL_KeyState (&in_left);
viewangles[YAW] = anglemod(viewangles[YAW]);
}
if (in_klook.state & 1)
{
V_StopPitchDrift ();
viewangles[PITCH] -= speed*cl_pitchspeed->value * CL_KeyState (&in_forward);
viewangles[PITCH] += speed*cl_pitchspeed->value * CL_KeyState (&in_back);
}
up = CL_KeyState (&in_lookup);
down = CL_KeyState(&in_lookdown);
viewangles[PITCH] -= speed*cl_pitchspeed->value * up;
viewangles[PITCH] += speed*cl_pitchspeed->value * down;
if (up || down)
V_StopPitchDrift ();
if (viewangles[PITCH] > cl_pitchdown->value)
viewangles[PITCH] = cl_pitchdown->value;
if (viewangles[PITCH] < -cl_pitchup->value)
viewangles[PITCH] = -cl_pitchup->value;
if (viewangles[ROLL] > 50)
viewangles[ROLL] = 50;
if (viewangles[ROLL] < -50)
viewangles[ROLL] = -50;
}
/*
================
CL_CreateMove
Send the intended movement message to the server
if active == 1 then we are 1) not playing back demos ( where our commands are ignored ) and
2 ) we have finished signing on to server
================
*/
void DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int active )
{
float spd;
vec3_t viewangles;
static vec3_t oldangles;
if ( active )
{
//memset( viewangles, 0, sizeof( vec3_t ) );
//viewangles[ 0 ] = viewangles[ 1 ] = viewangles[ 2 ] = 0.0;
gEngfuncs.GetViewAngles( (float *)viewangles );
CL_AdjustAngles ( frametime, viewangles );
memset (cmd, 0, sizeof(*cmd));
gEngfuncs.SetViewAngles( (float *)viewangles );
if ( in_strafe.state & 1 )
{
cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right);
cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left);
}
cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright);
cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft);
cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up);
cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down);
if ( !(in_klook.state & 1 ) )
{
cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward);
cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back);
}
// adjust for speed key
if ( in_speed.state & 1 )
{
cmd->forwardmove *= cl_movespeedkey->value;
cmd->sidemove *= cl_movespeedkey->value;
cmd->upmove *= cl_movespeedkey->value;
}
// clip to maxspeed
spd = gEngfuncs.GetClientMaxspeed();
if ( spd != 0.0 )
{
// scale the 3 speeds so that the total velocity is not > cl.maxspeed
float fmov = sqrt( (cmd->forwardmove*cmd->forwardmove) + (cmd->sidemove*cmd->sidemove) + (cmd->upmove*cmd->upmove) );
if ( fmov > spd )
{
float fratio = spd / fmov;
cmd->forwardmove *= fratio;
cmd->sidemove *= fratio;
cmd->upmove *= fratio;
}
}
// Allow mice and other controllers to add their inputs
IN_Move ( frametime, cmd );
}
cmd->impulse = in_impulse;
in_impulse = 0;
cmd->weaponselect = g_weaponselect;
g_weaponselect = 0;
//
// set button and flag bits
//
cmd->buttons = CL_ButtonBits( 1 );
// Using joystick?
if ( in_joystick->value )
{
if ( cmd->forwardmove > 0 )
{
cmd->buttons |= IN_FORWARD;
}
else if ( cmd->forwardmove < 0 )
{
cmd->buttons |= IN_BACK;
}
}
gEngfuncs.GetViewAngles( (float *)viewangles );
// Set current view angles.
if ( gHUD.m_Health.m_iHealth > 0 )
{
VectorCopy( viewangles, cmd->viewangles );
VectorCopy( viewangles, oldangles );
}
else
{
VectorCopy( oldangles, cmd->viewangles );
}
}
/*
============
CL_IsDead
Returns 1 if health is <= 0
============
*/
int CL_IsDead( void )
{
return ( gHUD.m_Health.m_iHealth <= 0 ) ? 1 : 0;
}
/*
============
CL_ButtonBits
Returns appropriate button info for keyboard and mouse state
Set bResetState to 1 to clear old state info
============
*/
int CL_ButtonBits( int bResetState )
{
int bits = 0;
if ( in_attack.state & 3 )
{
bits |= IN_ATTACK;
}
if (in_duck.state & 3)
{
bits |= IN_DUCK;
}
if (in_jump.state & 3)
{
bits |= IN_JUMP;
}
if ( in_forward.state & 3 )
{
bits |= IN_FORWARD;
}
if (in_back.state & 3)
{
bits |= IN_BACK;
}
if (in_use.state & 3)
{
bits |= IN_USE;
}
if (in_cancel)
{
bits |= IN_CANCEL;
}
if ( in_left.state & 3 )
{
bits |= IN_LEFT;
}
if (in_right.state & 3)
{
bits |= IN_RIGHT;
}
if ( in_moveleft.state & 3 )
{
bits |= IN_MOVELEFT;
}
if (in_moveright.state & 3)
{
bits |= IN_MOVERIGHT;
}
if (in_attack2.state & 3)
{
bits |= IN_ATTACK2;
}
if (in_reload.state & 3)
{
bits |= IN_RELOAD;
}
if (in_alt1.state & 3)
{
bits |= IN_ALT1;
}
if ( in_score.state & 3 )
{
bits |= IN_SCORE;
}
// Dead or in intermission? Shore scoreboard, too
if ( CL_IsDead() || gHUD.m_iIntermission )
{
bits |= IN_SCORE;
}
if ( bResetState )
{
in_attack.state &= ~2;
in_duck.state &= ~2;
in_jump.state &= ~2;
in_forward.state &= ~2;
in_back.state &= ~2;
in_use.state &= ~2;
in_left.state &= ~2;
in_right.state &= ~2;
in_moveleft.state &= ~2;
in_moveright.state &= ~2;
in_attack2.state &= ~2;
in_reload.state &= ~2;
in_alt1.state &= ~2;
in_score.state &= ~2;
}
return bits;
}
/*
============
CL_ResetButtonBits
============
*/
void CL_ResetButtonBits( int bits )
{
int bitsNew = CL_ButtonBits( 0 ) ^ bits;
// Has the attack button been changed
if ( bitsNew & IN_ATTACK )
{
// Was it pressed? or let go?
if ( bits & IN_ATTACK )
{
KeyDown( &in_attack );
}
else
{
// totally clear state
in_attack.state &= ~7;
}
}
}
/*
============
InitInput
============
*/
void InitInput (void)
{
gEngfuncs.pfnAddCommand ("+moveup",IN_UpDown);
gEngfuncs.pfnAddCommand ("-moveup",IN_UpUp);
gEngfuncs.pfnAddCommand ("+movedown",IN_DownDown);
gEngfuncs.pfnAddCommand ("-movedown",IN_DownUp);
gEngfuncs.pfnAddCommand ("+left",IN_LeftDown);
gEngfuncs.pfnAddCommand ("-left",IN_LeftUp);
gEngfuncs.pfnAddCommand ("+right",IN_RightDown);
gEngfuncs.pfnAddCommand ("-right",IN_RightUp);
gEngfuncs.pfnAddCommand ("+forward",IN_ForwardDown);
gEngfuncs.pfnAddCommand ("-forward",IN_ForwardUp);
gEngfuncs.pfnAddCommand ("+back",IN_BackDown);
gEngfuncs.pfnAddCommand ("-back",IN_BackUp);
gEngfuncs.pfnAddCommand ("+lookup", IN_LookupDown);
gEngfuncs.pfnAddCommand ("-lookup", IN_LookupUp);
gEngfuncs.pfnAddCommand ("+lookdown", IN_LookdownDown);
gEngfuncs.pfnAddCommand ("-lookdown", IN_LookdownUp);
gEngfuncs.pfnAddCommand ("+strafe", IN_StrafeDown);
gEngfuncs.pfnAddCommand ("-strafe", IN_StrafeUp);
gEngfuncs.pfnAddCommand ("+moveleft", IN_MoveleftDown);
gEngfuncs.pfnAddCommand ("-moveleft", IN_MoveleftUp);
gEngfuncs.pfnAddCommand ("+moveright", IN_MoverightDown);
gEngfuncs.pfnAddCommand ("-moveright", IN_MoverightUp);
gEngfuncs.pfnAddCommand ("+speed", IN_SpeedDown);
gEngfuncs.pfnAddCommand ("-speed", IN_SpeedUp);
gEngfuncs.pfnAddCommand ("+attack", IN_AttackDown);
gEngfuncs.pfnAddCommand ("-attack", IN_AttackUp);
gEngfuncs.pfnAddCommand ("+attack2", IN_Attack2Down);
gEngfuncs.pfnAddCommand ("-attack2", IN_Attack2Up);
gEngfuncs.pfnAddCommand ("+use", IN_UseDown);
gEngfuncs.pfnAddCommand ("-use", IN_UseUp);
gEngfuncs.pfnAddCommand ("+jump", IN_JumpDown);
gEngfuncs.pfnAddCommand ("-jump", IN_JumpUp);
gEngfuncs.pfnAddCommand ("impulse", IN_Impulse);
gEngfuncs.pfnAddCommand ("+klook", IN_KLookDown);
gEngfuncs.pfnAddCommand ("-klook", IN_KLookUp);
gEngfuncs.pfnAddCommand ("+mlook", IN_MLookDown);
gEngfuncs.pfnAddCommand ("-mlook", IN_MLookUp);
gEngfuncs.pfnAddCommand ("+jlook", IN_JLookDown);
gEngfuncs.pfnAddCommand ("-jlook", IN_JLookUp);
gEngfuncs.pfnAddCommand ("+duck", IN_DuckDown);
gEngfuncs.pfnAddCommand ("-duck", IN_DuckUp);
gEngfuncs.pfnAddCommand ("+reload", IN_ReloadDown);
gEngfuncs.pfnAddCommand ("-reload", IN_ReloadUp);
gEngfuncs.pfnAddCommand ("+alt1", IN_Alt1Down);
gEngfuncs.pfnAddCommand ("-alt1", IN_Alt1Up);
gEngfuncs.pfnAddCommand ("+score", IN_ScoreDown);
gEngfuncs.pfnAddCommand ("-score", IN_ScoreUp);
gEngfuncs.pfnAddCommand ("+showscores", IN_ScoreDown);
gEngfuncs.pfnAddCommand ("-showscores", IN_ScoreUp);
gEngfuncs.pfnAddCommand ("+graph", IN_GraphDown);
gEngfuncs.pfnAddCommand ("-graph", IN_GraphUp);
gEngfuncs.pfnAddCommand ("+break",IN_BreakDown);
gEngfuncs.pfnAddCommand ("-break",IN_BreakUp);
lookstrafe = gEngfuncs.pfnRegisterVariable ( "lookstrafe", "0", FCVAR_ARCHIVE );
lookspring = gEngfuncs.pfnRegisterVariable ( "lookspring", "0", FCVAR_ARCHIVE );
cl_anglespeedkey = gEngfuncs.pfnRegisterVariable ( "cl_anglespeedkey", "0.67", 0 );
cl_yawspeed = gEngfuncs.pfnRegisterVariable ( "cl_yawspeed", "210", 0 );
cl_pitchspeed = gEngfuncs.pfnRegisterVariable ( "cl_pitchspeed", "225", 0 );
cl_upspeed = gEngfuncs.pfnRegisterVariable ( "cl_upspeed", "320", 0 );
cl_forwardspeed = gEngfuncs.pfnRegisterVariable ( "cl_forwardspeed", "400", FCVAR_ARCHIVE );
cl_backspeed = gEngfuncs.pfnRegisterVariable ( "cl_backspeed", "400", FCVAR_ARCHIVE );
cl_sidespeed = gEngfuncs.pfnRegisterVariable ( "cl_sidespeed", "400", 0 );
cl_movespeedkey = gEngfuncs.pfnRegisterVariable ( "cl_movespeedkey", "0.3", 0 );
cl_pitchup = gEngfuncs.pfnRegisterVariable ( "cl_pitchup", "89", 0 );
cl_pitchdown = gEngfuncs.pfnRegisterVariable ( "cl_pitchdown", "89", 0 );
cl_vsmoothing = gEngfuncs.pfnRegisterVariable ( "cl_vsmoothing", "0.05", FCVAR_ARCHIVE );
m_pitch = gEngfuncs.pfnRegisterVariable ( "m_pitch","0.022", FCVAR_ARCHIVE );
m_yaw = gEngfuncs.pfnRegisterVariable ( "m_yaw","0.022", FCVAR_ARCHIVE );
m_forward = gEngfuncs.pfnRegisterVariable ( "m_forward","1", FCVAR_ARCHIVE );
m_side = gEngfuncs.pfnRegisterVariable ( "m_side","0.8", FCVAR_ARCHIVE );
// Initialize third person camera controls.
CAM_Init();
// Initialize inputs
IN_Init();
// Initialize keyboard
KB_Init();
// Initialize view system
V_Init();
}
/*
============
ShutdownInput
============
*/
void ShutdownInput (void)
{
IN_Shutdown();
KB_Shutdown();
}
void DLLEXPORT HUD_Shutdown( void )
{
ShutdownInput();
}

940
cl_dll/inputw32.cpp Normal file
View File

@ -0,0 +1,940 @@
// in_win.c -- windows 95 mouse and joystick code
// 02/21/97 JCB Added extended DirectInput code to support external controllers.
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
#include "kbutton.h"
#include "cvardef.h"
#include "usercmd.h"
#include "const.h"
#include "camera.h"
#include "in_defs.h"
#include "../engine/keydefs.h"
#include "view.h"
#include "windows.h"
#define MOUSE_BUTTON_COUNT 5
// Set this to 1 to show mouse cursor. Experimental
int g_iVisibleMouse = 0;
extern "C"
{
void DLLEXPORT IN_ActivateMouse( void );
void DLLEXPORT IN_DeactivateMouse( void );
void DLLEXPORT IN_MouseEvent (int mstate);
void DLLEXPORT IN_Accumulate (void);
void DLLEXPORT IN_ClearStates (void);
}
extern cl_enginefunc_t gEngfuncs;
extern int iMouseInUse;
extern kbutton_t in_strafe;
extern kbutton_t in_mlook;
extern kbutton_t in_speed;
extern kbutton_t in_jlook;
extern cvar_t *m_pitch;
extern cvar_t *m_yaw;
extern cvar_t *m_forward;
extern cvar_t *m_side;
extern cvar_t *lookstrafe;
extern cvar_t *lookspring;
extern cvar_t *cl_pitchdown;
extern cvar_t *cl_pitchup;
extern cvar_t *cl_yawspeed;
extern cvar_t *cl_sidespeed;
extern cvar_t *cl_forwardspeed;
extern cvar_t *cl_pitchspeed;
extern cvar_t *cl_movespeedkey;
// mouse variables
cvar_t *m_filter;
cvar_t *sensitivity;
int mouse_buttons;
int mouse_oldbuttonstate;
POINT current_pos;
int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
static int restore_spi;
static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1};
static int mouseactive;
int mouseinitialized;
static int mouseparmsvalid;
static int mouseshowtoggle = 1;
// joystick defines and variables
// where should defines be moved?
#define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick
#define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball
#define JOY_MAX_AXES 6 // X, Y, Z, R, U, V
#define JOY_AXIS_X 0
#define JOY_AXIS_Y 1
#define JOY_AXIS_Z 2
#define JOY_AXIS_R 3
#define JOY_AXIS_U 4
#define JOY_AXIS_V 5
enum _ControlList
{
AxisNada = 0,
AxisForward,
AxisLook,
AxisSide,
AxisTurn
};
DWORD dwAxisFlags[JOY_MAX_AXES] =
{
JOY_RETURNX,
JOY_RETURNY,
JOY_RETURNZ,
JOY_RETURNR,
JOY_RETURNU,
JOY_RETURNV
};
DWORD dwAxisMap[ JOY_MAX_AXES ];
DWORD dwControlMap[ JOY_MAX_AXES ];
PDWORD pdwRawValue[ JOY_MAX_AXES ];
// none of these cvars are saved over a session
// this means that advanced controller configuration needs to be executed
// each time. this avoids any problems with getting back to a default usage
// or when changing from one controller to another. this way at least something
// works.
cvar_t *in_joystick;
cvar_t *joy_name;
cvar_t *joy_advanced;
cvar_t *joy_advaxisx;
cvar_t *joy_advaxisy;
cvar_t *joy_advaxisz;
cvar_t *joy_advaxisr;
cvar_t *joy_advaxisu;
cvar_t *joy_advaxisv;
cvar_t *joy_forwardthreshold;
cvar_t *joy_sidethreshold;
cvar_t *joy_pitchthreshold;
cvar_t *joy_yawthreshold;
cvar_t *joy_forwardsensitivity;
cvar_t *joy_sidesensitivity;
cvar_t *joy_pitchsensitivity;
cvar_t *joy_yawsensitivity;
cvar_t *joy_wwhack1;
cvar_t *joy_wwhack2;
int joy_avail, joy_advancedinit, joy_haspov;
DWORD joy_oldbuttonstate, joy_oldpovstate;
int joy_id;
DWORD joy_flags;
DWORD joy_numbuttons;
static JOYINFOEX ji;
/*
===========
Force_CenterView_f
===========
*/
void Force_CenterView_f (void)
{
vec3_t viewangles;
if (!iMouseInUse)
{
gEngfuncs.GetViewAngles( (float *)viewangles );
viewangles[PITCH] = 0;
gEngfuncs.SetViewAngles( (float *)viewangles );
}
}
/*
===========
IN_ActivateMouse
===========
*/
void DLLEXPORT IN_ActivateMouse (void)
{
if (mouseinitialized)
{
if (mouseparmsvalid)
restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0);
mouseactive = 1;
}
}
/*
===========
IN_DeactivateMouse
===========
*/
void DLLEXPORT IN_DeactivateMouse (void)
{
if (mouseinitialized)
{
if (restore_spi)
SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0);
mouseactive = 0;
}
}
/*
===========
IN_StartupMouse
===========
*/
void IN_StartupMouse (void)
{
if ( gEngfuncs.CheckParm ("-nomouse", NULL ) )
return;
mouseinitialized = 1;
mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0);
if (mouseparmsvalid)
{
if ( gEngfuncs.CheckParm ("-noforcemspd", NULL ) )
newmouseparms[2] = originalmouseparms[2];
if ( gEngfuncs.CheckParm ("-noforcemaccel", NULL ) )
{
newmouseparms[0] = originalmouseparms[0];
newmouseparms[1] = originalmouseparms[1];
}
if ( gEngfuncs.CheckParm ("-noforcemparms", NULL ) )
{
newmouseparms[0] = originalmouseparms[0];
newmouseparms[1] = originalmouseparms[1];
newmouseparms[2] = originalmouseparms[2];
}
}
mouse_buttons = MOUSE_BUTTON_COUNT;
}
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown (void)
{
IN_DeactivateMouse ();
}
/*
===========
IN_GetMousePos
Ask for mouse position from engine
===========
*/
void IN_GetMousePos( int *mx, int *my )
{
gEngfuncs.GetMousePosition( mx, my );
}
/*
===========
IN_ResetMouse
FIXME: Call through to engine?
===========
*/
void IN_ResetMouse( void )
{
SetCursorPos ( gEngfuncs.GetWindowCenterX(), gEngfuncs.GetWindowCenterY() );
}
/*
===========
IN_MouseEvent
===========
*/
void DLLEXPORT IN_MouseEvent (int mstate)
{
int i;
if ( iMouseInUse || g_iVisibleMouse )
return;
// perform button actions
for (i=0 ; i<mouse_buttons ; i++)
{
if ( (mstate & (1<<i)) &&
!(mouse_oldbuttonstate & (1<<i)) )
{
gEngfuncs.Key_Event (K_MOUSE1 + i, 1);
}
if ( !(mstate & (1<<i)) &&
(mouse_oldbuttonstate & (1<<i)) )
{
gEngfuncs.Key_Event (K_MOUSE1 + i, 0);
}
}
mouse_oldbuttonstate = mstate;
}
/*
===========
IN_MouseMove
===========
*/
void IN_MouseMove ( float frametime, usercmd_t *cmd)
{
int mx, my;
vec3_t viewangles;
gEngfuncs.GetViewAngles( (float *)viewangles );
if ( in_mlook.state & 1)
{
V_StopPitchDrift ();
}
//jjb - this disbles normal mouse control if the user is trying to
// move the camera, or if the mouse cursor is visible or if we're in intermission
if ( !iMouseInUse && !g_iVisibleMouse && !gHUD.m_iIntermission )
{
GetCursorPos (&current_pos);
mx = current_pos.x - gEngfuncs.GetWindowCenterX() + mx_accum;
my = current_pos.y - gEngfuncs.GetWindowCenterY() + my_accum;
mx_accum = 0;
my_accum = 0;
if (m_filter->value)
{
mouse_x = (mx + old_mouse_x) * 0.5;
mouse_y = (my + old_mouse_y) * 0.5;
}
else
{
mouse_x = mx;
mouse_y = my;
}
old_mouse_x = mx;
old_mouse_y = my;
if ( gHUD.GetSensitivity() != 0 )
{
mouse_x *= gHUD.GetSensitivity();
mouse_y *= gHUD.GetSensitivity();
}
else
{
mouse_x *= sensitivity->value;
mouse_y *= sensitivity->value;
}
// add mouse X/Y movement to cmd
if ( (in_strafe.state & 1) || (lookstrafe->value && (in_mlook.state & 1) ))
cmd->sidemove += m_side->value * mouse_x;
else
viewangles[YAW] -= m_yaw->value * mouse_x;
if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
{
viewangles[PITCH] += m_pitch->value * mouse_y;
if (viewangles[PITCH] > cl_pitchdown->value)
viewangles[PITCH] = cl_pitchdown->value;
if (viewangles[PITCH] < -cl_pitchup->value)
viewangles[PITCH] = -cl_pitchup->value;
}
else
{
if ((in_strafe.state & 1) && gEngfuncs.IsNoClipping() )
{
cmd->upmove -= m_forward->value * mouse_y;
}
else
{
cmd->forwardmove -= m_forward->value * mouse_y;
}
}
// if the mouse has moved, force it to the center, so there's room to move
if ( mx || my )
{
IN_ResetMouse();
}
}
gEngfuncs.SetViewAngles( (float *)viewangles );
/*
//#define TRACE_TEST
#if defined( TRACE_TEST )
{
int mx, my;
void V_Move( int mx, int my );
IN_GetMousePos( &mx, &my );
V_Move( mx, my );
}
#endif
*/
}
/*
===========
IN_Accumulate
===========
*/
void DLLEXPORT IN_Accumulate (void)
{
//only accumulate mouse if we are not moving the camera with the mouse
if ( !iMouseInUse && !g_iVisibleMouse )
{
if (mouseactive)
{
GetCursorPos (&current_pos);
mx_accum += current_pos.x - gEngfuncs.GetWindowCenterX();
my_accum += current_pos.y - gEngfuncs.GetWindowCenterY();
// force the mouse to the center, so there's room to move
IN_ResetMouse();
}
}
}
/*
===================
IN_ClearStates
===================
*/
void DLLEXPORT IN_ClearStates (void)
{
if ( !mouseactive )
return;
mx_accum = 0;
my_accum = 0;
mouse_oldbuttonstate = 0;
}
/*
===============
IN_StartupJoystick
===============
*/
void IN_StartupJoystick (void)
{
int numdevs;
JOYCAPS jc;
MMRESULT mmr;
// assume no joystick
joy_avail = 0;
// abort startup if user requests no joystick
if ( gEngfuncs.CheckParm ("-nojoy", NULL ) )
return;
// verify joystick driver is present
if ((numdevs = joyGetNumDevs ()) == 0)
{
gEngfuncs.Con_DPrintf ("joystick not found -- driver not present\n\n");
return;
}
// cycle through the joystick ids for the first valid one
for (joy_id=0 ; joy_id<numdevs ; joy_id++)
{
memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji);
ji.dwFlags = JOY_RETURNCENTERED;
if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR)
break;
}
// abort startup if we didn't find a valid joystick
if (mmr != JOYERR_NOERROR)
{
gEngfuncs.Con_DPrintf ("joystick not found -- no valid joysticks (%x)\n\n", mmr);
return;
}
// get the capabilities of the selected joystick
// abort startup if command fails
memset (&jc, 0, sizeof(jc));
if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR)
{
gEngfuncs.Con_DPrintf ("joystick not found -- invalid joystick capabilities (%x)\n\n", mmr);
return;
}
// save the joystick's number of buttons and POV status
joy_numbuttons = jc.wNumButtons;
joy_haspov = jc.wCaps & JOYCAPS_HASPOV;
// old button and POV states default to no buttons pressed
joy_oldbuttonstate = joy_oldpovstate = 0;
// mark the joystick as available and advanced initialization not completed
// this is needed as cvars are not available during initialization
gEngfuncs.Con_Printf ("joystick found\n\n", mmr);
joy_avail = 1;
joy_advancedinit = 0;
}
/*
===========
RawValuePointer
===========
*/
PDWORD RawValuePointer (int axis)
{
switch (axis)
{
case JOY_AXIS_X:
return &ji.dwXpos;
case JOY_AXIS_Y:
return &ji.dwYpos;
case JOY_AXIS_Z:
return &ji.dwZpos;
case JOY_AXIS_R:
return &ji.dwRpos;
case JOY_AXIS_U:
return &ji.dwUpos;
case JOY_AXIS_V:
return &ji.dwVpos;
}
// FIX: need to do some kind of error
return &ji.dwXpos;
}
/*
===========
Joy_AdvancedUpdate_f
===========
*/
void Joy_AdvancedUpdate_f (void)
{
// called once by IN_ReadJoystick and by user whenever an update is needed
// cvars are now available
int i;
DWORD dwTemp;
// initialize all the maps
for (i = 0; i < JOY_MAX_AXES; i++)
{
dwAxisMap[i] = AxisNada;
dwControlMap[i] = JOY_ABSOLUTE_AXIS;
pdwRawValue[i] = RawValuePointer(i);
}
if( joy_advanced->value == 0.0)
{
// default joystick initialization
// 2 axes only with joystick control
dwAxisMap[JOY_AXIS_X] = AxisTurn;
// dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS;
dwAxisMap[JOY_AXIS_Y] = AxisForward;
// dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS;
}
else
{
if ( strcmp ( joy_name->string, "joystick") != 0 )
{
// notify user of advanced controller
gEngfuncs.Con_Printf ("\n%s configured\n\n", joy_name->string);
}
// advanced initialization here
// data supplied by user via joy_axisn cvars
dwTemp = (DWORD) joy_advaxisx->value;
dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisy->value;
dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisz->value;
dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisr->value;
dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisu->value;
dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS;
dwTemp = (DWORD) joy_advaxisv->value;
dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f;
dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS;
}
// compute the axes to collect from DirectInput
joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV;
for (i = 0; i < JOY_MAX_AXES; i++)
{
if (dwAxisMap[i] != AxisNada)
{
joy_flags |= dwAxisFlags[i];
}
}
}
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
int i, key_index;
DWORD buttonstate, povstate;
if (!joy_avail)
{
return;
}
// loop through the joystick buttons
// key a joystick event or auxillary event for higher number buttons for each state change
buttonstate = ji.dwButtons;
for (i=0 ; i < (int)joy_numbuttons ; i++)
{
if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) )
{
key_index = (i < 4) ? K_JOY1 : K_AUX1;
gEngfuncs.Key_Event (key_index + i, 1);
}
if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) )
{
key_index = (i < 4) ? K_JOY1 : K_AUX1;
gEngfuncs.Key_Event (key_index + i, 0);
}
}
joy_oldbuttonstate = buttonstate;
if (joy_haspov)
{
// convert POV information into 4 bits of state information
// this avoids any potential problems related to moving from one
// direction to another without going through the center position
povstate = 0;
if(ji.dwPOV != JOY_POVCENTERED)
{
if (ji.dwPOV == JOY_POVFORWARD)
povstate |= 0x01;
if (ji.dwPOV == JOY_POVRIGHT)
povstate |= 0x02;
if (ji.dwPOV == JOY_POVBACKWARD)
povstate |= 0x04;
if (ji.dwPOV == JOY_POVLEFT)
povstate |= 0x08;
}
// determine which bits have changed and key an auxillary event for each change
for (i=0 ; i < 4 ; i++)
{
if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) )
{
gEngfuncs.Key_Event (K_AUX29 + i, 1);
}
if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) )
{
gEngfuncs.Key_Event (K_AUX29 + i, 0);
}
}
joy_oldpovstate = povstate;
}
}
/*
===============
IN_ReadJoystick
===============
*/
int IN_ReadJoystick (void)
{
memset (&ji, 0, sizeof(ji));
ji.dwSize = sizeof(ji);
ji.dwFlags = joy_flags;
if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR)
{
// this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver
// rather than having 32768 be the zero point, they have the zero point at 32668
// go figure -- anyway, now we get the full resolution out of the device
if (joy_wwhack1->value != 0.0)
{
ji.dwUpos += 100;
}
return 1;
}
else
{
// read error occurred
// turning off the joystick seems too harsh for 1 read error,\
// but what should be done?
// Con_Printf ("IN_ReadJoystick: no response\n");
// joy_avail = 0;
return 0;
}
}
/*
===========
IN_JoyMove
===========
*/
void IN_JoyMove ( float frametime, usercmd_t *cmd )
{
float speed, aspeed;
float fAxisValue, fTemp;
int i;
vec3_t viewangles;
gEngfuncs.GetViewAngles( (float *)viewangles );
// complete initialization if first time in
// this is needed as cvars are not available at initialization time
if( joy_advancedinit != 1 )
{
Joy_AdvancedUpdate_f();
joy_advancedinit = 1;
}
// verify joystick is available and that the user wants to use it
if (!joy_avail || !in_joystick->value)
{
return;
}
// collect the joystick data, if possible
if (IN_ReadJoystick () != 1)
{
return;
}
if (in_speed.state & 1)
speed = cl_movespeedkey->value;
else
speed = 1;
aspeed = speed * frametime;
// loop through the axes
for (i = 0; i < JOY_MAX_AXES; i++)
{
// get the floating point zero-centered, potentially-inverted data for the current axis
fAxisValue = (float) *pdwRawValue[i];
// move centerpoint to zero
fAxisValue -= 32768.0;
if (joy_wwhack2->value != 0.0)
{
if (dwAxisMap[i] == AxisTurn)
{
// this is a special formula for the Logitech WingMan Warrior
// y=ax^b; where a = 300 and b = 1.3
// also x values are in increments of 800 (so this is factored out)
// then bounds check result to level out excessively high spin rates
fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3);
if (fTemp > 14000.0)
fTemp = 14000.0;
// restore direction information
fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp;
}
}
// convert range from -32768..32767 to -1..1
fAxisValue /= 32768.0;
switch (dwAxisMap[i])
{
case AxisForward:
if ((joy_advanced->value == 0.0) && (in_jlook.state & 1))
{
// user wants forward control to become look control
if (fabs(fAxisValue) > joy_pitchthreshold->value)
{
// if mouse invert is on, invert the joystick pitch value
// only absolute control support here (joy_advanced is 0)
if (m_pitch->value < 0.0)
{
viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
}
else
{
viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
}
V_StopPitchDrift();
}
else
{
// no pitch movement
// disable pitch return-to-center unless requested by user
// *** this code can be removed when the lookspring bug is fixed
// *** the bug always has the lookspring feature on
if(lookspring->value == 0.0)
{
V_StopPitchDrift();
}
}
}
else
{
// user wants forward control to be forward control
if (fabs(fAxisValue) > joy_forwardthreshold->value)
{
cmd->forwardmove += (fAxisValue * joy_forwardsensitivity->value) * speed * cl_forwardspeed->value;
}
}
break;
case AxisSide:
if (fabs(fAxisValue) > joy_sidethreshold->value)
{
cmd->sidemove += (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
}
break;
case AxisTurn:
if ((in_strafe.state & 1) || (lookstrafe->value && (in_jlook.state & 1)))
{
// user wants turn control to become side control
if (fabs(fAxisValue) > joy_sidethreshold->value)
{
cmd->sidemove -= (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value;
}
}
else
{
// user wants turn control to be turn control
if (fabs(fAxisValue) > joy_yawthreshold->value)
{
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
{
viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * aspeed * cl_yawspeed->value;
}
else
{
viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * speed * 180.0;
}
}
}
break;
case AxisLook:
if (in_jlook.state & 1)
{
if (fabs(fAxisValue) > joy_pitchthreshold->value)
{
// pitch movement detected and pitch movement desired by user
if(dwControlMap[i] == JOY_ABSOLUTE_AXIS)
{
viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value;
}
else
{
viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * speed * 180.0;
}
V_StopPitchDrift();
}
else
{
// no pitch movement
// disable pitch return-to-center unless requested by user
// *** this code can be removed when the lookspring bug is fixed
// *** the bug always has the lookspring feature on
if( lookspring->value == 0.0 )
{
V_StopPitchDrift();
}
}
}
break;
default:
break;
}
}
// bounds check pitch
if (viewangles[PITCH] > cl_pitchdown->value)
viewangles[PITCH] = cl_pitchdown->value;
if (viewangles[PITCH] < -cl_pitchup->value)
viewangles[PITCH] = -cl_pitchup->value;
gEngfuncs.SetViewAngles( (float *)viewangles );
}
/*
===========
IN_Move
===========
*/
void IN_Move ( float frametime, usercmd_t *cmd)
{
if ( !iMouseInUse && mouseactive )
{
IN_MouseMove ( frametime, cmd);
}
IN_JoyMove ( frametime, cmd);
}
/*
===========
IN_Init
===========
*/
void IN_Init (void)
{
m_filter = gEngfuncs.pfnRegisterVariable ( "m_filter","0", FCVAR_ARCHIVE );
sensitivity = gEngfuncs.pfnRegisterVariable ( "sensitivity","3", FCVAR_ARCHIVE ); // user mouse sensitivity setting.
in_joystick = gEngfuncs.pfnRegisterVariable ( "joystick","0", FCVAR_ARCHIVE );
joy_name = gEngfuncs.pfnRegisterVariable ( "joyname", "joystick", 0 );
joy_advanced = gEngfuncs.pfnRegisterVariable ( "joyadvanced", "0", 0 );
joy_advaxisx = gEngfuncs.pfnRegisterVariable ( "joyadvaxisx", "0", 0 );
joy_advaxisy = gEngfuncs.pfnRegisterVariable ( "joyadvaxisy", "0", 0 );
joy_advaxisz = gEngfuncs.pfnRegisterVariable ( "joyadvaxisz", "0", 0 );
joy_advaxisr = gEngfuncs.pfnRegisterVariable ( "joyadvaxisr", "0", 0 );
joy_advaxisu = gEngfuncs.pfnRegisterVariable ( "joyadvaxisu", "0", 0 );
joy_advaxisv = gEngfuncs.pfnRegisterVariable ( "joyadvaxisv", "0", 0 );
joy_forwardthreshold = gEngfuncs.pfnRegisterVariable ( "joyforwardthreshold", "0.15", 0 );
joy_sidethreshold = gEngfuncs.pfnRegisterVariable ( "joysidethreshold", "0.15", 0 );
joy_pitchthreshold = gEngfuncs.pfnRegisterVariable ( "joypitchthreshold", "0.15", 0 );
joy_yawthreshold = gEngfuncs.pfnRegisterVariable ( "joyyawthreshold", "0.15", 0 );
joy_forwardsensitivity = gEngfuncs.pfnRegisterVariable ( "joyforwardsensitivity", "-1.0", 0 );
joy_sidesensitivity = gEngfuncs.pfnRegisterVariable ( "joysidesensitivity", "-1.0", 0 );
joy_pitchsensitivity = gEngfuncs.pfnRegisterVariable ( "joypitchsensitivity", "1.0", 0 );
joy_yawsensitivity = gEngfuncs.pfnRegisterVariable ( "joyyawsensitivity", "-1.0", 0 );
joy_wwhack1 = gEngfuncs.pfnRegisterVariable ( "joywwhack1", "0.0", 0 );
joy_wwhack2 = gEngfuncs.pfnRegisterVariable ( "joywwhack2", "0.0", 0 );
gEngfuncs.pfnAddCommand ("force_centerview", Force_CenterView_f);
gEngfuncs.pfnAddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f);
IN_StartupMouse ();
IN_StartupJoystick ();
}

11
cl_dll/kbutton.h Normal file
View File

@ -0,0 +1,11 @@
#if !defined( KBUTTONH )
#define KBUTTONH
#pragma once
typedef struct kbutton_s
{
int down[2]; // key nums holding it down
int state; // low bit is down state
} kbutton_t;
#endif // !KBUTTONH

View File

@ -18,16 +18,20 @@
// generic menu handler
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
#include "vgui_TeamFortressViewport.h"
#define MAX_MENU_STRING 512
char g_szMenuString[MAX_MENU_STRING];
char g_szPrelocalisedMenuString[MAX_MENU_STRING];
int KB_ConvertString( char *in, char **ppout );
DECLARE_MESSAGE( m_Menu, ShowMenu );
int CHudMenu :: Init( void )
@ -73,7 +77,7 @@ int CHudMenu :: Draw( float flTime )
}
// don't draw the menu if the scoreboard is being shown
if ( gHUD.m_Scoreboard.m_iShowscoresHeld )
if ( gViewPort && gViewPort->IsScoreBoardVisible() )
return 1;
// draw the menu, along the left-hand side of the screen
@ -131,6 +135,8 @@ void CHudMenu :: SelectMenuItem( int menu_item )
// if this message is never received, then scores will simply be the combined totals of the players.
int CHudMenu :: MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf )
{
char *temp = NULL;
BEGIN_READ( pbuf, iSize );
m_bitsValidSlots = READ_SHORT();
@ -157,6 +163,13 @@ int CHudMenu :: MsgFunc_ShowMenu( const char *pszName, int iSize, void *pbuf )
if ( !NeedMore )
{ // we have the whole string, so we can localise it now
strcpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString( g_szPrelocalisedMenuString ) );
// Swap in characters
if ( KB_ConvertString( g_szMenuString, &temp ) )
{
strcpy( g_szMenuString, temp );
free( temp );
}
}
m_fMenuDisplayed = 1;

View File

@ -19,7 +19,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#include <stdio.h>
#include "parsemsg.h"

View File

@ -1,4 +1,5 @@
SCC = This is a Source Code Control file
[cl_dll.mak]
SCC_Project_Name = "$/HLStandardSDK/SourceCode/cl_dll", NUWHAAAA
SCC_Aux_Path = "\\Jeeves\VSSCODE\"
SCC_Project_Name = "$/Sdk/Standard/cl_dll", UBZBAAAA

View File

@ -19,14 +19,18 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
#include "vgui_TeamFortressViewport.h"
extern float *GetClientColor( int clientIndex );
#define MAX_LINES 5
#define MAX_CHARS_PER_LINE 128 /* it can be less than this, depending on char size */
#define MAX_CHARS_PER_LINE 256 /* it can be less than this, depending on char size */
// allow 20 pixels on either side of the text
#define MAX_LINE_WIDTH ( ScreenWidth - 40 )
@ -34,6 +38,8 @@
static float SCROLL_SPEED = 5;
static char g_szLineBuffer[ MAX_LINES + 1 ][ MAX_CHARS_PER_LINE ];
static float *g_pflNameColors[ MAX_LINES + 1 ];
static int g_iNameLengths[ MAX_LINES + 1 ];
static float flScrollTime = 0; // the time at which the lines next scroll up
static int Y_START = 0;
@ -58,6 +64,8 @@ int CHudSayText :: Init( void )
void CHudSayText :: InitHUDData( void )
{
memset( g_szLineBuffer, 0, sizeof g_szLineBuffer );
memset( g_pflNameColors, 0, sizeof g_pflNameColors );
memset( g_iNameLengths, 0, sizeof g_iNameLengths );
}
int CHudSayText :: VidInit( void )
@ -66,22 +74,31 @@ int CHudSayText :: VidInit( void )
}
void ScrollTextUp( void )
int ScrollTextUp( void )
{
ConsolePrint( g_szLineBuffer[0] ); // move the first line into the console buffer
g_szLineBuffer[MAX_LINES][0] = 0;
memmove( g_szLineBuffer[0], g_szLineBuffer[1], sizeof(g_szLineBuffer) - sizeof(g_szLineBuffer[0]) ); // overwrite the first line
memmove( &g_pflNameColors[0], &g_pflNameColors[1], sizeof(g_pflNameColors) - sizeof(g_pflNameColors[0]) );
memmove( &g_iNameLengths[0], &g_iNameLengths[1], sizeof(g_iNameLengths) - sizeof(g_iNameLengths[0]) );
g_szLineBuffer[MAX_LINES-1][0] = 0;
if ( g_szLineBuffer[0][0] == ' ' ) // also scroll up following lines
{
g_szLineBuffer[0][0] = 2;
ScrollTextUp();
return 1 + ScrollTextUp();
}
return 1;
}
int CHudSayText :: Draw( float flTime )
{
int y = Y_START;
if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
return 1;
// make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
flScrollTime = min( flScrollTime, flTime + SCROLL_SPEED );
@ -105,7 +122,27 @@ int CHudSayText :: Draw( float flTime )
for ( int i = 0; i < MAX_LINES; i++ )
{
if ( *g_szLineBuffer[i] )
DrawConsoleString( LINE_START, y, g_szLineBuffer[i] );
{
if ( *g_szLineBuffer[i] == 2 && g_pflNameColors[i] )
{
// it's a saytext string
static char buf[MAX_PLAYER_NAME_LENGTH+32];
// draw the first x characters in the player color
strncpy( buf, g_szLineBuffer[i], min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH+32) );
buf[ min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH+31) ] = 0;
gEngfuncs.pfnDrawSetTextColor( g_pflNameColors[i][0], g_pflNameColors[i][1], g_pflNameColors[i][2] );
int x = DrawConsoleString( LINE_START, y, buf );
// color is reset after each string draw
DrawConsoleString( x, y, g_szLineBuffer[i] + g_iNameLengths[i] );
}
else
{
// normal draw
DrawConsoleString( LINE_START, y, g_szLineBuffer[i] );
}
}
y += line_height;
}
@ -119,13 +156,16 @@ int CHudSayText :: MsgFunc_SayText( const char *pszName, int iSize, void *pbuf )
BEGIN_READ( pbuf, iSize );
int client_index = READ_BYTE(); // the client who spoke the message
SayTextPrint( READ_STRING(), iSize - 1 );
SayTextPrint( READ_STRING(), iSize - 1, client_index );
return 1;
}
void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize )
void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex )
{
if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
return;
// find an empty string slot
for ( int i = 0; i < MAX_LINES; i++ )
{
@ -139,6 +179,27 @@ void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize )
i = MAX_LINES - 1;
}
g_iNameLengths[i] = 0;
g_pflNameColors[i] = NULL;
// if it's a say message, search for the players name in the string
if ( *pszBuf == 2 && clientIndex > 0 )
{
GetPlayerInfo( clientIndex, &g_PlayerInfoList[clientIndex] );
const char *pName = g_PlayerInfoList[clientIndex].name;
if ( pName )
{
const char *nameInString = strstr( pszBuf, pName );
if ( nameInString )
{
g_iNameLengths[i] = strlen( pName ) + (nameInString - pszBuf);
g_pflNameColors[i] = GetClientColor( clientIndex );
}
}
}
strncpy( g_szLineBuffer[i], pszBuf, max(iBufSize -1, MAX_CHARS_PER_LINE-1) );
// make sure the text fits in one line
@ -155,9 +216,9 @@ void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize )
PlaySound( "misc/talk.wav", 1 );
if ( ScreenHeight >= 480 )
Y_START = ScreenHeight - 45;
Y_START = ScreenHeight - 60;
else
Y_START = ScreenHeight - 35;
Y_START = ScreenHeight - 45;
Y_START -= (line_height * (MAX_LINES+1));
}
@ -175,6 +236,21 @@ void CHudSayText :: EnsureTextFitsInOneLineAndWrapIfHaveTo( int line )
char *last_break = NULL;
for ( char *x = g_szLineBuffer[line]; *x != 0; x++ )
{
// check for a color change, if so skip past it
if ( x[0] == '/' && x[1] == '(' )
{
x += 2;
// skip forward until past mode specifier
while ( *x != 0 && *x != ')' )
x++;
if ( *x != 0 )
x++;
if ( *x == 0 )
break;
}
char buf[2];
buf[1] = 0;
@ -193,15 +269,23 @@ void CHudSayText :: EnsureTextFitsInOneLineAndWrapIfHaveTo( int line )
x = last_break;
// find an empty string slot
for ( int j = 0; j < MAX_LINES; j++ )
int j;
do
{
if ( ! *g_szLineBuffer[j] )
break;
}
if ( j == MAX_LINES )
{
j = MAX_LINES - 1;
for ( j = 0; j < MAX_LINES; j++ )
{
if ( ! *g_szLineBuffer[j] )
break;
}
if ( j == MAX_LINES )
{
// need to make more room to display text, scroll stuff up then fix the pointers
int linesmoved = ScrollTextUp();
line -= linesmoved;
last_break = last_break - (sizeof(g_szLineBuffer[0]) * linesmoved);
}
}
while ( j == MAX_LINES );
// copy remaining string into next buffer, making sure it starts with a space character
if ( (char)*last_break == (char)' ' )

View File

@ -1,528 +0,0 @@
/***
*
* 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.
*
****/
//
// Scoreboard.cpp
//
// implementation of CHudScoreboard class
//
#include "hud.h"
#include "util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
DECLARE_COMMAND( m_Scoreboard, ShowScores );
DECLARE_COMMAND( m_Scoreboard, HideScores );
DECLARE_MESSAGE( m_Scoreboard, ScoreInfo );
DECLARE_MESSAGE( m_Scoreboard, TeamInfo );
DECLARE_MESSAGE( m_Scoreboard, TeamScore );
int CHudScoreboard :: Init( void )
{
gHUD.AddHudElem( this );
// Hook messages & commands here
HOOK_COMMAND( "+showscores", ShowScores );
HOOK_COMMAND( "-showscores", HideScores );
HOOK_MESSAGE( ScoreInfo );
HOOK_MESSAGE( TeamScore );
HOOK_MESSAGE( TeamInfo );
InitHUDData();
return 1;
}
int CHudScoreboard :: VidInit( void )
{
// Load sprites here
return 1;
}
void CHudScoreboard :: InitHUDData( void )
{
memset( m_PlayerExtraInfo, 0, sizeof m_PlayerExtraInfo );
m_iLastKilledBy = 0;
m_fLastKillTime = 0;
m_iPlayerNum = 0;
m_iNumTeams = 0;
memset( m_TeamInfo, 0, sizeof m_TeamInfo );
m_iFlags &= ~HUD_ACTIVE; // starts out inactive
m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission
}
/* The scoreboard
We have a minimum width of 1-320 - we could have the field widths scale with it?
*/
// X positions
// relative to the side of the scoreboard
#define NAME_RANGE_MIN 20
#define NAME_RANGE_MAX 145
#define KILLS_RANGE_MIN 130
#define KILLS_RANGE_MAX 170
#define DIVIDER_POS 180
#define DEATHS_RANGE_MIN 185
#define DEATHS_RANGE_MAX 210
#define PING_RANGE_MIN 245
#define PING_RANGE_MAX 295
#define SCOREBOARD_WIDTH 320
// Y positions
#define ROW_GAP 13
#define ROW_RANGE_MIN 15
#define ROW_RANGE_MAX ( ScreenHeight - 50 )
int CHudScoreboard :: Draw( float fTime )
{
if ( !m_iShowscoresHeld && gHUD.m_Health.m_iHealth > 0 && !gHUD.m_iIntermission )
return 1;
GetAllPlayersInfo();
// just sort the list on the fly
// list is sorted first by frags, then by deaths
float list_slot = 0;
int xpos_rel = (ScreenWidth - SCOREBOARD_WIDTH) / 2;
// print the heading line
int ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);
int xpos = NAME_RANGE_MIN + xpos_rel;
if ( !gHUD.m_Teamplay )
gHUD.DrawHudString( xpos, ypos, NAME_RANGE_MAX + xpos_rel, "Player", 255, 140, 0 );
else
gHUD.DrawHudString( xpos, ypos, NAME_RANGE_MAX + xpos_rel, "Teams", 255, 140, 0 );
gHUD.DrawHudStringReverse( KILLS_RANGE_MAX + xpos_rel, ypos, 0, "kills", 255, 140, 0 );
gHUD.DrawHudString( DIVIDER_POS + xpos_rel, ypos, ScreenWidth, "/", 255, 140, 0 );
gHUD.DrawHudString( DEATHS_RANGE_MIN + xpos_rel + 5, ypos, ScreenWidth, "deaths", 255, 140, 0 );
gHUD.DrawHudString( PING_RANGE_MAX + xpos_rel - 35, ypos, ScreenWidth, "latency", 255, 140, 0 );
list_slot += 1.2;
ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);
xpos = NAME_RANGE_MIN + xpos_rel;
FillRGBA( xpos - 5, ypos, PING_RANGE_MAX - 5, 1, 255, 140, 0, 255); // draw the seperator line
list_slot += 0.8;
if ( !gHUD.m_Teamplay )
{
// it's not teamplay, so just draw a simple player list
DrawPlayers( xpos_rel, list_slot );
return 1;
}
// clear out team scores
for ( int i = 1; i <= m_iNumTeams; i++ )
{
if ( !m_TeamInfo[i].scores_overriden )
m_TeamInfo[i].frags = m_TeamInfo[i].deaths = 0;
m_TeamInfo[i].ping = m_TeamInfo[i].packetloss = 0;
}
// recalc the team scores, then draw them
for ( i = 1; i < MAX_PLAYERS; i++ )
{
if ( m_PlayerInfoList[i].name == NULL )
continue; // empty player slot, skip
if ( m_PlayerExtraInfo[i].teamname[0] == 0 )
continue; // skip over players who are not in a team
// find what team this player is in
for ( int j = 1; j <= m_iNumTeams; j++ )
{
if ( !stricmp( m_PlayerExtraInfo[i].teamname, m_TeamInfo[j].name ) )
break;
}
if ( j > m_iNumTeams ) // player is not in a team, skip to the next guy
continue;
if ( !m_TeamInfo[j].scores_overriden )
{
m_TeamInfo[j].frags += m_PlayerExtraInfo[i].frags;
m_TeamInfo[j].deaths += m_PlayerExtraInfo[i].deaths;
}
m_TeamInfo[j].ping += m_PlayerInfoList[i].ping;
m_TeamInfo[j].packetloss += m_PlayerInfoList[i].packetloss;
if ( m_PlayerInfoList[i].thisplayer )
m_TeamInfo[j].ownteam = TRUE;
else
m_TeamInfo[j].ownteam = FALSE;
}
// find team ping/packetloss averages
for ( i = 1; i <= m_iNumTeams; i++ )
{
m_TeamInfo[i].already_drawn = FALSE;
if ( m_TeamInfo[i].players > 0 )
{
m_TeamInfo[i].ping /= m_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping
m_TeamInfo[i].packetloss /= m_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping
}
}
// Draw the teams
while ( 1 )
{
int highest_frags = -99999; int lowest_deaths = 99999;
int best_team = 0;
for ( i = 1; i <= m_iNumTeams; i++ )
{
if ( m_TeamInfo[i].players < 0 )
continue;
if ( !m_TeamInfo[i].already_drawn && m_TeamInfo[i].frags >= highest_frags )
{
if ( m_TeamInfo[i].frags > highest_frags || m_TeamInfo[i].deaths < lowest_deaths )
{
best_team = i;
lowest_deaths = m_TeamInfo[i].deaths;
highest_frags = m_TeamInfo[i].frags;
}
}
}
// draw the best team on the scoreboard
if ( !best_team )
break;
// draw out the best team
team_info_t *team_info = &m_TeamInfo[best_team];
ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);
// check we haven't drawn too far down
if ( ypos > ROW_RANGE_MAX ) // don't draw to close to the lower border
break;
xpos = NAME_RANGE_MIN + xpos_rel;
int r = 255, g = 225, b = 55; // draw the stuff kinda yellowish
if ( team_info->ownteam ) // if it is their team, draw the background different color
{
// overlay the background in blue, then draw the score text over it
FillRGBA( NAME_RANGE_MIN + xpos_rel - 5, ypos, PING_RANGE_MAX - 5, ROW_GAP, 0, 0, 255, 70 );
}
// draw their name (left to right)
gHUD.DrawHudString( xpos, ypos, NAME_RANGE_MAX + xpos_rel, team_info->name, r, g, b );
// draw kills (right to left)
xpos = KILLS_RANGE_MAX + xpos_rel;
gHUD.DrawHudNumberString( xpos, ypos, KILLS_RANGE_MIN + xpos_rel, team_info->frags, r, g, b );
// draw divider
xpos = DIVIDER_POS + xpos_rel;
gHUD.DrawHudString( xpos, ypos, xpos + 20, "/", r, g, b );
// draw deaths
xpos = DEATHS_RANGE_MAX + xpos_rel;
gHUD.DrawHudNumberString( xpos, ypos, DEATHS_RANGE_MIN + xpos_rel, team_info->deaths, r, g, b );
// draw ping
// draw ping & packetloss
static char buf[64];
sprintf( buf, "%d", team_info->ping );
xpos = ((PING_RANGE_MAX - PING_RANGE_MIN) / 2) + PING_RANGE_MIN + xpos_rel + 25;
UnpackRGB( r, g, b, RGB_YELLOWISH );
gHUD.DrawHudStringReverse( xpos, ypos, xpos - 50, buf, r, g, b );
/* Packetloss removed on Kelly 'shipping nazi' Bailey's orders
sprintf( buf, " %d", team_info->packetloss );
gHUD.DrawHudString( xpos, ypos, xpos+50, buf, r, g, b );
*/
team_info->already_drawn = TRUE; // set the already_drawn to be TRUE, so this team won't get drawn again
list_slot++;
// draw all the players that belong to this team, indented slightly
list_slot = DrawPlayers( xpos_rel, list_slot, 10, team_info->name );
}
// draw all the players who are not in a team
list_slot += 0.5;
DrawPlayers( xpos_rel, list_slot, 0, "" );
return 1;
}
// returns the ypos where it finishes drawing
int CHudScoreboard :: DrawPlayers( int xpos_rel, float list_slot, int nameoffset, char *team )
{
// draw the players, in order, and restricted to team if set
while ( 1 )
{
// Find the top ranking player
int highest_frags = -99999; int lowest_deaths = 99999;
int best_player = 0;
for ( int i = 1; i < MAX_PLAYERS; i++ )
{
if ( m_PlayerInfoList[i].name && m_PlayerExtraInfo[i].frags >= highest_frags )
{
if ( !(team && stricmp(m_PlayerExtraInfo[i].teamname, team)) ) // make sure it is the specified team
{
extra_player_info_t *pl_info = &m_PlayerExtraInfo[i];
if ( pl_info->frags > highest_frags || pl_info->deaths < lowest_deaths )
{
best_player = i;
lowest_deaths = pl_info->deaths;
highest_frags = pl_info->frags;
}
}
}
}
if ( !best_player )
break;
// draw out the best player
hud_player_info_t *pl_info = &m_PlayerInfoList[best_player];
int ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP);
// check we haven't drawn too far down
if ( ypos > ROW_RANGE_MAX ) // don't draw to close to the lower border
break;
int xpos = NAME_RANGE_MIN + xpos_rel;
int r = 255, g = 255, b = 255;
if ( best_player == m_iLastKilledBy && m_fLastKillTime && m_fLastKillTime > gHUD.m_flTime )
{
if ( pl_info->thisplayer )
{ // green is the suicide color? i wish this could do grey...
FillRGBA( NAME_RANGE_MIN + xpos_rel - 5, ypos, PING_RANGE_MAX - 5, ROW_GAP, 80, 155, 0, 70 );
}
else
{ // Highlight the killers name - overlay the background in red, then draw the score text over it
FillRGBA( NAME_RANGE_MIN + xpos_rel - 5, ypos, PING_RANGE_MAX - 5, ROW_GAP, 255, 0, 0, ((float)15 * (float)(m_fLastKillTime - gHUD.m_flTime)) );
}
}
else if ( pl_info->thisplayer ) // if it is their name, draw it a different color
{
// overlay the background in blue, then draw the score text over it
FillRGBA( NAME_RANGE_MIN + xpos_rel - 5, ypos, PING_RANGE_MAX - 5, ROW_GAP, 0, 0, 255, 70 );
}
// draw their name (left to right)
gHUD.DrawHudString( xpos + nameoffset, ypos, NAME_RANGE_MAX + xpos_rel, pl_info->name, r, g, b );
// draw kills (right to left)
xpos = KILLS_RANGE_MAX + xpos_rel;
gHUD.DrawHudNumberString( xpos, ypos, KILLS_RANGE_MIN + xpos_rel, m_PlayerExtraInfo[best_player].frags, r, g, b );
// draw divider
xpos = DIVIDER_POS + xpos_rel;
gHUD.DrawHudString( xpos, ypos, xpos + 20, "/", r, g, b );
// draw deaths
xpos = DEATHS_RANGE_MAX + xpos_rel;
gHUD.DrawHudNumberString( xpos, ypos, DEATHS_RANGE_MIN + xpos_rel, m_PlayerExtraInfo[best_player].deaths, r, g, b );
// draw ping & packetloss
static char buf[64];
sprintf( buf, "%d", m_PlayerInfoList[best_player].ping );
xpos = ((PING_RANGE_MAX - PING_RANGE_MIN) / 2) + PING_RANGE_MIN + xpos_rel + 25;
gHUD.DrawHudStringReverse( xpos, ypos, xpos - 50, buf, r, g, b );
/* Packetloss removed on Kelly 'shipping nazi' Bailey's orders
if ( m_PlayerInfoList[best_player].packetloss >= 63 )
{
UnpackRGB( r, g, b, RGB_REDISH );
sprintf( buf, " !!!!" );
}
else
{
sprintf( buf, " %d", m_PlayerInfoList[best_player].packetloss );
}
gHUD.DrawHudString( xpos, ypos, xpos+50, buf, r, g, b );
*/
pl_info->name = NULL; // set the name to be NULL, so this client won't get drawn again
list_slot++;
}
return list_slot;
}
void CHudScoreboard :: GetAllPlayersInfo( void )
{
for ( int i = 1; i < MAX_PLAYERS; i++ )
{
GetPlayerInfo( i, &m_PlayerInfoList[i] );
if ( m_PlayerInfoList[i].thisplayer )
m_iPlayerNum = i; // !!!HACK: this should be initialized elsewhere... maybe gotten from the engine
}
}
int CHudScoreboard :: MsgFunc_ScoreInfo( const char *pszName, int iSize, void *pbuf )
{
m_iFlags |= HUD_ACTIVE;
BEGIN_READ( pbuf, iSize );
short cl = READ_BYTE();
short frags = READ_SHORT();
short deaths = READ_SHORT();
if ( cl > 0 && cl <= MAX_PLAYERS )
{
m_PlayerExtraInfo[cl].frags = frags;
m_PlayerExtraInfo[cl].deaths = deaths;
}
return 1;
}
// Message handler for TeamInfo message
// accepts two values:
// byte: client number
// string: client team name
int CHudScoreboard :: MsgFunc_TeamInfo( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
short cl = READ_BYTE();
if ( cl > 0 && cl <= MAX_PLAYERS )
{ // set the players team
strncpy( m_PlayerExtraInfo[cl].teamname, READ_STRING(), MAX_TEAM_NAME );
}
// rebuild the list of teams
// clear out player counts from teams
for ( int i = 1; i <= m_iNumTeams; i++ )
{
m_TeamInfo[i].players = 0;
}
// rebuild the team list
GetAllPlayersInfo();
m_iNumTeams = 0;
for ( i = 1; i < MAX_PLAYERS; i++ )
{
if ( m_PlayerInfoList[i].name == NULL )
continue;
if ( m_PlayerExtraInfo[i].teamname[0] == 0 )
continue; // skip over players who are not in a team
// is this player in an existing team?
for ( int j = 1; j <= m_iNumTeams; j++ )
{
if ( m_TeamInfo[j].name[0] == '\0' )
break;
if ( !stricmp( m_PlayerExtraInfo[i].teamname, m_TeamInfo[j].name ) )
break;
}
if ( j > m_iNumTeams )
{ // they aren't in a listed team, so make a new one
// search through for an empty team slot
for ( int j = 1; j <= m_iNumTeams; j++ )
{
if ( m_TeamInfo[j].name[0] == '\0' )
break;
}
m_iNumTeams = max( j, m_iNumTeams );
strncpy( m_TeamInfo[j].name, m_PlayerExtraInfo[i].teamname, MAX_TEAM_NAME );
m_TeamInfo[j].players = 0;
}
m_TeamInfo[j].players++;
}
// clear out any empty teams
for ( i = 1; i <= m_iNumTeams; i++ )
{
if ( m_TeamInfo[i].players < 1 )
memset( &m_TeamInfo[i], 0, sizeof(team_info_t) );
}
return 1;
}
// Message handler for TeamScore message
// accepts three values:
// string: team name
// short: teams kills
// short: teams deaths
// if this message is never received, then scores will simply be the combined totals of the players.
int CHudScoreboard :: MsgFunc_TeamScore( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( pbuf, iSize );
char *TeamName = READ_STRING();
// find the team matching the name
for ( int i = 1; i <= m_iNumTeams; i++ )
{
if ( !stricmp( TeamName, m_TeamInfo[i].name ) )
break;
}
if ( i > m_iNumTeams )
return 1;
// use this new score data instead of combined player scores
m_TeamInfo[i].scores_overriden = TRUE;
m_TeamInfo[i].frags = READ_SHORT();
m_TeamInfo[i].deaths = READ_SHORT();
return 1;
}
void CHudScoreboard :: DeathMsg( int killer, int victim )
{
// if we were the one killed, or the world killed us, set the scoreboard to indicate suicide
if ( victim == m_iPlayerNum || killer == 0 )
{
m_iLastKilledBy = killer ? killer : m_iPlayerNum;
m_fLastKillTime = gHUD.m_flTime + 10; // display who we were killed by for 10 seconds
if ( killer == m_iPlayerNum )
m_iLastKilledBy = m_iPlayerNum;
}
}
void CHudScoreboard :: UserCmd_ShowScores( void )
{
m_iShowscoresHeld = TRUE;
}
void CHudScoreboard :: UserCmd_HideScores( void )
{
m_iShowscoresHeld = FALSE;
}

View File

@ -16,10 +16,14 @@
// status_icons.cpp
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include <string.h>
#include <stdio.h>
#include "parsemsg.h"
#include "event_api.h"
DECLARE_MESSAGE( m_StatusIcons, StatusIcon );
@ -132,6 +136,13 @@ void CHudStatusIcons::EnableIcon( char *pszIconName, unsigned char red, unsigned
m_IconList[i].g = green;
m_IconList[i].b = blue;
strcpy( m_IconList[i].szSpriteName, pszIconName );
// Hack: Play Timer sound when a grenade icon is played (in 0.8 seconds)
if ( strstr(m_IconList[i].szSpriteName, "grenade") )
{
cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
gEngfuncs.pEventAPI->EV_PlaySound( pthisplayer->index, pthisplayer->origin, CHAN_STATIC, "weapons/timer.wav", 1.0, ATTN_NORM, 0, PITCH_NORM );
}
}
void CHudStatusIcons::DisableIcon( char *pszIconName )

View File

@ -20,7 +20,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
@ -129,10 +129,10 @@ void CHudStatusBar :: ParseStatusString( int line_num )
switch ( valtype )
{
case 'p': // player name
GetPlayerInfo( indexval, &gHUD.m_Scoreboard.m_PlayerInfoList[indexval] );
if ( gHUD.m_Scoreboard.m_PlayerInfoList[indexval].name != NULL )
GetPlayerInfo( indexval, &g_PlayerInfoList[indexval] );
if ( g_PlayerInfoList[indexval].name != NULL )
{
strncpy( szRepString, gHUD.m_Scoreboard.m_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH );
strncpy( szRepString, g_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH );
}
else
{
@ -178,9 +178,9 @@ int CHudStatusBar :: Draw( float fTime )
int Y_START;
if ( ScreenHeight >= 480 )
Y_START = ScreenHeight - 45;
Y_START = ScreenHeight - 55;
else
Y_START = ScreenHeight - 35;
Y_START = ScreenHeight - 45;
int x = 5;
int y = Y_START - ( TextHeight * i ); // draw along bottom of screen

View File

@ -21,11 +21,13 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#include <stdio.h>
#include "parsemsg.h"
#include "vgui_TeamFortressViewport.h"
DECLARE_MESSAGE( m_TextMessage, TextMsg );
int CHudTextMessage::Init(void)
@ -52,7 +54,7 @@ char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, in
// cut msg name out of string
static char word_buf[255];
char *wdst = word_buf, *word_start = src;
for ( ++src ; *src >= 'A' && *src <= 'z'; wdst++, src++ )
for ( ++src ; (*src >= 'A' && *src <= 'z') || (*src >= '0' && *src <= '9'); wdst++, src++ )
{
*wdst = *src;
}
@ -90,8 +92,9 @@ char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, in
// As above, but with a local static buffer
char *CHudTextMessage::BufferedLocaliseTextString( const char *msg )
{
char dst_buffer[1024];
return LocaliseTextString( msg, dst_buffer, 1024 );
static char dst_buffer[1024];
LocaliseTextString( msg, dst_buffer, 1024 );
return dst_buffer;
}
// Simplified version of LocaliseTextString; assumes string is only one word
@ -179,6 +182,9 @@ int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf
StripEndNewlineFromString( sstr4 );
char *psz = szBuf[5];
if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
return 1;
switch ( msg_dest )
{
case HUD_PRINTCENTER:

1357
cl_dll/tf_defs.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
//
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#include <stdio.h>
#include "parsemsg.h"

115
cl_dll/tri.cpp Normal file
View File

@ -0,0 +1,115 @@
// Triangle rendering, if any
#include "hud.h"
#include "cl_util.h"
// Triangle rendering apis are in gEngfuncs.pTriAPI
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "triangleapi.h"
#define DLLEXPORT __declspec( dllexport )
extern "C"
{
void DLLEXPORT HUD_DrawNormalTriangles( void );
void DLLEXPORT HUD_DrawTransparentTriangles( void );
};
//#define TEST_IT
#if defined( TEST_IT )
/*
=================
Draw_Triangles
Example routine. Draws a sprite offset from the player origin.
=================
*/
void Draw_Triangles( void )
{
cl_entity_t *player;
vec3_t org;
// Load it up with some bogus data
player = gEngfuncs.GetLocalPlayer();
if ( !player )
return;
org = player->origin;
org.x += 50;
org.y += 50;
if (gHUD.m_hsprCursor == 0)
{
char sz[256];
sprintf( sz, "sprites/cursor.spr" );
gHUD.m_hsprCursor = SPR_Load( sz );
}
if ( !gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)gEngfuncs.GetSpritePointer( gHUD.m_hsprCursor ), 0 ))
{
return;
}
// Create a triangle, sigh
gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
gEngfuncs.pTriAPI->CullFace( TRI_NONE );
gEngfuncs.pTriAPI->Begin( TRI_QUADS );
// Overload p->color with index into tracer palette, p->packedColor with brightness
gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 );
// UNDONE: This gouraud shading causes tracers to disappear on some cards (permedia2)
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 0, 0 );
gEngfuncs.pTriAPI->Vertex3f( org.x, org.y, org.z );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 0, 1 );
gEngfuncs.pTriAPI->Vertex3f( org.x, org.y + 50, org.z );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 1, 1 );
gEngfuncs.pTriAPI->Vertex3f( org.x + 50, org.y + 50, org.z );
gEngfuncs.pTriAPI->Brightness( 1 );
gEngfuncs.pTriAPI->TexCoord2f( 1, 0 );
gEngfuncs.pTriAPI->Vertex3f( org.x + 50, org.y, org.z );
gEngfuncs.pTriAPI->End();
gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
}
#endif
/*
=================
HUD_DrawNormalTriangles
Non-transparent triangles-- add them here
=================
*/
void DLLEXPORT HUD_DrawNormalTriangles( void )
{
#if defined( TEST_IT )
// Draw_Triangles();
#endif
}
/*
=================
HUD_DrawTransparentTriangles
Render any triangles with transparent rendermode needs here
=================
*/
void DLLEXPORT HUD_DrawTransparentTriangles( void )
{
#if defined( TEST_IT )
// Draw_Triangles();
#endif
}

View File

@ -23,10 +23,98 @@
#include "MATH.H"
#include "hud.h"
#include "util.h"
#include "cl_util.h"
#include <string.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
vec3_t vec3_origin( 0, 0, 0 );
double sqrt(double x);
float Length(const float *v)
{
int i;
float length;
length = 0;
for (i=0 ; i< 3 ; i++)
length += v[i]*v[i];
length = sqrt (length); // FIXME
return length;
}
void VectorAngles( const float *forward, float *angles )
{
float tmp, yaw, pitch;
if (forward[1] == 0 && forward[0] == 0)
{
yaw = 0;
if (forward[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
if (yaw < 0)
yaw += 360;
tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);
pitch = (atan2(forward[2], tmp) * 180 / M_PI);
if (pitch < 0)
pitch += 360;
}
angles[0] = pitch;
angles[1] = yaw;
angles[2] = 0;
}
float VectorNormalize (float *v)
{
float length, ilength;
length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
length = sqrt (length); // FIXME
if (length)
{
ilength = 1/length;
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
return length;
}
void VectorInverse ( float *v )
{
v[0] = -v[0];
v[1] = -v[1];
v[2] = -v[2];
}
void VectorScale (const float *in, float scale, float *out)
{
out[0] = in[0]*scale;
out[1] = in[1]*scale;
out[2] = in[2]*scale;
}
void VectorMA (const float *veca, float scale, const float *vecb, float *vecc)
{
vecc[0] = veca[0] + scale*vecb[0];
vecc[1] = veca[1] + scale*vecb[1];
vecc[2] = veca[2] + scale*vecb[2];
}
HSPRITE LoadSprite(const char *pszName)
{

426
cl_dll/vgui_ClassMenu.cpp Normal file
View File

@ -0,0 +1,426 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: TFC Class Menu
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "VGUI_Font.h"
#include <VGUI_TextImage.h>
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
#include "kbutton.h"
#include "cvardef.h"
#include "usercmd.h"
#include "const.h"
#include "camera.h"
#include "in_defs.h"
#include "parsemsg.h"
#include "vgui_int.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ServerBrowser.h"
// Class Menu Dimensions
#define CLASSMENU_TITLE_X XRES(40)
#define CLASSMENU_TITLE_Y YRES(32)
#define CLASSMENU_TOPLEFT_BUTTON_X XRES(40)
#define CLASSMENU_TOPLEFT_BUTTON_Y YRES(80)
#define CLASSMENU_BUTTON_SIZE_X XRES(124)
#define CLASSMENU_BUTTON_SIZE_Y YRES(24)
#define CLASSMENU_BUTTON_SPACER_Y YRES(8)
#define CLASSMENU_WINDOW_X XRES(176)
#define CLASSMENU_WINDOW_Y YRES(80)
#define CLASSMENU_WINDOW_SIZE_X XRES(424)
#define CLASSMENU_WINDOW_SIZE_Y YRES(312)
#define CLASSMENU_WINDOW_TEXT_X XRES(150)
#define CLASSMENU_WINDOW_TEXT_Y YRES(80)
#define CLASSMENU_WINDOW_NAME_X XRES(150)
#define CLASSMENU_WINDOW_NAME_Y YRES(8)
#define CLASSMENU_WINDOW_PLAYERS_Y YRES(42)
// Creation
CClassMenuPanel::CClassMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide,int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
// don't show class graphics at below 640x480 resolution
bool bShowClassGraphic = true;
if ( ScreenWidth < 640 )
{
bShowClassGraphic = false;
}
memset( m_pClassImages, 0, sizeof(m_pClassImages) );
// Get the scheme used for the Titles
CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
// schemes
SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
SchemeHandle_t hClassWindowText = pSchemes->getSchemeHandle( "Briefing Text" );
// color schemes
int r, g, b, a;
// Create the title
Label *pLabel = new Label( "", CLASSMENU_TITLE_X, CLASSMENU_TITLE_Y );
pLabel->setParent( this );
pLabel->setFont( pSchemes->getFont(hTitleScheme) );
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
pLabel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
pLabel->setBgColor( r, g, b, a );
pLabel->setContentAlignment( vgui::Label::a_west );
pLabel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Title_SelectYourClass"));
// Create the Scroll panel
m_pScrollPanel = new CTFScrollPanel( CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y );
m_pScrollPanel->setParent(this);
//force the scrollbars on, so after the validate clientClip will be smaller
m_pScrollPanel->setScrollBarAutoVisible(false, false);
m_pScrollPanel->setScrollBarVisible(true, true);
m_pScrollPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
m_pScrollPanel->validate();
int clientWide=m_pScrollPanel->getClient()->getWide();
//turn scrollpanel back into auto show scrollbar mode and validate
m_pScrollPanel->setScrollBarAutoVisible(false,true);
m_pScrollPanel->setScrollBarVisible(false,false);
m_pScrollPanel->validate();
// Create the Class buttons
for (int i = 0; i <= PC_RANDOM; i++)
{
char sz[256];
int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y + ( (CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y) * i );
ActionSignal *pASignal = new CMenuHandler_StringCommandClassSelect( sTFClassSelection[i], true );
// Class button
sprintf(sz, "%s", CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[i] ) );
m_pButtons[i] = new ClassButton( i, sz, CLASSMENU_TOPLEFT_BUTTON_X, iYPos, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y, true);
// RandomPC uses '0'
if ( i >= 1 && i <= 9 )
{
sprintf(sz,"%d",i);
}
else
{
sprintf(sz,"0");
}
m_pButtons[i]->setBoundKey( sz[0] );
m_pButtons[i]->setContentAlignment( vgui::Label::a_west );
m_pButtons[i]->addActionSignal( pASignal );
m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver(this, i) );
m_pButtons[i]->setParent( this );
// Create the Class Info Window
//m_pClassInfoPanel[i] = new CTransparentPanel( 255, CLASSMENU_WINDOW_X, CLASSMENU_WINDOW_Y, CLASSMENU_WINDOW_SIZE_X, CLASSMENU_WINDOW_SIZE_Y );
m_pClassInfoPanel[i] = new CTransparentPanel( 255, 0, 0, clientWide, CLASSMENU_WINDOW_SIZE_Y );
m_pClassInfoPanel[i]->setParent( m_pScrollPanel->getClient() );
//m_pClassInfoPanel[i]->setVisible( false );
// don't show class pic in lower resolutions
int textOffs = XRES(8);
if ( bShowClassGraphic )
{
textOffs = CLASSMENU_WINDOW_NAME_X;
}
// Create the Class Name Label
sprintf(sz, "#Title_%s", sTFClassSelection[i]);
char* localName=CHudTextMessage::BufferedLocaliseTextString( sz );
Label *pNameLabel = new Label( "", textOffs, CLASSMENU_WINDOW_NAME_Y );
pNameLabel->setFont( pSchemes->getFont(hTitleScheme) );
pNameLabel->setParent( m_pClassInfoPanel[i] );
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
pNameLabel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
pNameLabel->setBgColor( r, g, b, a );
pNameLabel->setContentAlignment( vgui::Label::a_west );
//pNameLabel->setBorder(new LineBorder());
pNameLabel->setText(localName);
// Create the Class Image
if ( bShowClassGraphic )
{
for ( int team = 0; team < 2; team++ )
{
if ( team == 1 )
{
sprintf( sz, "%sred", sTFClassSelection[i] );
}
else
{
sprintf( sz, "%sblue", sTFClassSelection[i] );
}
m_pClassImages[team][i] = new CImageLabel( sz, 0, 0, CLASSMENU_WINDOW_TEXT_X, CLASSMENU_WINDOW_TEXT_Y );
CImageLabel *pLabel = m_pClassImages[team][i];
pLabel->setParent( m_pClassInfoPanel[i] );
//pLabel->setBorder(new LineBorder());
if ( team != 1 )
{
pLabel->setVisible( false );
}
// Reposition it based upon it's size
int xOut, yOut;
pNameLabel->getTextSize( xOut, yOut );
pLabel->setPos( (CLASSMENU_WINDOW_TEXT_X - pLabel->getWide()) / 2, yOut /2 );
}
}
// Create the Player count string
gHUD.m_TextMessage.LocaliseTextString( "#Title_CurrentlyOnYourTeam", m_sPlayersOnTeamString, STRLENMAX_PLAYERSONTEAM );
m_pPlayers[i] = new Label( "", textOffs, CLASSMENU_WINDOW_PLAYERS_Y );
m_pPlayers[i]->setParent( m_pClassInfoPanel[i] );
m_pPlayers[i]->setBgColor( 0, 0, 0, 255 );
m_pPlayers[i]->setContentAlignment( vgui::Label::a_west );
m_pPlayers[i]->setFont( pSchemes->getFont(hClassWindowText) );
// Open up the Class Briefing File
sprintf(sz, "classes/short_%s.txt", sTFClassSelection[i]);
char *cText = "Class Description not available.";
char *pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL );
if (pfile)
cText = pfile;
// Create the Text info window
TextPanel *pTextWindow = new TextPanel(cText, textOffs, CLASSMENU_WINDOW_TEXT_Y, (CLASSMENU_WINDOW_SIZE_X - textOffs)-5, CLASSMENU_WINDOW_SIZE_Y - CLASSMENU_WINDOW_TEXT_Y);
pTextWindow->setParent( m_pClassInfoPanel[i] );
pTextWindow->setFont( pSchemes->getFont(hClassWindowText) );
pSchemes->getFgColor( hClassWindowText, r, g, b, a );
pTextWindow->setFgColor( r, g, b, a );
pSchemes->getBgColor( hClassWindowText, r, g, b, a );
pTextWindow->setBgColor( r, g, b, a );
// Resize the Info panel to fit it all
int wide,tall;
pTextWindow->getTextImage()->getTextSizeWrapped( wide,tall);
pTextWindow->setSize(wide,tall);
//pTextWindow->setBorder(new LineBorder());
int xx,yy;
pTextWindow->getPos(xx,yy);
int maxX=xx+wide;
int maxY=yy+tall;
//check to see if the image goes lower than the text
//just use the red teams [0] images
if(m_pClassImages[0][i]!=null)
{
m_pClassImages[0][i]->getPos(xx,yy);
if((yy+m_pClassImages[0][i]->getTall())>maxY)
{
maxY=yy+m_pClassImages[0][i]->getTall();
}
}
m_pClassInfoPanel[i]->setSize( maxX , maxY );
//m_pClassInfoPanel[i]->setBorder(new LineBorder());
}
// Create the Cancel button
m_pCancelButton = new CommandButton( gHUD.m_TextMessage.BufferedLocaliseTextString( "#Menu_Cancel" ), CLASSMENU_TOPLEFT_BUTTON_X, 0, CLASSMENU_BUTTON_SIZE_X, CLASSMENU_BUTTON_SIZE_Y);
m_pCancelButton->setParent( this );
m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
m_iCurrentInfo = 0;
}
// Update
void CClassMenuPanel::Update()
{
// Don't allow the player to join a team if they're not in a team
if (!g_iTeamNumber)
return;
int iYPos = CLASSMENU_TOPLEFT_BUTTON_Y;
// Cycle through the rest of the buttons
for (int i = 0; i <= PC_RANDOM; i++)
{
bool bCivilian = (gViewPort->GetValidClasses(g_iTeamNumber) == -1);
if ( bCivilian )
{
// If this team can only be civilians, only the civilian button's visible
if (i == 0)
{
m_pButtons[0]->setVisible( true );
SetActiveInfo( 0 );
iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y;
}
else
{
m_pButtons[i]->setVisible( false );
}
}
else
{
if ( m_pButtons[i]->IsNotValid() || i == 0 )
{
m_pButtons[i]->setVisible( false );
}
else
{
m_pButtons[i]->setVisible( true );
m_pButtons[i]->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos );
iYPos += CLASSMENU_BUTTON_SIZE_Y + CLASSMENU_BUTTON_SPACER_Y;
// Start with the first option up
if (!m_iCurrentInfo)
SetActiveInfo( i );
}
}
// Now count the number of teammembers of this class
int iTotal = 0;
for ( int j = 1; j < MAX_PLAYERS; j++ )
{
if ( g_PlayerInfoList[j].name == NULL )
continue; // empty player slot, skip
if ( g_PlayerExtraInfo[j].teamname[0] == 0 )
continue; // skip over players who are not in a team
if ( g_PlayerInfoList[j].thisplayer )
continue; // skip this player
if ( g_PlayerExtraInfo[j].teamnumber != g_iTeamNumber )
continue; // skip over players in other teams
// If this team is forced to be civilians, just count the number of teammates
if ( g_PlayerExtraInfo[j].playerclass != i && !bCivilian )
continue;
iTotal++;
}
char sz[256];
sprintf(sz, m_sPlayersOnTeamString, iTotal);
m_pPlayers[i]->setText( sz );
// Set the text color to the teamcolor
m_pPlayers[i]->setFgColor( iTeamColors[g_iTeamNumber][0], iTeamColors[g_iTeamNumber][1], iTeamColors[g_iTeamNumber][2], 0 );
// set the graphic to be the team pick
for ( int team = 0; team < MAX_TEAMS; team++ )
{
// unset all the other images
if ( m_pClassImages[team][i] )
{
m_pClassImages[team][i]->setVisible( false );
}
// set the current team image
if ( m_pClassImages[g_iTeamNumber-1][i] != NULL )
{
m_pClassImages[g_iTeamNumber-1][i]->setVisible( true );
}
else if ( m_pClassImages[0][i] )
{
m_pClassImages[0][i]->setVisible( true );
}
}
}
// If the player already has a class, make the cancel button visible
if ( g_iPlayerClass )
{
m_pCancelButton->setPos( CLASSMENU_TOPLEFT_BUTTON_X, iYPos );
m_pCancelButton->setVisible( true );
}
else
{
m_pCancelButton->setVisible( false );
}
}
//======================================
// Key inputs for the Class Menu
bool CClassMenuPanel::SlotInput( int iSlot )
{
if ( (iSlot < 0) || (iSlot > 9) )
return false;
if ( !m_pButtons[ iSlot ] )
return false;
// Is the button pushable? (0 is special case)
if (iSlot == 0)
{
// Selects Civilian and RandomPC
if ( gViewPort->GetValidClasses(g_iTeamNumber) == -1 )
{
m_pButtons[ 0 ]->fireActionSignal();
return true;
}
// Select RandomPC
iSlot = 10;
}
if ( !(m_pButtons[ iSlot ]->IsNotValid()) )
{
m_pButtons[ iSlot ]->fireActionSignal();
return true;
}
return false;
}
//======================================
// Update the Class menu before opening it
void CClassMenuPanel::Open( void )
{
Update();
CMenuPanel::Open();
}
//-----------------------------------------------------------------------------
// Purpose: Called each time a new level is started.
//-----------------------------------------------------------------------------
void CClassMenuPanel::Initialize( void )
{
setVisible( false );
m_pScrollPanel->setScrollValue( 0, 0 );
}
//======================================
// Mouse is over a class button, bring up the class info
void CClassMenuPanel::SetActiveInfo( int iInput )
{
// Remove all the Info panels and bring up the specified one
for (int i = 0; i <= PC_RANDOM; i++)
{
m_pButtons[i]->setArmed( false );
m_pClassInfoPanel[i]->setVisible( false );
}
if ( iInput > PC_RANDOM || iInput < 0 )
iInput = 0;
m_pButtons[iInput]->setArmed( true );
m_pClassInfoPanel[iInput]->setVisible( true );
m_iCurrentInfo = iInput;
m_pScrollPanel->setScrollValue(0,0);
m_pScrollPanel->validate();
}

View File

@ -0,0 +1,95 @@
#include"vgui_ConsolePanel.h"
#include"hud.h"
#include<VGUI_ActionSignal.h>
#include<VGUI_TextGrid.h>
#include<VGUI_TextEntry.h>
#include<VGUI_EtchedBorder.h>
#include<VGUI_LoweredBorder.h>
using namespace vgui;
namespace
{
class Handler : public ActionSignal
{
private:
ConsolePanel* _consolePanel;
public:
Handler(ConsolePanel* consolePanel)
{
_consolePanel=consolePanel;
}
public:
virtual void actionPerformed(Panel* panel)
{
_consolePanel->doExecCommand();
}
};
}
ConsolePanel::ConsolePanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
{
setBorder(new EtchedBorder());
_textGrid=new TextGrid(80,21,5,5,200,100);
_textGrid->setBorder(new LoweredBorder());
_textGrid->setParent(this);
_textEntry=new TextEntry("",5,5,200,20);
_textEntry->setParent(this);
_textEntry->addActionSignal(new Handler(this));
}
int ConsolePanel::print(const char* text)
{
return _textGrid->printf("%s",text);
}
int ConsolePanel::vprintf(const char* format,va_list argList)
{
return _textGrid->vprintf(format,argList);
}
int ConsolePanel::printf(const char* format,...)
{
va_list argList;
va_start(argList,format);
int ret=vprintf(format,argList);
va_end(argList);
return ret;
}
void ConsolePanel::doExecCommand()
{
char buf[2048];
_textEntry->getText(0,buf,2048);
_textEntry->setText(null,0);
gEngfuncs.pfnClientCmd(buf);
}
void ConsolePanel::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
getPaintSize(wide,tall);
_textGrid->setBounds(5,5,wide-10,tall-35);
_textEntry->setBounds(5,tall-25,wide-10,20);
}

View File

@ -0,0 +1,32 @@
#ifndef CONSOLEPANEL_H
#define CONSOLEPANEL_H
#include<stdarg.h>
#include<VGUI_Panel.h>
namespace vgui
{
class TextGrid;
class TextEntry;
}
class ConsolePanel : public vgui::Panel
{
private:
vgui::TextGrid* _textGrid;
vgui::TextEntry* _textEntry;
public:
ConsolePanel(int x,int y,int wide,int tall);
public:
virtual void setSize(int wide,int tall);
virtual int print(const char* text);
virtual int vprintf(const char* format,va_list argList);
virtual int printf(const char* format,...);
virtual void doExecCommand();
};
#endif

View File

@ -0,0 +1,206 @@
#include<stdio.h>
#include"vgui_ControlConfigPanel.h"
#include<VGUI_HeaderPanel.h>
#include<VGUI_TablePanel.h>
#include<VGUI_Label.h>
#include<VGUI_ScrollPanel.h>
#include<VGUI_Scheme.h>
#include<VGUI_DataInputStream.h>
#include<VGUI.h>
#include<VGUI_TextEntry.h>
using namespace vgui;
namespace
{
class FooTablePanel : public TablePanel
{
private:
Label* _label;
TextEntry* _textEntry;
ControlConfigPanel* _controlConfigPanel;
public:
FooTablePanel(ControlConfigPanel* controlConfigPanel,int x,int y,int wide,int tall,int columnCount) : TablePanel(x,y,wide,tall,columnCount)
{
_controlConfigPanel=controlConfigPanel;
_label=new Label("You are a dumb monkey",0,0,100,20);
_label->setBgColor(Scheme::sc_primary3);
_label->setFgColor(Scheme::sc_primary1);
_label->setFont(Scheme::sf_primary3);
_textEntry=new TextEntry("",0,0,100,20);
//_textEntry->setFont(Scheme::sf_primary3);
}
public:
virtual int getRowCount()
{
return _controlConfigPanel->GetCVarCount();
}
virtual int getCellTall(int row)
{
return 12;
}
virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
{
char cvar[128],desc[128],bind[128],bindAlt[128];
_controlConfigPanel->GetCVar(row,cvar,128,desc,128);
if(cellSelected)
{
_label->setBgColor(Scheme::sc_primary1);
_label->setFgColor(Scheme::sc_primary3);
}
else
if(rowSelected)
{
_label->setBgColor(Scheme::sc_primary2);
_label->setFgColor(Scheme::sc_primary1);
}
else
{
_label->setBgColor(Scheme::sc_primary3);
_label->setFgColor(Scheme::sc_primary1);
}
switch(column)
{
case 0:
{
_label->setText(desc);
_label->setContentAlignment(Label::a_west);
break;
}
case 1:
{
_controlConfigPanel->GetCVarBind(cvar,bind,128,bindAlt,128);
_label->setText(bind);
_label->setContentAlignment(Label::a_center);
break;
}
case 2:
{
_controlConfigPanel->GetCVarBind(cvar,bind,128,bindAlt,128);
_label->setText(bindAlt);
_label->setContentAlignment(Label::a_center);
break;
}
default:
{
_label->setText("");
break;
}
}
return _label;
}
virtual Panel* startCellEditing(int column,int row)
{
_textEntry->setText("Goat",strlen("Goat"));
_textEntry->requestFocus();
return _textEntry;
}
};
}
ControlConfigPanel::ControlConfigPanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
{
setPaintBorderEnabled(false);
setPaintBackgroundEnabled(false);
setPaintEnabled(false);
_actionLabel=new Label("Action");
_actionLabel->setBgColor(Scheme::sc_primary3);
_actionLabel->setFgColor(Scheme::sc_primary3);
_keyButtonLabel=new Label("Key / Button");
_keyButtonLabel->setBgColor(Scheme::sc_primary3);
_keyButtonLabel->setFgColor(Scheme::sc_primary3);
_alternateLabel=new Label("Alternate");
_alternateLabel->setBgColor(Scheme::sc_primary3);
_alternateLabel->setFgColor(Scheme::sc_primary3);
_headerPanel=new HeaderPanel(0,0,wide,20);
_headerPanel->setParent(this);
_headerPanel->addSectionPanel(_actionLabel);
_headerPanel->addSectionPanel(_keyButtonLabel);
_headerPanel->addSectionPanel(_alternateLabel);
_headerPanel->setSliderPos( 0, wide/2 );
_headerPanel->setSliderPos( 1, (wide/2) + (wide/4) );
_headerPanel->setSliderPos( 2, wide );
_scrollPanel=new ScrollPanel(0,20,wide,tall-20);
_scrollPanel->setParent(this);
_scrollPanel->setPaintBorderEnabled(false);
_scrollPanel->setPaintBackgroundEnabled(false);
_scrollPanel->setPaintEnabled(false);
_scrollPanel->getClient()->setPaintBorderEnabled(false);
_scrollPanel->getClient()->setPaintBackgroundEnabled(false);
_scrollPanel->getClient()->setPaintEnabled(false);
_scrollPanel->setScrollBarVisible(false,true);
_tablePanel=new FooTablePanel(this,0,0,_scrollPanel->getClient()->getWide(),800, 3);
_tablePanel->setParent(_scrollPanel->getClient());
_tablePanel->setHeaderPanel(_headerPanel);
_tablePanel->setBgColor(Color(200,0,0,255));
_tablePanel->setFgColor(Color(Scheme::sc_primary2));
_tablePanel->setGridVisible(true,true);
_tablePanel->setGridSize(1,1);
}
void ControlConfigPanel::AddCVar(const char* cvar,const char* desc)
{
_cvarDar.addElement(vgui_strdup(cvar));
_descDar.addElement(vgui_strdup(desc));
}
int ControlConfigPanel::GetCVarCount()
{
return _cvarDar.getCount();
}
void ControlConfigPanel::GetCVar(int index,char* cvar,int cvarLen,char* desc,int descLen)
{
vgui_strcpy(cvar,cvarLen,_cvarDar[index]);
vgui_strcpy(desc,descLen,_descDar[index]);
}
void ControlConfigPanel::AddCVarFromInputStream(InputStream* is)
{
if(is==null)
{
return;
}
DataInputStream dis(is);
bool success;
while(1)
{
char buf[256],cvar[128],desc[128];
dis.readLine(buf,256,success);
if(!success)
{
break;
}
if(sscanf(buf,"\"%[^\"]\" \"%[^\"]\"",cvar,desc)==2)
{
AddCVar(cvar,desc);
}
}
}
void ControlConfigPanel::GetCVarBind(const char* cvar,char* bind,int bindLen,char* bindAlt,int bindAltLen)
{
sprintf(bind,"%s : Bind",cvar);
sprintf(bindAlt,"%s : BindAlt",cvar);
}
void ControlConfigPanel::SetCVarBind(const char* cvar,const char* bind,const char* bindAlt)
{
}

View File

@ -0,0 +1,41 @@
#ifndef CONTROLCONFIGPANEL_H
#define CONTROLCONFIGPANEL_H
#include<VGUI_Panel.h>
#include<VGUI_Dar.h>
namespace vgui
{
class HeaderPanel;
class TablePanel;
class ScrollPanel;
class InputStream;
class Label;
}
class ControlConfigPanel : public vgui::Panel
{
private:
vgui::HeaderPanel* _headerPanel;
vgui::TablePanel* _tablePanel;
vgui::ScrollPanel* _scrollPanel;
vgui::Dar<char*> _cvarDar;
vgui::Dar<char*> _descDar;
vgui::Label* _actionLabel;
vgui::Label* _keyButtonLabel;
vgui::Label* _alternateLabel;
public:
ControlConfigPanel(int x,int y,int wide,int tall);
public:
void AddCVar(const char* cvar,const char* desc);
void AddCVarFromInputStream(vgui::InputStream* is);
int GetCVarCount();
void GetCVar(int index,char* cvar,int cvarLen,char* desc,int descLen);
void GetCVarBind(const char* cvar,char* bind,int bindLen,char* bindAlt,int bindAltLen);
void SetCVarBind(const char* cvar,const char* bind,const char* bindAlt);
};
#endif

View File

@ -0,0 +1,441 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Contains implementation of various VGUI-derived objects
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "VGUI_Font.h"
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
#include "kbutton.h"
#include "cvardef.h"
#include "usercmd.h"
#include "const.h"
#include "camera.h"
#include "in_defs.h"
#include "parsemsg.h"
#include "vgui_int.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ServerBrowser.h"
// Arrow filenames
char *sArrowFilenames[] =
{
"arrowup",
"arrowdn",
"arrowlt",
"arrowrt",
};
//-----------------------------------------------------------------------------
// Purpose: Loads a .tga file and returns a pointer to the VGUI tga object
//-----------------------------------------------------------------------------
BitmapTGA *LoadTGA( const char* pImageName )
{
BitmapTGA *pTGA;
char sz[256];
sprintf(sz, "%%d_%s", pImageName);
// Load the Image
FileInputStream* fis = new FileInputStream( GetVGUITGAName(sz), false );
pTGA = new BitmapTGA(fis,true);
fis->close();
return pTGA;
}
//===========================================================
// All TFC Hud buttons are derived from this one.
CommandButton::CommandButton( const char* text,int x,int y,int wide,int tall, bool bNoHighlight) : Button("",x,y,wide,tall)
{
m_iPlayerClass = 0;
m_bNoHighlight = bNoHighlight;
Init();
setText( text );
}
CommandButton::CommandButton( int iPlayerClass, const char* text,int x,int y,int wide,int tall) : Button("",x,y,wide,tall)
{
m_iPlayerClass = iPlayerClass;
m_bNoHighlight = false;
Init();
setText( text );
}
void CommandButton::Init( void )
{
m_pSubMenu = NULL;
m_pSubLabel = NULL;
m_pParentMenu = NULL;
// Set text color to orange
setFgColor(Scheme::sc_primary1);
// left align
setContentAlignment( vgui::Label::a_west );
// Add the Highlight signal
if (!m_bNoHighlight)
addInputSignal( new CHandler_CommandButtonHighlight(this) );
// not bound to any button yet
m_cBoundKey = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Prepends the button text with the current bound key
// if no bound key, then a clear space ' ' instead
//-----------------------------------------------------------------------------
void CommandButton::RecalculateText( void )
{
char szBuf[128];
if ( m_cBoundKey != 0 )
{
sprintf( szBuf, " %c %s", m_cBoundKey, m_sMainText );
szBuf[MAX_BUTTON_SIZE-1] = 0;
}
else
{
// just draw a space if no key bound
sprintf( szBuf, " %s", m_sMainText );
szBuf[MAX_BUTTON_SIZE-1] = 0;
}
Button::setText( szBuf );
}
void CommandButton::setText( const char *text )
{
strncpy( m_sMainText, text, MAX_BUTTON_SIZE );
m_sMainText[MAX_BUTTON_SIZE-1] = 0;
RecalculateText();
}
void CommandButton::setBoundKey( char boundKey )
{
m_cBoundKey = boundKey;
RecalculateText();
}
char CommandButton::getBoundKey( void )
{
return m_cBoundKey;
}
void CommandButton::AddSubMenu( CCommandMenu *pNewMenu )
{
m_pSubMenu = pNewMenu;
// Prevent this button from being pushed
setMouseClickEnabled( MOUSE_LEFT, false );
}
void CommandButton::UpdateSubMenus( int iAdjustment )
{
if ( m_pSubMenu )
m_pSubMenu->RecalculatePositions( iAdjustment );
}
void CommandButton::paint()
{
// Make the sub label paint the same as the button
if ( m_pSubLabel )
{
if ( isSelected() )
m_pSubLabel->PushDown();
else
m_pSubLabel->PushUp();
}
// draw armed button text in white
if ( isArmed() )
{
setFgColor( Scheme::sc_secondary2 );
}
else
{
setFgColor( Scheme::sc_primary1 );
}
Button::paint();
}
void CommandButton::paintBackground()
{
if ( isArmed() )
{
// Orange highlight background
drawSetColor( Scheme::sc_primary2 );
drawFilledRect(0,0,_size[0],_size[1]);
}
// Orange Border
drawSetColor( Scheme::sc_secondary1 );
drawOutlinedRect(0,0,_size[0],_size[1]);
}
//-----------------------------------------------------------------------------
// Purpose: Highlights the current button, and all it's parent menus
//-----------------------------------------------------------------------------
void CommandButton::cursorEntered( void )
{
// unarm all the other buttons in this menu
CCommandMenu *containingMenu = getParentMenu();
if ( containingMenu )
{
containingMenu->ClearButtonsOfArmedState();
// make all our higher buttons armed
CCommandMenu *pCParent = containingMenu->GetParentMenu();
if ( pCParent )
{
CommandButton *pParentButton = pCParent->FindButtonWithSubmenu( containingMenu );
pParentButton->cursorEntered();
}
}
// arm ourselves
setArmed( true );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CommandButton::cursorExited( void )
{
// only clear ourselves if we have do not have a containing menu
// only stay armed if we have a sub menu
// the buttons only unarm themselves when another button is armed instead
if ( !getParentMenu() || !GetSubMenu() )
{
setArmed( false );
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns the command menu that the button is part of, if any
// Output : CCommandMenu *
//-----------------------------------------------------------------------------
CCommandMenu *CommandButton::getParentMenu( void )
{
return m_pParentMenu;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the menu that contains this button
// Input : *pParentMenu -
//-----------------------------------------------------------------------------
void CommandButton::setParentMenu( CCommandMenu *pParentMenu )
{
m_pParentMenu = pParentMenu;
}
//===========================================================
int ClassButton::IsNotValid()
{
// If this is the main ChangeClass button, remove it if the player's only able to be civilians
if ( m_iPlayerClass == -1 )
{
if (gViewPort->GetValidClasses(g_iTeamNumber) == -1)
return true;
return false;
}
// Is it an illegal class?
if ((gViewPort->GetValidClasses(0) & sTFValidClassInts[ m_iPlayerClass ]) || (gViewPort->GetValidClasses(g_iTeamNumber) & sTFValidClassInts[ m_iPlayerClass ]))
return true;
// Only check current class if they've got autokill on
bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0;
if ( bAutoKill )
{
// Is it the player's current class?
if ( (gViewPort->IsRandomPC() && m_iPlayerClass == PC_RANDOM) || (!gViewPort->IsRandomPC() && (m_iPlayerClass == g_iPlayerClass)) )
return true;
}
return false;
}
//===========================================================
// Button with Class image beneath it
CImageLabel::CImageLabel( const char* pImageName,int x,int y ) : Label( "", x,y )
{
setContentFitted(true);
m_pTGA = LoadTGA(pImageName);
setImage( m_pTGA );
}
CImageLabel::CImageLabel( const char* pImageName,int x,int y,int wide,int tall ) : Label( "", x,y,wide,tall )
{
setContentFitted(true);
m_pTGA = LoadTGA(pImageName);
setImage( m_pTGA );
}
//===========================================================
// Image size
int CImageLabel::getImageWide( void )
{
int iXSize, iYSize;
m_pTGA->getSize( iXSize, iYSize );
return iXSize;
}
int CImageLabel::getImageTall( void )
{
int iXSize, iYSize;
m_pTGA->getSize( iXSize, iYSize );
return iYSize;
}
//===========================================================
// Various overloaded paint functions for Custom VGUI objects
void CCommandMenu::paintBackground()
{
// Transparent black background
drawSetColor(Scheme::sc_primary3);
drawFilledRect(0,0,_size[0],_size[1]);
}
//=================================================================================
// CUSTOM SCROLLPANEL
//=================================================================================
CTFScrollButton::CTFScrollButton(int iArrow, const char* text,int x,int y,int wide,int tall) : CommandButton(text,x,y,wide,tall)
{
// Set text color to orange
setFgColor(Scheme::sc_primary1);
// Load in the arrow
m_pTGA = LoadTGA( sArrowFilenames[iArrow] );
setImage( m_pTGA );
// Highlight signal
InputSignal *pISignal = new CHandler_CommandButtonHighlight(this);
addInputSignal(pISignal);
}
void CTFScrollButton::paint( void )
{
// draw armed button text in white
if ( isArmed() )
{
m_pTGA->setColor( Color(255,255,255, 0) );
}
else
{
m_pTGA->setColor( Color(255,255,255, 128) );
}
m_pTGA->doPaint(this);
}
void CTFScrollButton::paintBackground( void )
{
/*
if ( isArmed() )
{
// Orange highlight background
drawSetColor( Scheme::sc_primary2 );
drawFilledRect(0,0,_size[0],_size[1]);
}
// Orange Border
drawSetColor( Scheme::sc_secondary1 );
drawOutlinedRect(0,0,_size[0]-1,_size[1]);
*/
}
void CTFSlider::paintBackground( void )
{
int wide,tall,nobx,noby;
getPaintSize(wide,tall);
getNobPos(nobx,noby);
// Border
drawSetColor( Scheme::sc_secondary1 );
drawOutlinedRect( 0,0,wide,tall );
if( isVertical() )
{
// Nob Fill
drawSetColor( Scheme::sc_primary2 );
drawFilledRect( 0,nobx,wide,noby );
// Nob Outline
drawSetColor( Scheme::sc_primary1 );
drawOutlinedRect( 0,nobx,wide,noby );
}
else
{
// Nob Fill
drawSetColor( Scheme::sc_primary2 );
drawFilledRect( nobx,0,noby,tall );
// Nob Outline
drawSetColor( Scheme::sc_primary1 );
drawOutlinedRect( nobx,0,noby,tall );
}
}
CTFScrollPanel::CTFScrollPanel(int x,int y,int wide,int tall) : ScrollPanel(x,y,wide,tall)
{
ScrollBar *pScrollBar = getVerticalScrollBar();
pScrollBar->setButton( new CTFScrollButton( ARROW_UP, "", 0,0,16,16 ), 0 );
pScrollBar->setButton( new CTFScrollButton( ARROW_DOWN, "", 0,0,16,16 ), 1 );
pScrollBar->setSlider( new CTFSlider(0,wide-1,wide,(tall-(wide*2))+2,true) );
pScrollBar->setPaintBorderEnabled(false);
pScrollBar->setPaintBackgroundEnabled(false);
pScrollBar->setPaintEnabled(false);
pScrollBar = getHorizontalScrollBar();
pScrollBar->setButton( new CTFScrollButton( ARROW_LEFT, "", 0,0,16,16 ), 0 );
pScrollBar->setButton( new CTFScrollButton( ARROW_RIGHT, "", 0,0,16,16 ), 1 );
pScrollBar->setSlider( new CTFSlider(tall,0,wide-(tall*2),tall,false) );
pScrollBar->setPaintBorderEnabled(false);
pScrollBar->setPaintBackgroundEnabled(false);
pScrollBar->setPaintEnabled(false);
}
//=================================================================================
// CUSTOM HANDLERS
//=================================================================================
void CHandler_MenuButtonOver::cursorEntered(Panel *panel)
{
if ( gViewPort && m_pMenuPanel )
{
m_pMenuPanel->SetActiveInfo( m_iButton );
}
}
void CMenuHandler_StringCommandClassSelect::actionPerformed(Panel* panel)
{
CMenuHandler_StringCommand::actionPerformed( panel );
bool bAutoKill = CVAR_GET_FLOAT( "hud_classautokill" ) != 0;
if ( bAutoKill && g_iPlayerClass != 0 )
gEngfuncs.pfnClientCmd("kill");
}

147
cl_dll/vgui_MOTDWindow.cpp Normal file
View File

@ -0,0 +1,147 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "VGUI_Font.h"
#include "VGUI_ScrollPanel.h"
#include "VGUI_TextImage.h"
#include<VGUI_StackLayout.h>
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
#include "kbutton.h"
#include "const.h"
#include "vgui_int.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ServerBrowser.h"
#define MOTD_TITLE_X XRES(16)
#define MOTD_TITLE_Y YRES(16)
#define MOTD_WINDOW_X XRES(112)
#define MOTD_WINDOW_Y YRES(80)
#define MOTD_WINDOW_SIZE_X XRES(424)
#define MOTD_WINDOW_SIZE_Y YRES(312)
//-----------------------------------------------------------------------------
// Purpose: Displays the MOTD and basic server information
//-----------------------------------------------------------------------------
class CMessageWindowPanel : public CMenuPanel
{
public:
CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullScreen, int iRemoveMe, int x, int y, int wide, int tall );
private:
CTransparentPanel *m_pBackgroundPanel;
};
//-----------------------------------------------------------------------------
// Purpose: Creates a new CMessageWindowPanel
// Output : CMenuPanel - interface to the panel
//-----------------------------------------------------------------------------
CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall )
{
return new CMessageWindowPanel( szMOTD, szTitle, iShadeFullscreen, iRemoveMe, x, y, wide, tall );
}
//-----------------------------------------------------------------------------
// Purpose: Constructs a message panel
//-----------------------------------------------------------------------------
CMessageWindowPanel::CMessageWindowPanel( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall ) : CMenuPanel( iShadeFullscreen ? 100 : 255, iRemoveMe, x, y, wide, tall )
{
// Get the scheme used for the Titles
CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
// schemes
SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
SchemeHandle_t hMOTDText = pSchemes->getSchemeHandle( "Briefing Text" );
// color schemes
int r, g, b, a;
// Create the window
m_pBackgroundPanel = new CTransparentPanel( iShadeFullscreen ? 255 : 100, MOTD_WINDOW_X, MOTD_WINDOW_Y, MOTD_WINDOW_SIZE_X, MOTD_WINDOW_SIZE_Y );
m_pBackgroundPanel->setParent( this );
m_pBackgroundPanel->setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0)) );
m_pBackgroundPanel->setVisible( true );
int iXSize,iYSize,iXPos,iYPos;
m_pBackgroundPanel->getPos( iXPos,iYPos );
m_pBackgroundPanel->getSize( iXSize,iYSize );
// Create the title
Label *pLabel = new Label( "", iXPos + MOTD_TITLE_X, iYPos + MOTD_TITLE_Y );
pLabel->setParent( this );
pLabel->setFont( pSchemes->getFont(hTitleScheme) );
pLabel->setFont( Scheme::sf_primary1 );
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
pLabel->setFgColor( r, g, b, a );
pLabel->setFgColor( Scheme::sc_primary1 );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
pLabel->setBgColor( r, g, b, a );
pLabel->setContentAlignment( vgui::Label::a_west );
pLabel->setText(szTitle);
// Create the Scroll panel
ScrollPanel *pScrollPanel = new CTFScrollPanel( iXPos + XRES(16), iYPos + MOTD_TITLE_Y*2 + YRES(16), iXSize - XRES(32), iYSize - (YRES(48) + BUTTON_SIZE_Y*2) );
pScrollPanel->setParent(this);
//force the scrollbars on so clientClip will take them in account after the validate
pScrollPanel->setScrollBarAutoVisible(false, false);
pScrollPanel->setScrollBarVisible(true, true);
pScrollPanel->validate();
// Create the text panel
TextPanel *pText = new TextPanel( "", 0,0, 64,64);
pText->setParent( pScrollPanel->getClient() );
// get the font and colors from the scheme
pText->setFont( pSchemes->getFont(hMOTDText) );
pSchemes->getFgColor( hMOTDText, r, g, b, a );
pText->setFgColor( r, g, b, a );
pSchemes->getBgColor( hMOTDText, r, g, b, a );
pText->setBgColor( r, g, b, a );
pText->setText(szMOTD);
pText->setSize(pScrollPanel->getClientClip()->getWide()-2, 5000);
// Get the total size of the MOTD text and resize the text panel
int iScrollSizeX, iScrollSizeY;
pText->getTextImage()->getTextSizeWrapped( iScrollSizeX, iScrollSizeY );
pText->setSize( iScrollSizeX , iScrollSizeY );
//pText->setBorder(new LineBorder());
//turn the scrollbars back into automode
pScrollPanel->setScrollBarAutoVisible(true, true);
pScrollPanel->setScrollBarVisible(false, false);
pScrollPanel->validate();
CommandButton *pButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_OK" ), iXPos + XRES(16), iYPos + iYSize - YRES(16) - BUTTON_SIZE_Y, CMENU_SIZE_X, BUTTON_SIZE_Y);
pButton->addActionSignal(new CMenuHandler_TextWindow(HIDE_TEXTWINDOW));
pButton->setParent(this);
}

View File

@ -0,0 +1,544 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "hud.h"
#include "vgui_SchemeManager.h"
#include "cvardef.h"
#include <string.h>
cvar_t *g_CV_BitmapFonts;
void Scheme_Init()
{
g_CV_BitmapFonts = gEngfuncs.pfnRegisterVariable("bitmapfonts", "1", 0);
}
//-----------------------------------------------------------------------------
// Purpose: Scheme managers data container
//-----------------------------------------------------------------------------
class CSchemeManager::CScheme
{
public:
enum {
SCHEME_NAME_LENGTH = 32,
FONT_NAME_LENGTH = 48,
FONT_FILENAME_LENGTH = 64,
};
// name
char schemeName[SCHEME_NAME_LENGTH];
// font
char fontName[FONT_NAME_LENGTH];
int fontSize;
int fontWeight;
vgui::Font *font;
int ownFontPointer; // true if the font is ours to delete
// scheme
byte fgColor[4];
byte bgColor[4];
byte armedFgColor[4];
byte armedBgColor[4];
byte mousedownFgColor[4];
byte mousedownBgColor[4];
byte borderColor[4];
// construction/destruction
CScheme();
~CScheme();
};
CSchemeManager::CScheme::CScheme()
{
schemeName[0] = 0;
fontName[0] = 0;
fontSize = 0;
fontWeight = 0;
font = NULL;
ownFontPointer = false;
}
CSchemeManager::CScheme::~CScheme()
{
// only delete our font pointer if we own it
if ( ownFontPointer )
{
delete font;
}
}
//-----------------------------------------------------------------------------
// Purpose: resolution information
// !! needs to be shared out
//-----------------------------------------------------------------------------
static int g_ResArray[] =
{
320,
400,
512,
640,
800,
1024,
1152,
1280,
1600
};
static int g_NumReses = sizeof(g_ResArray) / sizeof(int);
static byte *LoadFileByResolution( const char *filePrefix, int xRes, const char *filePostfix )
{
// find our resolution in the res array
int resNum = g_NumReses - 1;
while ( g_ResArray[resNum] > xRes )
{
resNum--;
if ( resNum < 0 )
return NULL;
}
// try open the file
byte *pFile = NULL;
while ( 1 )
{
// try load
char fname[256];
sprintf( fname, "%s%d%s", filePrefix, g_ResArray[resNum], filePostfix );
pFile = gEngfuncs.COM_LoadFile( fname, 5, NULL );
if ( pFile )
break;
if ( resNum == 0 )
return NULL;
resNum--;
};
return pFile;
}
static void ParseRGBAFromString( byte colorArray[4], const char *colorVector )
{
int r, g, b, a;
sscanf( colorVector, "%d %d %d %d", &r, &g, &b, &a );
colorArray[0] = r;
colorArray[1] = g;
colorArray[2] = b;
colorArray[3] = a;
}
//-----------------------------------------------------------------------------
// Purpose: initializes the scheme manager
// loading the scheme files for the current resolution
// Input : xRes -
// yRes - dimensions of output window
//-----------------------------------------------------------------------------
CSchemeManager::CSchemeManager( int xRes, int yRes )
{
// basic setup
m_pSchemeList = NULL;
m_iNumSchemes = 0;
// find the closest matching scheme file to our resolution
char token[1024];
char *pFile = (char*)LoadFileByResolution( "", xRes, "_textscheme.txt" );
m_xRes = xRes;
char *pFileStart = pFile;
byte *pFontData;
int fontFileLength;
char fontFilename[512];
//
// Read the scheme descriptions from the text file, into a temporary array
// format is simply:
// <paramName name> = <paramValue>
//
// a <paramName name> of "SchemeName" signals a new scheme is being described
//
const static int numTmpSchemes = 64;
static CScheme tmpSchemes[numTmpSchemes];
memset( tmpSchemes, 0, sizeof(tmpSchemes) );
int currentScheme = -1;
CScheme *pScheme = NULL;
if ( !pFile )
{
gEngfuncs.Con_DPrintf( "Unable to find *_textscheme.txt\n");
goto buildDefaultFont;
}
// record what has been entered so we can create defaults from the different values
bool hasFgColor, hasBgColor, hasArmedFgColor, hasArmedBgColor, hasMouseDownFgColor, hasMouseDownBgColor;
pFile = gEngfuncs.COM_ParseFile( pFile, token );
while ( strlen(token) > 0 && (currentScheme < numTmpSchemes) )
{
// get the paramName name
static const int tokenSize = 64;
char paramName[tokenSize], paramValue[tokenSize];
strncpy( paramName, token, tokenSize );
paramName[tokenSize-1] = 0; // ensure null termination
// get the '=' character
pFile = gEngfuncs.COM_ParseFile( pFile, token );
if ( stricmp( token, "=" ) )
{
if ( currentScheme < 0 )
{
gEngfuncs.Con_Printf( "error parsing font scheme text file at file start - expected '=', found '%s''\n", token );
}
else
{
gEngfuncs.Con_Printf( "error parsing font scheme text file at scheme '%s' - expected '=', found '%s''\n", tmpSchemes[currentScheme].schemeName, token );
}
break;
}
// get paramValue
pFile = gEngfuncs.COM_ParseFile( pFile, token );
strncpy( paramValue, token, tokenSize );
paramValue[tokenSize-1] = 0; // ensure null termination
// is this a new scheme?
if ( !stricmp(paramName, "SchemeName") )
{
// setup the defaults for the current scheme
if ( pScheme )
{
// foreground color defaults (normal -> armed -> mouse down)
if ( !hasFgColor )
{
pScheme->fgColor[0] = pScheme->fgColor[1] = pScheme->fgColor[2] = pScheme->fgColor[3] = 255;
}
if ( !hasArmedFgColor )
{
memcpy( pScheme->armedFgColor, pScheme->fgColor, sizeof(pScheme->armedFgColor) );
}
if ( !hasMouseDownFgColor )
{
memcpy( pScheme->mousedownFgColor, pScheme->armedFgColor, sizeof(pScheme->mousedownFgColor) );
}
// background color (normal -> armed -> mouse down)
if ( !hasBgColor )
{
pScheme->bgColor[0] = pScheme->bgColor[1] = pScheme->bgColor[2] = pScheme->bgColor[3] = 0;
}
if ( !hasArmedBgColor )
{
memcpy( pScheme->armedBgColor, pScheme->bgColor, sizeof(pScheme->armedBgColor) );
}
if ( !hasMouseDownBgColor )
{
memcpy( pScheme->mousedownBgColor, pScheme->armedBgColor, sizeof(pScheme->mousedownBgColor) );
}
// font size
if ( !pScheme->fontSize )
{
pScheme->fontSize = 17;
}
if ( !pScheme->fontName[0] )
{
strcpy( pScheme->fontName, "Arial" );
}
}
// create the new scheme
currentScheme++;
pScheme = &tmpSchemes[currentScheme];
hasFgColor = hasBgColor = hasArmedFgColor = hasArmedBgColor = hasMouseDownFgColor = hasMouseDownBgColor = false;
strncpy( pScheme->schemeName, paramValue, CScheme::SCHEME_NAME_LENGTH );
pScheme->schemeName[CScheme::SCHEME_NAME_LENGTH-1] = '\0'; // ensure null termination of string
}
if ( !pScheme )
{
gEngfuncs.Con_Printf( "font scheme text file MUST start with a 'SchemeName'\n");
break;
}
// pull the data out into the scheme
if ( !stricmp(paramName, "FontName") )
{
strncpy( pScheme->fontName, paramValue, CScheme::FONT_NAME_LENGTH );
pScheme->fontName[CScheme::FONT_NAME_LENGTH-1] = 0;
}
else if ( !stricmp(paramName, "FontSize") )
{
pScheme->fontSize = atoi( paramValue );
}
else if ( !stricmp(paramName, "FontWeight") )
{
pScheme->fontWeight = atoi( paramValue );
}
else if ( !stricmp(paramName, "FgColor") )
{
ParseRGBAFromString( pScheme->fgColor, paramValue );
hasFgColor = true;
}
else if ( !stricmp(paramName, "BgColor") )
{
ParseRGBAFromString( pScheme->bgColor, paramValue );
hasBgColor = true;
}
else if ( !stricmp(paramName, "FgColorArmed") )
{
ParseRGBAFromString( pScheme->armedFgColor, paramValue );
hasArmedFgColor = true;
}
else if ( !stricmp(paramName, "BgColorArmed") )
{
ParseRGBAFromString( pScheme->armedBgColor, paramValue );
hasArmedBgColor = true;
}
else if ( !stricmp(paramName, "FgColorMousedown") )
{
ParseRGBAFromString( pScheme->mousedownFgColor, paramValue );
hasMouseDownFgColor = true;
}
else if ( !stricmp(paramName, "BgColorMousedown") )
{
ParseRGBAFromString( pScheme->mousedownBgColor, paramValue );
hasMouseDownBgColor = true;
}
else if ( !stricmp(paramName, "BorderColor") )
{
ParseRGBAFromString( pScheme->borderColor, paramValue );
hasMouseDownBgColor = true;
}
// get the new token last, so we now if the loop needs to be continued or not
pFile = gEngfuncs.COM_ParseFile( pFile, token );
}
// free the file
gEngfuncs.COM_FreeFile( pFileStart );
buildDefaultFont:
// make sure we have at least 1 valid font
if ( currentScheme < 0 )
{
currentScheme = 0;
strcpy( tmpSchemes[0].schemeName, "Default Scheme" );
strcpy( tmpSchemes[0].fontName, "Arial" );
tmpSchemes[0].fontSize = 0;
tmpSchemes[0].fgColor[0] = tmpSchemes[0].fgColor[1] = tmpSchemes[0].fgColor[2] = tmpSchemes[0].fgColor[3] = 255;
tmpSchemes[0].armedFgColor[0] = tmpSchemes[0].armedFgColor[1] = tmpSchemes[0].armedFgColor[2] = tmpSchemes[0].armedFgColor[3] = 255;
tmpSchemes[0].mousedownFgColor[0] = tmpSchemes[0].mousedownFgColor[1] = tmpSchemes[0].mousedownFgColor[2] = tmpSchemes[0].mousedownFgColor[3] = 255;
}
// we have the full list of schemes in the tmpSchemes array
// now allocate the correct sized list
m_iNumSchemes = currentScheme + 1; // 0-based index
m_pSchemeList = new CScheme[ m_iNumSchemes ];
// copy in the data
memcpy( m_pSchemeList, tmpSchemes, sizeof(CScheme) * m_iNumSchemes );
// create the fonts
for ( int i = 0; i < m_iNumSchemes; i++ )
{
m_pSchemeList[i].font = NULL;
// see if the current font values exist in a previously loaded font
for ( int j = 0; j < i; j++ )
{
// check if the font name, size, and weight are the same
if ( !stricmp(m_pSchemeList[i].fontName, m_pSchemeList[j].fontName)
&& m_pSchemeList[i].fontSize == m_pSchemeList[j].fontSize
&& m_pSchemeList[i].fontWeight == m_pSchemeList[j].fontWeight )
{
// copy the pointer, but mark i as not owning it
m_pSchemeList[i].font = m_pSchemeList[j].font;
m_pSchemeList[i].ownFontPointer = false;
}
}
// if we haven't found the font already, load it ourselves
if ( !m_pSchemeList[i].font )
{
fontFileLength = -1;
pFontData = NULL;
if(g_CV_BitmapFonts && g_CV_BitmapFonts->value)
{
sprintf(fontFilename, "gfx\\vgui\\fonts\\%d_%s.tga", m_xRes, m_pSchemeList[i].schemeName);
pFontData = gEngfuncs.COM_LoadFile( fontFilename, 5, &fontFileLength );
if(!pFontData)
gEngfuncs.Con_Printf("Missing bitmap font: %s\n", fontFilename);
}
m_pSchemeList[i].font = new vgui::Font(
m_pSchemeList[i].fontName,
pFontData,
fontFileLength,
m_pSchemeList[i].fontSize,
0,
0,
m_pSchemeList[i].fontWeight,
false,
false,
false,
false);
m_pSchemeList[i].ownFontPointer = true;
}
// fix up alpha values; VGUI uses 1-A (A=0 being solid, A=255 transparent)
m_pSchemeList[i].fgColor[3] = 255 - m_pSchemeList[i].fgColor[3];
m_pSchemeList[i].bgColor[3] = 255 - m_pSchemeList[i].bgColor[3];
m_pSchemeList[i].armedFgColor[3] = 255 - m_pSchemeList[i].armedFgColor[3];
m_pSchemeList[i].armedBgColor[3] = 255 - m_pSchemeList[i].armedBgColor[3];
m_pSchemeList[i].mousedownFgColor[3] = 255 - m_pSchemeList[i].mousedownFgColor[3];
m_pSchemeList[i].mousedownBgColor[3] = 255 - m_pSchemeList[i].mousedownBgColor[3];
}
}
//-----------------------------------------------------------------------------
// Purpose: frees all the memory used by the scheme manager
//-----------------------------------------------------------------------------
CSchemeManager::~CSchemeManager()
{
delete [] m_pSchemeList;
m_iNumSchemes = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Finds a scheme in the list, by name
// Input : char *schemeName - string name of the scheme
// Output : SchemeHandle_t handle to the scheme
//-----------------------------------------------------------------------------
SchemeHandle_t CSchemeManager::getSchemeHandle( const char *schemeName )
{
// iterate through the list
for ( int i = 0; i < m_iNumSchemes; i++ )
{
if ( !stricmp(schemeName, m_pSchemeList[i].schemeName) )
return i;
}
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: always returns a valid scheme handle
// Input : schemeHandle -
// Output : CScheme
//-----------------------------------------------------------------------------
CSchemeManager::CScheme *CSchemeManager::getSafeScheme( SchemeHandle_t schemeHandle )
{
if ( schemeHandle < m_iNumSchemes )
return m_pSchemeList + schemeHandle;
return m_pSchemeList;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the schemes pointer to a font
// Input : schemeHandle -
// Output : vgui::Font
//-----------------------------------------------------------------------------
vgui::Font *CSchemeManager::getFont( SchemeHandle_t schemeHandle )
{
return getSafeScheme( schemeHandle )->font;
}
void CSchemeManager::getFgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->fgColor[0];
g = pScheme->fgColor[1];
b = pScheme->fgColor[2];
a = pScheme->fgColor[3];
}
void CSchemeManager::getBgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->bgColor[0];
g = pScheme->bgColor[1];
b = pScheme->bgColor[2];
a = pScheme->bgColor[3];
}
void CSchemeManager::getFgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->armedFgColor[0];
g = pScheme->armedFgColor[1];
b = pScheme->armedFgColor[2];
a = pScheme->armedFgColor[3];
}
void CSchemeManager::getBgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->armedBgColor[0];
g = pScheme->armedBgColor[1];
b = pScheme->armedBgColor[2];
a = pScheme->armedBgColor[3];
}
void CSchemeManager::getFgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->mousedownFgColor[0];
g = pScheme->mousedownFgColor[1];
b = pScheme->mousedownFgColor[2];
a = pScheme->mousedownFgColor[3];
}
void CSchemeManager::getBgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->mousedownBgColor[0];
g = pScheme->mousedownBgColor[1];
b = pScheme->mousedownBgColor[2];
a = pScheme->mousedownBgColor[3];
}
void CSchemeManager::getBorderColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a )
{
CScheme *pScheme = getSafeScheme( schemeHandle );
r = pScheme->borderColor[0];
g = pScheme->borderColor[1];
b = pScheme->borderColor[2];
a = pScheme->borderColor[3];
}

View File

@ -0,0 +1,47 @@
#include <VGUI_Font.h>
// handle to an individual scheme
typedef int SchemeHandle_t;
// Register console variables, etc..
void Scheme_Init();
//-----------------------------------------------------------------------------
// Purpose: Handles the loading of text scheme description from disk
// supports different font/color/size schemes at different resolutions
//-----------------------------------------------------------------------------
class CSchemeManager
{
public:
// initialization
CSchemeManager( int xRes, int yRes );
virtual ~CSchemeManager();
// scheme handling
SchemeHandle_t getSchemeHandle( const char *schemeName );
// getting info from schemes
vgui::Font *getFont( SchemeHandle_t schemeHandle );
void getFgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
void getBgColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
void getFgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
void getBgArmedColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
void getFgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
void getBgMousedownColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
void getBorderColor( SchemeHandle_t schemeHandle, int &r, int &g, int &b, int &a );
private:
class CScheme;
CScheme *m_pSchemeList;
int m_iNumSchemes;
// Resolution we were initted at.
int m_xRes;
CScheme *getSafeScheme( SchemeHandle_t schemeHandle );
};

629
cl_dll/vgui_ScorePanel.cpp Normal file
View File

@ -0,0 +1,629 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: VGUI scoreboard
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include<VGUI_LineBorder.h>
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ScorePanel.h"
hud_player_info_t g_PlayerInfoList[MAX_PLAYERS+1]; // player info from the engine
extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS+1]; // additional player info sent directly to the client dll
team_info_t g_TeamInfo[MAX_TEAMS+1];
int g_IsSpectator[MAX_PLAYERS+1];
int HUD_IsGame( const char *game );
int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 );
// Scoreboard dimensions
#define SBOARD_TITLE_SIZE_Y YRES(24)
#define SBOARD_HEADER_SIZE_Y YRES(40)
#define SBOARD_TABLE_X XRES(16)
#define SBOARD_TABLE_Y (SBOARD_TITLE_SIZE_Y + SBOARD_HEADER_SIZE_Y)
#define SBOARD_TEAM_CELL_SIZE_Y YRES(20)
#define SBOARD_CELL_SIZE_Y YRES(13)
// Column sizes
#define CSIZE_NAME XRES(140)
#define CSIZE_CLASS CSIZE_NAME + XRES(64)
#define CSIZE_KILLS CSIZE_CLASS + XRES(60)
#define CSIZE_DEATHS CSIZE_KILLS + XRES(64)
#define SMALL_CSIZE_NAME XRES(124)
#define SMALL_CSIZE_CLASS SMALL_CSIZE_NAME + XRES(60)
#define SMALL_CSIZE_KILLS SMALL_CSIZE_CLASS + XRES(64)
#define SMALL_CSIZE_DEATHS SMALL_CSIZE_KILLS + XRES(70)
#define TEAM_NO 0
#define TEAM_YES 1
#define TEAM_UNASSIGNED 2
#define TEAM_SPECTATORS 3
// Team Colors used in the scoreboard
int ScoreColorsBG[5][3] =
{
{ 0, 0, 0 },
{ 66, 114, 247 },
{ 220, 51, 38 },
{ 236, 212, 48 },
{ 68, 199, 42 },
};
int ScoreColorsFG[5][3] =
{
{ 255, 255, 255 },
{ 170, 193, 251 },
{ 215, 151, 146 },
{ 227, 203, 46 },
{ 143, 215, 142 },
};
//-----------------------------------------------------------------------------
// Purpose: Set different cell heights for Teams and Players
//-----------------------------------------------------------------------------
int ScoreTablePanel::getCellTall(int row)
{
if ( m_iIsATeam[row] )
return SBOARD_TEAM_CELL_SIZE_Y;
return SBOARD_CELL_SIZE_Y;
}
//-----------------------------------------------------------------------------
// Purpose: Render each of the cells in the Table
//-----------------------------------------------------------------------------
Panel* ScoreTablePanel::getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
{
char sz[128];
hud_player_info_t *pl_info = NULL;
team_info_t *team_info = NULL;
if ( m_iIsATeam[row] == TEAM_YES )
{
// Get the team's data
team_info = &g_TeamInfo[ m_iSortedRows[row] ];
// White text for team names
m_pLabel->setFgColor(Scheme::sc_white);
// Set background color
m_pLabel->setBgColor( ScoreColorsBG[ team_info->teamnumber ][0], ScoreColorsBG[ team_info->teamnumber ][1], ScoreColorsBG[ team_info->teamnumber ][2], 128 );
}
else if ( m_iIsATeam[row] == TEAM_UNASSIGNED || m_iIsATeam[row] == TEAM_SPECTATORS )
{
// White text for team names
m_pLabel->setFgColor(Scheme::sc_white);
// Set background color
m_pLabel->setBgColor( 0,0,0, 255 );
}
else
{
// Grey text for player names
m_pLabel->setFgColor( ScoreColorsFG[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ][0], ScoreColorsFG[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ][1], ScoreColorsFG[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ][2], 128 );
// Get the player's data
pl_info = &g_PlayerInfoList[ m_iSortedRows[row] ];
// Set background color
if ( pl_info->thisplayer ) // if it is their name, draw it a different color
{
// Highlight this player
m_pLabel->setFgColor(Scheme::sc_white);
m_pLabel->setBgColor( ScoreColorsBG[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ][0], ScoreColorsBG[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ][1], ScoreColorsBG[ g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ][2], 196 );
}
else if ( m_iSortedRows[row] == m_iLastKilledBy && m_fLastKillTime && m_fLastKillTime > gHUD.m_flTime )
{
// Killer's name
m_pLabel->setBgColor( 255,0,0, 255 - ((float)15 * (float)(m_fLastKillTime - gHUD.m_flTime)) );
}
else
{
m_pLabel->setBgColor( 0,0,0, 255 );
}
}
// Align
if (column <= 1)
{
if ( m_iIsATeam[row] )
m_pLabel->setContentAlignment( vgui::Label::a_southwest );
else
m_pLabel->setContentAlignment( vgui::Label::a_west );
}
else
{
if ( m_iIsATeam[row] )
m_pLabel->setContentAlignment( vgui::Label::a_south );
else
m_pLabel->setContentAlignment( vgui::Label::a_center );
}
// Fill out with the correct data
if ( m_iIsATeam[row] )
{
int i;
char sz2[128];
strcpy(sz, "");
switch (column)
{
case 0:
if ( m_iIsATeam[row] == TEAM_UNASSIGNED )
{
sprintf( sz2, CHudTextMessage::BufferedLocaliseTextString( "#Unassigned" ) );
}
else if ( m_iIsATeam[row] == TEAM_SPECTATORS )
{
sprintf( sz2, CHudTextMessage::BufferedLocaliseTextString( "#Spectators" ) );
}
else
{
sprintf( sz2, CHudTextMessage::BufferedLocaliseTextString( team_info->name ) );
}
// Uppercase it
for (i = 0; i < (int)strlen(sz2); i++)
{
if ( *(sz2 + i) )
sz[i] = toupper( *(sz2 + i) );
}
sz[i] = '\0';
// Append the number of players
if ( m_iIsATeam[row] == TEAM_YES )
{
if (team_info->players == 1)
sprintf(sz, "%s (1 player)", sz );
else
sprintf(sz, "%s (%d players)", sz, team_info->players );
}
break;
case 1:
// No class for teams
break;
case 2:
if ( m_iIsATeam[row] == TEAM_YES )
sprintf(sz, "%d", team_info->frags );
break;
case 3:
if ( m_iIsATeam[row] == TEAM_YES )
sprintf(sz, "%d", team_info->deaths );
break;
case 4:
if ( m_iIsATeam[row] == TEAM_YES )
sprintf(sz, "%d", team_info->ping );
break;
default:
break;
}
m_pLabel->setText(sz);
}
else
{
bool bShowClass = false;
switch (column)
{
case 0:
sprintf(sz, " %s", pl_info->name);
break;
case 1:
// No class for other team's members (unless allied or spectator)
if ( gViewPort && EV_TFC_IsAllyTeam( g_iTeamNumber, g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ) )
bShowClass = true;
// Don't show classes if this client hasnt picked a team yet
if ( g_iTeamNumber == 0 )
bShowClass = false;
if ( g_iUser1 )
bShowClass = true;
if (bShowClass)
{
// Only print Civilian if this team are all civilians
bool bNoClass = false;
if ( g_PlayerExtraInfo[ m_iSortedRows[row] ].playerclass == 0 )
{
if ( gViewPort->GetValidClasses( g_PlayerExtraInfo[ m_iSortedRows[row] ].teamnumber ) != -1 )
bNoClass = true;
}
if (bNoClass)
sprintf(sz, "");
else
sprintf( sz, "%s", CHudTextMessage::BufferedLocaliseTextString( sLocalisedClasses[ g_PlayerExtraInfo[ m_iSortedRows[row] ].playerclass ] ) );
}
else
{
strcpy(sz, "");
}
break;
case 2:
sprintf(sz, "%d", g_PlayerExtraInfo[ m_iSortedRows[row] ].frags );
break;
case 3:
sprintf(sz, "%d", g_PlayerExtraInfo[ m_iSortedRows[row] ].deaths );
break;
case 4:
sprintf(sz, "%d", g_PlayerInfoList[ m_iSortedRows[row] ].ping );
break;
default:
strcpy(sz, "");
}
m_pLabel->setText(sz);
}
return m_pLabel;
}
//-----------------------------------------------------------------------------
// Purpose: Create the ScoreBoard panel
//-----------------------------------------------------------------------------
ScorePanel::ScorePanel(int x,int y,int wide,int tall) : Panel(x,y,wide,tall)
{
setBorder( new LineBorder( Color(255 * 0.7,170 * 0.7,0,0) ) );
setBgColor( 0,0,0, 100 );
m_pTitleLabel = new Label( " SCORES", 0,0, wide, SBOARD_TITLE_SIZE_Y );
m_pTitleLabel->setBgColor( Scheme::sc_primary2 );
m_pTitleLabel->setFgColor( Scheme::sc_primary1 );
m_pTitleLabel->setContentAlignment( vgui::Label::a_west );
m_pTitleLabel->setParent(this);
_headerPanel = new HeaderPanel( SBOARD_TABLE_X, SBOARD_TITLE_SIZE_Y, wide - (SBOARD_TABLE_X * 2), SBOARD_HEADER_SIZE_Y);
_headerPanel->setParent(this);
// BUGBUG: This isn't working. gHUD.m_Teamplay hasn't been initialized yet.
if ( gHUD.m_Teamplay )
_headerPanel->addSectionPanel( new CLabelHeader( CHudTextMessage::BufferedLocaliseTextString( "#TEAMS" ), true) );
else
_headerPanel->addSectionPanel( new CLabelHeader( CHudTextMessage::BufferedLocaliseTextString( "#PLAYERS" ), true) );
if ( HUD_IsGame( "tfc" ) )
_headerPanel->addSectionPanel( new CLabelHeader( CHudTextMessage::BufferedLocaliseTextString( "#CLASS" ), true) );
else
_headerPanel->addSectionPanel( new CLabelHeader("", true) );
_headerPanel->addSectionPanel( new CLabelHeader( CHudTextMessage::BufferedLocaliseTextString( "#SCORE" )) );
_headerPanel->addSectionPanel( new CLabelHeader( CHudTextMessage::BufferedLocaliseTextString( "#DEATHS")) );
_headerPanel->addSectionPanel( new CLabelHeader( CHudTextMessage::BufferedLocaliseTextString( "#LATENCY")) );
_headerPanel->setBgColor( 0,0,0, 255 );
// Need to special case 400x300, because the titles just wont fit otherwise
if ( ScreenWidth == 400 )
{
_headerPanel->setSliderPos( 0, SMALL_CSIZE_NAME );
_headerPanel->setSliderPos( 1, SMALL_CSIZE_CLASS );
_headerPanel->setSliderPos( 2, SMALL_CSIZE_KILLS );
_headerPanel->setSliderPos( 3, SMALL_CSIZE_DEATHS );
_headerPanel->setSliderPos( 4, wide - (SBOARD_TABLE_X * 2) - 1 );
}
else
{
_headerPanel->setSliderPos( 0, CSIZE_NAME );
_headerPanel->setSliderPos( 1, CSIZE_CLASS );
_headerPanel->setSliderPos( 2, CSIZE_KILLS );
_headerPanel->setSliderPos( 3, CSIZE_DEATHS );
_headerPanel->setSliderPos( 4, wide - (SBOARD_TABLE_X * 2) - 1 );
}
_tablePanel = new ScoreTablePanel(SBOARD_TABLE_X, SBOARD_TABLE_Y, wide - (SBOARD_TABLE_X * 2), tall - SBOARD_TABLE_Y, NUM_COLUMNS);
_tablePanel->setParent(this);
_tablePanel->setHeaderPanel(_headerPanel);
_tablePanel->setBgColor( 0,0,0, 255 );
Initialize();
}
//-----------------------------------------------------------------------------
// Purpose: Called each time a new level is started.
//-----------------------------------------------------------------------------
void ScorePanel::Initialize( void )
{
// Clear out scoreboard data
_tablePanel->m_iLastKilledBy = 0;
_tablePanel->m_fLastKillTime = 0;
m_iPlayerNum = 0;
m_iNumTeams = 0;
memset( g_PlayerExtraInfo, 0, sizeof g_PlayerExtraInfo );
memset( g_TeamInfo, 0, sizeof g_TeamInfo );
}
//-----------------------------------------------------------------------------
// Purpose: Set the size of the header and table when this panel's size changes
//-----------------------------------------------------------------------------
void ScorePanel::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
_headerPanel->setBounds(0,0,wide,SBOARD_HEADER_SIZE_Y);
_tablePanel->setBounds(0,20,wide,tall - SBOARD_HEADER_SIZE_Y);
}
//-----------------------------------------------------------------------------
// Purpose: Recalculate the internal scoreboard data
//-----------------------------------------------------------------------------
void ScorePanel::Update()
{
// Set the title
if (gViewPort->m_szServerName)
{
char sz[MAX_SERVERNAME_LENGTH + 16];
sprintf(sz, " SCORES: %s", gViewPort->m_szServerName );
m_pTitleLabel->setText(sz);
}
_tablePanel->m_iRows = 0;
gViewPort->GetAllPlayersInfo();
// Clear out sorts
for (int i = 0; i < MAX_PLAYERS; i++)
{
_tablePanel->m_iSortedRows[i] = 0;
_tablePanel->m_iIsATeam[i] = TEAM_NO;
_tablePanel->m_bHasBeenSorted[i] = false;
}
// If it's not teamplay, sort all the players. Otherwise, sort the teams.
if ( !gHUD.m_Teamplay )
SortPlayers( 0, NULL );
else
SortTeams();
}
//-----------------------------------------------------------------------------
// Purpose: Sort all the teams
//-----------------------------------------------------------------------------
void ScorePanel::SortTeams()
{
// clear out team scores
for ( int i = 1; i <= m_iNumTeams; i++ )
{
if ( !g_TeamInfo[i].scores_overriden )
g_TeamInfo[i].frags = g_TeamInfo[i].deaths = 0;
g_TeamInfo[i].ping = g_TeamInfo[i].packetloss = 0;
}
// recalc the team scores, then draw them
for ( i = 1; i < MAX_PLAYERS; i++ )
{
if ( g_PlayerInfoList[i].name == NULL )
continue; // empty player slot, skip
if ( g_PlayerExtraInfo[i].teamname[0] == 0 )
continue; // skip over players who are not in a team
// find what team this player is in
for ( int j = 1; j <= m_iNumTeams; j++ )
{
if ( !stricmp( g_PlayerExtraInfo[i].teamname, g_TeamInfo[j].name ) )
break;
}
if ( j > m_iNumTeams ) // player is not in a team, skip to the next guy
continue;
if ( !g_TeamInfo[j].scores_overriden )
{
g_TeamInfo[j].frags += g_PlayerExtraInfo[i].frags;
g_TeamInfo[j].deaths += g_PlayerExtraInfo[i].deaths;
}
g_TeamInfo[j].ping += g_PlayerInfoList[i].ping;
g_TeamInfo[j].packetloss += g_PlayerInfoList[i].packetloss;
if ( g_PlayerInfoList[i].thisplayer )
g_TeamInfo[j].ownteam = TRUE;
else
g_TeamInfo[j].ownteam = FALSE;
// Set the team's number (used for team colors)
g_TeamInfo[j].teamnumber = g_PlayerExtraInfo[i].teamnumber;
}
// find team ping/packetloss averages
for ( i = 1; i <= m_iNumTeams; i++ )
{
g_TeamInfo[i].already_drawn = FALSE;
if ( g_TeamInfo[i].players > 0 )
{
g_TeamInfo[i].ping /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping
g_TeamInfo[i].packetloss /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping
}
}
// Draw the teams
while ( 1 )
{
int highest_frags = -99999; int lowest_deaths = 99999;
int best_team = 0;
for ( i = 1; i <= m_iNumTeams; i++ )
{
if ( g_TeamInfo[i].players < 1 )
continue;
if ( !g_TeamInfo[i].already_drawn && g_TeamInfo[i].frags >= highest_frags )
{
if ( g_TeamInfo[i].frags > highest_frags || g_TeamInfo[i].deaths < lowest_deaths )
{
best_team = i;
lowest_deaths = g_TeamInfo[i].deaths;
highest_frags = g_TeamInfo[i].frags;
}
}
}
// draw the best team on the scoreboard
if ( !best_team )
break;
// Put this team in the sorted list
_tablePanel->m_iSortedRows[ _tablePanel->m_iRows ] = best_team;
_tablePanel->m_iIsATeam[ _tablePanel->m_iRows ] = TEAM_YES;
g_TeamInfo[best_team].already_drawn = TRUE; // set the already_drawn to be TRUE, so this team won't get sorted again
_tablePanel->m_iRows++;
// Now sort all the players on this team
SortPlayers( 0, g_TeamInfo[best_team].name );
}
// Now add all the spectators
SortPlayers( TEAM_SPECTATORS, NULL );
// Now add all the players who aren't in a team yet
SortPlayers( TEAM_UNASSIGNED, NULL );
}
//-----------------------------------------------------------------------------
// Purpose: Sort a list of players
//-----------------------------------------------------------------------------
void ScorePanel::SortPlayers( int iTeam, char *team )
{
bool bCreatedTeam = false;
// draw the players, in order, and restricted to team if set
while ( 1 )
{
// Find the top ranking player
int highest_frags = -99999; int lowest_deaths = 99999;
int best_player;
best_player = 0;
for ( int i = 1; i < MAX_PLAYERS; i++ )
{
if ( _tablePanel->m_bHasBeenSorted[i] == false && g_PlayerInfoList[i].name && g_PlayerExtraInfo[i].frags >= highest_frags )
{
cl_entity_t *ent = gEngfuncs.GetEntityByIndex( i );
if ( ent && ((iTeam == TEAM_SPECTATORS && g_IsSpectator[i] != 0) || (iTeam != TEAM_SPECTATORS && !(team && stricmp(g_PlayerExtraInfo[i].teamname, team)))) )
{
extra_player_info_t *pl_info = &g_PlayerExtraInfo[i];
if ( pl_info->frags > highest_frags || pl_info->deaths < lowest_deaths )
{
best_player = i;
lowest_deaths = pl_info->deaths;
highest_frags = pl_info->frags;
}
}
}
}
if ( !best_player )
break;
// If we haven't created the Team yet, do it first
if (!bCreatedTeam && iTeam)
{
_tablePanel->m_iIsATeam[ _tablePanel->m_iRows ] = iTeam;
_tablePanel->m_iRows++;
bCreatedTeam = true;
}
// Put this player in the sorted list
_tablePanel->m_iSortedRows[ _tablePanel->m_iRows ] = best_player;
_tablePanel->m_bHasBeenSorted[ best_player ] = true;
_tablePanel->m_iRows++;
}
}
//-----------------------------------------------------------------------------
// Purpose: Recalculate the existing teams in the match
//-----------------------------------------------------------------------------
void ScorePanel::RebuildTeams()
{
// clear out player counts from teams
for ( int i = 1; i <= m_iNumTeams; i++ )
{
g_TeamInfo[i].players = 0;
}
// rebuild the team list
gViewPort->GetAllPlayersInfo();
m_iNumTeams = 0;
for ( i = 1; i < MAX_PLAYERS; i++ )
{
if ( g_PlayerInfoList[i].name == NULL )
continue;
if ( g_PlayerExtraInfo[i].teamname[0] == 0 )
continue; // skip over players who are not in a team
// is this player in an existing team?
for ( int j = 1; j <= m_iNumTeams; j++ )
{
if ( g_TeamInfo[j].name[0] == '\0' )
break;
if ( !stricmp( g_PlayerExtraInfo[i].teamname, g_TeamInfo[j].name ) )
break;
}
if ( j > m_iNumTeams )
{ // they aren't in a listed team, so make a new one
// search through for an empty team slot
for ( int j = 1; j <= m_iNumTeams; j++ )
{
if ( g_TeamInfo[j].name[0] == '\0' )
break;
}
m_iNumTeams = max( j, m_iNumTeams );
strncpy( g_TeamInfo[j].name, g_PlayerExtraInfo[i].teamname, MAX_TEAM_NAME );
g_TeamInfo[j].players = 0;
}
g_TeamInfo[j].players++;
}
// clear out any empty teams
for ( i = 1; i <= m_iNumTeams; i++ )
{
if ( g_TeamInfo[i].players < 1 )
memset( &g_TeamInfo[i], 0, sizeof(team_info_t) );
}
// Update the scoreboard
Update();
}
//-----------------------------------------------------------------------------
// Purpose: Setup highlights for player names in scoreboard
//-----------------------------------------------------------------------------
void ScorePanel::DeathMsg( int killer, int victim )
{
// if we were the one killed, or the world killed us, set the scoreboard to indicate suicide
if ( victim == m_iPlayerNum || killer == 0 )
{
_tablePanel->m_iLastKilledBy = killer ? killer : m_iPlayerNum;
_tablePanel->m_fLastKillTime = gHUD.m_flTime + 10; // display who we were killed by for 10 seconds
if ( killer == m_iPlayerNum )
_tablePanel->m_iLastKilledBy = m_iPlayerNum;
}
}

122
cl_dll/vgui_ScorePanel.h Normal file
View File

@ -0,0 +1,122 @@
#ifndef SCOREPANEL_H
#define SCOREPANEL_H
#include<VGUI_Panel.h>
#include<VGUI_TablePanel.h>
#include<VGUI_HeaderPanel.h>
#include<VGUI_TextGrid.h>
#include<VGUI_Label.h>
#define MAX_SCORES 10
// Scoreboard cells
#define NUM_COLUMNS 5
#define NUM_ROWS (MAX_PLAYERS + MAX_TEAMS)
// Scoreboard positions
#define SBOARD_INDENT_X XRES(104)
#define SBOARD_INDENT_Y YRES(40)
using namespace vgui;
//-----------------------------------------------------------------------------
// Purpose: Custom label for cells in the Scoreboard's Table Header
//-----------------------------------------------------------------------------
class CLabelHeader : public Label
{
private:
void Init( void )
{
setFont( Scheme::sf_primary1 );
setFgColor( Scheme::sc_primary1 );
setBgColor( 0,0,0, 255 );
}
public:
CLabelHeader(const char* text,int x,int y,int wide,int tall) : Label(text,x,y,wide,tall)
{
Init();
}
CLabelHeader(const char* text, bool bAlignLeft = false) : Label(text)
{
Init();
if (bAlignLeft)
setContentAlignment(Label::a_west);
}
};
//-----------------------------------------------------------------------------
// Purpose: Custom Table for the scoreboard
//-----------------------------------------------------------------------------
class ScoreTablePanel : public TablePanel
{
private:
TextGrid *_textGrid;
Label *m_pLabel;
public:
int m_iRows;
int m_iSortedRows[NUM_ROWS];
int m_iIsATeam[NUM_ROWS];
bool m_bHasBeenSorted[MAX_PLAYERS];
int m_iLastKilledBy;
int m_fLastKillTime;
public:
ScoreTablePanel(int x,int y,int wide,int tall,int columnCount) : TablePanel(x,y,wide,tall,columnCount)
{
setCellEditingEnabled(false);
m_pLabel = new Label( "", 0, 0, wide, tall );
m_pLabel->setFont( Scheme::sf_primary2 );
}
virtual int getRowCount()
{
return m_iRows;
}
virtual Panel* startCellEditing(int column,int row)
{
return null;
}
virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected);
virtual int getCellTall(int row);
};
//-----------------------------------------------------------------------------
// Purpose: Scoreboard back panel
//-----------------------------------------------------------------------------
class ScorePanel : public Panel
{
private:
HeaderPanel *_headerPanel;
ScoreTablePanel *_tablePanel;
Label *m_pTitleLabel;
public:
int m_iNumTeams;
int m_iPlayerNum;
int m_iShowscoresHeld;
public:
ScorePanel(int x,int y,int wide,int tall);
virtual void setSize(int wide,int tall);
void Update( void );
void SortTeams( void );
void SortPlayers( int iTeam, char *team );
void RebuildTeams( void );
void DeathMsg( int killer, int victim );
void Initialize( void );
void Open( void )
{
RebuildTeams();
setVisible(true);
}
};
#endif

View File

@ -0,0 +1,617 @@
#include<VGUI_HeaderPanel.h>
#include<VGUI_TablePanel.h>
#include<VGUI_LineBorder.h>
#include<VGUI_Label.h>
#include<VGUI_Button.h>
#include<VGUI_ActionSignal.h>
#include "hud.h"
#include "cl_util.h"
#include "hud_servers.h"
#include "net_api.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ServerBrowser.h"
using namespace vgui;
namespace
{
#define MAX_SB_ROWS 24
#define NUM_COLUMNS 5
#define HEADER_SIZE_Y YRES(18)
// Column sizes
#define CSIZE_ADDRESS XRES(200)
#define CSIZE_SERVER XRES(400)
#define CSIZE_MAP XRES(500)
#define CSIZE_CURRENT XRES(570)
#define CSIZE_PING XRES(640)
#define CELL_HEIGHT YRES(15)
class ServerBrowserTablePanel;
class CBrowser_InputSignal : public InputSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
CBrowser_InputSignal( ServerBrowserTablePanel *pBrowser )
{
m_pBrowser = pBrowser;
}
virtual void cursorMoved(int x,int y,Panel* panel) {};
virtual void cursorEntered(Panel* panel){};
virtual void cursorExited(Panel* Panel) {};
virtual void mousePressed(MouseCode code,Panel* panel);
virtual void mouseDoublePressed(MouseCode code,Panel* panel);
virtual void mouseReleased(MouseCode code,Panel* panel) {};
virtual void mouseWheeled(int delta,Panel* panel) {};
virtual void keyPressed(KeyCode code,Panel* panel) {};
virtual void keyTyped(KeyCode code,Panel* panel) {};
virtual void keyReleased(KeyCode code,Panel* panel) {};
virtual void keyFocusTicked(Panel* panel) {};
};
class ServerBrowserTablePanel : public TablePanel
{
private:
Label *m_pLabel;
int m_nMouseOverRow;
public:
ServerBrowserTablePanel( int x,int y,int wide,int tall,int columnCount) : TablePanel( x,y,wide,tall,columnCount)
{
m_pLabel = new Label( "", 0, 0 /*,wide, tall*/ );
m_nMouseOverRow = 0;
}
public:
void setMouseOverRow( int row )
{
m_nMouseOverRow = row;
}
void DoSort( char *sortkey )
{
// Request server list and refresh servers...
SortServers( sortkey );
}
void DoRefresh( void )
{
// Request server list and refresh servers...
ServersList();
BroadcastServersList( 0 );
}
void DoBroadcastRefresh( void )
{
// Request server list and refresh servers...
BroadcastServersList( 1 );
}
void DoStop( void )
{
// Stop requesting
ServersCancel();
}
void DoCancel( void )
{
ClientCmd( "togglebrowser\n" );
}
void DoConnect( void )
{
const char *info;
const char *address;
char sz[ 256 ];
info = ServersGetInfo( m_nMouseOverRow );
if ( !info )
return;
address = gEngfuncs.pNetAPI->ValueForKey( info, "address" );
//gEngfuncs.Con_Printf( "Connecting to %s\n", address );
sprintf( sz, "connect %s\n", address );
ClientCmd( sz );
DoCancel();
}
void DoPing( void )
{
ServerPing( 0 );
ServerRules( 0 );
ServerPlayers( 0 );
}
virtual int getRowCount()
{
int rowcount;
int height, width;
getSize( width, height );
// Space for buttons
height -= YRES(20);
height = max( 0, height );
rowcount = height / CELL_HEIGHT;
return rowcount;
}
virtual int getCellTall(int row)
{
return CELL_HEIGHT - 2;
}
virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected)
{
const char *info;
const char *val, *val2;
char sz[ 32 ];
info = ServersGetInfo( row );
if ( row == m_nMouseOverRow )
{
m_pLabel->setFgColor( 200, 240, 63, 100 );
}
else
{
m_pLabel->setFgColor( 255, 255, 255, 0 );
}
m_pLabel->setBgColor( 0, 0, 0, 200 );
m_pLabel->setContentAlignment( vgui::Label::a_west );
m_pLabel->setFont( Scheme::sf_primary2 );
if ( info )
{
// Fill out with the correct data
switch ( column )
{
case 0:
val = gEngfuncs.pNetAPI->ValueForKey( info, "address" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Name;
m_pLabel->setText( sz );
}
break;
case 1:
val = gEngfuncs.pNetAPI->ValueForKey( info, "hostname" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Map;
m_pLabel->setText( sz );
}
break;
case 2:
val = gEngfuncs.pNetAPI->ValueForKey( info, "map" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Name;
m_pLabel->setText( sz );
}
break;
case 3:
val = gEngfuncs.pNetAPI->ValueForKey( info, "current" );
val2 = gEngfuncs.pNetAPI->ValueForKey( info, "max" );
if ( val && val2 )
{
sprintf( sz, "%s/%s", val, val2 );
sz[ 31 ] = '\0';
// Server Map;
m_pLabel->setText( sz );
}
break;
case 4:
val = gEngfuncs.pNetAPI->ValueForKey( info, "ping" );
if ( val )
{
strncpy( sz, val, 31 );
sz[ 31 ] = '\0';
// Server Name;
m_pLabel->setText( sz );
}
break;
default:
break;
}
}
else
{
if ( !row && !column )
{
if ( ServersIsQuerying() )
{
m_pLabel->setText( "Waiting for servers to respond..." );
}
else
{
m_pLabel->setText( "Press 'Refresh' to search for servers..." );
}
}
else
{
m_pLabel->setText( "" );
}
}
return m_pLabel;
}
virtual Panel* startCellEditing(int column,int row)
{
return null;
}
};
class ConnectHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
ConnectHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoConnect();
}
};
class RefreshHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
RefreshHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoRefresh();
}
};
class BroadcastRefreshHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
BroadcastRefreshHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoBroadcastRefresh();
}
};
class StopHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
StopHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoStop();
}
};
class CancelHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
CancelHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoCancel();
}
};
class PingHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
PingHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoPing();
}
};
class SortHandler : public ActionSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
public:
SortHandler( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
}
virtual void actionPerformed( Panel *panel )
{
m_pBrowser->DoSort( "map" );
}
};
}
class LabelSortInputHandler : public InputSignal
{
private:
ServerBrowserTablePanel *m_pBrowser;
char m_szSortKey[ 64 ];
public:
LabelSortInputHandler( ServerBrowserTablePanel *pBrowser, char *name )
{
m_pBrowser = pBrowser;
strcpy( m_szSortKey, name );
}
virtual void cursorMoved(int x,int y,Panel* panel) {};
virtual void cursorEntered(Panel* panel){};
virtual void cursorExited(Panel* Panel) {};
virtual void mousePressed(MouseCode code,Panel* panel)
{
m_pBrowser->DoSort( m_szSortKey );
}
virtual void mouseDoublePressed(MouseCode code,Panel* panel)
{
m_pBrowser->DoSort( m_szSortKey );
}
virtual void mouseReleased(MouseCode code,Panel* panel) {};
virtual void mouseWheeled(int delta,Panel* panel) {};
virtual void keyPressed(KeyCode code,Panel* panel) {};
virtual void keyTyped(KeyCode code,Panel* panel) {};
virtual void keyReleased(KeyCode code,Panel* panel) {};
virtual void keyFocusTicked(Panel* panel) {};
};
class CSBLabel : public Label
{
private:
char m_szSortKey[ 64 ];
ServerBrowserTablePanel *m_pBrowser;
public:
CSBLabel( char *name, char *sortkey ) : Label( name )
{
m_pBrowser = NULL;
strcpy( m_szSortKey, sortkey );
int label_bg_r = 120,
label_bg_g = 75,
label_bg_b = 32,
label_bg_a = 200;
int label_fg_r = 255,
label_fg_g = 0,
label_fg_b = 0,
label_fg_a = 0;
setContentAlignment( vgui::Label::a_west );
setFgColor( label_fg_r, label_fg_g, label_fg_b, label_fg_a );
setBgColor( label_bg_r, label_bg_g, label_bg_b, label_bg_a );
setFont( Scheme::sf_primary2 );
}
void setTable( ServerBrowserTablePanel *browser )
{
m_pBrowser = browser;
addInputSignal( new LabelSortInputHandler( (ServerBrowserTablePanel * )m_pBrowser, m_szSortKey ) );
}
};
ServerBrowser::ServerBrowser(int x,int y,int wide,int tall) : CTransparentPanel( 100, x,y,wide,tall )
{
int i;
_headerPanel = new HeaderPanel(0,0,wide,HEADER_SIZE_Y);
_headerPanel->setParent(this);
_headerPanel->setFgColor( 100,100,100, 100 );
_headerPanel->setBgColor( 0, 0, 0, 100 );
CSBLabel *pLabel[5];
pLabel[0] = new CSBLabel( "Address", "address" );
pLabel[1] = new CSBLabel( "Server", "hostname" );
pLabel[2] = new CSBLabel( "Map", "map" );
pLabel[3] = new CSBLabel( "Current", "current" );
pLabel[4] = new CSBLabel( "Latency", "ping" );
for ( i = 0; i < 5; i++ )
{
_headerPanel->addSectionPanel( pLabel[i] );
}
// _headerPanel->setFont( Scheme::sf_primary1 );
_headerPanel->setSliderPos( 0, CSIZE_ADDRESS );
_headerPanel->setSliderPos( 1, CSIZE_SERVER );
_headerPanel->setSliderPos( 2, CSIZE_MAP );
_headerPanel->setSliderPos( 3, CSIZE_CURRENT );
_headerPanel->setSliderPos( 4, CSIZE_PING );
_tablePanel = new ServerBrowserTablePanel( 0, HEADER_SIZE_Y, wide, tall - HEADER_SIZE_Y, NUM_COLUMNS );
_tablePanel->setParent(this);
_tablePanel->setHeaderPanel(_headerPanel);
_tablePanel->setFgColor( 100,100,100, 100 );
_tablePanel->setBgColor( 0, 0, 0, 100 );
_tablePanel->addInputSignal( new CBrowser_InputSignal( (ServerBrowserTablePanel *)_tablePanel ) );
for ( i = 0; i < 5; i++ )
{
pLabel[i]->setTable( (ServerBrowserTablePanel * )_tablePanel );
}
int bw = 80, bh = 15;
int by = tall - HEADER_SIZE_Y;
int btnx = 10;
_connectButton = new CommandButton( "Connect", btnx, by, bw, bh );
_connectButton->setParent( this );
_connectButton->addActionSignal( new ConnectHandler( (ServerBrowserTablePanel * )_tablePanel ) );
btnx += bw;
_refreshButton = new CommandButton( "Refresh", btnx, by, bw, bh );
_refreshButton->setParent( this );
_refreshButton->addActionSignal( new RefreshHandler( (ServerBrowserTablePanel * )_tablePanel ) );
/*
btnx += bw;
_broadcastRefreshButton = new CommandButton( "LAN", btnx, by, bw, bh );
_broadcastRefreshButton->setParent( this );
_broadcastRefreshButton->addActionSignal( new BroadcastRefreshHandler( (ServerBrowserTablePanel * )_tablePanel ) );
*/
btnx += bw;
_stopButton = new CommandButton( "Stop", btnx, by, bw, bh );
_stopButton->setParent( this );
_stopButton->addActionSignal( new StopHandler( (ServerBrowserTablePanel * )_tablePanel ) );
/*
btnx += bw;
_pingButton = new CommandButton( "Test", btnx, by, bw, bh );
_pingButton->setParent( this );
_pingButton->addActionSignal( new PingHandler( (ServerBrowserTablePanel * )_tablePanel ) );
btnx += bw;
_sortButton = new CommandButton( "Sort", btnx, by, bw, bh );
_sortButton->setParent( this );
_sortButton->addActionSignal( new SortHandler( (ServerBrowserTablePanel * )_tablePanel ) );
*/
btnx += bw;
_cancelButton = new CommandButton( "Close", btnx, by, bw, bh );
_cancelButton->setParent( this );
_cancelButton->addActionSignal( new CancelHandler( (ServerBrowserTablePanel * )_tablePanel ) );
setPaintBorderEnabled(false);
setPaintBackgroundEnabled(false);
setPaintEnabled(false);
}
void ServerBrowser::setSize(int wide,int tall)
{
Panel::setSize(wide,tall);
_headerPanel->setBounds(0,0,wide,HEADER_SIZE_Y);
_tablePanel->setBounds(0,HEADER_SIZE_Y,wide,tall - HEADER_SIZE_Y);
_connectButton->setBounds( 5, tall - HEADER_SIZE_Y, 75, 15 );
_refreshButton->setBounds( 85, tall - HEADER_SIZE_Y, 75, 15 );
/*
_broadcastRefreshButton->setBounds( 165, tall - HEADER_SIZE_Y, 75, 15 );
*/
_stopButton->setBounds( 165, tall - HEADER_SIZE_Y, 75, 15 );
/*
_pingButton->setBounds( 325, tall - HEADER_SIZE_Y, 75, 15 );
*/
_cancelButton->setBounds( 245, tall - HEADER_SIZE_Y, 75, 15 );
}
void CBrowser_InputSignal::mousePressed(MouseCode code,Panel* panel)
{
int x, y;
int therow = 2;
if ( code != MOUSE_LEFT )
return;
panel->getApp()->getCursorPos(x,y);
panel->screenToLocal( x, y );
therow = y / CELL_HEIGHT;
// Figure out which row it's on
m_pBrowser->setMouseOverRow( therow );
}
void CBrowser_InputSignal::mouseDoublePressed(MouseCode code,Panel* panel)
{
int x, y;
int therow = 2;
if ( code != MOUSE_LEFT )
return;
panel->getApp()->getCursorPos(x,y);
panel->screenToLocal( x, y );
therow = y / CELL_HEIGHT;
// Figure out which row it's on
m_pBrowser->setMouseOverRow( therow );
m_pBrowser->DoConnect();
}

View File

@ -0,0 +1,44 @@
#ifndef ServerBrowser_H
#define ServerBrowser_H
#include<VGUI_Panel.h>
namespace vgui
{
class Button;
class TablePanel;
class HeaderPanel;
}
class CTransparentPanel;
class CommandButton;
// Scoreboard positions
#define SB_X_INDENT (20 * ((float)ScreenHeight / 640))
#define SB_Y_INDENT (20 * ((float)ScreenHeight / 480))
class ServerBrowser : public CTransparentPanel
{
private:
HeaderPanel * _headerPanel;
TablePanel* _tablePanel;
CommandButton* _connectButton;
CommandButton* _refreshButton;
CommandButton* _broadcastRefreshButton;
CommandButton* _stopButton;
CommandButton* _sortButton;
CommandButton* _cancelButton;
CommandButton* _pingButton;
public:
ServerBrowser(int x,int y,int wide,int tall);
public:
virtual void setSize(int wide,int tall);
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

122
cl_dll/vgui_int.cpp Normal file
View File

@ -0,0 +1,122 @@
#include"vgui_int.h"
#include<VGUI_Label.h>
#include<VGUI_BorderLayout.h>
#include<VGUI_LineBorder.h>
#include<VGUI_SurfaceBase.h>
#include<VGUI_TextEntry.h>
#include<VGUI_ActionSignal.h>
#include<string.h>
#include "hud.h"
#include "cl_util.h"
#include "camera.h"
#include "kbutton.h"
#include "cvardef.h"
#include "usercmd.h"
#include "const.h"
#include "camera.h"
#include "in_defs.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ControlConfigPanel.h"
namespace
{
class TexturePanel : public Panel , public ActionSignal
{
private:
int _bindIndex;
TextEntry* _textEntry;
public:
TexturePanel() : Panel(0,0,256,276)
{
_bindIndex=2700;
_textEntry=new TextEntry("2700",0,0,128,20);
_textEntry->setParent(this);
_textEntry->addActionSignal(this);
}
public:
virtual bool isWithin(int x,int y)
{
return _textEntry->isWithin(x,y);
}
public:
virtual void actionPerformed(Panel* panel)
{
char buf[256];
_textEntry->getText(0,buf,256);
sscanf(buf,"%d",&_bindIndex);
}
protected:
virtual void paintBackground()
{
Panel::paintBackground();
int wide,tall;
getPaintSize(wide,tall);
drawSetColor(0,0,255,0);
drawSetTexture(_bindIndex);
drawTexturedRect(0,19,257,257);
}
};
}
using namespace vgui;
void VGui_ViewportPaintBackground(int extents[4])
{
gEngfuncs.VGui_ViewportPaintBackground(extents);
}
void* VGui_GetPanel()
{
return (Panel*)gEngfuncs.VGui_GetPanel();
}
void VGui_Startup()
{
Panel* root=(Panel*)VGui_GetPanel();
root->setBgColor(128,128,0,0);
//root->setNonPainted(false);
//root->setBorder(new LineBorder());
root->setLayout(new BorderLayout(0));
//root->getSurfaceBase()->setEmulatedCursorVisible(true);
if (gViewPort != NULL)
{
// root->removeChild(gViewPort);
// free the memory
// delete gViewPort;
// gViewPort = NULL;
gViewPort->Initialize();
}
else
{
gViewPort = new TeamFortressViewport(0,0,root->getWide(),root->getTall());
gViewPort->setParent(root);
}
/*
TexturePanel* texturePanel=new TexturePanel();
texturePanel->setParent(gViewPort);
*/
}
void VGui_Shutdown()
{
delete gViewPort;
gViewPort = NULL;
}

15
cl_dll/vgui_int.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef VGUI_INT_H
#define VGUI_INT_H
extern "C"
{
void VGui_Startup();
void VGui_Shutdown();
//Only safe to call from inside subclass of Panel::paintBackground
void VGui_ViewportPaintBackground(int extents[4]);
}
#endif

389
cl_dll/vgui_teammenu.cpp Normal file
View File

@ -0,0 +1,389 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: TFC Team Menu
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "vgui_int.h"
#include "VGUI_Font.h"
#include "VGUI_ScrollPanel.h"
#include "VGUI_TextImage.h"
#include "hud.h"
#include "cl_util.h"
#include "vgui_TeamFortressViewport.h"
// Team Menu Dimensions
#define TEAMMENU_TITLE_X XRES(40)
#define TEAMMENU_TITLE_Y YRES(32)
#define TEAMMENU_TOPLEFT_BUTTON_X XRES(40)
#define TEAMMENU_TOPLEFT_BUTTON_Y YRES(80)
#define TEAMMENU_BUTTON_SIZE_X XRES(124)
#define TEAMMENU_BUTTON_SIZE_Y YRES(24)
#define TEAMMENU_BUTTON_SPACER_Y YRES(8)
#define TEAMMENU_WINDOW_X XRES(176)
#define TEAMMENU_WINDOW_Y YRES(80)
#define TEAMMENU_WINDOW_SIZE_X XRES(424)
#define TEAMMENU_WINDOW_SIZE_Y YRES(312)
#define TEAMMENU_WINDOW_TITLE_X XRES(16)
#define TEAMMENU_WINDOW_TITLE_Y YRES(16)
#define TEAMMENU_WINDOW_TEXT_X XRES(16)
#define TEAMMENU_WINDOW_TEXT_Y YRES(48)
#define TEAMMENU_WINDOW_TEXT_SIZE_Y YRES(178)
#define TEAMMENU_WINDOW_INFO_X XRES(16)
#define TEAMMENU_WINDOW_INFO_Y YRES(234)
// Creation
CTeamMenuPanel::CTeamMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide,int tall) : CMenuPanel(iTrans, iRemoveMe, x,y,wide,tall)
{
// Get the scheme used for the Titles
CSchemeManager *pSchemes = gViewPort->GetSchemeManager();
// schemes
SchemeHandle_t hTitleScheme = pSchemes->getSchemeHandle( "Title Font" );
SchemeHandle_t hTeamWindowText = pSchemes->getSchemeHandle( "Briefing Text" );
SchemeHandle_t hTeamInfoText = pSchemes->getSchemeHandle( "Team Info Text" );
// get the Font used for the Titles
Font *pTitleFont = pSchemes->getFont( hTitleScheme );
int r, g, b, a;
// Create the title
Label *pLabel = new Label( "", TEAMMENU_TITLE_X, TEAMMENU_TITLE_Y );
pLabel->setParent( this );
pLabel->setFont( pTitleFont );
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
pLabel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
pLabel->setBgColor( r, g, b, a );
pLabel->setContentAlignment( vgui::Label::a_west );
pLabel->setText(gHUD.m_TextMessage.BufferedLocaliseTextString("#Title_SelectYourTeam"));
// Create the Info Window
m_pTeamWindow = new CTransparentPanel( 255, TEAMMENU_WINDOW_X, TEAMMENU_WINDOW_Y, TEAMMENU_WINDOW_SIZE_X, TEAMMENU_WINDOW_SIZE_Y );
m_pTeamWindow->setParent( this );
m_pTeamWindow->setBorder( new LineBorder( Color(255*0.7,170*0.7,0,0 )) );
// Create the Map Name Label
m_pMapTitle = new Label( "", TEAMMENU_WINDOW_TITLE_X, TEAMMENU_WINDOW_TITLE_Y );
m_pMapTitle->setFont( pTitleFont );
m_pMapTitle->setParent( m_pTeamWindow );
pSchemes->getFgColor( hTitleScheme, r, g, b, a );
m_pMapTitle->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTitleScheme, r, g, b, a );
m_pMapTitle->setBgColor( r, g, b, a );
m_pMapTitle->setContentAlignment( vgui::Label::a_west );
// Create the Scroll panel
m_pScrollPanel = new CTFScrollPanel( TEAMMENU_WINDOW_TEXT_X, TEAMMENU_WINDOW_TEXT_Y, TEAMMENU_WINDOW_SIZE_X - (TEAMMENU_WINDOW_TEXT_X * 2), TEAMMENU_WINDOW_TEXT_SIZE_Y );
m_pScrollPanel->setParent(m_pTeamWindow);
m_pScrollPanel->setScrollBarVisible(false, false);
// Create the Map Briefing panel
m_pBriefing = new TextPanel("", 0,0, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_TEXT_X, TEAMMENU_WINDOW_TEXT_SIZE_Y );
m_pBriefing->setParent( m_pScrollPanel->getClient() );
m_pBriefing->setFont( pSchemes->getFont(hTeamWindowText) );
pSchemes->getFgColor( hTeamWindowText, r, g, b, a );
m_pBriefing->setFgColor( r, g, b, a );
pSchemes->getBgColor( hTeamWindowText, r, g, b, a );
m_pBriefing->setBgColor( r, g, b, a );
m_pBriefing->setText("Map Description not available.");
// Team Menu buttons
for (int i = 1; i <= 5; i++)
{
char sz[256];
int iYPos = TEAMMENU_TOPLEFT_BUTTON_Y + ( (TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y) * i );
// Team button
m_pButtons[i] = new CommandButton( "", TEAMMENU_TOPLEFT_BUTTON_X, iYPos, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y, true);
m_pButtons[i]->setParent( this );
m_pButtons[i]->setContentAlignment( vgui::Label::a_west );
m_pButtons[i]->setVisible( false );
// AutoAssign button uses special case
if (i == 5)
{
m_pButtons[5]->setBoundKey( '5' );
m_pButtons[5]->setText( gHUD.m_TextMessage.BufferedLocaliseTextString("#Team_AutoAssign") );
m_pButtons[5]->setVisible( true );
}
// Create the Signals
sprintf(sz, "jointeam %d", i);
m_pButtons[i]->addActionSignal( new CMenuHandler_StringCommandWatch( sz, true ) );
m_pButtons[i]->addInputSignal( new CHandler_MenuButtonOver(this, i) );
// Create the Team Info panel
m_pTeamInfoPanel[i] = new TextPanel("", TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_INFO_Y, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_Y );
m_pTeamInfoPanel[i]->setParent( m_pTeamWindow );
m_pTeamInfoPanel[i]->setFont( pSchemes->getFont(hTeamInfoText) );
m_pTeamInfoPanel[i]->setFgColor( iTeamColors[i][0], iTeamColors[i][1], iTeamColors[i][2], 0 );
m_pTeamInfoPanel[i]->setBgColor( 0,0,0, 255 );
}
// Create the Cancel button
m_pCancelButton = new CommandButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Cancel" ), TEAMMENU_TOPLEFT_BUTTON_X, 0, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y);
m_pCancelButton->setParent( this );
m_pCancelButton->addActionSignal( new CMenuHandler_TextWindow(HIDE_TEXTWINDOW) );
// Create the Spectate button
m_pSpectateButton = new SpectateButton( CHudTextMessage::BufferedLocaliseTextString( "#Menu_Spectate" ), TEAMMENU_TOPLEFT_BUTTON_X, 0, TEAMMENU_BUTTON_SIZE_X, TEAMMENU_BUTTON_SIZE_Y, true);
m_pSpectateButton->setParent( this );
m_pSpectateButton->addActionSignal( new CMenuHandler_StringCommand( "spectate", true ) );
m_pSpectateButton->setBoundKey( '6' );
m_pSpectateButton->addInputSignal( new CHandler_MenuButtonOver(this, 6) );
Initialize();
}
//-----------------------------------------------------------------------------
// Purpose: Called each time a new level is started.
//-----------------------------------------------------------------------------
void CTeamMenuPanel::Initialize( void )
{
m_bUpdatedMapName = false;
m_iCurrentInfo = 0;
m_pScrollPanel->setScrollValue( 0, 0 );
}
//-----------------------------------------------------------------------------
// Purpose: Called everytime the Team Menu is displayed
//-----------------------------------------------------------------------------
void CTeamMenuPanel::Update( void )
{
int iYPos = TEAMMENU_TOPLEFT_BUTTON_Y;
// Set the team buttons
for (int i = 1; i <= 4; i++)
{
if (m_pButtons[i])
{
if ( i <= gViewPort->GetNumberOfTeams() )
{
m_pButtons[i]->setText( gViewPort->GetTeamName(i) );
// bound key replacement
char sz[32];
sprintf( sz, "%d", i );
m_pButtons[i]->setBoundKey( sz[0] );
m_pButtons[i]->setVisible( true );
m_pButtons[i]->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
// Start with the first option up
if (!m_iCurrentInfo)
SetActiveInfo( i );
char szPlayerList[ (MAX_PLAYER_NAME_LENGTH + 3) * 31 ]; // name + ", "
strcpy(szPlayerList, "\n");
// Update the Team Info
// Now count the number of teammembers of this class
int iTotal = 0;
for ( int j = 1; j < MAX_PLAYERS; j++ )
{
if ( g_PlayerInfoList[j].name == NULL )
continue; // empty player slot, skip
if ( g_PlayerInfoList[j].thisplayer )
continue; // skip this player
if ( g_PlayerExtraInfo[j].teamnumber != i )
continue; // skip over players in other teams
iTotal++;
if (iTotal > 1)
strncat( szPlayerList, ", ", sizeof(szPlayerList) - strlen(szPlayerList) );
strncat( szPlayerList, g_PlayerInfoList[j].name, sizeof(szPlayerList) - strlen(szPlayerList) );
szPlayerList[ sizeof(szPlayerList) - 1 ] = '\0';
}
if (iTotal > 0)
{
// Set the text of the info Panel
char szText[ ((MAX_PLAYER_NAME_LENGTH + 3) * 31) + 256 ];
if (iTotal == 1)
sprintf(szText, "%s: %d Player (%d points)", gViewPort->GetTeamName(i), iTotal, g_TeamInfo[i].frags );
else
sprintf(szText, "%s: %d Players (%d points)", gViewPort->GetTeamName(i), iTotal, g_TeamInfo[i].frags );
strncat( szText, szPlayerList, sizeof(szText) - strlen(szText) );
szText[ sizeof(szText) - 1 ] = '\0';
m_pTeamInfoPanel[i]->setText( szText );
}
else
{
m_pTeamInfoPanel[i]->setText( "" );
}
}
else
{
// Hide the button (may be visible from previous maps)
m_pButtons[i]->setVisible( false );
}
}
}
// Move the AutoAssign button into place
m_pButtons[5]->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
// Spectate button
if (m_pSpectateButton->IsNotValid())
{
m_pSpectateButton->setVisible( false );
}
else
{
m_pSpectateButton->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
m_pSpectateButton->setVisible( true );
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
}
// If the player is already in a team, make the cancel button visible
if ( g_iTeamNumber )
{
m_pCancelButton->setPos( TEAMMENU_TOPLEFT_BUTTON_X, iYPos );
iYPos += TEAMMENU_BUTTON_SIZE_Y + TEAMMENU_BUTTON_SPACER_Y;
m_pCancelButton->setVisible( true );
}
else
{
m_pCancelButton->setVisible( false );
}
// Set the Map Title
if (!m_bUpdatedMapName)
{
const char *level = gEngfuncs.pfnGetLevelName();
if (level && level[0])
{
char sz[256];
char szTitle[256];
char *ch;
// Update the level name
strcpy( sz, level );
ch = strchr( sz, '/' );
if (!ch)
ch = strchr( sz, '\\' );
strcpy( szTitle, ch+1 );
ch = strchr( szTitle, '.' );
*ch = '\0';
m_pMapTitle->setText( szTitle );
*ch = '.';
// Update the map briefing
strcpy( sz, level );
ch = strchr( sz, '.' );
*ch = '\0';
strcat( sz, ".txt" );
char *pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL );
if (pfile)
{
m_pBriefing->setText( pfile );
// Get the total size of the Briefing text and resize the text panel
int iXSize, iYSize;
m_pBriefing->getTextImage()->getTextSize( iXSize, iYSize );
m_pBriefing->setSize( iXSize, iYSize );
}
m_bUpdatedMapName = true;
}
}
m_pScrollPanel->validate();
}
//=====================================
// Key inputs
bool CTeamMenuPanel::SlotInput( int iSlot )
{
// Check for AutoAssign
if ( iSlot == 5)
{
m_pButtons[5]->fireActionSignal();
return true;
}
// Spectate
if ( iSlot == 6)
{
m_pSpectateButton->fireActionSignal();
return true;
}
// Otherwise, see if a particular team is selectable
if ( (iSlot < 1) || (iSlot > gViewPort->GetNumberOfTeams()) )
return false;
if ( !m_pButtons[ iSlot ] )
return false;
// Is the button pushable?
if ( m_pButtons[ iSlot ]->isVisible() )
{
m_pButtons[ iSlot ]->fireActionSignal();
return true;
}
return false;
}
//======================================
// Update the Team menu before opening it
void CTeamMenuPanel::Open( void )
{
Update();
CMenuPanel::Open();
}
void CTeamMenuPanel::paintBackground()
{
// make sure we get the map briefing up
if ( !m_bUpdatedMapName )
Update();
CMenuPanel::paintBackground();
}
//======================================
// Mouse is over a team button, bring up the class info
void CTeamMenuPanel::SetActiveInfo( int iInput )
{
// Remove all the Info panels and bring up the specified one
m_pSpectateButton->setArmed( false );
for (int i = 1; i <= 5; i++)
{
m_pButtons[i]->setArmed( false );
m_pTeamInfoPanel[i]->setVisible( false );
}
// 6 is Spectate
if (iInput == 6)
{
m_pSpectateButton->setArmed( true );
}
else
{
m_pButtons[iInput]->setArmed( true );
m_pTeamInfoPanel[iInput]->setVisible( true );
}
m_iCurrentInfo = iInput;
m_pScrollPanel->validate();
}

1023
cl_dll/view.cpp Normal file

File diff suppressed because it is too large Load Diff

8
cl_dll/view.h Normal file
View File

@ -0,0 +1,8 @@
#if !defined ( VIEWH )
#define VIEWH
#pragma once
void V_StartPitchDrift( void );
void V_StopPitchDrift( void );
#endif // !VIEWH

9
cl_dll/wrect.h Normal file
View File

@ -0,0 +1,9 @@
#if !defined( WRECTH )
#define WRECTH
typedef struct rect_s
{
int left, right, top, bottom;
} wrect_t;
#endif

62
common/beamdef.h Normal file
View File

@ -0,0 +1,62 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined ( BEAMDEFH )
#define BEAMDEFH
#ifdef _WIN32
#pragma once
#endif
#define FBEAM_STARTENTITY 0x00000001
#define FBEAM_ENDENTITY 0x00000002
#define FBEAM_FADEIN 0x00000004
#define FBEAM_FADEOUT 0x00000008
#define FBEAM_SINENOISE 0x00000010
#define FBEAM_SOLID 0x00000020
#define FBEAM_SHADEIN 0x00000040
#define FBEAM_SHADEOUT 0x00000080
#define FBEAM_STARTVISIBLE 0x10000000 // Has this client actually seen this beam's start entity yet?
#define FBEAM_ENDVISIBLE 0x20000000 // Has this client actually seen this beam's end entity yet?
#define FBEAM_ISACTIVE 0x40000000
#define FBEAM_FOREVER 0x80000000
typedef struct beam_s BEAM;
struct beam_s
{
BEAM *next;
int type;
int flags;
vec3_t source;
vec3_t target;
vec3_t delta;
float t; // 0 .. 1 over lifetime of beam
float freq;
float die;
float width;
float amplitude;
float r, g, b;
float brightness;
float speed;
float frameRate;
float frame;
int segments;
int startEntity;
int endEntity;
int modelIndex;
int frameCount;
struct model_s *pFollowModel;
struct particle_s *particles;
};
#endif

115
common/cl_entity.h Normal file
View File

@ -0,0 +1,115 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
// cl_entity.h
#if !defined( CL_ENTITYH )
#define CL_ENTITYH
#ifdef _WIN32
#pragma once
#endif
typedef struct efrag_s
{
struct mleaf_s *leaf;
struct efrag_s *leafnext;
struct cl_entity_s *entity;
struct efrag_s *entnext;
} efrag_t;
typedef struct
{
byte mouthopen; // 0 = mouth closed, 255 = mouth agape
byte sndcount; // counter for running average
int sndavg; // running average
} mouth_t;
typedef struct
{
float prevanimtime;
float sequencetime;
byte prevseqblending[2];
vec3_t prevorigin;
vec3_t prevangles;
int prevsequence;
float prevframe;
byte prevcontroller[4];
byte prevblending[2];
} latchedvars_t;
typedef struct
{
// Time stamp for this movement
float animtime;
vec3_t origin;
vec3_t angles;
} position_history_t;
typedef struct cl_entity_s cl_entity_t;
#define HISTORY_MAX 64 // Must be power of 2
#define HISTORY_MASK ( HISTORY_MAX - 1 )
#if !defined( ENTITY_STATEH )
#include "entity_state.h"
#endif
#if !defined( PROGS_H )
#include "progs.h"
#endif
struct cl_entity_s
{
int index; // Index into cl_entities ( should match actual slot, but not necessarily )
qboolean player; // True if this entity is a "player"
entity_state_t baseline; // The original state from which to delta during an uncompressed message
entity_state_t prevstate; // The state information from the penultimate message received from the server
entity_state_t curstate; // The state information from the last message received from server
int current_position; // Last received history update index
position_history_t ph[ HISTORY_MAX ]; // History of position and angle updates for this player
mouth_t mouth; // For synchronizing mouth movements.
latchedvars_t latched; // Variables used by studio model rendering routines
// Information based on interplocation, extrapolation, prediction, or just copied from last msg received.
//
float lastmove;
// Actual render position and angles
vec3_t origin;
vec3_t angles;
// Attachment points
vec3_t attachment[4];
// Other entity local information
int trivial_accept;
struct model_s *model; // cl.model_precache[ curstate.modelindes ]; all visible entities have a model
struct efrag_s *efrag; // linked list of efrags
struct mnode_s *topnode; // for bmodels, first world node that splits bmodel, or NULL if not split
float syncbase; // for client-side animations -- used by obsolete alias animation system, remove?
int visframe; // last frame this entity was found in an active leaf
colorVec cvFloorColor;
};
#endif // !CL_ENTITYH

31
common/con_nprint.h Normal file
View File

@ -0,0 +1,31 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined( CON_NPRINTH )
#define CON_NPRINTH
#ifdef _WIN32
#pragma once
#endif
typedef struct con_nprint_s
{
int index; // Row #
float time_to_live; // # of seconds before it dissappears
float color[ 3 ]; // RGB colors ( 0.0 -> 1.0 scale )
} con_nprint_t;
void Con_NPrintf( int idx, char *fmt, ... );
void Con_NXPrintf( struct con_nprint_s *info, char *fmt, ... );
#endif

View File

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, Valve LLC. All rights reserved.
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
@ -28,7 +28,7 @@
#define FL_MONSTER (1<<5)
#define FL_GODMODE (1<<6)
#define FL_NOTARGET (1<<7)
//#define FL_ITEM (1<<8) // NOT USED
#define FL_SKIPLOCALHOST (1<<8) // Don't send entity to local host, it's predicting this entity itself
#define FL_ONGROUND (1<<9) // At rest / on the ground
#define FL_PARTIALGROUND (1<<10) // not all corners are valid
#define FL_WATERJUMP (1<<11) // player jumping out of water
@ -109,6 +109,9 @@
#define EF_NOINTERP 32 // don't interpolate the next frame
#define EF_LIGHT 64 // rocket flare glow sprite
#define EF_NODRAW 128 // don't draw entity
// entity flags
#define EFLAG_SLERP 1 // do studio interpolation of this entity
//
// temp entity events
@ -176,6 +179,7 @@
// byte (life in 0.1's)
// byte (width in 0.1's)
// byte (amplitude in 0.01's)
// short (sprite model index)
#define TE_BEAMENTS 8
// short (start entity)
@ -546,15 +550,15 @@
// byte ( color ) this is an index into an array of color vectors in the engine. (0 - )
// byte ( length * 10 )
#define MSG_BROADCAST 0 // unreliable to all
#define MSG_ONE 1 // reliable to one (msg_entity)
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
#define MSG_PVS 4 // Ents in PVS of org
#define MSG_PAS 5 // Ents in PAS of org
#define MSG_PVS_R 6 // Reliable to PVS
#define MSG_PAS_R 7 // Reliable to PAS
#define MSG_BROADCAST 0 // unreliable to all
#define MSG_ONE 1 // reliable to one (msg_entity)
#define MSG_ALL 2 // reliable to all
#define MSG_INIT 3 // write to the init string
#define MSG_PVS 4 // Ents in PVS of org
#define MSG_PAS 5 // Ents in PAS of org
#define MSG_PVS_R 6 // Reliable to PVS
#define MSG_PAS_R 7 // Reliable to PAS
#define MSG_ONE_UNRELIABLE 8 // Send to one client, but don't put in reliable stream, put in unreliable datagram ( could be dropped )
// contents of a spot in the world
#define CONTENTS_EMPTY -1
@ -616,22 +620,9 @@
#define SF_TRAIN_PASSABLE 8 // Train is not solid -- used to make water trains
// buttons
#define IN_ATTACK (1 << 0)
#define IN_JUMP (1 << 1)
#define IN_DUCK (1 << 2)
#define IN_FORWARD (1 << 3)
#define IN_BACK (1 << 4)
#define IN_USE (1 << 5)
#define IN_CANCEL (1 << 6)
#define IN_LEFT (1 << 7)
#define IN_RIGHT (1 << 8)
#define IN_MOVELEFT (1 << 9)
#define IN_MOVERIGHT (1 << 10)
#define IN_ATTACK2 (1 << 11)
#define IN_RUN (1 << 12)
#define IN_RELOAD (1 << 13)
#define IN_ALT1 (1 << 14)
#define IN_ALT2 (1 << 15)
#ifndef IN_BUTTONS_H
#include "in_buttons.h"
#endif
// Break Model Defines
@ -725,13 +716,18 @@ typedef struct
unsigned r, g, b, a;
} colorVec;
#ifdef _WIN32
#pragma pack(push,2)
#endif
typedef struct
{
unsigned short r, g, b, a;
} PackedColorVec;
#pragma pack(pop)
#ifdef _WIN32
#pragma pack(pop)
#endif
typedef struct link_s
{
struct link_s *prev, *next;

51
common/crc.h Normal file
View File

@ -0,0 +1,51 @@
/***
*
* Copyright (c) 1999, 2000, 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.
*
****/
/* crc.h */
#ifndef CRC_H
#define CRC_H
#ifdef _WIN32
#pragma once
#endif
// MD5 Hash
typedef struct
{
unsigned int buf[4];
unsigned int bits[2];
unsigned char in[64];
} MD5Context_t;
typedef unsigned long CRC32_t;
void CRC32_Init(CRC32_t *pulCRC);
CRC32_t CRC32_Final(CRC32_t pulCRC);
void CRC32_ProcessBuffer(CRC32_t *pulCRC, void *p, int len);
void CRC32_ProcessByte(CRC32_t *pulCRC, unsigned char ch);
int CRC_File(CRC32_t *crcvalue, char *pszFileName);
unsigned char COM_BlockSequenceCRCByte(unsigned char *base, int length, int sequence);
void MD5Init(MD5Context_t *context);
void MD5Update(MD5Context_t *context, unsigned char const *buf,
unsigned int len);
void MD5Final(unsigned char digest[16], MD5Context_t *context);
void Transform(unsigned int buf[4], unsigned int const in[16]);
int MD5_Hash_File(unsigned char digest[16], char *pszFileName, int bUsefopen, int bSeed, unsigned int seed[4]);
char *MD5_Print(unsigned char hash[16]);
int MD5_Hash_CachedFile(unsigned char digest[16], unsigned char *pCache, int nFileSize, int bSeed, unsigned int seed[4]);
int CRC_MapFile(CRC32_t *crcvalue, char *pszFileName);
#endif

36
common/cvardef.h Normal file
View File

@ -0,0 +1,36 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#ifndef CVARDEF_H
#define CVARDEF_H
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc
#define FCVAR_USERINFO (1<<1) // changes the client's info string
#define FCVAR_SERVER (1<<2) // notifies players when changed
#define FCVAR_EXTDLL (1<<3) // defined by external DLL
#define FCVAR_CLIENTDLL (1<<4) // defined by the client dll
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
typedef struct cvar_s
{
char *name;
char *string;
int flags;
float value;
struct cvar_s *next;
} cvar_t;
#endif

31
common/demo_api.h Normal file
View File

@ -0,0 +1,31 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined ( DEMO_APIH )
#define DEMO_APIH
#ifdef _WIN32
#pragma once
#endif
typedef struct demo_api_s
{
int ( *IsRecording ) ( void );
int ( *IsPlayingback ) ( void );
int ( *IsTimeDemo ) ( void );
void ( *WriteBuffer ) ( int size, unsigned char *buffer );
} demo_api_t;
extern demo_api_t demoapi;
#endif

33
common/dlight.h Normal file
View File

@ -0,0 +1,33 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined ( DLIGHTH )
#define DLIGHTH
#ifdef _WIN32
#pragma once
#endif
typedef struct
{
vec3_t origin;
float radius;
color24 color;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
int key;
qboolean dark; // subtracts light instead of adding
} dlight_t;
#endif

15
common/dll_state.h Normal file
View File

@ -0,0 +1,15 @@
//DLL State Flags
#define DLL_INACTIVE 0 // no dll
#define DLL_ACTIVE 1 // dll is running
#define DLL_PAUSED 2 // dll is paused
#define DLL_CLOSE 3 // closing down dll
#define DLL_TRANS 4 // Level Transition
// DLL Pause reasons
#define DLL_NORMAL 0 // User hit Esc or something.
#define DLL_QUIT 4 // Quit now
// DLL Substate info ( not relevant )
#define ENG_NORMAL (1<<0)

View File

@ -0,0 +1,101 @@
// engine/launcher interface
#if !defined( ENGINE_LAUNCHER_APIH )
#define ENGINE_LAUNCHER_APIH
#ifdef _WIN32
#pragma once
#endif
//typedef void ( *xcommand_t ) ( void );
#define RENDERTYPE_UNDEFINED 0
#define RENDERTYPE_SOFTWARE 1
#define RENDERTYPE_HARDWARE 2
#define ENGINE_LAUNCHER_API_VERSION 1
typedef struct engine_api_s
{
int version;
int rendertype;
int size;
// Functions
int ( *GetEngineState ) ( void );
void ( *Cbuf_AddText ) ( char *text ); // append cmd at end of buf
void ( *Cbuf_InsertText ) ( char *text ); // insert cmd at start of buf
void ( *Cmd_AddCommand ) ( char *cmd_name, void ( *funcname )( void ) );
int ( *Cmd_Argc ) ( void );
char *( *Cmd_Args ) ( void );
char *( *Cmd_Argv ) ( int arg );
void ( *Con_Printf ) ( char *, ... );
void ( *Con_SafePrintf ) ( char *, ... );
void ( *Cvar_Set ) ( char *var_name, char *value );
void ( *Cvar_SetValue ) ( char *var_name, float value );
int ( *Cvar_VariableInt ) ( char *var_name );
char *( *Cvar_VariableString ) ( char *var_name );
float ( *Cvar_VariableValue ) ( char *var_name );
void ( *ForceReloadProfile ) ( void );
int ( *GetGameInfo ) ( struct GameInfo_s *pGI, char *pszChannel );
void ( *GameSetBackground ) ( int bBack );
void ( *GameSetState ) ( int iState );
void ( *GameSetSubState ) ( int iState );
int ( *GetPauseState ) ( void );
int ( *Host_Frame ) ( float time, int iState, int *stateInfo );
void ( *Host_GetHostInfo ) ( float *fps, int *nActive, int *nSpectators, int *nMaxPlayers, char *pszMap );
void ( *Host_Shutdown ) ( void );
int ( *Game_Init ) ( char *lpCmdLine, unsigned char *pMem, int iSize, struct exefuncs_s *pef, void *, int );
void ( *IN_ActivateMouse ) ( void );
void ( *IN_ClearStates ) ( void );
void ( *IN_DeactivateMouse ) ( void );
void ( *IN_MouseEvent ) ( int mstate );
void ( *Keyboard_ReturnToGame ) ( void );
void ( *Key_ClearStates ) ( void );
void ( *Key_Event ) ( int key, int down );
int ( *LoadGame ) ( const char *pszSlot );
void ( *S_BlockSound ) ( void );
void ( *S_ClearBuffer ) ( void );
void ( *S_GetDSPointer ) ( struct IDirectSound **lpDS, struct IDirectSoundBuffer **lpDSBuf );
void *( *S_GetWAVPointer ) ( void );
void ( *S_UnblockSound ) ( void );
int ( *SaveGame ) ( const char *pszSlot, const char *pszComment );
void ( *SetAuth ) ( void *pobj );
void ( *SetMessagePumpDisableMode ) ( int bMode );
void ( *SetPauseState ) ( int bPause );
void ( *SetStartupMode ) ( int bMode );
void ( *SNDDMA_Shutdown ) ( void );
void ( *Snd_AcquireBuffer ) ( void );
void ( *Snd_ReleaseBuffer ) ( void );
void ( *StoreProfile ) ( void );
double ( *Sys_FloatTime ) ( void );
void ( *VID_UpdateWindowVars ) ( void *prc, int x, int y );
void ( *VID_UpdateVID ) ( struct viddef_s *pvid );
// VGUI interfaces
void ( *VGui_CallEngineSurfaceProc ) ( void* hwnd, unsigned int msg, unsigned int wparam, long lparam );
// notifications that the launcher is taking/giving focus to the engine
void ( *EngineTakingFocus ) ( void );
void ( *LauncherTakingFocus ) ( void );
#ifdef _WIN32
// Only filled in by rendertype RENDERTYPE_HARDWARE
void ( *GL_Init ) ( void );
int ( *GL_SetMode ) ( HWND hwndGame, HDC *pmaindc, HGLRC *pbaseRC, int fD3D, const char *p, const char *pszCmdLine );
void ( *GL_Shutdown ) ( HWND hwnd, HDC hdc, HGLRC hglrc );
void ( *QGL_D3DShared ) ( struct tagD3DGlobals *d3dGShared );
int ( WINAPI *glSwapBuffers ) ( HDC dc );
#else
// NOT USED IN LINUX!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void ( *GL_Init ) ( void );
void ( *GL_SetMode ) ( void );
void ( *GL_Shutdown ) ( void );
void ( *QGL_D3DShared ) ( void );
void ( *glSwapBuffers ) ( void );
// LINUX
#endif
} engine_api_t;
#endif // ENGINE_LAUNCHER_APIH

193
common/entity_state.h Normal file
View File

@ -0,0 +1,193 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined( ENTITY_STATEH )
#define ENTITY_STATEH
#ifdef _WIN32
#pragma once
#endif
// For entityType below
#define ENTITY_NORMAL (1<<0)
#define ENTITY_BEAM (1<<1)
// Entity state is used for the baseline and for delta compression of a packet of
// entities that is sent to a client.
typedef struct entity_state_s entity_state_t;
struct entity_state_s
{
// Fields which are filled in by routines outside of delta compression
int entityType;
// Index into cl_entities array for this entity.
int number;
float msg_time;
// Message number last time the player/entity state was updated.
int messagenum;
// Fields which can be transitted and reconstructed over the network stream
vec3_t origin;
vec3_t angles;
int modelindex;
int sequence;
float frame;
int colormap;
short skin;
short solid;
int effects;
float scale;
byte eflags;
// Render information
int rendermode;
int renderamt;
color24 rendercolor;
int renderfx;
int movetype;
float animtime;
float framerate;
int body;
byte controller[4];
byte blending[4];
vec3_t velocity;
// Send bbox down to client for use during prediction.
vec3_t mins;
vec3_t maxs;
int aiment;
// If owned by a player, the index of that player ( for projectiles ).
int owner;
// Friction, for prediction.
float friction;
// Gravity multiplier
float gravity;
// PLAYER SPECIFIC
int team;
int playerclass;
int health;
qboolean spectator;
int weaponmodel;
int gaitsequence;
// If standing on conveyor, e.g.
vec3_t basevelocity;
// Use the crouched hull, or the regular player hull.
int usehull;
// Latched buttons last time state updated.
int oldbuttons;
// -1 = in air, else pmove entity number
int onground;
int iStepLeft;
// How fast we are falling
float flFallVelocity;
float fov;
int weaponanim;
// Parametric movement overrides
vec3_t startpos;
vec3_t endpos;
float impacttime;
float starttime;
// For mods
int iuser1;
int iuser2;
int iuser3;
int iuser4;
float fuser1;
float fuser2;
float fuser3;
float fuser4;
vec3_t vuser1;
vec3_t vuser2;
vec3_t vuser3;
vec3_t vuser4;
};
#include "pm_info.h"
typedef struct clientdata_s
{
vec3_t origin;
vec3_t velocity;
int viewmodel;
vec3_t punchangle;
int flags;
int waterlevel;
int watertype;
vec3_t view_ofs;
float health;
int bInDuck;
int weapons; // remove?
int flTimeStepSound;
int flDuckTime;
int flSwimTime;
int waterjumptime;
float maxspeed;
float fov;
int weaponanim;
int m_iId;
int ammo_shells;
int ammo_nails;
int ammo_cells;
int ammo_rockets;
float m_flNextAttack;
int tfstate;
int pushmsec;
int deadflag;
char physinfo[ MAX_PHYSINFO_STRING ];
// For mods
int iuser1;
int iuser2;
int iuser3;
int iuser4;
float fuser1;
float fuser2;
float fuser3;
float fuser4;
vec3_t vuser1;
vec3_t vuser2;
vec3_t vuser3;
vec3_t vuser4;
} clientdata_t;
#include "weaponinfo.h"
typedef struct local_state_s
{
entity_state_t playerstate;
clientdata_t client;
weapon_data_t weapondata[ 32 ];
} local_state_t;
#endif // !ENTITY_STATEH

26
common/entity_types.h Normal file
View File

@ -0,0 +1,26 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
// entity_types.h
#if !defined( ENTITY_TYPESH )
#define ENTITY_TYPESH
#define ET_NORMAL 0
#define ET_PLAYER 1
#define ET_TEMPENTITY 2
#define ET_BEAM 3
// BMODEL or SPRITE that was split across BSP nodes
#define ET_FRAGMENTED 4
#endif // !ENTITY_TYPESH

51
common/event_api.h Normal file
View File

@ -0,0 +1,51 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined ( EVENT_APIH )
#define EVENT_APIH
#ifdef _WIN32
#pragma once
#endif
#define EVENT_API_VERSION 1
typedef struct event_api_s
{
int version;
void ( *EV_PlaySound ) ( int ent, float *origin, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch );
void ( *EV_StopSound ) ( int ent, int channel, const char *sample );
int ( *EV_FindModelIndex )( const char *pmodel );
int ( *EV_IsLocal ) ( int playernum );
int ( *EV_LocalPlayerDucking ) ( void );
void ( *EV_LocalPlayerViewheight ) ( float * );
void ( *EV_LocalPlayerBounds ) ( int hull, float *mins, float *maxs );
int ( *EV_IndexFromTrace) ( struct pmtrace_s *pTrace );
struct physent_s *( *EV_GetPhysent ) ( int idx );
void ( *EV_SetUpPlayerPrediction ) ( int dopred, int bIncludeLocalClient );
void ( *EV_PushPMStates ) ( void );
void ( *EV_PopPMStates ) ( void );
void ( *EV_SetSolidPlayers ) (int playernum);
void ( *EV_SetTraceHull ) ( int hull );
void ( *EV_PlayerTrace ) ( float *start, float *end, int traceFlags, int ignore_pe, struct pmtrace_s *tr );
void ( *EV_WeaponAnimation ) ( int sequence, int body );
unsigned short ( *EV_PrecacheEvent ) ( int type, const char* psz );
void ( *EV_PlaybackEvent ) ( int flags, const struct edict_s *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
const char *( *EV_TraceTexture ) ( int ground, float *vstart, float *vend );
void ( *EV_StopAllSounds ) ( int entnum, int entchannel );
void ( *EV_KillEvents ) ( int entnum, const char *eventname );
} event_api_t;
extern event_api_t eventapi;
#endif

51
common/event_args.h Normal file
View File

@ -0,0 +1,51 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined( EVENT_ARGSH )
#define EVENT_ARGSH
#ifdef _WIN32
#pragma once
#endif
// Event was invoked with stated origin
#define FEVENT_ORIGIN ( 1<<0 )
// Event was invoked with stated angles
#define FEVENT_ANGLES ( 1<<1 )
typedef struct event_args_s
{
int flags;
// Transmitted
int entindex;
float origin[3];
float angles[3];
float velocity[3];
int ducking;
float fparam1;
float fparam2;
int iparam1;
int iparam2;
int bparam1;
int bparam2;
} event_args_t;
#endif

47
common/event_flags.h Normal file
View File

@ -0,0 +1,47 @@
/***
*
* Copyright (c) 1999, 2000, 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.
*
****/
#if !defined( EVENT_FLAGSH )
#define EVENT_FLAGSH
#ifdef _WIN32
#pragma once
#endif
// Skip local host for event send.
#define FEV_NOTHOST (1<<0)
// Send the event reliably. You must specify the origin and angles and use
// PLAYBACK_EVENT_FULL for this to work correctly on the server for anything
// that depends on the event origin/angles. I.e., the origin/angles are not
// taken from the invoking edict for reliable events.
#define FEV_RELIABLE (1<<1)
// Don't restrict to PAS/PVS, send this event to _everybody_ on the server ( useful for stopping CHAN_STATIC
// sounds started by client event when client is not in PVS anymore ( hwguy in TFC e.g. ).
#define FEV_GLOBAL (1<<2)
// If this client already has one of these events in its queue, just update the event instead of sending it as a duplicate
//
#define FEV_UPDATE (1<<3)
// Only send to entity specified as the invoker
#define FEV_HOSTONLY (1<<4)
// Only send if the event was created on the server.
#define FEV_SERVER (1<<5)
// Only issue event client side ( from shared code )
#define FEV_CLIENT (1<<6)
#endif

41
common/exefuncs.h Normal file
View File

@ -0,0 +1,41 @@
// exefuncs.h
#ifndef EXEFUNCS_H
#define EXEFUNCS_H
// Engine hands this to DLLs for functionality callbacks
typedef struct exefuncs_s
{
int fMMX;
int iCPUMhz;
void (*unused1)(void);
void (*unused2)(void);
void (*unused3)(void);
void (*unused4)(void);
void (*VID_ForceLockState)(int lk);
int (*VID_ForceUnlockedAndReturnState)(void);
void (*unused5)(void);
void (*unused6)(void);
void (*unused7)(void);
void (*unused8)(void);
void (*unused9)(void);
void (*unused10)(void);
void (*unused11)(void);
void (*unused12)(void);
void (*unused13)(void);
void (*unused14)(void);
void (*unused15)(void);
void (*ErrorMessage)(int nLevel, const char *pszErrorMessage);
void (*unused16)(void);
void (*Sys_Printf)(char *fmt, ...);
void (*unused17)(void);
void (*unused18)(void);
void (*unused19)(void);
void (*unused20)(void);
void (*unused21)(void);
void (*unused22)(void);
void (*unused23)(void);
void (*unused24)(void);
void (*unused25)(void);
} exefuncs_t;
#endif

38
common/in_buttons.h Normal file
View File

@ -0,0 +1,38 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#ifndef IN_BUTTONS_H
#define IN_BUTTONS_H
#ifdef _WIN32
#pragma once
#endif
#define IN_ATTACK (1 << 0)
#define IN_JUMP (1 << 1)
#define IN_DUCK (1 << 2)
#define IN_FORWARD (1 << 3)
#define IN_BACK (1 << 4)
#define IN_USE (1 << 5)
#define IN_CANCEL (1 << 6)
#define IN_LEFT (1 << 7)
#define IN_RIGHT (1 << 8)
#define IN_MOVELEFT (1 << 9)
#define IN_MOVERIGHT (1 << 10)
#define IN_ATTACK2 (1 << 11)
#define IN_RUN (1 << 12)
#define IN_RELOAD (1 << 13)
#define IN_ALT1 (1 << 14)
#define IN_SCORE (1 << 15) // Used by client.dll for when scoreboard is held down
#endif // IN_BUTTONS_H

146
common/mathlib.h Normal file
View File

@ -0,0 +1,146 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
// mathlib.h
typedef float vec_t;
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4]; // x,y,z,w
typedef vec_t vec5_t[5];
typedef short vec_s_t;
typedef vec_s_t vec3s_t[3];
typedef vec_s_t vec4s_t[4]; // x,y,z,w
typedef vec_s_t vec5s_t[5];
typedef int fixed4_t;
typedef int fixed8_t;
typedef int fixed16_t;
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
struct mplane_s;
extern vec3_t vec3_origin;
extern int nanmask;
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
#define VectorClear(a) {(a)[0]=0.0;(a)[1]=0.0;(a)[2]=0.0;}
void VectorMA (const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc);
vec_t _DotProduct (vec3_t v1, vec3_t v2);
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out);
void _VectorCopy (vec3_t in, vec3_t out);
int VectorCompare (const vec3_t v1, const vec3_t v2);
float Length (const vec3_t v);
void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross);
float VectorNormalize (vec3_t v); // returns vector length
void VectorInverse (vec3_t v);
void VectorScale (const vec3_t in, vec_t scale, vec3_t out);
int Q_log2(int val);
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
// Here are some "manual" INLINE routines for doing floating point to integer conversions
extern short new_cw, old_cw;
typedef union DLONG {
int i[2];
double d;
float f;
} DLONG;
extern DLONG dlong;
#ifdef _WIN32
void __inline set_fpu_cw(void)
{
_asm
{ wait
fnstcw old_cw
wait
mov ax, word ptr old_cw
or ah, 0xc
mov word ptr new_cw,ax
fldcw new_cw
}
}
int __inline quick_ftol(float f)
{
_asm {
// Assumes that we are already in chop mode, and only need a 32-bit int
fld DWORD PTR f
fistp DWORD PTR dlong
}
return dlong.i[0];
}
void __inline restore_fpu_cw(void)
{
_asm fldcw old_cw
}
#else
#define set_fpu_cw() /* */
#define quick_ftol(f) ftol(f)
#define restore_fpu_cw() /* */
#endif
void FloorDivMod (double numer, double denom, int *quotient,
int *rem);
fixed16_t Invert24To16(fixed16_t val);
int GreatestCommonDivisor (int i1, int i2);
void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
void AngleVectorsTranspose (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
#define AngleIVectors AngleVectorsTranspose
void AngleMatrix (const vec3_t angles, float (*matrix)[4] );
void AngleIMatrix (const vec3_t angles, float (*matrix)[4] );
void VectorTransform (const vec3_t in1, float in2[3][4], vec3_t out);
void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up);
void VectorAngles( const vec3_t forward, vec3_t angles );
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane);
float anglemod(float a);
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
(((p)->type < 3)? \
( \
((p)->dist <= (emins)[(p)->type])? \
1 \
: \
( \
((p)->dist >= (emaxs)[(p)->type])?\
2 \
: \
3 \
) \
) \
: \
BoxOnPlaneSide( (emins), (emaxs), (p)))

92
common/net_api.h Normal file
View File

@ -0,0 +1,92 @@
#if !defined( NET_APIH )
#define NET_APIH
#ifdef _WIN32
#pragma once
#endif
#if !defined ( NETADRH )
#include "netadr.h"
#endif
#define NETAPI_REQUEST_SERVERLIST ( 0 ) // Doesn't need a remote address
#define NETAPI_REQUEST_PING ( 1 )
#define NETAPI_REQUEST_RULES ( 2 )
#define NETAPI_REQUEST_PLAYERS ( 3 )
#define NETAPI_REQUEST_DETAILS ( 4 )
// Set this flag for things like broadcast requests, etc. where the engine should not
// kill the request hook after receiving the first response
#define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 )
typedef void ( *net_api_response_func_t ) ( struct net_response_s *response );
#define NET_SUCCESS ( 0 )
#define NET_ERROR_TIMEOUT ( 1<<0 )
#define NET_ERROR_PROTO_UNSUPPORTED ( 1<<1 )
#define NET_ERROR_UNDEFINED ( 1<<2 )
typedef struct net_adrlist_s
{
struct net_adrlist_s *next;
netadr_t remote_address;
} net_adrlist_t;
typedef struct net_response_s
{
// NET_SUCCESS or an error code
int error;
// Context ID
int context;
// Type
int type;
// Server that is responding to the request
netadr_t remote_address;
// Response RTT ping time
double ping;
// Key/Value pair string ( separated by backlash \ characters )
// WARNING: You must copy this buffer in the callback function, because it is freed
// by the engine right after the call!!!!
// ALSO: For NETAPI_REQUEST_SERVERLIST requests, this will be a pointer to a linked list of net_adrlist_t's
void *response;
} net_response_t;
typedef struct net_status_s
{
// Connected to remote server? 1 == yes, 0 otherwise
int connected;
// Client's IP address
netadr_t local_address;
// Address of remote server
netadr_t remote_address;
// Packet Loss ( as a percentage )
int packet_loss;
// Latency, in seconds ( multiply by 1000.0 to get milliseconds )
double latency;
// Connection time, in seconds
double connection_time;
// Rate setting ( for incoming data )
double rate;
} net_status_t;
typedef struct net_api_s
{
// APIs
void ( *InitNetworking )( void );
void ( *Status ) ( struct net_status_s *status );
void ( *SendRequest) ( int context, int request, int flags, double timeout, struct netadr_s *remote_address, net_api_response_func_t response );
void ( *CancelRequest ) ( int context );
void ( *CancelAllRequests ) ( void );
char *( *AdrToString ) ( struct netadr_s *a );
int ( *CompareAdr ) ( struct netadr_s *a, struct netadr_s *b );
int ( *StringToAdr ) ( char *s, struct netadr_s *a );
const char *( *ValueForKey ) ( const char *s, const char *key );
void ( *RemoveKey ) ( char *s, const char *key );
void ( *SetValueForKey ) (char *s, const char *key, const char *value, int maxsize );
} net_api_t;
extern net_api_t netapi;
#endif // NET_APIH

40
common/netadr.h Normal file
View File

@ -0,0 +1,40 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
// netadr.h
#ifndef NETADR_H
#define NETADR_H
#ifdef _WIN32
#pragma once
#endif
typedef enum
{
NA_UNUSED,
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX
} netadrtype_t;
typedef struct netadr_s
{
netadrtype_t type;
unsigned char ip[4];
unsigned char ipx[10];
unsigned short port;
} netadr_t;
#endif // NETADR_H

57
common/particledef.h Normal file
View File

@ -0,0 +1,57 @@
/***
*
* Copyright (c) 1999, 2000 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.
*
****/
#if !defined( PARTICLEDEFH )
#define PARTICLEDEFH
#ifdef _WIN32
#pragma once
#endif
typedef enum {
pt_static,
pt_grav,
pt_slowgrav,
pt_fire,
pt_explode,
pt_explode2,
pt_blob,
pt_blob2,
pt_vox_slowgrav,
pt_vox_grav,
pt_clientcustom // Must have callback function specified
} ptype_t;
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
typedef struct particle_s
{
// driver-usable fields
vec3_t org;
short color;
short packedColor;
// drivers never touch the following fields
struct particle_s *next;
vec3_t vel;
float ramp;
float die;
ptype_t type;
void (*deathfunc)( struct particle_s *particle );
// for pt_clientcusttom, we'll call this function each frame
void (*callback)( struct particle_s *particle, float frametime );
// for deathfunc, etc.
unsigned char context;
} particle_t;
#endif

Some files were not shown because too many files have changed in this diff Show More