diff --git a/cl_dll/cdll_int.cpp b/cl_dll/cdll_int.cpp index d58f913..2519e92 100644 --- a/cl_dll/cdll_int.cpp +++ b/cl_dll/cdll_int.cpp @@ -1,333 +1,333 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// cdll_int.c -// -// this implementation handles the linking of the engine to the DLL -// - -#include "hud.h" -#include "cl_util.h" -#include "netadr.h" - -extern "C" -{ -#include "pm_shared.h" -} - -#include -#include "interface.h" -#include "render_api.h" -#include "mobility_int.h" - -#ifdef _WIN32 -#define DLLEXPORT __declspec( dllexport ) -#else -#define DLLEXPORT -#endif - -cl_enginefunc_t gEngfuncs; -render_api_t gRenderAPI; -mobile_engfuncs_t gMobileAPI; -CHud gHUD; -int g_iXash; // indicates a buildnum - -void InitInput (void); -void EV_HookEvents( void ); -void IN_Commands( void ); - -/* -========================== - Initialize - -Called when the DLL is first loaded. -========================== -*/ -extern "C" -{ -int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion ); -int DLLEXPORT HUD_VidInit( void ); -void DLLEXPORT HUD_Init( void ); -int DLLEXPORT HUD_Redraw( float flTime, int intermission ); -int DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime ); -void 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( const 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 ); -void DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking); -void DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf ); -int DLLEXPORT HUD_GetRenderInterface( int version, render_api_t *renderfuncs, render_interface_t *callback ); -int DLLEXPORT HUD_MobilityInterface( mobile_engfuncs_t *mobileapi ); -} - -/* -================================ -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( const 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 ) -{ - gEngfuncs = *pEnginefuncs; - - if (iVersion != CLDLL_INTERFACE_VERSION) - return 0; - - memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t)); - - g_iXash = (int)CVAR_GET_FLOAT("build"); - - EV_HookEvents(); - - return 1; -} - - -/* -========================== - HUD_VidInit - -Called when the game initializes -and whenever the vid_mode is changed -so the HUD can reinitialize itself. -========================== -*/ - -int DLLEXPORT HUD_VidInit( void ) -{ - gHUD.VidInit(); - - //VGui_Startup(); - - return 1; -} - -/* -========================== - HUD_Init - -Called whenever the client connects -to a server. Reinitializes all -the hud variables. -========================== -*/ - -void DLLEXPORT HUD_Init( void ) -{ - InitInput(); - gHUD.Init(); - //Scheme_Init(); -} - - -/* -========================== - HUD_Redraw - -called every screen frame to -redraw the HUD. -=========================== -*/ - -int DLLEXPORT HUD_Redraw( float time, int intermission ) -{ - gHUD.Redraw( time, intermission ); - - return 1; -} - - -/* -========================== - HUD_UpdateClientData - -called every time shared client -dll/engine data gets changed, -and gives the cdll a chance -to modify the data. - -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 ); -} - -/* -========================== - HUD_Reset - -Called at start and end of demos to restore to "non"HUD state. -========================== -*/ - -void DLLEXPORT HUD_Reset( void ) -{ - gHUD.VidInit(); -} - -/* -========================== -HUD_Frame - -Called by engine every frame that client .dll is loaded -========================== -*/ - -void DLLEXPORT HUD_Frame( double time ) -{ - //ServersThink( time ); - - //GetClientVoiceMgr()->Frame(time); -} - - -/* -========================== -HUD_VoiceStatus - -Called when a player starts or stops talking. -========================== -*/ - -void DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking) -{ - //GetClientVoiceMgr()->UpdateSpeakerStatus(entindex, bTalking); -} - -/* -========================== -HUD_DirectorEvent - -Called when a director event message was received -========================== -*/ - -void DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf ) -{ - gHUD.m_Spectator.DirectorMessage( iSize, pbuf ); -} - -/* -========================== -HUD_GetRenderInterface - -Called when Xash3D sends render api to us -========================== -*/ - -int DLLEXPORT HUD_GetRenderInterface( int version, render_api_t *renderfuncs, render_interface_t *callback ) -{ - if( version != CL_RENDER_INTERFACE_VERSION ) - { - return false; - } - - gRenderAPI = *renderfuncs; - - // we didn't send callbacks to engine, because we don't use it - // *callback = renderInterface; - - return true; -} - -/* -======================== -HUD_MobilityInterface -======================== -*/ -int DLLEXPORT HUD_MobilityInterface( mobile_engfuncs_t *mobileapi ) -{ - if( mobileapi->version != MOBILITY_API_VERSION ) - { - gEngfuncs.Con_Printf("Client Error: Mobile API version mismatch. Got: %i, want: %i\n", mobileapi->version, MOBILITY_API_VERSION); - return 1; - } - - gMobileAPI = *mobileapi; - - return 0; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// cdll_int.c +// +// this implementation handles the linking of the engine to the DLL +// + +#include "hud.h" +#include "cl_util.h" +#include "netadr.h" + +extern "C" +{ +#include "pm_shared.h" +} + +#include +#include "interface.h" +#include "render_api.h" +#include "mobility_int.h" + +#ifdef _WIN32 +#define DLLEXPORT __declspec( dllexport ) +#else +#define DLLEXPORT +#endif + +cl_enginefunc_t gEngfuncs; +render_api_t gRenderAPI; +mobile_engfuncs_t gMobileAPI; +CHud gHUD; +int g_iXash; // indicates a buildnum + +void InitInput (void); +void EV_HookEvents( void ); +void IN_Commands( void ); + +/* +========================== + Initialize + +Called when the DLL is first loaded. +========================== +*/ +extern "C" +{ +int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion ); +int DLLEXPORT HUD_VidInit( void ); +void DLLEXPORT HUD_Init( void ); +int DLLEXPORT HUD_Redraw( float flTime, int intermission ); +int DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime ); +void 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( const 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 ); +void DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking); +void DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf ); +int DLLEXPORT HUD_GetRenderInterface( int version, render_api_t *renderfuncs, render_interface_t *callback ); +int DLLEXPORT HUD_MobilityInterface( mobile_engfuncs_t *mobileapi ); +} + +/* +================================ +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( const 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 ) +{ + gEngfuncs = *pEnginefuncs; + + if (iVersion != CLDLL_INTERFACE_VERSION) + return 0; + + memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t)); + + g_iXash = (int)CVAR_GET_FLOAT("build"); + + EV_HookEvents(); + + return 1; +} + + +/* +========================== + HUD_VidInit + +Called when the game initializes +and whenever the vid_mode is changed +so the HUD can reinitialize itself. +========================== +*/ + +int DLLEXPORT HUD_VidInit( void ) +{ + gHUD.VidInit(); + + //VGui_Startup(); + + return 1; +} + +/* +========================== + HUD_Init + +Called whenever the client connects +to a server. Reinitializes all +the hud variables. +========================== +*/ + +void DLLEXPORT HUD_Init( void ) +{ + InitInput(); + gHUD.Init(); + //Scheme_Init(); +} + + +/* +========================== + HUD_Redraw + +called every screen frame to +redraw the HUD. +=========================== +*/ + +int DLLEXPORT HUD_Redraw( float time, int intermission ) +{ + gHUD.Redraw( time, intermission ); + + return 1; +} + + +/* +========================== + HUD_UpdateClientData + +called every time shared client +dll/engine data gets changed, +and gives the cdll a chance +to modify the data. + +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 ); +} + +/* +========================== + HUD_Reset + +Called at start and end of demos to restore to "non"HUD state. +========================== +*/ + +void DLLEXPORT HUD_Reset( void ) +{ + gHUD.VidInit(); +} + +/* +========================== +HUD_Frame + +Called by engine every frame that client .dll is loaded +========================== +*/ + +void DLLEXPORT HUD_Frame( double time ) +{ + //ServersThink( time ); + + //GetClientVoiceMgr()->Frame(time); +} + + +/* +========================== +HUD_VoiceStatus + +Called when a player starts or stops talking. +========================== +*/ + +void DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking) +{ + //GetClientVoiceMgr()->UpdateSpeakerStatus(entindex, bTalking); +} + +/* +========================== +HUD_DirectorEvent + +Called when a director event message was received +========================== +*/ + +void DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf ) +{ + gHUD.m_Spectator.DirectorMessage( iSize, pbuf ); +} + +/* +========================== +HUD_GetRenderInterface + +Called when Xash3D sends render api to us +========================== +*/ + +int DLLEXPORT HUD_GetRenderInterface( int version, render_api_t *renderfuncs, render_interface_t *callback ) +{ + if( version != CL_RENDER_INTERFACE_VERSION ) + { + return false; + } + + gRenderAPI = *renderfuncs; + + // we didn't send callbacks to engine, because we don't use it + // *callback = renderInterface; + + return true; +} + +/* +======================== +HUD_MobilityInterface +======================== +*/ +int DLLEXPORT HUD_MobilityInterface( mobile_engfuncs_t *mobileapi ) +{ + if( mobileapi->version != MOBILITY_API_VERSION ) + { + gEngfuncs.Con_Printf("Client Error: Mobile API version mismatch. Got: %i, want: %i\n", mobileapi->version, MOBILITY_API_VERSION); + return 1; + } + + gMobileAPI = *mobileapi; + + return 0; +} diff --git a/cl_dll/com_weapons.cpp b/cl_dll/com_weapons.cpp index 69b531c..8891aba 100644 --- a/cl_dll/com_weapons.cpp +++ b/cl_dll/com_weapons.cpp @@ -1,292 +1,292 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// Com_Weapons.cpp -// Shared weapons common/shared functions -#include -#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; -static int g_currentweapon; - -/* -===================== -HUD_SendWeaponAnim - -Change weapon model animation -===================== -*/ -void HUD_SendWeaponAnim( int iAnim, int iWeaponId, int iBody, int iForce ) -{ - // Don't actually change it. - if ( !g_runfuncs && !iForce ) - return; - - g_currentanim = iAnim; - g_currentweapon = iWeaponId; - - // Tell animation system new info - gEngfuncs.pfnWeaponAnim( iAnim, iBody ); -} - -/* -===================== -HUD_GetWeaponAnim - -Retrieve current predicted weapon animation -===================== -*/ -int HUD_GetWeaponAnim( void ) -{ - return g_currentanim; -} - -/* -===================== -HUD_GetWeapon - -Retrieve current predicted weapon id -===================== -*/ -int HUD_GetWeapon( void ) -{ - return g_currentweapon; -} - -/* -===================== -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 int function ) { return "func"; } -void stub_SetModel ( edict_t *e, const char *m ) {} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// Com_Weapons.cpp +// Shared weapons common/shared functions +#include +#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; +static int g_currentweapon; + +/* +===================== +HUD_SendWeaponAnim + +Change weapon model animation +===================== +*/ +void HUD_SendWeaponAnim( int iAnim, int iWeaponId, int iBody, int iForce ) +{ + // Don't actually change it. + if ( !g_runfuncs && !iForce ) + return; + + g_currentanim = iAnim; + g_currentweapon = iWeaponId; + + // Tell animation system new info + gEngfuncs.pfnWeaponAnim( iAnim, iBody ); +} + +/* +===================== +HUD_GetWeaponAnim + +Retrieve current predicted weapon animation +===================== +*/ +int HUD_GetWeaponAnim( void ) +{ + return g_currentanim; +} + +/* +===================== +HUD_GetWeapon + +Retrieve current predicted weapon id +===================== +*/ +int HUD_GetWeapon( void ) +{ + return g_currentweapon; +} + +/* +===================== +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 int function ) { return "func"; } +void stub_SetModel ( edict_t *e, const char *m ) {} diff --git a/cl_dll/cs_wpn/com_weapons.cpp b/cl_dll/cs_wpn/com_weapons.cpp index f748bd1..2f8f441 100644 --- a/cl_dll/cs_wpn/com_weapons.cpp +++ b/cl_dll/cs_wpn/com_weapons.cpp @@ -1,278 +1,278 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// Com_Weapons.cpp -// Shared weapons common/shared functions -#include -#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 int function ) { return "func"; } -void stub_SetModel ( edict_t *e, const char *m ) {} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// Com_Weapons.cpp +// Shared weapons common/shared functions +#include +#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 int function ) { return "func"; } +void stub_SetModel ( edict_t *e, const char *m ) {} diff --git a/cl_dll/cs_wpn/cs_baseentity.cpp b/cl_dll/cs_wpn/cs_baseentity.cpp index 2738b17..7dacce4 100644 --- a/cl_dll/cs_wpn/cs_baseentity.cpp +++ b/cl_dll/cs_wpn/cs_baseentity.cpp @@ -1,284 +1,284 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -/* -========================== -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 "port.h" -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "player.h" -#include "weapons.h" -#include "nodes.h" -#include "soundent.h" -#include "skill.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 ) { } -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 ) { } -CBaseEntity *UTIL_FindEntityByClassname(CBaseEntity *pStartEntity, const char *szName) { return 0; } - -// CBaseToggle Stubs -int CBaseToggle::Restore( class CRestore & ) { return 1; } -int CBaseToggle::Save( class CSave & ) { return 1; } -void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { } - -void UTIL_Remove( CBaseEntity *pEntity ){ } -struct skilldata_t gSkillData; -void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax ){ } -CBaseEntity *UTIL_FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ){ return 0;} - -Vector UTIL_VecToAngles( const Vector &vec ){ return 0; } -CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate ) { return 0; } -void CBeam::PointEntInit( const Vector &start, int endIndex ) { } -CBeam *CBeam::BeamCreate( const char *pSpriteName, int width ) { return NULL; } -void CSprite::Expand( float scaleSpeed, float fadeSpeed ) { } - - -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, const 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, const 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, const 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::PlayerUse ( void ) { } -void CBasePlayer::Jump() { } -void CBasePlayer::Duck( ) { } -int CBasePlayer::Classify ( void ) { return 0; } -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 ( const char *pszItemName ) { } -BOOL CBasePlayer::HasPlayerItem( CBasePlayerItem *pCheckItem ) { return FALSE; } -BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) { return FALSE; } -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 ) { } - -// CS16 START -void CBasePlayer::Restart( ) { } -void CBasePlayer::ResetMaxSpeed() { } -void CBasePlayer::RoundRespawn() { } -void CBasePlayer::Blind(float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha) { } -void CBasePlayer::SetProgressBarTime( int iTime ) { } -void CBasePlayer::SetBombIcon( int ) { } -void CBasePlayer::UpdateShieldCrosshair(bool bShieldDrawn) { } -void CBasePlayer::Radio(const char *msg_id, const char *msg_verbose, int pitch, bool showIcon) { } - -void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage) { } -void UTIL_TraceHull(const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, TraceResult *ptr) { } -float TEXTURETYPE_PlaySound(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType) { return 0.0f; } -void UTIL_ScreenShake(const Vector ¢er, float amplitude, float frequency, float duration, float radius) { } -void UTIL_Bubbles(Vector mins, Vector maxs, int count) { } -void RemoveEntityHashValue(entvars_s *pev, const char *value, hash_types_e fieldType) { } -void AddEntityHashValue(entvars_s *pev, const char *value, hash_types_e fieldType) { } -int UTIL_PointContents(const Vector &vec) { return 0; } -void UTIL_EmitAmbientSound(edict_t *entity, const Vector &vecOrigin, const char *samp, float vol, float attenuation, int fFlags, int pitch) { } - -CGrenade *CGrenade::ShootSatchelCharge(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) { return 0; } -CGrenade *CGrenade::ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time) { return 0; } -CGrenade *CGrenade::ShootTimed2(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time, int iTeam, unsigned short usEvent) { return 0; } -CGrenade *CGrenade::ShootSmokeGrenade(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time, unsigned short usEvent) { return 0; } - -// CS16 END - -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 DecalGunshot( TraceResult *pTrace, int iBulletType, bool ClientOnly, entvars_t *pShooter, bool bHitMetal ) { } -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 ) { } -void CSoundEnt::InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration ) {} -void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType ){} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +/* +========================== +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 "port.h" +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "player.h" +#include "weapons.h" +#include "nodes.h" +#include "soundent.h" +#include "skill.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 ) { } +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 ) { } +CBaseEntity *UTIL_FindEntityByClassname(CBaseEntity *pStartEntity, const char *szName) { return 0; } + +// CBaseToggle Stubs +int CBaseToggle::Restore( class CRestore & ) { return 1; } +int CBaseToggle::Save( class CSave & ) { return 1; } +void CBaseToggle :: KeyValue( struct KeyValueData_s * ) { } + +void UTIL_Remove( CBaseEntity *pEntity ){ } +struct skilldata_t gSkillData; +void UTIL_SetSize( entvars_t *pev, const Vector &vecMin, const Vector &vecMax ){ } +CBaseEntity *UTIL_FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ){ return 0;} + +Vector UTIL_VecToAngles( const Vector &vec ){ return 0; } +CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, BOOL animate ) { return 0; } +void CBeam::PointEntInit( const Vector &start, int endIndex ) { } +CBeam *CBeam::BeamCreate( const char *pSpriteName, int width ) { return NULL; } +void CSprite::Expand( float scaleSpeed, float fadeSpeed ) { } + + +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, const 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, const 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, const 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::PlayerUse ( void ) { } +void CBasePlayer::Jump() { } +void CBasePlayer::Duck( ) { } +int CBasePlayer::Classify ( void ) { return 0; } +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 ( const char *pszItemName ) { } +BOOL CBasePlayer::HasPlayerItem( CBasePlayerItem *pCheckItem ) { return FALSE; } +BOOL CBasePlayer :: SwitchWeapon( CBasePlayerItem *pWeapon ) { return FALSE; } +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 ) { } + +// CS16 START +void CBasePlayer::Restart( ) { } +void CBasePlayer::ResetMaxSpeed() { } +void CBasePlayer::RoundRespawn() { } +void CBasePlayer::Blind(float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha) { } +void CBasePlayer::SetProgressBarTime( int iTime ) { } +void CBasePlayer::SetBombIcon( int ) { } +void CBasePlayer::UpdateShieldCrosshair(bool bShieldDrawn) { } +void CBasePlayer::Radio(const char *msg_id, const char *msg_verbose, int pitch, bool showIcon) { } + +void RadiusFlash(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage) { } +void UTIL_TraceHull(const Vector &vecStart, const Vector &vecEnd, IGNORE_MONSTERS igmon, int hullNumber, edict_t *pentIgnore, TraceResult *ptr) { } +float TEXTURETYPE_PlaySound(TraceResult *ptr, Vector vecSrc, Vector vecEnd, int iBulletType) { return 0.0f; } +void UTIL_ScreenShake(const Vector ¢er, float amplitude, float frequency, float duration, float radius) { } +void UTIL_Bubbles(Vector mins, Vector maxs, int count) { } +void RemoveEntityHashValue(entvars_s *pev, const char *value, hash_types_e fieldType) { } +void AddEntityHashValue(entvars_s *pev, const char *value, hash_types_e fieldType) { } +int UTIL_PointContents(const Vector &vec) { return 0; } +void UTIL_EmitAmbientSound(edict_t *entity, const Vector &vecOrigin, const char *samp, float vol, float attenuation, int fFlags, int pitch) { } + +CGrenade *CGrenade::ShootSatchelCharge(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity) { return 0; } +CGrenade *CGrenade::ShootTimed(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time) { return 0; } +CGrenade *CGrenade::ShootTimed2(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time, int iTeam, unsigned short usEvent) { return 0; } +CGrenade *CGrenade::ShootSmokeGrenade(entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time, unsigned short usEvent) { return 0; } + +// CS16 END + +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 DecalGunshot( TraceResult *pTrace, int iBulletType, bool ClientOnly, entvars_t *pShooter, bool bHitMetal ) { } +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 ) { } +void CSoundEnt::InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration ) {} +void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType ){} diff --git a/cl_dll/cs_wpn/cs_objects.cpp b/cl_dll/cs_wpn/cs_objects.cpp index e8d4b4c..6505d08 100644 --- a/cl_dll/cs_wpn/cs_objects.cpp +++ b/cl_dll/cs_wpn/cs_objects.cpp @@ -1,38 +1,38 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "hud.h" -#include "cl_util.h" -#include "demo.h" - -#include "demo_api.h" -#include "const.h" -#include "entity_state.h" -#include "cl_entity.h" - -#include "pm_defs.h" -#include "event_api.h" -#include "entity_types.h" -#include "r_efx.h" - -/* -===================== -Game_AddObjects - -Add game specific, client-side objects here -===================== -*/ -void Game_AddObjects( void ) -{ -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#include "hud.h" +#include "cl_util.h" +#include "demo.h" + +#include "demo_api.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" + +#include "pm_defs.h" +#include "event_api.h" +#include "entity_types.h" +#include "r_efx.h" + +/* +===================== +Game_AddObjects + +Add game specific, client-side objects here +===================== +*/ +void Game_AddObjects( void ) +{ +} diff --git a/cl_dll/cs_wpn/cs_weapons.cpp b/cl_dll/cs_wpn/cs_weapons.cpp index 48d0d48..483bad1 100644 --- a/cl_dll/cs_wpn/cs_weapons.cpp +++ b/cl_dll/cs_wpn/cs_weapons.cpp @@ -1,1563 +1,1563 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#include "port.h" -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "monsters.h" - -#define PLAYER_H -#include "weapons.h" -#undef PLAYER_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" - -#include "cl_entity.h" - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#define CanAttack( x, y, z ) ((x) <= (y)) - -extern "C" char PM_FindTextureType( char *name ); - -extern globalvars_t *gpGlobals; -extern int g_iUser1; -extern bool g_bGlockBurstMode; - -// 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 = { 0 }; - -static CBasePlayerWeapon *g_pWpns[ 32 ]; - -extern int g_rseq; -extern int g_gaitseq; -extern vec3_t g_clorg; -extern vec3_t g_clang; - -float g_flApplyVel = 0.0; - -// HLDM Weapon placeholder entities -CAK47 g_AK47; -CAUG g_AUG; -CAWP g_AWP; -CC4 g_C4; -CDEAGLE g_DEAGLE; -CELITE g_ELITE; -CFamas g_Famas; -CFiveSeven g_FiveSeven; -CFlashbang g_Flashbang; -CG3SG1 g_G3SG1; -CGalil g_Galil; -CGLOCK18 g_GLOCK18; -CHEGrenade g_HEGrenade; -CKnife g_Knife; -CM249 g_M249; -CM3 g_M3; -CM4A1 g_M4A1; -CMAC10 g_MAC10; -CMP5N g_MP5N; -CP228 g_P228; -CP90 g_P90; -CSCOUT g_SCOUT; -CSG550 g_SG550; -CSG552 g_SG552; -CSmokeGrenade g_SmokeGrenade; -CTMP g_TMP; -CUMP45 g_UMP45; -CUSP g_USP; -CXM1014 g_XM1014; - -int g_iWeaponFlags; -bool g_bInBombZone; -int g_iFreezeTimeOver; -bool g_bHoldingShield; -bool g_bHoldingKnife; -vec3_t g_vPlayerVelocity; -float g_flPlayerSpeed; -int g_iPlayerFlags; - -/* -====================== -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. -===================== -*/ -edict_t *EHANDLE::Get(void) -{ - if (!m_pent) - return NULL; - - if (m_pent->serialnumber != m_serialnumber) - return NULL; - - return m_pent; -} - -edict_t *EHANDLE::Set(edict_t *pent) -{ - m_pent = pent; - - if (pent) - m_serialnumber = m_pent->serialnumber; - - return pent; -} - -EHANDLE::operator CBaseEntity *(void) -{ - return (CBaseEntity *)GET_PRIVATE(Get()); -} - -CBaseEntity *EHANDLE::operator = (CBaseEntity *pEntity) -{ - if (pEntity) - { - m_pent = ENT(pEntity->pev); - - if (m_pent) - m_serialnumber = m_pent->serialnumber; - } - else - { - m_pent = NULL; - m_serialnumber = 0; - } - - return pEntity; -} - -EHANDLE::operator int(void) -{ - return Get() != NULL; -} - -CBaseEntity *EHANDLE::operator ->(void) -{ - return (CBaseEntity *)GET_PRIVATE(Get()); -} - - -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; - memset( &info, 0, sizeof( ItemInfo ) ); - - ((CBasePlayerWeapon *)pEntity)->m_pPlayer = pWeaponOwner; - - ((CBasePlayerWeapon *)pEntity)->GetItemInfo( &info ); - - g_pWpns[ info.iId ] = (CBasePlayerWeapon *)pEntity; - CBasePlayerItem::ItemInfoArray[ info.iId ] = info; - } -} - -/* -===================== -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, int body ) -{ - if( !m_pPlayer->m_pActiveItem ) - return FALSE; - - if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) - return FALSE; - - int j = min(iClipSize - m_iClip, player.m_rgAmmo[m_iPrimaryAmmoType]); - - if (j == 0) - return FALSE; - - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay; - - //!!UNDONE -- reload sound goes here !!! - SendWeaponAnim( iAnim, UseDecrement() ); - - m_fInReload = TRUE; - - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + fDelay + 0.5f; - return TRUE; -} - -/* -===================== -CBasePlayerWeapon :: CanDeploy -===================== -*/ -BOOL CBasePlayerWeapon :: CanDeploy( void ) -{ -#if 0 - 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; -#else - return TRUE; -#endif -} -/* -===================== -CBasePlayer :: HasShield - -===================== -*/ -bool CBasePlayer::HasShield() -{ - return g_bHoldingShield; -} - -/* -===================== -CBasePlayerWeapon::HasSecondaryAttack() - -===================== -*/ -bool CBasePlayerWeapon::HasSecondaryAttack() -{ - if (g_bHoldingShield == false) - { - if (m_iId == WEAPON_AK47 || m_iId == WEAPON_XM1014 || m_iId == WEAPON_MAC10 || m_iId == WEAPON_ELITE || m_iId == WEAPON_FIVESEVEN || m_iId == WEAPON_MP5N || m_iId == WEAPON_M249 || m_iId == WEAPON_M3 || m_iId == WEAPON_TMP || m_iId == WEAPON_DEAGLE || m_iId == WEAPON_P228 || m_iId == WEAPON_P90 || m_iId == WEAPON_C4 || m_iId == WEAPON_GALIL) - return false; - } - - return true; -} - -void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL isGlock18) -{ - m_iClip--; - - if (m_iClip < 0) - { - m_iClip = 0; - shotsFired = 3; - shootTime = 0; - return; - } - - UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); - - Vector vecDir; - - if (isGlock18) - { - vecDir = m_pPlayer->FireBullets3(m_pPlayer->GetGunPosition(), gpGlobals->v_forward, 0.05, 8192, 1, BULLET_PLAYER_9MM, 18, 0.9, m_pPlayer->pev, TRUE, m_pPlayer->random_seed); - PLAYBACK_EVENT_FULL(FEV_NOTHOST, ENT(m_pPlayer->pev), m_usFireGlock18, 0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, (int)(m_pPlayer->pev->punchangle.x * 10000), (int)(m_pPlayer->pev->punchangle.y * 10000), m_iClip != 0, FALSE); - m_pPlayer->ammo_9mm--; - } - else - { - vecDir = m_pPlayer->FireBullets3(m_pPlayer->GetGunPosition(), gpGlobals->v_forward, m_fBurstSpread, 8192, 2, BULLET_PLAYER_556MM, 30, 0.96, m_pPlayer->pev, TRUE, m_pPlayer->random_seed); - PLAYBACK_EVENT_FULL(FEV_NOTHOST, ENT(m_pPlayer->pev), m_usFireFamas, 0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, (int)(m_pPlayer->pev->punchangle.x * 10000000), (int)(m_pPlayer->pev->punchangle.y * 10000000), m_iClip != 0, FALSE); - m_pPlayer->ammo_556nato--; - } - - m_pPlayer->pev->effects |= EF_MUZZLEFLASH; - m_pPlayer->SetAnimation(PLAYER_ATTACK1); - shotsFired++; - - if (shotsFired == 3) - shootTime = 0; - else - shootTime = gpGlobals->time + 0.1; -} - -bool CBasePlayerWeapon::ShieldSecondaryFire(int up_anim, int down_anim) -{ - if (m_pPlayer->HasShield() == false) - return false; - - if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) - { - m_iWeaponState &= ~WPNSTATE_SHIELD_DRAWN; - SendWeaponAnim(down_anim, UseDecrement() != FALSE); - strncpy(m_pPlayer->m_szAnimExtention, "shieldgun", sizeof(m_pPlayer->m_szAnimExtention)); - m_fMaxSpeed = 250; - m_pPlayer->m_bShieldDrawn = false; - } - else - { - m_iWeaponState |= WPNSTATE_SHIELD_DRAWN; - SendWeaponAnim(up_anim, UseDecrement() != FALSE); - strncpy(m_pPlayer->m_szAnimExtention, "shielded", sizeof(m_pPlayer->m_szAnimExtention)); - m_fMaxSpeed = 180; - m_pPlayer->m_bShieldDrawn = true; - } - - m_pPlayer->UpdateShieldCrosshair((m_iWeaponState & WPNSTATE_SHIELD_DRAWN) ? true : false); - m_pPlayer->ResetMaxSpeed(); - - m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.4; - m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.4; - m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6; - return true; -} - -void CBasePlayerWeapon::KickBack(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change){} - -void CBasePlayerWeapon::SetPlayerShieldAnim(void) -{ - if (m_pPlayer->HasShield() == true) - { - if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) - strncpy(m_pPlayer->m_szAnimExtention, "shield", sizeof(m_pPlayer->m_szAnimExtention)); - else - strncpy(m_pPlayer->m_szAnimExtention, "shieldgun", sizeof(m_pPlayer->m_szAnimExtention)); - } -} - -void CBasePlayerWeapon::ResetPlayerShieldAnim(void) -{ - if (m_pPlayer->HasShield() == true) - { - if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) - strncpy(m_pPlayer->m_szAnimExtention, "shieldgun", sizeof(m_pPlayer->m_szAnimExtention)); - } -} - -/* -===================== -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, skiplocal ); - - m_pPlayer->m_flNextAttack = 0.75f; - m_flTimeWeaponIdle = 1.5f; - return TRUE; -} - -/* -===================== -CBasePlayerWeapon :: PlayEmptySound - -===================== -*/ -BOOL CBasePlayerWeapon :: PlayEmptySound( void ) -{ -#if 0 - if (m_iPlayEmptySound) - { - switch (m_iId) - { - case WEAPON_USP: - case WEAPON_GLOCK18: - case WEAPON_P228: - case WEAPON_DEAGLE: - case WEAPON_ELITE: - case WEAPON_FIVESEVEN: - HUD_PlaySound("weapons/dryfire_pistol.wav", 0.8); - break; - default: - HUD_PlaySound("weapons/dryfire_rifle.wav", 0.8); - break; - } - } -#endif - 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; - - HUD_SendWeaponAnim( iAnim, m_iId, m_pPlayer->pev->body, 0 ); -} - -Vector CBaseEntity::FireBullets3 ( Vector vecSrc, Vector vecDirShooting, float flSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand ) -{ - float x, y, z; - - if ( pevAttacker ) - { - x = UTIL_SharedRandomFloat(shared_rand, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 1, -0.5, 0.5); - y = UTIL_SharedRandomFloat(shared_rand + 2, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 3, -0.5, 0.5); - } - else - { - do - { - x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); - y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); - z = x * x + y * y; - } - while (z > 1); - } - - return Vector(x * flSpread, y * flSpread, 0); -} -/* -===================== -CBasePlayerWeapon::ItemPostFrame - -Handles weapon firing, reloading, etc. -===================== -*/ -void CBasePlayerWeapon::ItemPostFrame( void ) -{ - int button = m_pPlayer->pev->button; - - if (!HasSecondaryAttack()) - button &= ~IN_ATTACK2; - - if (m_flGlock18Shoot != 0) - { - m_iClip--; - if( m_iClip < 0 ) - { - m_iClip = m_iGlock18ShotsFired = 0; - } - FireRemaining(m_iGlock18ShotsFired, m_flGlock18Shoot, TRUE); - } - else if (gpGlobals->time > m_flFamasShoot && m_flFamasShoot != 0) - { - m_iClip--; - if( m_iClip < 0 ) - { - m_iClip = m_iFamasShotsFired = 0; - } - FireRemaining(m_iFamasShotsFired, m_flFamasShoot, FALSE); - } - - if (m_flNextPrimaryAttack <= 0.0f) - { - if (m_pPlayer->m_bResumeZoom) - { - m_pPlayer->pev->fov = m_pPlayer->m_iFOV = m_pPlayer->m_iLastZoom; - - if (m_pPlayer->m_iFOV == m_pPlayer->m_iLastZoom) - m_pPlayer->m_bResumeZoom = false; - } - } - - if (!g_bHoldingShield) - { - if (m_fInReload && m_pPlayer->pev->button & IN_ATTACK2) - { - SecondaryAttack(); - m_pPlayer->pev->button &= ~IN_ATTACK2; - m_fInReload = FALSE; - m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase(); - } - } - - if ((m_fInReload) && m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase()) - { - int j = min(iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]); - - m_iClip += j; - m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j; - m_fInReload = FALSE; - } - - if ((button & IN_ATTACK2) && m_flNextSecondaryAttack <= UTIL_WeaponTimeBase()) - { - 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 <= UTIL_WeaponTimeBase()) - { - if ((!m_iClip && pszAmmo1()) || (iMaxClip() == WEAPON_NOCLIP && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()])) - m_fFireOnEmpty = TRUE; - - if (m_pPlayer->m_bCanShoot == true) - PrimaryAttack(); - } - else if (m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload) - { - if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) - { - if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0) - { - if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN)) - Reload(); - } - } - } - else if (!(button & (IN_ATTACK | IN_ATTACK2))) - { - if (m_bDelayFire == true) - { - m_bDelayFire = false; - - if (m_iShotsFired > 15) - m_iShotsFired = 15; - - m_flDecreaseShotsFired = gpGlobals->time + 0.4; - } - - m_fFireOnEmpty = FALSE; - - if (m_iId != WEAPON_USP && m_iId != WEAPON_GLOCK18 && m_iId != WEAPON_P228 && m_iId != WEAPON_DEAGLE && m_iId != WEAPON_ELITE && m_iId != WEAPON_FIVESEVEN) - { - if (m_iShotsFired > 0) - { - if (gpGlobals->time > m_flDecreaseShotsFired) - { - m_iShotsFired--; - m_flDecreaseShotsFired = gpGlobals->time + 0.0225; - } - } - } - else - m_iShotsFired = 0; - - - if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN)) - { - - if (m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) - && m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) - { - if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0) - { - Reload(); - return; - } - } - } - - WeaponIdle(); - return; - } -} - -/* -===================== -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( ); -} - -Vector CBasePlayer::GetGunPosition() -{ - Vector origin = pev->origin; - Vector view_ofs; - - gEngfuncs.pEventAPI->EV_LocalPlayerViewheight(view_ofs); - - return origin + view_ofs; -} - -/* -===================== -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 ) ); -#if 0 - static float flLastFraction = 1.0f; - - if( g_runfuncs ) - { - Vector vStart = vecStart, vEnd = vecEnd; - pmtrace_t pmtrace; - - gEngfuncs.pEventAPI->EV_SetTraceHull( 0 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vStart, vEnd, 0, -1, &pmtrace ); - flLastFraction = ptr->flFraction = pmtrace.fraction; - ptr->vecEndPos = pmtrace.endpos; - } - else - { - ptr->flFraction = flLastFraction; - } -#else - ptr->flFraction = 1.0f; -#endif -} - -/* -===================== -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 ); -} - -char UTIL_TextureHit(TraceResult *ptr, Vector vecSrc, Vector vecEnd) -{ - char chTextureType; - float rgfl1[3], rgfl2[3]; - const char *pTextureName; - char szbuffer[64]; - CBaseEntity *pEntity; - - if( ptr->pHit == NULL ) - return CHAR_TEX_FLESH; - - pEntity = CBaseEntity::Instance(ptr->pHit); - - if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) - return CHAR_TEX_FLESH; - - vecSrc.CopyToArray(rgfl1); - vecEnd.CopyToArray(rgfl2); - - if (pEntity) - pTextureName = TRACE_TEXTURE(ENT(pEntity->pev), rgfl1, rgfl2); - else - pTextureName = TRACE_TEXTURE(ENT(0), rgfl1, rgfl2); - - if (pTextureName) - { - if (*pTextureName == '-' || *pTextureName == '+') - pTextureName += 2; - - if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') - pTextureName++; - - strncpy(szbuffer, pTextureName, sizeof(szbuffer)); - szbuffer[CBTEXTURENAMEMAX - 1] = 0; - chTextureType = PM_FindTextureType(szbuffer); - } - else - chTextureType = 0; - - return chTextureType; -} - -CBaseEntity *UTIL_PlayerByIndex(int playerIndex) -{ - CBaseEntity *pPlayer = NULL; - - if (playerIndex > 0 && playerIndex <= gpGlobals->maxClients) - { - edict_t *pPlayerEdict = INDEXENT(playerIndex); - - if (pPlayerEdict && !pPlayerEdict->free) - pPlayer = CBaseEntity::Instance(pPlayerEdict); - } - - return pPlayer; -} - -void UTIL_MakeVectors( const Vector &vec ) -{ - gEngfuncs.pfnAngleVectors( vec, gpGlobals->v_forward, gpGlobals->v_right, gpGlobals->v_up ); -} - - -/* -===================== -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 ); -}*/ - -int RandomLong( int a, int b ) -{ - return gEngfuncs.pfnRandomLong( a, b ); -} - -/* -===================== -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 = RandomLong; - - // 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_P228, &player); - HUD_PrepEntity( &g_SCOUT, &player); - HUD_PrepEntity( &g_HEGrenade, &player); - HUD_PrepEntity( &g_XM1014, &player); - HUD_PrepEntity( &g_C4, &player); - HUD_PrepEntity( &g_MAC10, &player); - HUD_PrepEntity( &g_AUG, &player); - HUD_PrepEntity( &g_SmokeGrenade, &player); - HUD_PrepEntity( &g_ELITE, &player); - HUD_PrepEntity( &g_FiveSeven, &player); - HUD_PrepEntity( &g_UMP45, &player); - HUD_PrepEntity( &g_SG550, &player); - HUD_PrepEntity( &g_Galil, &player); - HUD_PrepEntity( &g_Famas, &player); - HUD_PrepEntity( &g_USP, &player); - HUD_PrepEntity( &g_GLOCK18, &player); - HUD_PrepEntity( &g_AWP, &player); - HUD_PrepEntity( &g_MP5N, &player); - HUD_PrepEntity( &g_M249, &player); - HUD_PrepEntity( &g_M4A1, &player); - HUD_PrepEntity( &g_M3, &player ); - HUD_PrepEntity( &g_TMP, &player); - HUD_PrepEntity( &g_G3SG1, &player); - HUD_PrepEntity( &g_Flashbang, &player); - HUD_PrepEntity( &g_DEAGLE, &player); - HUD_PrepEntity( &g_SG552, &player); - HUD_PrepEntity( &g_AK47, &player); - HUD_PrepEntity( &g_Knife, &player); - HUD_PrepEntity( &g_P90, &player ); -} - - -int GetWeaponAccuracyFlags( int weaponid ) -{ - int result = 0; - - if( weaponid <= WEAPON_P90 ) - { - switch( weaponid ) - { - case WEAPON_AUG: - case WEAPON_GALIL: - case WEAPON_M249: - case WEAPON_SG552: - case WEAPON_AK47: - case WEAPON_P90: - result = ACCURACY_AIR | ACCURACY_SPEED; - break; - case WEAPON_P228: - case WEAPON_FIVESEVEN: - case WEAPON_DEAGLE: - result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK; - break; - case WEAPON_GLOCK18: - if( g_iWeaponFlags & WPNSTATE_GLOCK18_BURST_MODE) - { - result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK; - } - else - { - result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK | ACCURACY_MULTIPLY_BY_14_2; - } - break; - case WEAPON_MAC10: - case WEAPON_UMP45: - case WEAPON_MP5N: - case WEAPON_TMP: - result = ACCURACY_AIR; - break; - case WEAPON_M4A1: - if(g_iWeaponFlags & WPNSTATE_USP_SILENCED) - { - result = ACCURACY_AIR | ACCURACY_SPEED; - } - else - { - result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_MULTIPLY_BY_14; - } - break; - case WEAPON_FAMAS: - if(g_iWeaponFlags & WPNSTATE_FAMAS_BURST_MODE) - { - result = ACCURACY_AIR | ACCURACY_SPEED; - } - else - { - result = ACCURACY_AIR | ACCURACY_SPEED | (1<<4); - } - break; - case WEAPON_USP: - if(g_iWeaponFlags & WPNSTATE_USP_SILENCED) - { - result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK; - } - else - { - result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK | ACCURACY_MULTIPLY_BY_14; - } - break; - } - } - - return result; -} - - -/* -===================== -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; - int flags; - - 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_P228: - pWeapon = &g_P228; - break; - - case WEAPON_SCOUT: - pWeapon = &g_SCOUT; - break; - - case WEAPON_HEGRENADE: - pWeapon = &g_HEGrenade; - break; - - case WEAPON_XM1014: - pWeapon = &g_XM1014; - break; - - case WEAPON_C4: - pWeapon = &g_C4; - break; - - case WEAPON_MAC10: - pWeapon = &g_MAC10; - break; - - case WEAPON_AUG: - pWeapon = &g_AUG; - break; - - case WEAPON_SMOKEGRENADE: - pWeapon = &g_SmokeGrenade; - break; - - case WEAPON_ELITE: - pWeapon = &g_ELITE; - break; - - case WEAPON_FIVESEVEN: - pWeapon = &g_FiveSeven; - break; - - case WEAPON_UMP45: - pWeapon = &g_UMP45; - break; - - case WEAPON_SG550: - pWeapon = &g_SG550; - break; - - case WEAPON_GALIL: - pWeapon = &g_Galil; - break; - - case WEAPON_FAMAS: - pWeapon = &g_Famas; - break; - - case WEAPON_USP: - pWeapon = &g_USP; - break; - - case WEAPON_GLOCK18: - pWeapon = &g_GLOCK18; - break; - - case WEAPON_AWP: - pWeapon = &g_AWP; - break; - - case WEAPON_MP5N: - pWeapon = &g_MP5N; - break; - - case WEAPON_M249: - pWeapon = &g_M249; - break; - - case WEAPON_M3: - pWeapon = &g_M3; - break; - - case WEAPON_M4A1: - pWeapon = &g_M4A1; - break; - - case WEAPON_TMP: - pWeapon = &g_TMP; - break; - - case WEAPON_G3SG1: - pWeapon = &g_G3SG1; - break; - - case WEAPON_FLASHBANG: - pWeapon = &g_Flashbang; - break; - - case WEAPON_DEAGLE: - pWeapon = &g_DEAGLE; - break; - - case WEAPON_SG552: - pWeapon = &g_SG552; - break; - - case WEAPON_AK47: - pWeapon = &g_AK47; - break; - - case WEAPON_KNIFE: - pWeapon = &g_Knife; - break; - - case WEAPON_P90: - pWeapon = &g_P90; - break; - - /*case WEAPON_NONE: - break; - - case WEAPON_GLOCK: - default: - gEngfuncs.Con_Printf("VALVEWHY: Unknown Weapon %i is active.\n", from->client.m_iId ); - break;*/ - } - - // 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; - - // 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; - } - - // We are not predicting the current weapon, just bow out here. - if ( !pWeapon ) - return; - - for ( i = 0; i < MAX_WEAPONS; i++ ) - { - pCurrent = g_pWpns[ i ]; - if ( !pCurrent ) - { - continue; - } - - pfrom = &from->weapondata[ i ]; - - pCurrent->m_fInReload = pfrom->m_fInReload; - pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload; - pCurrent->m_iClip = pfrom->m_iClip; - pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; - pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; - pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; - pCurrent->m_flStartThrow = pfrom->fuser2; - pCurrent->m_flReleaseThrow = pfrom->fuser3; - pCurrent->m_iSwing = pfrom->iuser1; - pCurrent->m_iWeaponState = pfrom->m_iWeaponState; - pCurrent->m_flLastFire = pfrom->m_fAimedDamage; - pCurrent->m_iShotsFired = pfrom->m_fInZoom; - pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[ 2 ]; - pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[ 0 ]; - player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ] = (int)from->client.vuser4[ 1 ]; - } - - if( pWeapon ) - g_iWeaponFlags = pWeapon->m_iWeaponState; - - // 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; - g_iPlayerFlags = 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->punchangle = from->client.punchangle; - 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; - - g_vPlayerVelocity = from->client.velocity; - g_flPlayerSpeed = from->client.velocity.Length(); - - //Stores all our ammo info, so the client side weapons can use them. - player.ammo_9mm = (int)from->client.ammo_nails; - player.ammo_556nato = (int)from->client.ammo_cells; - player.ammo_buckshot = (int)from->client.ammo_shells; - player.ammo_556natobox = (int)from->client.ammo_rockets; - player.ammo_762nato = (int)from->client.vuser2.x; - player.ammo_45acp = (int)from->client.vuser2.y; - player.ammo_50ae = (int)from->client.vuser2.z; - player.ammo_338mag = (int)from->client.vuser3.x; - player.ammo_57mm = (int)from->client.vuser3.y; - player.ammo_357sig = (int)from->client.vuser3.z; - - cl_entity_t *pplayer = gEngfuncs.GetLocalPlayer(); - if( pplayer ) - { - player.pev->origin = from->client.origin; - player.pev->angles = pplayer->angles; - player.pev->v_angle = v_angles; - } - - flags = from->client.iuser3; - g_bHoldingKnife = pWeapon->m_iId == WEAPON_KNIFE; - player.m_bCanShoot = (flags & PLAYER_CAN_SHOOT) != 0; - g_iFreezeTimeOver = !(flags & PLAYER_FREEZE_TIME_OVER); - g_bInBombZone = (flags & PLAYER_IN_BOMB_ZONE) != 0; - g_bHoldingShield = (flags & PLAYER_HOLDING_SHIELD) != 0; - - // Point to current weapon object - if ( pWeapon ) - { - player.m_pActiveItem = pWeapon; - } - - // 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 && !g_iUser1 ) - { - /*if( g_bHoldingKnife && pWeapon->m_iClientWeaponState && - player.pev->button & IN_FORWARD ) - player.m_flNextAttack = 0; - else if( player.m_flNextAttack > 0 ) - { - - }*/ - if ( player.m_flNextAttack <= 0 ) - { - pWeapon->ItemPostFrame(); - } - } - - // 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 prediction 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; - to->client.punchangle = player.pev->punchangle; - - - to->client.ammo_nails = player.ammo_9mm; - to->client.ammo_cells = player.ammo_556nato; - to->client.ammo_shells = player.ammo_buckshot; - to->client.ammo_rockets = player.ammo_556natobox; - to->client.vuser2.x = player.ammo_762nato; - to->client.vuser2.y = player.ammo_45acp; - to->client.vuser2.z = player.ammo_50ae; - to->client.vuser3.x = player.ammo_338mag; - to->client.vuser3.y = player.ammo_57mm; - to->client.vuser3.z = player.ammo_357sig; - to->client.iuser3 = flags; - - - - - // 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 ) && ( HUD_GetWeapon() != to->client.m_iId )) - // Force a fixed anim down to viewmodel - HUD_SendWeaponAnim( to->client.weaponanim, to->client.m_iId, 2, 1 ); - - if (pWeapon->m_iPrimaryAmmoType < MAX_AMMO_TYPES) - { - to->client.vuser4.x = pWeapon->m_iPrimaryAmmoType; - to->client.vuser4.y = player.m_rgAmmo[ pWeapon->m_iPrimaryAmmoType ]; - } - else - { - to->client.vuser4.x = -1.0; - to->client.vuser4.y = 0; - } - - for ( i = 0; i < MAX_WEAPONS; 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_fInSpecialReload = pCurrent->m_fInSpecialReload; - pto->m_iClip = pCurrent->m_iClip; - pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; - pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; - pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; - pto->m_flNextReload = pCurrent->m_flNextReload; - pto->fuser2 = pCurrent->m_flStartThrow; - pto->fuser3 = pCurrent->m_flReleaseThrow; - pto->iuser1 = pCurrent->m_iSwing; - pto->m_iWeaponState = pCurrent->m_iWeaponState; - pto->m_fInZoom = pCurrent->m_iShotsFired; - pto->m_fAimedDamage = pCurrent->m_flLastFire; - - // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) - pto->m_flNextReload -= cmd->msec / 1000.0f; - pto->m_fNextAimBonus -= cmd->msec / 1000.0f; - pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0f; - pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0f; - pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0f; - - - if( pto->m_flPumpTime != -9999.0f ) - { - pto->m_flPumpTime -= cmd->msec / 1000.0f; - if( pto->m_flPumpTime < -1.0f ) - pto->m_flPumpTime = 1.0f; - } - - 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; - } - - /*if ( pto->fuser1 < -0.001 ) - { - pto->fuser1 = -0.001; - }*/ - } - - // m_flNextAttack is now part of the weapons, but is part of the player instead - to->client.m_flNextAttack -= cmd->msec / 1000.0f; - 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( local_state_t *from, local_state_t *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed ) -{ - g_runfuncs = runfuncs; - //g_curstate = from; - -//#if defined( CLIENT_WEAPONS ) - /*if ( cl_lw && cl_lw->value ) - { - HUD_WeaponsPostThink( from, to, cmd, time, random_seed ); - } - else -#endif - { - to->client.fov = g_lastFOV; - g_iWeaponFlags = from->weapondata[ from->client.m_iId ].m_iWeaponState; - g_iPlayerFlags = from->client.flags; - g_iFreezeTimeOver = !(from->client.iuser3 & PLAYER_FREEZE_TIME_OVER); - g_bInBombZone = (from->client.iuser3 & PLAYER_IN_BOMB_ZONE) != 0; - g_bHoldingShield = (from->client.iuser3 & PLAYER_HOLDING_SHIELD) != 0; - g_bGlockBurstMode = false; // will be taken from g_iWeaponFlags - }*/ - - HUD_WeaponsPostThink( from, to, cmd, time, random_seed ); - - if ( g_runfuncs ) - { - g_gaitseq = to->playerstate.gaitsequence; - g_rseq = to->playerstate.sequence; - g_clang = cmd->viewangles; - g_clorg = to->playerstate.origin; - } - - // All games can use FOV state - g_lastFOV = to->client.fov; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "port.h" +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "monsters.h" + +#define PLAYER_H +#include "weapons.h" +#undef PLAYER_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" + +#include "cl_entity.h" + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#define CanAttack( x, y, z ) ((x) <= (y)) + +extern "C" char PM_FindTextureType( char *name ); + +extern globalvars_t *gpGlobals; +extern int g_iUser1; +extern bool g_bGlockBurstMode; + +// 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 = { 0 }; + +static CBasePlayerWeapon *g_pWpns[ 32 ]; + +extern int g_rseq; +extern int g_gaitseq; +extern vec3_t g_clorg; +extern vec3_t g_clang; + +float g_flApplyVel = 0.0; + +// HLDM Weapon placeholder entities +CAK47 g_AK47; +CAUG g_AUG; +CAWP g_AWP; +CC4 g_C4; +CDEAGLE g_DEAGLE; +CELITE g_ELITE; +CFamas g_Famas; +CFiveSeven g_FiveSeven; +CFlashbang g_Flashbang; +CG3SG1 g_G3SG1; +CGalil g_Galil; +CGLOCK18 g_GLOCK18; +CHEGrenade g_HEGrenade; +CKnife g_Knife; +CM249 g_M249; +CM3 g_M3; +CM4A1 g_M4A1; +CMAC10 g_MAC10; +CMP5N g_MP5N; +CP228 g_P228; +CP90 g_P90; +CSCOUT g_SCOUT; +CSG550 g_SG550; +CSG552 g_SG552; +CSmokeGrenade g_SmokeGrenade; +CTMP g_TMP; +CUMP45 g_UMP45; +CUSP g_USP; +CXM1014 g_XM1014; + +int g_iWeaponFlags; +bool g_bInBombZone; +int g_iFreezeTimeOver; +bool g_bHoldingShield; +bool g_bHoldingKnife; +vec3_t g_vPlayerVelocity; +float g_flPlayerSpeed; +int g_iPlayerFlags; + +/* +====================== +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. +===================== +*/ +edict_t *EHANDLE::Get(void) +{ + if (!m_pent) + return NULL; + + if (m_pent->serialnumber != m_serialnumber) + return NULL; + + return m_pent; +} + +edict_t *EHANDLE::Set(edict_t *pent) +{ + m_pent = pent; + + if (pent) + m_serialnumber = m_pent->serialnumber; + + return pent; +} + +EHANDLE::operator CBaseEntity *(void) +{ + return (CBaseEntity *)GET_PRIVATE(Get()); +} + +CBaseEntity *EHANDLE::operator = (CBaseEntity *pEntity) +{ + if (pEntity) + { + m_pent = ENT(pEntity->pev); + + if (m_pent) + m_serialnumber = m_pent->serialnumber; + } + else + { + m_pent = NULL; + m_serialnumber = 0; + } + + return pEntity; +} + +EHANDLE::operator int(void) +{ + return Get() != NULL; +} + +CBaseEntity *EHANDLE::operator ->(void) +{ + return (CBaseEntity *)GET_PRIVATE(Get()); +} + + +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; + memset( &info, 0, sizeof( ItemInfo ) ); + + ((CBasePlayerWeapon *)pEntity)->m_pPlayer = pWeaponOwner; + + ((CBasePlayerWeapon *)pEntity)->GetItemInfo( &info ); + + g_pWpns[ info.iId ] = (CBasePlayerWeapon *)pEntity; + CBasePlayerItem::ItemInfoArray[ info.iId ] = info; + } +} + +/* +===================== +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, int body ) +{ + if( !m_pPlayer->m_pActiveItem ) + return FALSE; + + if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) + return FALSE; + + int j = min(iClipSize - m_iClip, player.m_rgAmmo[m_iPrimaryAmmoType]); + + if (j == 0) + return FALSE; + + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay; + + //!!UNDONE -- reload sound goes here !!! + SendWeaponAnim( iAnim, UseDecrement() ); + + m_fInReload = TRUE; + + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + fDelay + 0.5f; + return TRUE; +} + +/* +===================== +CBasePlayerWeapon :: CanDeploy +===================== +*/ +BOOL CBasePlayerWeapon :: CanDeploy( void ) +{ +#if 0 + 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; +#else + return TRUE; +#endif +} +/* +===================== +CBasePlayer :: HasShield + +===================== +*/ +bool CBasePlayer::HasShield() +{ + return g_bHoldingShield; +} + +/* +===================== +CBasePlayerWeapon::HasSecondaryAttack() + +===================== +*/ +bool CBasePlayerWeapon::HasSecondaryAttack() +{ + if (g_bHoldingShield == false) + { + if (m_iId == WEAPON_AK47 || m_iId == WEAPON_XM1014 || m_iId == WEAPON_MAC10 || m_iId == WEAPON_ELITE || m_iId == WEAPON_FIVESEVEN || m_iId == WEAPON_MP5N || m_iId == WEAPON_M249 || m_iId == WEAPON_M3 || m_iId == WEAPON_TMP || m_iId == WEAPON_DEAGLE || m_iId == WEAPON_P228 || m_iId == WEAPON_P90 || m_iId == WEAPON_C4 || m_iId == WEAPON_GALIL) + return false; + } + + return true; +} + +void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL isGlock18) +{ + m_iClip--; + + if (m_iClip < 0) + { + m_iClip = 0; + shotsFired = 3; + shootTime = 0; + return; + } + + UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); + + Vector vecDir; + + if (isGlock18) + { + vecDir = m_pPlayer->FireBullets3(m_pPlayer->GetGunPosition(), gpGlobals->v_forward, 0.05, 8192, 1, BULLET_PLAYER_9MM, 18, 0.9, m_pPlayer->pev, TRUE, m_pPlayer->random_seed); + PLAYBACK_EVENT_FULL(FEV_NOTHOST, ENT(m_pPlayer->pev), m_usFireGlock18, 0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, (int)(m_pPlayer->pev->punchangle.x * 10000), (int)(m_pPlayer->pev->punchangle.y * 10000), m_iClip != 0, FALSE); + m_pPlayer->ammo_9mm--; + } + else + { + vecDir = m_pPlayer->FireBullets3(m_pPlayer->GetGunPosition(), gpGlobals->v_forward, m_fBurstSpread, 8192, 2, BULLET_PLAYER_556MM, 30, 0.96, m_pPlayer->pev, TRUE, m_pPlayer->random_seed); + PLAYBACK_EVENT_FULL(FEV_NOTHOST, ENT(m_pPlayer->pev), m_usFireFamas, 0, (float *)&g_vecZero, (float *)&g_vecZero, vecDir.x, vecDir.y, (int)(m_pPlayer->pev->punchangle.x * 10000000), (int)(m_pPlayer->pev->punchangle.y * 10000000), m_iClip != 0, FALSE); + m_pPlayer->ammo_556nato--; + } + + m_pPlayer->pev->effects |= EF_MUZZLEFLASH; + m_pPlayer->SetAnimation(PLAYER_ATTACK1); + shotsFired++; + + if (shotsFired == 3) + shootTime = 0; + else + shootTime = gpGlobals->time + 0.1; +} + +bool CBasePlayerWeapon::ShieldSecondaryFire(int up_anim, int down_anim) +{ + if (m_pPlayer->HasShield() == false) + return false; + + if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) + { + m_iWeaponState &= ~WPNSTATE_SHIELD_DRAWN; + SendWeaponAnim(down_anim, UseDecrement() != FALSE); + strncpy(m_pPlayer->m_szAnimExtention, "shieldgun", sizeof(m_pPlayer->m_szAnimExtention)); + m_fMaxSpeed = 250; + m_pPlayer->m_bShieldDrawn = false; + } + else + { + m_iWeaponState |= WPNSTATE_SHIELD_DRAWN; + SendWeaponAnim(up_anim, UseDecrement() != FALSE); + strncpy(m_pPlayer->m_szAnimExtention, "shielded", sizeof(m_pPlayer->m_szAnimExtention)); + m_fMaxSpeed = 180; + m_pPlayer->m_bShieldDrawn = true; + } + + m_pPlayer->UpdateShieldCrosshair((m_iWeaponState & WPNSTATE_SHIELD_DRAWN) ? true : false); + m_pPlayer->ResetMaxSpeed(); + + m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.4; + m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.4; + m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.6; + return true; +} + +void CBasePlayerWeapon::KickBack(float up_base, float lateral_base, float up_modifier, float lateral_modifier, float up_max, float lateral_max, int direction_change){} + +void CBasePlayerWeapon::SetPlayerShieldAnim(void) +{ + if (m_pPlayer->HasShield() == true) + { + if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) + strncpy(m_pPlayer->m_szAnimExtention, "shield", sizeof(m_pPlayer->m_szAnimExtention)); + else + strncpy(m_pPlayer->m_szAnimExtention, "shieldgun", sizeof(m_pPlayer->m_szAnimExtention)); + } +} + +void CBasePlayerWeapon::ResetPlayerShieldAnim(void) +{ + if (m_pPlayer->HasShield() == true) + { + if (m_iWeaponState & WPNSTATE_SHIELD_DRAWN) + strncpy(m_pPlayer->m_szAnimExtention, "shieldgun", sizeof(m_pPlayer->m_szAnimExtention)); + } +} + +/* +===================== +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, skiplocal ); + + m_pPlayer->m_flNextAttack = 0.75f; + m_flTimeWeaponIdle = 1.5f; + return TRUE; +} + +/* +===================== +CBasePlayerWeapon :: PlayEmptySound + +===================== +*/ +BOOL CBasePlayerWeapon :: PlayEmptySound( void ) +{ +#if 0 + if (m_iPlayEmptySound) + { + switch (m_iId) + { + case WEAPON_USP: + case WEAPON_GLOCK18: + case WEAPON_P228: + case WEAPON_DEAGLE: + case WEAPON_ELITE: + case WEAPON_FIVESEVEN: + HUD_PlaySound("weapons/dryfire_pistol.wav", 0.8); + break; + default: + HUD_PlaySound("weapons/dryfire_rifle.wav", 0.8); + break; + } + } +#endif + 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; + + HUD_SendWeaponAnim( iAnim, m_iId, m_pPlayer->pev->body, 0 ); +} + +Vector CBaseEntity::FireBullets3 ( Vector vecSrc, Vector vecDirShooting, float flSpread, float flDistance, int iPenetration, int iBulletType, int iDamage, float flRangeModifier, entvars_t *pevAttacker, bool bPistol, int shared_rand ) +{ + float x, y, z; + + if ( pevAttacker ) + { + x = UTIL_SharedRandomFloat(shared_rand, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 1, -0.5, 0.5); + y = UTIL_SharedRandomFloat(shared_rand + 2, -0.5, 0.5) + UTIL_SharedRandomFloat(shared_rand + 3, -0.5, 0.5); + } + else + { + do + { + x = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); + y = RANDOM_FLOAT(-0.5, 0.5) + RANDOM_FLOAT(-0.5, 0.5); + z = x * x + y * y; + } + while (z > 1); + } + + return Vector(x * flSpread, y * flSpread, 0); +} +/* +===================== +CBasePlayerWeapon::ItemPostFrame + +Handles weapon firing, reloading, etc. +===================== +*/ +void CBasePlayerWeapon::ItemPostFrame( void ) +{ + int button = m_pPlayer->pev->button; + + if (!HasSecondaryAttack()) + button &= ~IN_ATTACK2; + + if (m_flGlock18Shoot != 0) + { + m_iClip--; + if( m_iClip < 0 ) + { + m_iClip = m_iGlock18ShotsFired = 0; + } + FireRemaining(m_iGlock18ShotsFired, m_flGlock18Shoot, TRUE); + } + else if (gpGlobals->time > m_flFamasShoot && m_flFamasShoot != 0) + { + m_iClip--; + if( m_iClip < 0 ) + { + m_iClip = m_iFamasShotsFired = 0; + } + FireRemaining(m_iFamasShotsFired, m_flFamasShoot, FALSE); + } + + if (m_flNextPrimaryAttack <= 0.0f) + { + if (m_pPlayer->m_bResumeZoom) + { + m_pPlayer->pev->fov = m_pPlayer->m_iFOV = m_pPlayer->m_iLastZoom; + + if (m_pPlayer->m_iFOV == m_pPlayer->m_iLastZoom) + m_pPlayer->m_bResumeZoom = false; + } + } + + if (!g_bHoldingShield) + { + if (m_fInReload && m_pPlayer->pev->button & IN_ATTACK2) + { + SecondaryAttack(); + m_pPlayer->pev->button &= ~IN_ATTACK2; + m_fInReload = FALSE; + m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase(); + } + } + + if ((m_fInReload) && m_pPlayer->m_flNextAttack <= UTIL_WeaponTimeBase()) + { + int j = min(iMaxClip() - m_iClip, m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]); + + m_iClip += j; + m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= j; + m_fInReload = FALSE; + } + + if ((button & IN_ATTACK2) && m_flNextSecondaryAttack <= UTIL_WeaponTimeBase()) + { + 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 <= UTIL_WeaponTimeBase()) + { + if ((!m_iClip && pszAmmo1()) || (iMaxClip() == WEAPON_NOCLIP && !m_pPlayer->m_rgAmmo[PrimaryAmmoIndex()])) + m_fFireOnEmpty = TRUE; + + if (m_pPlayer->m_bCanShoot == true) + PrimaryAttack(); + } + else if (m_pPlayer->pev->button & IN_RELOAD && iMaxClip() != WEAPON_NOCLIP && !m_fInReload) + { + if (m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) + { + if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0) + { + if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN)) + Reload(); + } + } + } + else if (!(button & (IN_ATTACK | IN_ATTACK2))) + { + if (m_bDelayFire == true) + { + m_bDelayFire = false; + + if (m_iShotsFired > 15) + m_iShotsFired = 15; + + m_flDecreaseShotsFired = gpGlobals->time + 0.4; + } + + m_fFireOnEmpty = FALSE; + + if (m_iId != WEAPON_USP && m_iId != WEAPON_GLOCK18 && m_iId != WEAPON_P228 && m_iId != WEAPON_DEAGLE && m_iId != WEAPON_ELITE && m_iId != WEAPON_FIVESEVEN) + { + if (m_iShotsFired > 0) + { + if (gpGlobals->time > m_flDecreaseShotsFired) + { + m_iShotsFired--; + m_flDecreaseShotsFired = gpGlobals->time + 0.0225; + } + } + } + else + m_iShotsFired = 0; + + + if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN)) + { + + if (m_iClip == 0 && !(iFlags() & ITEM_FLAG_NOAUTORELOAD) + && m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) + { + if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0) + { + Reload(); + return; + } + } + } + + WeaponIdle(); + return; + } +} + +/* +===================== +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( ); +} + +Vector CBasePlayer::GetGunPosition() +{ + Vector origin = pev->origin; + Vector view_ofs; + + gEngfuncs.pEventAPI->EV_LocalPlayerViewheight(view_ofs); + + return origin + view_ofs; +} + +/* +===================== +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 ) ); +#if 0 + static float flLastFraction = 1.0f; + + if( g_runfuncs ) + { + Vector vStart = vecStart, vEnd = vecEnd; + pmtrace_t pmtrace; + + gEngfuncs.pEventAPI->EV_SetTraceHull( 0 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vStart, vEnd, 0, -1, &pmtrace ); + flLastFraction = ptr->flFraction = pmtrace.fraction; + ptr->vecEndPos = pmtrace.endpos; + } + else + { + ptr->flFraction = flLastFraction; + } +#else + ptr->flFraction = 1.0f; +#endif +} + +/* +===================== +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 ); +} + +char UTIL_TextureHit(TraceResult *ptr, Vector vecSrc, Vector vecEnd) +{ + char chTextureType; + float rgfl1[3], rgfl2[3]; + const char *pTextureName; + char szbuffer[64]; + CBaseEntity *pEntity; + + if( ptr->pHit == NULL ) + return CHAR_TEX_FLESH; + + pEntity = CBaseEntity::Instance(ptr->pHit); + + if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE) + return CHAR_TEX_FLESH; + + vecSrc.CopyToArray(rgfl1); + vecEnd.CopyToArray(rgfl2); + + if (pEntity) + pTextureName = TRACE_TEXTURE(ENT(pEntity->pev), rgfl1, rgfl2); + else + pTextureName = TRACE_TEXTURE(ENT(0), rgfl1, rgfl2); + + if (pTextureName) + { + if (*pTextureName == '-' || *pTextureName == '+') + pTextureName += 2; + + if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') + pTextureName++; + + strncpy(szbuffer, pTextureName, sizeof(szbuffer)); + szbuffer[CBTEXTURENAMEMAX - 1] = 0; + chTextureType = PM_FindTextureType(szbuffer); + } + else + chTextureType = 0; + + return chTextureType; +} + +CBaseEntity *UTIL_PlayerByIndex(int playerIndex) +{ + CBaseEntity *pPlayer = NULL; + + if (playerIndex > 0 && playerIndex <= gpGlobals->maxClients) + { + edict_t *pPlayerEdict = INDEXENT(playerIndex); + + if (pPlayerEdict && !pPlayerEdict->free) + pPlayer = CBaseEntity::Instance(pPlayerEdict); + } + + return pPlayer; +} + +void UTIL_MakeVectors( const Vector &vec ) +{ + gEngfuncs.pfnAngleVectors( vec, gpGlobals->v_forward, gpGlobals->v_right, gpGlobals->v_up ); +} + + +/* +===================== +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 ); +}*/ + +int RandomLong( int a, int b ) +{ + return gEngfuncs.pfnRandomLong( a, b ); +} + +/* +===================== +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 = RandomLong; + + // 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_P228, &player); + HUD_PrepEntity( &g_SCOUT, &player); + HUD_PrepEntity( &g_HEGrenade, &player); + HUD_PrepEntity( &g_XM1014, &player); + HUD_PrepEntity( &g_C4, &player); + HUD_PrepEntity( &g_MAC10, &player); + HUD_PrepEntity( &g_AUG, &player); + HUD_PrepEntity( &g_SmokeGrenade, &player); + HUD_PrepEntity( &g_ELITE, &player); + HUD_PrepEntity( &g_FiveSeven, &player); + HUD_PrepEntity( &g_UMP45, &player); + HUD_PrepEntity( &g_SG550, &player); + HUD_PrepEntity( &g_Galil, &player); + HUD_PrepEntity( &g_Famas, &player); + HUD_PrepEntity( &g_USP, &player); + HUD_PrepEntity( &g_GLOCK18, &player); + HUD_PrepEntity( &g_AWP, &player); + HUD_PrepEntity( &g_MP5N, &player); + HUD_PrepEntity( &g_M249, &player); + HUD_PrepEntity( &g_M4A1, &player); + HUD_PrepEntity( &g_M3, &player ); + HUD_PrepEntity( &g_TMP, &player); + HUD_PrepEntity( &g_G3SG1, &player); + HUD_PrepEntity( &g_Flashbang, &player); + HUD_PrepEntity( &g_DEAGLE, &player); + HUD_PrepEntity( &g_SG552, &player); + HUD_PrepEntity( &g_AK47, &player); + HUD_PrepEntity( &g_Knife, &player); + HUD_PrepEntity( &g_P90, &player ); +} + + +int GetWeaponAccuracyFlags( int weaponid ) +{ + int result = 0; + + if( weaponid <= WEAPON_P90 ) + { + switch( weaponid ) + { + case WEAPON_AUG: + case WEAPON_GALIL: + case WEAPON_M249: + case WEAPON_SG552: + case WEAPON_AK47: + case WEAPON_P90: + result = ACCURACY_AIR | ACCURACY_SPEED; + break; + case WEAPON_P228: + case WEAPON_FIVESEVEN: + case WEAPON_DEAGLE: + result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK; + break; + case WEAPON_GLOCK18: + if( g_iWeaponFlags & WPNSTATE_GLOCK18_BURST_MODE) + { + result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK; + } + else + { + result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK | ACCURACY_MULTIPLY_BY_14_2; + } + break; + case WEAPON_MAC10: + case WEAPON_UMP45: + case WEAPON_MP5N: + case WEAPON_TMP: + result = ACCURACY_AIR; + break; + case WEAPON_M4A1: + if(g_iWeaponFlags & WPNSTATE_USP_SILENCED) + { + result = ACCURACY_AIR | ACCURACY_SPEED; + } + else + { + result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_MULTIPLY_BY_14; + } + break; + case WEAPON_FAMAS: + if(g_iWeaponFlags & WPNSTATE_FAMAS_BURST_MODE) + { + result = ACCURACY_AIR | ACCURACY_SPEED; + } + else + { + result = ACCURACY_AIR | ACCURACY_SPEED | (1<<4); + } + break; + case WEAPON_USP: + if(g_iWeaponFlags & WPNSTATE_USP_SILENCED) + { + result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK; + } + else + { + result = ACCURACY_AIR | ACCURACY_SPEED | ACCURACY_DUCK | ACCURACY_MULTIPLY_BY_14; + } + break; + } + } + + return result; +} + + +/* +===================== +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; + int flags; + + 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_P228: + pWeapon = &g_P228; + break; + + case WEAPON_SCOUT: + pWeapon = &g_SCOUT; + break; + + case WEAPON_HEGRENADE: + pWeapon = &g_HEGrenade; + break; + + case WEAPON_XM1014: + pWeapon = &g_XM1014; + break; + + case WEAPON_C4: + pWeapon = &g_C4; + break; + + case WEAPON_MAC10: + pWeapon = &g_MAC10; + break; + + case WEAPON_AUG: + pWeapon = &g_AUG; + break; + + case WEAPON_SMOKEGRENADE: + pWeapon = &g_SmokeGrenade; + break; + + case WEAPON_ELITE: + pWeapon = &g_ELITE; + break; + + case WEAPON_FIVESEVEN: + pWeapon = &g_FiveSeven; + break; + + case WEAPON_UMP45: + pWeapon = &g_UMP45; + break; + + case WEAPON_SG550: + pWeapon = &g_SG550; + break; + + case WEAPON_GALIL: + pWeapon = &g_Galil; + break; + + case WEAPON_FAMAS: + pWeapon = &g_Famas; + break; + + case WEAPON_USP: + pWeapon = &g_USP; + break; + + case WEAPON_GLOCK18: + pWeapon = &g_GLOCK18; + break; + + case WEAPON_AWP: + pWeapon = &g_AWP; + break; + + case WEAPON_MP5N: + pWeapon = &g_MP5N; + break; + + case WEAPON_M249: + pWeapon = &g_M249; + break; + + case WEAPON_M3: + pWeapon = &g_M3; + break; + + case WEAPON_M4A1: + pWeapon = &g_M4A1; + break; + + case WEAPON_TMP: + pWeapon = &g_TMP; + break; + + case WEAPON_G3SG1: + pWeapon = &g_G3SG1; + break; + + case WEAPON_FLASHBANG: + pWeapon = &g_Flashbang; + break; + + case WEAPON_DEAGLE: + pWeapon = &g_DEAGLE; + break; + + case WEAPON_SG552: + pWeapon = &g_SG552; + break; + + case WEAPON_AK47: + pWeapon = &g_AK47; + break; + + case WEAPON_KNIFE: + pWeapon = &g_Knife; + break; + + case WEAPON_P90: + pWeapon = &g_P90; + break; + + /*case WEAPON_NONE: + break; + + case WEAPON_GLOCK: + default: + gEngfuncs.Con_Printf("VALVEWHY: Unknown Weapon %i is active.\n", from->client.m_iId ); + break;*/ + } + + // 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; + + // 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; + } + + // We are not predicting the current weapon, just bow out here. + if ( !pWeapon ) + return; + + for ( i = 0; i < MAX_WEAPONS; i++ ) + { + pCurrent = g_pWpns[ i ]; + if ( !pCurrent ) + { + continue; + } + + pfrom = &from->weapondata[ i ]; + + pCurrent->m_fInReload = pfrom->m_fInReload; + pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload; + pCurrent->m_iClip = pfrom->m_iClip; + pCurrent->m_flNextPrimaryAttack = pfrom->m_flNextPrimaryAttack; + pCurrent->m_flNextSecondaryAttack = pfrom->m_flNextSecondaryAttack; + pCurrent->m_flTimeWeaponIdle = pfrom->m_flTimeWeaponIdle; + pCurrent->m_flStartThrow = pfrom->fuser2; + pCurrent->m_flReleaseThrow = pfrom->fuser3; + pCurrent->m_iSwing = pfrom->iuser1; + pCurrent->m_iWeaponState = pfrom->m_iWeaponState; + pCurrent->m_flLastFire = pfrom->m_fAimedDamage; + pCurrent->m_iShotsFired = pfrom->m_fInZoom; + pCurrent->m_iSecondaryAmmoType = (int)from->client.vuser3[ 2 ]; + pCurrent->m_iPrimaryAmmoType = (int)from->client.vuser4[ 0 ]; + player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ] = (int)from->client.vuser4[ 1 ]; + } + + if( pWeapon ) + g_iWeaponFlags = pWeapon->m_iWeaponState; + + // 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; + g_iPlayerFlags = 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->punchangle = from->client.punchangle; + 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; + + g_vPlayerVelocity = from->client.velocity; + g_flPlayerSpeed = from->client.velocity.Length(); + + //Stores all our ammo info, so the client side weapons can use them. + player.ammo_9mm = (int)from->client.ammo_nails; + player.ammo_556nato = (int)from->client.ammo_cells; + player.ammo_buckshot = (int)from->client.ammo_shells; + player.ammo_556natobox = (int)from->client.ammo_rockets; + player.ammo_762nato = (int)from->client.vuser2.x; + player.ammo_45acp = (int)from->client.vuser2.y; + player.ammo_50ae = (int)from->client.vuser2.z; + player.ammo_338mag = (int)from->client.vuser3.x; + player.ammo_57mm = (int)from->client.vuser3.y; + player.ammo_357sig = (int)from->client.vuser3.z; + + cl_entity_t *pplayer = gEngfuncs.GetLocalPlayer(); + if( pplayer ) + { + player.pev->origin = from->client.origin; + player.pev->angles = pplayer->angles; + player.pev->v_angle = v_angles; + } + + flags = from->client.iuser3; + g_bHoldingKnife = pWeapon->m_iId == WEAPON_KNIFE; + player.m_bCanShoot = (flags & PLAYER_CAN_SHOOT) != 0; + g_iFreezeTimeOver = !(flags & PLAYER_FREEZE_TIME_OVER); + g_bInBombZone = (flags & PLAYER_IN_BOMB_ZONE) != 0; + g_bHoldingShield = (flags & PLAYER_HOLDING_SHIELD) != 0; + + // Point to current weapon object + if ( pWeapon ) + { + player.m_pActiveItem = pWeapon; + } + + // 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 && !g_iUser1 ) + { + /*if( g_bHoldingKnife && pWeapon->m_iClientWeaponState && + player.pev->button & IN_FORWARD ) + player.m_flNextAttack = 0; + else if( player.m_flNextAttack > 0 ) + { + + }*/ + if ( player.m_flNextAttack <= 0 ) + { + pWeapon->ItemPostFrame(); + } + } + + // 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 prediction 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; + to->client.punchangle = player.pev->punchangle; + + + to->client.ammo_nails = player.ammo_9mm; + to->client.ammo_cells = player.ammo_556nato; + to->client.ammo_shells = player.ammo_buckshot; + to->client.ammo_rockets = player.ammo_556natobox; + to->client.vuser2.x = player.ammo_762nato; + to->client.vuser2.y = player.ammo_45acp; + to->client.vuser2.z = player.ammo_50ae; + to->client.vuser3.x = player.ammo_338mag; + to->client.vuser3.y = player.ammo_57mm; + to->client.vuser3.z = player.ammo_357sig; + to->client.iuser3 = flags; + + + + + // 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 ) && ( HUD_GetWeapon() != to->client.m_iId )) + // Force a fixed anim down to viewmodel + HUD_SendWeaponAnim( to->client.weaponanim, to->client.m_iId, 2, 1 ); + + if (pWeapon->m_iPrimaryAmmoType < MAX_AMMO_TYPES) + { + to->client.vuser4.x = pWeapon->m_iPrimaryAmmoType; + to->client.vuser4.y = player.m_rgAmmo[ pWeapon->m_iPrimaryAmmoType ]; + } + else + { + to->client.vuser4.x = -1.0; + to->client.vuser4.y = 0; + } + + for ( i = 0; i < MAX_WEAPONS; 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_fInSpecialReload = pCurrent->m_fInSpecialReload; + pto->m_iClip = pCurrent->m_iClip; + pto->m_flNextPrimaryAttack = pCurrent->m_flNextPrimaryAttack; + pto->m_flNextSecondaryAttack = pCurrent->m_flNextSecondaryAttack; + pto->m_flTimeWeaponIdle = pCurrent->m_flTimeWeaponIdle; + pto->m_flNextReload = pCurrent->m_flNextReload; + pto->fuser2 = pCurrent->m_flStartThrow; + pto->fuser3 = pCurrent->m_flReleaseThrow; + pto->iuser1 = pCurrent->m_iSwing; + pto->m_iWeaponState = pCurrent->m_iWeaponState; + pto->m_fInZoom = pCurrent->m_iShotsFired; + pto->m_fAimedDamage = pCurrent->m_flLastFire; + + // Decrement weapon counters, server does this at same time ( during post think, after doing everything else ) + pto->m_flNextReload -= cmd->msec / 1000.0f; + pto->m_fNextAimBonus -= cmd->msec / 1000.0f; + pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0f; + pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0f; + pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0f; + + + if( pto->m_flPumpTime != -9999.0f ) + { + pto->m_flPumpTime -= cmd->msec / 1000.0f; + if( pto->m_flPumpTime < -1.0f ) + pto->m_flPumpTime = 1.0f; + } + + 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; + } + + /*if ( pto->fuser1 < -0.001 ) + { + pto->fuser1 = -0.001; + }*/ + } + + // m_flNextAttack is now part of the weapons, but is part of the player instead + to->client.m_flNextAttack -= cmd->msec / 1000.0f; + 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( local_state_t *from, local_state_t *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed ) +{ + g_runfuncs = runfuncs; + //g_curstate = from; + +//#if defined( CLIENT_WEAPONS ) + /*if ( cl_lw && cl_lw->value ) + { + HUD_WeaponsPostThink( from, to, cmd, time, random_seed ); + } + else +#endif + { + to->client.fov = g_lastFOV; + g_iWeaponFlags = from->weapondata[ from->client.m_iId ].m_iWeaponState; + g_iPlayerFlags = from->client.flags; + g_iFreezeTimeOver = !(from->client.iuser3 & PLAYER_FREEZE_TIME_OVER); + g_bInBombZone = (from->client.iuser3 & PLAYER_IN_BOMB_ZONE) != 0; + g_bHoldingShield = (from->client.iuser3 & PLAYER_HOLDING_SHIELD) != 0; + g_bGlockBurstMode = false; // will be taken from g_iWeaponFlags + }*/ + + HUD_WeaponsPostThink( from, to, cmd, time, random_seed ); + + if ( g_runfuncs ) + { + g_gaitseq = to->playerstate.gaitsequence; + g_rseq = to->playerstate.sequence; + g_clang = cmd->viewangles; + g_clorg = to->playerstate.origin; + } + + // All games can use FOV state + g_lastFOV = to->client.fov; +} diff --git a/cl_dll/demo.cpp b/cl_dll/demo.cpp index fc51591..92c5197 100644 --- a/cl_dll/demo.cpp +++ b/cl_dll/demo.cpp @@ -1,105 +1,105 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "hud.h" -#include "cl_util.h" -#include "demo.h" -#include "demo_api.h" -#include -#ifdef _WIN32 -#define DLLEXPORT __declspec( dllexport ) -#else -#define DLLEXPORT -#endif -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; - } -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#include "hud.h" +#include "cl_util.h" +#include "demo.h" +#include "demo_api.h" +#include +#ifdef _WIN32 +#define DLLEXPORT __declspec( dllexport ) +#else +#define DLLEXPORT +#endif +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; + } +} diff --git a/cl_dll/entity.cpp b/cl_dll/entity.cpp index fcd0851..b86274a 100644 --- a/cl_dll/entity.cpp +++ b/cl_dll/entity.cpp @@ -1,995 +1,995 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// Client side entity management functions - -#include - -#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" -#include "pm_shared.h" - -#ifdef _WIN32 -#define DLLEXPORT __declspec( dllexport ) -#else -#define DLLEXPORT -#endif - -void Game_AddObjects( void ); - -extern vec3_t v_origin; - -int g_iAlive = 1; -int iOnTrain[MAX_PLAYERS]; - -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: - if(ent->player && iOnTrain[ent->index]) - { - VectorCopy(ent->curstate.origin, ent->origin); - VectorCopy(ent->curstate.angles, ent->angles); - } - break; - case ET_BEAM: - case ET_TEMPENTITY: - case ET_FRAGMENTED: - default: - break; - } - // each frame every entity passes this function, so the overview hooks it to filter the overview entities - // in spectator mode: - // each frame every entity passes this function, so the overview hooks - // it to filter the overview entities - - if ( g_iUser1 ) - { - gHUD.m_Spectator.AddOverviewEntity( type, ent, modelname ); - - if ( ( g_iUser1 == OBS_IN_EYE || gHUD.m_Spectator.m_pip->value == INSET_IN_EYE ) && - ent->index == g_iUser2 ) - return 0; // don't draw the player we are following in eye - - } - - 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; - - // Duck prevention - state->iuser3 = client->iuser3; - - // Fire prevention - state->iuser4 = client->iuser4; -} - -/* -========================= -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 = g_PlayerExtraInfo[dst->number].teamnumber; - - dst->iuser1 = g_iUser1 = src->iuser1; - dst->iuser2 = g_iUser2 = src->iuser2; - dst->iuser3 = g_iUser3 = src->iuser3; - } - dst->fuser2 = src->fuser2; - if( src->number > 0 && src->number < MAX_PLAYERS ) - iOnTrain[src->number] = src->iuser4; -} - -/* -========================= -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; - ps->iuser4 = pps->iuser4; - - 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; - - // Spectating or not dead == get control over view angles. - g_iAlive = ( ppcd->iuser1 || ( pcd->deadflag == DEAD_NO ) ) ? 1 : 0; - - // Spectator - pcd->iuser1 = ppcd->iuser1; - pcd->iuser2 = ppcd->iuser2; - - // Duck prevention - pcd->iuser3 = ppcd->iuser3; - - if ( gEngfuncs.IsSpectateOnly() ) - { - // in specator mode we tell the engine who we want to spectate and how - // iuser3 is not used for duck prevention (since the spectator can't duck at all) - pcd->iuser1 = g_iUser1; // observer mode - pcd->iuser2 = g_iUser2; // first target - pcd->iuser3 = g_iUser3; // second target - - } - - // Fire prevention - pcd->iuser4 = ppcd->iuser4; - - pcd->fuser2 = ppcd->fuser2; - pcd->fuser3 = ppcd->fuser3; - - VectorCopy( ppcd->vuser1, pcd->vuser1 ); - VectorCopy( ppcd->vuser2, pcd->vuser2 ); - VectorCopy( ppcd->vuser3, pcd->vuser3 ); - VectorCopy( ppcd->vuser4, pcd->vuser4 ); - - 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(); - - //GetClientVoiceMgr()->CreateEntities(); -} - -/* -========================= -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 + (long long)(void*)pTemp ); - pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (long long)(void*)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) && !(pTemp->flags & FTENT_IGNOREGRAVITY)) - { - 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_IGNOREGRAVITY) ) - { - 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 -} - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// Client side entity management functions + +#include + +#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" +#include "pm_shared.h" + +#ifdef _WIN32 +#define DLLEXPORT __declspec( dllexport ) +#else +#define DLLEXPORT +#endif + +void Game_AddObjects( void ); + +extern vec3_t v_origin; + +int g_iAlive = 1; +int iOnTrain[MAX_PLAYERS]; + +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: + if(ent->player && iOnTrain[ent->index]) + { + VectorCopy(ent->curstate.origin, ent->origin); + VectorCopy(ent->curstate.angles, ent->angles); + } + break; + case ET_BEAM: + case ET_TEMPENTITY: + case ET_FRAGMENTED: + default: + break; + } + // each frame every entity passes this function, so the overview hooks it to filter the overview entities + // in spectator mode: + // each frame every entity passes this function, so the overview hooks + // it to filter the overview entities + + if ( g_iUser1 ) + { + gHUD.m_Spectator.AddOverviewEntity( type, ent, modelname ); + + if ( ( g_iUser1 == OBS_IN_EYE || gHUD.m_Spectator.m_pip->value == INSET_IN_EYE ) && + ent->index == g_iUser2 ) + return 0; // don't draw the player we are following in eye + + } + + 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; + + // Duck prevention + state->iuser3 = client->iuser3; + + // Fire prevention + state->iuser4 = client->iuser4; +} + +/* +========================= +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 = g_PlayerExtraInfo[dst->number].teamnumber; + + dst->iuser1 = g_iUser1 = src->iuser1; + dst->iuser2 = g_iUser2 = src->iuser2; + dst->iuser3 = g_iUser3 = src->iuser3; + } + dst->fuser2 = src->fuser2; + if( src->number > 0 && src->number < MAX_PLAYERS ) + iOnTrain[src->number] = src->iuser4; +} + +/* +========================= +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; + ps->iuser4 = pps->iuser4; + + 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; + + // Spectating or not dead == get control over view angles. + g_iAlive = ( ppcd->iuser1 || ( pcd->deadflag == DEAD_NO ) ) ? 1 : 0; + + // Spectator + pcd->iuser1 = ppcd->iuser1; + pcd->iuser2 = ppcd->iuser2; + + // Duck prevention + pcd->iuser3 = ppcd->iuser3; + + if ( gEngfuncs.IsSpectateOnly() ) + { + // in specator mode we tell the engine who we want to spectate and how + // iuser3 is not used for duck prevention (since the spectator can't duck at all) + pcd->iuser1 = g_iUser1; // observer mode + pcd->iuser2 = g_iUser2; // first target + pcd->iuser3 = g_iUser3; // second target + + } + + // Fire prevention + pcd->iuser4 = ppcd->iuser4; + + pcd->fuser2 = ppcd->fuser2; + pcd->fuser3 = ppcd->fuser3; + + VectorCopy( ppcd->vuser1, pcd->vuser1 ); + VectorCopy( ppcd->vuser2, pcd->vuser2 ); + VectorCopy( ppcd->vuser3, pcd->vuser3 ); + VectorCopy( ppcd->vuser4, pcd->vuser4 ); + + 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(); + + //GetClientVoiceMgr()->CreateEntities(); +} + +/* +========================= +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 + (long long)(void*)pTemp ); + pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (long long)(void*)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) && !(pTemp->flags & FTENT_IGNOREGRAVITY)) + { + 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_IGNOREGRAVITY) ) + { + 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 +} + diff --git a/cl_dll/ev_common.cpp b/cl_dll/ev_common.cpp index c6ea1ce..9d88816 100644 --- a/cl_dll/ev_common.cpp +++ b/cl_dll/ev_common.cpp @@ -1,204 +1,204 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// 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" -#include "pm_shared.h" - -#define IS_FIRSTPERSON_SPEC ( g_iUser1 == OBS_IN_EYE || (g_iUser1 && (gHUD.m_Spectator.m_pip->value == INSET_IN_EYE)) ) -/* -================= -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 ) -{ - // check if we are in some way in first person spec mode - if ( IS_FIRSTPERSON_SPEC ) - return (g_iUser2 == idx); - else - 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; - Vector view_ofs(0, 0, 0); - - idx = args->entindex; - - view_ofs[2] = DEFAULT_VIEWHEIGHT; - - if ( EV_IsPlayer( idx ) ) - { - // in spec mode use entity viewheigh, not own - if ( EV_IsLocal( idx ) && !IS_FIRSTPERSON_SPEC ) - { - // 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, int life ) -{ - vec3_t endpos; - VectorClear( endpos ); - endpos[1] = rotation; - gEngfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, life, 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; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// 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" +#include "pm_shared.h" + +#define IS_FIRSTPERSON_SPEC ( g_iUser1 == OBS_IN_EYE || (g_iUser1 && (gHUD.m_Spectator.m_pip->value == INSET_IN_EYE)) ) +/* +================= +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 ) +{ + // check if we are in some way in first person spec mode + if ( IS_FIRSTPERSON_SPEC ) + return (g_iUser2 == idx); + else + 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; + Vector view_ofs(0, 0, 0); + + idx = args->entindex; + + view_ofs[2] = DEFAULT_VIEWHEIGHT; + + if ( EV_IsPlayer( idx ) ) + { + // in spec mode use entity viewheigh, not own + if ( EV_IsLocal( idx ) && !IS_FIRSTPERSON_SPEC ) + { + // 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, int life ) +{ + vec3_t endpos; + VectorClear( endpos ); + endpos[1] = rotation; + gEngfuncs.pEfxAPI->R_TempModel( origin, velocity, endpos, life, 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; +} diff --git a/cl_dll/ev_hldm.cpp b/cl_dll/ev_hldm.cpp index 65a53ed..be0001d 100644 --- a/cl_dll/ev_hldm.cpp +++ b/cl_dll/ev_hldm.cpp @@ -1,1707 +1,1707 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "entity_state.h" -#include "cl_entity.h" -#include "entity_types.h" -#include "usercmd.h" -#include "pm_defs.h" -#include "pm_materials.h" - -#include "eventscripts.h" -#include "ev_hldm.h" - -#include "r_efx.h" -#include "event_api.h" -#include "event_args.h" -#include "in_defs.h" - -#include - -#include "r_studioint.h" -#include "com_model.h" - -extern engine_studio_api_t IEngineStudio; - -static int tracerCount[ 32 ]; - -extern "C" char PM_FindTextureType( char *name ); - -void V_PunchAxis( int axis, float punch ); -void VectorAngles( const float *forward, float *angles ); - -extern cvar_t *cl_lw; - -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_FireMP52( 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_Crowbar( struct event_args_s *args ); -void EV_FireCrossbow( struct event_args_s *args ); -void EV_FireCrossbow2( struct event_args_s *args ); -void EV_FireRpg( struct event_args_s *args ); -void EV_EgonFire( struct event_args_s *args ); -void EV_EgonStop( struct event_args_s *args ); -void EV_HornetGunFire( struct event_args_s *args ); -void EV_TripmineFire( struct event_args_s *args ); -void EV_SnarkFire( struct event_args_s *args ); -void EV_Dummy( struct event_args_s *args ); - -void EV_TrainPitchAdjust( struct event_args_s *args ); -} - -#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 ) -#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 ) -#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 ) -#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 ) -#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 ) -#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 ) -#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 ) -#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 ) -#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 ) -#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 ) -#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 ) -#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 ) - -// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the -// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture. -// returns volume of strike instrument (crowbar) to play -float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType ) -{ - // hit the world, try to play sound based on texture material type - char chTextureType = CHAR_TEX_CONCRETE; - float fvol; - float fvolbar; - char *rgsz[4]; - int cnt; - float fattn = ATTN_NORM; - int entity; - char *pTextureName; - char texname[ 64 ]; - char szbuffer[ 64 ]; - - entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr ); - - // FIXME check if playtexture sounds movevar is set - // - - chTextureType = 0; - - // Player - if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) - { - // hit body - chTextureType = CHAR_TEX_FLESH; - } - else if ( entity == 0 ) - { - // get texture from entity or world (world is ent(0)) - pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); - - if ( pTextureName ) - { - strcpy( texname, pTextureName ); - pTextureName = texname; - - // strip leading '-0' or '+0~' or '{' or '!' - if (*pTextureName == '-' || *pTextureName == '+') - { - pTextureName += 2; - } - - if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') - { - pTextureName++; - } - - // '}}' - strcpy( szbuffer, pTextureName ); - szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0; - - // get texture type - chTextureType = PM_FindTextureType( szbuffer ); - } - } - - switch (chTextureType) - { - default: - case CHAR_TEX_CONCRETE: fvol = 0.9; fvolbar = 0.6; - rgsz[0] = "player/pl_step1.wav"; - rgsz[1] = "player/pl_step2.wav"; - cnt = 2; - break; - case CHAR_TEX_METAL: fvol = 0.9; fvolbar = 0.3; - rgsz[0] = "player/pl_metal1.wav"; - rgsz[1] = "player/pl_metal2.wav"; - cnt = 2; - break; - case CHAR_TEX_DIRT: fvol = 0.9; fvolbar = 0.1; - rgsz[0] = "player/pl_dirt1.wav"; - rgsz[1] = "player/pl_dirt2.wav"; - rgsz[2] = "player/pl_dirt3.wav"; - cnt = 3; - break; - case CHAR_TEX_VENT: fvol = 0.5; fvolbar = 0.3; - rgsz[0] = "player/pl_duct1.wav"; - rgsz[1] = "player/pl_duct1.wav"; - cnt = 2; - break; - case CHAR_TEX_GRATE: fvol = 0.9; fvolbar = 0.5; - rgsz[0] = "player/pl_grate1.wav"; - rgsz[1] = "player/pl_grate4.wav"; - cnt = 2; - break; - case CHAR_TEX_TILE: fvol = 0.8; fvolbar = 0.2; - rgsz[0] = "player/pl_tile1.wav"; - rgsz[1] = "player/pl_tile3.wav"; - rgsz[2] = "player/pl_tile2.wav"; - rgsz[3] = "player/pl_tile4.wav"; - cnt = 4; - break; - case CHAR_TEX_SLOSH: fvol = 0.9; fvolbar = 0.0; - rgsz[0] = "player/pl_slosh1.wav"; - rgsz[1] = "player/pl_slosh3.wav"; - rgsz[2] = "player/pl_slosh2.wav"; - rgsz[3] = "player/pl_slosh4.wav"; - cnt = 4; - break; - case CHAR_TEX_WOOD: fvol = 0.9; fvolbar = 0.2; - rgsz[0] = "debris/wood1.wav"; - rgsz[1] = "debris/wood2.wav"; - rgsz[2] = "debris/wood3.wav"; - cnt = 3; - break; - case CHAR_TEX_GLASS: - case CHAR_TEX_COMPUTER: - fvol = 0.8; fvolbar = 0.2; - rgsz[0] = "debris/glass1.wav"; - rgsz[1] = "debris/glass2.wav"; - rgsz[2] = "debris/glass3.wav"; - cnt = 3; - break; - case CHAR_TEX_FLESH: - if (iBulletType == BULLET_PLAYER_CROWBAR) - return 0.0; // crowbar already makes this sound - fvol = 1.0; fvolbar = 0.2; - rgsz[0] = "weapons/bullet_hit1.wav"; - rgsz[1] = "weapons/bullet_hit2.wav"; - fattn = 1.0; - cnt = 2; - break; - } - - // play material hit sound - gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) ); - return fvolbar; -} - -char *EV_HLDM_DamageDecal( physent_t *pe ) -{ - static char decalname[ 32 ]; - int idx; - - if ( pe->classnumber == 1 ) - { - idx = gEngfuncs.pfnRandomLong( 0, 2 ); - sprintf( decalname, "{break%i", idx + 1 ); - } - else if ( pe->rendermode != kRenderNormal ) - { - sprintf( decalname, "{bproof1" ); - } - else - { - idx = gEngfuncs.pfnRandomLong( 0, 4 ); - sprintf( decalname, "{shot%i", idx + 1 ); - } - return decalname; -} - -void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName ) -{ - int iRand; - physent_t *pe; - - gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos ); - - iRand = gEngfuncs.pfnRandomLong(0,0x7FFF); - if ( iRand < (0x7fff/2) )// not every bullet makes a sound. - { - switch( iRand % 5) - { - case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - } - } - - pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); - - // Only decal brush models such as the world etc. - if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) ) - { - if ( CVAR_GET_FLOAT( "r_decals" ) ) - { - gEngfuncs.pEfxAPI->R_DecalShoot( - gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ), - gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 ); - } - } -} - -void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType ) -{ - physent_t *pe; - - pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); - - if ( pe && pe->solid == SOLID_BSP ) - { - switch( iBulletType ) - { - case BULLET_PLAYER_9MM: - case BULLET_MONSTER_9MM: - case BULLET_PLAYER_MP5: - case BULLET_MONSTER_MP5: - case BULLET_PLAYER_BUCKSHOT: - case BULLET_PLAYER_357: - default: - // smoke and decal - EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) ); - break; - } - } -} - -int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount ) -{ - int tracer = 0; - int i; - qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false; - - if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 ) - { - vec3_t vecTracerSrc; - - if ( player ) - { - vec3_t offset( 0, 0, -4 ); - - // adjust tracer position for player - for ( i = 0; i < 3; i++ ) - { - vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16; - } - } - else - { - VectorCopy( vecSrc, vecTracerSrc ); - } - - if ( iTracerFreq != 1 ) // guns that always trace also always decal - tracer = 1; - - switch( iBulletType ) - { - case BULLET_PLAYER_MP5: - case BULLET_MONSTER_MP5: - case BULLET_MONSTER_9MM: - case BULLET_MONSTER_12MM: - default: - EV_CreateTracer( vecTracerSrc, end ); - break; - } - } - - return tracer; -} - - -/* -================ -FireBullets - -Go to the trouble of combining multiple pellets into a single damage call. -================ -*/ -void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY ) -{ - int i; - pmtrace_t tr; - int iShot; - int tracer; - - for ( iShot = 1; iShot <= cShots; iShot++ ) - { - vec3_t vecDir, vecEnd; - - float x, y, z; - //We randomize for the Shotgun. - if ( iBulletType == BULLET_PLAYER_BUCKSHOT ) - { - do { - x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); - y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); - z = x*x+y*y; - } while (z > 1); - - for ( i = 0 ; i < 3; i++ ) - { - vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[ i ] + y * flSpreadY * up [ i ]; - vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ]; - } - }//But other guns already have their spread randomized in the synched spread. - else - { - - for ( i = 0 ; i < 3; i++ ) - { - vecDir[i] = vecDirShooting[i] + flSpreadX * right[ i ] + flSpreadY * up [ i ]; - vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ]; - } - } - - 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 ( idx - 1 ); - - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); - - tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); - - // do damage, paint decals - if ( tr.fraction != 1.0 ) - { - switch(iBulletType) - { - default: - case BULLET_PLAYER_9MM: - - EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); - EV_HLDM_DecalGunshot( &tr, iBulletType ); - - break; - case BULLET_PLAYER_MP5: - - if ( !tracer ) - { - EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); - EV_HLDM_DecalGunshot( &tr, iBulletType ); - } - break; - case BULLET_PLAYER_BUCKSHOT: - - EV_HLDM_DecalGunshot( &tr, iBulletType ); - - break; - case BULLET_PLAYER_357: - - EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); - EV_HLDM_DecalGunshot( &tr, iBulletType ); - - break; - - } - } - - gEngfuncs.pEventAPI->EV_PopPMStates(); - } -} - -//====================== -// GLOCK START -//====================== -void EV_FireGlock1( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - int empty; - - vec3_t ShellVelocity; - vec3_t ShellOrigin; - int shell; - vec3_t vecSrc, vecAiming; - vec3_t up, right, forward; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - empty = args->bparam1; - AngleVectors( angles, forward, right, up ); - - shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell - - if ( EV_IsLocal( idx ) ) - { - EV_MuzzleFlash(); - gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, 2 ); - - V_PunchAxis( 0, -2.0 ); - } - - EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); - - EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL ); - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) ); - - EV_GetGunPosition( args, vecSrc, origin ); - - VectorCopy( forward, vecAiming ); - - EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, 0, args->fparam1, args->fparam2 ); -} - -void EV_FireGlock2( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - vec3_t ShellVelocity; - vec3_t ShellOrigin; - int shell; - vec3_t vecSrc, vecAiming; - vec3_t vecSpread; - vec3_t up, right, forward; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - AngleVectors( angles, forward, right, up ); - - shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell - - if ( EV_IsLocal( idx ) ) - { - // Add muzzle flash to current weapon model - EV_MuzzleFlash(); - gEngfuncs.pEventAPI->EV_WeaponAnimation( GLOCK_SHOOT, 2 ); - - V_PunchAxis( 0, -2.0 ); - } - - EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); - - EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL ); - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) ); - - EV_GetGunPosition( args, vecSrc, origin ); - - VectorCopy( forward, vecAiming ); - - EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, &tracerCount[idx-1], args->fparam1, args->fparam2 ); - -} -//====================== -// GLOCK END -//====================== - -//====================== -// SHOTGUN START -//====================== -void EV_FireShotGunDouble( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - int j; - vec3_t ShellVelocity; - vec3_t ShellOrigin; - int shell; - vec3_t vecSrc, vecAiming; - vec3_t vecSpread; - vec3_t up, right, forward; - float flSpread = 0.01; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - AngleVectors( angles, forward, right, up ); - - shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell - - if ( EV_IsLocal( idx ) ) - { - // Add muzzle flash to current weapon model - EV_MuzzleFlash(); - gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE2, 2 ); - V_PunchAxis( 0, -10.0 ); - } - - for ( j = 0; j < 2; j++ ) - { - EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 ); - - EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL ); - } - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/dbarrel1.wav", gEngfuncs.pfnRandomFloat(0.98, 1.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) ); - - EV_GetGunPosition( args, vecSrc, origin ); - VectorCopy( forward, vecAiming ); - - if ( gEngfuncs.GetMaxClients() > 1 ) - { - EV_HLDM_FireBullets( idx, forward, right, up, 8, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.17365, 0.04362 ); - } - else - { - EV_HLDM_FireBullets( idx, forward, right, up, 12, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 ); - } -} - -void EV_FireShotGunSingle( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - vec3_t ShellVelocity; - vec3_t ShellOrigin; - int shell; - vec3_t vecSrc, vecAiming; - vec3_t vecSpread; - vec3_t up, right, forward; - float flSpread = 0.01; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - AngleVectors( angles, forward, right, up ); - - shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell - - if ( EV_IsLocal( idx ) ) - { - // Add muzzle flash to current weapon model - EV_MuzzleFlash(); - gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE, 2 ); - - V_PunchAxis( 0, -5.0 ); - } - - EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 ); - - EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL ); - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sbarrel1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) ); - - EV_GetGunPosition( args, vecSrc, origin ); - VectorCopy( forward, vecAiming ); - - if ( gEngfuncs.GetMaxClients() > 1 ) - { - EV_HLDM_FireBullets( idx, forward, right, up, 4, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.04362 ); - } - else - { - EV_HLDM_FireBullets( idx, forward, right, up, 6, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 ); - } -} -//====================== -// SHOTGUN END -//====================== - -//====================== -// MP5 START -//====================== -void EV_FireMP5( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - vec3_t ShellVelocity; - vec3_t ShellOrigin; - int shell; - vec3_t vecSrc, vecAiming; - vec3_t up, right, forward; - float flSpread = 0.01; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - AngleVectors( angles, forward, right, up ); - - shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell - - if ( EV_IsLocal( idx ) ) - { - // Add muzzle flash to current weapon model - EV_MuzzleFlash(); - gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2 ); - - V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) ); - } - - EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); - - EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL ); - - switch( gEngfuncs.pfnRandomLong( 0, 1 ) ) - { - case 0: - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); - break; - case 1: - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); - break; - } - - EV_GetGunPosition( args, vecSrc, origin ); - VectorCopy( forward, vecAiming ); - - if ( gEngfuncs.GetMaxClients() > 1 ) - { - EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 ); - } - else - { - EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 ); - } -} - -// We only predict the animation and sound -// The grenade is still launched from the server. -void EV_FireMP52( event_args_t *args ) -{ - int idx; - vec3_t origin; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - - if ( EV_IsLocal( idx ) ) - { - gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_LAUNCH, 2 ); - V_PunchAxis( 0, -10 ); - } - - switch( gEngfuncs.pfnRandomLong( 0, 1 ) ) - { - case 0: - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); - break; - case 1: - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); - break; - } -} -//====================== -// MP5 END -//====================== - -//====================== -// PHYTON START -// ( .357 ) -//====================== -void EV_FirePython( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - vec3_t vecSrc, vecAiming; - vec3_t up, right, forward; - float flSpread = 0.01; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - AngleVectors( angles, forward, right, up ); - - if ( EV_IsLocal( idx ) ) - { - // Python uses different body in multiplayer versus single player - int multiplayer = gEngfuncs.GetMaxClients() == 1 ? 0 : 1; - - // Add muzzle flash to current weapon model - EV_MuzzleFlash(); - gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE1, multiplayer ? 1 : 0 ); - - V_PunchAxis( 0, -10.0 ); - } - - switch( gEngfuncs.pfnRandomLong( 0, 1 ) ) - { - case 0: - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM ); - break; - case 1: - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot2.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM ); - break; - } - - EV_GetGunPosition( args, vecSrc, origin ); - - VectorCopy( forward, vecAiming ); - - EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_357, 0, 0, args->fparam1, args->fparam2 ); -} -//====================== -// PHYTON END -// ( .357 ) -//====================== - -//====================== -// GAUSS START -//====================== -#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch - -void EV_SpinGauss( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - int iSoundState = 0; - - int pitch; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - pitch = args->iparam1; - - iSoundState = args->bparam1 ? SND_CHANGE_PITCH : 0; - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "ambience/pulsemachine.wav", 1.0, ATTN_NORM, iSoundState, pitch ); -} - -/* -============================== -EV_StopPreviousGauss - -============================== -*/ -void EV_StopPreviousGauss( int idx ) -{ - // Make sure we don't have a gauss spin event in the queue for this guy - gEngfuncs.pEventAPI->EV_KillEvents( idx, "events/gaussspin.sc" ); - gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_WEAPON, "ambience/pulsemachine.wav" ); -} - -extern float g_flApplyVel; - -void EV_FireGauss( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - float flDamage = args->fparam1; - int primaryfire = args->bparam1; - - int m_fPrimaryFire = args->bparam1; - int m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME; - vec3_t vecSrc; - vec3_t vecDest; - edict_t *pentIgnore; - pmtrace_t tr, beam_tr; - float flMaxFrac = 1.0; - int nTotal = 0; - int fHasPunched = 0; - int fFirstBeam = 1; - int nMaxHits = 10; - physent_t *pEntity; - int m_iBeam, m_iGlow, m_iBalls; - vec3_t up, right, forward; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - VectorCopy( args->velocity, velocity ); - - if ( args->bparam2 ) - { - EV_StopPreviousGauss( idx ); - return; - } - -// Con_Printf( "Firing gauss with %f\n", flDamage ); - EV_GetGunPosition( args, vecSrc, origin ); - - m_iBeam = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/smoke.spr" ); - m_iBalls = m_iGlow = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/hotglow.spr" ); - - AngleVectors( angles, forward, right, up ); - - VectorMA( vecSrc, 8192, forward, vecDest ); - - if ( EV_IsLocal( idx ) ) - { - V_PunchAxis( 0, -2.0 ); - gEngfuncs.pEventAPI->EV_WeaponAnimation( GAUSS_FIRE2, 2 ); - - if ( m_fPrimaryFire == false ) - g_flApplyVel = flDamage; - - } - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/gauss2.wav", 0.5 + flDamage * (1.0 / 400.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) ); - - while (flDamage > 10 && nMaxHits > 0) - { - nMaxHits--; - - 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 ( idx - 1 ); - - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr ); - - gEngfuncs.pEventAPI->EV_PopPMStates(); - - if ( tr.allsolid ) - break; - - if (fFirstBeam) - { - if ( EV_IsLocal( idx ) ) - { - // Add muzzle flash to current weapon model - EV_MuzzleFlash(); - } - fFirstBeam = 0; - - gEngfuncs.pEfxAPI->R_BeamEntPoint( - idx | 0x1000, - tr.endpos, - m_iBeam, - 0.1, - m_fPrimaryFire ? 1.0 : 2.5, - 0.0, - m_fPrimaryFire ? 128.0 : flDamage, - 0, - 0, - 0, - m_fPrimaryFire ? 255 : 255, - m_fPrimaryFire ? 128 : 255, - m_fPrimaryFire ? 0 : 255 - ); - } - else - { - gEngfuncs.pEfxAPI->R_BeamPoints( vecSrc, - tr.endpos, - m_iBeam, - 0.1, - m_fPrimaryFire ? 1.0 : 2.5, - 0.0, - m_fPrimaryFire ? 128.0 : flDamage, - 0, - 0, - 0, - m_fPrimaryFire ? 255 : 255, - m_fPrimaryFire ? 128 : 255, - m_fPrimaryFire ? 0 : 255 - ); - } - - pEntity = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent ); - if ( pEntity == NULL ) - break; - - if ( pEntity->solid == SOLID_BSP ) - { - float n; - - pentIgnore = NULL; - - n = -DotProduct( tr.plane.normal, forward ); - - if (n < 0.5) // 60 degrees - { - // ALERT( at_console, "reflect %f\n", n ); - // reflect - vec3_t r; - - VectorMA( forward, 2.0 * n, tr.plane.normal, r ); - - flMaxFrac = flMaxFrac - tr.fraction; - - VectorCopy( r, forward ); - - VectorMA( tr.endpos, 8.0, forward, vecSrc ); - VectorMA( vecSrc, 8192.0, forward, vecDest ); - - gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT ); - - vec3_t fwd; - VectorAdd( tr.endpos, tr.plane.normal, fwd ); - - gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, - 255, 100 ); - - // lose energy - if ( n == 0 ) - { - n = 0.1; - } - - flDamage = flDamage * (1 - n); - - } - else - { - // tunnel - EV_HLDM_DecalGunshot( &tr, BULLET_MONSTER_12MM ); - - gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT ); - - // limit it to one hole punch - if (fHasPunched) - { - break; - } - fHasPunched = 1; - - // try punching through wall if secondary attack (primary is incapable of breaking through) - if ( !m_fPrimaryFire ) - { - vec3_t start; - - VectorMA( tr.endpos, 8.0, forward, start ); - - // Store off the old count - gEngfuncs.pEventAPI->EV_PushPMStates(); - - // Now add in all of the players. - gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); - - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr ); - - if ( !beam_tr.allsolid ) - { - vec3_t delta; - float n; - - // trace backwards to find exit point - - gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr ); - - VectorSubtract( beam_tr.endpos, tr.endpos, delta ); - - n = Length( delta ); - - if (n < flDamage) - { - if (n == 0) - n = 1; - flDamage -= n; - - // absorption balls - { - vec3_t fwd; - VectorSubtract( tr.endpos, forward, fwd ); - gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, - 255, 100 ); - } - - //////////////////////////////////// WHAT TO DO HERE - // CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 ); - - EV_HLDM_DecalGunshot( &beam_tr, BULLET_MONSTER_12MM ); - - gEngfuncs.pEfxAPI->R_TempSprite( beam_tr.endpos, vec3_origin, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT ); - - // balls - { - vec3_t fwd; - VectorSubtract( beam_tr.endpos, forward, fwd ); - gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, beam_tr.endpos, fwd, m_iBalls, (int)(flDamage * 0.3), 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 200, - 255, 40 ); - } - - VectorAdd( beam_tr.endpos, forward, vecSrc ); - } - } - else - { - flDamage = 0; - } - - gEngfuncs.pEventAPI->EV_PopPMStates(); - } - else - { - if ( m_fPrimaryFire ) - { - // slug doesn't punch through ever with primary - // fire, so leave a little glowy bit and make some balls - gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT ); - - { - vec3_t fwd; - VectorAdd( tr.endpos, tr.plane.normal, fwd ); - gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 8, 0.6, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, - 255, 200 ); - } - } - - flDamage = 0; - } - } - } - else - { - VectorAdd( tr.endpos, forward, vecSrc ); - } - } -} -//====================== -// GAUSS END -//====================== - -//====================== -// CROWBAR START -//====================== - -enum crowbar_e { - CROWBAR_IDLE = 0, - CROWBAR_DRAW, - CROWBAR_HOLSTER, - CROWBAR_ATTACK1HIT, - CROWBAR_ATTACK1MISS, - CROWBAR_ATTACK2MISS, - CROWBAR_ATTACK2HIT, - CROWBAR_ATTACK3MISS, - CROWBAR_ATTACK3HIT -}; - -int g_iSwing; - -//Only predict the miss sounds, hit sounds are still played -//server side, so players don't get the wrong idea. -void EV_Crowbar( event_args_t *args ) -{ - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - - //Play Swing sound - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM); - - if ( EV_IsLocal( idx ) ) - { - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK1MISS, 1 ); - - switch( (g_iSwing++) % 3 ) - { - case 0: - gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK1MISS, 1 ); break; - case 1: - gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK2MISS, 1 ); break; - case 2: - gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK3MISS, 1 ); break; - } - } -} -//====================== -// CROWBAR END -//====================== - -//====================== -// CROSSBOW START -//====================== -enum crossbow_e { - CROSSBOW_IDLE1 = 0, // full - CROSSBOW_IDLE2, // empty - CROSSBOW_FIDGET1, // full - CROSSBOW_FIDGET2, // empty - CROSSBOW_FIRE1, // full - CROSSBOW_FIRE2, // reload - CROSSBOW_FIRE3, // empty - CROSSBOW_RELOAD, // from empty - CROSSBOW_DRAW1, // full - CROSSBOW_DRAW2, // empty - CROSSBOW_HOLSTER1, // full - CROSSBOW_HOLSTER2, // empty -}; - -//===================== -// EV_BoltCallback -// This function is used to correct the origin and angles -// of the bolt, so it looks like it's stuck on the wall. -//===================== -void EV_BoltCallback ( struct tempent_s *ent, float frametime, float currenttime ) -{ - ent->entity.origin = ent->entity.baseline.vuser1; - ent->entity.angles = ent->entity.baseline.vuser2; -} - -void EV_FireCrossbow2( event_args_t *args ) -{ - vec3_t vecSrc, vecEnd; - vec3_t up, right, forward; - pmtrace_t tr; - - int idx; - vec3_t origin; - vec3_t angles; - vec3_t velocity; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - - VectorCopy( args->velocity, velocity ); - - AngleVectors( angles, forward, right, up ); - - EV_GetGunPosition( args, vecSrc, origin ); - - VectorMA( vecSrc, 8192, forward, vecEnd ); - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); - - if ( EV_IsLocal( idx ) ) - { - if ( args->iparam1 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); - else if ( args->iparam2 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 ); - } - - // Store off the old count - gEngfuncs.pEventAPI->EV_PushPMStates(); - - // Now add in all of the players. - gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); - - //We hit something - if ( tr.fraction < 1.0 ) - { - physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent ); - - //Not the world, let's assume we hit something organic ( dog, cat, uncle joe, etc ). - if ( pe->solid != SOLID_BSP ) - { - switch( gEngfuncs.pfnRandomLong(0,1) ) - { - case 0: - gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break; - case 1: - gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break; - } - } - //Stick to world but don't stick to glass, it might break and leave the bolt floating. It can still stick to other non-transparent breakables though. - else if ( pe->rendermode == kRenderNormal ) - { - gEngfuncs.pEventAPI->EV_PlaySound( 0, tr.endpos, CHAN_BODY, "weapons/xbow_hit1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, PITCH_NORM ); - - //Not underwater, do some sparks... - if ( gEngfuncs.PM_PointContents( tr.endpos, NULL ) != CONTENTS_WATER) - gEngfuncs.pEfxAPI->R_SparkShower( tr.endpos ); - - vec3_t vBoltAngles; - int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/crossbow_bolt.mdl" ); - - VectorAngles( forward, vBoltAngles ); - - TEMPENTITY *bolt = gEngfuncs.pEfxAPI->R_TempModel( tr.endpos - forward * 10, Vector( 0, 0, 0), vBoltAngles , 5, iModelIndex, TE_BOUNCE_NULL ); - - if ( bolt ) - { - bolt->flags |= ( FTENT_CLIENTCUSTOM ); //So it calls the callback function. - bolt->entity.baseline.vuser1 = tr.endpos - forward * 10; // Pull out a little bit - bolt->entity.baseline.vuser2 = vBoltAngles; //Look forward! - bolt->callback = EV_BoltCallback; //So we can set the angles and origin back. (Stick the bolt to the wall) - } - } - } - - gEngfuncs.pEventAPI->EV_PopPMStates(); -} - -//TODO: Fully predict the fliying bolt. -void EV_FireCrossbow( event_args_t *args ) -{ - int idx; - vec3_t origin; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); - - //Only play the weapon anims if I shot it. - if ( EV_IsLocal( idx ) ) - { - if ( args->iparam1 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); - else if ( args->iparam2 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 ); - - V_PunchAxis( 0, -2.0 ); - } -} -//====================== -// CROSSBOW END -//====================== - -//====================== -// RPG START -//====================== -enum rpg_e { - RPG_IDLE = 0, - RPG_FIDGET, - RPG_RELOAD, // to reload - RPG_FIRE2, // to empty - RPG_HOLSTER1, // loaded - RPG_DRAW1, // loaded - RPG_HOLSTER2, // unloaded - RPG_DRAW_UL, // unloaded - RPG_IDLE_UL, // unloaded idle - RPG_FIDGET_UL, // unloaded fidget -}; - -void EV_FireRpg( event_args_t *args ) -{ - int idx; - vec3_t origin; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM ); - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM ); - - //Only play the weapon anims if I shot it. - if ( EV_IsLocal( idx ) ) - { - gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 ); - - V_PunchAxis( 0, -5.0 ); - } -} -//====================== -// RPG END -//====================== - -//====================== -// EGON END -//====================== -enum egon_e { - EGON_IDLE1 = 0, - EGON_FIDGET1, - EGON_ALTFIREON, - EGON_ALTFIRECYCLE, - EGON_ALTFIREOFF, - EGON_FIRE1, - EGON_FIRE2, - EGON_FIRE3, - EGON_FIRE4, - EGON_DRAW, - EGON_HOLSTER -}; - -int g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 }; -int g_fireAnims2[] = { EGON_ALTFIRECYCLE }; - -enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE }; -enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE}; - -#define EGON_PRIMARY_VOLUME 450 -#define EGON_BEAM_SPRITE "sprites/xbeam1.spr" -#define EGON_FLARE_SPRITE "sprites/XSpark1.spr" -#define EGON_SOUND_OFF "weapons/egon_off1.wav" -#define EGON_SOUND_RUN "weapons/egon_run3.wav" -#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav" - -#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) - -BEAM *pBeam; -BEAM *pBeam2; - -void EV_EgonFire( event_args_t *args ) -{ - int idx, iFireState, iFireMode; - vec3_t origin; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - iFireState = args->iparam1; - iFireMode = args->iparam2; - int iStartup = args->bparam1; - - - if ( iStartup ) - { - if ( iFireMode == FIRE_WIDE ) - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 ); - else - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 ); - } - else - { - if ( iFireMode == FIRE_WIDE ) - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 ); - else - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 ); - } - - //Only play the weapon anims if I shot it. - if ( EV_IsLocal( idx ) ) - gEngfuncs.pEventAPI->EV_WeaponAnimation ( g_fireAnims1[ gEngfuncs.pfnRandomLong( 0, 3 ) ], 1 ); - - if ( iStartup == 1 && EV_IsLocal( idx ) && !pBeam && !pBeam2 && cl_lw->value ) //Adrian: Added the cl_lw check for those lital people that hate weapon prediction. - { - vec3_t vecSrc, vecEnd, origin, angles, forward, right, up; - pmtrace_t tr; - - cl_entity_t *pl = gEngfuncs.GetEntityByIndex( idx ); - - if ( pl ) - { - VectorCopy( gHUD.m_vecAngles, angles ); - - AngleVectors( angles, forward, right, up ); - - EV_GetGunPosition( args, vecSrc, pl->origin ); - - VectorMA( vecSrc, 2048, forward, vecEnd ); - - 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 ( idx - 1 ); - - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); - - gEngfuncs.pEventAPI->EV_PopPMStates(); - - int iBeamModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE ); - - float r = 50.0f; - float g = 50.0f; - float b = 125.0f; - - if ( IEngineStudio.IsHardware() ) - { - r /= 100.0f; - g /= 100.0f; - } - - - pBeam = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b ); - - if ( pBeam ) - pBeam->flags |= ( FBEAM_SINENOISE ); - - pBeam2 = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b ); - } - } -} - -void EV_EgonStop( event_args_t *args ) -{ - int idx; - vec3_t origin; - - idx = args->entindex; - VectorCopy ( args->origin, origin ); - - gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN ); - - if ( args->iparam1 ) - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 ); - - if ( EV_IsLocal( idx ) ) - { - if ( pBeam ) - { - pBeam->die = 0.0; - pBeam = NULL; - } - - - if ( pBeam2 ) - { - pBeam2->die = 0.0; - pBeam2 = NULL; - } - } -} -//====================== -// EGON END -//====================== - -//====================== -// HORNET START -//====================== -enum hgun_e { - HGUN_IDLE1 = 0, - HGUN_FIDGETSWAY, - HGUN_FIDGETSHAKE, - HGUN_DOWN, - HGUN_UP, - HGUN_SHOOT -}; - -void EV_HornetGunFire( event_args_t *args ) -{ - int idx, iFireMode; - vec3_t origin, angles, vecSrc, forward, right, up; - - idx = args->entindex; - VectorCopy( args->origin, origin ); - VectorCopy( args->angles, angles ); - iFireMode = args->iparam1; - - //Only play the weapon anims if I shot it. - if ( EV_IsLocal( idx ) ) - { - V_PunchAxis( 0, gEngfuncs.pfnRandomLong ( 0, 2 ) ); - gEngfuncs.pEventAPI->EV_WeaponAnimation ( HGUN_SHOOT, 1 ); - } - - switch ( gEngfuncs.pfnRandomLong ( 0 , 2 ) ) - { - case 0: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM, 0, 100 ); break; - case 1: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM, 0, 100 ); break; - case 2: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM, 0, 100 ); break; - } -} -//====================== -// HORNET END -//====================== - -//====================== -// TRIPMINE START -//====================== -enum tripmine_e { - TRIPMINE_IDLE1 = 0, - TRIPMINE_IDLE2, - TRIPMINE_ARM1, - TRIPMINE_ARM2, - TRIPMINE_FIDGET, - TRIPMINE_HOLSTER, - TRIPMINE_DRAW, - TRIPMINE_WORLD, - TRIPMINE_GROUND, -}; - -//We only check if it's possible to put a trip mine -//and if it is, then we play the animation. Server still places it. -void EV_TripmineFire( event_args_t *args ) -{ - int idx; - vec3_t vecSrc, angles, view_ofs, forward; - pmtrace_t tr; - - idx = args->entindex; - VectorCopy( args->origin, vecSrc ); - VectorCopy( args->angles, angles ); - - AngleVectors ( angles, forward, NULL, NULL ); - - if ( !EV_IsLocal ( idx ) ) - return; - - // Grab predicted result for local player - gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs ); - - vecSrc = vecSrc + view_ofs; - - // Store off the old count - gEngfuncs.pEventAPI->EV_PushPMStates(); - - // Now add in all of the players. - gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecSrc + forward * 128, PM_NORMAL, -1, &tr ); - - //Hit something solid - if ( tr.fraction < 1.0 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation ( TRIPMINE_DRAW, 0 ); - - gEngfuncs.pEventAPI->EV_PopPMStates(); -} -//====================== -// TRIPMINE END -//====================== - -//====================== -// SQUEAK START -//====================== -enum squeak_e { - SQUEAK_IDLE1 = 0, - SQUEAK_FIDGETFIT, - SQUEAK_FIDGETNIP, - SQUEAK_DOWN, - SQUEAK_UP, - SQUEAK_THROW -}; - -#define VEC_HULL_MIN Vector(-16, -16, -36) -#define VEC_DUCK_HULL_MIN Vector(-16, -16, -18 ) - -void EV_SnarkFire( event_args_t *args ) -{ - int idx; - vec3_t vecSrc, angles, view_ofs, forward; - pmtrace_t tr; - - idx = args->entindex; - VectorCopy( args->origin, vecSrc ); - VectorCopy( args->angles, angles ); - - AngleVectors ( angles, forward, NULL, NULL ); - - if ( !EV_IsLocal ( idx ) ) - return; - - if ( args->ducking ) - vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN ); - - // Store off the old count - gEngfuncs.pEventAPI->EV_PushPMStates(); - - // Now add in all of the players. - gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc + forward * 20, vecSrc + forward * 64, PM_NORMAL, -1, &tr ); - - //Find space to drop the thing. - if ( tr.allsolid == 0 && tr.startsolid == 0 && tr.fraction > 0.25 ) - gEngfuncs.pEventAPI->EV_WeaponAnimation ( SQUEAK_THROW, 0 ); - - gEngfuncs.pEventAPI->EV_PopPMStates(); -} -//====================== -// SQUEAK END -//====================== - -void EV_TrainPitchAdjust( event_args_t *args ) -{ - int idx; - vec3_t origin; - - unsigned short us_params; - int noise; - float m_flVolume; - int pitch; - int stop; - - char sz[ 256 ]; - - idx = args->entindex; - - VectorCopy( args->origin, origin ); - - us_params = (unsigned short)args->iparam1; - stop = args->bparam1; - - m_flVolume = (float)(us_params & 0x003f)/40.0; - noise = (int)(((us_params) >> 12 ) & 0x0007); - pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) ); - - switch ( noise ) - { - case 1: strcpy( sz, "plats/ttrain1.wav"); break; - case 2: strcpy( sz, "plats/ttrain2.wav"); break; - case 3: strcpy( sz, "plats/ttrain3.wav"); break; - case 4: strcpy( sz, "plats/ttrain4.wav"); break; - case 5: strcpy( sz, "plats/ttrain6.wav"); break; - case 6: strcpy( sz, "plats/ttrain7.wav"); break; - default: - // no sound - strcpy( sz, "" ); - return; - } - - if ( stop ) - { - gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz ); - } - else - { - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch ); - } -} - -int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 ) -{ - return 0; -} - -void EV_Dummy( struct event_args_s *args ) -{ - gEngfuncs.pEventAPI->EV_WeaponAnimation( 1, 1 ); - return; -} - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "entity_types.h" +#include "usercmd.h" +#include "pm_defs.h" +#include "pm_materials.h" + +#include "eventscripts.h" +#include "ev_hldm.h" + +#include "r_efx.h" +#include "event_api.h" +#include "event_args.h" +#include "in_defs.h" + +#include + +#include "r_studioint.h" +#include "com_model.h" + +extern engine_studio_api_t IEngineStudio; + +static int tracerCount[ 32 ]; + +extern "C" char PM_FindTextureType( char *name ); + +void V_PunchAxis( int axis, float punch ); +void VectorAngles( const float *forward, float *angles ); + +extern cvar_t *cl_lw; + +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_FireMP52( 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_Crowbar( struct event_args_s *args ); +void EV_FireCrossbow( struct event_args_s *args ); +void EV_FireCrossbow2( struct event_args_s *args ); +void EV_FireRpg( struct event_args_s *args ); +void EV_EgonFire( struct event_args_s *args ); +void EV_EgonStop( struct event_args_s *args ); +void EV_HornetGunFire( struct event_args_s *args ); +void EV_TripmineFire( struct event_args_s *args ); +void EV_SnarkFire( struct event_args_s *args ); +void EV_Dummy( struct event_args_s *args ); + +void EV_TrainPitchAdjust( struct event_args_s *args ); +} + +#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 ) +#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 ) +#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 ) +#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 ) +#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 ) +#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 ) +#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 ) +#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 ) +#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 ) +#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 ) +#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 ) +#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 ) + +// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the +// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture. +// returns volume of strike instrument (crowbar) to play +float EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType ) +{ + // hit the world, try to play sound based on texture material type + char chTextureType = CHAR_TEX_CONCRETE; + float fvol; + float fvolbar; + char *rgsz[4]; + int cnt; + float fattn = ATTN_NORM; + int entity; + char *pTextureName; + char texname[ 64 ]; + char szbuffer[ 64 ]; + + entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr ); + + // FIXME check if playtexture sounds movevar is set + // + + chTextureType = 0; + + // Player + if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) + { + // hit body + chTextureType = CHAR_TEX_FLESH; + } + else if ( entity == 0 ) + { + // get texture from entity or world (world is ent(0)) + pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); + + if ( pTextureName ) + { + strcpy( texname, pTextureName ); + pTextureName = texname; + + // strip leading '-0' or '+0~' or '{' or '!' + if (*pTextureName == '-' || *pTextureName == '+') + { + pTextureName += 2; + } + + if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') + { + pTextureName++; + } + + // '}}' + strcpy( szbuffer, pTextureName ); + szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0; + + // get texture type + chTextureType = PM_FindTextureType( szbuffer ); + } + } + + switch (chTextureType) + { + default: + case CHAR_TEX_CONCRETE: fvol = 0.9; fvolbar = 0.6; + rgsz[0] = "player/pl_step1.wav"; + rgsz[1] = "player/pl_step2.wav"; + cnt = 2; + break; + case CHAR_TEX_METAL: fvol = 0.9; fvolbar = 0.3; + rgsz[0] = "player/pl_metal1.wav"; + rgsz[1] = "player/pl_metal2.wav"; + cnt = 2; + break; + case CHAR_TEX_DIRT: fvol = 0.9; fvolbar = 0.1; + rgsz[0] = "player/pl_dirt1.wav"; + rgsz[1] = "player/pl_dirt2.wav"; + rgsz[2] = "player/pl_dirt3.wav"; + cnt = 3; + break; + case CHAR_TEX_VENT: fvol = 0.5; fvolbar = 0.3; + rgsz[0] = "player/pl_duct1.wav"; + rgsz[1] = "player/pl_duct1.wav"; + cnt = 2; + break; + case CHAR_TEX_GRATE: fvol = 0.9; fvolbar = 0.5; + rgsz[0] = "player/pl_grate1.wav"; + rgsz[1] = "player/pl_grate4.wav"; + cnt = 2; + break; + case CHAR_TEX_TILE: fvol = 0.8; fvolbar = 0.2; + rgsz[0] = "player/pl_tile1.wav"; + rgsz[1] = "player/pl_tile3.wav"; + rgsz[2] = "player/pl_tile2.wav"; + rgsz[3] = "player/pl_tile4.wav"; + cnt = 4; + break; + case CHAR_TEX_SLOSH: fvol = 0.9; fvolbar = 0.0; + rgsz[0] = "player/pl_slosh1.wav"; + rgsz[1] = "player/pl_slosh3.wav"; + rgsz[2] = "player/pl_slosh2.wav"; + rgsz[3] = "player/pl_slosh4.wav"; + cnt = 4; + break; + case CHAR_TEX_WOOD: fvol = 0.9; fvolbar = 0.2; + rgsz[0] = "debris/wood1.wav"; + rgsz[1] = "debris/wood2.wav"; + rgsz[2] = "debris/wood3.wav"; + cnt = 3; + break; + case CHAR_TEX_GLASS: + case CHAR_TEX_COMPUTER: + fvol = 0.8; fvolbar = 0.2; + rgsz[0] = "debris/glass1.wav"; + rgsz[1] = "debris/glass2.wav"; + rgsz[2] = "debris/glass3.wav"; + cnt = 3; + break; + case CHAR_TEX_FLESH: + if (iBulletType == BULLET_PLAYER_CROWBAR) + return 0.0; // crowbar already makes this sound + fvol = 1.0; fvolbar = 0.2; + rgsz[0] = "weapons/bullet_hit1.wav"; + rgsz[1] = "weapons/bullet_hit2.wav"; + fattn = 1.0; + cnt = 2; + break; + } + + // play material hit sound + gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) ); + return fvolbar; +} + +char *EV_HLDM_DamageDecal( physent_t *pe ) +{ + static char decalname[ 32 ]; + int idx; + + if ( pe->classnumber == 1 ) + { + idx = gEngfuncs.pfnRandomLong( 0, 2 ); + sprintf( decalname, "{break%i", idx + 1 ); + } + else if ( pe->rendermode != kRenderNormal ) + { + sprintf( decalname, "{bproof1" ); + } + else + { + idx = gEngfuncs.pfnRandomLong( 0, 4 ); + sprintf( decalname, "{shot%i", idx + 1 ); + } + return decalname; +} + +void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName ) +{ + int iRand; + physent_t *pe; + + gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos ); + + iRand = gEngfuncs.pfnRandomLong(0,0x7FFF); + if ( iRand < (0x7fff/2) )// not every bullet makes a sound. + { + switch( iRand % 5) + { + case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + } + } + + pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); + + // Only decal brush models such as the world etc. + if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) ) + { + if ( CVAR_GET_FLOAT( "r_decals" ) ) + { + gEngfuncs.pEfxAPI->R_DecalShoot( + gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ), + gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 ); + } + } +} + +void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType ) +{ + physent_t *pe; + + pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); + + if ( pe && pe->solid == SOLID_BSP ) + { + switch( iBulletType ) + { + case BULLET_PLAYER_9MM: + case BULLET_MONSTER_9MM: + case BULLET_PLAYER_MP5: + case BULLET_MONSTER_MP5: + case BULLET_PLAYER_BUCKSHOT: + case BULLET_PLAYER_357: + default: + // smoke and decal + EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) ); + break; + } + } +} + +int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount ) +{ + int tracer = 0; + int i; + qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false; + + if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 ) + { + vec3_t vecTracerSrc; + + if ( player ) + { + vec3_t offset( 0, 0, -4 ); + + // adjust tracer position for player + for ( i = 0; i < 3; i++ ) + { + vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16; + } + } + else + { + VectorCopy( vecSrc, vecTracerSrc ); + } + + if ( iTracerFreq != 1 ) // guns that always trace also always decal + tracer = 1; + + switch( iBulletType ) + { + case BULLET_PLAYER_MP5: + case BULLET_MONSTER_MP5: + case BULLET_MONSTER_9MM: + case BULLET_MONSTER_12MM: + default: + EV_CreateTracer( vecTracerSrc, end ); + break; + } + } + + return tracer; +} + + +/* +================ +FireBullets + +Go to the trouble of combining multiple pellets into a single damage call. +================ +*/ +void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY ) +{ + int i; + pmtrace_t tr; + int iShot; + int tracer; + + for ( iShot = 1; iShot <= cShots; iShot++ ) + { + vec3_t vecDir, vecEnd; + + float x, y, z; + //We randomize for the Shotgun. + if ( iBulletType == BULLET_PLAYER_BUCKSHOT ) + { + do { + x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); + y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); + z = x*x+y*y; + } while (z > 1); + + for ( i = 0 ; i < 3; i++ ) + { + vecDir[i] = vecDirShooting[i] + x * flSpreadX * right[ i ] + y * flSpreadY * up [ i ]; + vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ]; + } + }//But other guns already have their spread randomized in the synched spread. + else + { + + for ( i = 0 ; i < 3; i++ ) + { + vecDir[i] = vecDirShooting[i] + flSpreadX * right[ i ] + flSpreadY * up [ i ]; + vecEnd[i] = vecSrc[ i ] + flDistance * vecDir[ i ]; + } + } + + 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 ( idx - 1 ); + + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + + tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); + + // do damage, paint decals + if ( tr.fraction != 1.0 ) + { + switch(iBulletType) + { + default: + case BULLET_PLAYER_9MM: + + EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); + EV_HLDM_DecalGunshot( &tr, iBulletType ); + + break; + case BULLET_PLAYER_MP5: + + if ( !tracer ) + { + EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); + EV_HLDM_DecalGunshot( &tr, iBulletType ); + } + break; + case BULLET_PLAYER_BUCKSHOT: + + EV_HLDM_DecalGunshot( &tr, iBulletType ); + + break; + case BULLET_PLAYER_357: + + EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType ); + EV_HLDM_DecalGunshot( &tr, iBulletType ); + + break; + + } + } + + gEngfuncs.pEventAPI->EV_PopPMStates(); + } +} + +//====================== +// GLOCK START +//====================== +void EV_FireGlock1( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + int empty; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + empty = args->bparam1; + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell + + if ( EV_IsLocal( idx ) ) + { + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, 2 ); + + V_PunchAxis( 0, -2.0 ); + } + + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); + + EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL ); + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) ); + + EV_GetGunPosition( args, vecSrc, origin ); + + VectorCopy( forward, vecAiming ); + + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, 0, args->fparam1, args->fparam2 ); +} + +void EV_FireGlock2( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t vecSpread; + vec3_t up, right, forward; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell + + if ( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( GLOCK_SHOOT, 2 ); + + V_PunchAxis( 0, -2.0 ); + } + + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); + + EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL ); + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) ); + + EV_GetGunPosition( args, vecSrc, origin ); + + VectorCopy( forward, vecAiming ); + + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, &tracerCount[idx-1], args->fparam1, args->fparam2 ); + +} +//====================== +// GLOCK END +//====================== + +//====================== +// SHOTGUN START +//====================== +void EV_FireShotGunDouble( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + int j; + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t vecSpread; + vec3_t up, right, forward; + float flSpread = 0.01; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell + + if ( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE2, 2 ); + V_PunchAxis( 0, -10.0 ); + } + + for ( j = 0; j < 2; j++ ) + { + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 ); + + EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL ); + } + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/dbarrel1.wav", gEngfuncs.pfnRandomFloat(0.98, 1.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) ); + + EV_GetGunPosition( args, vecSrc, origin ); + VectorCopy( forward, vecAiming ); + + if ( gEngfuncs.GetMaxClients() > 1 ) + { + EV_HLDM_FireBullets( idx, forward, right, up, 8, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.17365, 0.04362 ); + } + else + { + EV_HLDM_FireBullets( idx, forward, right, up, 12, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 ); + } +} + +void EV_FireShotGunSingle( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t vecSpread; + vec3_t up, right, forward; + float flSpread = 0.01; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shotgunshell.mdl");// brass shell + + if ( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE, 2 ); + + V_PunchAxis( 0, -5.0 ); + } + + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 ); + + EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL ); + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sbarrel1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) ); + + EV_GetGunPosition( args, vecSrc, origin ); + VectorCopy( forward, vecAiming ); + + if ( gEngfuncs.GetMaxClients() > 1 ) + { + EV_HLDM_FireBullets( idx, forward, right, up, 4, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.04362 ); + } + else + { + EV_HLDM_FireBullets( idx, forward, right, up, 6, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &tracerCount[idx-1], 0.08716, 0.08716 ); + } +} +//====================== +// SHOTGUN END +//====================== + +//====================== +// MP5 START +//====================== +void EV_FireMP5( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t ShellVelocity; + vec3_t ShellOrigin; + int shell; + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; + float flSpread = 0.01; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shell.mdl");// brass shell + + if ( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_FIRE1 + gEngfuncs.pfnRandomLong(0,2), 2 ); + + V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) ); + } + + EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 ); + + EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL ); + + switch( gEngfuncs.pfnRandomLong( 0, 1 ) ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + } + + EV_GetGunPosition( args, vecSrc, origin ); + VectorCopy( forward, vecAiming ); + + if ( gEngfuncs.GetMaxClients() > 1 ) + { + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 ); + } + else + { + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &tracerCount[idx-1], args->fparam1, args->fparam2 ); + } +} + +// We only predict the animation and sound +// The grenade is still launched from the server. +void EV_FireMP52( event_args_t *args ) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + + if ( EV_IsLocal( idx ) ) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_LAUNCH, 2 ); + V_PunchAxis( 0, -10 ); + } + + switch( gEngfuncs.pfnRandomLong( 0, 1 ) ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) ); + break; + } +} +//====================== +// MP5 END +//====================== + +//====================== +// PHYTON START +// ( .357 ) +//====================== +void EV_FirePython( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + vec3_t vecSrc, vecAiming; + vec3_t up, right, forward; + float flSpread = 0.01; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + if ( EV_IsLocal( idx ) ) + { + // Python uses different body in multiplayer versus single player + int multiplayer = gEngfuncs.GetMaxClients() == 1 ? 0 : 1; + + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE1, multiplayer ? 1 : 0 ); + + V_PunchAxis( 0, -10.0 ); + } + + switch( gEngfuncs.pfnRandomLong( 0, 1 ) ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM ); + break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot2.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM ); + break; + } + + EV_GetGunPosition( args, vecSrc, origin ); + + VectorCopy( forward, vecAiming ); + + EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_357, 0, 0, args->fparam1, args->fparam2 ); +} +//====================== +// PHYTON END +// ( .357 ) +//====================== + +//====================== +// GAUSS START +//====================== +#define SND_CHANGE_PITCH (1<<7) // duplicated in protocol.h change sound pitch + +void EV_SpinGauss( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + int iSoundState = 0; + + int pitch; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + pitch = args->iparam1; + + iSoundState = args->bparam1 ? SND_CHANGE_PITCH : 0; + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "ambience/pulsemachine.wav", 1.0, ATTN_NORM, iSoundState, pitch ); +} + +/* +============================== +EV_StopPreviousGauss + +============================== +*/ +void EV_StopPreviousGauss( int idx ) +{ + // Make sure we don't have a gauss spin event in the queue for this guy + gEngfuncs.pEventAPI->EV_KillEvents( idx, "events/gaussspin.sc" ); + gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_WEAPON, "ambience/pulsemachine.wav" ); +} + +extern float g_flApplyVel; + +void EV_FireGauss( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + float flDamage = args->fparam1; + int primaryfire = args->bparam1; + + int m_fPrimaryFire = args->bparam1; + int m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME; + vec3_t vecSrc; + vec3_t vecDest; + edict_t *pentIgnore; + pmtrace_t tr, beam_tr; + float flMaxFrac = 1.0; + int nTotal = 0; + int fHasPunched = 0; + int fFirstBeam = 1; + int nMaxHits = 10; + physent_t *pEntity; + int m_iBeam, m_iGlow, m_iBalls; + vec3_t up, right, forward; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + VectorCopy( args->velocity, velocity ); + + if ( args->bparam2 ) + { + EV_StopPreviousGauss( idx ); + return; + } + +// Con_Printf( "Firing gauss with %f\n", flDamage ); + EV_GetGunPosition( args, vecSrc, origin ); + + m_iBeam = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/smoke.spr" ); + m_iBalls = m_iGlow = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/hotglow.spr" ); + + AngleVectors( angles, forward, right, up ); + + VectorMA( vecSrc, 8192, forward, vecDest ); + + if ( EV_IsLocal( idx ) ) + { + V_PunchAxis( 0, -2.0 ); + gEngfuncs.pEventAPI->EV_WeaponAnimation( GAUSS_FIRE2, 2 ); + + if ( m_fPrimaryFire == false ) + g_flApplyVel = flDamage; + + } + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/gauss2.wav", 0.5 + flDamage * (1.0 / 400.0), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) ); + + while (flDamage > 10 && nMaxHits > 0) + { + nMaxHits--; + + 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 ( idx - 1 ); + + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr ); + + gEngfuncs.pEventAPI->EV_PopPMStates(); + + if ( tr.allsolid ) + break; + + if (fFirstBeam) + { + if ( EV_IsLocal( idx ) ) + { + // Add muzzle flash to current weapon model + EV_MuzzleFlash(); + } + fFirstBeam = 0; + + gEngfuncs.pEfxAPI->R_BeamEntPoint( + idx | 0x1000, + tr.endpos, + m_iBeam, + 0.1, + m_fPrimaryFire ? 1.0 : 2.5, + 0.0, + m_fPrimaryFire ? 128.0 : flDamage, + 0, + 0, + 0, + m_fPrimaryFire ? 255 : 255, + m_fPrimaryFire ? 128 : 255, + m_fPrimaryFire ? 0 : 255 + ); + } + else + { + gEngfuncs.pEfxAPI->R_BeamPoints( vecSrc, + tr.endpos, + m_iBeam, + 0.1, + m_fPrimaryFire ? 1.0 : 2.5, + 0.0, + m_fPrimaryFire ? 128.0 : flDamage, + 0, + 0, + 0, + m_fPrimaryFire ? 255 : 255, + m_fPrimaryFire ? 128 : 255, + m_fPrimaryFire ? 0 : 255 + ); + } + + pEntity = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent ); + if ( pEntity == NULL ) + break; + + if ( pEntity->solid == SOLID_BSP ) + { + float n; + + pentIgnore = NULL; + + n = -DotProduct( tr.plane.normal, forward ); + + if (n < 0.5) // 60 degrees + { + // ALERT( at_console, "reflect %f\n", n ); + // reflect + vec3_t r; + + VectorMA( forward, 2.0 * n, tr.plane.normal, r ); + + flMaxFrac = flMaxFrac - tr.fraction; + + VectorCopy( r, forward ); + + VectorMA( tr.endpos, 8.0, forward, vecSrc ); + VectorMA( vecSrc, 8192.0, forward, vecDest ); + + gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0, flDamage * n * 0.5 * 0.1, FTENT_FADEOUT ); + + vec3_t fwd; + VectorAdd( tr.endpos, tr.plane.normal, fwd ); + + gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, + 255, 100 ); + + // lose energy + if ( n == 0 ) + { + n = 0.1; + } + + flDamage = flDamage * (1 - n); + + } + else + { + // tunnel + EV_HLDM_DecalGunshot( &tr, BULLET_MONSTER_12MM ); + + gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT ); + + // limit it to one hole punch + if (fHasPunched) + { + break; + } + fHasPunched = 1; + + // try punching through wall if secondary attack (primary is incapable of breaking through) + if ( !m_fPrimaryFire ) + { + vec3_t start; + + VectorMA( tr.endpos, 8.0, forward, start ); + + // Store off the old count + gEngfuncs.pEventAPI->EV_PushPMStates(); + + // Now add in all of the players. + gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); + + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr ); + + if ( !beam_tr.allsolid ) + { + vec3_t delta; + float n; + + // trace backwards to find exit point + + gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr ); + + VectorSubtract( beam_tr.endpos, tr.endpos, delta ); + + n = Length( delta ); + + if (n < flDamage) + { + if (n == 0) + n = 1; + flDamage -= n; + + // absorption balls + { + vec3_t fwd; + VectorSubtract( tr.endpos, forward, fwd ); + gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, + 255, 100 ); + } + + //////////////////////////////////// WHAT TO DO HERE + // CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 ); + + EV_HLDM_DecalGunshot( &beam_tr, BULLET_MONSTER_12MM ); + + gEngfuncs.pEfxAPI->R_TempSprite( beam_tr.endpos, vec3_origin, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0, 6.0, FTENT_FADEOUT ); + + // balls + { + vec3_t fwd; + VectorSubtract( beam_tr.endpos, forward, fwd ); + gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, beam_tr.endpos, fwd, m_iBalls, (int)(flDamage * 0.3), 0.1, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 200, + 255, 40 ); + } + + VectorAdd( beam_tr.endpos, forward, vecSrc ); + } + } + else + { + flDamage = 0; + } + + gEngfuncs.pEventAPI->EV_PopPMStates(); + } + else + { + if ( m_fPrimaryFire ) + { + // slug doesn't punch through ever with primary + // fire, so leave a little glowy bit and make some balls + gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0 / 255.0, 0.3, FTENT_FADEOUT ); + + { + vec3_t fwd; + VectorAdd( tr.endpos, tr.plane.normal, fwd ); + gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 8, 0.6, gEngfuncs.pfnRandomFloat( 10, 20 ) / 100.0, 100, + 255, 200 ); + } + } + + flDamage = 0; + } + } + } + else + { + VectorAdd( tr.endpos, forward, vecSrc ); + } + } +} +//====================== +// GAUSS END +//====================== + +//====================== +// CROWBAR START +//====================== + +enum crowbar_e { + CROWBAR_IDLE = 0, + CROWBAR_DRAW, + CROWBAR_HOLSTER, + CROWBAR_ATTACK1HIT, + CROWBAR_ATTACK1MISS, + CROWBAR_ATTACK2MISS, + CROWBAR_ATTACK2HIT, + CROWBAR_ATTACK3MISS, + CROWBAR_ATTACK3HIT +}; + +int g_iSwing; + +//Only predict the miss sounds, hit sounds are still played +//server side, so players don't get the wrong idea. +void EV_Crowbar( event_args_t *args ) +{ + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + + //Play Swing sound + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM); + + if ( EV_IsLocal( idx ) ) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK1MISS, 1 ); + + switch( (g_iSwing++) % 3 ) + { + case 0: + gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK1MISS, 1 ); break; + case 1: + gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK2MISS, 1 ); break; + case 2: + gEngfuncs.pEventAPI->EV_WeaponAnimation ( CROWBAR_ATTACK3MISS, 1 ); break; + } + } +} +//====================== +// CROWBAR END +//====================== + +//====================== +// CROSSBOW START +//====================== +enum crossbow_e { + CROSSBOW_IDLE1 = 0, // full + CROSSBOW_IDLE2, // empty + CROSSBOW_FIDGET1, // full + CROSSBOW_FIDGET2, // empty + CROSSBOW_FIRE1, // full + CROSSBOW_FIRE2, // reload + CROSSBOW_FIRE3, // empty + CROSSBOW_RELOAD, // from empty + CROSSBOW_DRAW1, // full + CROSSBOW_DRAW2, // empty + CROSSBOW_HOLSTER1, // full + CROSSBOW_HOLSTER2, // empty +}; + +//===================== +// EV_BoltCallback +// This function is used to correct the origin and angles +// of the bolt, so it looks like it's stuck on the wall. +//===================== +void EV_BoltCallback ( struct tempent_s *ent, float frametime, float currenttime ) +{ + ent->entity.origin = ent->entity.baseline.vuser1; + ent->entity.angles = ent->entity.baseline.vuser2; +} + +void EV_FireCrossbow2( event_args_t *args ) +{ + vec3_t vecSrc, vecEnd; + vec3_t up, right, forward; + pmtrace_t tr; + + int idx; + vec3_t origin; + vec3_t angles; + vec3_t velocity; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + + VectorCopy( args->velocity, velocity ); + + AngleVectors( angles, forward, right, up ); + + EV_GetGunPosition( args, vecSrc, origin ); + + VectorMA( vecSrc, 8192, forward, vecEnd ); + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); + + if ( EV_IsLocal( idx ) ) + { + if ( args->iparam1 ) + gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); + else if ( args->iparam2 ) + gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 ); + } + + // Store off the old count + gEngfuncs.pEventAPI->EV_PushPMStates(); + + // Now add in all of the players. + gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + + //We hit something + if ( tr.fraction < 1.0 ) + { + physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent ); + + //Not the world, let's assume we hit something organic ( dog, cat, uncle joe, etc ). + if ( pe->solid != SOLID_BSP ) + { + switch( gEngfuncs.pfnRandomLong(0,1) ) + { + case 0: + gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break; + case 1: + gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM, 0, PITCH_NORM ); break; + } + } + //Stick to world but don't stick to glass, it might break and leave the bolt floating. It can still stick to other non-transparent breakables though. + else if ( pe->rendermode == kRenderNormal ) + { + gEngfuncs.pEventAPI->EV_PlaySound( 0, tr.endpos, CHAN_BODY, "weapons/xbow_hit1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, PITCH_NORM ); + + //Not underwater, do some sparks... + if ( gEngfuncs.PM_PointContents( tr.endpos, NULL ) != CONTENTS_WATER) + gEngfuncs.pEfxAPI->R_SparkShower( tr.endpos ); + + vec3_t vBoltAngles; + int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/crossbow_bolt.mdl" ); + + VectorAngles( forward, vBoltAngles ); + + TEMPENTITY *bolt = gEngfuncs.pEfxAPI->R_TempModel( tr.endpos - forward * 10, Vector( 0, 0, 0), vBoltAngles , 5, iModelIndex, TE_BOUNCE_NULL ); + + if ( bolt ) + { + bolt->flags |= ( FTENT_CLIENTCUSTOM ); //So it calls the callback function. + bolt->entity.baseline.vuser1 = tr.endpos - forward * 10; // Pull out a little bit + bolt->entity.baseline.vuser2 = vBoltAngles; //Look forward! + bolt->callback = EV_BoltCallback; //So we can set the angles and origin back. (Stick the bolt to the wall) + } + } + } + + gEngfuncs.pEventAPI->EV_PopPMStates(); +} + +//TODO: Fully predict the fliying bolt. +void EV_FireCrossbow( event_args_t *args ) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong(0,0xF) ); + + //Only play the weapon anims if I shot it. + if ( EV_IsLocal( idx ) ) + { + if ( args->iparam1 ) + gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 ); + else if ( args->iparam2 ) + gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 ); + + V_PunchAxis( 0, -2.0 ); + } +} +//====================== +// CROSSBOW END +//====================== + +//====================== +// RPG START +//====================== +enum rpg_e { + RPG_IDLE = 0, + RPG_FIDGET, + RPG_RELOAD, // to reload + RPG_FIRE2, // to empty + RPG_HOLSTER1, // loaded + RPG_DRAW1, // loaded + RPG_HOLSTER2, // unloaded + RPG_DRAW_UL, // unloaded + RPG_IDLE_UL, // unloaded idle + RPG_FIDGET_UL, // unloaded fidget +}; + +void EV_FireRpg( event_args_t *args ) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM ); + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM ); + + //Only play the weapon anims if I shot it. + if ( EV_IsLocal( idx ) ) + { + gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 ); + + V_PunchAxis( 0, -5.0 ); + } +} +//====================== +// RPG END +//====================== + +//====================== +// EGON END +//====================== +enum egon_e { + EGON_IDLE1 = 0, + EGON_FIDGET1, + EGON_ALTFIREON, + EGON_ALTFIRECYCLE, + EGON_ALTFIREOFF, + EGON_FIRE1, + EGON_FIRE2, + EGON_FIRE3, + EGON_FIRE4, + EGON_DRAW, + EGON_HOLSTER +}; + +int g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 }; +int g_fireAnims2[] = { EGON_ALTFIRECYCLE }; + +enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE }; +enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE}; + +#define EGON_PRIMARY_VOLUME 450 +#define EGON_BEAM_SPRITE "sprites/xbeam1.spr" +#define EGON_FLARE_SPRITE "sprites/XSpark1.spr" +#define EGON_SOUND_OFF "weapons/egon_off1.wav" +#define EGON_SOUND_RUN "weapons/egon_run3.wav" +#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav" + +#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) + +BEAM *pBeam; +BEAM *pBeam2; + +void EV_EgonFire( event_args_t *args ) +{ + int idx, iFireState, iFireMode; + vec3_t origin; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + iFireState = args->iparam1; + iFireMode = args->iparam2; + int iStartup = args->bparam1; + + + if ( iStartup ) + { + if ( iFireMode == FIRE_WIDE ) + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 ); + else + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 ); + } + else + { + if ( iFireMode == FIRE_WIDE ) + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 ); + else + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 ); + } + + //Only play the weapon anims if I shot it. + if ( EV_IsLocal( idx ) ) + gEngfuncs.pEventAPI->EV_WeaponAnimation ( g_fireAnims1[ gEngfuncs.pfnRandomLong( 0, 3 ) ], 1 ); + + if ( iStartup == 1 && EV_IsLocal( idx ) && !pBeam && !pBeam2 && cl_lw->value ) //Adrian: Added the cl_lw check for those lital people that hate weapon prediction. + { + vec3_t vecSrc, vecEnd, origin, angles, forward, right, up; + pmtrace_t tr; + + cl_entity_t *pl = gEngfuncs.GetEntityByIndex( idx ); + + if ( pl ) + { + VectorCopy( gHUD.m_vecAngles, angles ); + + AngleVectors( angles, forward, right, up ); + + EV_GetGunPosition( args, vecSrc, pl->origin ); + + VectorMA( vecSrc, 2048, forward, vecEnd ); + + 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 ( idx - 1 ); + + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr ); + + gEngfuncs.pEventAPI->EV_PopPMStates(); + + int iBeamModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE ); + + float r = 50.0f; + float g = 50.0f; + float b = 125.0f; + + if ( IEngineStudio.IsHardware() ) + { + r /= 100.0f; + g /= 100.0f; + } + + + pBeam = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b ); + + if ( pBeam ) + pBeam->flags |= ( FBEAM_SINENOISE ); + + pBeam2 = gEngfuncs.pEfxAPI->R_BeamEntPoint ( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b ); + } + } +} + +void EV_EgonStop( event_args_t *args ) +{ + int idx; + vec3_t origin; + + idx = args->entindex; + VectorCopy ( args->origin, origin ); + + gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN ); + + if ( args->iparam1 ) + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 ); + + if ( EV_IsLocal( idx ) ) + { + if ( pBeam ) + { + pBeam->die = 0.0; + pBeam = NULL; + } + + + if ( pBeam2 ) + { + pBeam2->die = 0.0; + pBeam2 = NULL; + } + } +} +//====================== +// EGON END +//====================== + +//====================== +// HORNET START +//====================== +enum hgun_e { + HGUN_IDLE1 = 0, + HGUN_FIDGETSWAY, + HGUN_FIDGETSHAKE, + HGUN_DOWN, + HGUN_UP, + HGUN_SHOOT +}; + +void EV_HornetGunFire( event_args_t *args ) +{ + int idx, iFireMode; + vec3_t origin, angles, vecSrc, forward, right, up; + + idx = args->entindex; + VectorCopy( args->origin, origin ); + VectorCopy( args->angles, angles ); + iFireMode = args->iparam1; + + //Only play the weapon anims if I shot it. + if ( EV_IsLocal( idx ) ) + { + V_PunchAxis( 0, gEngfuncs.pfnRandomLong ( 0, 2 ) ); + gEngfuncs.pEventAPI->EV_WeaponAnimation ( HGUN_SHOOT, 1 ); + } + + switch ( gEngfuncs.pfnRandomLong ( 0 , 2 ) ) + { + case 0: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM, 0, 100 ); break; + case 1: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM, 0, 100 ); break; + case 2: gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM, 0, 100 ); break; + } +} +//====================== +// HORNET END +//====================== + +//====================== +// TRIPMINE START +//====================== +enum tripmine_e { + TRIPMINE_IDLE1 = 0, + TRIPMINE_IDLE2, + TRIPMINE_ARM1, + TRIPMINE_ARM2, + TRIPMINE_FIDGET, + TRIPMINE_HOLSTER, + TRIPMINE_DRAW, + TRIPMINE_WORLD, + TRIPMINE_GROUND, +}; + +//We only check if it's possible to put a trip mine +//and if it is, then we play the animation. Server still places it. +void EV_TripmineFire( event_args_t *args ) +{ + int idx; + vec3_t vecSrc, angles, view_ofs, forward; + pmtrace_t tr; + + idx = args->entindex; + VectorCopy( args->origin, vecSrc ); + VectorCopy( args->angles, angles ); + + AngleVectors ( angles, forward, NULL, NULL ); + + if ( !EV_IsLocal ( idx ) ) + return; + + // Grab predicted result for local player + gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs ); + + vecSrc = vecSrc + view_ofs; + + // Store off the old count + gEngfuncs.pEventAPI->EV_PushPMStates(); + + // Now add in all of the players. + gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecSrc + forward * 128, PM_NORMAL, -1, &tr ); + + //Hit something solid + if ( tr.fraction < 1.0 ) + gEngfuncs.pEventAPI->EV_WeaponAnimation ( TRIPMINE_DRAW, 0 ); + + gEngfuncs.pEventAPI->EV_PopPMStates(); +} +//====================== +// TRIPMINE END +//====================== + +//====================== +// SQUEAK START +//====================== +enum squeak_e { + SQUEAK_IDLE1 = 0, + SQUEAK_FIDGETFIT, + SQUEAK_FIDGETNIP, + SQUEAK_DOWN, + SQUEAK_UP, + SQUEAK_THROW +}; + +#define VEC_HULL_MIN Vector(-16, -16, -36) +#define VEC_DUCK_HULL_MIN Vector(-16, -16, -18 ) + +void EV_SnarkFire( event_args_t *args ) +{ + int idx; + vec3_t vecSrc, angles, view_ofs, forward; + pmtrace_t tr; + + idx = args->entindex; + VectorCopy( args->origin, vecSrc ); + VectorCopy( args->angles, angles ); + + AngleVectors ( angles, forward, NULL, NULL ); + + if ( !EV_IsLocal ( idx ) ) + return; + + if ( args->ducking ) + vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN ); + + // Store off the old count + gEngfuncs.pEventAPI->EV_PushPMStates(); + + // Now add in all of the players. + gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 ); + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc + forward * 20, vecSrc + forward * 64, PM_NORMAL, -1, &tr ); + + //Find space to drop the thing. + if ( tr.allsolid == 0 && tr.startsolid == 0 && tr.fraction > 0.25 ) + gEngfuncs.pEventAPI->EV_WeaponAnimation ( SQUEAK_THROW, 0 ); + + gEngfuncs.pEventAPI->EV_PopPMStates(); +} +//====================== +// SQUEAK END +//====================== + +void EV_TrainPitchAdjust( event_args_t *args ) +{ + int idx; + vec3_t origin; + + unsigned short us_params; + int noise; + float m_flVolume; + int pitch; + int stop; + + char sz[ 256 ]; + + idx = args->entindex; + + VectorCopy( args->origin, origin ); + + us_params = (unsigned short)args->iparam1; + stop = args->bparam1; + + m_flVolume = (float)(us_params & 0x003f)/40.0; + noise = (int)(((us_params) >> 12 ) & 0x0007); + pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) ); + + switch ( noise ) + { + case 1: strcpy( sz, "plats/ttrain1.wav"); break; + case 2: strcpy( sz, "plats/ttrain2.wav"); break; + case 3: strcpy( sz, "plats/ttrain3.wav"); break; + case 4: strcpy( sz, "plats/ttrain4.wav"); break; + case 5: strcpy( sz, "plats/ttrain6.wav"); break; + case 6: strcpy( sz, "plats/ttrain7.wav"); break; + default: + // no sound + strcpy( sz, "" ); + return; + } + + if ( stop ) + { + gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz ); + } + else + { + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch ); + } +} + +int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 ) +{ + return 0; +} + +void EV_Dummy( struct event_args_s *args ) +{ + gEngfuncs.pEventAPI->EV_WeaponAnimation( 1, 1 ); + return; +} + diff --git a/cl_dll/events.cpp b/cl_dll/events.cpp index 65c842b..a51dd72 100644 --- a/cl_dll/events.cpp +++ b/cl_dll/events.cpp @@ -1,23 +1,23 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#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(); +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#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(); } \ No newline at end of file diff --git a/cl_dll/events/ev_cs16.cpp b/cl_dll/events/ev_cs16.cpp index ba5e04d..ffa56fe 100644 --- a/cl_dll/events/ev_cs16.cpp +++ b/cl_dll/events/ev_cs16.cpp @@ -1,775 +1,775 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "entity_state.h" -#include "cl_entity.h" -#include "entity_types.h" -#include "usercmd.h" -#include "pm_defs.h" -#include "pm_materials.h" - -#include "eventscripts.h" -#include "ev_hldm.h" - -#include "r_efx.h" -#include "triangleapi.h" -#include "event_api.h" -#include "event_args.h" -#include "in_defs.h" - -#include - -#include "r_studioint.h" -#include "com_model.h" - -#include - -static int tracerCount[ 32 ]; -extern float g_flRoundTime; - -extern "C" char PM_FindTextureType( char *name ); - -// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the -// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture. -// returns volume of strike instrument (crowbar) to play -void EV_HLDM_NewExplode( float x, float y, float z, float ScaleExplode1 ) -{ - - int iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/dexplo.spr"); - TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 5 ), - Vector( 0, 0, 0 ), - ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL ); - - if(pTemp) - { - pTemp->fadeSpeed = 90.0; - pTemp->entity.curstate.framerate = 37.0; - pTemp->entity.curstate.renderamt = 155; - pTemp->entity.curstate.rendercolor.r = 255; - pTemp->entity.curstate.rendercolor.g = 255; - pTemp->entity.curstate.rendercolor.b = 255; - } - - iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/fexplo.spr"); - pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 10), - Vector( 0, 0, 0 ), - ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL ); - - if(pTemp) - { - pTemp->fadeSpeed = 90.0; - pTemp->entity.curstate.framerate = 35.0; - pTemp->entity.curstate.renderamt = 150; - pTemp->entity.curstate.rendercolor.r = 255; - pTemp->entity.curstate.rendercolor.g = 255; - pTemp->entity.curstate.rendercolor.b = 255; - pTemp->entity.angles = Vector( 90, 0, 0 ); - } - - for( int i = 1; i <= 10; i++ ) - { - int iSmokeSprite = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/smoke.spr"); - TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z ), - Vector( (int)gEngfuncs.pfnRandomLong( -100, 100 ), (int)gEngfuncs.pfnRandomLong( -100, 100 ), (int)gEngfuncs.pfnRandomLong( -100, 100 ) ), - 5, iSmokeSprite, kRenderTransAlpha, kRenderFxNone, 1.0, 0.5, FTENT_FADEOUT | FTENT_PERSIST ); - - if(pTemp) - { - pTemp->fadeSpeed = 0.6; - pTemp->entity.curstate.framerate = 1; - pTemp->entity.curstate.renderamt = 255; - int Color = gEngfuncs.pfnRandomLong( 0, 140 ); - pTemp->entity.curstate.rendercolor.r = Color; - pTemp->entity.curstate.rendercolor.g = Color; - pTemp->entity.curstate.rendercolor.b = Color; - } - } - -} - -char EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType ) -{ - // hit the world, try to play sound based on texture material type - char chTextureType = CHAR_TEX_CONCRETE; - float fvol; - float fvolbar; - char *rgsz[4]; - int cnt; - float fattn = ATTN_NORM; - int entity; - char *pTextureName; - char texname[ 64 ]; - char szbuffer[ 64 ]; - - entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr ); - - // FIXME check if playtexture sounds movevar is set - // - - chTextureType = 0; - - // Player - if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) - { - // hit body - chTextureType = CHAR_TEX_FLESH; - } - else if ( entity == 0 ) - { - // get texture from entity or world (world is ent(0)) - pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); - - if ( pTextureName ) - { - strncpy( texname, pTextureName, sizeof( texname ) ); - pTextureName = texname; - - // strip leading '-0' or '+0~' or '{' or '!' - if (*pTextureName == '-' || *pTextureName == '+') - { - pTextureName += 2; - } - - if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') - { - pTextureName++; - } - - // '}}' - strncpy( szbuffer, pTextureName, sizeof(szbuffer) ); - szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0; - - // get texture type - chTextureType = PM_FindTextureType( szbuffer ); - } - } - - switch (chTextureType) - { - default: - case CHAR_TEX_CONCRETE: - { - fvol = 0.9; - fvolbar = 0.6; - rgsz[0] = "player/pl_step1.wav"; - rgsz[1] = "player/pl_step2.wav"; - cnt = 2; - break; - } - case CHAR_TEX_METAL: - { - fvol = 0.9; - fvolbar = 0.3; - rgsz[0] = "player/pl_metal1.wav"; - rgsz[1] = "player/pl_metal2.wav"; - cnt = 2; - break; - } - case CHAR_TEX_DIRT: - { - fvol = 0.9; - fvolbar = 0.1; - rgsz[0] = "player/pl_dirt1.wav"; - rgsz[1] = "player/pl_dirt2.wav"; - rgsz[2] = "player/pl_dirt3.wav"; - cnt = 3; - break; - } - case CHAR_TEX_VENT: - { - fvol = 0.5; - fvolbar = 0.3; - rgsz[0] = "player/pl_duct1.wav"; - rgsz[1] = "player/pl_duct1.wav"; - cnt = 2; - break; - } - case CHAR_TEX_GRATE: - { - fvol = 0.9; - fvolbar = 0.5; - rgsz[0] = "player/pl_grate1.wav"; - rgsz[1] = "player/pl_grate4.wav"; - cnt = 2; - break; - } - case CHAR_TEX_TILE: - { - fvol = 0.8; - fvolbar = 0.2; - rgsz[0] = "player/pl_tile1.wav"; - rgsz[1] = "player/pl_tile3.wav"; - rgsz[2] = "player/pl_tile2.wav"; - rgsz[3] = "player/pl_tile4.wav"; - cnt = 4; - break; - } - case CHAR_TEX_SLOSH: - { - fvol = 0.9; - fvolbar = 0; - rgsz[0] = "player/pl_slosh1.wav"; - rgsz[1] = "player/pl_slosh3.wav"; - rgsz[2] = "player/pl_slosh2.wav"; - rgsz[3] = "player/pl_slosh4.wav"; - cnt = 4; - break; - } - case CHAR_TEX_SNOW: - { - fvol = 0.7; - fvolbar = 0.4; - rgsz[0] = "debris/pl_snow1.wav"; - rgsz[1] = "debris/pl_snow2.wav"; - rgsz[2] = "debris/pl_snow3.wav"; - rgsz[3] = "debris/pl_snow4.wav"; - cnt = 4; - break; - } - case CHAR_TEX_WOOD: - { - fvol = 0.9; - fvolbar = 0.2; - rgsz[0] = "debris/wood1.wav"; - rgsz[1] = "debris/wood2.wav"; - rgsz[2] = "debris/wood3.wav"; - cnt = 3; - break; - } - case CHAR_TEX_GLASS: - case CHAR_TEX_COMPUTER: - { - fvol = 0.8; - fvolbar = 0.2; - rgsz[0] = "debris/glass1.wav"; - rgsz[1] = "debris/glass2.wav"; - rgsz[2] = "debris/glass3.wav"; - cnt = 3; - break; - } - case CHAR_TEX_FLESH: - { - fvol = 1.0;fvolbar = 0.2; - rgsz[0] = "weapons/bullet_hit1.wav"; - rgsz[1] = "weapons/bullet_hit2.wav"; - fattn = 1.0; - cnt = 2; - break; - } - } - - // play material hit sound - gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) ); - - return chTextureType; -} - -char *EV_HLDM_DamageDecal( physent_t *pe ) -{ - static char decalname[ 32 ]; - int idx; - - if ( pe->classnumber == 1 ) - { - idx = gEngfuncs.pfnRandomLong( 0, 2 ); - sprintf( decalname, "{break%i", idx + 1 ); - } - else if ( pe->rendermode != kRenderNormal ) - { - sprintf( decalname, "{bproof1" ); - } - else - { - idx = gEngfuncs.pfnRandomLong( 0, 4 ); - sprintf( decalname, "{shot%i", idx + 1 ); - } - return decalname; -} - -void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName, char chTextureType ) -{ - int iRand; - physent_t *pe; - - gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos ); - - - iRand = gEngfuncs.pfnRandomLong(0,0x7FFF); - if ( iRand < (0x7fff/2) )// not every bullet makes a sound. - { - if( chTextureType == CHAR_TEX_VENT || chTextureType == CHAR_TEX_METAL ) - { - switch( iRand % 2 ) - { - case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_metal-1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; - case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_metal-2.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; - } - } - else - { - switch( iRand % 7) - { - case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; - case 5: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_conc-1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; - case 6: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_conc-2.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; - } - } - - } - - pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); - - // Only decal brush models such as the world etc. - if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) ) - { - if ( CVAR_GET_FLOAT( "r_decals" ) ) - { - gEngfuncs.pEfxAPI->R_DecalShoot( - gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ), - gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 ); - - } - } -} - -void EV_HLDM_DecalGunshot(pmtrace_t *pTrace, int iBulletType, float scale, int r, int g, int b, bool bCreateSparks, char cTextureType) -{ - physent_t *pe; - - pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); - - if ( pe && pe->solid == SOLID_BSP ) - { - EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ), cTextureType ); - - Vector dir = pTrace->plane.normal; - dir = dir * gEngfuncs.pfnRandomFloat(4.0f, 12.0f ); - if( bCreateSparks ) - { - gEngfuncs.pEfxAPI->R_StreakSplash( pTrace->endpos, dir, 4, gEngfuncs.pfnRandomLong( 15, 30 ), dir.z, -75.0f, 75.0f ); - } - - int wallPuffSprite; - switch( gEngfuncs.pfnRandomLong( 0, 4 ) ) // every bullet makes a wall puff - { - case 0: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff1.spr"); break; - case 1: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff2.spr"); break; - case 2: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff3.spr"); break; - case 3: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff4.spr"); break; - } - TEMPENTITY *te = gEngfuncs.pEfxAPI->R_DefaultSprite( pTrace->endpos, wallPuffSprite, 30.0f ); - if( te ) - { - te->flags = FTENT_SPRANIMATE | FTENT_FADEOUT; - te->entity.curstate.rendermode = kRenderTransAdd; - te->entity.curstate.rendercolor.r = r; - te->entity.curstate.rendercolor.g = g; - te->entity.curstate.rendercolor.b = b; - te->entity.curstate.renderamt = 255; - te->entity.curstate.scale = 0.25; - te->entity.baseline.origin = 10 * pTrace->plane.normal; - } - - } -} - -int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount ) -{ - int tracer = 0; - int i; - qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false; - - if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 ) - { - vec3_t vecTracerSrc; - - if ( player ) - { - vec3_t offset( 0, 0, -4 ); - - // adjust tracer position for player - for ( i = 0; i < 3; i++ ) - { - vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16; - } - } - else - { - VectorCopy( vecSrc, vecTracerSrc ); - } - - if ( iTracerFreq != 1 ) // guns that always trace also always decal - tracer = 1; - - - EV_CreateTracer( vecTracerSrc, end ); - } - - return tracer; -} - -/* -============ -EV_DescribeBulletTypeParameters - -Sets iPenetrationPower and flPenetrationDistance. -If iBulletType is unknown, calls assert() and sets these two vars to 0 -============ -*/ -void EV_DescribeBulletTypeParameters(int iBulletType, int &iPenetrationPower, float &flPenetrationDistance) -{ - switch (iBulletType) - { - case BULLET_PLAYER_9MM: - { - iPenetrationPower = 21; - flPenetrationDistance = 800; - break; - } - - case BULLET_PLAYER_45ACP: - { - iPenetrationPower = 15; - flPenetrationDistance = 500; - break; - } - - case BULLET_PLAYER_50AE: - { - iPenetrationPower = 30; - flPenetrationDistance = 1000; - break; - } - - case BULLET_PLAYER_762MM: - { - iPenetrationPower = 39; - flPenetrationDistance = 5000; - break; - } - - case BULLET_PLAYER_556MM: - { - iPenetrationPower = 35; - flPenetrationDistance = 4000; - break; - } - - case BULLET_PLAYER_338MAG: - { - iPenetrationPower = 45; - flPenetrationDistance = 8000; - break; - } - - case BULLET_PLAYER_57MM: - { - iPenetrationPower = 30; - flPenetrationDistance = 2000; - break; - } - - case BULLET_PLAYER_357SIG: - { - iPenetrationPower = 25; - flPenetrationDistance = 800; - break; - } - - default: - { - iPenetrationPower = 0; - flPenetrationDistance = 0; - break; - } - } -} - - - -/* -================ -FireBullets - -Go to the trouble of combining multiple pellets into a single damage call. -================ -*/ -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, int iPenetration) -{ - int i; - pmtrace_t tr; - int iShot; - int tracer; - int iPenetrationPower; - float flPenetrationDistance; - - EV_DescribeBulletTypeParameters( iBulletType, iPenetrationPower, flPenetrationDistance ); - - for ( iShot = 1; iShot <= cShots; iShot++ ) - { - Vector vecShotSrc = vecSrc; - int iShotPenetration = iPenetration; - Vector vecDir, vecEnd; - - if ( iBulletType == BULLET_PLAYER_BUCKSHOT ) - { - //We randomize for the Shotgun. - float x, y, z; - do { - x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); - y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); - z = x*x+y*y; - } while (z > 1); - - for ( i = 0 ; i < 3; i++ ) - { - vecDir[i] = vecDirShooting[i] + x * vecSpread[0] * right[ i ] + y * vecSpread[1] * up [ i ]; - vecEnd[i] = vecShotSrc[ i ] + flDistance * vecDir[ i ]; - } - } - else //But other guns already have their spread randomized in the synched spread. - { - for ( i = 0 ; i < 3; i++ ) - { - vecDir[i] = vecDirShooting[i] + vecSpread[0] * right[ i ] + vecSpread[1] * up [ i ]; - vecEnd[i] = vecShotSrc[ i ] + flDistance * vecDir[ i ]; - } - } - - 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 ( idx - 1 ); - - - while (iShotPenetration != 0) - { - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace(vecShotSrc, vecEnd, 0, -1, &tr); - tracer = EV_HLDM_CheckTracer( idx, vecShotSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); - - float flCurrentDistance = tr.fraction * flDistance; -#ifdef _DEBUG - // absolute end - gEngfuncs.pEfxAPI->R_ParticleLine( vecEnd, vecEnd, 255, 255, 255, 20.0f); -#endif - - if( flCurrentDistance == 0.0f ) - { -#ifdef _DEBUG - // absolute start ( don't traceline after ) - gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, vecShotSrc, 255, 255, 0, 20.0f ); -#endif - break; - } - -#ifdef _DEBUG - // absoulute start - gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, vecShotSrc, 0, 0, 255, 20.0f); - // trace - gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, tr.endpos, 0, 255, 0, 20.0f ); - // hit - gEngfuncs.pEfxAPI->R_ParticleLine( tr.endpos, tr.endpos, 255, 0, 0, 20.0f); -#endif - if ( flCurrentDistance > flPenetrationDistance ) - iShotPenetration = 0; - else iShotPenetration--; - - char cTextureType = EV_HLDM_PlayTextureSound(idx, &tr, vecShotSrc, vecEnd, iBulletType ); - bool bSparks = true; - int r_smoke, g_smoke, b_smoke; - r_smoke = g_smoke = b_smoke = 40; - - switch (cTextureType) - { - case CHAR_TEX_METAL: - iPenetrationPower *= 0.15; - break; - case CHAR_TEX_CONCRETE: - r_smoke = g_smoke = b_smoke = 65; - iPenetrationPower *= 0.25; - break; - case CHAR_TEX_VENT: - case CHAR_TEX_GRATE: - iPenetrationPower *= 0.5; - break; - case CHAR_TEX_TILE: - iPenetrationPower *= 0.65; - break; - case CHAR_TEX_COMPUTER: - iPenetrationPower *= 0.4; - break; - case CHAR_TEX_WOOD: - bSparks = false; - r_smoke = 75; - g_smoke = 42; - b_smoke = 15; - break; - } - - // do damage, paint decals - EV_HLDM_DecalGunshot( &tr, iBulletType, 0, r_smoke, g_smoke, b_smoke, bSparks, cTextureType ); - - if( iBulletType == BULLET_PLAYER_BUCKSHOT || iShotPenetration == 0 ) - { - break; - } - - flDistance = (flDistance - flCurrentDistance) * 0.5; - for( int i = 0; i < 3; i++ ) - { - vecShotSrc[i] = tr.endpos[i] + iPenetrationPower * vecDir[i]; - vecEnd[i] = vecShotSrc[i] + flDistance * vecDir[i]; - } - - Vector vStartPos, vEndPos; - pmtrace_t trOriginal; - int i; - for( i = 1; i <= iPenetrationPower; i++ ) - { - for( int j = 0; j < 3; j++ ) - { - vStartPos[j] = tr.endpos[j] + i * vecDir[j]; - vEndPos[j] = vecDir[j] + vStartPos[j]; - } - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace(vStartPos, vEndPos, 0, -1, &trOriginal); - if ( trOriginal.startsolid && trOriginal.inopen ) - break; - } - if( i != iPenetrationPower ) - { - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace(vEndPos, vStartPos, 0, -1, &trOriginal); - EV_HLDM_DecalGunshot( &trOriginal, iBulletType, 0, r_smoke, g_smoke, b_smoke, bSparks, cTextureType ); - } - } - gEngfuncs.pEventAPI->EV_PopPMStates(); - } - -} - -void EV_TrainPitchAdjust( event_args_t *args ) -{ - int idx; - vec3_t origin; - - unsigned short us_params; - int noise; - float m_flVolume; - int pitch; - int stop; - - char sz[ 256 ]; - - idx = args->entindex; - - VectorCopy( args->origin, origin ); - - us_params = (unsigned short)args->iparam1; - stop = args->bparam1; - - m_flVolume = (float)(us_params & 0x003f)/40.0; - noise = (int)(((us_params) >> 12 ) & 0x0007); - pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) ); - - switch ( noise ) - { - case 1: strncpy( sz, "plats/ttrain1.wav", sizeof(sz)); break; - case 2: strncpy( sz, "plats/ttrain2.wav", sizeof(sz)); break; - case 3: strncpy( sz, "plats/ttrain3.wav", sizeof(sz)); break; - case 4: strncpy( sz, "plats/ttrain4.wav", sizeof(sz)); break; - case 5: strncpy( sz, "plats/ttrain6.wav", sizeof(sz)); break; - case 6: strncpy( sz, "plats/ttrain7.wav", sizeof(sz)); break; - default: - // no sound - strncpy( sz, "", sizeof(sz) ); - return; - } - - if ( stop ) - { - gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz ); - } - else - { - gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, 0, pitch ); - } -} - -void EV_CS16Client_KillEveryRound( TEMPENTITY *te, float frametime, float current_time ) -{ - if( g_flRoundTime > te->entity.curstate.fuser4 ) - { - // Mark it die on next TempEntUpdate - te->die = 0.0f; - // Set null renderamt, so it will be invisible now - // Also it will die immediately, if FTEMP_FADEOUT was set - te->entity.curstate.renderamt = 0; - } -} - -void RemoveBody(TEMPENTITY *te, float frametime, float current_time) -{ - // go underground... - /*if ( current_time >= 2 * te->entity.curstate.fuser2 + 5.0 ) - te->entity.origin.z -= 5.0 * frametime;*/ -} - -void HitBody(TEMPENTITY *ent, pmtrace_s *ptr) -{ - /*if ( ptr->plane.normal.z > 0.0 ) - ent->flags |= FTENT_NONE;*/ -} - - -void CreateCorpse(Vector *p_vOrigin, Vector *p_vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody) -{ - int modelIdx = gEngfuncs.pEventAPI->EV_FindModelIndex(pModel); - vec3_t null(0, 0, 0); - TEMPENTITY *model = gEngfuncs.pEfxAPI->R_TempModel( (float*)p_vOrigin, - null, - (float*)p_vAngles, - gEngfuncs.pfnGetCvarFloat("cl_corpsestay"), - modelIdx, - 0 ); - - if(model) - { - //model->frameMax = -1; - model->entity.curstate.animtime = flAnimTime; - model->entity.curstate.framerate = 1.0; - model->entity.curstate.frame = 0; - model->entity.curstate.sequence = iSequence; - model->entity.curstate.body = iBody; - model->entity.curstate.fuser1 = gHUD.m_flTime + 1.0; - model->entity.curstate.fuser2 = gEngfuncs.pfnGetCvarFloat("cl_corpsestay") + gHUD.m_flTime; - model->hitcallback = HitBody; - model->callback = RemoveBody; - } -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "entity_types.h" +#include "usercmd.h" +#include "pm_defs.h" +#include "pm_materials.h" + +#include "eventscripts.h" +#include "ev_hldm.h" + +#include "r_efx.h" +#include "triangleapi.h" +#include "event_api.h" +#include "event_args.h" +#include "in_defs.h" + +#include + +#include "r_studioint.h" +#include "com_model.h" + +#include + +static int tracerCount[ 32 ]; +extern float g_flRoundTime; + +extern "C" char PM_FindTextureType( char *name ); + +// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the +// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture. +// returns volume of strike instrument (crowbar) to play +void EV_HLDM_NewExplode( float x, float y, float z, float ScaleExplode1 ) +{ + + int iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/dexplo.spr"); + TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 5 ), + Vector( 0, 0, 0 ), + ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL ); + + if(pTemp) + { + pTemp->fadeSpeed = 90.0; + pTemp->entity.curstate.framerate = 37.0; + pTemp->entity.curstate.renderamt = 155; + pTemp->entity.curstate.rendercolor.r = 255; + pTemp->entity.curstate.rendercolor.g = 255; + pTemp->entity.curstate.rendercolor.b = 255; + } + + iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/fexplo.spr"); + pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 10), + Vector( 0, 0, 0 ), + ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL ); + + if(pTemp) + { + pTemp->fadeSpeed = 90.0; + pTemp->entity.curstate.framerate = 35.0; + pTemp->entity.curstate.renderamt = 150; + pTemp->entity.curstate.rendercolor.r = 255; + pTemp->entity.curstate.rendercolor.g = 255; + pTemp->entity.curstate.rendercolor.b = 255; + pTemp->entity.angles = Vector( 90, 0, 0 ); + } + + for( int i = 1; i <= 10; i++ ) + { + int iSmokeSprite = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/smoke.spr"); + TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z ), + Vector( (int)gEngfuncs.pfnRandomLong( -100, 100 ), (int)gEngfuncs.pfnRandomLong( -100, 100 ), (int)gEngfuncs.pfnRandomLong( -100, 100 ) ), + 5, iSmokeSprite, kRenderTransAlpha, kRenderFxNone, 1.0, 0.5, FTENT_FADEOUT | FTENT_PERSIST ); + + if(pTemp) + { + pTemp->fadeSpeed = 0.6; + pTemp->entity.curstate.framerate = 1; + pTemp->entity.curstate.renderamt = 255; + int Color = gEngfuncs.pfnRandomLong( 0, 140 ); + pTemp->entity.curstate.rendercolor.r = Color; + pTemp->entity.curstate.rendercolor.g = Color; + pTemp->entity.curstate.rendercolor.b = Color; + } + } + +} + +char EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType ) +{ + // hit the world, try to play sound based on texture material type + char chTextureType = CHAR_TEX_CONCRETE; + float fvol; + float fvolbar; + char *rgsz[4]; + int cnt; + float fattn = ATTN_NORM; + int entity; + char *pTextureName; + char texname[ 64 ]; + char szbuffer[ 64 ]; + + entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr ); + + // FIXME check if playtexture sounds movevar is set + // + + chTextureType = 0; + + // Player + if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() ) + { + // hit body + chTextureType = CHAR_TEX_FLESH; + } + else if ( entity == 0 ) + { + // get texture from entity or world (world is ent(0)) + pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd ); + + if ( pTextureName ) + { + strncpy( texname, pTextureName, sizeof( texname ) ); + pTextureName = texname; + + // strip leading '-0' or '+0~' or '{' or '!' + if (*pTextureName == '-' || *pTextureName == '+') + { + pTextureName += 2; + } + + if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') + { + pTextureName++; + } + + // '}}' + strncpy( szbuffer, pTextureName, sizeof(szbuffer) ); + szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0; + + // get texture type + chTextureType = PM_FindTextureType( szbuffer ); + } + } + + switch (chTextureType) + { + default: + case CHAR_TEX_CONCRETE: + { + fvol = 0.9; + fvolbar = 0.6; + rgsz[0] = "player/pl_step1.wav"; + rgsz[1] = "player/pl_step2.wav"; + cnt = 2; + break; + } + case CHAR_TEX_METAL: + { + fvol = 0.9; + fvolbar = 0.3; + rgsz[0] = "player/pl_metal1.wav"; + rgsz[1] = "player/pl_metal2.wav"; + cnt = 2; + break; + } + case CHAR_TEX_DIRT: + { + fvol = 0.9; + fvolbar = 0.1; + rgsz[0] = "player/pl_dirt1.wav"; + rgsz[1] = "player/pl_dirt2.wav"; + rgsz[2] = "player/pl_dirt3.wav"; + cnt = 3; + break; + } + case CHAR_TEX_VENT: + { + fvol = 0.5; + fvolbar = 0.3; + rgsz[0] = "player/pl_duct1.wav"; + rgsz[1] = "player/pl_duct1.wav"; + cnt = 2; + break; + } + case CHAR_TEX_GRATE: + { + fvol = 0.9; + fvolbar = 0.5; + rgsz[0] = "player/pl_grate1.wav"; + rgsz[1] = "player/pl_grate4.wav"; + cnt = 2; + break; + } + case CHAR_TEX_TILE: + { + fvol = 0.8; + fvolbar = 0.2; + rgsz[0] = "player/pl_tile1.wav"; + rgsz[1] = "player/pl_tile3.wav"; + rgsz[2] = "player/pl_tile2.wav"; + rgsz[3] = "player/pl_tile4.wav"; + cnt = 4; + break; + } + case CHAR_TEX_SLOSH: + { + fvol = 0.9; + fvolbar = 0; + rgsz[0] = "player/pl_slosh1.wav"; + rgsz[1] = "player/pl_slosh3.wav"; + rgsz[2] = "player/pl_slosh2.wav"; + rgsz[3] = "player/pl_slosh4.wav"; + cnt = 4; + break; + } + case CHAR_TEX_SNOW: + { + fvol = 0.7; + fvolbar = 0.4; + rgsz[0] = "debris/pl_snow1.wav"; + rgsz[1] = "debris/pl_snow2.wav"; + rgsz[2] = "debris/pl_snow3.wav"; + rgsz[3] = "debris/pl_snow4.wav"; + cnt = 4; + break; + } + case CHAR_TEX_WOOD: + { + fvol = 0.9; + fvolbar = 0.2; + rgsz[0] = "debris/wood1.wav"; + rgsz[1] = "debris/wood2.wav"; + rgsz[2] = "debris/wood3.wav"; + cnt = 3; + break; + } + case CHAR_TEX_GLASS: + case CHAR_TEX_COMPUTER: + { + fvol = 0.8; + fvolbar = 0.2; + rgsz[0] = "debris/glass1.wav"; + rgsz[1] = "debris/glass2.wav"; + rgsz[2] = "debris/glass3.wav"; + cnt = 3; + break; + } + case CHAR_TEX_FLESH: + { + fvol = 1.0;fvolbar = 0.2; + rgsz[0] = "weapons/bullet_hit1.wav"; + rgsz[1] = "weapons/bullet_hit2.wav"; + fattn = 1.0; + cnt = 2; + break; + } + } + + // play material hit sound + gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) ); + + return chTextureType; +} + +char *EV_HLDM_DamageDecal( physent_t *pe ) +{ + static char decalname[ 32 ]; + int idx; + + if ( pe->classnumber == 1 ) + { + idx = gEngfuncs.pfnRandomLong( 0, 2 ); + sprintf( decalname, "{break%i", idx + 1 ); + } + else if ( pe->rendermode != kRenderNormal ) + { + sprintf( decalname, "{bproof1" ); + } + else + { + idx = gEngfuncs.pfnRandomLong( 0, 4 ); + sprintf( decalname, "{shot%i", idx + 1 ); + } + return decalname; +} + +void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName, char chTextureType ) +{ + int iRand; + physent_t *pe; + + gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos ); + + + iRand = gEngfuncs.pfnRandomLong(0,0x7FFF); + if ( iRand < (0x7fff/2) )// not every bullet makes a sound. + { + if( chTextureType == CHAR_TEX_VENT || chTextureType == CHAR_TEX_METAL ) + { + switch( iRand % 2 ) + { + case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_metal-1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; + case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_metal-2.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; + } + } + else + { + switch( iRand % 7) + { + case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break; + case 5: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_conc-1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; + case 6: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_conc-2.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break; + } + } + + } + + pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); + + // Only decal brush models such as the world etc. + if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) ) + { + if ( CVAR_GET_FLOAT( "r_decals" ) ) + { + gEngfuncs.pEfxAPI->R_DecalShoot( + gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ), + gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 ); + + } + } +} + +void EV_HLDM_DecalGunshot(pmtrace_t *pTrace, int iBulletType, float scale, int r, int g, int b, bool bCreateSparks, char cTextureType) +{ + physent_t *pe; + + pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent ); + + if ( pe && pe->solid == SOLID_BSP ) + { + EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ), cTextureType ); + + Vector dir = pTrace->plane.normal; + dir = dir * gEngfuncs.pfnRandomFloat(4.0f, 12.0f ); + if( bCreateSparks ) + { + gEngfuncs.pEfxAPI->R_StreakSplash( pTrace->endpos, dir, 4, gEngfuncs.pfnRandomLong( 15, 30 ), dir.z, -75.0f, 75.0f ); + } + + int wallPuffSprite; + switch( gEngfuncs.pfnRandomLong( 0, 4 ) ) // every bullet makes a wall puff + { + case 0: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff1.spr"); break; + case 1: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff2.spr"); break; + case 2: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff3.spr"); break; + case 3: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff4.spr"); break; + } + TEMPENTITY *te = gEngfuncs.pEfxAPI->R_DefaultSprite( pTrace->endpos, wallPuffSprite, 30.0f ); + if( te ) + { + te->flags = FTENT_SPRANIMATE | FTENT_FADEOUT; + te->entity.curstate.rendermode = kRenderTransAdd; + te->entity.curstate.rendercolor.r = r; + te->entity.curstate.rendercolor.g = g; + te->entity.curstate.rendercolor.b = b; + te->entity.curstate.renderamt = 255; + te->entity.curstate.scale = 0.25; + te->entity.baseline.origin = 10 * pTrace->plane.normal; + } + + } +} + +int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount ) +{ + int tracer = 0; + int i; + qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false; + + if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 ) + { + vec3_t vecTracerSrc; + + if ( player ) + { + vec3_t offset( 0, 0, -4 ); + + // adjust tracer position for player + for ( i = 0; i < 3; i++ ) + { + vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16; + } + } + else + { + VectorCopy( vecSrc, vecTracerSrc ); + } + + if ( iTracerFreq != 1 ) // guns that always trace also always decal + tracer = 1; + + + EV_CreateTracer( vecTracerSrc, end ); + } + + return tracer; +} + +/* +============ +EV_DescribeBulletTypeParameters + +Sets iPenetrationPower and flPenetrationDistance. +If iBulletType is unknown, calls assert() and sets these two vars to 0 +============ +*/ +void EV_DescribeBulletTypeParameters(int iBulletType, int &iPenetrationPower, float &flPenetrationDistance) +{ + switch (iBulletType) + { + case BULLET_PLAYER_9MM: + { + iPenetrationPower = 21; + flPenetrationDistance = 800; + break; + } + + case BULLET_PLAYER_45ACP: + { + iPenetrationPower = 15; + flPenetrationDistance = 500; + break; + } + + case BULLET_PLAYER_50AE: + { + iPenetrationPower = 30; + flPenetrationDistance = 1000; + break; + } + + case BULLET_PLAYER_762MM: + { + iPenetrationPower = 39; + flPenetrationDistance = 5000; + break; + } + + case BULLET_PLAYER_556MM: + { + iPenetrationPower = 35; + flPenetrationDistance = 4000; + break; + } + + case BULLET_PLAYER_338MAG: + { + iPenetrationPower = 45; + flPenetrationDistance = 8000; + break; + } + + case BULLET_PLAYER_57MM: + { + iPenetrationPower = 30; + flPenetrationDistance = 2000; + break; + } + + case BULLET_PLAYER_357SIG: + { + iPenetrationPower = 25; + flPenetrationDistance = 800; + break; + } + + default: + { + iPenetrationPower = 0; + flPenetrationDistance = 0; + break; + } + } +} + + + +/* +================ +FireBullets + +Go to the trouble of combining multiple pellets into a single damage call. +================ +*/ +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, int iPenetration) +{ + int i; + pmtrace_t tr; + int iShot; + int tracer; + int iPenetrationPower; + float flPenetrationDistance; + + EV_DescribeBulletTypeParameters( iBulletType, iPenetrationPower, flPenetrationDistance ); + + for ( iShot = 1; iShot <= cShots; iShot++ ) + { + Vector vecShotSrc = vecSrc; + int iShotPenetration = iPenetration; + Vector vecDir, vecEnd; + + if ( iBulletType == BULLET_PLAYER_BUCKSHOT ) + { + //We randomize for the Shotgun. + float x, y, z; + do { + x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); + y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5); + z = x*x+y*y; + } while (z > 1); + + for ( i = 0 ; i < 3; i++ ) + { + vecDir[i] = vecDirShooting[i] + x * vecSpread[0] * right[ i ] + y * vecSpread[1] * up [ i ]; + vecEnd[i] = vecShotSrc[ i ] + flDistance * vecDir[ i ]; + } + } + else //But other guns already have their spread randomized in the synched spread. + { + for ( i = 0 ; i < 3; i++ ) + { + vecDir[i] = vecDirShooting[i] + vecSpread[0] * right[ i ] + vecSpread[1] * up [ i ]; + vecEnd[i] = vecShotSrc[ i ] + flDistance * vecDir[ i ]; + } + } + + 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 ( idx - 1 ); + + + while (iShotPenetration != 0) + { + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace(vecShotSrc, vecEnd, 0, -1, &tr); + tracer = EV_HLDM_CheckTracer( idx, vecShotSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount ); + + float flCurrentDistance = tr.fraction * flDistance; +#ifdef _DEBUG + // absolute end + gEngfuncs.pEfxAPI->R_ParticleLine( vecEnd, vecEnd, 255, 255, 255, 20.0f); +#endif + + if( flCurrentDistance == 0.0f ) + { +#ifdef _DEBUG + // absolute start ( don't traceline after ) + gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, vecShotSrc, 255, 255, 0, 20.0f ); +#endif + break; + } + +#ifdef _DEBUG + // absoulute start + gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, vecShotSrc, 0, 0, 255, 20.0f); + // trace + gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, tr.endpos, 0, 255, 0, 20.0f ); + // hit + gEngfuncs.pEfxAPI->R_ParticleLine( tr.endpos, tr.endpos, 255, 0, 0, 20.0f); +#endif + if ( flCurrentDistance > flPenetrationDistance ) + iShotPenetration = 0; + else iShotPenetration--; + + char cTextureType = EV_HLDM_PlayTextureSound(idx, &tr, vecShotSrc, vecEnd, iBulletType ); + bool bSparks = true; + int r_smoke, g_smoke, b_smoke; + r_smoke = g_smoke = b_smoke = 40; + + switch (cTextureType) + { + case CHAR_TEX_METAL: + iPenetrationPower *= 0.15; + break; + case CHAR_TEX_CONCRETE: + r_smoke = g_smoke = b_smoke = 65; + iPenetrationPower *= 0.25; + break; + case CHAR_TEX_VENT: + case CHAR_TEX_GRATE: + iPenetrationPower *= 0.5; + break; + case CHAR_TEX_TILE: + iPenetrationPower *= 0.65; + break; + case CHAR_TEX_COMPUTER: + iPenetrationPower *= 0.4; + break; + case CHAR_TEX_WOOD: + bSparks = false; + r_smoke = 75; + g_smoke = 42; + b_smoke = 15; + break; + } + + // do damage, paint decals + EV_HLDM_DecalGunshot( &tr, iBulletType, 0, r_smoke, g_smoke, b_smoke, bSparks, cTextureType ); + + if( iBulletType == BULLET_PLAYER_BUCKSHOT || iShotPenetration == 0 ) + { + break; + } + + flDistance = (flDistance - flCurrentDistance) * 0.5; + for( int i = 0; i < 3; i++ ) + { + vecShotSrc[i] = tr.endpos[i] + iPenetrationPower * vecDir[i]; + vecEnd[i] = vecShotSrc[i] + flDistance * vecDir[i]; + } + + Vector vStartPos, vEndPos; + pmtrace_t trOriginal; + int i; + for( i = 1; i <= iPenetrationPower; i++ ) + { + for( int j = 0; j < 3; j++ ) + { + vStartPos[j] = tr.endpos[j] + i * vecDir[j]; + vEndPos[j] = vecDir[j] + vStartPos[j]; + } + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace(vStartPos, vEndPos, 0, -1, &trOriginal); + if ( trOriginal.startsolid && trOriginal.inopen ) + break; + } + if( i != iPenetrationPower ) + { + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace(vEndPos, vStartPos, 0, -1, &trOriginal); + EV_HLDM_DecalGunshot( &trOriginal, iBulletType, 0, r_smoke, g_smoke, b_smoke, bSparks, cTextureType ); + } + } + gEngfuncs.pEventAPI->EV_PopPMStates(); + } + +} + +void EV_TrainPitchAdjust( event_args_t *args ) +{ + int idx; + vec3_t origin; + + unsigned short us_params; + int noise; + float m_flVolume; + int pitch; + int stop; + + char sz[ 256 ]; + + idx = args->entindex; + + VectorCopy( args->origin, origin ); + + us_params = (unsigned short)args->iparam1; + stop = args->bparam1; + + m_flVolume = (float)(us_params & 0x003f)/40.0; + noise = (int)(((us_params) >> 12 ) & 0x0007); + pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) ); + + switch ( noise ) + { + case 1: strncpy( sz, "plats/ttrain1.wav", sizeof(sz)); break; + case 2: strncpy( sz, "plats/ttrain2.wav", sizeof(sz)); break; + case 3: strncpy( sz, "plats/ttrain3.wav", sizeof(sz)); break; + case 4: strncpy( sz, "plats/ttrain4.wav", sizeof(sz)); break; + case 5: strncpy( sz, "plats/ttrain6.wav", sizeof(sz)); break; + case 6: strncpy( sz, "plats/ttrain7.wav", sizeof(sz)); break; + default: + // no sound + strncpy( sz, "", sizeof(sz) ); + return; + } + + if ( stop ) + { + gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz ); + } + else + { + gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, 0, pitch ); + } +} + +void EV_CS16Client_KillEveryRound( TEMPENTITY *te, float frametime, float current_time ) +{ + if( g_flRoundTime > te->entity.curstate.fuser4 ) + { + // Mark it die on next TempEntUpdate + te->die = 0.0f; + // Set null renderamt, so it will be invisible now + // Also it will die immediately, if FTEMP_FADEOUT was set + te->entity.curstate.renderamt = 0; + } +} + +void RemoveBody(TEMPENTITY *te, float frametime, float current_time) +{ + // go underground... + /*if ( current_time >= 2 * te->entity.curstate.fuser2 + 5.0 ) + te->entity.origin.z -= 5.0 * frametime;*/ +} + +void HitBody(TEMPENTITY *ent, pmtrace_s *ptr) +{ + /*if ( ptr->plane.normal.z > 0.0 ) + ent->flags |= FTENT_NONE;*/ +} + + +void CreateCorpse(Vector *p_vOrigin, Vector *p_vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody) +{ + int modelIdx = gEngfuncs.pEventAPI->EV_FindModelIndex(pModel); + vec3_t null(0, 0, 0); + TEMPENTITY *model = gEngfuncs.pEfxAPI->R_TempModel( (float*)p_vOrigin, + null, + (float*)p_vAngles, + gEngfuncs.pfnGetCvarFloat("cl_corpsestay"), + modelIdx, + 0 ); + + if(model) + { + //model->frameMax = -1; + model->entity.curstate.animtime = flAnimTime; + model->entity.curstate.framerate = 1.0; + model->entity.curstate.frame = 0; + model->entity.curstate.sequence = iSequence; + model->entity.curstate.body = iBody; + model->entity.curstate.fuser1 = gHUD.m_flTime + 1.0; + model->entity.curstate.fuser2 = gEngfuncs.pfnGetCvarFloat("cl_corpsestay") + gHUD.m_flTime; + model->hitcallback = HitBody; + model->callback = RemoveBody; + } +} diff --git a/cl_dll/events/hl_events.cpp b/cl_dll/events/hl_events.cpp index 7a33a27..5c2505f 100644 --- a/cl_dll/events/hl_events.cpp +++ b/cl_dll/events/hl_events.cpp @@ -1,62 +1,62 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#include "events.h" - -/* -====================== -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 ) -{ - HOOK_EVENT( ak47, FireAK47 ); - HOOK_EVENT( aug, FireAUG ); - HOOK_EVENT( awp, FireAWP ); - HOOK_EVENT( createexplo, CreateExplo ); - HOOK_EVENT( createsmoke, CreateSmoke ); - HOOK_EVENT( deagle, FireDEAGLE ); - HOOK_EVENT( decal_reset, DecalReset ); - HOOK_EVENT( elite_left, FireEliteLeft ); - HOOK_EVENT( elite_right, FireEliteRight ); - HOOK_EVENT( famas, FireFAMAS ); - HOOK_EVENT( fiveseven, Fire57 ); - HOOK_EVENT( g3sg1, FireG3SG1 ); - HOOK_EVENT( galil, FireGALIL ); - HOOK_EVENT( glock18, Fireglock18 ); - HOOK_EVENT( knife, Knife ); - HOOK_EVENT( m249, FireM249 ); - HOOK_EVENT( m3, FireM3 ); - HOOK_EVENT( m4a1, FireM4A1 ); - HOOK_EVENT( mac10, FireMAC10 ); - HOOK_EVENT( mp5n, FireMP5 ); - HOOK_EVENT( p228, FireP228 ); - HOOK_EVENT( p90, FireP90 ); - HOOK_EVENT( scout, FireScout ); - HOOK_EVENT( sg550, FireSG550 ); - HOOK_EVENT( sg552, FireSG552 ); - HOOK_EVENT( tmp, FireTMP ); - HOOK_EVENT( ump45, FireUMP45 ); - HOOK_EVENT( usp, FireUSP ); - HOOK_EVENT( vehicle, Vehicle ); - HOOK_EVENT( xm1014, FireXM1014 ); -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#include "events.h" + +/* +====================== +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 ) +{ + HOOK_EVENT( ak47, FireAK47 ); + HOOK_EVENT( aug, FireAUG ); + HOOK_EVENT( awp, FireAWP ); + HOOK_EVENT( createexplo, CreateExplo ); + HOOK_EVENT( createsmoke, CreateSmoke ); + HOOK_EVENT( deagle, FireDEAGLE ); + HOOK_EVENT( decal_reset, DecalReset ); + HOOK_EVENT( elite_left, FireEliteLeft ); + HOOK_EVENT( elite_right, FireEliteRight ); + HOOK_EVENT( famas, FireFAMAS ); + HOOK_EVENT( fiveseven, Fire57 ); + HOOK_EVENT( g3sg1, FireG3SG1 ); + HOOK_EVENT( galil, FireGALIL ); + HOOK_EVENT( glock18, Fireglock18 ); + HOOK_EVENT( knife, Knife ); + HOOK_EVENT( m249, FireM249 ); + HOOK_EVENT( m3, FireM3 ); + HOOK_EVENT( m4a1, FireM4A1 ); + HOOK_EVENT( mac10, FireMAC10 ); + HOOK_EVENT( mp5n, FireMP5 ); + HOOK_EVENT( p228, FireP228 ); + HOOK_EVENT( p90, FireP90 ); + HOOK_EVENT( scout, FireScout ); + HOOK_EVENT( sg550, FireSG550 ); + HOOK_EVENT( sg552, FireSG552 ); + HOOK_EVENT( tmp, FireTMP ); + HOOK_EVENT( ump45, FireUMP45 ); + HOOK_EVENT( usp, FireUSP ); + HOOK_EVENT( vehicle, Vehicle ); + HOOK_EVENT( xm1014, FireXM1014 ); +} diff --git a/cl_dll/hud/ammo.cpp b/cl_dll/hud/ammo.cpp index 1c030d7..db18c56 100644 --- a/cl_dll/hud/ammo.cpp +++ b/cl_dll/hud/ammo.cpp @@ -1,1671 +1,1671 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// Ammo.cpp -// -// implementation of CHudAmmo class -// - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" -#include "pm_shared.h" - -#include -#include - -#include "ammohistory.h" -#include "eventscripts.h" -#include "com_weapons.h" - -//#include "vgui_TeamFortressViewport.h" - -#ifdef _MSC_VER - -void sincosf (float rad, float *sine, float *cosine) -{ - *sine = sinf (rad); - *cosine = cosf (rad); -} - -#ifndef M_PI -#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h -#endif - -#endif - -WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise - // this points to the active weapon menu item -WEAPON *gpLastSel; // Last weapon menu selection - -client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount); - -WeaponsResource gWR; - -int g_weaponselect = 0; -int g_iShotsFired; - -void WeaponsResource :: LoadAllWeaponSprites( void ) -{ - for (int i = 0; i < MAX_WEAPONS; i++) - { - if ( rgWeapons[i].iId ) - LoadWeaponSprites( &rgWeapons[i] ); - } -} - -int WeaponsResource :: CountAmmo( int iId ) -{ - if ( iId < 0 ) - return 0; - - return riAmmo[iId]; -} - -int WeaponsResource :: HasAmmo( WEAPON *p ) -{ - if ( !p ) - return FALSE; - - // weapons with no max ammo can always be selected - if ( p->iMax1 == -1 ) - return TRUE; - - return (p->iAmmoType == -1) || p->iClip > 0 || CountAmmo(p->iAmmoType) - || CountAmmo(p->iAmmo2Type) || ( p->iFlags & WEAPON_FLAGS_SELECTONEMPTY ); -} - - -void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon ) -{ - int i, iRes; - - if (ScreenWidth < 640) - iRes = 320; - else - iRes = 640; - - char sz[128]; - - if ( !pWeapon ) - return; - - memset( &pWeapon->rcActive, 0, sizeof(wrect_t) ); - memset( &pWeapon->rcInactive, 0, sizeof(wrect_t) ); - memset( &pWeapon->rcAmmo, 0, sizeof(wrect_t) ); - memset( &pWeapon->rcAmmo2, 0, sizeof(wrect_t) ); - pWeapon->hInactive = 0; - pWeapon->hActive = 0; - pWeapon->hAmmo = 0; - pWeapon->hAmmo2 = 0; - - sprintf(sz, "sprites/%s.txt", pWeapon->szName); - client_sprite_t *pList = SPR_GetList(sz, &i); - - if (!pList) - return; - - client_sprite_t *p; - - p = GetSpriteList( pList, "crosshair", iRes, i ); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hCrosshair = SPR_Load(sz); - pWeapon->rcCrosshair = p->rc; - } - else - pWeapon->hCrosshair = 0; - - p = GetSpriteList(pList, "autoaim", iRes, i); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hAutoaim = SPR_Load(sz); - pWeapon->rcAutoaim = p->rc; - } - else - pWeapon->hAutoaim = 0; - - p = GetSpriteList( pList, "zoom", iRes, i ); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hZoomedCrosshair = SPR_Load(sz); - pWeapon->rcZoomedCrosshair = p->rc; - } - else - { - pWeapon->hZoomedCrosshair = pWeapon->hCrosshair; //default to non-zoomed crosshair - pWeapon->rcZoomedCrosshair = pWeapon->rcCrosshair; - } - - p = GetSpriteList(pList, "zoom_autoaim", iRes, i); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hZoomedAutoaim = SPR_Load(sz); - pWeapon->rcZoomedAutoaim = p->rc; - } - else - { - pWeapon->hZoomedAutoaim = pWeapon->hZoomedCrosshair; //default to zoomed crosshair - pWeapon->rcZoomedAutoaim = pWeapon->rcZoomedCrosshair; - } - - p = GetSpriteList(pList, "weapon", iRes, i); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hInactive = SPR_Load(sz); - pWeapon->rcInactive = p->rc; - - gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); - } - else - pWeapon->hInactive = 0; - - p = GetSpriteList(pList, "weapon_s", iRes, i); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hActive = SPR_Load(sz); - pWeapon->rcActive = p->rc; - } - else - pWeapon->hActive = 0; - - p = GetSpriteList(pList, "ammo", iRes, i); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hAmmo = SPR_Load(sz); - pWeapon->rcAmmo = p->rc; - - gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); - } - else - pWeapon->hAmmo = 0; - - p = GetSpriteList(pList, "ammo2", iRes, i); - if (p) - { - sprintf(sz, "sprites/%s.spr", p->szSprite); - pWeapon->hAmmo2 = SPR_Load(sz); - pWeapon->rcAmmo2 = p->rc; - - gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); - } - else - pWeapon->hAmmo2 = 0; - -} - -// Returns the first weapon for a given slot. -WEAPON *WeaponsResource :: GetFirstPos( int iSlot ) -{ - WEAPON *pret = NULL; - - for (int i = 0; i < MAX_WEAPON_POSITIONS; i++) - { - if ( rgSlots[iSlot][i] /*&& HasAmmo( rgSlots[iSlot][i] )*/ ) - { - pret = rgSlots[iSlot][i]; - break; - } - } - - return pret; -} - - -WEAPON* WeaponsResource :: GetNextActivePos( int iSlot, int iSlotPos ) -{ - if ( iSlotPos >= MAX_WEAPON_POSITIONS || iSlot >= MAX_WEAPON_SLOTS ) - return NULL; - - WEAPON *p = gWR.rgSlots[ iSlot ][ iSlotPos+1 ]; - - if ( !p || !gWR.HasAmmo(p) ) - return GetNextActivePos( iSlot, iSlotPos + 1 ); - - return p; -} - - -int giBucketHeight, giBucketWidth, giABHeight, giABWidth; // Ammo Bar width and height - -HSPRITE ghsprBuckets; // Sprite for top row of weapons menu - -DECLARE_MESSAGE(m_Ammo, CurWeapon ); // Current weapon and clip -DECLARE_MESSAGE(m_Ammo, WeaponList); // new weapon type -DECLARE_MESSAGE(m_Ammo, AmmoX); // update known ammo type's count -DECLARE_MESSAGE(m_Ammo, AmmoPickup); // flashes an ammo pickup record -DECLARE_MESSAGE(m_Ammo, WeapPickup); // flashes a weapon pickup record -DECLARE_MESSAGE(m_Ammo, HideWeapon); // hides the weapon, ammo, and crosshair displays temporarily -DECLARE_MESSAGE(m_Ammo, ItemPickup); -DECLARE_MESSAGE(m_Ammo, Crosshair); -DECLARE_MESSAGE(m_Ammo, Brass); - -DECLARE_COMMAND(m_Ammo, Slot1); -DECLARE_COMMAND(m_Ammo, Slot2); -DECLARE_COMMAND(m_Ammo, Slot3); -DECLARE_COMMAND(m_Ammo, Slot4); -DECLARE_COMMAND(m_Ammo, Slot5); -DECLARE_COMMAND(m_Ammo, Slot6); -DECLARE_COMMAND(m_Ammo, Slot7); -DECLARE_COMMAND(m_Ammo, Slot8); -DECLARE_COMMAND(m_Ammo, Slot9); -DECLARE_COMMAND(m_Ammo, Slot10); -DECLARE_COMMAND(m_Ammo, Close); -DECLARE_COMMAND(m_Ammo, NextWeapon); -DECLARE_COMMAND(m_Ammo, PrevWeapon); -DECLARE_COMMAND(m_Ammo, Adjust_Crosshair); -DECLARE_COMMAND(m_Ammo, Rebuy); -DECLARE_COMMAND(m_Ammo, Autobuy); - -// width of ammo fonts -#define AMMO_SMALL_WIDTH 10 -#define AMMO_LARGE_WIDTH 20 - -#define HISTORY_DRAW_TIME "5" - -int CHudAmmo::Init(void) -{ - gHUD.AddHudElem(this); - - HOOK_MESSAGE(CurWeapon); - HOOK_MESSAGE(WeaponList); - HOOK_MESSAGE(AmmoPickup); - HOOK_MESSAGE(WeapPickup); - HOOK_MESSAGE(ItemPickup); - HOOK_MESSAGE(HideWeapon); - HOOK_MESSAGE(AmmoX); - HOOK_MESSAGE(Crosshair); - HOOK_MESSAGE(Brass); - - HOOK_COMMAND("slot1", Slot1); - HOOK_COMMAND("slot2", Slot2); - HOOK_COMMAND("slot3", Slot3); - HOOK_COMMAND("slot4", Slot4); - HOOK_COMMAND("slot5", Slot5); - HOOK_COMMAND("slot6", Slot6); - HOOK_COMMAND("slot7", Slot7); - HOOK_COMMAND("slot8", Slot8); - HOOK_COMMAND("slot9", Slot9); - HOOK_COMMAND("slot10", Slot10); - HOOK_COMMAND("cancelselect", Close); - HOOK_COMMAND("invnext", NextWeapon); - HOOK_COMMAND("invprev", PrevWeapon); - HOOK_COMMAND("adjust_crosshair", Adjust_Crosshair); - HOOK_COMMAND("rebuy", Rebuy); - HOOK_COMMAND("autobuy", Autobuy); - - Reset(); - - m_pHud_DrawHistory_Time = CVAR_CREATE( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0 ); - m_pHud_FastSwitch = CVAR_CREATE( "hud_fastswitch", "0", FCVAR_ARCHIVE ); // controls whether or not weapons can be selected in one keypress - CVAR_CREATE( "cl_observercrosshair", "1", 0 ); - m_pClCrosshairColor = CVAR_CREATE( "cl_crosshair_color", "50 250 50", FCVAR_ARCHIVE ); - m_pClCrosshairTranslucent = CVAR_CREATE( "cl_crosshair_translucent", "1", FCVAR_ARCHIVE ); - m_pClCrosshairSize = CVAR_CREATE( "cl_crosshair_size", "auto", FCVAR_ARCHIVE ); - m_pClDynamicCrosshair = CVAR_CREATE("cl_dynamiccrosshair", "1", FCVAR_ARCHIVE); - - m_iFlags |= HUD_ACTIVE; //!!! - m_R = 50; - m_G = 250; - m_B = 50; - m_iAlpha = 200; - - m_cvarB = m_cvarR = m_cvarG = -1; - m_iCurrentCrosshair = 0; - m_bAdditive = 1; - m_iCrosshairScaleBase = 1024; - m_bDrawCrosshair = true; - - gWR.Init(); - gHR.Init(); - - return 1; -}; - -void CHudAmmo::Reset(void) -{ - m_fFade = 0; - m_iFlags |= HUD_ACTIVE; //!!! - - gpActiveSel = NULL; - gHUD.m_iHideHUDDisplay = 0; - - gWR.Reset(); - gHR.Reset(); - - // VidInit(); - -} - -int CHudAmmo::VidInit(void) -{ - // Load sprites for buckets (top row of weapon menu) - m_HUD_bucket0 = gHUD.GetSpriteIndex( "bucket1" ); - m_HUD_selection = gHUD.GetSpriteIndex( "selection" ); - - ghsprBuckets = gHUD.GetSprite(m_HUD_bucket0); - giBucketWidth = gHUD.GetSpriteRect(m_HUD_bucket0).right - gHUD.GetSpriteRect(m_HUD_bucket0).left; - giBucketHeight = gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top; - - gHR.iHistoryGap = max( gHR.iHistoryGap, gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top); - - // If we've already loaded weapons, let's get new sprites - gWR.LoadAllWeaponSprites(); - - if (ScreenWidth >= 640) - { - giABWidth = 20; - giABHeight = 4; - } - else - { - giABWidth = 10; - giABHeight = 2; - } - - return 1; -} - -// -// Think: -// Used for selection of weapon menu item. -// -void CHudAmmo::Think(void) -{ - if ( gHUD.m_fPlayerDead ) - return; - - if ( gHUD.m_iWeaponBits != gWR.iOldWeaponBits ) - { - gWR.iOldWeaponBits = gHUD.m_iWeaponBits; - - for (int i = 0; i < MAX_WEAPONS-1; i++ ) - { - WEAPON *p = gWR.GetWeapon(i); - - if ( p ) - { - if ( gHUD.m_iWeaponBits & ( 1 << p->iId ) ) - { - gWR.PickupWeapon( p ); - } - else - { - gWR.DropWeapon( p ); - } - } - } - } - - if (!gpActiveSel) - return; - - // has the player selected one? - if (gHUD.m_iKeyBits & IN_ATTACK) - { - if (gpActiveSel != (WEAPON *)1) - { - ServerCmd(gpActiveSel->szName); - g_weaponselect = gpActiveSel->iId; - } - - gpLastSel = gpActiveSel; - gpActiveSel = NULL; - gHUD.m_iKeyBits &= ~IN_ATTACK; - - PlaySound("common/wpn_select.wav", 1); - } - -} - -// -// Helper function to return a Ammo pointer from id -// - -HSPRITE* WeaponsResource :: GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect ) -{ - for ( int i = 0; i < MAX_WEAPONS; i++ ) - { - if ( rgWeapons[i].iAmmoType == iAmmoId ) - { - rect = rgWeapons[i].rcAmmo; - return &rgWeapons[i].hAmmo; - } - else if ( rgWeapons[i].iAmmo2Type == iAmmoId ) - { - rect = rgWeapons[i].rcAmmo2; - return &rgWeapons[i].hAmmo2; - } - } - - return NULL; -} - - -// Menu Selection Code - -void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection ) -{ - if ( gHUD.m_Menu.m_fMenuDisplayed && (fAdvance == FALSE) && (iDirection == 1) ) - { // menu is overriding slot use commands - gHUD.m_Menu.SelectMenuItem( iSlot + 1 ); // slots are one off the key numbers - return; - } - - if ( iSlot > MAX_WEAPON_SLOTS ) - return; - - if ( gHUD.m_fPlayerDead || gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) ) - return; - - if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) - return; - - if ( ! ( gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT)) )) - return; - - WEAPON *p = NULL; - bool fastSwitch = gHUD.m_Ammo.m_pHud_FastSwitch->value != 0.0f; - - if ( (gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot) ) - { - PlaySound( "common/wpn_hudon.wav", 1 ); - p = GetFirstPos( iSlot ); - - if ( p && fastSwitch ) // check for fast weapon switch mode - { - // if fast weapon switch is on, then weapons can be selected in a single keypress - // but only if there is only one item in the bucket - WEAPON *p2 = GetNextActivePos( p->iSlot, p->iSlotPos ); - if ( !p2 ) - { // only one active item in bucket, so change directly to weapon - ServerCmd( p->szName ); - g_weaponselect = p->iId; - return; - } - } - } - else - { - PlaySound("common/wpn_moveselect.wav", 1); - if ( gpActiveSel ) - p = GetNextActivePos( gpActiveSel->iSlot, gpActiveSel->iSlotPos ); - if ( !p ) - p = GetFirstPos( iSlot ); - } - - - if ( !p ) // no selection found - { - // just display the weapon list, unless fastswitch is on just ignore it - if ( !fastSwitch ) - gpActiveSel = (WEAPON *)1; - else - gpActiveSel = NULL; - } - else - gpActiveSel = p; -} - -//------------------------------------------------------------------------ -// Message Handlers -//------------------------------------------------------------------------ - -// -// AmmoX -- Update the count of a known type of ammo -// -int CHudAmmo::MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - int iIndex = READ_BYTE(); - int iCount = READ_BYTE(); - - gWR.SetAmmo( iIndex, abs(iCount) ); - - return 1; -} - -int CHudAmmo::MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - int iIndex = READ_BYTE(); - int iCount = READ_BYTE(); - - // Add ammo to the history - gHR.AddToHistory( HISTSLOT_AMMO, iIndex, abs(iCount) ); - - return 1; -} - -int CHudAmmo::MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - int iIndex = READ_BYTE(); - - // Add the weapon to the history - gHR.AddToHistory( HISTSLOT_WEAP, iIndex ); - - return 1; -} - -int CHudAmmo::MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - const char *szName = READ_STRING(); - - // Add the weapon to the history - gHR.AddToHistory( HISTSLOT_ITEM, szName ); - - return 1; -} - - -int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - gHUD.m_iHideHUDDisplay = READ_BYTE(); - - if (gEngfuncs.IsSpectateOnly()) - return 1; - - if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) ) - { - static wrect_t nullrc = {0, 0, 0, 0}; - gpActiveSel = NULL; - SetCrosshair( 0, nullrc, 0, 0, 0 ); - } - else - { - if ( m_pWeapon ) - SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 ); - } - - return 1; -} - -// -// CurWeapon: Update hud state with the current weapon and clip count. Ammo -// counts are updated with AmmoX. Server assures that the Weapon ammo type -// numbers match a real ammo type. -// -int CHudAmmo::MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf ) -{ - static wrect_t nullrc; - int fOnTarget = FALSE; - - BEGIN_READ( pbuf, iSize ); - - int iState = READ_BYTE(); - int iId = READ_CHAR(); - int iClip = READ_CHAR(); - - // detect if we're also on target - if ( iState > 1 ) - { - fOnTarget = TRUE; - } - - if ( iId < 1 ) - { - SetCrosshair(0, nullrc, 0, 0, 0); - return 0; - } - - if ( g_iUser1 != OBS_IN_EYE ) - { - // Is player dead??? - if ((iId == -1) && (iClip == -1)) - { - gHUD.m_fPlayerDead = TRUE; - gpActiveSel = NULL; - return 1; - } - gHUD.m_fPlayerDead = FALSE; - } - - WEAPON *pWeapon = gWR.GetWeapon( iId ); - - if ( !pWeapon ) - return 0; - - if ( iClip < -1 ) - pWeapon->iClip = abs(iClip); - else - pWeapon->iClip = iClip; - - - if ( iState == 0 ) // we're not the current weapon, so update no more - return 1; - - m_pWeapon = pWeapon; - - /*if( gHUD.m_iFOV <= 40 ) - { // zoomed crosshairs - if (fOnTarget && m_pWeapon->hZoomedAutoaim) - SetCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255); - else - SetCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255); - - } - else - { - SetCrosshair( 0, nullrc, 0, 0, 0); - }*/ - - - m_fFade = 200.0f; //!!! - m_iFlags |= HUD_ACTIVE; - - return 1; -} - -// -// WeaponList -- Tells the hud about a new weapon type. -// -int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - WEAPON Weapon; - - strncpy( Weapon.szName, READ_STRING(), MAX_WEAPON_NAME ); - Weapon.iAmmoType = (int)READ_CHAR(); - - Weapon.iMax1 = READ_BYTE(); - if (Weapon.iMax1 == 255) - Weapon.iMax1 = -1; - - Weapon.iAmmo2Type = READ_CHAR(); - Weapon.iMax2 = READ_BYTE(); - if (Weapon.iMax2 == 255) - Weapon.iMax2 = -1; - - Weapon.iSlot = READ_CHAR(); - Weapon.iSlotPos = READ_CHAR(); - Weapon.iId = READ_CHAR(); - Weapon.iFlags = READ_BYTE(); - Weapon.iClip = 0; - - gWR.AddWeapon( &Weapon ); - - return 1; - -} - -int CHudAmmo::MsgFunc_Crosshair(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - if( READ_BYTE() > 0) - { - m_bDrawCrosshair = true; - } - else - { - m_bDrawCrosshair = false; - } - return 0; -} - -int CHudAmmo::MsgFunc_Brass( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - int MessageID = READ_BYTE(); - - Vector start, velocity; - start.x = READ_COORD(); - start.y = READ_COORD(); - start.z = READ_COORD(); - READ_COORD(); - READ_COORD(); // unused data - READ_COORD(); - velocity.x = READ_COORD(); - velocity.y = READ_COORD(); - velocity.z = READ_COORD(); - - float Rotation = M_PI * READ_ANGLE() / 180.0f; - int ModelIndex = READ_SHORT(); - int BounceSoundType = READ_BYTE(); - int Life = READ_BYTE(); - int PlayerID = READ_BYTE(); - - float sin, cos, x, y; - sincosf( Rotation, &sin, &cos ); - x = -9.0 * sin; - y = 9.0 * cos; - - if( cl_righthand->value != 0.0f ) - { - velocity.x += sin * -120.0; - velocity.y += cos * 120.0; - x = 9.0 * sin; - y = -9.0 * cos; - } - - start.x += x; - start.y += y; - EV_EjectBrass( start, velocity, Rotation, ModelIndex, BounceSoundType, Life ); - return 1; -} - -//------------------------------------------------------------------------ -// Command Handlers -//------------------------------------------------------------------------ -// Slot button pressed -void CHudAmmo::SlotInput( int iSlot ) -{ - // Let the Viewport use it first, for menus - //if ( gViewPort && gViewPort->SlotInput( iSlot ) ) - //return; - - gWR.SelectSlot(iSlot, FALSE, 1); -} - -void CHudAmmo::UserCmd_Slot1(void) -{ - SlotInput( 0 ); -} - -void CHudAmmo::UserCmd_Slot2(void) -{ - SlotInput( 1 ); -} - -void CHudAmmo::UserCmd_Slot3(void) -{ - SlotInput( 2 ); -} - -void CHudAmmo::UserCmd_Slot4(void) -{ - SlotInput( 3 ); -} - -void CHudAmmo::UserCmd_Slot5(void) -{ - SlotInput( 4 ); -} - -void CHudAmmo::UserCmd_Slot6(void) -{ - SlotInput( 5 ); -} - -void CHudAmmo::UserCmd_Slot7(void) -{ - SlotInput( 6 ); -} - -void CHudAmmo::UserCmd_Slot8(void) -{ - SlotInput( 7 ); -} - -void CHudAmmo::UserCmd_Slot9(void) -{ - SlotInput( 8 ); -} - -void CHudAmmo::UserCmd_Slot10(void) -{ - SlotInput( 9 ); -} - -void CHudAmmo::UserCmd_Adjust_Crosshair() -{ - int newCrosshair; - int oldCrosshair = m_iCurrentCrosshair; - - if ( gEngfuncs.Cmd_Argc() <= 1 ) - { - newCrosshair = (oldCrosshair + 1) % 5; - } - else - { - const char *arg = gEngfuncs.Cmd_Argv(1); - newCrosshair = atoi(arg) % 10; - } - - m_iCurrentCrosshair = newCrosshair; - if ( newCrosshair <= 9 ) - { - switch ( newCrosshair ) - { - case 0: - case 5: - m_R = 50; - m_G = 250; - m_B = 50; - break; - case 1: - case 6: - m_R = 250; - m_G = 50; - m_B = 50; - break; - case 2: - case 7: - m_R = 50; - m_G = 50; - m_B = 250; - break; - case 3: - case 8: - m_R = 250; - m_G = 250; - m_B = 50; - break; - case 4: - case 9: - m_R = 50; - m_G = 250; - m_B = 250; - break; - } - m_bAdditive = newCrosshair < 5 ? true: false; - } - else - { - m_R = 50; - m_G = 250; - m_B = 50; - m_bAdditive = 1; - } - - char s[16]; - sprintf(s, "%d %d %d", m_R, m_G, m_B); - gEngfuncs.Cvar_Set("cl_crosshair_color", s); - gEngfuncs.Cvar_Set("cl_crosshair_translucent", (char*)(m_bAdditive ? "1" : "0")); -} - - -void CHudAmmo::UserCmd_Close(void) -{ - if (gpActiveSel) - { - gpLastSel = gpActiveSel; - gpActiveSel = NULL; - PlaySound("common/wpn_hudoff.wav", 1); - } - else - ClientCmd("escape"); -} - - -// Selects the next item in the weapon menu -void CHudAmmo::UserCmd_NextWeapon(void) -{ - if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) ) - return; - - if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 ) - gpActiveSel = m_pWeapon; - - int pos = 0; - int slot = 0; - if ( gpActiveSel ) - { - pos = gpActiveSel->iSlotPos + 1; - slot = gpActiveSel->iSlot; - } - - for ( int loop = 0; loop <= 1; loop++ ) - { - for ( ; slot < MAX_WEAPON_SLOTS; slot++ ) - { - for ( ; pos < MAX_WEAPON_POSITIONS; pos++ ) - { - WEAPON *wsp = gWR.GetWeaponSlot( slot, pos ); - - if ( wsp /*&& gWR.HasAmmo(wsp)*/ ) - { - gpActiveSel = wsp; - return; - } - } - - pos = 0; - } - - slot = 0; // start looking from the first slot again - } - - gpActiveSel = NULL; -} - -// Selects the previous item in the menu -void CHudAmmo::UserCmd_PrevWeapon(void) -{ - if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) ) - return; - - if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 ) - gpActiveSel = m_pWeapon; - - int pos = MAX_WEAPON_POSITIONS-1; - int slot = MAX_WEAPON_SLOTS-1; - if ( gpActiveSel ) - { - pos = gpActiveSel->iSlotPos - 1; - slot = gpActiveSel->iSlot; - } - - for ( int loop = 0; loop <= 1; loop++ ) - { - for ( ; slot >= 0; slot-- ) - { - for ( ; pos >= 0; pos-- ) - { - WEAPON *wsp = gWR.GetWeaponSlot( slot, pos ); - - if ( wsp /*&& gWR.HasAmmo(wsp)*/ ) - { - gpActiveSel = wsp; - return; - } - } - - pos = MAX_WEAPON_POSITIONS-1; - } - - slot = MAX_WEAPON_SLOTS-1; - } - - gpActiveSel = NULL; -} - -void CHudAmmo::UserCmd_Autobuy() -{ - char *afile = (char*)gEngfuncs.COM_LoadFile("autobuy.txt", 5, NULL); - char *pfile = afile; - char token[256]; - char szCmd[1024]; - - if( !pfile ) - { - ConsolePrint( "Can't open autobuy.txt file.\n" ); - return; - } - - strncpy(szCmd, "cl_setautobuy", sizeof(szCmd)); - - while(pfile = gEngfuncs.COM_ParseFile( pfile, token )) - { - // append space first - strncat(szCmd, " ", sizeof(szCmd)); - strncat(szCmd, token, sizeof(szCmd)); - } - - ConsolePrint(szCmd); - gEngfuncs.pfnServerCmd(szCmd); - - gEngfuncs.COM_FreeFile( afile ); -} - -void CHudAmmo::UserCmd_Rebuy() -{ - char *afile = (char*)gEngfuncs.COM_LoadFile("rebuy.txt", 5, NULL); - char *pfile = afile; - char token[64]; - char szCmd[1024]; - int lastCh; - - if( !pfile ) - { - ConsolePrint( "Can't open rebuy.txt file.\n" ); - return; - } - - // start with \" - strncpy(szCmd, "cl_setrebuy \"", sizeof(szCmd)); - - - - while(pfile = gEngfuncs.COM_ParseFile( pfile, token )) - { - strncat(szCmd, token, sizeof(szCmd)); - // append space after token - strncat(szCmd, " ", sizeof(szCmd)); - } - // replace last space with ", before terminator - lastCh = strlen(szCmd); - szCmd[lastCh - 1] = '\"'; - - ConsolePrint(szCmd); - gEngfuncs.pfnServerCmd(szCmd); - - gEngfuncs.COM_FreeFile( afile ); -} - - -//------------------------------------------------------------------------- -// Drawing code -//------------------------------------------------------------------------- - -int CHudAmmo::Draw(float flTime) -{ - wrect_t nullrc; - int a, x, y, r, g, b; - int AmmoWidth; - - if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) - return 1; - - if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) ) - return 1; - - // Draw Weapon Menu - DrawWList(flTime); - - // Draw ammo pickup history - gHR.DrawAmmoHistory( flTime ); - - if (!(m_iFlags & HUD_ACTIVE)) - return 0; - - if (!m_pWeapon) - return 0; - - if( gHUD.m_iFOV > 40 ) - { - SetCrosshair( 0, nullrc, 0, 0, 0); - DrawCrosshair(flTime, m_pWeapon->iId); // draw a dynamic crosshair - } - else - { - SetCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255); - } - - WEAPON *pw = m_pWeapon; // shorthand - - // SPR_Draw Ammo - if ((pw->iAmmoType < 0) && (pw->iAmmo2Type < 0)) - return 0; - - int iFlags = DHN_DRAWZERO; // draw 0 values - - AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; - - a = (int) max( MIN_ALPHA, m_fFade ); - - if (m_fFade > 0) - m_fFade -= (gHUD.m_flTimeDelta * 20); - - DrawUtils::DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - DrawUtils::DrawUtils::ScaleColors(r, g, b, a ); - - // Does this weapon have a clip? - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2; - - // Does weapon have any ammo at all? - if (m_pWeapon->iAmmoType > 0) - { - int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left; - - if (pw->iClip >= 0) - { - // room for the number and the '|' and the current ammo - - x = ScreenWidth - (8 * AmmoWidth) - iIconWidth; - x = DrawUtils::DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b); - - wrect_t rc; - rc.top = 0; - rc.left = 0; - rc.right = AmmoWidth; - rc.bottom = 100; - - int iBarWidth = AmmoWidth/10; - - x += AmmoWidth/2; - - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - // draw the | bar - FillRGBA(x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a); - - x += iBarWidth + AmmoWidth/2;; - - // GL Seems to need this - DrawUtils::ScaleColors(r, g, b, a ); - x = DrawUtils::DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b); - - - } - else - { - // SPR_Draw a bullets only line - x = ScreenWidth - 4 * AmmoWidth - iIconWidth; - x = DrawUtils::DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b); - } - - // Draw the ammo Icon - int iOffset = (m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top)/8; - SPR_Set(m_pWeapon->hAmmo, r, g, b); - SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo); - } - - // Does weapon have seconday ammo? - if (pw->iAmmo2Type > 0) - { - int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left; - - // Do we have secondary ammo? - if ((pw->iAmmo2Type != 0) && (gWR.CountAmmo(pw->iAmmo2Type) > 0)) - { - y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight/4; - x = ScreenWidth - 4 * AmmoWidth - iIconWidth; - x = DrawUtils::DrawHudNumber(x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo(pw->iAmmo2Type), r, g, b); - - // Draw the ammo Icon - SPR_Set(m_pWeapon->hAmmo2, r, g, b); - int iOffset = (m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top)/8; - SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo2); - } - } - - return 1; -} - -#define WEST_XPOS (ScreenWidth / 2 - flCrosshairDistance - iLength + 1) -#define EAST_XPOS (flCrosshairDistance + ScreenWidth / 2) -#define EAST_WEST_YPOS (ScreenHeight / 2) - -#define NORTH_YPOS (ScreenHeight / 2 - flCrosshairDistance - iLength + 1) -#define SOUTH_YPOS (ScreenHeight / 2 + flCrosshairDistance) -#define NORTH_SOUTH_XPOS (ScreenWidth / 2) - -int Distances[30][2] = -{ -{ 8, 3 }, // 0 -{ 4, 3 }, // 1 -{ 5, 3 }, // 2 -{ 8, 3 }, // 3 -{ 9, 4 }, // 4 -{ 6, 3 }, // 5 -{ 9, 3 }, // 6 -{ 3, 3 }, // 7 -{ 8, 3 }, // 8 -{ 4, 3 }, // 9 -{ 8, 3 }, // 10 -{ 6, 3 }, // 11 -{ 5, 3 }, // 12 -{ 4, 3 }, // 13 -{ 4, 3 }, // 14 -{ 8, 3 }, // 15 -{ 8, 3 }, // 16 -{ 8, 3 }, // 17 -{ 6, 3 }, // 18 -{ 6, 3 }, // 19 -{ 8, 6 }, // 20 -{ 4, 3 }, // 21 -{ 7, 3 }, // 22 -{ 6, 4 }, // 23 -{ 8, 3 }, // 24 -{ 8, 3 }, // 25 -{ 5, 3 }, // 26 -{ 4, 4 }, // 27 -{ 7, 3 }, // 28 -{ 7, 3 }, // 29 -}; - -void CHudAmmo::DrawCrosshair( float flTime, int weaponid ) -{ - int flags; - int iDeltaDistance, iDistance; - int iLength; - float flCrosshairDistance; - - - if ( g_iWeaponFlags & WPNSTATE_SHIELD_DRAWN ) - return; - - if ( weaponid > 30 ) - { - iDistance = 4; - iDeltaDistance = 3; - } - else - { - // TODO: Get an info about crosshair for weapon - iDistance = Distances[weaponid-1][0]; - iDeltaDistance = Distances[weaponid-1][1]; - } - - iLength = 0; - flags = GetWeaponAccuracyFlags(weaponid); - if ( flags && m_pClDynamicCrosshair->value && !(gHUD.m_iHideHUDDisplay & 1) ) - { - if ( g_iPlayerFlags & FL_ONGROUND || !(flags & ACCURACY_AIR) ) - { - if ( (g_iPlayerFlags & FL_DUCKING) && (flags & ACCURACY_DUCK) ) - iDistance *= 0.5; - else - { - int iWeaponSpeed = 0; - - switch( weaponid ) - { - case 30: // p90 - iWeaponSpeed = 170; - break; - case 8: // aug - case 14: // galil - case 15: // famas - case 20: // m249 - case 22: // m4a1 - case 27: // sg552 - case 28: // ak47 - iWeaponSpeed = 140; - break; - } - - if ( (g_flPlayerSpeed >= iWeaponSpeed) && (flags & ACCURACY_SPEED) ) - iDistance *= 1.5; - } - } - else iDistance *= 2; - if ( flags & ACCURACY_MULTIPLY_BY_14 ) - iDistance *= 1.4; - if ( flags & ACCURACY_MULTIPLY_BY_14_2 ) - iDistance *= 1.4; - } - - if ( m_iAmmoLastCheck >= g_iShotsFired ) - { - m_flCrosshairDistance -= (m_flCrosshairDistance * 0.013 + 0.1 ); - m_iAlpha += 2; - } - else - { - m_flCrosshairDistance += iDeltaDistance; - m_iAlpha -= 40; - - if ( m_flCrosshairDistance > 15.0 ) - m_flCrosshairDistance = 15.0; - if ( m_iAlpha < 120 ) - m_iAlpha = 120; - } - - if ( g_iShotsFired > 600 ) - g_iShotsFired = 1; - - CalcCrosshairColor(); - CalcCrosshairDrawMode(); - CalcCrosshairSize(); - - m_iAmmoLastCheck = g_iShotsFired; - if ( iDistance > m_flCrosshairDistance ) - m_flCrosshairDistance = iDistance; - if ( m_iAlpha > 255 ) - m_iAlpha = 255; - iLength = (m_flCrosshairDistance - iDistance) * 0.5 + 5; - flCrosshairDistance = m_flCrosshairDistance; - if ( ScreenWidth != m_iCrosshairScaleBase ) - { - flCrosshairDistance = ScreenWidth * flCrosshairDistance / m_iCrosshairScaleBase; - iLength = ScreenWidth * iLength / m_iCrosshairScaleBase; - } - - - // drawing - if ( gHUD.m_NVG.m_iEnable ) - { - FillRGBABlend(WEST_XPOS, EAST_WEST_YPOS, iLength, 1, 250, 50, 50, m_iAlpha); - FillRGBABlend(EAST_XPOS, EAST_WEST_YPOS, iLength, 1, 250, 50, 50, m_iAlpha); - FillRGBABlend(NORTH_SOUTH_XPOS, NORTH_YPOS, 1, iLength, 250, 50, 50, m_iAlpha); - FillRGBABlend(NORTH_SOUTH_XPOS, SOUTH_YPOS, 1, iLength, 250, 50, 50, m_iAlpha); - } - else if ( !m_bAdditive ) - { - FillRGBABlend(WEST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); - FillRGBABlend(EAST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); - FillRGBABlend(NORTH_SOUTH_XPOS, NORTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); - FillRGBABlend(NORTH_SOUTH_XPOS, SOUTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); - } - else - { - FillRGBA(WEST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); - FillRGBA(EAST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); - FillRGBA(NORTH_SOUTH_XPOS, NORTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); - FillRGBA(NORTH_SOUTH_XPOS, SOUTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); - } - return; -} - -void CHudAmmo::CalcCrosshairSize() -{ - const char *size = m_pClCrosshairSize->string; - - if( !stricmp(size, "auto") ) - { - if( ScreenWidth < 640 ) - m_iCrosshairScaleBase = 1024; - else if( ScreenWidth < 1024 ) - m_iCrosshairScaleBase = 800; - else m_iCrosshairScaleBase = 640; - } - else if( !stricmp( size, "small" )) - { - m_iCrosshairScaleBase = 640; - } - else if( !stricmp( size, "medium" )) - { - m_iCrosshairScaleBase = 800; - } - else if( !stricmp( size, "large" )) - { - m_iCrosshairScaleBase = 1024; - } - return; -} - -void CHudAmmo::CalcCrosshairDrawMode() -{ - float drawMode = m_pClCrosshairTranslucent->value; - if ( drawMode == 0.0f ) - { - m_bAdditive = 0; - } - else if ( drawMode == 1.0f ) - { - m_bAdditive = 1; - } - else - { - gEngfuncs.Con_Printf("usage: cl_crosshair_translucent <1|0>\n"); - } -} - -void CHudAmmo::CalcCrosshairColor() -{ - const char *colors = m_pClCrosshairColor->string; - - int tempR; - int tempG; - int tempB; - - sscanf( colors, "%d %d %d", &tempR, &tempG, &tempB); - - m_R = m_cvarR = bound( 0, tempR, 255 ); - m_G = m_cvarG = bound( 0, tempG, 255 ); - m_B = m_cvarB = bound( 0, tempB, 255 ); -} - -// -// Draws the ammo bar on the hud -// -int DrawBar(int x, int y, int width, int height, float f) -{ - int r, g, b; - - if (f < 0) - f = 0; - if (f > 1) - f = 1; - - if (f) - { - int w = f * width; - - // Always show at least one pixel if we have ammo. - if (w <= 0) - w = 1; - DrawUtils::UnpackRGB(r, g, b, RGB_GREENISH); - FillRGBA(x, y, w, height, r, g, b, 255); - x += w; - width -= w; - } - - DrawUtils::UnpackRGB(r, g, b, RGB_YELLOWISH); - - FillRGBA(x, y, width, height, r, g, b, 128); - - return (x + width); -} - - - -void DrawAmmoBar(WEAPON *p, int x, int y, int width, int height) -{ - if ( !p ) - return; - - if (p->iAmmoType != -1) - { - if (!gWR.CountAmmo(p->iAmmoType)) - return; - - float f = (float)gWR.CountAmmo(p->iAmmoType)/(float)p->iMax1; - - x = DrawBar(x, y, width, height, f); - - - // Do we have secondary ammo too? - - if (p->iAmmo2Type != -1) - { - f = (float)gWR.CountAmmo(p->iAmmo2Type)/(float)p->iMax2; - - x += 5; //!!! - - DrawBar(x, y, width, height, f); - } - } -} - - - - -// -// Draw Weapon Menu -// -int CHudAmmo::DrawWList(float flTime) -{ - int r,g,b,x,y,a,i; - - if ( !gpActiveSel ) - return 0; - - int iActiveSlot; - - if ( gpActiveSel == (WEAPON *)1 ) - iActiveSlot = -1; // current slot has no weapons - else - iActiveSlot = gpActiveSel->iSlot; - - x = gHUD.m_Radar.m_hRadar.rect.right + 10; //!!! - y = 10; //!!! - - - // Ensure that there are available choices in the active slot - if ( iActiveSlot > 0 ) - { - if ( !gWR.GetFirstPos( iActiveSlot ) ) - { - gpActiveSel = (WEAPON *)1; - iActiveSlot = -1; - } - } - - // Draw top line - for ( i = 0; i < MAX_WEAPON_SLOTS; i++ ) - { - int iWidth; - - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - if ( iActiveSlot == i ) - a = 255; - else - a = 192; - - DrawUtils::ScaleColors(r, g, b, 255); - SPR_Set(gHUD.GetSprite(m_HUD_bucket0 + i), r, g, b ); - - // make active slot wide enough to accomodate gun pictures - if ( i == iActiveSlot ) - { - WEAPON *p = gWR.GetFirstPos(iActiveSlot); - if ( p ) - iWidth = p->rcActive.right - p->rcActive.left; - else - iWidth = giBucketWidth; - } - else - iWidth = giBucketWidth; - - SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i)); - - x += iWidth + 5; - } - - - a = 128; //!!! - x = gHUD.m_Radar.m_hRadar.rect.right + 10; //!!!; - - // Draw all of the buckets - for (i = 0; i < MAX_WEAPON_SLOTS; i++) - { - y = giBucketHeight + 10; - - // If this is the active slot, draw the bigger pictures, - // otherwise just draw boxes - if ( i == iActiveSlot ) - { - WEAPON *p = gWR.GetFirstPos( i ); - int iWidth = giBucketWidth; - if ( p ) - iWidth = p->rcActive.right - p->rcActive.left; - - for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) - { - p = gWR.GetWeaponSlot( i, iPos ); - - if ( !p || !p->iId ) - continue; - - - // if active, then we must have ammo. - if ( gWR.HasAmmo(p) ) - { - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH ); - DrawUtils::ScaleColors(r, g, b, 192); - } - else - { - DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); - DrawUtils::ScaleColors(r, g, b, 128); - } - - - if ( gpActiveSel == p ) - { - SPR_Set(p->hActive, r, g, b ); - SPR_DrawAdditive(0, x, y, &p->rcActive); - - SPR_Set(gHUD.GetSprite(m_HUD_selection), r, g, b ); - SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_selection)); - } - else - { - // Draw Weapon if Red if no ammo - SPR_Set( p->hInactive, r, g, b ); - SPR_DrawAdditive( 0, x, y, &p->rcInactive ); - } - - // Draw Ammo Bar - - DrawAmmoBar(p, x + giABWidth/2, y, giABWidth, giABHeight); - - y += p->rcActive.bottom - p->rcActive.top + 5; - } - - x += iWidth + 5; - - } - else - { - // Draw Row of weapons. - - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) - { - WEAPON *p = gWR.GetWeaponSlot( i, iPos ); - - if ( !p || !p->iId ) - continue; - - if ( gWR.HasAmmo(p) ) - { - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - a = 128; - } - else - { - DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); - a = 96; - } - - FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a ); - - y += giBucketHeight + 5; - } - - x += giBucketWidth + 5; - } - } - - return 1; - -} - - -/* ================================= - GetSpriteList - -Finds and returns the matching -sprite name 'psz' and resolution 'iRes' -in the given sprite list 'pList' -iCount is the number of items in the pList -================================= */ -client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount) -{ - if (!pList) - return NULL; - - int i = iCount; - client_sprite_t *p = pList; - - while(i--) - { - if ((!strcmp(psz, p->szName)) && (p->iRes == iRes)) - return p; - p++; - } - - return NULL; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// Ammo.cpp +// +// implementation of CHudAmmo class +// + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" +#include "pm_shared.h" + +#include +#include + +#include "ammohistory.h" +#include "eventscripts.h" +#include "com_weapons.h" + +//#include "vgui_TeamFortressViewport.h" + +#ifdef _MSC_VER + +void sincosf (float rad, float *sine, float *cosine) +{ + *sine = sinf (rad); + *cosine = cosf (rad); +} + +#ifndef M_PI +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif + +#endif + +WEAPON *gpActiveSel; // NULL means off, 1 means just the menu bar, otherwise + // this points to the active weapon menu item +WEAPON *gpLastSel; // Last weapon menu selection + +client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount); + +WeaponsResource gWR; + +int g_weaponselect = 0; +int g_iShotsFired; + +void WeaponsResource :: LoadAllWeaponSprites( void ) +{ + for (int i = 0; i < MAX_WEAPONS; i++) + { + if ( rgWeapons[i].iId ) + LoadWeaponSprites( &rgWeapons[i] ); + } +} + +int WeaponsResource :: CountAmmo( int iId ) +{ + if ( iId < 0 ) + return 0; + + return riAmmo[iId]; +} + +int WeaponsResource :: HasAmmo( WEAPON *p ) +{ + if ( !p ) + return FALSE; + + // weapons with no max ammo can always be selected + if ( p->iMax1 == -1 ) + return TRUE; + + return (p->iAmmoType == -1) || p->iClip > 0 || CountAmmo(p->iAmmoType) + || CountAmmo(p->iAmmo2Type) || ( p->iFlags & WEAPON_FLAGS_SELECTONEMPTY ); +} + + +void WeaponsResource :: LoadWeaponSprites( WEAPON *pWeapon ) +{ + int i, iRes; + + if (ScreenWidth < 640) + iRes = 320; + else + iRes = 640; + + char sz[128]; + + if ( !pWeapon ) + return; + + memset( &pWeapon->rcActive, 0, sizeof(wrect_t) ); + memset( &pWeapon->rcInactive, 0, sizeof(wrect_t) ); + memset( &pWeapon->rcAmmo, 0, sizeof(wrect_t) ); + memset( &pWeapon->rcAmmo2, 0, sizeof(wrect_t) ); + pWeapon->hInactive = 0; + pWeapon->hActive = 0; + pWeapon->hAmmo = 0; + pWeapon->hAmmo2 = 0; + + sprintf(sz, "sprites/%s.txt", pWeapon->szName); + client_sprite_t *pList = SPR_GetList(sz, &i); + + if (!pList) + return; + + client_sprite_t *p; + + p = GetSpriteList( pList, "crosshair", iRes, i ); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hCrosshair = SPR_Load(sz); + pWeapon->rcCrosshair = p->rc; + } + else + pWeapon->hCrosshair = 0; + + p = GetSpriteList(pList, "autoaim", iRes, i); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hAutoaim = SPR_Load(sz); + pWeapon->rcAutoaim = p->rc; + } + else + pWeapon->hAutoaim = 0; + + p = GetSpriteList( pList, "zoom", iRes, i ); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hZoomedCrosshair = SPR_Load(sz); + pWeapon->rcZoomedCrosshair = p->rc; + } + else + { + pWeapon->hZoomedCrosshair = pWeapon->hCrosshair; //default to non-zoomed crosshair + pWeapon->rcZoomedCrosshair = pWeapon->rcCrosshair; + } + + p = GetSpriteList(pList, "zoom_autoaim", iRes, i); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hZoomedAutoaim = SPR_Load(sz); + pWeapon->rcZoomedAutoaim = p->rc; + } + else + { + pWeapon->hZoomedAutoaim = pWeapon->hZoomedCrosshair; //default to zoomed crosshair + pWeapon->rcZoomedAutoaim = pWeapon->rcZoomedCrosshair; + } + + p = GetSpriteList(pList, "weapon", iRes, i); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hInactive = SPR_Load(sz); + pWeapon->rcInactive = p->rc; + + gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); + } + else + pWeapon->hInactive = 0; + + p = GetSpriteList(pList, "weapon_s", iRes, i); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hActive = SPR_Load(sz); + pWeapon->rcActive = p->rc; + } + else + pWeapon->hActive = 0; + + p = GetSpriteList(pList, "ammo", iRes, i); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hAmmo = SPR_Load(sz); + pWeapon->rcAmmo = p->rc; + + gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); + } + else + pWeapon->hAmmo = 0; + + p = GetSpriteList(pList, "ammo2", iRes, i); + if (p) + { + sprintf(sz, "sprites/%s.spr", p->szSprite); + pWeapon->hAmmo2 = SPR_Load(sz); + pWeapon->rcAmmo2 = p->rc; + + gHR.iHistoryGap = max( gHR.iHistoryGap, pWeapon->rcActive.bottom - pWeapon->rcActive.top ); + } + else + pWeapon->hAmmo2 = 0; + +} + +// Returns the first weapon for a given slot. +WEAPON *WeaponsResource :: GetFirstPos( int iSlot ) +{ + WEAPON *pret = NULL; + + for (int i = 0; i < MAX_WEAPON_POSITIONS; i++) + { + if ( rgSlots[iSlot][i] /*&& HasAmmo( rgSlots[iSlot][i] )*/ ) + { + pret = rgSlots[iSlot][i]; + break; + } + } + + return pret; +} + + +WEAPON* WeaponsResource :: GetNextActivePos( int iSlot, int iSlotPos ) +{ + if ( iSlotPos >= MAX_WEAPON_POSITIONS || iSlot >= MAX_WEAPON_SLOTS ) + return NULL; + + WEAPON *p = gWR.rgSlots[ iSlot ][ iSlotPos+1 ]; + + if ( !p || !gWR.HasAmmo(p) ) + return GetNextActivePos( iSlot, iSlotPos + 1 ); + + return p; +} + + +int giBucketHeight, giBucketWidth, giABHeight, giABWidth; // Ammo Bar width and height + +HSPRITE ghsprBuckets; // Sprite for top row of weapons menu + +DECLARE_MESSAGE(m_Ammo, CurWeapon ); // Current weapon and clip +DECLARE_MESSAGE(m_Ammo, WeaponList); // new weapon type +DECLARE_MESSAGE(m_Ammo, AmmoX); // update known ammo type's count +DECLARE_MESSAGE(m_Ammo, AmmoPickup); // flashes an ammo pickup record +DECLARE_MESSAGE(m_Ammo, WeapPickup); // flashes a weapon pickup record +DECLARE_MESSAGE(m_Ammo, HideWeapon); // hides the weapon, ammo, and crosshair displays temporarily +DECLARE_MESSAGE(m_Ammo, ItemPickup); +DECLARE_MESSAGE(m_Ammo, Crosshair); +DECLARE_MESSAGE(m_Ammo, Brass); + +DECLARE_COMMAND(m_Ammo, Slot1); +DECLARE_COMMAND(m_Ammo, Slot2); +DECLARE_COMMAND(m_Ammo, Slot3); +DECLARE_COMMAND(m_Ammo, Slot4); +DECLARE_COMMAND(m_Ammo, Slot5); +DECLARE_COMMAND(m_Ammo, Slot6); +DECLARE_COMMAND(m_Ammo, Slot7); +DECLARE_COMMAND(m_Ammo, Slot8); +DECLARE_COMMAND(m_Ammo, Slot9); +DECLARE_COMMAND(m_Ammo, Slot10); +DECLARE_COMMAND(m_Ammo, Close); +DECLARE_COMMAND(m_Ammo, NextWeapon); +DECLARE_COMMAND(m_Ammo, PrevWeapon); +DECLARE_COMMAND(m_Ammo, Adjust_Crosshair); +DECLARE_COMMAND(m_Ammo, Rebuy); +DECLARE_COMMAND(m_Ammo, Autobuy); + +// width of ammo fonts +#define AMMO_SMALL_WIDTH 10 +#define AMMO_LARGE_WIDTH 20 + +#define HISTORY_DRAW_TIME "5" + +int CHudAmmo::Init(void) +{ + gHUD.AddHudElem(this); + + HOOK_MESSAGE(CurWeapon); + HOOK_MESSAGE(WeaponList); + HOOK_MESSAGE(AmmoPickup); + HOOK_MESSAGE(WeapPickup); + HOOK_MESSAGE(ItemPickup); + HOOK_MESSAGE(HideWeapon); + HOOK_MESSAGE(AmmoX); + HOOK_MESSAGE(Crosshair); + HOOK_MESSAGE(Brass); + + HOOK_COMMAND("slot1", Slot1); + HOOK_COMMAND("slot2", Slot2); + HOOK_COMMAND("slot3", Slot3); + HOOK_COMMAND("slot4", Slot4); + HOOK_COMMAND("slot5", Slot5); + HOOK_COMMAND("slot6", Slot6); + HOOK_COMMAND("slot7", Slot7); + HOOK_COMMAND("slot8", Slot8); + HOOK_COMMAND("slot9", Slot9); + HOOK_COMMAND("slot10", Slot10); + HOOK_COMMAND("cancelselect", Close); + HOOK_COMMAND("invnext", NextWeapon); + HOOK_COMMAND("invprev", PrevWeapon); + HOOK_COMMAND("adjust_crosshair", Adjust_Crosshair); + HOOK_COMMAND("rebuy", Rebuy); + HOOK_COMMAND("autobuy", Autobuy); + + Reset(); + + m_pHud_DrawHistory_Time = CVAR_CREATE( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0 ); + m_pHud_FastSwitch = CVAR_CREATE( "hud_fastswitch", "0", FCVAR_ARCHIVE ); // controls whether or not weapons can be selected in one keypress + CVAR_CREATE( "cl_observercrosshair", "1", 0 ); + m_pClCrosshairColor = CVAR_CREATE( "cl_crosshair_color", "50 250 50", FCVAR_ARCHIVE ); + m_pClCrosshairTranslucent = CVAR_CREATE( "cl_crosshair_translucent", "1", FCVAR_ARCHIVE ); + m_pClCrosshairSize = CVAR_CREATE( "cl_crosshair_size", "auto", FCVAR_ARCHIVE ); + m_pClDynamicCrosshair = CVAR_CREATE("cl_dynamiccrosshair", "1", FCVAR_ARCHIVE); + + m_iFlags |= HUD_ACTIVE; //!!! + m_R = 50; + m_G = 250; + m_B = 50; + m_iAlpha = 200; + + m_cvarB = m_cvarR = m_cvarG = -1; + m_iCurrentCrosshair = 0; + m_bAdditive = 1; + m_iCrosshairScaleBase = 1024; + m_bDrawCrosshair = true; + + gWR.Init(); + gHR.Init(); + + return 1; +}; + +void CHudAmmo::Reset(void) +{ + m_fFade = 0; + m_iFlags |= HUD_ACTIVE; //!!! + + gpActiveSel = NULL; + gHUD.m_iHideHUDDisplay = 0; + + gWR.Reset(); + gHR.Reset(); + + // VidInit(); + +} + +int CHudAmmo::VidInit(void) +{ + // Load sprites for buckets (top row of weapon menu) + m_HUD_bucket0 = gHUD.GetSpriteIndex( "bucket1" ); + m_HUD_selection = gHUD.GetSpriteIndex( "selection" ); + + ghsprBuckets = gHUD.GetSprite(m_HUD_bucket0); + giBucketWidth = gHUD.GetSpriteRect(m_HUD_bucket0).right - gHUD.GetSpriteRect(m_HUD_bucket0).left; + giBucketHeight = gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top; + + gHR.iHistoryGap = max( gHR.iHistoryGap, gHUD.GetSpriteRect(m_HUD_bucket0).bottom - gHUD.GetSpriteRect(m_HUD_bucket0).top); + + // If we've already loaded weapons, let's get new sprites + gWR.LoadAllWeaponSprites(); + + if (ScreenWidth >= 640) + { + giABWidth = 20; + giABHeight = 4; + } + else + { + giABWidth = 10; + giABHeight = 2; + } + + return 1; +} + +// +// Think: +// Used for selection of weapon menu item. +// +void CHudAmmo::Think(void) +{ + if ( gHUD.m_fPlayerDead ) + return; + + if ( gHUD.m_iWeaponBits != gWR.iOldWeaponBits ) + { + gWR.iOldWeaponBits = gHUD.m_iWeaponBits; + + for (int i = 0; i < MAX_WEAPONS-1; i++ ) + { + WEAPON *p = gWR.GetWeapon(i); + + if ( p ) + { + if ( gHUD.m_iWeaponBits & ( 1 << p->iId ) ) + { + gWR.PickupWeapon( p ); + } + else + { + gWR.DropWeapon( p ); + } + } + } + } + + if (!gpActiveSel) + return; + + // has the player selected one? + if (gHUD.m_iKeyBits & IN_ATTACK) + { + if (gpActiveSel != (WEAPON *)1) + { + ServerCmd(gpActiveSel->szName); + g_weaponselect = gpActiveSel->iId; + } + + gpLastSel = gpActiveSel; + gpActiveSel = NULL; + gHUD.m_iKeyBits &= ~IN_ATTACK; + + PlaySound("common/wpn_select.wav", 1); + } + +} + +// +// Helper function to return a Ammo pointer from id +// + +HSPRITE* WeaponsResource :: GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect ) +{ + for ( int i = 0; i < MAX_WEAPONS; i++ ) + { + if ( rgWeapons[i].iAmmoType == iAmmoId ) + { + rect = rgWeapons[i].rcAmmo; + return &rgWeapons[i].hAmmo; + } + else if ( rgWeapons[i].iAmmo2Type == iAmmoId ) + { + rect = rgWeapons[i].rcAmmo2; + return &rgWeapons[i].hAmmo2; + } + } + + return NULL; +} + + +// Menu Selection Code + +void WeaponsResource :: SelectSlot( int iSlot, int fAdvance, int iDirection ) +{ + if ( gHUD.m_Menu.m_fMenuDisplayed && (fAdvance == FALSE) && (iDirection == 1) ) + { // menu is overriding slot use commands + gHUD.m_Menu.SelectMenuItem( iSlot + 1 ); // slots are one off the key numbers + return; + } + + if ( iSlot > MAX_WEAPON_SLOTS ) + return; + + if ( gHUD.m_fPlayerDead || gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ) ) + return; + + if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) + return; + + if ( ! ( gHUD.m_iWeaponBits & ~(1<<(WEAPON_SUIT)) )) + return; + + WEAPON *p = NULL; + bool fastSwitch = gHUD.m_Ammo.m_pHud_FastSwitch->value != 0.0f; + + if ( (gpActiveSel == NULL) || (gpActiveSel == (WEAPON *)1) || (iSlot != gpActiveSel->iSlot) ) + { + PlaySound( "common/wpn_hudon.wav", 1 ); + p = GetFirstPos( iSlot ); + + if ( p && fastSwitch ) // check for fast weapon switch mode + { + // if fast weapon switch is on, then weapons can be selected in a single keypress + // but only if there is only one item in the bucket + WEAPON *p2 = GetNextActivePos( p->iSlot, p->iSlotPos ); + if ( !p2 ) + { // only one active item in bucket, so change directly to weapon + ServerCmd( p->szName ); + g_weaponselect = p->iId; + return; + } + } + } + else + { + PlaySound("common/wpn_moveselect.wav", 1); + if ( gpActiveSel ) + p = GetNextActivePos( gpActiveSel->iSlot, gpActiveSel->iSlotPos ); + if ( !p ) + p = GetFirstPos( iSlot ); + } + + + if ( !p ) // no selection found + { + // just display the weapon list, unless fastswitch is on just ignore it + if ( !fastSwitch ) + gpActiveSel = (WEAPON *)1; + else + gpActiveSel = NULL; + } + else + gpActiveSel = p; +} + +//------------------------------------------------------------------------ +// Message Handlers +//------------------------------------------------------------------------ + +// +// AmmoX -- Update the count of a known type of ammo +// +int CHudAmmo::MsgFunc_AmmoX(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + int iIndex = READ_BYTE(); + int iCount = READ_BYTE(); + + gWR.SetAmmo( iIndex, abs(iCount) ); + + return 1; +} + +int CHudAmmo::MsgFunc_AmmoPickup( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + int iIndex = READ_BYTE(); + int iCount = READ_BYTE(); + + // Add ammo to the history + gHR.AddToHistory( HISTSLOT_AMMO, iIndex, abs(iCount) ); + + return 1; +} + +int CHudAmmo::MsgFunc_WeapPickup( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + int iIndex = READ_BYTE(); + + // Add the weapon to the history + gHR.AddToHistory( HISTSLOT_WEAP, iIndex ); + + return 1; +} + +int CHudAmmo::MsgFunc_ItemPickup( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + const char *szName = READ_STRING(); + + // Add the weapon to the history + gHR.AddToHistory( HISTSLOT_ITEM, szName ); + + return 1; +} + + +int CHudAmmo::MsgFunc_HideWeapon( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + gHUD.m_iHideHUDDisplay = READ_BYTE(); + + if (gEngfuncs.IsSpectateOnly()) + return 1; + + if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) ) + { + static wrect_t nullrc = {0, 0, 0, 0}; + gpActiveSel = NULL; + SetCrosshair( 0, nullrc, 0, 0, 0 ); + } + else + { + if ( m_pWeapon ) + SetCrosshair( m_pWeapon->hCrosshair, m_pWeapon->rcCrosshair, 255, 255, 255 ); + } + + return 1; +} + +// +// CurWeapon: Update hud state with the current weapon and clip count. Ammo +// counts are updated with AmmoX. Server assures that the Weapon ammo type +// numbers match a real ammo type. +// +int CHudAmmo::MsgFunc_CurWeapon(const char *pszName, int iSize, void *pbuf ) +{ + static wrect_t nullrc; + int fOnTarget = FALSE; + + BEGIN_READ( pbuf, iSize ); + + int iState = READ_BYTE(); + int iId = READ_CHAR(); + int iClip = READ_CHAR(); + + // detect if we're also on target + if ( iState > 1 ) + { + fOnTarget = TRUE; + } + + if ( iId < 1 ) + { + SetCrosshair(0, nullrc, 0, 0, 0); + return 0; + } + + if ( g_iUser1 != OBS_IN_EYE ) + { + // Is player dead??? + if ((iId == -1) && (iClip == -1)) + { + gHUD.m_fPlayerDead = TRUE; + gpActiveSel = NULL; + return 1; + } + gHUD.m_fPlayerDead = FALSE; + } + + WEAPON *pWeapon = gWR.GetWeapon( iId ); + + if ( !pWeapon ) + return 0; + + if ( iClip < -1 ) + pWeapon->iClip = abs(iClip); + else + pWeapon->iClip = iClip; + + + if ( iState == 0 ) // we're not the current weapon, so update no more + return 1; + + m_pWeapon = pWeapon; + + /*if( gHUD.m_iFOV <= 40 ) + { // zoomed crosshairs + if (fOnTarget && m_pWeapon->hZoomedAutoaim) + SetCrosshair(m_pWeapon->hZoomedAutoaim, m_pWeapon->rcZoomedAutoaim, 255, 255, 255); + else + SetCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255); + + } + else + { + SetCrosshair( 0, nullrc, 0, 0, 0); + }*/ + + + m_fFade = 200.0f; //!!! + m_iFlags |= HUD_ACTIVE; + + return 1; +} + +// +// WeaponList -- Tells the hud about a new weapon type. +// +int CHudAmmo::MsgFunc_WeaponList(const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + WEAPON Weapon; + + strncpy( Weapon.szName, READ_STRING(), MAX_WEAPON_NAME ); + Weapon.iAmmoType = (int)READ_CHAR(); + + Weapon.iMax1 = READ_BYTE(); + if (Weapon.iMax1 == 255) + Weapon.iMax1 = -1; + + Weapon.iAmmo2Type = READ_CHAR(); + Weapon.iMax2 = READ_BYTE(); + if (Weapon.iMax2 == 255) + Weapon.iMax2 = -1; + + Weapon.iSlot = READ_CHAR(); + Weapon.iSlotPos = READ_CHAR(); + Weapon.iId = READ_CHAR(); + Weapon.iFlags = READ_BYTE(); + Weapon.iClip = 0; + + gWR.AddWeapon( &Weapon ); + + return 1; + +} + +int CHudAmmo::MsgFunc_Crosshair(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + if( READ_BYTE() > 0) + { + m_bDrawCrosshair = true; + } + else + { + m_bDrawCrosshair = false; + } + return 0; +} + +int CHudAmmo::MsgFunc_Brass( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + int MessageID = READ_BYTE(); + + Vector start, velocity; + start.x = READ_COORD(); + start.y = READ_COORD(); + start.z = READ_COORD(); + READ_COORD(); + READ_COORD(); // unused data + READ_COORD(); + velocity.x = READ_COORD(); + velocity.y = READ_COORD(); + velocity.z = READ_COORD(); + + float Rotation = M_PI * READ_ANGLE() / 180.0f; + int ModelIndex = READ_SHORT(); + int BounceSoundType = READ_BYTE(); + int Life = READ_BYTE(); + int PlayerID = READ_BYTE(); + + float sin, cos, x, y; + sincosf( Rotation, &sin, &cos ); + x = -9.0 * sin; + y = 9.0 * cos; + + if( cl_righthand->value != 0.0f ) + { + velocity.x += sin * -120.0; + velocity.y += cos * 120.0; + x = 9.0 * sin; + y = -9.0 * cos; + } + + start.x += x; + start.y += y; + EV_EjectBrass( start, velocity, Rotation, ModelIndex, BounceSoundType, Life ); + return 1; +} + +//------------------------------------------------------------------------ +// Command Handlers +//------------------------------------------------------------------------ +// Slot button pressed +void CHudAmmo::SlotInput( int iSlot ) +{ + // Let the Viewport use it first, for menus + //if ( gViewPort && gViewPort->SlotInput( iSlot ) ) + //return; + + gWR.SelectSlot(iSlot, FALSE, 1); +} + +void CHudAmmo::UserCmd_Slot1(void) +{ + SlotInput( 0 ); +} + +void CHudAmmo::UserCmd_Slot2(void) +{ + SlotInput( 1 ); +} + +void CHudAmmo::UserCmd_Slot3(void) +{ + SlotInput( 2 ); +} + +void CHudAmmo::UserCmd_Slot4(void) +{ + SlotInput( 3 ); +} + +void CHudAmmo::UserCmd_Slot5(void) +{ + SlotInput( 4 ); +} + +void CHudAmmo::UserCmd_Slot6(void) +{ + SlotInput( 5 ); +} + +void CHudAmmo::UserCmd_Slot7(void) +{ + SlotInput( 6 ); +} + +void CHudAmmo::UserCmd_Slot8(void) +{ + SlotInput( 7 ); +} + +void CHudAmmo::UserCmd_Slot9(void) +{ + SlotInput( 8 ); +} + +void CHudAmmo::UserCmd_Slot10(void) +{ + SlotInput( 9 ); +} + +void CHudAmmo::UserCmd_Adjust_Crosshair() +{ + int newCrosshair; + int oldCrosshair = m_iCurrentCrosshair; + + if ( gEngfuncs.Cmd_Argc() <= 1 ) + { + newCrosshair = (oldCrosshair + 1) % 5; + } + else + { + const char *arg = gEngfuncs.Cmd_Argv(1); + newCrosshair = atoi(arg) % 10; + } + + m_iCurrentCrosshair = newCrosshair; + if ( newCrosshair <= 9 ) + { + switch ( newCrosshair ) + { + case 0: + case 5: + m_R = 50; + m_G = 250; + m_B = 50; + break; + case 1: + case 6: + m_R = 250; + m_G = 50; + m_B = 50; + break; + case 2: + case 7: + m_R = 50; + m_G = 50; + m_B = 250; + break; + case 3: + case 8: + m_R = 250; + m_G = 250; + m_B = 50; + break; + case 4: + case 9: + m_R = 50; + m_G = 250; + m_B = 250; + break; + } + m_bAdditive = newCrosshair < 5 ? true: false; + } + else + { + m_R = 50; + m_G = 250; + m_B = 50; + m_bAdditive = 1; + } + + char s[16]; + sprintf(s, "%d %d %d", m_R, m_G, m_B); + gEngfuncs.Cvar_Set("cl_crosshair_color", s); + gEngfuncs.Cvar_Set("cl_crosshair_translucent", (char*)(m_bAdditive ? "1" : "0")); +} + + +void CHudAmmo::UserCmd_Close(void) +{ + if (gpActiveSel) + { + gpLastSel = gpActiveSel; + gpActiveSel = NULL; + PlaySound("common/wpn_hudoff.wav", 1); + } + else + ClientCmd("escape"); +} + + +// Selects the next item in the weapon menu +void CHudAmmo::UserCmd_NextWeapon(void) +{ + if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) ) + return; + + if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 ) + gpActiveSel = m_pWeapon; + + int pos = 0; + int slot = 0; + if ( gpActiveSel ) + { + pos = gpActiveSel->iSlotPos + 1; + slot = gpActiveSel->iSlot; + } + + for ( int loop = 0; loop <= 1; loop++ ) + { + for ( ; slot < MAX_WEAPON_SLOTS; slot++ ) + { + for ( ; pos < MAX_WEAPON_POSITIONS; pos++ ) + { + WEAPON *wsp = gWR.GetWeaponSlot( slot, pos ); + + if ( wsp /*&& gWR.HasAmmo(wsp)*/ ) + { + gpActiveSel = wsp; + return; + } + } + + pos = 0; + } + + slot = 0; // start looking from the first slot again + } + + gpActiveSel = NULL; +} + +// Selects the previous item in the menu +void CHudAmmo::UserCmd_PrevWeapon(void) +{ + if ( gHUD.m_fPlayerDead || (gHUD.m_iHideHUDDisplay & (HIDEHUD_WEAPONS | HIDEHUD_ALL)) ) + return; + + if ( !gpActiveSel || gpActiveSel == (WEAPON*)1 ) + gpActiveSel = m_pWeapon; + + int pos = MAX_WEAPON_POSITIONS-1; + int slot = MAX_WEAPON_SLOTS-1; + if ( gpActiveSel ) + { + pos = gpActiveSel->iSlotPos - 1; + slot = gpActiveSel->iSlot; + } + + for ( int loop = 0; loop <= 1; loop++ ) + { + for ( ; slot >= 0; slot-- ) + { + for ( ; pos >= 0; pos-- ) + { + WEAPON *wsp = gWR.GetWeaponSlot( slot, pos ); + + if ( wsp /*&& gWR.HasAmmo(wsp)*/ ) + { + gpActiveSel = wsp; + return; + } + } + + pos = MAX_WEAPON_POSITIONS-1; + } + + slot = MAX_WEAPON_SLOTS-1; + } + + gpActiveSel = NULL; +} + +void CHudAmmo::UserCmd_Autobuy() +{ + char *afile = (char*)gEngfuncs.COM_LoadFile("autobuy.txt", 5, NULL); + char *pfile = afile; + char token[256]; + char szCmd[1024]; + + if( !pfile ) + { + ConsolePrint( "Can't open autobuy.txt file.\n" ); + return; + } + + strncpy(szCmd, "cl_setautobuy", sizeof(szCmd)); + + while(pfile = gEngfuncs.COM_ParseFile( pfile, token )) + { + // append space first + strncat(szCmd, " ", sizeof(szCmd)); + strncat(szCmd, token, sizeof(szCmd)); + } + + ConsolePrint(szCmd); + gEngfuncs.pfnServerCmd(szCmd); + + gEngfuncs.COM_FreeFile( afile ); +} + +void CHudAmmo::UserCmd_Rebuy() +{ + char *afile = (char*)gEngfuncs.COM_LoadFile("rebuy.txt", 5, NULL); + char *pfile = afile; + char token[64]; + char szCmd[1024]; + int lastCh; + + if( !pfile ) + { + ConsolePrint( "Can't open rebuy.txt file.\n" ); + return; + } + + // start with \" + strncpy(szCmd, "cl_setrebuy \"", sizeof(szCmd)); + + + + while(pfile = gEngfuncs.COM_ParseFile( pfile, token )) + { + strncat(szCmd, token, sizeof(szCmd)); + // append space after token + strncat(szCmd, " ", sizeof(szCmd)); + } + // replace last space with ", before terminator + lastCh = strlen(szCmd); + szCmd[lastCh - 1] = '\"'; + + ConsolePrint(szCmd); + gEngfuncs.pfnServerCmd(szCmd); + + gEngfuncs.COM_FreeFile( afile ); +} + + +//------------------------------------------------------------------------- +// Drawing code +//------------------------------------------------------------------------- + +int CHudAmmo::Draw(float flTime) +{ + wrect_t nullrc; + int a, x, y, r, g, b; + int AmmoWidth; + + if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) + return 1; + + if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) ) + return 1; + + // Draw Weapon Menu + DrawWList(flTime); + + // Draw ammo pickup history + gHR.DrawAmmoHistory( flTime ); + + if (!(m_iFlags & HUD_ACTIVE)) + return 0; + + if (!m_pWeapon) + return 0; + + if( gHUD.m_iFOV > 40 ) + { + SetCrosshair( 0, nullrc, 0, 0, 0); + DrawCrosshair(flTime, m_pWeapon->iId); // draw a dynamic crosshair + } + else + { + SetCrosshair(m_pWeapon->hZoomedCrosshair, m_pWeapon->rcZoomedCrosshair, 255, 255, 255); + } + + WEAPON *pw = m_pWeapon; // shorthand + + // SPR_Draw Ammo + if ((pw->iAmmoType < 0) && (pw->iAmmo2Type < 0)) + return 0; + + int iFlags = DHN_DRAWZERO; // draw 0 values + + AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; + + a = (int) max( MIN_ALPHA, m_fFade ); + + if (m_fFade > 0) + m_fFade -= (gHUD.m_flTimeDelta * 20); + + DrawUtils::DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + DrawUtils::DrawUtils::ScaleColors(r, g, b, a ); + + // Does this weapon have a clip? + y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight/2; + + // Does weapon have any ammo at all? + if (m_pWeapon->iAmmoType > 0) + { + int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left; + + if (pw->iClip >= 0) + { + // room for the number and the '|' and the current ammo + + x = ScreenWidth - (8 * AmmoWidth) - iIconWidth; + x = DrawUtils::DrawHudNumber(x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b); + + wrect_t rc; + rc.top = 0; + rc.left = 0; + rc.right = AmmoWidth; + rc.bottom = 100; + + int iBarWidth = AmmoWidth/10; + + x += AmmoWidth/2; + + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + // draw the | bar + FillRGBA(x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a); + + x += iBarWidth + AmmoWidth/2;; + + // GL Seems to need this + DrawUtils::ScaleColors(r, g, b, a ); + x = DrawUtils::DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b); + + + } + else + { + // SPR_Draw a bullets only line + x = ScreenWidth - 4 * AmmoWidth - iIconWidth; + x = DrawUtils::DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo(pw->iAmmoType), r, g, b); + } + + // Draw the ammo Icon + int iOffset = (m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top)/8; + SPR_Set(m_pWeapon->hAmmo, r, g, b); + SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo); + } + + // Does weapon have seconday ammo? + if (pw->iAmmo2Type > 0) + { + int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left; + + // Do we have secondary ammo? + if ((pw->iAmmo2Type != 0) && (gWR.CountAmmo(pw->iAmmo2Type) > 0)) + { + y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight/4; + x = ScreenWidth - 4 * AmmoWidth - iIconWidth; + x = DrawUtils::DrawHudNumber(x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo(pw->iAmmo2Type), r, g, b); + + // Draw the ammo Icon + SPR_Set(m_pWeapon->hAmmo2, r, g, b); + int iOffset = (m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top)/8; + SPR_DrawAdditive(0, x, y - iOffset, &m_pWeapon->rcAmmo2); + } + } + + return 1; +} + +#define WEST_XPOS (ScreenWidth / 2 - flCrosshairDistance - iLength + 1) +#define EAST_XPOS (flCrosshairDistance + ScreenWidth / 2) +#define EAST_WEST_YPOS (ScreenHeight / 2) + +#define NORTH_YPOS (ScreenHeight / 2 - flCrosshairDistance - iLength + 1) +#define SOUTH_YPOS (ScreenHeight / 2 + flCrosshairDistance) +#define NORTH_SOUTH_XPOS (ScreenWidth / 2) + +int Distances[30][2] = +{ +{ 8, 3 }, // 0 +{ 4, 3 }, // 1 +{ 5, 3 }, // 2 +{ 8, 3 }, // 3 +{ 9, 4 }, // 4 +{ 6, 3 }, // 5 +{ 9, 3 }, // 6 +{ 3, 3 }, // 7 +{ 8, 3 }, // 8 +{ 4, 3 }, // 9 +{ 8, 3 }, // 10 +{ 6, 3 }, // 11 +{ 5, 3 }, // 12 +{ 4, 3 }, // 13 +{ 4, 3 }, // 14 +{ 8, 3 }, // 15 +{ 8, 3 }, // 16 +{ 8, 3 }, // 17 +{ 6, 3 }, // 18 +{ 6, 3 }, // 19 +{ 8, 6 }, // 20 +{ 4, 3 }, // 21 +{ 7, 3 }, // 22 +{ 6, 4 }, // 23 +{ 8, 3 }, // 24 +{ 8, 3 }, // 25 +{ 5, 3 }, // 26 +{ 4, 4 }, // 27 +{ 7, 3 }, // 28 +{ 7, 3 }, // 29 +}; + +void CHudAmmo::DrawCrosshair( float flTime, int weaponid ) +{ + int flags; + int iDeltaDistance, iDistance; + int iLength; + float flCrosshairDistance; + + + if ( g_iWeaponFlags & WPNSTATE_SHIELD_DRAWN ) + return; + + if ( weaponid > 30 ) + { + iDistance = 4; + iDeltaDistance = 3; + } + else + { + // TODO: Get an info about crosshair for weapon + iDistance = Distances[weaponid-1][0]; + iDeltaDistance = Distances[weaponid-1][1]; + } + + iLength = 0; + flags = GetWeaponAccuracyFlags(weaponid); + if ( flags && m_pClDynamicCrosshair->value && !(gHUD.m_iHideHUDDisplay & 1) ) + { + if ( g_iPlayerFlags & FL_ONGROUND || !(flags & ACCURACY_AIR) ) + { + if ( (g_iPlayerFlags & FL_DUCKING) && (flags & ACCURACY_DUCK) ) + iDistance *= 0.5; + else + { + int iWeaponSpeed = 0; + + switch( weaponid ) + { + case 30: // p90 + iWeaponSpeed = 170; + break; + case 8: // aug + case 14: // galil + case 15: // famas + case 20: // m249 + case 22: // m4a1 + case 27: // sg552 + case 28: // ak47 + iWeaponSpeed = 140; + break; + } + + if ( (g_flPlayerSpeed >= iWeaponSpeed) && (flags & ACCURACY_SPEED) ) + iDistance *= 1.5; + } + } + else iDistance *= 2; + if ( flags & ACCURACY_MULTIPLY_BY_14 ) + iDistance *= 1.4; + if ( flags & ACCURACY_MULTIPLY_BY_14_2 ) + iDistance *= 1.4; + } + + if ( m_iAmmoLastCheck >= g_iShotsFired ) + { + m_flCrosshairDistance -= (m_flCrosshairDistance * 0.013 + 0.1 ); + m_iAlpha += 2; + } + else + { + m_flCrosshairDistance += iDeltaDistance; + m_iAlpha -= 40; + + if ( m_flCrosshairDistance > 15.0 ) + m_flCrosshairDistance = 15.0; + if ( m_iAlpha < 120 ) + m_iAlpha = 120; + } + + if ( g_iShotsFired > 600 ) + g_iShotsFired = 1; + + CalcCrosshairColor(); + CalcCrosshairDrawMode(); + CalcCrosshairSize(); + + m_iAmmoLastCheck = g_iShotsFired; + if ( iDistance > m_flCrosshairDistance ) + m_flCrosshairDistance = iDistance; + if ( m_iAlpha > 255 ) + m_iAlpha = 255; + iLength = (m_flCrosshairDistance - iDistance) * 0.5 + 5; + flCrosshairDistance = m_flCrosshairDistance; + if ( ScreenWidth != m_iCrosshairScaleBase ) + { + flCrosshairDistance = ScreenWidth * flCrosshairDistance / m_iCrosshairScaleBase; + iLength = ScreenWidth * iLength / m_iCrosshairScaleBase; + } + + + // drawing + if ( gHUD.m_NVG.m_iEnable ) + { + FillRGBABlend(WEST_XPOS, EAST_WEST_YPOS, iLength, 1, 250, 50, 50, m_iAlpha); + FillRGBABlend(EAST_XPOS, EAST_WEST_YPOS, iLength, 1, 250, 50, 50, m_iAlpha); + FillRGBABlend(NORTH_SOUTH_XPOS, NORTH_YPOS, 1, iLength, 250, 50, 50, m_iAlpha); + FillRGBABlend(NORTH_SOUTH_XPOS, SOUTH_YPOS, 1, iLength, 250, 50, 50, m_iAlpha); + } + else if ( !m_bAdditive ) + { + FillRGBABlend(WEST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); + FillRGBABlend(EAST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); + FillRGBABlend(NORTH_SOUTH_XPOS, NORTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); + FillRGBABlend(NORTH_SOUTH_XPOS, SOUTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); + } + else + { + FillRGBA(WEST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); + FillRGBA(EAST_XPOS, EAST_WEST_YPOS, iLength, 1, m_R, m_G, m_B, m_iAlpha); + FillRGBA(NORTH_SOUTH_XPOS, NORTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); + FillRGBA(NORTH_SOUTH_XPOS, SOUTH_YPOS, 1, iLength, m_R, m_G, m_B, m_iAlpha); + } + return; +} + +void CHudAmmo::CalcCrosshairSize() +{ + const char *size = m_pClCrosshairSize->string; + + if( !stricmp(size, "auto") ) + { + if( ScreenWidth < 640 ) + m_iCrosshairScaleBase = 1024; + else if( ScreenWidth < 1024 ) + m_iCrosshairScaleBase = 800; + else m_iCrosshairScaleBase = 640; + } + else if( !stricmp( size, "small" )) + { + m_iCrosshairScaleBase = 640; + } + else if( !stricmp( size, "medium" )) + { + m_iCrosshairScaleBase = 800; + } + else if( !stricmp( size, "large" )) + { + m_iCrosshairScaleBase = 1024; + } + return; +} + +void CHudAmmo::CalcCrosshairDrawMode() +{ + float drawMode = m_pClCrosshairTranslucent->value; + if ( drawMode == 0.0f ) + { + m_bAdditive = 0; + } + else if ( drawMode == 1.0f ) + { + m_bAdditive = 1; + } + else + { + gEngfuncs.Con_Printf("usage: cl_crosshair_translucent <1|0>\n"); + } +} + +void CHudAmmo::CalcCrosshairColor() +{ + const char *colors = m_pClCrosshairColor->string; + + int tempR; + int tempG; + int tempB; + + sscanf( colors, "%d %d %d", &tempR, &tempG, &tempB); + + m_R = m_cvarR = bound( 0, tempR, 255 ); + m_G = m_cvarG = bound( 0, tempG, 255 ); + m_B = m_cvarB = bound( 0, tempB, 255 ); +} + +// +// Draws the ammo bar on the hud +// +int DrawBar(int x, int y, int width, int height, float f) +{ + int r, g, b; + + if (f < 0) + f = 0; + if (f > 1) + f = 1; + + if (f) + { + int w = f * width; + + // Always show at least one pixel if we have ammo. + if (w <= 0) + w = 1; + DrawUtils::UnpackRGB(r, g, b, RGB_GREENISH); + FillRGBA(x, y, w, height, r, g, b, 255); + x += w; + width -= w; + } + + DrawUtils::UnpackRGB(r, g, b, RGB_YELLOWISH); + + FillRGBA(x, y, width, height, r, g, b, 128); + + return (x + width); +} + + + +void DrawAmmoBar(WEAPON *p, int x, int y, int width, int height) +{ + if ( !p ) + return; + + if (p->iAmmoType != -1) + { + if (!gWR.CountAmmo(p->iAmmoType)) + return; + + float f = (float)gWR.CountAmmo(p->iAmmoType)/(float)p->iMax1; + + x = DrawBar(x, y, width, height, f); + + + // Do we have secondary ammo too? + + if (p->iAmmo2Type != -1) + { + f = (float)gWR.CountAmmo(p->iAmmo2Type)/(float)p->iMax2; + + x += 5; //!!! + + DrawBar(x, y, width, height, f); + } + } +} + + + + +// +// Draw Weapon Menu +// +int CHudAmmo::DrawWList(float flTime) +{ + int r,g,b,x,y,a,i; + + if ( !gpActiveSel ) + return 0; + + int iActiveSlot; + + if ( gpActiveSel == (WEAPON *)1 ) + iActiveSlot = -1; // current slot has no weapons + else + iActiveSlot = gpActiveSel->iSlot; + + x = gHUD.m_Radar.m_hRadar.rect.right + 10; //!!! + y = 10; //!!! + + + // Ensure that there are available choices in the active slot + if ( iActiveSlot > 0 ) + { + if ( !gWR.GetFirstPos( iActiveSlot ) ) + { + gpActiveSel = (WEAPON *)1; + iActiveSlot = -1; + } + } + + // Draw top line + for ( i = 0; i < MAX_WEAPON_SLOTS; i++ ) + { + int iWidth; + + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + if ( iActiveSlot == i ) + a = 255; + else + a = 192; + + DrawUtils::ScaleColors(r, g, b, 255); + SPR_Set(gHUD.GetSprite(m_HUD_bucket0 + i), r, g, b ); + + // make active slot wide enough to accomodate gun pictures + if ( i == iActiveSlot ) + { + WEAPON *p = gWR.GetFirstPos(iActiveSlot); + if ( p ) + iWidth = p->rcActive.right - p->rcActive.left; + else + iWidth = giBucketWidth; + } + else + iWidth = giBucketWidth; + + SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_bucket0 + i)); + + x += iWidth + 5; + } + + + a = 128; //!!! + x = gHUD.m_Radar.m_hRadar.rect.right + 10; //!!!; + + // Draw all of the buckets + for (i = 0; i < MAX_WEAPON_SLOTS; i++) + { + y = giBucketHeight + 10; + + // If this is the active slot, draw the bigger pictures, + // otherwise just draw boxes + if ( i == iActiveSlot ) + { + WEAPON *p = gWR.GetFirstPos( i ); + int iWidth = giBucketWidth; + if ( p ) + iWidth = p->rcActive.right - p->rcActive.left; + + for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) + { + p = gWR.GetWeaponSlot( i, iPos ); + + if ( !p || !p->iId ) + continue; + + + // if active, then we must have ammo. + if ( gWR.HasAmmo(p) ) + { + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH ); + DrawUtils::ScaleColors(r, g, b, 192); + } + else + { + DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); + DrawUtils::ScaleColors(r, g, b, 128); + } + + + if ( gpActiveSel == p ) + { + SPR_Set(p->hActive, r, g, b ); + SPR_DrawAdditive(0, x, y, &p->rcActive); + + SPR_Set(gHUD.GetSprite(m_HUD_selection), r, g, b ); + SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_selection)); + } + else + { + // Draw Weapon if Red if no ammo + SPR_Set( p->hInactive, r, g, b ); + SPR_DrawAdditive( 0, x, y, &p->rcInactive ); + } + + // Draw Ammo Bar + + DrawAmmoBar(p, x + giABWidth/2, y, giABWidth, giABHeight); + + y += p->rcActive.bottom - p->rcActive.top + 5; + } + + x += iWidth + 5; + + } + else + { + // Draw Row of weapons. + + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + for ( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) + { + WEAPON *p = gWR.GetWeaponSlot( i, iPos ); + + if ( !p || !p->iId ) + continue; + + if ( gWR.HasAmmo(p) ) + { + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + a = 128; + } + else + { + DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); + a = 96; + } + + FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a ); + + y += giBucketHeight + 5; + } + + x += giBucketWidth + 5; + } + } + + return 1; + +} + + +/* ================================= + GetSpriteList + +Finds and returns the matching +sprite name 'psz' and resolution 'iRes' +in the given sprite list 'pList' +iCount is the number of items in the pList +================================= */ +client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount) +{ + if (!pList) + return NULL; + + int i = iCount; + client_sprite_t *p = pList; + + while(i--) + { + if ((!strcmp(psz, p->szName)) && (p->iRes == iRes)) + return p; + p++; + } + + return NULL; +} diff --git a/cl_dll/hud/ammo_secondary.cpp b/cl_dll/hud/ammo_secondary.cpp index 5dba1cd..838b977 100644 --- a/cl_dll/hud/ammo_secondary.cpp +++ b/cl_dll/hud/ammo_secondary.cpp @@ -1,159 +1,159 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// ammo_secondary.cpp -// -// implementation of CHudAmmoSecondary class -// - -#include "hud.h" -#include "cl_util.h" -#include -#include -#include "parsemsg.h" - -DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoVal ); -DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoIcon ); - -int CHudAmmoSecondary :: Init( void ) -{ - HOOK_MESSAGE( SecAmmoVal ); - HOOK_MESSAGE( SecAmmoIcon ); - - gHUD.AddHudElem(this); - m_HUD_ammoicon = 0; - - for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ ) - m_iAmmoAmounts[i] = -1; // -1 means don't draw this value - - Reset(); - - return 1; -} - -void CHudAmmoSecondary :: Reset( void ) -{ - m_fFade = 0; -} - -int CHudAmmoSecondary :: VidInit( void ) -{ - return 1; -} - -int CHudAmmoSecondary :: Draw(float flTime) -{ - if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) ) - return 1; - - // draw secondary ammo icons above normal ammo readout - int a, x, y, r, g, b, AmmoWidth; - DrawUtils::UnpackRGB( r, g, b, RGB_YELLOWISH ); - a = (int) max( MIN_ALPHA, m_fFade ); - if (m_fFade > 0) - m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons - DrawUtils::ScaleColors( r, g, b, a ); - - AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; - - y = ScreenHeight - (gHUD.m_iFontHeight*4); // this is one font height higher than the weapon ammo values - x = ScreenWidth - AmmoWidth; - - if ( m_HUD_ammoicon ) - { - // Draw the ammo icon - x -= (gHUD.GetSpriteRect(m_HUD_ammoicon).right - gHUD.GetSpriteRect(m_HUD_ammoicon).left); - y -= (gHUD.GetSpriteRect(m_HUD_ammoicon).top - gHUD.GetSpriteRect(m_HUD_ammoicon).bottom); - - SPR_Set( gHUD.GetSprite(m_HUD_ammoicon), r, g, b ); - SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_ammoicon) ); - } - else - { // move the cursor by the '0' char instead, since we don't have an icon to work with - x -= AmmoWidth; - y -= (gHUD.GetSpriteRect(gHUD.m_HUD_number_0).top - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).bottom); - } - - // draw the ammo counts, in reverse order, from right to left - for ( int i = MAX_SEC_AMMO_VALUES-1; i >= 0; i-- ) - { - if ( m_iAmmoAmounts[i] < 0 ) - continue; // negative ammo amounts imply that they shouldn't be drawn - - // half a char gap between the ammo number and the previous pic - x -= (AmmoWidth / 2); - - // draw the number, right-aligned - x -= (DrawUtils::GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth); - DrawUtils::DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b ); - - if ( i != 0 ) - { - // draw the divider bar - x -= (AmmoWidth / 2); - FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a); - } - } - - return 1; -} - -// Message handler for Secondary Ammo Value -// accepts one value: -// string: sprite name -int CHudAmmoSecondary :: MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - m_HUD_ammoicon = gHUD.GetSpriteIndex( READ_STRING() ); - - return 1; -} - -// Message handler for Secondary Ammo Icon -// Sets an ammo value -// takes two values: -// byte: ammo index -// byte: ammo value -int CHudAmmoSecondary :: MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int index = READ_BYTE(); - if ( index < 0 || index >= MAX_SEC_AMMO_VALUES ) - return 1; - - m_iAmmoAmounts[index] = READ_BYTE(); - m_iFlags |= HUD_ACTIVE; - - // check to see if there is anything left to draw - int count = 0; - for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ ) - { - count += max( 0, m_iAmmoAmounts[i] ); - } - - if ( count == 0 ) - { // the ammo fields are all empty, so turn off this hud area - m_iFlags &= ~HUD_ACTIVE; - return 1; - } - - // make the icons light up - m_fFade = 200.0f; - - return 1; -} - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// ammo_secondary.cpp +// +// implementation of CHudAmmoSecondary class +// + +#include "hud.h" +#include "cl_util.h" +#include +#include +#include "parsemsg.h" + +DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoVal ); +DECLARE_MESSAGE( m_AmmoSecondary, SecAmmoIcon ); + +int CHudAmmoSecondary :: Init( void ) +{ + HOOK_MESSAGE( SecAmmoVal ); + HOOK_MESSAGE( SecAmmoIcon ); + + gHUD.AddHudElem(this); + m_HUD_ammoicon = 0; + + for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ ) + m_iAmmoAmounts[i] = -1; // -1 means don't draw this value + + Reset(); + + return 1; +} + +void CHudAmmoSecondary :: Reset( void ) +{ + m_fFade = 0; +} + +int CHudAmmoSecondary :: VidInit( void ) +{ + return 1; +} + +int CHudAmmoSecondary :: Draw(float flTime) +{ + if ( (gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL )) ) + return 1; + + // draw secondary ammo icons above normal ammo readout + int a, x, y, r, g, b, AmmoWidth; + DrawUtils::UnpackRGB( r, g, b, RGB_YELLOWISH ); + a = (int) max( MIN_ALPHA, m_fFade ); + if (m_fFade > 0) + m_fFade -= (gHUD.m_flTimeDelta * 20); // slowly lower alpha to fade out icons + DrawUtils::ScaleColors( r, g, b, a ); + + AmmoWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; + + y = ScreenHeight - (gHUD.m_iFontHeight*4); // this is one font height higher than the weapon ammo values + x = ScreenWidth - AmmoWidth; + + if ( m_HUD_ammoicon ) + { + // Draw the ammo icon + x -= (gHUD.GetSpriteRect(m_HUD_ammoicon).right - gHUD.GetSpriteRect(m_HUD_ammoicon).left); + y -= (gHUD.GetSpriteRect(m_HUD_ammoicon).top - gHUD.GetSpriteRect(m_HUD_ammoicon).bottom); + + SPR_Set( gHUD.GetSprite(m_HUD_ammoicon), r, g, b ); + SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_ammoicon) ); + } + else + { // move the cursor by the '0' char instead, since we don't have an icon to work with + x -= AmmoWidth; + y -= (gHUD.GetSpriteRect(gHUD.m_HUD_number_0).top - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).bottom); + } + + // draw the ammo counts, in reverse order, from right to left + for ( int i = MAX_SEC_AMMO_VALUES-1; i >= 0; i-- ) + { + if ( m_iAmmoAmounts[i] < 0 ) + continue; // negative ammo amounts imply that they shouldn't be drawn + + // half a char gap between the ammo number and the previous pic + x -= (AmmoWidth / 2); + + // draw the number, right-aligned + x -= (DrawUtils::GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth); + DrawUtils::DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b ); + + if ( i != 0 ) + { + // draw the divider bar + x -= (AmmoWidth / 2); + FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a); + } + } + + return 1; +} + +// Message handler for Secondary Ammo Value +// accepts one value: +// string: sprite name +int CHudAmmoSecondary :: MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + m_HUD_ammoicon = gHUD.GetSpriteIndex( READ_STRING() ); + + return 1; +} + +// Message handler for Secondary Ammo Icon +// Sets an ammo value +// takes two values: +// byte: ammo index +// byte: ammo value +int CHudAmmoSecondary :: MsgFunc_SecAmmoVal( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int index = READ_BYTE(); + if ( index < 0 || index >= MAX_SEC_AMMO_VALUES ) + return 1; + + m_iAmmoAmounts[index] = READ_BYTE(); + m_iFlags |= HUD_ACTIVE; + + // check to see if there is anything left to draw + int count = 0; + for ( int i = 0; i < MAX_SEC_AMMO_VALUES; i++ ) + { + count += max( 0, m_iAmmoAmounts[i] ); + } + + if ( count == 0 ) + { // the ammo fields are all empty, so turn off this hud area + m_iFlags &= ~HUD_ACTIVE; + return 1; + } + + // make the icons light up + m_fFade = 200.0f; + + return 1; +} + + diff --git a/cl_dll/hud/ammohistory.cpp b/cl_dll/hud/ammohistory.cpp index 39ff699..b84b4eb 100644 --- a/cl_dll/hud/ammohistory.cpp +++ b/cl_dll/hud/ammohistory.cpp @@ -1,191 +1,191 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// ammohistory.cpp -// - - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" - -#include -#include - -#include "ammohistory.h" - -HistoryResource gHR; - -#define AMMO_PICKUP_GAP (gHR.iHistoryGap+5) -#define AMMO_PICKUP_PICK_HEIGHT (gHUD.m_iFontHeight * 3 + (gHR.iHistoryGap * 2)) -#define AMMO_PICKUP_HEIGHT_MAX (ScreenHeight - 100) - -#define MAX_ITEM_NAME 32 -int HISTORY_DRAW_TIME = 5; - -// keep a list of items -struct ITEM_INFO -{ - char szName[MAX_ITEM_NAME]; - HSPRITE spr; - wrect_t rect; -}; - -void HistoryResource :: AddToHistory( int iType, int iId, int iCount ) -{ - if ( iType == HISTSLOT_AMMO && !iCount ) - return; // no amount, so don't add - - if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) ) - { // the pic would have to be drawn too high - // so start from the bottom - iCurrentHistorySlot = 0; - } - - HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot - HISTORY_DRAW_TIME = gHUD.m_Ammo.m_pHud_DrawHistory_Time->value; - - freeslot->type = iType; - freeslot->iId = iId; - freeslot->iCount = iCount; - freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME; -} - -void HistoryResource :: AddToHistory( int iType, const char *szName, int iCount ) -{ - if ( iType != HISTSLOT_ITEM ) - return; - - if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) ) - { // the pic would have to be drawn too high - // so start from the bottom - iCurrentHistorySlot = 0; - } - - HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot - - // I am really unhappy with all the code in this file - // I am too, -- a1batross - - int i = gHUD.GetSpriteIndex( szName ); - if ( i == -1 ) - return; // unknown sprite name, don't add it to history - - freeslot->iId = i; - freeslot->type = iType; - freeslot->iCount = iCount; - - HISTORY_DRAW_TIME = gHUD.m_Ammo.m_pHud_DrawHistory_Time->value; - freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME; -} - - -void HistoryResource :: CheckClearHistory( void ) -{ - for ( int i = 0; i < MAX_HISTORY; i++ ) - { - if ( rgAmmoHistory[i].type ) - return; - } - - iCurrentHistorySlot = 0; -} - -// -// Draw Ammo pickup history -// -int HistoryResource :: DrawAmmoHistory( float flTime ) -{ - for ( int i = 0; i < MAX_HISTORY; i++ ) - { - if ( rgAmmoHistory[i].type ) - { - rgAmmoHistory[i].DisplayTime = min( rgAmmoHistory[i].DisplayTime, gHUD.m_flTime + HISTORY_DRAW_TIME ); - - if ( rgAmmoHistory[i].DisplayTime <= flTime ) - { // pic drawing time has expired - memset( &rgAmmoHistory[i], 0, sizeof(HIST_ITEM) ); - CheckClearHistory(); - } - else if ( rgAmmoHistory[i].type == HISTSLOT_AMMO ) - { - wrect_t rcPic; - HSPRITE *spr = gWR.GetAmmoPicFromWeapon( rgAmmoHistory[i].iId, rcPic ); - - int r, g, b; - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - DrawUtils::ScaleColors(r, g, b, min(scale, 255) ); - - // Draw the pic - int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - 24; - if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic - { // the dll has to make sure it has sent info the weapons you need - SPR_Set( *spr, r, g, b ); - SPR_DrawAdditive( 0, xpos, ypos, &rcPic ); - } - - // Draw the number - DrawUtils::DrawHudNumberString( xpos - 10, ypos, xpos - 100, rgAmmoHistory[i].iCount, r, g, b ); - } - else if ( rgAmmoHistory[i].type == HISTSLOT_WEAP ) - { - WEAPON *weap = gWR.GetWeapon( rgAmmoHistory[i].iId ); - - if ( !weap ) - return 1; // we don't know about the weapon yet, so don't draw anything - - int r, g, b; - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - if ( !gWR.HasAmmo( weap ) ) - DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red - - float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - DrawUtils::ScaleColors(r, g, b, min(scale, 255) ); - - int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); - SPR_Set( weap->hInactive, r, g, b ); - SPR_DrawAdditive( 0, xpos, ypos, &weap->rcInactive ); - } - else if ( rgAmmoHistory[i].type == HISTSLOT_ITEM ) - { - int r, g, b; - - if ( !rgAmmoHistory[i].iId ) - continue; // sprite not loaded - - wrect_t rect = gHUD.GetSpriteRect( rgAmmoHistory[i].iId ); - - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; - DrawUtils::ScaleColors(r, g, b, min(scale, 255) ); - - int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); - int xpos = ScreenWidth - (rect.right - rect.left) - 10; - - SPR_Set( gHUD.GetSprite( rgAmmoHistory[i].iId ), r, g, b ); - SPR_DrawAdditive( 0, xpos, ypos, &rect ); - } - } - } - - - return 1; -} - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// ammohistory.cpp +// + + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include + +#include "ammohistory.h" + +HistoryResource gHR; + +#define AMMO_PICKUP_GAP (gHR.iHistoryGap+5) +#define AMMO_PICKUP_PICK_HEIGHT (gHUD.m_iFontHeight * 3 + (gHR.iHistoryGap * 2)) +#define AMMO_PICKUP_HEIGHT_MAX (ScreenHeight - 100) + +#define MAX_ITEM_NAME 32 +int HISTORY_DRAW_TIME = 5; + +// keep a list of items +struct ITEM_INFO +{ + char szName[MAX_ITEM_NAME]; + HSPRITE spr; + wrect_t rect; +}; + +void HistoryResource :: AddToHistory( int iType, int iId, int iCount ) +{ + if ( iType == HISTSLOT_AMMO && !iCount ) + return; // no amount, so don't add + + if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) ) + { // the pic would have to be drawn too high + // so start from the bottom + iCurrentHistorySlot = 0; + } + + HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot + HISTORY_DRAW_TIME = gHUD.m_Ammo.m_pHud_DrawHistory_Time->value; + + freeslot->type = iType; + freeslot->iId = iId; + freeslot->iCount = iCount; + freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME; +} + +void HistoryResource :: AddToHistory( int iType, const char *szName, int iCount ) +{ + if ( iType != HISTSLOT_ITEM ) + return; + + if ( (((AMMO_PICKUP_GAP * iCurrentHistorySlot) + AMMO_PICKUP_PICK_HEIGHT) > AMMO_PICKUP_HEIGHT_MAX) || (iCurrentHistorySlot >= MAX_HISTORY) ) + { // the pic would have to be drawn too high + // so start from the bottom + iCurrentHistorySlot = 0; + } + + HIST_ITEM *freeslot = &rgAmmoHistory[iCurrentHistorySlot++]; // default to just writing to the first slot + + // I am really unhappy with all the code in this file + // I am too, -- a1batross + + int i = gHUD.GetSpriteIndex( szName ); + if ( i == -1 ) + return; // unknown sprite name, don't add it to history + + freeslot->iId = i; + freeslot->type = iType; + freeslot->iCount = iCount; + + HISTORY_DRAW_TIME = gHUD.m_Ammo.m_pHud_DrawHistory_Time->value; + freeslot->DisplayTime = gHUD.m_flTime + HISTORY_DRAW_TIME; +} + + +void HistoryResource :: CheckClearHistory( void ) +{ + for ( int i = 0; i < MAX_HISTORY; i++ ) + { + if ( rgAmmoHistory[i].type ) + return; + } + + iCurrentHistorySlot = 0; +} + +// +// Draw Ammo pickup history +// +int HistoryResource :: DrawAmmoHistory( float flTime ) +{ + for ( int i = 0; i < MAX_HISTORY; i++ ) + { + if ( rgAmmoHistory[i].type ) + { + rgAmmoHistory[i].DisplayTime = min( rgAmmoHistory[i].DisplayTime, gHUD.m_flTime + HISTORY_DRAW_TIME ); + + if ( rgAmmoHistory[i].DisplayTime <= flTime ) + { // pic drawing time has expired + memset( &rgAmmoHistory[i], 0, sizeof(HIST_ITEM) ); + CheckClearHistory(); + } + else if ( rgAmmoHistory[i].type == HISTSLOT_AMMO ) + { + wrect_t rcPic; + HSPRITE *spr = gWR.GetAmmoPicFromWeapon( rgAmmoHistory[i].iId, rcPic ); + + int r, g, b; + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; + DrawUtils::ScaleColors(r, g, b, min(scale, 255) ); + + // Draw the pic + int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); + int xpos = ScreenWidth - 24; + if ( spr && *spr ) // weapon isn't loaded yet so just don't draw the pic + { // the dll has to make sure it has sent info the weapons you need + SPR_Set( *spr, r, g, b ); + SPR_DrawAdditive( 0, xpos, ypos, &rcPic ); + } + + // Draw the number + DrawUtils::DrawHudNumberString( xpos - 10, ypos, xpos - 100, rgAmmoHistory[i].iCount, r, g, b ); + } + else if ( rgAmmoHistory[i].type == HISTSLOT_WEAP ) + { + WEAPON *weap = gWR.GetWeapon( rgAmmoHistory[i].iId ); + + if ( !weap ) + return 1; // we don't know about the weapon yet, so don't draw anything + + int r, g, b; + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + if ( !gWR.HasAmmo( weap ) ) + DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red + + float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; + DrawUtils::ScaleColors(r, g, b, min(scale, 255) ); + + int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); + int xpos = ScreenWidth - (weap->rcInactive.right - weap->rcInactive.left); + SPR_Set( weap->hInactive, r, g, b ); + SPR_DrawAdditive( 0, xpos, ypos, &weap->rcInactive ); + } + else if ( rgAmmoHistory[i].type == HISTSLOT_ITEM ) + { + int r, g, b; + + if ( !rgAmmoHistory[i].iId ) + continue; // sprite not loaded + + wrect_t rect = gHUD.GetSpriteRect( rgAmmoHistory[i].iId ); + + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80; + DrawUtils::ScaleColors(r, g, b, min(scale, 255) ); + + int ypos = ScreenHeight - (AMMO_PICKUP_PICK_HEIGHT + (AMMO_PICKUP_GAP * i)); + int xpos = ScreenWidth - (rect.right - rect.left) - 10; + + SPR_Set( gHUD.GetSprite( rgAmmoHistory[i].iId ), r, g, b ); + SPR_DrawAdditive( 0, xpos, ypos, &rect ); + } + } + } + + + return 1; +} + + diff --git a/cl_dll/hud/death.cpp b/cl_dll/hud/death.cpp index 99b5aa4..03a90e3 100644 --- a/cl_dll/hud/death.cpp +++ b/cl_dll/hud/death.cpp @@ -1,298 +1,298 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// death notice -// -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" - -#include -#include -float color[3]; - -DECLARE_MESSAGE( m_DeathNotice, DeathMsg ); - -struct DeathNoticeItem { - char szKiller[MAX_PLAYER_NAME_LENGTH*2]; - char szVictim[MAX_PLAYER_NAME_LENGTH*2]; - int iId; // the index number of the associated sprite - bool bSuicide; - bool bTeamKill; - bool bNonPlayerKill; - float flDisplayTime; - float *KillerColor; - float *VictimColor; - int iHeadShotId; -}; - -#define MAX_DEATHNOTICES 4 -static int DEATHNOTICE_DISPLAY_TIME = 6; - -#define DEATHNOTICE_TOP 32 - -DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ]; - -int CHudDeathNotice :: Init( void ) -{ - gHUD.AddHudElem( this ); - - HOOK_MESSAGE( DeathMsg ); - - hud_deathnotice_time = CVAR_CREATE( "hud_deathnotice_time", "6", 0 ); - - return 1; -} - - -void CHudDeathNotice :: InitHUDData( void ) -{ - memset( rgDeathNoticeList, 0, sizeof(rgDeathNoticeList) ); -} - - -int CHudDeathNotice :: VidInit( void ) -{ - m_HUD_d_skull = gHUD.GetSpriteIndex( "d_skull" ); - m_HUD_d_headshot = gHUD.GetSpriteIndex("d_headshot"); - - return 1; -} - -int CHudDeathNotice :: Draw( float flTime ) -{ - int x, y, r, g, b; - - for ( int i = 0; i < MAX_DEATHNOTICES; i++ ) - { - if ( rgDeathNoticeList[i].iId == 0 ) - break; // we've gone through them all - - if ( rgDeathNoticeList[i].flDisplayTime < flTime ) - { // display time has expired - // remove the current item from the list - memmove( &rgDeathNoticeList[i], &rgDeathNoticeList[i+1], sizeof(DeathNoticeItem) * (MAX_DEATHNOTICES - i) ); - i--; // continue on the next item; stop the counter getting incremented - continue; - } - - rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME ); - - // Hide when scoreboard drawing. It will break triapi - //if ( gViewPort && gViewPort->AllowedToPrintText() ) - //if ( !gHUD.m_iNoConsolePrint ) - { - // Draw the death notice - y = YRES(DEATHNOTICE_TOP) + 2 + (20 * i); //!!! - - int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId; - x = ScreenWidth - DrawUtils::ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left); - if( rgDeathNoticeList[i].iHeadShotId ) - x -= gHUD.GetSpriteRect(m_HUD_d_headshot).right - gHUD.GetSpriteRect(m_HUD_d_headshot).left; - - if ( !rgDeathNoticeList[i].bSuicide ) - { - x -= (5 + DrawUtils::ConsoleStringLen( rgDeathNoticeList[i].szKiller ) ); - - // Draw killers name - if ( rgDeathNoticeList[i].KillerColor ) - DrawUtils::SetConsoleTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] ); - x = 5 + DrawUtils::DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller ); - } - - r = 255; g = 80; b = 0; - if ( rgDeathNoticeList[i].bTeamKill ) - { - 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); - - if( rgDeathNoticeList[i].iHeadShotId) - { - SPR_Set( gHUD.GetSprite(m_HUD_d_headshot), r, g, b ); - SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_d_headshot)); - x += (gHUD.GetSpriteRect(m_HUD_d_headshot).right - gHUD.GetSpriteRect(m_HUD_d_headshot).left); - } - - // Draw victims name (if it was a player that was killed) - if (!rgDeathNoticeList[i].bNonPlayerKill) - { - if ( rgDeathNoticeList[i].VictimColor ) - DrawUtils::SetConsoleTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] ); - x = DrawUtils::DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim ); - } - } - } - - return 1; -} - -// This message handler may be better off elsewhere -int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf ) -{ - m_iFlags |= HUD_ACTIVE; - - BEGIN_READ( pbuf, iSize ); - - int killer = READ_BYTE(); - int victim = READ_BYTE(); - int headshot = READ_BYTE(); - - char killedwith[32]; - strncpy( killedwith, "d_", sizeof(killedwith) ); - strncat( killedwith, READ_STRING(), sizeof(killedwith) ); - - //if (gViewPort) - // gViewPort->DeathMsg( killer, victim ); - gHUD.m_Scoreboard.DeathMsg( killer, victim ); - - gHUD.m_Spectator.DeathMessage(victim); - int i; - for ( i = 0; i < MAX_DEATHNOTICES; i++ ) - { - if ( rgDeathNoticeList[i].iId == 0 ) - break; - } - if ( i == MAX_DEATHNOTICES ) - { // move the rest of the list forward to make room for this item - memmove( rgDeathNoticeList, rgDeathNoticeList+1, sizeof(DeathNoticeItem) * MAX_DEATHNOTICES ); - i = MAX_DEATHNOTICES - 1; - } - - //if (gViewPort) - //gViewPort->GetAllPlayersInfo(); - gHUD.m_Scoreboard.GetAllPlayersInfo(); - - // 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; - } - - // Is it a non-player object kill? - if ( ((char)victim) == -1 ) - { - rgDeathNoticeList[i].bNonPlayerKill = true; - - // Store the object's name in the Victim slot (skip the d_ bit) - strncpy( rgDeathNoticeList[i].szVictim, killedwith+2, sizeof(killedwith) ); - } - else - { - if ( killer == victim || killer == 0 ) - rgDeathNoticeList[i].bSuicide = true; - - if ( !strncmp( killedwith, "d_teammate", sizeof(killedwith) ) ) - rgDeathNoticeList[i].bTeamKill = true; - } - - rgDeathNoticeList[i].iHeadShotId = headshot; - - // Find the sprite in the list - int spr = gHUD.GetSpriteIndex( killedwith ); - - rgDeathNoticeList[i].iId = spr; - - rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + hud_deathnotice_time->value; - - - if (rgDeathNoticeList[i].bNonPlayerKill) - { - ConsolePrint( rgDeathNoticeList[i].szKiller ); - ConsolePrint( " killed a " ); - ConsolePrint( rgDeathNoticeList[i].szVictim ); - ConsolePrint( "\n" ); - } - else - { - // record the death notice in the console - if ( rgDeathNoticeList[i].bSuicide ) - { - ConsolePrint( rgDeathNoticeList[i].szVictim ); - - if ( !strncmp( killedwith, "d_world", sizeof(killedwith) ) ) - { - ConsolePrint( " died" ); - } - else - { - ConsolePrint( " killed self" ); - } - } - else if ( rgDeathNoticeList[i].bTeamKill ) - { - ConsolePrint( rgDeathNoticeList[i].szKiller ); - ConsolePrint( " killed his teammate " ); - ConsolePrint( rgDeathNoticeList[i].szVictim ); - } - else - { - if( headshot ) - ConsolePrint( "*** "); - ConsolePrint( rgDeathNoticeList[i].szKiller ); - ConsolePrint( " killed " ); - ConsolePrint( rgDeathNoticeList[i].szVictim ); - } - - if ( killedwith && *killedwith && (*killedwith > 13 ) && strncmp( killedwith, "d_world", sizeof(killedwith) ) && !rgDeathNoticeList[i].bTeamKill ) - { - if ( headshot ) - ConsolePrint(" with a headshot from "); - else - ConsolePrint(" with "); - - ConsolePrint( killedwith+2 ); // skip over the "d_" part - } - - if( headshot ) ConsolePrint( " ***"); - ConsolePrint( "\n" ); - } - - return 1; -} - - - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// death notice +// +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include +float color[3]; + +DECLARE_MESSAGE( m_DeathNotice, DeathMsg ); + +struct DeathNoticeItem { + char szKiller[MAX_PLAYER_NAME_LENGTH*2]; + char szVictim[MAX_PLAYER_NAME_LENGTH*2]; + int iId; // the index number of the associated sprite + bool bSuicide; + bool bTeamKill; + bool bNonPlayerKill; + float flDisplayTime; + float *KillerColor; + float *VictimColor; + int iHeadShotId; +}; + +#define MAX_DEATHNOTICES 4 +static int DEATHNOTICE_DISPLAY_TIME = 6; + +#define DEATHNOTICE_TOP 32 + +DeathNoticeItem rgDeathNoticeList[ MAX_DEATHNOTICES + 1 ]; + +int CHudDeathNotice :: Init( void ) +{ + gHUD.AddHudElem( this ); + + HOOK_MESSAGE( DeathMsg ); + + hud_deathnotice_time = CVAR_CREATE( "hud_deathnotice_time", "6", 0 ); + + return 1; +} + + +void CHudDeathNotice :: InitHUDData( void ) +{ + memset( rgDeathNoticeList, 0, sizeof(rgDeathNoticeList) ); +} + + +int CHudDeathNotice :: VidInit( void ) +{ + m_HUD_d_skull = gHUD.GetSpriteIndex( "d_skull" ); + m_HUD_d_headshot = gHUD.GetSpriteIndex("d_headshot"); + + return 1; +} + +int CHudDeathNotice :: Draw( float flTime ) +{ + int x, y, r, g, b; + + for ( int i = 0; i < MAX_DEATHNOTICES; i++ ) + { + if ( rgDeathNoticeList[i].iId == 0 ) + break; // we've gone through them all + + if ( rgDeathNoticeList[i].flDisplayTime < flTime ) + { // display time has expired + // remove the current item from the list + memmove( &rgDeathNoticeList[i], &rgDeathNoticeList[i+1], sizeof(DeathNoticeItem) * (MAX_DEATHNOTICES - i) ); + i--; // continue on the next item; stop the counter getting incremented + continue; + } + + rgDeathNoticeList[i].flDisplayTime = min( rgDeathNoticeList[i].flDisplayTime, gHUD.m_flTime + DEATHNOTICE_DISPLAY_TIME ); + + // Hide when scoreboard drawing. It will break triapi + //if ( gViewPort && gViewPort->AllowedToPrintText() ) + //if ( !gHUD.m_iNoConsolePrint ) + { + // Draw the death notice + y = YRES(DEATHNOTICE_TOP) + 2 + (20 * i); //!!! + + int id = (rgDeathNoticeList[i].iId == -1) ? m_HUD_d_skull : rgDeathNoticeList[i].iId; + x = ScreenWidth - DrawUtils::ConsoleStringLen(rgDeathNoticeList[i].szVictim) - (gHUD.GetSpriteRect(id).right - gHUD.GetSpriteRect(id).left); + if( rgDeathNoticeList[i].iHeadShotId ) + x -= gHUD.GetSpriteRect(m_HUD_d_headshot).right - gHUD.GetSpriteRect(m_HUD_d_headshot).left; + + if ( !rgDeathNoticeList[i].bSuicide ) + { + x -= (5 + DrawUtils::ConsoleStringLen( rgDeathNoticeList[i].szKiller ) ); + + // Draw killers name + if ( rgDeathNoticeList[i].KillerColor ) + DrawUtils::SetConsoleTextColor( rgDeathNoticeList[i].KillerColor[0], rgDeathNoticeList[i].KillerColor[1], rgDeathNoticeList[i].KillerColor[2] ); + x = 5 + DrawUtils::DrawConsoleString( x, y, rgDeathNoticeList[i].szKiller ); + } + + r = 255; g = 80; b = 0; + if ( rgDeathNoticeList[i].bTeamKill ) + { + 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); + + if( rgDeathNoticeList[i].iHeadShotId) + { + SPR_Set( gHUD.GetSprite(m_HUD_d_headshot), r, g, b ); + SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_d_headshot)); + x += (gHUD.GetSpriteRect(m_HUD_d_headshot).right - gHUD.GetSpriteRect(m_HUD_d_headshot).left); + } + + // Draw victims name (if it was a player that was killed) + if (!rgDeathNoticeList[i].bNonPlayerKill) + { + if ( rgDeathNoticeList[i].VictimColor ) + DrawUtils::SetConsoleTextColor( rgDeathNoticeList[i].VictimColor[0], rgDeathNoticeList[i].VictimColor[1], rgDeathNoticeList[i].VictimColor[2] ); + x = DrawUtils::DrawConsoleString( x, y, rgDeathNoticeList[i].szVictim ); + } + } + } + + return 1; +} + +// This message handler may be better off elsewhere +int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *pbuf ) +{ + m_iFlags |= HUD_ACTIVE; + + BEGIN_READ( pbuf, iSize ); + + int killer = READ_BYTE(); + int victim = READ_BYTE(); + int headshot = READ_BYTE(); + + char killedwith[32]; + strncpy( killedwith, "d_", sizeof(killedwith) ); + strncat( killedwith, READ_STRING(), sizeof(killedwith) ); + + //if (gViewPort) + // gViewPort->DeathMsg( killer, victim ); + gHUD.m_Scoreboard.DeathMsg( killer, victim ); + + gHUD.m_Spectator.DeathMessage(victim); + int i; + for ( i = 0; i < MAX_DEATHNOTICES; i++ ) + { + if ( rgDeathNoticeList[i].iId == 0 ) + break; + } + if ( i == MAX_DEATHNOTICES ) + { // move the rest of the list forward to make room for this item + memmove( rgDeathNoticeList, rgDeathNoticeList+1, sizeof(DeathNoticeItem) * MAX_DEATHNOTICES ); + i = MAX_DEATHNOTICES - 1; + } + + //if (gViewPort) + //gViewPort->GetAllPlayersInfo(); + gHUD.m_Scoreboard.GetAllPlayersInfo(); + + // 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; + } + + // Is it a non-player object kill? + if ( ((char)victim) == -1 ) + { + rgDeathNoticeList[i].bNonPlayerKill = true; + + // Store the object's name in the Victim slot (skip the d_ bit) + strncpy( rgDeathNoticeList[i].szVictim, killedwith+2, sizeof(killedwith) ); + } + else + { + if ( killer == victim || killer == 0 ) + rgDeathNoticeList[i].bSuicide = true; + + if ( !strncmp( killedwith, "d_teammate", sizeof(killedwith) ) ) + rgDeathNoticeList[i].bTeamKill = true; + } + + rgDeathNoticeList[i].iHeadShotId = headshot; + + // Find the sprite in the list + int spr = gHUD.GetSpriteIndex( killedwith ); + + rgDeathNoticeList[i].iId = spr; + + rgDeathNoticeList[i].flDisplayTime = gHUD.m_flTime + hud_deathnotice_time->value; + + + if (rgDeathNoticeList[i].bNonPlayerKill) + { + ConsolePrint( rgDeathNoticeList[i].szKiller ); + ConsolePrint( " killed a " ); + ConsolePrint( rgDeathNoticeList[i].szVictim ); + ConsolePrint( "\n" ); + } + else + { + // record the death notice in the console + if ( rgDeathNoticeList[i].bSuicide ) + { + ConsolePrint( rgDeathNoticeList[i].szVictim ); + + if ( !strncmp( killedwith, "d_world", sizeof(killedwith) ) ) + { + ConsolePrint( " died" ); + } + else + { + ConsolePrint( " killed self" ); + } + } + else if ( rgDeathNoticeList[i].bTeamKill ) + { + ConsolePrint( rgDeathNoticeList[i].szKiller ); + ConsolePrint( " killed his teammate " ); + ConsolePrint( rgDeathNoticeList[i].szVictim ); + } + else + { + if( headshot ) + ConsolePrint( "*** "); + ConsolePrint( rgDeathNoticeList[i].szKiller ); + ConsolePrint( " killed " ); + ConsolePrint( rgDeathNoticeList[i].szVictim ); + } + + if ( killedwith && *killedwith && (*killedwith > 13 ) && strncmp( killedwith, "d_world", sizeof(killedwith) ) && !rgDeathNoticeList[i].bTeamKill ) + { + if ( headshot ) + ConsolePrint(" with a headshot from "); + else + ConsolePrint(" with "); + + ConsolePrint( killedwith+2 ); // skip over the "d_" part + } + + if( headshot ) ConsolePrint( " ***"); + ConsolePrint( "\n" ); + } + + return 1; +} + + + + diff --git a/cl_dll/hud/flashlight.cpp b/cl_dll/hud/flashlight.cpp index fcbab33..1a7ad39 100644 --- a/cl_dll/hud/flashlight.cpp +++ b/cl_dll/hud/flashlight.cpp @@ -1,139 +1,139 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// flashlight.cpp -// -// implementation of CHudFlashlight class -// - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" - -#include -#include - - - -DECLARE_MESSAGE(m_Flash, FlashBat) -DECLARE_MESSAGE(m_Flash, Flashlight) - -#define BAT_NAME "sprites/%d_Flashlight.spr" - -int CHudFlashlight::Init(void) -{ - m_fFade = 0; - m_fOn = 0; - - HOOK_MESSAGE(Flashlight); - HOOK_MESSAGE(FlashBat); - - m_iFlags |= HUD_ACTIVE; - - gHUD.AddHudElem(this); - - return 1; -}; - -void CHudFlashlight::Reset(void) -{ - m_fFade = 0; - m_fOn = 0; -} - -int CHudFlashlight::VidInit(void) -{ - m_hSprite1.SetSpriteByName("flash_empty"); - m_hSprite2.SetSpriteByName("flash_full"); - m_hBeam.SetSpriteByName("flash_beam"); - m_iWidth = m_hSprite1.rect.right - m_hSprite1.rect.left; - - return 1; -}; - -int CHudFlashlight:: MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - int x = READ_BYTE(); - m_iBat = x; - m_flBat = ((float)x)/100.0; - - return 1; -} - -int CHudFlashlight:: MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - m_fOn = READ_BYTE(); - int x = READ_BYTE(); - m_iBat = x; - m_flBat = ((float)x)/100.0; - - return 1; -} - -int CHudFlashlight::Draw(float flTime) -{ - if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) ) - return 1; - - int r, g, b, x, y, a; - wrect_t rc; - - if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) - return 1; - - if (m_fOn) - a = 225; - else - a = MIN_ALPHA; - - if (m_flBat < 0.20) - DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); - else - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - DrawUtils::ScaleColors(r, g, b, a); - - y = (m_hSprite1.rect.bottom - m_hSprite1.rect.top)/2; - x = ScreenWidth - m_iWidth - m_iWidth/2 ; - - // Draw the flashlight casing - SPR_Set(m_hSprite1.spr, r, g, b ); - SPR_DrawAdditive( 0, x, y, &m_hSprite1.rect); - - if ( m_fOn ) - { // draw the flashlight beam - x = ScreenWidth - m_iWidth/2; - - SPR_Set( m_hBeam.spr, r, g, b ); - SPR_DrawAdditive( 0, x, y, &m_hBeam.rect ); - } - - // draw the flashlight energy level - x = ScreenWidth - m_iWidth - m_iWidth/2 ; - int iOffset = m_iWidth * (1.0 - m_flBat); - if (iOffset < m_iWidth) - { - rc = m_hSprite2.rect; - rc.left += iOffset; - - SPR_Set(m_hSprite2.spr, r, g, b ); - SPR_DrawAdditive( 0, x + iOffset, y, &rc); - } - - - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// flashlight.cpp +// +// implementation of CHudFlashlight class +// + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include + + + +DECLARE_MESSAGE(m_Flash, FlashBat) +DECLARE_MESSAGE(m_Flash, Flashlight) + +#define BAT_NAME "sprites/%d_Flashlight.spr" + +int CHudFlashlight::Init(void) +{ + m_fFade = 0; + m_fOn = 0; + + HOOK_MESSAGE(Flashlight); + HOOK_MESSAGE(FlashBat); + + m_iFlags |= HUD_ACTIVE; + + gHUD.AddHudElem(this); + + return 1; +}; + +void CHudFlashlight::Reset(void) +{ + m_fFade = 0; + m_fOn = 0; +} + +int CHudFlashlight::VidInit(void) +{ + m_hSprite1.SetSpriteByName("flash_empty"); + m_hSprite2.SetSpriteByName("flash_full"); + m_hBeam.SetSpriteByName("flash_beam"); + m_iWidth = m_hSprite1.rect.right - m_hSprite1.rect.left; + + return 1; +}; + +int CHudFlashlight:: MsgFunc_FlashBat(const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + int x = READ_BYTE(); + m_iBat = x; + m_flBat = ((float)x)/100.0; + + return 1; +} + +int CHudFlashlight:: MsgFunc_Flashlight(const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + m_fOn = READ_BYTE(); + int x = READ_BYTE(); + m_iBat = x; + m_flBat = ((float)x)/100.0; + + return 1; +} + +int CHudFlashlight::Draw(float flTime) +{ + if ( gHUD.m_iHideHUDDisplay & ( HIDEHUD_FLASHLIGHT | HIDEHUD_ALL ) ) + return 1; + + int r, g, b, x, y, a; + wrect_t rc; + + if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) + return 1; + + if (m_fOn) + a = 225; + else + a = MIN_ALPHA; + + if (m_flBat < 0.20) + DrawUtils::UnpackRGB(r,g,b, RGB_REDISH); + else + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + DrawUtils::ScaleColors(r, g, b, a); + + y = (m_hSprite1.rect.bottom - m_hSprite1.rect.top)/2; + x = ScreenWidth - m_iWidth - m_iWidth/2 ; + + // Draw the flashlight casing + SPR_Set(m_hSprite1.spr, r, g, b ); + SPR_DrawAdditive( 0, x, y, &m_hSprite1.rect); + + if ( m_fOn ) + { // draw the flashlight beam + x = ScreenWidth - m_iWidth/2; + + SPR_Set( m_hBeam.spr, r, g, b ); + SPR_DrawAdditive( 0, x, y, &m_hBeam.rect ); + } + + // draw the flashlight energy level + x = ScreenWidth - m_iWidth - m_iWidth/2 ; + int iOffset = m_iWidth * (1.0 - m_flBat); + if (iOffset < m_iWidth) + { + rc = m_hSprite2.rect; + rc.left += iOffset; + + SPR_Set(m_hSprite2.spr, r, g, b ); + SPR_DrawAdditive( 0, x + iOffset, y, &rc); + } + + + return 1; +} diff --git a/cl_dll/hud/geiger.cpp b/cl_dll/hud/geiger.cpp index 6f5f984..8fa1407 100644 --- a/cl_dll/hud/geiger.cpp +++ b/cl_dll/hud/geiger.cpp @@ -1,184 +1,184 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// Geiger.cpp -// -// implementation of CHudAmmo class -// - -#include "hud.h" -#include "cl_util.h" -#include -#include -#include - -#include "parsemsg.h" - -DECLARE_MESSAGE(m_Geiger, Geiger ) - -int CHudGeiger::Init(void) -{ - HOOK_MESSAGE( Geiger ); - - m_iGeigerRange = 0; - m_iFlags = 0; - - gHUD.AddHudElem(this); - - srand( (unsigned)time( NULL ) ); - - return 1; -}; - -int CHudGeiger::VidInit(void) -{ - return 1; -}; - -int CHudGeiger::MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf) -{ - - BEGIN_READ( pbuf, iSize ); - - // update geiger data - m_iGeigerRange = READ_BYTE(); - m_iGeigerRange = m_iGeigerRange << 2; - - m_iFlags |= HUD_ACTIVE; - - return 1; -} - -int CHudGeiger::Draw (float flTime) -{ - int pct; - float flvol; - int rg[3]; - int i; - - if (m_iGeigerRange < 1000 && m_iGeigerRange > 0) - { - // peicewise linear is better than continuous formula for this - if (m_iGeigerRange > 800) - { - pct = 0; //Con_Printf ( "range > 800\n"); - } - else if (m_iGeigerRange > 600) - { - pct = 2; - flvol = 0.4; //Con_Printf ( "range > 600\n"); - rg[0] = 1; - rg[1] = 1; - i = 2; - } - else if (m_iGeigerRange > 500) - { - pct = 4; - flvol = 0.5; //Con_Printf ( "range > 500\n"); - rg[0] = 1; - rg[1] = 2; - i = 2; - } - else if (m_iGeigerRange > 400) - { - pct = 8; - flvol = 0.6; //Con_Printf ( "range > 400\n"); - rg[0] = 1; - rg[1] = 2; - rg[2] = 3; - i = 3; - } - else if (m_iGeigerRange > 300) - { - pct = 8; - flvol = 0.7; //Con_Printf ( "range > 300\n"); - rg[0] = 2; - rg[1] = 3; - rg[2] = 4; - i = 3; - } - else if (m_iGeigerRange > 200) - { - pct = 28; - flvol = 0.78; //Con_Printf ( "range > 200\n"); - rg[0] = 2; - rg[1] = 3; - rg[2] = 4; - i = 3; - } - else if (m_iGeigerRange > 150) - { - pct = 40; - flvol = 0.80; //Con_Printf ( "range > 150\n"); - rg[0] = 3; - rg[1] = 4; - rg[2] = 5; - i = 3; - } - else if (m_iGeigerRange > 100) - { - pct = 60; - flvol = 0.85; //Con_Printf ( "range > 100\n"); - rg[0] = 3; - rg[1] = 4; - rg[2] = 5; - i = 3; - } - else if (m_iGeigerRange > 75) - { - pct = 80; - flvol = 0.9; //Con_Printf ( "range > 75\n"); - //gflGeigerDelay = cl.time + GEIGERDELAY * 0.75; - rg[0] = 4; - rg[1] = 5; - rg[2] = 6; - i = 3; - } - else if (m_iGeigerRange > 50) - { - pct = 90; - flvol = 0.95; //Con_Printf ( "range > 50\n"); - rg[0] = 5; - rg[1] = 6; - i = 2; - } - else - { - pct = 95; - flvol = 1.0; //Con_Printf ( "range < 50\n"); - rg[0] = 5; - rg[1] = 6; - i = 2; - } - - flvol = (flvol * ((rand() & 127)) / 255) + 0.25; // UTIL_RandomFloat(0.25, 0.5); - - if ((rand() & 127) < pct || (rand() & 127) < pct) - { - //S_StartDynamicSound (-1, 0, rgsfx[rand() % i], r_origin, flvol, 1.0, 0, 100); - char sz[256]; - - int j = rand() & 1; - if (i > 2) - j += rand() & 1; - - sprintf(sz, "player/geiger%d.wav", j + 1); - PlaySound(sz, flvol); - - } - } - - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// Geiger.cpp +// +// implementation of CHudAmmo class +// + +#include "hud.h" +#include "cl_util.h" +#include +#include +#include + +#include "parsemsg.h" + +DECLARE_MESSAGE(m_Geiger, Geiger ) + +int CHudGeiger::Init(void) +{ + HOOK_MESSAGE( Geiger ); + + m_iGeigerRange = 0; + m_iFlags = 0; + + gHUD.AddHudElem(this); + + srand( (unsigned)time( NULL ) ); + + return 1; +}; + +int CHudGeiger::VidInit(void) +{ + return 1; +}; + +int CHudGeiger::MsgFunc_Geiger(const char *pszName, int iSize, void *pbuf) +{ + + BEGIN_READ( pbuf, iSize ); + + // update geiger data + m_iGeigerRange = READ_BYTE(); + m_iGeigerRange = m_iGeigerRange << 2; + + m_iFlags |= HUD_ACTIVE; + + return 1; +} + +int CHudGeiger::Draw (float flTime) +{ + int pct; + float flvol; + int rg[3]; + int i; + + if (m_iGeigerRange < 1000 && m_iGeigerRange > 0) + { + // peicewise linear is better than continuous formula for this + if (m_iGeigerRange > 800) + { + pct = 0; //Con_Printf ( "range > 800\n"); + } + else if (m_iGeigerRange > 600) + { + pct = 2; + flvol = 0.4; //Con_Printf ( "range > 600\n"); + rg[0] = 1; + rg[1] = 1; + i = 2; + } + else if (m_iGeigerRange > 500) + { + pct = 4; + flvol = 0.5; //Con_Printf ( "range > 500\n"); + rg[0] = 1; + rg[1] = 2; + i = 2; + } + else if (m_iGeigerRange > 400) + { + pct = 8; + flvol = 0.6; //Con_Printf ( "range > 400\n"); + rg[0] = 1; + rg[1] = 2; + rg[2] = 3; + i = 3; + } + else if (m_iGeigerRange > 300) + { + pct = 8; + flvol = 0.7; //Con_Printf ( "range > 300\n"); + rg[0] = 2; + rg[1] = 3; + rg[2] = 4; + i = 3; + } + else if (m_iGeigerRange > 200) + { + pct = 28; + flvol = 0.78; //Con_Printf ( "range > 200\n"); + rg[0] = 2; + rg[1] = 3; + rg[2] = 4; + i = 3; + } + else if (m_iGeigerRange > 150) + { + pct = 40; + flvol = 0.80; //Con_Printf ( "range > 150\n"); + rg[0] = 3; + rg[1] = 4; + rg[2] = 5; + i = 3; + } + else if (m_iGeigerRange > 100) + { + pct = 60; + flvol = 0.85; //Con_Printf ( "range > 100\n"); + rg[0] = 3; + rg[1] = 4; + rg[2] = 5; + i = 3; + } + else if (m_iGeigerRange > 75) + { + pct = 80; + flvol = 0.9; //Con_Printf ( "range > 75\n"); + //gflGeigerDelay = cl.time + GEIGERDELAY * 0.75; + rg[0] = 4; + rg[1] = 5; + rg[2] = 6; + i = 3; + } + else if (m_iGeigerRange > 50) + { + pct = 90; + flvol = 0.95; //Con_Printf ( "range > 50\n"); + rg[0] = 5; + rg[1] = 6; + i = 2; + } + else + { + pct = 95; + flvol = 1.0; //Con_Printf ( "range < 50\n"); + rg[0] = 5; + rg[1] = 6; + i = 2; + } + + flvol = (flvol * ((rand() & 127)) / 255) + 0.25; // UTIL_RandomFloat(0.25, 0.5); + + if ((rand() & 127) < pct || (rand() & 127) < pct) + { + //S_StartDynamicSound (-1, 0, rgsfx[rand() % i], r_origin, flvol, 1.0, 0, 100); + char sz[256]; + + int j = rand() & 1; + if (i > 2) + j += rand() & 1; + + sprintf(sz, "player/geiger%d.wav", j + 1); + PlaySound(sz, flvol); + + } + } + + return 1; +} diff --git a/cl_dll/hud/health.cpp b/cl_dll/hud/health.cpp index 858799a..e02cad0 100644 --- a/cl_dll/hud/health.cpp +++ b/cl_dll/hud/health.cpp @@ -1,551 +1,551 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// Health.cpp -// -// implementation of CHudHealth class -// - -#include "stdio.h" -#include "stdlib.h" -#include "math.h" - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" -#include -#include "eventscripts.h" - -DECLARE_MESSAGE(m_Health, Health ) -DECLARE_MESSAGE(m_Health, Damage ) -DECLARE_MESSAGE(m_Health, ScoreAttrib ) -DECLARE_MESSAGE(m_Health, ClCorpse ) - -#define PAIN_NAME "sprites/%d_pain.spr" -#define DAMAGE_NAME "sprites/%d_dmg.spr" - -cvar_t *cl_radartype; - -int giDmgHeight, giDmgWidth; - -float g_LocationColor[3]; - -int giDmgFlags[NUM_DMG_TYPES] = -{ - DMG_POISON, - DMG_ACID, - DMG_FREEZE|DMG_SLOWFREEZE, - DMG_DROWN, - DMG_BURN|DMG_SLOWBURN, - DMG_NERVEGAS, - DMG_RADIATION, - DMG_SHOCK, - DMG_CALTROP, - DMG_TRANQ, - DMG_CONCUSS, - DMG_HALLUC -}; - -int CHudHealth::Init(void) -{ - HOOK_MESSAGE(Health); - HOOK_MESSAGE(Damage); - HOOK_MESSAGE(ScoreAttrib); - HOOK_MESSAGE(ClCorpse); - - m_iHealth = 100; - m_fFade = 0; - m_iFlags = 0; - m_bitsDamage = 0; - m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0; - giDmgHeight = 0; - giDmgWidth = 0; - - memset(m_dmg, 0, sizeof(DAMAGE_IMAGE) * NUM_DMG_TYPES); - - CVAR_CREATE("cl_corpsestay", "600", FCVAR_ARCHIVE); - gHUD.AddHudElem(this); - return 1; -} - -void CHudHealth::Reset( void ) -{ - // make sure the pain compass is cleared when the player respawns - m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0; - - - // force all the flashing damage icons to expire - m_bitsDamage = 0; - for ( int i = 0; i < NUM_DMG_TYPES; i++ ) - { - m_dmg[i].fExpire = 0; - } -} - -int CHudHealth::VidInit(void) -{ - m_hSprite = 0; - - m_HUD_dmg_bio = gHUD.GetSpriteIndex( "dmg_bio" ) + 1; - m_HUD_cross = gHUD.GetSpriteIndex( "cross" ); - - giDmgHeight = gHUD.GetSpriteRect(m_HUD_dmg_bio).right - gHUD.GetSpriteRect(m_HUD_dmg_bio).left; - giDmgWidth = gHUD.GetSpriteRect(m_HUD_dmg_bio).bottom - gHUD.GetSpriteRect(m_HUD_dmg_bio).top; - - return 1; -} - -int CHudHealth:: MsgFunc_Health(const char *pszName, int iSize, void *pbuf ) -{ - // TODO: update local health data - BEGIN_READ( pbuf, iSize ); - int x = READ_BYTE(); - - m_iFlags |= HUD_ACTIVE; - - // Only update the fade if we've changed health - if (x != m_iHealth) - { - m_fFade = FADE_TIME; - m_iHealth = x; - } - - return 1; -} - - -int CHudHealth:: MsgFunc_Damage(const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int armor = READ_BYTE(); // armor - int damageTaken = READ_BYTE(); // health - long bitsDamage = READ_LONG(); // damage bits - - vec3_t vecFrom; - - for ( int i = 0 ; i < 3 ; i++) - vecFrom[i] = READ_COORD(); - - UpdateTiles(gHUD.m_flTime, bitsDamage); - - // Actually took damage? - if ( damageTaken > 0 || armor > 0 ) - { - CalcDamageDirection(vecFrom); - float time = damageTaken * 4.0f + armor * 2.0f; - - if( time > 200.0f ) time = 200.0f; - gMobileAPI.pfnVibrate( time, 0 ); - } - return 1; -} - -int CHudHealth:: MsgFunc_ScoreAttrib(const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int index = READ_BYTE(); - unsigned char flags = READ_BYTE(); - g_PlayerExtraInfo[index].dead = !!(flags & PLAYER_DEAD); - g_PlayerExtraInfo[index].has_c4 = !!(flags & PLAYER_HAS_C4); - g_PlayerExtraInfo[index].vip = !!(flags & PLAYER_VIP); - return 1; -} -// Returns back a color from the -// Green <-> Yellow <-> Red ramp -void CHudHealth::GetPainColor( int &r, int &g, int &b ) -{ - int iHealth = m_iHealth; - - if (iHealth > 25) - iHealth -= 25; - else if ( iHealth < 0 ) - iHealth = 0; -#if 0 - g = iHealth * 255 / 100; - r = 255 - g; - b = 0; -#else - if (m_iHealth > 25) - { - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - } - else - { - r = 250; - g = 0; - b = 0; - } -#endif -} - -int CHudHealth::Draw(float flTime) -{ - int r, g, b; - int a = 0, x, y; - int HealthWidth; - - if ( (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || gEngfuncs.IsSpectateOnly() ) - return 1; - - if ( !m_hSprite ) - m_hSprite = LoadSprite(PAIN_NAME); - - // Has health changed? Flash the health # - if (m_fFade) - { - m_fFade -= (gHUD.m_flTimeDelta * 20); - if (m_fFade <= 0) - { - a = MIN_ALPHA; - m_fFade = 0; - } - - // Fade the health number back to dim - - a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128; - - } - else - a = MIN_ALPHA; - - // If health is getting low, make it bright red - if (m_iHealth <= 15) - a = 255; - - GetPainColor( r, g, b ); - DrawUtils::ScaleColors(r, g, b, a ); - - // Only draw health if we have the suit. - if (gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT))) - { - HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; - int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left; - - y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; - x = CrossWidth /2; - - SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b); - SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross)); - - x = CrossWidth + HealthWidth / 2; - - x = DrawUtils::DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b); - - x += HealthWidth/2; - - int iHeight = gHUD.m_iFontHeight; - int iWidth = HealthWidth/10; - FillRGBA(x, y, iWidth, iHeight, 255, 160, 0, a); - } - - DrawDamage(flTime); - return DrawPain(flTime); -} - -void CHudHealth::CalcDamageDirection(vec3_t vecFrom) -{ - vec3_t forward, right, up; - float side, front; - vec3_t vecOrigin, vecAngles; - - if (!vecFrom[0] && !vecFrom[1] && !vecFrom[2]) - { - m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0; - return; - } - - - memcpy(vecOrigin, gHUD.m_vecOrigin, sizeof(vec3_t)); - memcpy(vecAngles, gHUD.m_vecAngles, sizeof(vec3_t)); - - - VectorSubtract (vecFrom, vecOrigin, vecFrom); - - float flDistToTarget = vecFrom.Length(); - - vecFrom = vecFrom.Normalize(); - AngleVectors (vecAngles, forward, right, up); - - front = DotProduct (vecFrom, right); - side = DotProduct (vecFrom, forward); - - if (flDistToTarget <= 50) - { - m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 1; - } - else - { - if (side > 0) - { - if (side > 0.3) - m_fAttackFront = max(m_fAttackFront, side); - } - else - { - float f = fabs(side); - if (f > 0.3) - m_fAttackRear = max(m_fAttackRear, f); - } - - if (front > 0) - { - if (front > 0.3) - m_fAttackRight = max(m_fAttackRight, front); - } - else - { - float f = fabs(front); - if (f > 0.3) - m_fAttackLeft = max(m_fAttackLeft, f); - } - } -} - -int CHudHealth::DrawPain(float flTime) -{ - if (!(m_fAttackFront || m_fAttackRear || m_fAttackLeft || m_fAttackRight)) - return 1; - - int r, g, b; - int x, y, a, shade; - - // TODO: get the shift value of the health - a = 255; // max brightness until then - - float fFade = gHUD.m_flTimeDelta * 2; - - // SPR_Draw top - if (m_fAttackFront > 0.4) - { - GetPainColor(r,g,b); - shade = a * max( m_fAttackFront, 0.5 ); - DrawUtils::ScaleColors(r, g, b, shade); - SPR_Set(m_hSprite, r, g, b ); - - x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2; - y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3; - SPR_DrawAdditive(0, x, y, NULL); - m_fAttackFront = max( 0, m_fAttackFront - fFade ); - } else - m_fAttackFront = 0; - - if (m_fAttackRight > 0.4) - { - GetPainColor(r,g,b); - shade = a * max( m_fAttackRight, 0.5 ); - DrawUtils::ScaleColors(r, g, b, shade); - SPR_Set(m_hSprite, r, g, b ); - - x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2; - y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2; - SPR_DrawAdditive(1, x, y, NULL); - m_fAttackRight = max( 0, m_fAttackRight - fFade ); - } else - m_fAttackRight = 0; - - if (m_fAttackRear > 0.4) - { - GetPainColor(r,g,b); - shade = a * max( m_fAttackRear, 0.5 ); - DrawUtils::ScaleColors(r, g, b, shade); - SPR_Set(m_hSprite, r, g, b ); - - x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2; - y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2; - SPR_DrawAdditive(2, x, y, NULL); - m_fAttackRear = max( 0, m_fAttackRear - fFade ); - } else - m_fAttackRear = 0; - - if (m_fAttackLeft > 0.4) - { - GetPainColor(r,g,b); - shade = a * max( m_fAttackLeft, 0.5 ); - DrawUtils::ScaleColors(r, g, b, shade); - SPR_Set(m_hSprite, r, g, b ); - - x = ScreenWidth/2 - SPR_Width(m_hSprite, 3) * 3; - y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2; - SPR_DrawAdditive(3, x, y, NULL); - - m_fAttackLeft = max( 0, m_fAttackLeft - fFade ); - } else - m_fAttackLeft = 0; - - return 1; -} - -int CHudHealth::DrawDamage(float flTime) -{ - int r, g, b, a; - DAMAGE_IMAGE *pdmg; - - if (!m_bitsDamage) - return 1; - - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - - a = (int)( fabs(sin(flTime*2)) * 256.0); - - DrawUtils::ScaleColors(r, g, b, a); - int i; - // Draw all the items - for (i = 0; i < NUM_DMG_TYPES; i++) - { - if (m_bitsDamage & giDmgFlags[i]) - { - pdmg = &m_dmg[i]; - SPR_Set(gHUD.GetSprite(m_HUD_dmg_bio + i), r, g, b ); - SPR_DrawAdditive(0, pdmg->x, pdmg->y, &gHUD.GetSpriteRect(m_HUD_dmg_bio + i)); - } - } - - - // check for bits that should be expired - for ( i = 0; i < NUM_DMG_TYPES; i++ ) - { - DAMAGE_IMAGE *pdmg = &m_dmg[i]; - - if ( m_bitsDamage & giDmgFlags[i] ) - { - pdmg->fExpire = min( flTime + DMG_IMAGE_LIFE, pdmg->fExpire ); - - if ( pdmg->fExpire <= flTime // when the time has expired - && a < 40 ) // and the flash is at the low point of the cycle - { - pdmg->fExpire = 0; - - int y = pdmg->y; - pdmg->x = pdmg->y = 0; - - // move everyone above down - for (int j = 0; j < NUM_DMG_TYPES; j++) - { - pdmg = &m_dmg[j]; - if ((pdmg->y) && (pdmg->y < y)) - pdmg->y += giDmgHeight; - - } - - m_bitsDamage &= ~giDmgFlags[i]; // clear the bits - } - } - } - - return 1; -} - - -void CHudHealth::UpdateTiles(float flTime, long bitsDamage) -{ - DAMAGE_IMAGE *pdmg; - - // Which types are new? - long bitsOn = ~m_bitsDamage & bitsDamage; - - for (int i = 0; i < NUM_DMG_TYPES; i++) - { - pdmg = &m_dmg[i]; - - // Is this one already on? - if (m_bitsDamage & giDmgFlags[i]) - { - pdmg->fExpire = flTime + DMG_IMAGE_LIFE; // extend the duration - if (!pdmg->fBaseline) - pdmg->fBaseline = flTime; - } - - // Are we just turning it on? - if (bitsOn & giDmgFlags[i]) - { - // put this one at the bottom - pdmg->x = giDmgWidth/8; - pdmg->y = ScreenHeight - giDmgHeight * 2; - pdmg->fExpire=flTime + DMG_IMAGE_LIFE; - - // move everyone else up - for (int j = 0; j < NUM_DMG_TYPES; j++) - { - if (j == i) - continue; - - pdmg = &m_dmg[j]; - if (pdmg->y) - pdmg->y -= giDmgHeight; - - } - pdmg = &m_dmg[i]; - } - } - - // damage bits are only turned on here; they are turned off when the draw time has expired (in DrawDamage()) - m_bitsDamage |= bitsDamage; -} - - -int CHudHealth :: MsgFunc_ClCorpse(const char *pszName, int iSize, void *pbuf) -{ -#if 0 - BEGIN_READ(pbuf, iSize); - - char szModel[64]; - - char *pModel = READ_STRING(); - Vector origin; - origin.x = READ_LONG() / 128.0f; - origin.y = READ_LONG() / 128.0f; - origin.z = READ_LONG() / 128.0f; - Vector angles; - angles.x = READ_COORD(); - angles.y = READ_COORD(); - angles.z = READ_COORD(); - float delay = READ_LONG() / 100.0f; - int sequence = READ_BYTE(); - int classID = READ_BYTE(); - int teamID = READ_BYTE(); - int playerID = READ_BYTE(); - - if( !cl_minmodels->value ) - { - if( !strstr(pModel, "models/") ) - { - snprintf(szModel, sizeof(szModel), "models/player/%s/%s.mdl", pModel, pModel ); - } - } - else if( teamID == 1 ) // terrorists - { - int modelidx = cl_min_t->value; - if( BIsValidTModelIndex(modelidx) ) - strncpy(szModel, sPlayerModelFiles[modelidx], sizeof(szModel)); - else strncpy(szModel, sPlayerModelFiles[1], sizeof(szModel) ); // set leet.mdl - } - else if( teamID == 2 ) // ct - { - int modelidx = cl_min_ct->value; - - if( g_PlayerExtraInfo[playerID].vip ) - strncpy( szModel, sPlayerModelFiles[3], sizeof(szModel) ); // vip.mdl - else if( BIsValidCTModelIndex( modelidx ) ) - strncpy( szModel, sPlayerModelFiles[ modelidx ], sizeof(szModel)); - else strncpy( szModel, sPlayerModelFiles[2], sizeof(szModel) ); // gign.mdl - } - else strncpy( szModel, sPlayerModelFiles[0], sizeof(szModel) ); // player.mdl - - CreateCorpse( &origin, &angles, szModel, delay, sequence, classID ); -#endif - return 0; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// Health.cpp +// +// implementation of CHudHealth class +// + +#include "stdio.h" +#include "stdlib.h" +#include "math.h" + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" +#include +#include "eventscripts.h" + +DECLARE_MESSAGE(m_Health, Health ) +DECLARE_MESSAGE(m_Health, Damage ) +DECLARE_MESSAGE(m_Health, ScoreAttrib ) +DECLARE_MESSAGE(m_Health, ClCorpse ) + +#define PAIN_NAME "sprites/%d_pain.spr" +#define DAMAGE_NAME "sprites/%d_dmg.spr" + +cvar_t *cl_radartype; + +int giDmgHeight, giDmgWidth; + +float g_LocationColor[3]; + +int giDmgFlags[NUM_DMG_TYPES] = +{ + DMG_POISON, + DMG_ACID, + DMG_FREEZE|DMG_SLOWFREEZE, + DMG_DROWN, + DMG_BURN|DMG_SLOWBURN, + DMG_NERVEGAS, + DMG_RADIATION, + DMG_SHOCK, + DMG_CALTROP, + DMG_TRANQ, + DMG_CONCUSS, + DMG_HALLUC +}; + +int CHudHealth::Init(void) +{ + HOOK_MESSAGE(Health); + HOOK_MESSAGE(Damage); + HOOK_MESSAGE(ScoreAttrib); + HOOK_MESSAGE(ClCorpse); + + m_iHealth = 100; + m_fFade = 0; + m_iFlags = 0; + m_bitsDamage = 0; + m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0; + giDmgHeight = 0; + giDmgWidth = 0; + + memset(m_dmg, 0, sizeof(DAMAGE_IMAGE) * NUM_DMG_TYPES); + + CVAR_CREATE("cl_corpsestay", "600", FCVAR_ARCHIVE); + gHUD.AddHudElem(this); + return 1; +} + +void CHudHealth::Reset( void ) +{ + // make sure the pain compass is cleared when the player respawns + m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0; + + + // force all the flashing damage icons to expire + m_bitsDamage = 0; + for ( int i = 0; i < NUM_DMG_TYPES; i++ ) + { + m_dmg[i].fExpire = 0; + } +} + +int CHudHealth::VidInit(void) +{ + m_hSprite = 0; + + m_HUD_dmg_bio = gHUD.GetSpriteIndex( "dmg_bio" ) + 1; + m_HUD_cross = gHUD.GetSpriteIndex( "cross" ); + + giDmgHeight = gHUD.GetSpriteRect(m_HUD_dmg_bio).right - gHUD.GetSpriteRect(m_HUD_dmg_bio).left; + giDmgWidth = gHUD.GetSpriteRect(m_HUD_dmg_bio).bottom - gHUD.GetSpriteRect(m_HUD_dmg_bio).top; + + return 1; +} + +int CHudHealth:: MsgFunc_Health(const char *pszName, int iSize, void *pbuf ) +{ + // TODO: update local health data + BEGIN_READ( pbuf, iSize ); + int x = READ_BYTE(); + + m_iFlags |= HUD_ACTIVE; + + // Only update the fade if we've changed health + if (x != m_iHealth) + { + m_fFade = FADE_TIME; + m_iHealth = x; + } + + return 1; +} + + +int CHudHealth:: MsgFunc_Damage(const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int armor = READ_BYTE(); // armor + int damageTaken = READ_BYTE(); // health + long bitsDamage = READ_LONG(); // damage bits + + vec3_t vecFrom; + + for ( int i = 0 ; i < 3 ; i++) + vecFrom[i] = READ_COORD(); + + UpdateTiles(gHUD.m_flTime, bitsDamage); + + // Actually took damage? + if ( damageTaken > 0 || armor > 0 ) + { + CalcDamageDirection(vecFrom); + float time = damageTaken * 4.0f + armor * 2.0f; + + if( time > 200.0f ) time = 200.0f; + gMobileAPI.pfnVibrate( time, 0 ); + } + return 1; +} + +int CHudHealth:: MsgFunc_ScoreAttrib(const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int index = READ_BYTE(); + unsigned char flags = READ_BYTE(); + g_PlayerExtraInfo[index].dead = !!(flags & PLAYER_DEAD); + g_PlayerExtraInfo[index].has_c4 = !!(flags & PLAYER_HAS_C4); + g_PlayerExtraInfo[index].vip = !!(flags & PLAYER_VIP); + return 1; +} +// Returns back a color from the +// Green <-> Yellow <-> Red ramp +void CHudHealth::GetPainColor( int &r, int &g, int &b ) +{ + int iHealth = m_iHealth; + + if (iHealth > 25) + iHealth -= 25; + else if ( iHealth < 0 ) + iHealth = 0; +#if 0 + g = iHealth * 255 / 100; + r = 255 - g; + b = 0; +#else + if (m_iHealth > 25) + { + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + } + else + { + r = 250; + g = 0; + b = 0; + } +#endif +} + +int CHudHealth::Draw(float flTime) +{ + int r, g, b; + int a = 0, x, y; + int HealthWidth; + + if ( (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || gEngfuncs.IsSpectateOnly() ) + return 1; + + if ( !m_hSprite ) + m_hSprite = LoadSprite(PAIN_NAME); + + // Has health changed? Flash the health # + if (m_fFade) + { + m_fFade -= (gHUD.m_flTimeDelta * 20); + if (m_fFade <= 0) + { + a = MIN_ALPHA; + m_fFade = 0; + } + + // Fade the health number back to dim + + a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128; + + } + else + a = MIN_ALPHA; + + // If health is getting low, make it bright red + if (m_iHealth <= 15) + a = 255; + + GetPainColor( r, g, b ); + DrawUtils::ScaleColors(r, g, b, a ); + + // Only draw health if we have the suit. + if (gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT))) + { + HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; + int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left; + + y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; + x = CrossWidth /2; + + SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b); + SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross)); + + x = CrossWidth + HealthWidth / 2; + + x = DrawUtils::DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b); + + x += HealthWidth/2; + + int iHeight = gHUD.m_iFontHeight; + int iWidth = HealthWidth/10; + FillRGBA(x, y, iWidth, iHeight, 255, 160, 0, a); + } + + DrawDamage(flTime); + return DrawPain(flTime); +} + +void CHudHealth::CalcDamageDirection(vec3_t vecFrom) +{ + vec3_t forward, right, up; + float side, front; + vec3_t vecOrigin, vecAngles; + + if (!vecFrom[0] && !vecFrom[1] && !vecFrom[2]) + { + m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 0; + return; + } + + + memcpy(vecOrigin, gHUD.m_vecOrigin, sizeof(vec3_t)); + memcpy(vecAngles, gHUD.m_vecAngles, sizeof(vec3_t)); + + + VectorSubtract (vecFrom, vecOrigin, vecFrom); + + float flDistToTarget = vecFrom.Length(); + + vecFrom = vecFrom.Normalize(); + AngleVectors (vecAngles, forward, right, up); + + front = DotProduct (vecFrom, right); + side = DotProduct (vecFrom, forward); + + if (flDistToTarget <= 50) + { + m_fAttackFront = m_fAttackRear = m_fAttackRight = m_fAttackLeft = 1; + } + else + { + if (side > 0) + { + if (side > 0.3) + m_fAttackFront = max(m_fAttackFront, side); + } + else + { + float f = fabs(side); + if (f > 0.3) + m_fAttackRear = max(m_fAttackRear, f); + } + + if (front > 0) + { + if (front > 0.3) + m_fAttackRight = max(m_fAttackRight, front); + } + else + { + float f = fabs(front); + if (f > 0.3) + m_fAttackLeft = max(m_fAttackLeft, f); + } + } +} + +int CHudHealth::DrawPain(float flTime) +{ + if (!(m_fAttackFront || m_fAttackRear || m_fAttackLeft || m_fAttackRight)) + return 1; + + int r, g, b; + int x, y, a, shade; + + // TODO: get the shift value of the health + a = 255; // max brightness until then + + float fFade = gHUD.m_flTimeDelta * 2; + + // SPR_Draw top + if (m_fAttackFront > 0.4) + { + GetPainColor(r,g,b); + shade = a * max( m_fAttackFront, 0.5 ); + DrawUtils::ScaleColors(r, g, b, shade); + SPR_Set(m_hSprite, r, g, b ); + + x = ScreenWidth/2 - SPR_Width(m_hSprite, 0)/2; + y = ScreenHeight/2 - SPR_Height(m_hSprite,0) * 3; + SPR_DrawAdditive(0, x, y, NULL); + m_fAttackFront = max( 0, m_fAttackFront - fFade ); + } else + m_fAttackFront = 0; + + if (m_fAttackRight > 0.4) + { + GetPainColor(r,g,b); + shade = a * max( m_fAttackRight, 0.5 ); + DrawUtils::ScaleColors(r, g, b, shade); + SPR_Set(m_hSprite, r, g, b ); + + x = ScreenWidth/2 + SPR_Width(m_hSprite, 1) * 2; + y = ScreenHeight/2 - SPR_Height(m_hSprite,1)/2; + SPR_DrawAdditive(1, x, y, NULL); + m_fAttackRight = max( 0, m_fAttackRight - fFade ); + } else + m_fAttackRight = 0; + + if (m_fAttackRear > 0.4) + { + GetPainColor(r,g,b); + shade = a * max( m_fAttackRear, 0.5 ); + DrawUtils::ScaleColors(r, g, b, shade); + SPR_Set(m_hSprite, r, g, b ); + + x = ScreenWidth/2 - SPR_Width(m_hSprite, 2)/2; + y = ScreenHeight/2 + SPR_Height(m_hSprite,2) * 2; + SPR_DrawAdditive(2, x, y, NULL); + m_fAttackRear = max( 0, m_fAttackRear - fFade ); + } else + m_fAttackRear = 0; + + if (m_fAttackLeft > 0.4) + { + GetPainColor(r,g,b); + shade = a * max( m_fAttackLeft, 0.5 ); + DrawUtils::ScaleColors(r, g, b, shade); + SPR_Set(m_hSprite, r, g, b ); + + x = ScreenWidth/2 - SPR_Width(m_hSprite, 3) * 3; + y = ScreenHeight/2 - SPR_Height(m_hSprite,3)/2; + SPR_DrawAdditive(3, x, y, NULL); + + m_fAttackLeft = max( 0, m_fAttackLeft - fFade ); + } else + m_fAttackLeft = 0; + + return 1; +} + +int CHudHealth::DrawDamage(float flTime) +{ + int r, g, b, a; + DAMAGE_IMAGE *pdmg; + + if (!m_bitsDamage) + return 1; + + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + + a = (int)( fabs(sin(flTime*2)) * 256.0); + + DrawUtils::ScaleColors(r, g, b, a); + int i; + // Draw all the items + for (i = 0; i < NUM_DMG_TYPES; i++) + { + if (m_bitsDamage & giDmgFlags[i]) + { + pdmg = &m_dmg[i]; + SPR_Set(gHUD.GetSprite(m_HUD_dmg_bio + i), r, g, b ); + SPR_DrawAdditive(0, pdmg->x, pdmg->y, &gHUD.GetSpriteRect(m_HUD_dmg_bio + i)); + } + } + + + // check for bits that should be expired + for ( i = 0; i < NUM_DMG_TYPES; i++ ) + { + DAMAGE_IMAGE *pdmg = &m_dmg[i]; + + if ( m_bitsDamage & giDmgFlags[i] ) + { + pdmg->fExpire = min( flTime + DMG_IMAGE_LIFE, pdmg->fExpire ); + + if ( pdmg->fExpire <= flTime // when the time has expired + && a < 40 ) // and the flash is at the low point of the cycle + { + pdmg->fExpire = 0; + + int y = pdmg->y; + pdmg->x = pdmg->y = 0; + + // move everyone above down + for (int j = 0; j < NUM_DMG_TYPES; j++) + { + pdmg = &m_dmg[j]; + if ((pdmg->y) && (pdmg->y < y)) + pdmg->y += giDmgHeight; + + } + + m_bitsDamage &= ~giDmgFlags[i]; // clear the bits + } + } + } + + return 1; +} + + +void CHudHealth::UpdateTiles(float flTime, long bitsDamage) +{ + DAMAGE_IMAGE *pdmg; + + // Which types are new? + long bitsOn = ~m_bitsDamage & bitsDamage; + + for (int i = 0; i < NUM_DMG_TYPES; i++) + { + pdmg = &m_dmg[i]; + + // Is this one already on? + if (m_bitsDamage & giDmgFlags[i]) + { + pdmg->fExpire = flTime + DMG_IMAGE_LIFE; // extend the duration + if (!pdmg->fBaseline) + pdmg->fBaseline = flTime; + } + + // Are we just turning it on? + if (bitsOn & giDmgFlags[i]) + { + // put this one at the bottom + pdmg->x = giDmgWidth/8; + pdmg->y = ScreenHeight - giDmgHeight * 2; + pdmg->fExpire=flTime + DMG_IMAGE_LIFE; + + // move everyone else up + for (int j = 0; j < NUM_DMG_TYPES; j++) + { + if (j == i) + continue; + + pdmg = &m_dmg[j]; + if (pdmg->y) + pdmg->y -= giDmgHeight; + + } + pdmg = &m_dmg[i]; + } + } + + // damage bits are only turned on here; they are turned off when the draw time has expired (in DrawDamage()) + m_bitsDamage |= bitsDamage; +} + + +int CHudHealth :: MsgFunc_ClCorpse(const char *pszName, int iSize, void *pbuf) +{ +#if 0 + BEGIN_READ(pbuf, iSize); + + char szModel[64]; + + char *pModel = READ_STRING(); + Vector origin; + origin.x = READ_LONG() / 128.0f; + origin.y = READ_LONG() / 128.0f; + origin.z = READ_LONG() / 128.0f; + Vector angles; + angles.x = READ_COORD(); + angles.y = READ_COORD(); + angles.z = READ_COORD(); + float delay = READ_LONG() / 100.0f; + int sequence = READ_BYTE(); + int classID = READ_BYTE(); + int teamID = READ_BYTE(); + int playerID = READ_BYTE(); + + if( !cl_minmodels->value ) + { + if( !strstr(pModel, "models/") ) + { + snprintf(szModel, sizeof(szModel), "models/player/%s/%s.mdl", pModel, pModel ); + } + } + else if( teamID == 1 ) // terrorists + { + int modelidx = cl_min_t->value; + if( BIsValidTModelIndex(modelidx) ) + strncpy(szModel, sPlayerModelFiles[modelidx], sizeof(szModel)); + else strncpy(szModel, sPlayerModelFiles[1], sizeof(szModel) ); // set leet.mdl + } + else if( teamID == 2 ) // ct + { + int modelidx = cl_min_ct->value; + + if( g_PlayerExtraInfo[playerID].vip ) + strncpy( szModel, sPlayerModelFiles[3], sizeof(szModel) ); // vip.mdl + else if( BIsValidCTModelIndex( modelidx ) ) + strncpy( szModel, sPlayerModelFiles[ modelidx ], sizeof(szModel)); + else strncpy( szModel, sPlayerModelFiles[2], sizeof(szModel) ); // gign.mdl + } + else strncpy( szModel, sPlayerModelFiles[0], sizeof(szModel) ); // player.mdl + + CreateCorpse( &origin, &angles, szModel, delay, sequence, classID ); +#endif + return 0; +} diff --git a/cl_dll/hud/hud.cpp b/cl_dll/hud/hud.cpp index 52db1a1..34303d8 100644 --- a/cl_dll/hud/hud.cpp +++ b/cl_dll/hud/hud.cpp @@ -1,539 +1,539 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// hud.cpp -// -// implementation of CHud class -// - -#include "hud.h" -#include "cl_util.h" -#include -#include -#include -#include "parsemsg.h" - -#include "demo.h" -#include "demo_api.h" -#include "vgui_parser.h" -#include "rain.h" - - -extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount); - -extern cvar_t *sensitivity; -cvar_t *hud_textmode; -cvar_t *cl_righthand; -cvar_t *cl_weather; -cvar_t *cl_min_t; -cvar_t *cl_min_ct; -cvar_t *cl_minmodels; -cvar_t *cl_lw = NULL; -wrect_t nullrc = { 0, 0, 0, 0 }; -char *sPlayerModelFiles[12] = -{ - "models/player.mdl", - "models/player/leet/leet.mdl", // t - "models/player/gign/gign.mdl", // ct - "models/player/vip/vip.mdl", //ct - "models/player/gsg9/gsg9.mdl", // ct - "models/player/guerilla/guerilla.mdl", // t - "models/player/arctic/arctic.mdl", // t - "models/player/sas/sas.mdl", // ct - "models/player/terror/terror.mdl", // t - "models/player/urban/urban.mdl", // ct - "models/player/spetsnaz/spetsnaz.mdl", // ct - "models/player/militia/militia.mdl" // t -}; - -void ShutdownInput (void); - -#define GHUD_DECLARE_MESSAGE(x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf ) { return gHUD.MsgFunc_##x(pszName, iSize, pbuf); } - -GHUD_DECLARE_MESSAGE(Logo) -GHUD_DECLARE_MESSAGE(SetFOV) -GHUD_DECLARE_MESSAGE(InitHUD) -GHUD_DECLARE_MESSAGE(Concuss) -GHUD_DECLARE_MESSAGE(ResetHUD) -GHUD_DECLARE_MESSAGE(ViewMode) -GHUD_DECLARE_MESSAGE(GameMode) -GHUD_DECLARE_MESSAGE(ReceiveW) -GHUD_DECLARE_MESSAGE(BombDrop) -GHUD_DECLARE_MESSAGE(HostageK) -GHUD_DECLARE_MESSAGE(BombPickup) -GHUD_DECLARE_MESSAGE(HostagePos) -GHUD_DECLARE_MESSAGE(ShadowIdx) - -#ifdef _CS16CLIENT_ALLOW_SPECIAL_SCRIPTING -void __CmdFunc_InputCommandSpecial() -{ - gEngfuncs.pfnClientCmd("_special"); -} -#endif - -// This is called every time the DLL is loaded -void CHud :: Init( void ) -{ -#ifdef _CS16CLIENT_ALLOW_SPECIAL_SCRIPTING - HOOK_COMMAND( "special", InputCommandSpecial ); -#endif - - HOOK_MESSAGE( Logo ); - HOOK_MESSAGE( ResetHUD ); - HOOK_MESSAGE( GameMode ); - HOOK_MESSAGE( InitHUD ); - HOOK_MESSAGE( ViewMode ); - HOOK_MESSAGE( SetFOV ); - HOOK_MESSAGE( Concuss ); - HOOK_MESSAGE( ReceiveW ); - - HOOK_MESSAGE( BombDrop ); - HOOK_MESSAGE( BombPickup ); - HOOK_MESSAGE( HostagePos ); - HOOK_MESSAGE( HostageK ); - HOOK_MESSAGE( ShadowIdx ); - - CVAR_CREATE( "hud_classautokill", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); // controls whether or not to suicide immediately on TF class switch - CVAR_CREATE( "_vgui_menus", "0", FCVAR_ARCHIVE | FCVAR_USERINFO ); // force client to use old style menus - CVAR_CREATE( "cl_lb", "0", FCVAR_ARCHIVE | FCVAR_USERINFO ); // force client to use old style menus - CVAR_CREATE( "lefthand", "0", FCVAR_ARCHIVE | FCVAR_USERINFO ); - CVAR_CREATE( "_cl_autowepswitch", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); - CVAR_CREATE( "_ah", "1", FCVAR_ARCHIVE| FCVAR_USERINFO); - CVAR_CREATE( "hud_takesshots", "0", FCVAR_ARCHIVE ); // controls whether or not to automatically take screenshots at the end of a round - CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 ); - - hud_textmode = CVAR_CREATE( "hud_textmode", "0", FCVAR_ARCHIVE ); - cl_righthand = CVAR_CREATE( "hand", "1", FCVAR_ARCHIVE ); - cl_weather = CVAR_CREATE( "cl_weather", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); - cl_minmodels = CVAR_CREATE( "cl_minmodels", "1", FCVAR_ARCHIVE ); - cl_min_t = CVAR_CREATE( "cl_min_t", "1", FCVAR_ARCHIVE ); - cl_min_ct = CVAR_CREATE( "cl_min_ct", "1", FCVAR_ARCHIVE ); - cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); - cl_shadows = CVAR_CREATE( "cl_shadows", "1", FCVAR_ARCHIVE ); - default_fov = CVAR_CREATE( "default_fov", "90", 0 ); - m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); - m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); - - - - m_iLogo = 0; - m_iFOV = 0; - - - m_pSpriteList = NULL; - - // Clear any old HUD list - if ( m_pHudList ) - { - HUDLIST *pList; - while ( m_pHudList ) - { - pList = m_pHudList; - m_pHudList = m_pHudList->pNext; - free( pList ); - } - m_pHudList = NULL; - } - - // In case we get messages before the first update -- time will be valid - m_flTime = 1.0; - m_iNoConsolePrint = 0; - // fullscreen overlays - m_SniperScope.Init(); - m_NVG.Init(); - - // Game HUD things - m_Ammo.Init(); - m_Health.Init(); - m_Radio.Init(); - m_Timer.Init(); - m_Money.Init(); - m_AmmoSecondary.Init(); - m_Train.Init(); - m_Battery.Init(); - m_StatusIcons.Init(); - m_Radar.Init(); - - // chat, death notice, status bars and other - m_SayText.Init(); - m_Spectator.Init(); - m_Geiger.Init(); - m_Flash.Init(); - m_Message.Init(); - m_StatusBar.Init(); - m_DeathNotice.Init(); - m_TextMessage.Init(); - m_MOTD.Init(); - - // all things that have own background and must be drawn last - m_ProgressBar.Init(); - m_Menu.Init(); - m_Scoreboard.Init(); - - Localize_Init(); - InitRain(); - - //ServersInit(); - - MsgFunc_ResetHUD(0, 0, NULL ); -} - -// CHud destructor -// cleans up memory allocated for m_rg* arrays -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() -// searches through the sprite list loaded from hud.txt for a name matching SpriteName -// returns an index into the gHUD.m_rghSprites[] array -// returns -1 if sprite not found -int CHud :: GetSpriteIndex( const char *SpriteName ) -{ - // look through the loaded sprite name list for SpriteName - for ( int i = 0; i < m_iSpriteCount; i++ ) - { - if ( strncmp( SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH ) == 0 ) - return i; - } - - return -1; // invalid sprite -} - -HSPRITE CHud :: GetSprite( int index ) -{ - assert( index >= -1 && index <= m_iSpriteCount ); - - return (index >= 0) ? m_rghSprites[index] : 0; -} - -wrect_t& CHud :: GetSpriteRect( int index ) -{ - assert( index >= -1 && index <= m_iSpriteCount ); - - return (index >= 0) ? m_rgrcRects[index] : nullrc; -} - -void CHud :: VidInit( void ) -{ - m_scrinfo.iSize = sizeof(m_scrinfo); - GetScreenInfo(&m_scrinfo); - - m_truescrinfo.iWidth = CVAR_GET_FLOAT("width"); - m_truescrinfo.iHeight = CVAR_GET_FLOAT("height"); - - // ---------- - // Load Sprites - // --------- - // m_hsprFont = LoadSprite("sprites/%d_font.spr"); - - m_hsprLogo = 0; - m_hsprCursor = 0; - - if (ScreenWidth < 640) - m_iRes = 320; - else - m_iRes = 640; - - // Only load this once - if ( !m_pSpriteList ) - { - // we need to load the hud.txt, and all sprites within - m_pSpriteList = SPR_GetList("sprites/hud.txt", &m_iSpriteCountAllRes); - - if (m_pSpriteList) - { - // count the number of sprites of the appropriate res - m_iSpriteCount = 0; - client_sprite_t *p = m_pSpriteList; - int j; - for ( j = 0; j < m_iSpriteCountAllRes; j++ ) - { - if ( p->iRes == m_iRes ) - m_iSpriteCount++; - p++; - } - - // allocated memory for sprite handle arrays - m_rghSprites = new HSPRITE[m_iSpriteCount]; - m_rgrcRects = new wrect_t[m_iSpriteCount]; - m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH]; - - p = m_pSpriteList; - int index = 0; - for ( j = 0; j < m_iSpriteCountAllRes; j++ ) - { - if ( p->iRes == m_iRes ) - { - char sz[256]; - sprintf(sz, "sprites/%s.spr", p->szSprite); - m_rghSprites[index] = SPR_Load(sz); - m_rgrcRects[index] = p->rc; - strncpy( &m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH ); - - index++; - } - - p++; - } - } - } - else - { - // we have already have loaded the sprite reference from hud.txt, but - // we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game) - client_sprite_t *p = m_pSpriteList; - int index = 0; - for ( int j = 0; j < m_iSpriteCountAllRes; j++ ) - { - if ( p->iRes == m_iRes ) - { - char sz[256]; - sprintf( sz, "sprites/%s.spr", p->szSprite ); - m_rghSprites[index] = SPR_Load(sz); - index++; - } - - p++; - } - } - - // assumption: number_1, number_2, etc, are all listed and loaded sequentially - m_HUD_number_0 = GetSpriteIndex( "number_0" ); - - m_flScale = gEngfuncs.pfnGetCvarFloat("hud_scale"); - if(m_flScale < 0.01) - m_flScale = 1; - - m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top; - - m_Ammo.VidInit(); - m_Health.VidInit(); - m_Spectator.VidInit(); - m_Geiger.VidInit(); - m_Train.VidInit(); - m_Battery.VidInit(); - m_Flash.VidInit(); - m_Message.VidInit(); - m_StatusBar.VidInit(); - m_DeathNotice.VidInit(); - m_SayText.VidInit(); - m_Menu.VidInit(); - m_AmmoSecondary.VidInit(); - m_TextMessage.VidInit(); - m_StatusIcons.VidInit(); - m_Scoreboard.VidInit(); - m_MOTD.VidInit(); - m_Timer.VidInit(); - m_Money.VidInit(); - m_ProgressBar.VidInit(); - m_SniperScope.VidInit(); - m_Radar.VidInit(); -} - -int CHud::MsgFunc_Logo(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - // update Train data - m_iLogo = READ_BYTE(); - - 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 ); - - int newfov = READ_BYTE(); - int def_fov = CVAR_GET_FLOAT( "default_fov" ); - - //Weapon prediction already takes care of changing the fog. ( g_lastFOV ). - if ( cl_lw && cl_lw->value ) - return 1; - - g_lastFOV = newfov; - - if ( newfov == 0 ) - { - m_iFOV = def_fov; - } - 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 == def_fov ) - { - // 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)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); - } - - return 1; -} - -void CHud::AddHudElem(CHudBase *phudelem) -{ - HUDLIST *pdl, *ptemp; - - //phudelem->Think(); - - if (!phudelem) - return; - - pdl = (HUDLIST *)malloc(sizeof(HUDLIST)); - if (!pdl) - return; - - memset(pdl, 0, sizeof(HUDLIST)); - pdl->p = phudelem; - - if (!m_pHudList) - { - m_pHudList = pdl; - return; - } - - ptemp = m_pHudList; - - while (ptemp->pNext) - ptemp = ptemp->pNext; - - ptemp->pNext = pdl; -} - -float CHud::GetSensitivity( void ) -{ - return m_flMouseSensitivity; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// hud.cpp +// +// implementation of CHud class +// + +#include "hud.h" +#include "cl_util.h" +#include +#include +#include +#include "parsemsg.h" + +#include "demo.h" +#include "demo_api.h" +#include "vgui_parser.h" +#include "rain.h" + + +extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount); + +extern cvar_t *sensitivity; +cvar_t *hud_textmode; +cvar_t *cl_righthand; +cvar_t *cl_weather; +cvar_t *cl_min_t; +cvar_t *cl_min_ct; +cvar_t *cl_minmodels; +cvar_t *cl_lw = NULL; +wrect_t nullrc = { 0, 0, 0, 0 }; +char *sPlayerModelFiles[12] = +{ + "models/player.mdl", + "models/player/leet/leet.mdl", // t + "models/player/gign/gign.mdl", // ct + "models/player/vip/vip.mdl", //ct + "models/player/gsg9/gsg9.mdl", // ct + "models/player/guerilla/guerilla.mdl", // t + "models/player/arctic/arctic.mdl", // t + "models/player/sas/sas.mdl", // ct + "models/player/terror/terror.mdl", // t + "models/player/urban/urban.mdl", // ct + "models/player/spetsnaz/spetsnaz.mdl", // ct + "models/player/militia/militia.mdl" // t +}; + +void ShutdownInput (void); + +#define GHUD_DECLARE_MESSAGE(x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf ) { return gHUD.MsgFunc_##x(pszName, iSize, pbuf); } + +GHUD_DECLARE_MESSAGE(Logo) +GHUD_DECLARE_MESSAGE(SetFOV) +GHUD_DECLARE_MESSAGE(InitHUD) +GHUD_DECLARE_MESSAGE(Concuss) +GHUD_DECLARE_MESSAGE(ResetHUD) +GHUD_DECLARE_MESSAGE(ViewMode) +GHUD_DECLARE_MESSAGE(GameMode) +GHUD_DECLARE_MESSAGE(ReceiveW) +GHUD_DECLARE_MESSAGE(BombDrop) +GHUD_DECLARE_MESSAGE(HostageK) +GHUD_DECLARE_MESSAGE(BombPickup) +GHUD_DECLARE_MESSAGE(HostagePos) +GHUD_DECLARE_MESSAGE(ShadowIdx) + +#ifdef _CS16CLIENT_ALLOW_SPECIAL_SCRIPTING +void __CmdFunc_InputCommandSpecial() +{ + gEngfuncs.pfnClientCmd("_special"); +} +#endif + +// This is called every time the DLL is loaded +void CHud :: Init( void ) +{ +#ifdef _CS16CLIENT_ALLOW_SPECIAL_SCRIPTING + HOOK_COMMAND( "special", InputCommandSpecial ); +#endif + + HOOK_MESSAGE( Logo ); + HOOK_MESSAGE( ResetHUD ); + HOOK_MESSAGE( GameMode ); + HOOK_MESSAGE( InitHUD ); + HOOK_MESSAGE( ViewMode ); + HOOK_MESSAGE( SetFOV ); + HOOK_MESSAGE( Concuss ); + HOOK_MESSAGE( ReceiveW ); + + HOOK_MESSAGE( BombDrop ); + HOOK_MESSAGE( BombPickup ); + HOOK_MESSAGE( HostagePos ); + HOOK_MESSAGE( HostageK ); + HOOK_MESSAGE( ShadowIdx ); + + CVAR_CREATE( "hud_classautokill", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); // controls whether or not to suicide immediately on TF class switch + CVAR_CREATE( "_vgui_menus", "0", FCVAR_ARCHIVE | FCVAR_USERINFO ); // force client to use old style menus + CVAR_CREATE( "cl_lb", "0", FCVAR_ARCHIVE | FCVAR_USERINFO ); // force client to use old style menus + CVAR_CREATE( "lefthand", "0", FCVAR_ARCHIVE | FCVAR_USERINFO ); + CVAR_CREATE( "_cl_autowepswitch", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); + CVAR_CREATE( "_ah", "1", FCVAR_ARCHIVE| FCVAR_USERINFO); + CVAR_CREATE( "hud_takesshots", "0", FCVAR_ARCHIVE ); // controls whether or not to automatically take screenshots at the end of a round + CVAR_CREATE( "zoom_sensitivity_ratio", "1.2", 0 ); + + hud_textmode = CVAR_CREATE( "hud_textmode", "0", FCVAR_ARCHIVE ); + cl_righthand = CVAR_CREATE( "hand", "1", FCVAR_ARCHIVE ); + cl_weather = CVAR_CREATE( "cl_weather", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); + cl_minmodels = CVAR_CREATE( "cl_minmodels", "1", FCVAR_ARCHIVE ); + cl_min_t = CVAR_CREATE( "cl_min_t", "1", FCVAR_ARCHIVE ); + cl_min_ct = CVAR_CREATE( "cl_min_ct", "1", FCVAR_ARCHIVE ); + cl_lw = gEngfuncs.pfnGetCvarPointer( "cl_lw" ); + cl_shadows = CVAR_CREATE( "cl_shadows", "1", FCVAR_ARCHIVE ); + default_fov = CVAR_CREATE( "default_fov", "90", 0 ); + m_pCvarStealMouse = CVAR_CREATE( "hud_capturemouse", "1", FCVAR_ARCHIVE ); + m_pCvarDraw = CVAR_CREATE( "hud_draw", "1", FCVAR_ARCHIVE ); + + + + m_iLogo = 0; + m_iFOV = 0; + + + m_pSpriteList = NULL; + + // Clear any old HUD list + if ( m_pHudList ) + { + HUDLIST *pList; + while ( m_pHudList ) + { + pList = m_pHudList; + m_pHudList = m_pHudList->pNext; + free( pList ); + } + m_pHudList = NULL; + } + + // In case we get messages before the first update -- time will be valid + m_flTime = 1.0; + m_iNoConsolePrint = 0; + // fullscreen overlays + m_SniperScope.Init(); + m_NVG.Init(); + + // Game HUD things + m_Ammo.Init(); + m_Health.Init(); + m_Radio.Init(); + m_Timer.Init(); + m_Money.Init(); + m_AmmoSecondary.Init(); + m_Train.Init(); + m_Battery.Init(); + m_StatusIcons.Init(); + m_Radar.Init(); + + // chat, death notice, status bars and other + m_SayText.Init(); + m_Spectator.Init(); + m_Geiger.Init(); + m_Flash.Init(); + m_Message.Init(); + m_StatusBar.Init(); + m_DeathNotice.Init(); + m_TextMessage.Init(); + m_MOTD.Init(); + + // all things that have own background and must be drawn last + m_ProgressBar.Init(); + m_Menu.Init(); + m_Scoreboard.Init(); + + Localize_Init(); + InitRain(); + + //ServersInit(); + + MsgFunc_ResetHUD(0, 0, NULL ); +} + +// CHud destructor +// cleans up memory allocated for m_rg* arrays +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() +// searches through the sprite list loaded from hud.txt for a name matching SpriteName +// returns an index into the gHUD.m_rghSprites[] array +// returns -1 if sprite not found +int CHud :: GetSpriteIndex( const char *SpriteName ) +{ + // look through the loaded sprite name list for SpriteName + for ( int i = 0; i < m_iSpriteCount; i++ ) + { + if ( strncmp( SpriteName, m_rgszSpriteNames + (i * MAX_SPRITE_NAME_LENGTH), MAX_SPRITE_NAME_LENGTH ) == 0 ) + return i; + } + + return -1; // invalid sprite +} + +HSPRITE CHud :: GetSprite( int index ) +{ + assert( index >= -1 && index <= m_iSpriteCount ); + + return (index >= 0) ? m_rghSprites[index] : 0; +} + +wrect_t& CHud :: GetSpriteRect( int index ) +{ + assert( index >= -1 && index <= m_iSpriteCount ); + + return (index >= 0) ? m_rgrcRects[index] : nullrc; +} + +void CHud :: VidInit( void ) +{ + m_scrinfo.iSize = sizeof(m_scrinfo); + GetScreenInfo(&m_scrinfo); + + m_truescrinfo.iWidth = CVAR_GET_FLOAT("width"); + m_truescrinfo.iHeight = CVAR_GET_FLOAT("height"); + + // ---------- + // Load Sprites + // --------- + // m_hsprFont = LoadSprite("sprites/%d_font.spr"); + + m_hsprLogo = 0; + m_hsprCursor = 0; + + if (ScreenWidth < 640) + m_iRes = 320; + else + m_iRes = 640; + + // Only load this once + if ( !m_pSpriteList ) + { + // we need to load the hud.txt, and all sprites within + m_pSpriteList = SPR_GetList("sprites/hud.txt", &m_iSpriteCountAllRes); + + if (m_pSpriteList) + { + // count the number of sprites of the appropriate res + m_iSpriteCount = 0; + client_sprite_t *p = m_pSpriteList; + int j; + for ( j = 0; j < m_iSpriteCountAllRes; j++ ) + { + if ( p->iRes == m_iRes ) + m_iSpriteCount++; + p++; + } + + // allocated memory for sprite handle arrays + m_rghSprites = new HSPRITE[m_iSpriteCount]; + m_rgrcRects = new wrect_t[m_iSpriteCount]; + m_rgszSpriteNames = new char[m_iSpriteCount * MAX_SPRITE_NAME_LENGTH]; + + p = m_pSpriteList; + int index = 0; + for ( j = 0; j < m_iSpriteCountAllRes; j++ ) + { + if ( p->iRes == m_iRes ) + { + char sz[256]; + sprintf(sz, "sprites/%s.spr", p->szSprite); + m_rghSprites[index] = SPR_Load(sz); + m_rgrcRects[index] = p->rc; + strncpy( &m_rgszSpriteNames[index * MAX_SPRITE_NAME_LENGTH], p->szName, MAX_SPRITE_NAME_LENGTH ); + + index++; + } + + p++; + } + } + } + else + { + // we have already have loaded the sprite reference from hud.txt, but + // we need to make sure all the sprites have been loaded (we've gone through a transition, or loaded a save game) + client_sprite_t *p = m_pSpriteList; + int index = 0; + for ( int j = 0; j < m_iSpriteCountAllRes; j++ ) + { + if ( p->iRes == m_iRes ) + { + char sz[256]; + sprintf( sz, "sprites/%s.spr", p->szSprite ); + m_rghSprites[index] = SPR_Load(sz); + index++; + } + + p++; + } + } + + // assumption: number_1, number_2, etc, are all listed and loaded sequentially + m_HUD_number_0 = GetSpriteIndex( "number_0" ); + + m_flScale = gEngfuncs.pfnGetCvarFloat("hud_scale"); + if(m_flScale < 0.01) + m_flScale = 1; + + m_iFontHeight = m_rgrcRects[m_HUD_number_0].bottom - m_rgrcRects[m_HUD_number_0].top; + + m_Ammo.VidInit(); + m_Health.VidInit(); + m_Spectator.VidInit(); + m_Geiger.VidInit(); + m_Train.VidInit(); + m_Battery.VidInit(); + m_Flash.VidInit(); + m_Message.VidInit(); + m_StatusBar.VidInit(); + m_DeathNotice.VidInit(); + m_SayText.VidInit(); + m_Menu.VidInit(); + m_AmmoSecondary.VidInit(); + m_TextMessage.VidInit(); + m_StatusIcons.VidInit(); + m_Scoreboard.VidInit(); + m_MOTD.VidInit(); + m_Timer.VidInit(); + m_Money.VidInit(); + m_ProgressBar.VidInit(); + m_SniperScope.VidInit(); + m_Radar.VidInit(); +} + +int CHud::MsgFunc_Logo(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + // update Train data + m_iLogo = READ_BYTE(); + + 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 ); + + int newfov = READ_BYTE(); + int def_fov = CVAR_GET_FLOAT( "default_fov" ); + + //Weapon prediction already takes care of changing the fog. ( g_lastFOV ). + if ( cl_lw && cl_lw->value ) + return 1; + + g_lastFOV = newfov; + + if ( newfov == 0 ) + { + m_iFOV = def_fov; + } + 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 == def_fov ) + { + // 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)def_fov) * CVAR_GET_FLOAT("zoom_sensitivity_ratio"); + } + + return 1; +} + +void CHud::AddHudElem(CHudBase *phudelem) +{ + HUDLIST *pdl, *ptemp; + + //phudelem->Think(); + + if (!phudelem) + return; + + pdl = (HUDLIST *)malloc(sizeof(HUDLIST)); + if (!pdl) + return; + + memset(pdl, 0, sizeof(HUDLIST)); + pdl->p = phudelem; + + if (!m_pHudList) + { + m_pHudList = pdl; + return; + } + + ptemp = m_pHudList; + + while (ptemp->pNext) + ptemp = ptemp->pNext; + + ptemp->pNext = pdl; +} + +float CHud::GetSensitivity( void ) +{ + return m_flMouseSensitivity; +} diff --git a/cl_dll/hud/hud_msg.cpp b/cl_dll/hud/hud_msg.cpp index e7bdf35..cdc7872 100644 --- a/cl_dll/hud/hud_msg.cpp +++ b/cl_dll/hud/hud_msg.cpp @@ -1,215 +1,215 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// hud_msg.cpp -// - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" -#include "r_efx.h" -#include "rain.h" -#include "com_model.h" -#include "studio.h" -#include "studio_util.h" -#include "StudioModelRenderer.h" -#include "GameStudioModelRenderer.h" -#include "com_weapons.h" - -#include - -#define MAX_CLIENTS 32 - -extern float g_flRoundTime; - -/// USER-DEFINED SERVER MESSAGE HANDLERS - -int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf ) -{ - ASSERT( iSize == 0 ); - - // clear all hud data - HUDLIST *pList = m_pHudList; - - while ( pList ) - { - if ( pList->p ) - pList->p->Reset(); - pList = pList->pNext; - } - - // reset sensitivity - m_flMouseSensitivity = 0; - - // reset concussion effect - m_iConcussionEffect = 0; - - return 1; -} - -void CAM_ToFirstPerson(void); - -int CHud :: MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf ) -{ - CAM_ToFirstPerson(); - return 1; -} - -int CHud :: MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf ) -{ - // prepare all hud data - HUDLIST *pList = m_pHudList; - - while (pList) - { - if ( pList->p ) - pList->p->InitHUDData(); - pList = pList->pNext; - } - - g_iFreezeTimeOver = 0; - - memset( g_PlayerExtraInfo, 0, sizeof(g_PlayerExtraInfo) ); - - ResetRain(); - - // reset round time - g_flRoundTime = 0.0f; - - return 1; -} - - -int CHud :: MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - m_Teamplay = READ_BYTE(); - - return 1; -} - -int CHud :: MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - m_iConcussionEffect = READ_BYTE(); - if (m_iConcussionEffect) - this->m_StatusIcons.EnableIcon("dmg_concuss",255,160,0); - else - this->m_StatusIcons.DisableIcon("dmg_concuss"); - return 1; -} - -int CHud::MsgFunc_ReceiveW(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ(pbuf, iSize); - - int iWeatherType = READ_BYTE(); - - if( iWeatherType == 0 ) - { - ResetRain(); - return 1; - } - - Rain.distFromPlayer = 500; - Rain.dripsPerSecond = 500; - Rain.windX = Rain.windY = 30; - Rain.randX = Rain.randY = 0; - Rain.weatherMode = iWeatherType - 1; - Rain.globalHeight = 100; - - return 1; -} - -int CHud::MsgFunc_BombDrop(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ(pbuf, iSize); - - g_PlayerExtraInfo[33].origin.x = READ_COORD(); - g_PlayerExtraInfo[33].origin.y = READ_COORD(); - g_PlayerExtraInfo[33].origin.z = READ_COORD(); - - g_PlayerExtraInfo[33].radarflashon = 1; - g_PlayerExtraInfo[33].radarflashes = 99999; - g_PlayerExtraInfo[33].radarflash = gHUD.m_flTime; - strncpy(g_PlayerExtraInfo[33].teamname, "TERRORIST", MAX_TEAM_NAME); - g_PlayerExtraInfo[33].dead = 0; - g_PlayerExtraInfo[33].nextflash = true; - - int Flag = READ_BYTE(); - g_PlayerExtraInfo[33].playerclass = Flag; - - if( Flag ) // bomb planted - m_Timer.m_iFlags = 0; - - return 1; -} - -int CHud::MsgFunc_BombPickup(const char *pszName, int iSize, void *pbuf) -{ - g_PlayerExtraInfo[33].radarflashon = 0; - g_PlayerExtraInfo[33].radarflash = 0.0f; - g_PlayerExtraInfo[33].radarflashes = 0; - g_PlayerExtraInfo[33].dead = 1; - - return 1; -} - -int CHud::MsgFunc_HostagePos(const char *pszName, int iSize, void *pbuf) -{ - - BEGIN_READ(pbuf, iSize); - int Flag = READ_BYTE(); - int idx = READ_BYTE(); - if ( idx <= MAX_HOSTAGES ) - { - g_HostageInfo[idx].origin.x = READ_COORD(); - g_HostageInfo[idx].origin.y = READ_COORD(); - g_HostageInfo[idx].origin.z = READ_COORD(); - if ( Flag == 1 ) - { - g_HostageInfo[idx].radarflash = gHUD.m_flTime; - g_HostageInfo[idx].radarflashon = 1; - g_HostageInfo[idx].radarflashes = 99999; - } - strncpy(g_HostageInfo[idx].teamname, "CT", MAX_TEAM_NAME); - g_HostageInfo[idx].dead = 0; - } - - return 1; -} - -int CHud::MsgFunc_HostageK(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ(pbuf, iSize); - int idx = READ_BYTE(); - if ( idx <= MAX_HOSTAGES ) - { - g_HostageInfo[idx].dead = 1; - g_HostageInfo[idx].radarflash = gHUD.m_flTime; - g_HostageInfo[idx].radarflashes = 15; - } - - return 1; -} - -int CHud::MsgFunc_ShadowIdx(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ(pbuf, iSize); - - int idx = READ_BYTE(); - g_StudioRenderer.StudioSetShadowSprite(idx); - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// hud_msg.cpp +// + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" +#include "r_efx.h" +#include "rain.h" +#include "com_model.h" +#include "studio.h" +#include "studio_util.h" +#include "StudioModelRenderer.h" +#include "GameStudioModelRenderer.h" +#include "com_weapons.h" + +#include + +#define MAX_CLIENTS 32 + +extern float g_flRoundTime; + +/// USER-DEFINED SERVER MESSAGE HANDLERS + +int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf ) +{ + ASSERT( iSize == 0 ); + + // clear all hud data + HUDLIST *pList = m_pHudList; + + while ( pList ) + { + if ( pList->p ) + pList->p->Reset(); + pList = pList->pNext; + } + + // reset sensitivity + m_flMouseSensitivity = 0; + + // reset concussion effect + m_iConcussionEffect = 0; + + return 1; +} + +void CAM_ToFirstPerson(void); + +int CHud :: MsgFunc_ViewMode( const char *pszName, int iSize, void *pbuf ) +{ + CAM_ToFirstPerson(); + return 1; +} + +int CHud :: MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf ) +{ + // prepare all hud data + HUDLIST *pList = m_pHudList; + + while (pList) + { + if ( pList->p ) + pList->p->InitHUDData(); + pList = pList->pNext; + } + + g_iFreezeTimeOver = 0; + + memset( g_PlayerExtraInfo, 0, sizeof(g_PlayerExtraInfo) ); + + ResetRain(); + + // reset round time + g_flRoundTime = 0.0f; + + return 1; +} + + +int CHud :: MsgFunc_GameMode(const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + m_Teamplay = READ_BYTE(); + + return 1; +} + +int CHud :: MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + m_iConcussionEffect = READ_BYTE(); + if (m_iConcussionEffect) + this->m_StatusIcons.EnableIcon("dmg_concuss",255,160,0); + else + this->m_StatusIcons.DisableIcon("dmg_concuss"); + return 1; +} + +int CHud::MsgFunc_ReceiveW(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ(pbuf, iSize); + + int iWeatherType = READ_BYTE(); + + if( iWeatherType == 0 ) + { + ResetRain(); + return 1; + } + + Rain.distFromPlayer = 500; + Rain.dripsPerSecond = 500; + Rain.windX = Rain.windY = 30; + Rain.randX = Rain.randY = 0; + Rain.weatherMode = iWeatherType - 1; + Rain.globalHeight = 100; + + return 1; +} + +int CHud::MsgFunc_BombDrop(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ(pbuf, iSize); + + g_PlayerExtraInfo[33].origin.x = READ_COORD(); + g_PlayerExtraInfo[33].origin.y = READ_COORD(); + g_PlayerExtraInfo[33].origin.z = READ_COORD(); + + g_PlayerExtraInfo[33].radarflashon = 1; + g_PlayerExtraInfo[33].radarflashes = 99999; + g_PlayerExtraInfo[33].radarflash = gHUD.m_flTime; + strncpy(g_PlayerExtraInfo[33].teamname, "TERRORIST", MAX_TEAM_NAME); + g_PlayerExtraInfo[33].dead = 0; + g_PlayerExtraInfo[33].nextflash = true; + + int Flag = READ_BYTE(); + g_PlayerExtraInfo[33].playerclass = Flag; + + if( Flag ) // bomb planted + m_Timer.m_iFlags = 0; + + return 1; +} + +int CHud::MsgFunc_BombPickup(const char *pszName, int iSize, void *pbuf) +{ + g_PlayerExtraInfo[33].radarflashon = 0; + g_PlayerExtraInfo[33].radarflash = 0.0f; + g_PlayerExtraInfo[33].radarflashes = 0; + g_PlayerExtraInfo[33].dead = 1; + + return 1; +} + +int CHud::MsgFunc_HostagePos(const char *pszName, int iSize, void *pbuf) +{ + + BEGIN_READ(pbuf, iSize); + int Flag = READ_BYTE(); + int idx = READ_BYTE(); + if ( idx <= MAX_HOSTAGES ) + { + g_HostageInfo[idx].origin.x = READ_COORD(); + g_HostageInfo[idx].origin.y = READ_COORD(); + g_HostageInfo[idx].origin.z = READ_COORD(); + if ( Flag == 1 ) + { + g_HostageInfo[idx].radarflash = gHUD.m_flTime; + g_HostageInfo[idx].radarflashon = 1; + g_HostageInfo[idx].radarflashes = 99999; + } + strncpy(g_HostageInfo[idx].teamname, "CT", MAX_TEAM_NAME); + g_HostageInfo[idx].dead = 0; + } + + return 1; +} + +int CHud::MsgFunc_HostageK(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ(pbuf, iSize); + int idx = READ_BYTE(); + if ( idx <= MAX_HOSTAGES ) + { + g_HostageInfo[idx].dead = 1; + g_HostageInfo[idx].radarflash = gHUD.m_flTime; + g_HostageInfo[idx].radarflashes = 15; + } + + return 1; +} + +int CHud::MsgFunc_ShadowIdx(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ(pbuf, iSize); + + int idx = READ_BYTE(); + g_StudioRenderer.StudioSetShadowSprite(idx); + return 1; +} diff --git a/cl_dll/hud/hud_redraw.cpp b/cl_dll/hud/hud_redraw.cpp index 7086d84..c64728d 100644 --- a/cl_dll/hud/hud_redraw.cpp +++ b/cl_dll/hud/hud_redraw.cpp @@ -1,175 +1,175 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// hud_redraw.cpp -// -#include -#include "hud.h" -#include "cl_util.h" -#include "triangleapi.h" - -#include -#define MAX_LOGO_FRAMES 56 - -int grgLogoFrame[MAX_LOGO_FRAMES] = -{ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 14, 15, - 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 30, 31 -}; - - -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) - pList->p->Think(); - 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( default_fov->value, 90 ); - } - -} - -// Redraw -// step through the local data, placing the appropriate graphics & text as appropriate -// returns 1 if they've changed, 0 otherwise -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 int 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(); - gViewPort->UpdateSpectatorPanel(); - } - else if ( !m_iIntermission && intermission ) - { - m_iIntermission = intermission; - gViewPort->HideCommandMenu(); - gViewPort->HideVGUIMenu(); - gViewPort->ShowScoreBoard(); - gViewPort->UpdateSpectatorPanel(); - - // 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 ( m_pCvarDraw->value ) - { - HUDLIST *pList = m_pHudList; - - while (pList) - { - if ( !intermission ) - { - if ( (pList->p->m_iFlags & HUD_ACTIVE) && !(m_iHideHUDDisplay & HIDEHUD_ALL) ) - pList->p->Draw(flTime); - } - else - { // it's an intermission, so only draw hud elements that are set to draw during intermissions - if ( pList->p->m_iFlags & HUD_INTERMISSION ) - pList->p->Draw( flTime ); - } - - pList = pList->pNext; - } - } - - // are we in demo mode? do we need to draw the logo in the top corner? - if (m_iLogo) - { - int x, y, i; - - if (m_hsprLogo == 0) - m_hsprLogo = LoadSprite("sprites/%d_logo.spr"); - - SPR_Set(m_hsprLogo, 250, 250, 250 ); - - x = SPR_Width(m_hsprLogo, 0); - x = ScreenWidth - x; - y = SPR_Height(m_hsprLogo, 0)/2; - - // Draw the logo at 20 fps - int iFrame = (int)(flTime * 20) % MAX_LOGO_FRAMES; - i = grgLogoFrame[iFrame] - 1; - - SPR_DrawAdditive(i, x, y, NULL); - } - - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// hud_redraw.cpp +// +#include +#include "hud.h" +#include "cl_util.h" +#include "triangleapi.h" + +#include +#define MAX_LOGO_FRAMES 56 + +int grgLogoFrame[MAX_LOGO_FRAMES] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 12, 11, 10, 9, 8, 14, 15, + 16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 29, 29, 29, 29, 29, 28, 27, 26, 25, 24, 30, 31 +}; + + +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) + pList->p->Think(); + 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( default_fov->value, 90 ); + } + +} + +// Redraw +// step through the local data, placing the appropriate graphics & text as appropriate +// returns 1 if they've changed, 0 otherwise +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 int 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(); + gViewPort->UpdateSpectatorPanel(); + } + else if ( !m_iIntermission && intermission ) + { + m_iIntermission = intermission; + gViewPort->HideCommandMenu(); + gViewPort->HideVGUIMenu(); + gViewPort->ShowScoreBoard(); + gViewPort->UpdateSpectatorPanel(); + + // 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 ( m_pCvarDraw->value ) + { + HUDLIST *pList = m_pHudList; + + while (pList) + { + if ( !intermission ) + { + if ( (pList->p->m_iFlags & HUD_ACTIVE) && !(m_iHideHUDDisplay & HIDEHUD_ALL) ) + pList->p->Draw(flTime); + } + else + { // it's an intermission, so only draw hud elements that are set to draw during intermissions + if ( pList->p->m_iFlags & HUD_INTERMISSION ) + pList->p->Draw( flTime ); + } + + pList = pList->pNext; + } + } + + // are we in demo mode? do we need to draw the logo in the top corner? + if (m_iLogo) + { + int x, y, i; + + if (m_hsprLogo == 0) + m_hsprLogo = LoadSprite("sprites/%d_logo.spr"); + + SPR_Set(m_hsprLogo, 250, 250, 250 ); + + x = SPR_Width(m_hsprLogo, 0); + x = ScreenWidth - x; + y = SPR_Height(m_hsprLogo, 0)/2; + + // Draw the logo at 20 fps + int iFrame = (int)(flTime * 20) % MAX_LOGO_FRAMES; + i = grgLogoFrame[iFrame] - 1; + + SPR_DrawAdditive(i, x, y, NULL); + } + + return 1; +} diff --git a/cl_dll/hud/hud_spectator.cpp b/cl_dll/hud/hud_spectator.cpp index 8dafc9b..e5355c6 100644 --- a/cl_dll/hud/hud_spectator.cpp +++ b/cl_dll/hud/hud_spectator.cpp @@ -1,1692 +1,1692 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include "hud.h" -#include "cl_util.h" -#include -#include "cl_entity.h" -#include "triangleapi.h" -#include "hltv.h" - -#include "pm_shared.h" -#include "pm_defs.h" -#include "pmtrace.h" -#include "parsemsg.h" -#include "entity_types.h" - -// these are included for the math functions -#include "com_model.h" -#include "demo_api.h" -#include "event_api.h" -#include "studio_util.h" -#include "screenfade.h" - -#pragma warning(disable: 4244) - -extern "C" int iJumpSpectator; -extern "C" float vJumpOrigin[3]; -extern "C" float vJumpAngles[3]; - - -extern void V_GetInEyePos(int entity, float * origin, float * angles ); -extern void V_ResetChaseCam(); -extern void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles); -extern void VectorAngles( const float *forward, float *angles ); -extern "C" void NormalizeAngles( float *angles ); -extern float * GetClientColor( int clientIndex ); - -extern vec3_t v_origin; // last view origin -extern vec3_t v_angles; // last view angle -extern vec3_t v_cl_angles; // last client/mouse angle -extern vec3_t v_sim_org; // last sim origin - -void SpectatorMode(void) -{ - - - if ( gEngfuncs.Cmd_Argc() <= 1 ) - { - gEngfuncs.Con_Printf( "usage: spec_mode
[]\n" ); - return; - } - - // SetModes() will decide if command is executed on server or local - if ( gEngfuncs.Cmd_Argc() == 2 ) - gHUD.m_Spectator.SetModes( atoi( gEngfuncs.Cmd_Argv(1) ), -1 ); - else if ( gEngfuncs.Cmd_Argc() == 3 ) - gHUD.m_Spectator.SetModes( atoi( gEngfuncs.Cmd_Argv(1) ), atoi( gEngfuncs.Cmd_Argv(2) ) ); -} - -void SpectatorSpray(void) -{ - vec3_t forward; - char string[128]; - - if ( !gEngfuncs.IsSpectateOnly() ) - return; - - AngleVectors(v_angles,forward,NULL,NULL); - VectorScale(forward, 128, forward); - VectorAdd(forward, v_origin, forward); - pmtrace_t * trace = gEngfuncs.PM_TraceLine( v_origin, forward, PM_TRACELINE_PHYSENTSONLY, 2, -1 ); - if ( trace->fraction != 1.0 ) - { - sprintf(string, "drc_spray %.2f %.2f %.2f %i", - trace->endpos[0], trace->endpos[1], trace->endpos[2], trace->ent ); - gEngfuncs.pfnServerCmd(string); - } - -} -void SpectatorHelp(void) -{ - /*if ( gViewPort ) - { - gViewPort->ShowVGUIMenu( MENU_SPECHELP ); - } - else*/ - { - char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" ); - - if ( text ) - { - while ( *text ) - { - if ( *text != 13 ) - gEngfuncs.Con_Printf( "%c", *text ); - text++; - } - } - } -} - -void SpectatorMenu( void ) -{ - if ( gEngfuncs.Cmd_Argc() <= 1 ) - { - gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" ); - return; - } - - //gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv(1))!=0 ); -} - -void ToggleScores( void ) -{ - /*if ( gViewPort ) - { - if (gViewPort->IsScoreBoardVisible() ) - { - gViewPort->HideScoreBoard(); - } - else - { - gViewPort->ShowScoreBoard(); - } - }*/ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CHudSpectator::Init() -{ - gHUD.AddHudElem(this); - - m_iFlags |= HUD_ACTIVE; - m_flNextObserverInput = 0.0f; - m_zoomDelta = 0.0f; - m_moveDelta = 0.0f; - m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0); - iJumpSpectator = 0; - - memset( &m_OverviewData, 0, sizeof(m_OverviewData)); - memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities)); - m_lastPrimaryObject = m_lastSecondaryObject = 0; - - gEngfuncs.pfnAddCommand ("spec_mode", SpectatorMode ); - gEngfuncs.pfnAddCommand ("spec_decal", SpectatorSpray ); - gEngfuncs.pfnAddCommand ("spec_help", SpectatorHelp ); - gEngfuncs.pfnAddCommand ("spec_menu", SpectatorMenu ); - gEngfuncs.pfnAddCommand ("togglescores", ToggleScores ); - - m_drawnames = gEngfuncs.pfnRegisterVariable("spec_drawnames_internal","1",0); - m_specmode = gEngfuncs.pfnRegisterVariable("spec_mode_internal","1",0); - m_drawcone = gEngfuncs.pfnRegisterVariable("spec_drawcone_internal","1",0); - m_drawstatus = gEngfuncs.pfnRegisterVariable("spec_drawstatus_internal","1",0); - m_autoDirector = gEngfuncs.pfnRegisterVariable("spec_autodirector_internal","1",0); - m_pip = gEngfuncs.pfnRegisterVariable("spec_pip","1",0); - m_lastAutoDirector = 0.0f; - - if ( !m_drawnames || !m_drawcone || !m_drawstatus || !m_autoDirector || !m_pip) - { - gEngfuncs.Con_Printf("ERROR! Couldn't register all spectator variables.\n"); - return 0; - } - - return 1; -} - - -//----------------------------------------------------------------------------- -// UTIL_StringToVector originally from ..\dlls\util.cpp, slightly changed -//----------------------------------------------------------------------------- - -void UTIL_StringToVector( float * pVector, const char *pString ) -{ - char *pstr, *pfront, tempString[128]; - int j; - - strncpy( tempString, pString, sizeof(tempString) ); - pstr = pfront = tempString; - - for ( j = 0; j < 3; j++ ) - { - pVector[j] = atof( pfront ); - - while ( *pstr && *pstr != ' ' ) - pstr++; - if (!*pstr) - break; - pstr++; - pfront = pstr; - } - - if (j < 2) - { - for (j = j+1;j < 3; j++) - pVector[j] = 0; - } -} - -int UTIL_FindEntityInMap(char * name, float * origin, float * angle) -{ - int n,found = 0; - char keyname[256]; - char token[1024]; - - cl_entity_t * pEnt = gEngfuncs.GetEntityByIndex( 0 ); // get world model - - if ( !pEnt ) return 0; - - if ( !pEnt->model ) return 0; - - char * data = pEnt->model->entities; - - while (data) - { - data = gEngfuncs.COM_ParseFile(data, token); - - if ( (token[0] == '}') || (token[0]==0) ) - break; - - if (!data) - { - gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n"); - return 0; - } - - if (token[0] != '{') - { - gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: expected {\n"); - return 0; - } - - // we parse the first { now parse entities properties - - while ( 1 ) - { - // parse key - data = gEngfuncs.COM_ParseFile(data, token); - if (token[0] == '}') - break; // finish parsing this entity - - if (!data) - { - gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n"); - return 0; - }; - - strncpy (keyname, token, sizeof(keyname)); - - // another hack to fix keynames with trailing spaces - n = strlen(keyname); - while (n && keyname[n-1] == ' ') - { - keyname[n-1] = 0; - n--; - } - - // parse value - data = gEngfuncs.COM_ParseFile(data, token); - if (!data) - { - gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n"); - return 0; - }; - - if (token[0] == '}') - { - gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: closing brace without data"); - return 0; - } - - if (!strcmp(keyname,"classname")) - { - if (!strcmp(token, name )) - { - found = 1; // thats our entity - } - }; - - if( !strcmp( keyname, "angle" ) ) - { - float y = atof( token ); - - if (y >= 0) - { - angle[0] = 0.0f; - angle[1] = y; - } - else if ((int)y == -1) - { - angle[0] = -90.0f; - angle[1] = 0.0f;; - } - else - { - angle[0] = 90.0f; - angle[1] = 0.0f; - } - - angle[2] = 0.0f; - } - - if( !strcmp( keyname, "angles" ) ) - { - UTIL_StringToVector(angle, token); - } - - if (!strcmp(keyname,"origin")) - { - UTIL_StringToVector(origin, token); - - }; - - } // while (1) - - if (found) - return 1; - - } - - return 0; // we search all entities, but didn't found the correct - -} - -//----------------------------------------------------------------------------- -// SetSpectatorStartPosition(): -// Get valid map position and 'beam' spectator to this position -//----------------------------------------------------------------------------- - -void CHudSpectator::SetSpectatorStartPosition() -{ - // search for info_player start - if ( UTIL_FindEntityInMap( "trigger_camera", m_cameraOrigin, m_cameraAngles ) ) - iJumpSpectator = 1; - - else if ( UTIL_FindEntityInMap( "info_player_start", m_cameraOrigin, m_cameraAngles ) ) - iJumpSpectator = 1; - - else if ( UTIL_FindEntityInMap( "info_player_deathmatch", m_cameraOrigin, m_cameraAngles ) ) - iJumpSpectator = 1; - - else if ( UTIL_FindEntityInMap( "info_player_coop", m_cameraOrigin, m_cameraAngles ) ) - iJumpSpectator = 1; - else - { - static const Vector &nullvec = Vector (0.0, 0.0, 0.0); - // jump to 0,0,0 if no better position was found - VectorCopy(nullvec, m_cameraOrigin); - VectorCopy(nullvec, m_cameraAngles); - } - - VectorCopy(m_cameraOrigin, vJumpOrigin); - VectorCopy(m_cameraAngles, vJumpAngles); - - iJumpSpectator = 1; // jump anyway -} - -//----------------------------------------------------------------------------- -// Purpose: Loads new icons -//----------------------------------------------------------------------------- -int CHudSpectator::VidInit() -{ - m_hsprPlayer = SPR_Load("sprites/iplayer.spr"); - m_hsprPlayerBlue = SPR_Load("sprites/iplayerblue.spr"); - m_hsprPlayerRed = SPR_Load("sprites/iplayerred.spr"); - m_hsprPlayerDead = SPR_Load("sprites/iplayerdead.spr"); - m_hsprPlayerVIP = SPR_Load("sprites/iplayervip.spr"); - m_hsprPlayerC4 = SPR_Load("sprites/iplayerc4.spr"); - m_hsprUnkownMap = SPR_Load("sprites/tile.spr"); - m_hsprBeam = SPR_Load("sprites/laserbeam.spr"); - m_hsprCamera = SPR_Load("sprites/camera.spr"); - m_hsprBomb = SPR_Load("sprites/ic4.spr"); - m_hsprBackpack = SPR_Load("sprites/ibackpack.spr"); - m_hsprHostage = SPR_Load("sprites/ihostage.spr"); - m_hCrosshair = SPR_Load("sprites/crosshairs.spr"); - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flTime - -// intermission - -//----------------------------------------------------------------------------- -int CHudSpectator::Draw(float flTime) -{ - int lx; - - char string[256]; - float * color; - - // draw only in spectator mode - if ( !g_iUser1 ) - return 0; - - - if ( m_lastAutoDirector != m_autoDirector->value ) - { - m_lastAutoDirector = m_autoDirector->value; - char cmd[64]; - snprintf(cmd, sizeof(cmd), "spec_set_ad %f", m_autoDirector->value); - gEngfuncs.pfnClientCmd(cmd); - if ( m_lastAutoDirector == 0.0 ) - { - if ( m_lastAutoDirector == 0.0 && g_iUser1 == OBS_CHASE_LOCKED ) - { - SetModes(OBS_CHASE_FREE, INSET_OFF); - } - } - else if ( g_iUser1 == OBS_CHASE_FREE ) - { - SetModes(OBS_CHASE_LOCKED, INSET_OFF); - } - } - - // if user pressed zoom, aplly changes - if ( (m_zoomDelta != 0.0f) && ( g_iUser1 == OBS_MAP_FREE ) ) - { - m_mapZoom += m_zoomDelta; - - if ( m_mapZoom > 3.0f ) - m_mapZoom = 3.0f; - - if ( m_mapZoom < 0.5f ) - m_mapZoom = 0.5f; - } - - // if user moves in map mode, change map origin - if ( (m_moveDelta != 0.0f) && (g_iUser1 != OBS_ROAMING) ) - { - vec3_t right; - AngleVectors(v_angles, NULL, right, NULL); - VectorNormalize(right); - VectorScale(right, m_moveDelta, right ); - - VectorAdd( m_mapOrigin, right, m_mapOrigin ) - - } - - // Only draw the icon names only if map mode is in Main Mode - if ( g_iUser1 < OBS_MAP_FREE ) - return 1; - - if ( !m_drawnames->value ) - return 1; - - // make sure we have player info - //gViewPort->GetAllPlayersInfo(); - gHUD.m_Scoreboard.GetAllPlayersInfo(); - - - // loop through all the players and draw additional infos to their sprites on the map - for (int i = 0; i < MAX_PLAYERS; i++) - { - - if ( m_vPlayerPos[i][2]<0 ) // marked as invisible ? - continue; - - // can player exist without name? - if( !g_PlayerInfoList[i+1].name ) - continue; - - // check if name would be in inset window - if ( m_pip->value != INSET_OFF ) - { - if ( m_vPlayerPos[i][0] > XRES( m_OverviewData.insetWindowX ) && - m_vPlayerPos[i][1] > YRES( m_OverviewData.insetWindowY ) && - m_vPlayerPos[i][0] < XRES( m_OverviewData.insetWindowX + m_OverviewData.insetWindowWidth ) && - m_vPlayerPos[i][1] < YRES( m_OverviewData.insetWindowY + m_OverviewData.insetWindowHeight) - ) continue; - } - - color = GetClientColor( i+1 ); // ??? - - // draw the players name and health underneath - sprintf(string, "%s", g_PlayerInfoList[i+1].name ); - - lx = strlen(string)*3; // 3 is avg. character length :) - - DrawUtils::SetConsoleTextColor( color[0], color[1], color[2] ); - DrawUtils::DrawConsoleString( m_vPlayerPos[i][0]-lx,m_vPlayerPos[i][1], string); - - } - - - // Only draw the overview if Map Mode is selected for this view - if ( m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) ) ) - return 1; - - if ( m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE ) - return 1; - - return 1; -} - - -void CHudSpectator::DirectorMessage( int iSize, void *pbuf ) -{ - float value; - char * string; - - BEGIN_READ( pbuf, iSize ); - - int cmd = READ_BYTE(); - - switch ( cmd ) // director command byte - { - case DRC_CMD_START : - // now we have to do some things clientside, since the proxy doesn't know our mod - g_iPlayerClass = 0; - g_iTeamNumber = 0; - - // fake a InitHUD & ResetHUD message - gHUD.MsgFunc_InitHUD(NULL,0, NULL); - gHUD.MsgFunc_ResetHUD(NULL, 0, NULL); - - break; - - case DRC_CMD_EVENT : - m_lastPrimaryObject = READ_WORD(); - m_lastSecondaryObject = READ_WORD(); - m_iObserverFlags = READ_LONG(); - - if ( m_autoDirector->value ) - { - if ( (g_iUser2 != m_lastPrimaryObject) || (g_iUser3 != m_lastSecondaryObject) ) - V_ResetChaseCam(); - - g_iUser2 = m_lastPrimaryObject; - g_iUser3 = m_lastSecondaryObject; - } - - // gEngfuncs.Con_Printf("Director Camera: %i %i\n", firstObject, secondObject); - break; - - case DRC_CMD_MODE : - if ( m_autoDirector->value ) - { - SetModes( READ_BYTE(), -1 ); - } - break; - - case DRC_CMD_CAMERA : - if ( m_autoDirector->value ) - { - vJumpOrigin[0] = READ_COORD(); // position - vJumpOrigin[1] = READ_COORD(); - vJumpOrigin[2] = READ_COORD(); - - vJumpAngles[0] = READ_COORD(); // view angle - vJumpAngles[1] = READ_COORD(); - vJumpAngles[2] = READ_COORD(); - - gEngfuncs.SetViewAngles( vJumpAngles ); - - iJumpSpectator = 1; - } - break; - - case DRC_CMD_MESSAGE: - { - client_textmessage_t * msg = &m_HUDMessages[m_lastHudMessage]; - - msg->effect = READ_BYTE(); // effect - - DrawUtils::UnpackRGB( (int&)msg->r1, (int&)msg->g1, (int&)msg->b1, READ_LONG() ); // color - msg->r2 = msg->r1; - msg->g2 = msg->g1; - msg->b2 = msg->b1; - msg->a2 = msg->a1 = 0xFF; // not transparent - - msg->x = READ_FLOAT(); // x pos - msg->y = READ_FLOAT(); // y pos - - msg->fadein = READ_FLOAT(); // fadein - msg->fadeout = READ_FLOAT(); // fadeout - msg->holdtime = READ_FLOAT(); // holdtime - msg->fxtime = READ_FLOAT(); // fxtime; - - strncpy( m_HUDMessageText[m_lastHudMessage], READ_STRING(), 128 ); - m_HUDMessageText[m_lastHudMessage][127]=0; // text - - msg->pMessage = m_HUDMessageText[m_lastHudMessage]; - msg->pName = "HUD_MESSAGE"; - - gHUD.m_Message.MessageAdd( msg ); - - m_lastHudMessage++; - m_lastHudMessage %= MAX_SPEC_HUD_MESSAGES; - - } - - break; - - case DRC_CMD_SOUND : - string = READ_STRING(); - value = READ_FLOAT(); - - // gEngfuncs.Con_Printf("DRC_CMD_FX_SOUND: %s %.2f\n", string, value ); - gEngfuncs.pEventAPI->EV_PlaySound(0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM ); - - break; - - case DRC_CMD_TIMESCALE : - value = READ_FLOAT(); - break; - - - - case DRC_CMD_STATUS: - READ_LONG(); // total number of spectator slots - m_iSpectatorNumber = READ_LONG(); // total number of spectator - READ_WORD(); // total number of relay proxies - - //gViewPort->UpdateSpectatorPanel(); - break; - - case DRC_CMD_BANNER: - // gEngfuncs.Con_DPrintf("GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga - //gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() ); - //gViewPort->UpdateSpectatorPanel(); - break; - - /*case DRC_CMD_FADE: - break;*/ - - case DRC_CMD_STUFFTEXT: - ClientCmd( READ_STRING() ); - break; - - default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd ); - } -} - -void CHudSpectator::FindNextPlayer(bool bReverse) -{ - // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching - // only a subset of the players. e.g. Make it check the target's team. - - int iStart; - cl_entity_t * pEnt = NULL; - - // if we are NOT in HLTV mode, spectator targets are set on server - if ( !gEngfuncs.IsSpectateOnly() ) - { - char cmdstring[32]; - // forward command to server - sprintf(cmdstring,"follownext %i",bReverse?1:0); - gEngfuncs.pfnServerCmd(cmdstring); - return; - } - - if ( g_iUser2 ) - iStart = g_iUser2; - else - iStart = 1; - - g_iUser2 = 0; - - int iCurrent = iStart; - - int iDir = bReverse ? -1 : 1; - - // make sure we have player info - //gViewPort->GetAllPlayersInfo(); - gHUD.m_Scoreboard.GetAllPlayersInfo(); - - do - { - iCurrent += iDir; - - // Loop through the clients - if (iCurrent > MAX_PLAYERS) - iCurrent = 1; - if (iCurrent < 1) - iCurrent = MAX_PLAYERS; - - pEnt = gEngfuncs.GetEntityByIndex( iCurrent ); - - if ( !IsActivePlayer( pEnt ) ) - continue; - - // MOD AUTHORS: Add checks on target here. - - g_iUser2 = iCurrent; - break; - - } while ( iCurrent != iStart ); - - // Did we find a target? - if ( !g_iUser2 ) - { - gEngfuncs.Con_DPrintf( "No observer targets.\n" ); - // take save camera position - VectorCopy(m_cameraOrigin, vJumpOrigin); - VectorCopy(m_cameraAngles, vJumpAngles); - } - else - { - // use new entity position for roaming - VectorCopy ( pEnt->origin, vJumpOrigin ); - VectorCopy ( pEnt->angles, vJumpAngles ); - } - iJumpSpectator = 1; -} - -void CHudSpectator::HandleButtonsDown( int ButtonPressed ) -{ - double time = gEngfuncs.GetClientTime(); - - int newMainMode = g_iUser1; - int newInsetMode = m_pip->value; - - // gEngfuncs.Con_Printf(" HandleButtons:%i\n", ButtonPressed ); - // if ( !gViewPort ) - return; - - //Not in intermission. - if ( gHUD.m_iIntermission ) - return; - - if ( !g_iUser1 ) - return; // dont do anything if not in spectator mode - - // don't handle buttons during normal demo playback - if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() ) - return; - // Slow down mouse clicks. - if ( m_flNextObserverInput > time ) - return; - - // enable spectator screen - //if ( ButtonPressed & IN_DUCK ) - // gViewPort->m_pSpectatorPanel->ShowMenu(!gViewPort->m_pSpectatorPanel->m_menuVisible); - - // 'Use' changes inset window mode - if ( ButtonPressed & IN_USE ) - { - newInsetMode = ToggleInset(true); - } - - // if not in HLTV mode, buttons are handled server side - if ( gEngfuncs.IsSpectateOnly() ) - { - // changing target or chase mode not in overviewmode without inset window - - // Jump changes main window modes - if ( ButtonPressed & IN_JUMP ) - { - if ( g_iUser1 == OBS_CHASE_LOCKED ) - newMainMode = OBS_CHASE_FREE; - - else if ( g_iUser1 == OBS_CHASE_FREE ) - newMainMode = OBS_IN_EYE; - - else if ( g_iUser1 == OBS_IN_EYE ) - newMainMode = OBS_ROAMING; - - else if ( g_iUser1 == OBS_ROAMING ) - newMainMode = OBS_MAP_FREE; - - else if ( g_iUser1 == OBS_MAP_FREE ) - newMainMode = OBS_MAP_CHASE; - - else - newMainMode = OBS_CHASE_FREE; // don't use OBS_CHASE_LOCKED anymore - } - - // Attack moves to the next player - if ( ButtonPressed & (IN_ATTACK | IN_ATTACK2) ) - { - FindNextPlayer( (ButtonPressed & IN_ATTACK2) ? true:false ); - - if ( g_iUser1 == OBS_ROAMING ) - { - gEngfuncs.SetViewAngles( vJumpAngles ); - iJumpSpectator = 1; - - } - // lease directed mode if player want to see another player - m_autoDirector->value = 0.0f; - } - } - - SetModes(newMainMode, newInsetMode); - - if ( g_iUser1 == OBS_MAP_FREE ) - { - if ( ButtonPressed & IN_FORWARD ) - m_zoomDelta = 0.01f; - - if ( ButtonPressed & IN_BACK ) - m_zoomDelta = -0.01f; - - if ( ButtonPressed & IN_MOVELEFT ) - m_moveDelta = -12.0f; - - if ( ButtonPressed & IN_MOVERIGHT ) - m_moveDelta = 12.0f; - } - - m_flNextObserverInput = time + 0.2; -} - -void CHudSpectator::HandleButtonsUp( int ButtonPressed ) -{ - //if ( !gViewPort ) - return; - - // if ( !gViewPort->m_pSpectatorPanel->isVisible() ) - // return; // dont do anything if not in spectator mode - - if ( ButtonPressed & (IN_FORWARD | IN_BACK) ) - m_zoomDelta = 0.0f; - - if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) ) - m_moveDelta = 0.0f; -} - -void CHudSpectator::SetModes(int iNewMainMode, int iNewInsetMode) -{ - // if value == -1 keep old value - if ( iNewMainMode == -1 ) - iNewMainMode = g_iUser1; - - if ( iNewInsetMode == -1 ) - iNewInsetMode = m_pip->value; - - // inset mode is handled only clients side - m_pip->value = iNewInsetMode; - - if ( iNewMainMode < OBS_CHASE_LOCKED || iNewMainMode > OBS_MAP_CHASE ) - { - gEngfuncs.Con_Printf("Invalid spectator mode.\n"); - return; - } - - // main modes ettings will override inset window settings - if ( iNewMainMode != g_iUser1 ) - { - // if we are NOT in HLTV mode, main spectator mode is set on server - if ( !gEngfuncs.IsSpectateOnly() ) - { - return; - } - - if ( !g_iUser2 && (iNewMainMode !=OBS_ROAMING ) ) // make sure we have a target - { - // choose last Director object if still available - if ( IsActivePlayer( gEngfuncs.GetEntityByIndex( m_lastPrimaryObject ) ) ) - { - g_iUser2 = m_lastPrimaryObject; - g_iUser3 = m_lastSecondaryObject; - } - else - FindNextPlayer(false); // find any target - } - - switch ( iNewMainMode ) - { - case OBS_CHASE_LOCKED: g_iUser1 = OBS_CHASE_LOCKED; - break; - - case OBS_CHASE_FREE : g_iUser1 = OBS_CHASE_FREE; - break; - - case OBS_ROAMING : // jump to current vJumpOrigin/angle - g_iUser1 = OBS_ROAMING; - if ( g_iUser2 ) - { - V_GetChasePos( g_iUser2, v_cl_angles, vJumpOrigin, vJumpAngles ); - gEngfuncs.SetViewAngles( vJumpAngles ); - iJumpSpectator = 1; - } - break; - - case OBS_IN_EYE : g_iUser1 = OBS_IN_EYE; - break; - - case OBS_MAP_FREE : g_iUser1 = OBS_MAP_FREE; - // reset user values - m_mapZoom = m_OverviewData.zoom; - m_mapOrigin = m_OverviewData.origin; - break; - - case OBS_MAP_CHASE : g_iUser1 = OBS_MAP_CHASE; - // reset user values - m_mapZoom = m_OverviewData.zoom; - m_mapOrigin = m_OverviewData.origin; - break; - } - - if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) ) - { - m_crosshairRect.left = 24; - m_crosshairRect.top = 0; - m_crosshairRect.right = 48; - m_crosshairRect.bottom = 24; - - SetCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 ); - } - else - { - memset( &m_crosshairRect,0,sizeof(m_crosshairRect) ); - SetCrosshair( 0, m_crosshairRect, 0, 0, 0 ); - } - - char string[128]; - sprintf(string, "#Spec_Mode%d", g_iUser1 ); - sprintf(string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string )); - gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string ); - } - - //gViewPort->UpdateSpectatorPanel(); - -} - -bool CHudSpectator::IsActivePlayer(cl_entity_t * ent) -{ - return ( ent && - ent->player && - ent->curstate.solid != SOLID_NOT && - ent != gEngfuncs.GetLocalPlayer() && - g_PlayerInfoList[ent->index].name != NULL - ); -} - - -bool CHudSpectator::ParseOverviewFile( ) -{ - char filename[255]; - char levelname[255]; - char token[1024]; - float height; - - char *pfile = NULL; - - memset( &m_OverviewData, 0, sizeof(m_OverviewData)); - - // fill in standrd values - m_OverviewData.insetWindowX = 4; // upper left corner - m_OverviewData.insetWindowY = 4; - m_OverviewData.insetWindowHeight = 180; - m_OverviewData.insetWindowWidth = 240; - m_OverviewData.origin[0] = 0.0f; - m_OverviewData.origin[1] = 0.0f; - m_OverviewData.origin[2] = 0.0f; - m_OverviewData.zoom = 1.0f; - m_OverviewData.layers = 0; - m_OverviewData.layersHeights[0] = 0.0f; - strncpy( m_OverviewData.map, gEngfuncs.pfnGetLevelName(), sizeof(m_OverviewData.map) ); - - if ( strlen( m_OverviewData.map ) == 0 ) - return false; // not active yet - - strncpy(levelname, m_OverviewData.map + 5, sizeof( levelname )); - levelname[strlen(levelname)-4] = 0; - - sprintf(filename, "overviews/%s.txt", levelname ); - - pfile = (char *)gEngfuncs.COM_LoadFile( filename, 5, NULL); - - if (!pfile) - { - gEngfuncs.Con_Printf("Couldn't open file %s. Using default values for overiew mode.\n", filename ); - return false; - } - - - while (true) - { - pfile = gEngfuncs.COM_ParseFile(pfile, token); - - if (!pfile) - break; - - if ( !stricmp( token, "global" ) ) - { - // parse the global data - pfile = gEngfuncs.COM_ParseFile(pfile, token); - if ( stricmp( token, "{" ) ) - { - gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename ); - return false; - } - - pfile = gEngfuncs.COM_ParseFile(pfile,token); - - while (stricmp( token, "}") ) - { - if ( !stricmp( token, "zoom" ) ) - { - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.zoom = atof( token ); - } - else if ( !stricmp( token, "origin" ) ) - { - pfile = gEngfuncs.COM_ParseFile(pfile, token); - m_OverviewData.origin[0] = atof( token ); - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.origin[1] = atof( token ); - pfile = gEngfuncs.COM_ParseFile(pfile, token); - m_OverviewData.origin[2] = atof( token ); - } - else if ( !stricmp( token, "rotated" ) ) - { - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.rotated = atoi( token ); - } - else if ( !stricmp( token, "inset" ) ) - { - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.insetWindowX = atof( token ); - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.insetWindowY = atof( token ); - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.insetWindowWidth = atof( token ); - pfile = gEngfuncs.COM_ParseFile(pfile,token); - m_OverviewData.insetWindowHeight = atof( token ); - - } - else - { - gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token ); - return false; - } - - pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token - - } - } - else if ( !stricmp( token, "layer" ) ) - { - // parse a layer data - - if ( m_OverviewData.layers == OVERVIEW_MAX_LAYERS ) - { - gEngfuncs.Con_Printf("Error parsing overview file %s. ( too many layers )\n", filename ); - return false; - } - - pfile = gEngfuncs.COM_ParseFile(pfile,token); - - - if ( stricmp( token, "{" ) ) - { - gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename ); - return false; - } - - pfile = gEngfuncs.COM_ParseFile(pfile,token); - - while (stricmp( token, "}") ) - { - if ( !stricmp( token, "image" ) ) - { - pfile = gEngfuncs.COM_ParseFile(pfile,token); - strncpy(m_OverviewData.layersImages[ m_OverviewData.layers ], token, 255); - - - } - else if ( !stricmp( token, "height" ) ) - { - pfile = gEngfuncs.COM_ParseFile(pfile,token); - height = atof(token); - m_OverviewData.layersHeights[ m_OverviewData.layers ] = height; - } - else - { - gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token ); - return false; - } - - pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token - } - - m_OverviewData.layers++; - - } - } - - gEngfuncs.COM_FreeFile( pfile ); - - m_mapZoom = m_OverviewData.zoom; - m_mapOrigin = m_OverviewData.origin; - - return true; - -} - -void CHudSpectator::LoadMapSprites() -{ - // right now only support for one map layer - if (m_OverviewData.layers > 0 ) - { - m_MapSprite = gEngfuncs.LoadMapSprite( m_OverviewData.layersImages[0] ); - } - else - m_MapSprite = NULL; // the standard "unkown map" sprite will be used instead -} - -void CHudSpectator::DrawOverviewLayer() -{ - float screenaspect, xs, ys, xStep, yStep, x,y,z; - int ix,iy,i,xTiles,yTiles,frame; - - qboolean hasMapImage = m_MapSprite?TRUE:FALSE; - model_t * dummySprite = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprUnkownMap); - - if ( hasMapImage) - { - i = m_MapSprite->numframes / (4*3); - i = sqrt(i); - xTiles = i*4; - yTiles = i*3; - } - else - { - xTiles = 8; - yTiles = 6; - } - - - screenaspect = 4.0f/3.0f; - - - xs = m_OverviewData.origin[0]; - ys = m_OverviewData.origin[1]; - z = ( 90.0f - v_angles[0] ) / 90.0f; - z *= m_OverviewData.layersHeights[0]; // gOverviewData.z_min - 32; - - // i = r_overviewTexture + ( layer*OVERVIEW_X_TILES*OVERVIEW_Y_TILES ); - gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture ); - gEngfuncs.pTriAPI->CullFace( TRI_NONE ); - gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 ); - frame = 0; - - // rotated view ? - if ( m_OverviewData.rotated ) - { - xStep = (2*4096.0f / m_OverviewData.zoom ) / xTiles; - yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles; - - y = ys + (4096.0f / (m_OverviewData.zoom * screenaspect)); - - for (iy = 0; iy < yTiles; iy++) - { - x = xs - (4096.0f / (m_OverviewData.zoom)); - - for (ix = 0; ix < xTiles; ix++) - { - if (hasMapImage) - gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame ); - else - gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 ); - - gEngfuncs.pTriAPI->Begin( TRI_QUADS ); - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - gEngfuncs.pTriAPI->Vertex3f (x, y, z); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); - gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z); - gEngfuncs.pTriAPI->End(); - - frame++; - x+= xStep; - } - - y+=yStep; - } - } - else - { - xStep = -(2*4096.0f / m_OverviewData.zoom ) / xTiles; - yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles; - - - x = xs + (4096.0f / (m_OverviewData.zoom * screenaspect )); - - - - for (ix = 0; ix < yTiles; ix++) - { - - y = ys + (4096.0f / (m_OverviewData.zoom)); - - for (iy = 0; iy < xTiles; iy++) - { - if (hasMapImage) - gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame ); - else - gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 ); - - gEngfuncs.pTriAPI->Begin( TRI_QUADS ); - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - gEngfuncs.pTriAPI->Vertex3f (x, y, z); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); - gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z); - gEngfuncs.pTriAPI->End(); - - frame++; - - y+=yStep; - } - - x+= xStep; - - } - } -} - -void CHudSpectator::DrawOverviewEntities() -{ - int i,ir,ig,ib; - struct model_s *hSpriteModel; - vec3_t origin, angles, point, forward, right, left, up, world, screen, offset; - float x,y,z, r,g,b, sizeScale = 4.0f; - cl_entity_t * ent; - float rmatrix[3][4]; // transformation matrix - - float zScale = (90.0f - v_angles[0] ) / 90.0f; - - - z = m_OverviewData.layersHeights[0] * zScale; - // get yellow/brown HUD color - DrawUtils::UnpackRGB(ir,ig,ib, RGB_YELLOWISH); - r = (float)ir/255.0f; - g = (float)ig/255.0f; - b = (float)ib/255.0f; - - gEngfuncs.pTriAPI->CullFace( TRI_NONE ); - - for (i=0; i < MAX_PLAYERS; i++ ) - m_vPlayerPos[i][2] = -1; // mark as invisible - - // draw all players - for (i=0 ; i < MAX_OVERVIEW_ENTITIES ; i++) - { - if ( !m_OverviewEntities[i].hSprite ) - continue; - - hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_OverviewEntities[i].hSprite ); - ent = m_OverviewEntities[i].entity; - - gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 ); - gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture ); - - // see R_DrawSpriteModel - // draws players sprite - - AngleVectors(ent->angles, right, up, NULL ); - - VectorCopy(ent->origin,origin); - - gEngfuncs.pTriAPI->Begin( TRI_QUADS ); - - gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 ); - - gEngfuncs.pTriAPI->TexCoord2f (1, 0); - VectorMA (origin, 16.0f * sizeScale, up, point); - VectorMA (point, 16.0f * sizeScale, right, point); - point[2] *= zScale; - gEngfuncs.pTriAPI->Vertex3fv (point); - - gEngfuncs.pTriAPI->TexCoord2f (0, 0); - - VectorMA (origin, 16.0f * sizeScale, up, point); - VectorMA (point, -16.0f * sizeScale, right, point); - point[2] *= zScale; - gEngfuncs.pTriAPI->Vertex3fv (point); - - gEngfuncs.pTriAPI->TexCoord2f (0,1); - VectorMA (origin, -16.0f * sizeScale, up, point); - VectorMA (point, -16.0f * sizeScale, right, point); - point[2] *= zScale; - gEngfuncs.pTriAPI->Vertex3fv (point); - - gEngfuncs.pTriAPI->TexCoord2f (1,1); - VectorMA (origin, -16.0f * sizeScale, up, point); - VectorMA (point, 16.0f * sizeScale, right, point); - point[2] *= zScale; - gEngfuncs.pTriAPI->Vertex3fv (point); - - gEngfuncs.pTriAPI->End (); - - - if ( !ent->player) - continue; - // draw line under player icons - origin[2] *= zScale; - - gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); - - hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprBeam ); - gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 ); - - gEngfuncs.pTriAPI->Color4f(r, g, b, 0.3); - - gEngfuncs.pTriAPI->Begin ( TRI_QUADS ); - gEngfuncs.pTriAPI->TexCoord2f (1, 0); - gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4, origin[2]-zScale); - gEngfuncs.pTriAPI->TexCoord2f (0, 0); - gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4, origin[2]-zScale); - gEngfuncs.pTriAPI->TexCoord2f (0, 1); - gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4,z); - gEngfuncs.pTriAPI->TexCoord2f (1, 1); - gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4,z); - gEngfuncs.pTriAPI->End (); - - gEngfuncs.pTriAPI->Begin ( TRI_QUADS ); - gEngfuncs.pTriAPI->TexCoord2f (1, 0); - gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4, origin[2]-zScale); - gEngfuncs.pTriAPI->TexCoord2f (0, 0); - gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4, origin[2]-zScale); - gEngfuncs.pTriAPI->TexCoord2f (0, 1); - gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4,z); - gEngfuncs.pTriAPI->TexCoord2f (1, 1); - gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4,z); - gEngfuncs.pTriAPI->End (); - - // calculate screen position for name and infromation in hud::draw() - if ( gEngfuncs.pTriAPI->WorldToScreen(origin,screen) ) - continue; // object is behind viewer - - screen[0] = XPROJECT(screen[0]); - screen[1] = YPROJECT(screen[1]); - screen[2] = 0.0f; - - // calculate some offset under the icon - origin[0]+=32.0f; - origin[1]+=32.0f; - - gEngfuncs.pTriAPI->WorldToScreen(origin,offset); - - offset[0] = XPROJECT(offset[0]); - offset[1] = YPROJECT(offset[1]); - offset[2] = 0.0f; - - VectorSubtract(offset, screen, offset ); - - int playerNum = ent->index - 1; - - m_vPlayerPos[playerNum][0] = screen[0]; - m_vPlayerPos[playerNum][1] = screen[1] + Length(offset); - m_vPlayerPos[playerNum][2] = 1; // mark player as visible - } - - if ( !m_pip->value || !m_drawcone->value ) - return; - - // get current camera position and angle - - if ( m_pip->value == INSET_IN_EYE || g_iUser1 == OBS_IN_EYE ) - { - V_GetInEyePos( g_iUser2, origin, angles ); - } - else if ( m_pip->value == INSET_CHASE_FREE || g_iUser1 == OBS_CHASE_FREE ) - { - V_GetChasePos( g_iUser2, v_cl_angles, origin, angles ); - } - else if ( g_iUser1 == OBS_ROAMING ) - { - VectorCopy( v_sim_org, origin ); - VectorCopy( v_cl_angles, angles ); - } - else - V_GetChasePos( g_iUser2, NULL, origin, angles ); - - - // draw camera sprite - - x = origin[0]; - y = origin[1]; - z = origin[2]; - - angles[0] = 0; // always show horizontal camera sprite - - hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprCamera ); - gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); - gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 ); - - - gEngfuncs.pTriAPI->Color4f( r, g, b, 1.0 ); - - AngleVectors(angles, forward, NULL, NULL ); - VectorScale (forward, 512.0f, forward); - - offset[0] = 0.0f; - offset[1] = 45.0f; - offset[2] = 0.0f; - - AngleMatrix(offset, rmatrix ); - VectorTransform(forward, rmatrix , right ); - - offset[1]= -45.0f; - AngleMatrix(offset, rmatrix ); - VectorTransform(forward, rmatrix , left ); - - gEngfuncs.pTriAPI->Begin (TRI_TRIANGLES); - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - gEngfuncs.pTriAPI->Vertex3f (x+right[0], y+right[1], (z+right[2]) * zScale); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x, y, z * zScale); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x+left[0], y+left[1], (z+left[2]) * zScale); - gEngfuncs.pTriAPI->End (); - -} - - - -void CHudSpectator::DrawOverview() -{ - static bool glClearForce = false; - static float old_glClearValue; - - // draw only in sepctator mode - if ( !g_iUser1 || (m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) )) || (m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE) ) - { - // fix non clearing background for overview - if( glClearForce ) - { - gEngfuncs.Cvar_SetValue("gl_clear", old_glClearValue ); - glClearForce = false; - } - return; - } - - // fix non clearing background for overview - if( !glClearForce ) - { - old_glClearValue = CVAR_GET_FLOAT("gl_clear"); - gEngfuncs.Cvar_Set("gl_clear", "1"); - glClearForce = true; - } - - DrawOverviewLayer(); - DrawOverviewEntities(); - CheckOverviewEntities(); -} -void CHudSpectator::CheckOverviewEntities() -{ - double time = gEngfuncs.GetClientTime(); - - // removes old entities from list - for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ ) - { - // remove entity from list if it is too old - if ( m_OverviewEntities[i].killTime < time ) - { - memset( &m_OverviewEntities[i], 0, sizeof (overviewEntity_t) ); - } - } -} - -bool CHudSpectator::AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname) -{ - HSPRITE hSprite = 0; - double duration = -1.0f; // duration -1 means show it only this frame; - - if ( !ent ) - return false; - - if ( type == ET_PLAYER ) - { - if ( ent->curstate.solid != SOLID_NOT) - { - switch ( g_PlayerExtraInfo[ent->index].teamnumber ) - { - // blue and red teams are swapped in CS and TFC - case TEAM_TERRORIST: hSprite = m_hsprPlayerRed; break; - case TEAM_CT: hSprite = m_hsprPlayerBlue; break; - default: hSprite = m_hsprPlayer; break; - } - - if( g_PlayerExtraInfo[ent->index].has_c4 ) - hSprite = m_hsprPlayerC4; - else if( g_PlayerExtraInfo[ent->index].vip ) - hSprite = m_hsprPlayerVIP; - - return AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration ); - } - else - return false; // it's an spectator - } - /*else if (type == ET_NORMAL) - { - return false; - } - else - { - else return false; - }*/ - - if( !stricmp( modelname, "models/w_c4.mdl" )) - hSprite = m_hsprBomb; - else if( !stricmp( modelname, "models/w_backpack.mdl" )) - hSprite = m_hsprBackpack; - else if( strstr( modelname, "models/hostage") || strstr( modelname, "models/scientist")) - hSprite = m_hsprHostage; - else return false; - - return AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration ); -} - -void CHudSpectator::DeathMessage(int victim) -{ - // find out where the victim is - cl_entity_t *pl = gEngfuncs.GetEntityByIndex(victim); - - if (pl && pl->player) - AddOverviewEntityToList(m_hsprPlayerDead, pl, gEngfuncs.GetClientTime() + 2.0f ); -} - -bool CHudSpectator::AddOverviewEntityToList(HSPRITE sprite, cl_entity_t *ent, double killTime) -{ - for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ ) - { - // find empty entity slot - if ( m_OverviewEntities[i].entity == NULL) - { - m_OverviewEntities[i].entity = ent; - m_OverviewEntities[i].hSprite = sprite; - m_OverviewEntities[i].killTime = killTime; - return true; - } - } - - return false; // maximum overview entities reached -} -void CHudSpectator::CheckSettings() -{ - // disallow same inset mode as main mode: - - m_pip->value = (int)m_pip->value; - - if ( ( g_iUser1 < OBS_MAP_FREE ) && ( m_pip->value == INSET_CHASE_FREE || m_pip->value == INSET_IN_EYE ) ) - { - // otherwise both would show in World picures - m_pip->value = INSET_MAP_FREE; - } - - if ( ( g_iUser1 >= OBS_MAP_FREE ) && ( m_pip->value >= INSET_MAP_FREE ) ) - { - // both would show map views - m_pip->value = INSET_CHASE_FREE; - } - - // disble in intermission screen - if ( gHUD.m_iIntermission ) - m_pip->value = INSET_OFF; - - // check chat mode - if ( m_chatEnabled != (gHUD.m_SayText.m_HUD_saytext->value!=0) ) - { - // hud_saytext changed - m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0); - - if ( gEngfuncs.IsSpectateOnly() ) - { - // tell proxy our new chat mode - char chatcmd[32]; - sprintf(chatcmd, "ignoremsg %i", m_chatEnabled?0:1 ); - gEngfuncs.pfnServerCmd(chatcmd); - } - } - - // HL/TFC has no oberserver corsshair, so set it client side - if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) ) - { - m_crosshairRect.left = 24; - m_crosshairRect.top = 0; - m_crosshairRect.right = 48; - m_crosshairRect.bottom = 24; - - SetCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 ); - } - else - { - memset( &m_crosshairRect,0,sizeof(m_crosshairRect) ); - SetCrosshair( 0, m_crosshairRect, 0, 0, 0 ); - } - - - - // if we are a real player on server don't allow inset window - // in First Person mode since this is our resticted forcecamera mode 2 - // team number 3 = SPECTATOR see player.h - - if ( ( (g_iTeamNumber == 1) || (g_iTeamNumber == 2)) && (g_iUser1 == OBS_IN_EYE) ) - m_pip->value = INSET_OFF; - - // draw small border around inset view, adjust upper black bar - // gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF ); -} - -int CHudSpectator::ToggleInset(bool allowOff) -{ - int newInsetMode = (int)m_pip->value + 1; - - if ( g_iUser1 < OBS_MAP_FREE ) - { - if ( newInsetMode > INSET_MAP_CHASE ) - { - if (allowOff) - newInsetMode = INSET_OFF; - else - newInsetMode = INSET_MAP_FREE; - } - - if ( newInsetMode == INSET_CHASE_FREE ) - newInsetMode = INSET_MAP_FREE; - } - else - { - if ( newInsetMode > INSET_IN_EYE ) - { - if (allowOff) - newInsetMode = INSET_OFF; - else - newInsetMode = INSET_CHASE_FREE; - } - } - - return newInsetMode; -} -void CHudSpectator::Reset() -{ - // Reset HUD - if ( strcmp( m_OverviewData.map, gEngfuncs.pfnGetLevelName() ) ) - { - // update level overview if level changed - ParseOverviewFile(); - LoadMapSprites(); - } - - memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities)); - - SetSpectatorStartPosition(); -} - -void CHudSpectator::InitHUDData() -{ - m_lastPrimaryObject = m_lastSecondaryObject = 0; - m_flNextObserverInput = 0.0f; - m_lastHudMessage = 0; - m_iSpectatorNumber = 0; - iJumpSpectator = 0; - g_iUser1 = g_iUser2 = 0; - - memset( &m_OverviewData, 0, sizeof(m_OverviewData)); - memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities)); - - if ( gEngfuncs.IsSpectateOnly() || gEngfuncs.pDemoAPI->IsPlayingback() ) - m_autoDirector->value = 1.0f; - else - m_autoDirector->value = 0.0f; - - Reset(); - - SetModes( OBS_CHASE_FREE, INSET_OFF ); - - g_iUser2 = 0; // fake not target until first camera command - - // reset HUD FOV - gHUD.m_iFOV = CVAR_GET_FLOAT("default_fov"); -} - -int CHudSpectator::MsgFunc_Spectator(const char *pszName, int iSize, void *buf) -{ - return 1; -} +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "hud.h" +#include "cl_util.h" +#include +#include "cl_entity.h" +#include "triangleapi.h" +#include "hltv.h" + +#include "pm_shared.h" +#include "pm_defs.h" +#include "pmtrace.h" +#include "parsemsg.h" +#include "entity_types.h" + +// these are included for the math functions +#include "com_model.h" +#include "demo_api.h" +#include "event_api.h" +#include "studio_util.h" +#include "screenfade.h" + +#pragma warning(disable: 4244) + +extern "C" int iJumpSpectator; +extern "C" float vJumpOrigin[3]; +extern "C" float vJumpAngles[3]; + + +extern void V_GetInEyePos(int entity, float * origin, float * angles ); +extern void V_ResetChaseCam(); +extern void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles); +extern void VectorAngles( const float *forward, float *angles ); +extern "C" void NormalizeAngles( float *angles ); +extern float * GetClientColor( int clientIndex ); + +extern vec3_t v_origin; // last view origin +extern vec3_t v_angles; // last view angle +extern vec3_t v_cl_angles; // last client/mouse angle +extern vec3_t v_sim_org; // last sim origin + +void SpectatorMode(void) +{ + + + if ( gEngfuncs.Cmd_Argc() <= 1 ) + { + gEngfuncs.Con_Printf( "usage: spec_mode
[]\n" ); + return; + } + + // SetModes() will decide if command is executed on server or local + if ( gEngfuncs.Cmd_Argc() == 2 ) + gHUD.m_Spectator.SetModes( atoi( gEngfuncs.Cmd_Argv(1) ), -1 ); + else if ( gEngfuncs.Cmd_Argc() == 3 ) + gHUD.m_Spectator.SetModes( atoi( gEngfuncs.Cmd_Argv(1) ), atoi( gEngfuncs.Cmd_Argv(2) ) ); +} + +void SpectatorSpray(void) +{ + vec3_t forward; + char string[128]; + + if ( !gEngfuncs.IsSpectateOnly() ) + return; + + AngleVectors(v_angles,forward,NULL,NULL); + VectorScale(forward, 128, forward); + VectorAdd(forward, v_origin, forward); + pmtrace_t * trace = gEngfuncs.PM_TraceLine( v_origin, forward, PM_TRACELINE_PHYSENTSONLY, 2, -1 ); + if ( trace->fraction != 1.0 ) + { + sprintf(string, "drc_spray %.2f %.2f %.2f %i", + trace->endpos[0], trace->endpos[1], trace->endpos[2], trace->ent ); + gEngfuncs.pfnServerCmd(string); + } + +} +void SpectatorHelp(void) +{ + /*if ( gViewPort ) + { + gViewPort->ShowVGUIMenu( MENU_SPECHELP ); + } + else*/ + { + char *text = CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help_Text" ); + + if ( text ) + { + while ( *text ) + { + if ( *text != 13 ) + gEngfuncs.Con_Printf( "%c", *text ); + text++; + } + } + } +} + +void SpectatorMenu( void ) +{ + if ( gEngfuncs.Cmd_Argc() <= 1 ) + { + gEngfuncs.Con_Printf( "usage: spec_menu <0|1>\n" ); + return; + } + + //gViewPort->m_pSpectatorPanel->ShowMenu( atoi( gEngfuncs.Cmd_Argv(1))!=0 ); +} + +void ToggleScores( void ) +{ + /*if ( gViewPort ) + { + if (gViewPort->IsScoreBoardVisible() ) + { + gViewPort->HideScoreBoard(); + } + else + { + gViewPort->ShowScoreBoard(); + } + }*/ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CHudSpectator::Init() +{ + gHUD.AddHudElem(this); + + m_iFlags |= HUD_ACTIVE; + m_flNextObserverInput = 0.0f; + m_zoomDelta = 0.0f; + m_moveDelta = 0.0f; + m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0); + iJumpSpectator = 0; + + memset( &m_OverviewData, 0, sizeof(m_OverviewData)); + memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities)); + m_lastPrimaryObject = m_lastSecondaryObject = 0; + + gEngfuncs.pfnAddCommand ("spec_mode", SpectatorMode ); + gEngfuncs.pfnAddCommand ("spec_decal", SpectatorSpray ); + gEngfuncs.pfnAddCommand ("spec_help", SpectatorHelp ); + gEngfuncs.pfnAddCommand ("spec_menu", SpectatorMenu ); + gEngfuncs.pfnAddCommand ("togglescores", ToggleScores ); + + m_drawnames = gEngfuncs.pfnRegisterVariable("spec_drawnames_internal","1",0); + m_specmode = gEngfuncs.pfnRegisterVariable("spec_mode_internal","1",0); + m_drawcone = gEngfuncs.pfnRegisterVariable("spec_drawcone_internal","1",0); + m_drawstatus = gEngfuncs.pfnRegisterVariable("spec_drawstatus_internal","1",0); + m_autoDirector = gEngfuncs.pfnRegisterVariable("spec_autodirector_internal","1",0); + m_pip = gEngfuncs.pfnRegisterVariable("spec_pip","1",0); + m_lastAutoDirector = 0.0f; + + if ( !m_drawnames || !m_drawcone || !m_drawstatus || !m_autoDirector || !m_pip) + { + gEngfuncs.Con_Printf("ERROR! Couldn't register all spectator variables.\n"); + return 0; + } + + return 1; +} + + +//----------------------------------------------------------------------------- +// UTIL_StringToVector originally from ..\dlls\util.cpp, slightly changed +//----------------------------------------------------------------------------- + +void UTIL_StringToVector( float * pVector, const char *pString ) +{ + char *pstr, *pfront, tempString[128]; + int j; + + strncpy( tempString, pString, sizeof(tempString) ); + pstr = pfront = tempString; + + for ( j = 0; j < 3; j++ ) + { + pVector[j] = atof( pfront ); + + while ( *pstr && *pstr != ' ' ) + pstr++; + if (!*pstr) + break; + pstr++; + pfront = pstr; + } + + if (j < 2) + { + for (j = j+1;j < 3; j++) + pVector[j] = 0; + } +} + +int UTIL_FindEntityInMap(char * name, float * origin, float * angle) +{ + int n,found = 0; + char keyname[256]; + char token[1024]; + + cl_entity_t * pEnt = gEngfuncs.GetEntityByIndex( 0 ); // get world model + + if ( !pEnt ) return 0; + + if ( !pEnt->model ) return 0; + + char * data = pEnt->model->entities; + + while (data) + { + data = gEngfuncs.COM_ParseFile(data, token); + + if ( (token[0] == '}') || (token[0]==0) ) + break; + + if (!data) + { + gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n"); + return 0; + } + + if (token[0] != '{') + { + gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: expected {\n"); + return 0; + } + + // we parse the first { now parse entities properties + + while ( 1 ) + { + // parse key + data = gEngfuncs.COM_ParseFile(data, token); + if (token[0] == '}') + break; // finish parsing this entity + + if (!data) + { + gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n"); + return 0; + }; + + strncpy (keyname, token, sizeof(keyname)); + + // another hack to fix keynames with trailing spaces + n = strlen(keyname); + while (n && keyname[n-1] == ' ') + { + keyname[n-1] = 0; + n--; + } + + // parse value + data = gEngfuncs.COM_ParseFile(data, token); + if (!data) + { + gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: EOF without closing brace\n"); + return 0; + }; + + if (token[0] == '}') + { + gEngfuncs.Con_DPrintf("UTIL_FindEntityInMap: closing brace without data"); + return 0; + } + + if (!strcmp(keyname,"classname")) + { + if (!strcmp(token, name )) + { + found = 1; // thats our entity + } + }; + + if( !strcmp( keyname, "angle" ) ) + { + float y = atof( token ); + + if (y >= 0) + { + angle[0] = 0.0f; + angle[1] = y; + } + else if ((int)y == -1) + { + angle[0] = -90.0f; + angle[1] = 0.0f;; + } + else + { + angle[0] = 90.0f; + angle[1] = 0.0f; + } + + angle[2] = 0.0f; + } + + if( !strcmp( keyname, "angles" ) ) + { + UTIL_StringToVector(angle, token); + } + + if (!strcmp(keyname,"origin")) + { + UTIL_StringToVector(origin, token); + + }; + + } // while (1) + + if (found) + return 1; + + } + + return 0; // we search all entities, but didn't found the correct + +} + +//----------------------------------------------------------------------------- +// SetSpectatorStartPosition(): +// Get valid map position and 'beam' spectator to this position +//----------------------------------------------------------------------------- + +void CHudSpectator::SetSpectatorStartPosition() +{ + // search for info_player start + if ( UTIL_FindEntityInMap( "trigger_camera", m_cameraOrigin, m_cameraAngles ) ) + iJumpSpectator = 1; + + else if ( UTIL_FindEntityInMap( "info_player_start", m_cameraOrigin, m_cameraAngles ) ) + iJumpSpectator = 1; + + else if ( UTIL_FindEntityInMap( "info_player_deathmatch", m_cameraOrigin, m_cameraAngles ) ) + iJumpSpectator = 1; + + else if ( UTIL_FindEntityInMap( "info_player_coop", m_cameraOrigin, m_cameraAngles ) ) + iJumpSpectator = 1; + else + { + static const Vector &nullvec = Vector (0.0, 0.0, 0.0); + // jump to 0,0,0 if no better position was found + VectorCopy(nullvec, m_cameraOrigin); + VectorCopy(nullvec, m_cameraAngles); + } + + VectorCopy(m_cameraOrigin, vJumpOrigin); + VectorCopy(m_cameraAngles, vJumpAngles); + + iJumpSpectator = 1; // jump anyway +} + +//----------------------------------------------------------------------------- +// Purpose: Loads new icons +//----------------------------------------------------------------------------- +int CHudSpectator::VidInit() +{ + m_hsprPlayer = SPR_Load("sprites/iplayer.spr"); + m_hsprPlayerBlue = SPR_Load("sprites/iplayerblue.spr"); + m_hsprPlayerRed = SPR_Load("sprites/iplayerred.spr"); + m_hsprPlayerDead = SPR_Load("sprites/iplayerdead.spr"); + m_hsprPlayerVIP = SPR_Load("sprites/iplayervip.spr"); + m_hsprPlayerC4 = SPR_Load("sprites/iplayerc4.spr"); + m_hsprUnkownMap = SPR_Load("sprites/tile.spr"); + m_hsprBeam = SPR_Load("sprites/laserbeam.spr"); + m_hsprCamera = SPR_Load("sprites/camera.spr"); + m_hsprBomb = SPR_Load("sprites/ic4.spr"); + m_hsprBackpack = SPR_Load("sprites/ibackpack.spr"); + m_hsprHostage = SPR_Load("sprites/ihostage.spr"); + m_hCrosshair = SPR_Load("sprites/crosshairs.spr"); + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flTime - +// intermission - +//----------------------------------------------------------------------------- +int CHudSpectator::Draw(float flTime) +{ + int lx; + + char string[256]; + float * color; + + // draw only in spectator mode + if ( !g_iUser1 ) + return 0; + + + if ( m_lastAutoDirector != m_autoDirector->value ) + { + m_lastAutoDirector = m_autoDirector->value; + char cmd[64]; + snprintf(cmd, sizeof(cmd), "spec_set_ad %f", m_autoDirector->value); + gEngfuncs.pfnClientCmd(cmd); + if ( m_lastAutoDirector == 0.0 ) + { + if ( m_lastAutoDirector == 0.0 && g_iUser1 == OBS_CHASE_LOCKED ) + { + SetModes(OBS_CHASE_FREE, INSET_OFF); + } + } + else if ( g_iUser1 == OBS_CHASE_FREE ) + { + SetModes(OBS_CHASE_LOCKED, INSET_OFF); + } + } + + // if user pressed zoom, aplly changes + if ( (m_zoomDelta != 0.0f) && ( g_iUser1 == OBS_MAP_FREE ) ) + { + m_mapZoom += m_zoomDelta; + + if ( m_mapZoom > 3.0f ) + m_mapZoom = 3.0f; + + if ( m_mapZoom < 0.5f ) + m_mapZoom = 0.5f; + } + + // if user moves in map mode, change map origin + if ( (m_moveDelta != 0.0f) && (g_iUser1 != OBS_ROAMING) ) + { + vec3_t right; + AngleVectors(v_angles, NULL, right, NULL); + VectorNormalize(right); + VectorScale(right, m_moveDelta, right ); + + VectorAdd( m_mapOrigin, right, m_mapOrigin ) + + } + + // Only draw the icon names only if map mode is in Main Mode + if ( g_iUser1 < OBS_MAP_FREE ) + return 1; + + if ( !m_drawnames->value ) + return 1; + + // make sure we have player info + //gViewPort->GetAllPlayersInfo(); + gHUD.m_Scoreboard.GetAllPlayersInfo(); + + + // loop through all the players and draw additional infos to their sprites on the map + for (int i = 0; i < MAX_PLAYERS; i++) + { + + if ( m_vPlayerPos[i][2]<0 ) // marked as invisible ? + continue; + + // can player exist without name? + if( !g_PlayerInfoList[i+1].name ) + continue; + + // check if name would be in inset window + if ( m_pip->value != INSET_OFF ) + { + if ( m_vPlayerPos[i][0] > XRES( m_OverviewData.insetWindowX ) && + m_vPlayerPos[i][1] > YRES( m_OverviewData.insetWindowY ) && + m_vPlayerPos[i][0] < XRES( m_OverviewData.insetWindowX + m_OverviewData.insetWindowWidth ) && + m_vPlayerPos[i][1] < YRES( m_OverviewData.insetWindowY + m_OverviewData.insetWindowHeight) + ) continue; + } + + color = GetClientColor( i+1 ); // ??? + + // draw the players name and health underneath + sprintf(string, "%s", g_PlayerInfoList[i+1].name ); + + lx = strlen(string)*3; // 3 is avg. character length :) + + DrawUtils::SetConsoleTextColor( color[0], color[1], color[2] ); + DrawUtils::DrawConsoleString( m_vPlayerPos[i][0]-lx,m_vPlayerPos[i][1], string); + + } + + + // Only draw the overview if Map Mode is selected for this view + if ( m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) ) ) + return 1; + + if ( m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE ) + return 1; + + return 1; +} + + +void CHudSpectator::DirectorMessage( int iSize, void *pbuf ) +{ + float value; + char * string; + + BEGIN_READ( pbuf, iSize ); + + int cmd = READ_BYTE(); + + switch ( cmd ) // director command byte + { + case DRC_CMD_START : + // now we have to do some things clientside, since the proxy doesn't know our mod + g_iPlayerClass = 0; + g_iTeamNumber = 0; + + // fake a InitHUD & ResetHUD message + gHUD.MsgFunc_InitHUD(NULL,0, NULL); + gHUD.MsgFunc_ResetHUD(NULL, 0, NULL); + + break; + + case DRC_CMD_EVENT : + m_lastPrimaryObject = READ_WORD(); + m_lastSecondaryObject = READ_WORD(); + m_iObserverFlags = READ_LONG(); + + if ( m_autoDirector->value ) + { + if ( (g_iUser2 != m_lastPrimaryObject) || (g_iUser3 != m_lastSecondaryObject) ) + V_ResetChaseCam(); + + g_iUser2 = m_lastPrimaryObject; + g_iUser3 = m_lastSecondaryObject; + } + + // gEngfuncs.Con_Printf("Director Camera: %i %i\n", firstObject, secondObject); + break; + + case DRC_CMD_MODE : + if ( m_autoDirector->value ) + { + SetModes( READ_BYTE(), -1 ); + } + break; + + case DRC_CMD_CAMERA : + if ( m_autoDirector->value ) + { + vJumpOrigin[0] = READ_COORD(); // position + vJumpOrigin[1] = READ_COORD(); + vJumpOrigin[2] = READ_COORD(); + + vJumpAngles[0] = READ_COORD(); // view angle + vJumpAngles[1] = READ_COORD(); + vJumpAngles[2] = READ_COORD(); + + gEngfuncs.SetViewAngles( vJumpAngles ); + + iJumpSpectator = 1; + } + break; + + case DRC_CMD_MESSAGE: + { + client_textmessage_t * msg = &m_HUDMessages[m_lastHudMessage]; + + msg->effect = READ_BYTE(); // effect + + DrawUtils::UnpackRGB( (int&)msg->r1, (int&)msg->g1, (int&)msg->b1, READ_LONG() ); // color + msg->r2 = msg->r1; + msg->g2 = msg->g1; + msg->b2 = msg->b1; + msg->a2 = msg->a1 = 0xFF; // not transparent + + msg->x = READ_FLOAT(); // x pos + msg->y = READ_FLOAT(); // y pos + + msg->fadein = READ_FLOAT(); // fadein + msg->fadeout = READ_FLOAT(); // fadeout + msg->holdtime = READ_FLOAT(); // holdtime + msg->fxtime = READ_FLOAT(); // fxtime; + + strncpy( m_HUDMessageText[m_lastHudMessage], READ_STRING(), 128 ); + m_HUDMessageText[m_lastHudMessage][127]=0; // text + + msg->pMessage = m_HUDMessageText[m_lastHudMessage]; + msg->pName = "HUD_MESSAGE"; + + gHUD.m_Message.MessageAdd( msg ); + + m_lastHudMessage++; + m_lastHudMessage %= MAX_SPEC_HUD_MESSAGES; + + } + + break; + + case DRC_CMD_SOUND : + string = READ_STRING(); + value = READ_FLOAT(); + + // gEngfuncs.Con_Printf("DRC_CMD_FX_SOUND: %s %.2f\n", string, value ); + gEngfuncs.pEventAPI->EV_PlaySound(0, v_origin, CHAN_BODY, string, value, ATTN_NORM, 0, PITCH_NORM ); + + break; + + case DRC_CMD_TIMESCALE : + value = READ_FLOAT(); + break; + + + + case DRC_CMD_STATUS: + READ_LONG(); // total number of spectator slots + m_iSpectatorNumber = READ_LONG(); // total number of spectator + READ_WORD(); // total number of relay proxies + + //gViewPort->UpdateSpectatorPanel(); + break; + + case DRC_CMD_BANNER: + // gEngfuncs.Con_DPrintf("GUI: Banner %s\n",READ_STRING() ); // name of banner tga eg gfx/temp/7454562234563475.tga + //gViewPort->m_pSpectatorPanel->m_TopBanner->LoadImage( READ_STRING() ); + //gViewPort->UpdateSpectatorPanel(); + break; + + /*case DRC_CMD_FADE: + break;*/ + + case DRC_CMD_STUFFTEXT: + ClientCmd( READ_STRING() ); + break; + + default : gEngfuncs.Con_DPrintf("CHudSpectator::DirectorMessage: unknown command %i.\n", cmd ); + } +} + +void CHudSpectator::FindNextPlayer(bool bReverse) +{ + // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching + // only a subset of the players. e.g. Make it check the target's team. + + int iStart; + cl_entity_t * pEnt = NULL; + + // if we are NOT in HLTV mode, spectator targets are set on server + if ( !gEngfuncs.IsSpectateOnly() ) + { + char cmdstring[32]; + // forward command to server + sprintf(cmdstring,"follownext %i",bReverse?1:0); + gEngfuncs.pfnServerCmd(cmdstring); + return; + } + + if ( g_iUser2 ) + iStart = g_iUser2; + else + iStart = 1; + + g_iUser2 = 0; + + int iCurrent = iStart; + + int iDir = bReverse ? -1 : 1; + + // make sure we have player info + //gViewPort->GetAllPlayersInfo(); + gHUD.m_Scoreboard.GetAllPlayersInfo(); + + do + { + iCurrent += iDir; + + // Loop through the clients + if (iCurrent > MAX_PLAYERS) + iCurrent = 1; + if (iCurrent < 1) + iCurrent = MAX_PLAYERS; + + pEnt = gEngfuncs.GetEntityByIndex( iCurrent ); + + if ( !IsActivePlayer( pEnt ) ) + continue; + + // MOD AUTHORS: Add checks on target here. + + g_iUser2 = iCurrent; + break; + + } while ( iCurrent != iStart ); + + // Did we find a target? + if ( !g_iUser2 ) + { + gEngfuncs.Con_DPrintf( "No observer targets.\n" ); + // take save camera position + VectorCopy(m_cameraOrigin, vJumpOrigin); + VectorCopy(m_cameraAngles, vJumpAngles); + } + else + { + // use new entity position for roaming + VectorCopy ( pEnt->origin, vJumpOrigin ); + VectorCopy ( pEnt->angles, vJumpAngles ); + } + iJumpSpectator = 1; +} + +void CHudSpectator::HandleButtonsDown( int ButtonPressed ) +{ + double time = gEngfuncs.GetClientTime(); + + int newMainMode = g_iUser1; + int newInsetMode = m_pip->value; + + // gEngfuncs.Con_Printf(" HandleButtons:%i\n", ButtonPressed ); + // if ( !gViewPort ) + return; + + //Not in intermission. + if ( gHUD.m_iIntermission ) + return; + + if ( !g_iUser1 ) + return; // dont do anything if not in spectator mode + + // don't handle buttons during normal demo playback + if ( gEngfuncs.pDemoAPI->IsPlayingback() && !gEngfuncs.IsSpectateOnly() ) + return; + // Slow down mouse clicks. + if ( m_flNextObserverInput > time ) + return; + + // enable spectator screen + //if ( ButtonPressed & IN_DUCK ) + // gViewPort->m_pSpectatorPanel->ShowMenu(!gViewPort->m_pSpectatorPanel->m_menuVisible); + + // 'Use' changes inset window mode + if ( ButtonPressed & IN_USE ) + { + newInsetMode = ToggleInset(true); + } + + // if not in HLTV mode, buttons are handled server side + if ( gEngfuncs.IsSpectateOnly() ) + { + // changing target or chase mode not in overviewmode without inset window + + // Jump changes main window modes + if ( ButtonPressed & IN_JUMP ) + { + if ( g_iUser1 == OBS_CHASE_LOCKED ) + newMainMode = OBS_CHASE_FREE; + + else if ( g_iUser1 == OBS_CHASE_FREE ) + newMainMode = OBS_IN_EYE; + + else if ( g_iUser1 == OBS_IN_EYE ) + newMainMode = OBS_ROAMING; + + else if ( g_iUser1 == OBS_ROAMING ) + newMainMode = OBS_MAP_FREE; + + else if ( g_iUser1 == OBS_MAP_FREE ) + newMainMode = OBS_MAP_CHASE; + + else + newMainMode = OBS_CHASE_FREE; // don't use OBS_CHASE_LOCKED anymore + } + + // Attack moves to the next player + if ( ButtonPressed & (IN_ATTACK | IN_ATTACK2) ) + { + FindNextPlayer( (ButtonPressed & IN_ATTACK2) ? true:false ); + + if ( g_iUser1 == OBS_ROAMING ) + { + gEngfuncs.SetViewAngles( vJumpAngles ); + iJumpSpectator = 1; + + } + // lease directed mode if player want to see another player + m_autoDirector->value = 0.0f; + } + } + + SetModes(newMainMode, newInsetMode); + + if ( g_iUser1 == OBS_MAP_FREE ) + { + if ( ButtonPressed & IN_FORWARD ) + m_zoomDelta = 0.01f; + + if ( ButtonPressed & IN_BACK ) + m_zoomDelta = -0.01f; + + if ( ButtonPressed & IN_MOVELEFT ) + m_moveDelta = -12.0f; + + if ( ButtonPressed & IN_MOVERIGHT ) + m_moveDelta = 12.0f; + } + + m_flNextObserverInput = time + 0.2; +} + +void CHudSpectator::HandleButtonsUp( int ButtonPressed ) +{ + //if ( !gViewPort ) + return; + + // if ( !gViewPort->m_pSpectatorPanel->isVisible() ) + // return; // dont do anything if not in spectator mode + + if ( ButtonPressed & (IN_FORWARD | IN_BACK) ) + m_zoomDelta = 0.0f; + + if ( ButtonPressed & (IN_MOVELEFT | IN_MOVERIGHT) ) + m_moveDelta = 0.0f; +} + +void CHudSpectator::SetModes(int iNewMainMode, int iNewInsetMode) +{ + // if value == -1 keep old value + if ( iNewMainMode == -1 ) + iNewMainMode = g_iUser1; + + if ( iNewInsetMode == -1 ) + iNewInsetMode = m_pip->value; + + // inset mode is handled only clients side + m_pip->value = iNewInsetMode; + + if ( iNewMainMode < OBS_CHASE_LOCKED || iNewMainMode > OBS_MAP_CHASE ) + { + gEngfuncs.Con_Printf("Invalid spectator mode.\n"); + return; + } + + // main modes ettings will override inset window settings + if ( iNewMainMode != g_iUser1 ) + { + // if we are NOT in HLTV mode, main spectator mode is set on server + if ( !gEngfuncs.IsSpectateOnly() ) + { + return; + } + + if ( !g_iUser2 && (iNewMainMode !=OBS_ROAMING ) ) // make sure we have a target + { + // choose last Director object if still available + if ( IsActivePlayer( gEngfuncs.GetEntityByIndex( m_lastPrimaryObject ) ) ) + { + g_iUser2 = m_lastPrimaryObject; + g_iUser3 = m_lastSecondaryObject; + } + else + FindNextPlayer(false); // find any target + } + + switch ( iNewMainMode ) + { + case OBS_CHASE_LOCKED: g_iUser1 = OBS_CHASE_LOCKED; + break; + + case OBS_CHASE_FREE : g_iUser1 = OBS_CHASE_FREE; + break; + + case OBS_ROAMING : // jump to current vJumpOrigin/angle + g_iUser1 = OBS_ROAMING; + if ( g_iUser2 ) + { + V_GetChasePos( g_iUser2, v_cl_angles, vJumpOrigin, vJumpAngles ); + gEngfuncs.SetViewAngles( vJumpAngles ); + iJumpSpectator = 1; + } + break; + + case OBS_IN_EYE : g_iUser1 = OBS_IN_EYE; + break; + + case OBS_MAP_FREE : g_iUser1 = OBS_MAP_FREE; + // reset user values + m_mapZoom = m_OverviewData.zoom; + m_mapOrigin = m_OverviewData.origin; + break; + + case OBS_MAP_CHASE : g_iUser1 = OBS_MAP_CHASE; + // reset user values + m_mapZoom = m_OverviewData.zoom; + m_mapOrigin = m_OverviewData.origin; + break; + } + + if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) ) + { + m_crosshairRect.left = 24; + m_crosshairRect.top = 0; + m_crosshairRect.right = 48; + m_crosshairRect.bottom = 24; + + SetCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 ); + } + else + { + memset( &m_crosshairRect,0,sizeof(m_crosshairRect) ); + SetCrosshair( 0, m_crosshairRect, 0, 0, 0 ); + } + + char string[128]; + sprintf(string, "#Spec_Mode%d", g_iUser1 ); + sprintf(string, "%c%s", HUD_PRINTCENTER, CHudTextMessage::BufferedLocaliseTextString( string )); + gHUD.m_TextMessage.MsgFunc_TextMsg(NULL, strlen(string)+1, string ); + } + + //gViewPort->UpdateSpectatorPanel(); + +} + +bool CHudSpectator::IsActivePlayer(cl_entity_t * ent) +{ + return ( ent && + ent->player && + ent->curstate.solid != SOLID_NOT && + ent != gEngfuncs.GetLocalPlayer() && + g_PlayerInfoList[ent->index].name != NULL + ); +} + + +bool CHudSpectator::ParseOverviewFile( ) +{ + char filename[255]; + char levelname[255]; + char token[1024]; + float height; + + char *pfile = NULL; + + memset( &m_OverviewData, 0, sizeof(m_OverviewData)); + + // fill in standrd values + m_OverviewData.insetWindowX = 4; // upper left corner + m_OverviewData.insetWindowY = 4; + m_OverviewData.insetWindowHeight = 180; + m_OverviewData.insetWindowWidth = 240; + m_OverviewData.origin[0] = 0.0f; + m_OverviewData.origin[1] = 0.0f; + m_OverviewData.origin[2] = 0.0f; + m_OverviewData.zoom = 1.0f; + m_OverviewData.layers = 0; + m_OverviewData.layersHeights[0] = 0.0f; + strncpy( m_OverviewData.map, gEngfuncs.pfnGetLevelName(), sizeof(m_OverviewData.map) ); + + if ( strlen( m_OverviewData.map ) == 0 ) + return false; // not active yet + + strncpy(levelname, m_OverviewData.map + 5, sizeof( levelname )); + levelname[strlen(levelname)-4] = 0; + + sprintf(filename, "overviews/%s.txt", levelname ); + + pfile = (char *)gEngfuncs.COM_LoadFile( filename, 5, NULL); + + if (!pfile) + { + gEngfuncs.Con_Printf("Couldn't open file %s. Using default values for overiew mode.\n", filename ); + return false; + } + + + while (true) + { + pfile = gEngfuncs.COM_ParseFile(pfile, token); + + if (!pfile) + break; + + if ( !stricmp( token, "global" ) ) + { + // parse the global data + pfile = gEngfuncs.COM_ParseFile(pfile, token); + if ( stricmp( token, "{" ) ) + { + gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename ); + return false; + } + + pfile = gEngfuncs.COM_ParseFile(pfile,token); + + while (stricmp( token, "}") ) + { + if ( !stricmp( token, "zoom" ) ) + { + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.zoom = atof( token ); + } + else if ( !stricmp( token, "origin" ) ) + { + pfile = gEngfuncs.COM_ParseFile(pfile, token); + m_OverviewData.origin[0] = atof( token ); + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.origin[1] = atof( token ); + pfile = gEngfuncs.COM_ParseFile(pfile, token); + m_OverviewData.origin[2] = atof( token ); + } + else if ( !stricmp( token, "rotated" ) ) + { + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.rotated = atoi( token ); + } + else if ( !stricmp( token, "inset" ) ) + { + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.insetWindowX = atof( token ); + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.insetWindowY = atof( token ); + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.insetWindowWidth = atof( token ); + pfile = gEngfuncs.COM_ParseFile(pfile,token); + m_OverviewData.insetWindowHeight = atof( token ); + + } + else + { + gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token ); + return false; + } + + pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token + + } + } + else if ( !stricmp( token, "layer" ) ) + { + // parse a layer data + + if ( m_OverviewData.layers == OVERVIEW_MAX_LAYERS ) + { + gEngfuncs.Con_Printf("Error parsing overview file %s. ( too many layers )\n", filename ); + return false; + } + + pfile = gEngfuncs.COM_ParseFile(pfile,token); + + + if ( stricmp( token, "{" ) ) + { + gEngfuncs.Con_Printf("Error parsing overview file %s. (expected { )\n", filename ); + return false; + } + + pfile = gEngfuncs.COM_ParseFile(pfile,token); + + while (stricmp( token, "}") ) + { + if ( !stricmp( token, "image" ) ) + { + pfile = gEngfuncs.COM_ParseFile(pfile,token); + strncpy(m_OverviewData.layersImages[ m_OverviewData.layers ], token, 255); + + + } + else if ( !stricmp( token, "height" ) ) + { + pfile = gEngfuncs.COM_ParseFile(pfile,token); + height = atof(token); + m_OverviewData.layersHeights[ m_OverviewData.layers ] = height; + } + else + { + gEngfuncs.Con_Printf("Error parsing overview file %s. (%s unkown)\n", filename, token ); + return false; + } + + pfile = gEngfuncs.COM_ParseFile(pfile,token); // parse next token + } + + m_OverviewData.layers++; + + } + } + + gEngfuncs.COM_FreeFile( pfile ); + + m_mapZoom = m_OverviewData.zoom; + m_mapOrigin = m_OverviewData.origin; + + return true; + +} + +void CHudSpectator::LoadMapSprites() +{ + // right now only support for one map layer + if (m_OverviewData.layers > 0 ) + { + m_MapSprite = gEngfuncs.LoadMapSprite( m_OverviewData.layersImages[0] ); + } + else + m_MapSprite = NULL; // the standard "unkown map" sprite will be used instead +} + +void CHudSpectator::DrawOverviewLayer() +{ + float screenaspect, xs, ys, xStep, yStep, x,y,z; + int ix,iy,i,xTiles,yTiles,frame; + + qboolean hasMapImage = m_MapSprite?TRUE:FALSE; + model_t * dummySprite = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprUnkownMap); + + if ( hasMapImage) + { + i = m_MapSprite->numframes / (4*3); + i = sqrt(i); + xTiles = i*4; + yTiles = i*3; + } + else + { + xTiles = 8; + yTiles = 6; + } + + + screenaspect = 4.0f/3.0f; + + + xs = m_OverviewData.origin[0]; + ys = m_OverviewData.origin[1]; + z = ( 90.0f - v_angles[0] ) / 90.0f; + z *= m_OverviewData.layersHeights[0]; // gOverviewData.z_min - 32; + + // i = r_overviewTexture + ( layer*OVERVIEW_X_TILES*OVERVIEW_Y_TILES ); + gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture ); + gEngfuncs.pTriAPI->CullFace( TRI_NONE ); + gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 ); + frame = 0; + + // rotated view ? + if ( m_OverviewData.rotated ) + { + xStep = (2*4096.0f / m_OverviewData.zoom ) / xTiles; + yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles; + + y = ys + (4096.0f / (m_OverviewData.zoom * screenaspect)); + + for (iy = 0; iy < yTiles; iy++) + { + x = xs - (4096.0f / (m_OverviewData.zoom)); + + for (ix = 0; ix < xTiles; ix++) + { + if (hasMapImage) + gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame ); + else + gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 ); + + gEngfuncs.pTriAPI->Begin( TRI_QUADS ); + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + gEngfuncs.pTriAPI->Vertex3f (x, y, z); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); + gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z); + gEngfuncs.pTriAPI->End(); + + frame++; + x+= xStep; + } + + y+=yStep; + } + } + else + { + xStep = -(2*4096.0f / m_OverviewData.zoom ) / xTiles; + yStep = -(2*4096.0f / (m_OverviewData.zoom* screenaspect) ) / yTiles; + + + x = xs + (4096.0f / (m_OverviewData.zoom * screenaspect )); + + + + for (ix = 0; ix < yTiles; ix++) + { + + y = ys + (4096.0f / (m_OverviewData.zoom)); + + for (iy = 0; iy < xTiles; iy++) + { + if (hasMapImage) + gEngfuncs.pTriAPI->SpriteTexture( m_MapSprite, frame ); + else + gEngfuncs.pTriAPI->SpriteTexture( dummySprite, 0 ); + + gEngfuncs.pTriAPI->Begin( TRI_QUADS ); + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + gEngfuncs.pTriAPI->Vertex3f (x, y, z); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x+xStep ,y, z); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x+xStep, y+yStep, z); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); + gEngfuncs.pTriAPI->Vertex3f (x, y+yStep, z); + gEngfuncs.pTriAPI->End(); + + frame++; + + y+=yStep; + } + + x+= xStep; + + } + } +} + +void CHudSpectator::DrawOverviewEntities() +{ + int i,ir,ig,ib; + struct model_s *hSpriteModel; + vec3_t origin, angles, point, forward, right, left, up, world, screen, offset; + float x,y,z, r,g,b, sizeScale = 4.0f; + cl_entity_t * ent; + float rmatrix[3][4]; // transformation matrix + + float zScale = (90.0f - v_angles[0] ) / 90.0f; + + + z = m_OverviewData.layersHeights[0] * zScale; + // get yellow/brown HUD color + DrawUtils::UnpackRGB(ir,ig,ib, RGB_YELLOWISH); + r = (float)ir/255.0f; + g = (float)ig/255.0f; + b = (float)ib/255.0f; + + gEngfuncs.pTriAPI->CullFace( TRI_NONE ); + + for (i=0; i < MAX_PLAYERS; i++ ) + m_vPlayerPos[i][2] = -1; // mark as invisible + + // draw all players + for (i=0 ; i < MAX_OVERVIEW_ENTITIES ; i++) + { + if ( !m_OverviewEntities[i].hSprite ) + continue; + + hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_OverviewEntities[i].hSprite ); + ent = m_OverviewEntities[i].entity; + + gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 ); + gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture ); + + // see R_DrawSpriteModel + // draws players sprite + + AngleVectors(ent->angles, right, up, NULL ); + + VectorCopy(ent->origin,origin); + + gEngfuncs.pTriAPI->Begin( TRI_QUADS ); + + gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, 1.0 ); + + gEngfuncs.pTriAPI->TexCoord2f (1, 0); + VectorMA (origin, 16.0f * sizeScale, up, point); + VectorMA (point, 16.0f * sizeScale, right, point); + point[2] *= zScale; + gEngfuncs.pTriAPI->Vertex3fv (point); + + gEngfuncs.pTriAPI->TexCoord2f (0, 0); + + VectorMA (origin, 16.0f * sizeScale, up, point); + VectorMA (point, -16.0f * sizeScale, right, point); + point[2] *= zScale; + gEngfuncs.pTriAPI->Vertex3fv (point); + + gEngfuncs.pTriAPI->TexCoord2f (0,1); + VectorMA (origin, -16.0f * sizeScale, up, point); + VectorMA (point, -16.0f * sizeScale, right, point); + point[2] *= zScale; + gEngfuncs.pTriAPI->Vertex3fv (point); + + gEngfuncs.pTriAPI->TexCoord2f (1,1); + VectorMA (origin, -16.0f * sizeScale, up, point); + VectorMA (point, 16.0f * sizeScale, right, point); + point[2] *= zScale; + gEngfuncs.pTriAPI->Vertex3fv (point); + + gEngfuncs.pTriAPI->End (); + + + if ( !ent->player) + continue; + // draw line under player icons + origin[2] *= zScale; + + gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); + + hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprBeam ); + gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 ); + + gEngfuncs.pTriAPI->Color4f(r, g, b, 0.3); + + gEngfuncs.pTriAPI->Begin ( TRI_QUADS ); + gEngfuncs.pTriAPI->TexCoord2f (1, 0); + gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4, origin[2]-zScale); + gEngfuncs.pTriAPI->TexCoord2f (0, 0); + gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4, origin[2]-zScale); + gEngfuncs.pTriAPI->TexCoord2f (0, 1); + gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]-4,z); + gEngfuncs.pTriAPI->TexCoord2f (1, 1); + gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]+4,z); + gEngfuncs.pTriAPI->End (); + + gEngfuncs.pTriAPI->Begin ( TRI_QUADS ); + gEngfuncs.pTriAPI->TexCoord2f (1, 0); + gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4, origin[2]-zScale); + gEngfuncs.pTriAPI->TexCoord2f (0, 0); + gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4, origin[2]-zScale); + gEngfuncs.pTriAPI->TexCoord2f (0, 1); + gEngfuncs.pTriAPI->Vertex3f (origin[0]+4, origin[1]-4,z); + gEngfuncs.pTriAPI->TexCoord2f (1, 1); + gEngfuncs.pTriAPI->Vertex3f (origin[0]-4, origin[1]+4,z); + gEngfuncs.pTriAPI->End (); + + // calculate screen position for name and infromation in hud::draw() + if ( gEngfuncs.pTriAPI->WorldToScreen(origin,screen) ) + continue; // object is behind viewer + + screen[0] = XPROJECT(screen[0]); + screen[1] = YPROJECT(screen[1]); + screen[2] = 0.0f; + + // calculate some offset under the icon + origin[0]+=32.0f; + origin[1]+=32.0f; + + gEngfuncs.pTriAPI->WorldToScreen(origin,offset); + + offset[0] = XPROJECT(offset[0]); + offset[1] = YPROJECT(offset[1]); + offset[2] = 0.0f; + + VectorSubtract(offset, screen, offset ); + + int playerNum = ent->index - 1; + + m_vPlayerPos[playerNum][0] = screen[0]; + m_vPlayerPos[playerNum][1] = screen[1] + Length(offset); + m_vPlayerPos[playerNum][2] = 1; // mark player as visible + } + + if ( !m_pip->value || !m_drawcone->value ) + return; + + // get current camera position and angle + + if ( m_pip->value == INSET_IN_EYE || g_iUser1 == OBS_IN_EYE ) + { + V_GetInEyePos( g_iUser2, origin, angles ); + } + else if ( m_pip->value == INSET_CHASE_FREE || g_iUser1 == OBS_CHASE_FREE ) + { + V_GetChasePos( g_iUser2, v_cl_angles, origin, angles ); + } + else if ( g_iUser1 == OBS_ROAMING ) + { + VectorCopy( v_sim_org, origin ); + VectorCopy( v_cl_angles, angles ); + } + else + V_GetChasePos( g_iUser2, NULL, origin, angles ); + + + // draw camera sprite + + x = origin[0]; + y = origin[1]; + z = origin[2]; + + angles[0] = 0; // always show horizontal camera sprite + + hSpriteModel = (struct model_s *)gEngfuncs.GetSpritePointer( m_hsprCamera ); + gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); + gEngfuncs.pTriAPI->SpriteTexture( hSpriteModel, 0 ); + + + gEngfuncs.pTriAPI->Color4f( r, g, b, 1.0 ); + + AngleVectors(angles, forward, NULL, NULL ); + VectorScale (forward, 512.0f, forward); + + offset[0] = 0.0f; + offset[1] = 45.0f; + offset[2] = 0.0f; + + AngleMatrix(offset, rmatrix ); + VectorTransform(forward, rmatrix , right ); + + offset[1]= -45.0f; + AngleMatrix(offset, rmatrix ); + VectorTransform(forward, rmatrix , left ); + + gEngfuncs.pTriAPI->Begin (TRI_TRIANGLES); + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + gEngfuncs.pTriAPI->Vertex3f (x+right[0], y+right[1], (z+right[2]) * zScale); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x, y, z * zScale); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x+left[0], y+left[1], (z+left[2]) * zScale); + gEngfuncs.pTriAPI->End (); + +} + + + +void CHudSpectator::DrawOverview() +{ + static bool glClearForce = false; + static float old_glClearValue; + + // draw only in sepctator mode + if ( !g_iUser1 || (m_iDrawCycle == 0 && ( (g_iUser1 != OBS_MAP_FREE) && (g_iUser1 != OBS_MAP_CHASE) )) || (m_iDrawCycle == 1 && m_pip->value < INSET_MAP_FREE) ) + { + // fix non clearing background for overview + if( glClearForce ) + { + gEngfuncs.Cvar_SetValue("gl_clear", old_glClearValue ); + glClearForce = false; + } + return; + } + + // fix non clearing background for overview + if( !glClearForce ) + { + old_glClearValue = CVAR_GET_FLOAT("gl_clear"); + gEngfuncs.Cvar_Set("gl_clear", "1"); + glClearForce = true; + } + + DrawOverviewLayer(); + DrawOverviewEntities(); + CheckOverviewEntities(); +} +void CHudSpectator::CheckOverviewEntities() +{ + double time = gEngfuncs.GetClientTime(); + + // removes old entities from list + for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ ) + { + // remove entity from list if it is too old + if ( m_OverviewEntities[i].killTime < time ) + { + memset( &m_OverviewEntities[i], 0, sizeof (overviewEntity_t) ); + } + } +} + +bool CHudSpectator::AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname) +{ + HSPRITE hSprite = 0; + double duration = -1.0f; // duration -1 means show it only this frame; + + if ( !ent ) + return false; + + if ( type == ET_PLAYER ) + { + if ( ent->curstate.solid != SOLID_NOT) + { + switch ( g_PlayerExtraInfo[ent->index].teamnumber ) + { + // blue and red teams are swapped in CS and TFC + case TEAM_TERRORIST: hSprite = m_hsprPlayerRed; break; + case TEAM_CT: hSprite = m_hsprPlayerBlue; break; + default: hSprite = m_hsprPlayer; break; + } + + if( g_PlayerExtraInfo[ent->index].has_c4 ) + hSprite = m_hsprPlayerC4; + else if( g_PlayerExtraInfo[ent->index].vip ) + hSprite = m_hsprPlayerVIP; + + return AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration ); + } + else + return false; // it's an spectator + } + /*else if (type == ET_NORMAL) + { + return false; + } + else + { + else return false; + }*/ + + if( !stricmp( modelname, "models/w_c4.mdl" )) + hSprite = m_hsprBomb; + else if( !stricmp( modelname, "models/w_backpack.mdl" )) + hSprite = m_hsprBackpack; + else if( strstr( modelname, "models/hostage") || strstr( modelname, "models/scientist")) + hSprite = m_hsprHostage; + else return false; + + return AddOverviewEntityToList(hSprite, ent, gEngfuncs.GetClientTime() + duration ); +} + +void CHudSpectator::DeathMessage(int victim) +{ + // find out where the victim is + cl_entity_t *pl = gEngfuncs.GetEntityByIndex(victim); + + if (pl && pl->player) + AddOverviewEntityToList(m_hsprPlayerDead, pl, gEngfuncs.GetClientTime() + 2.0f ); +} + +bool CHudSpectator::AddOverviewEntityToList(HSPRITE sprite, cl_entity_t *ent, double killTime) +{ + for ( int i = 0; i< MAX_OVERVIEW_ENTITIES; i++ ) + { + // find empty entity slot + if ( m_OverviewEntities[i].entity == NULL) + { + m_OverviewEntities[i].entity = ent; + m_OverviewEntities[i].hSprite = sprite; + m_OverviewEntities[i].killTime = killTime; + return true; + } + } + + return false; // maximum overview entities reached +} +void CHudSpectator::CheckSettings() +{ + // disallow same inset mode as main mode: + + m_pip->value = (int)m_pip->value; + + if ( ( g_iUser1 < OBS_MAP_FREE ) && ( m_pip->value == INSET_CHASE_FREE || m_pip->value == INSET_IN_EYE ) ) + { + // otherwise both would show in World picures + m_pip->value = INSET_MAP_FREE; + } + + if ( ( g_iUser1 >= OBS_MAP_FREE ) && ( m_pip->value >= INSET_MAP_FREE ) ) + { + // both would show map views + m_pip->value = INSET_CHASE_FREE; + } + + // disble in intermission screen + if ( gHUD.m_iIntermission ) + m_pip->value = INSET_OFF; + + // check chat mode + if ( m_chatEnabled != (gHUD.m_SayText.m_HUD_saytext->value!=0) ) + { + // hud_saytext changed + m_chatEnabled = (gHUD.m_SayText.m_HUD_saytext->value!=0); + + if ( gEngfuncs.IsSpectateOnly() ) + { + // tell proxy our new chat mode + char chatcmd[32]; + sprintf(chatcmd, "ignoremsg %i", m_chatEnabled?0:1 ); + gEngfuncs.pfnServerCmd(chatcmd); + } + } + + // HL/TFC has no oberserver corsshair, so set it client side + if ( (g_iUser1 == OBS_IN_EYE) || (g_iUser1 == OBS_ROAMING) ) + { + m_crosshairRect.left = 24; + m_crosshairRect.top = 0; + m_crosshairRect.right = 48; + m_crosshairRect.bottom = 24; + + SetCrosshair( m_hCrosshair, m_crosshairRect, 255, 255, 255 ); + } + else + { + memset( &m_crosshairRect,0,sizeof(m_crosshairRect) ); + SetCrosshair( 0, m_crosshairRect, 0, 0, 0 ); + } + + + + // if we are a real player on server don't allow inset window + // in First Person mode since this is our resticted forcecamera mode 2 + // team number 3 = SPECTATOR see player.h + + if ( ( (g_iTeamNumber == 1) || (g_iTeamNumber == 2)) && (g_iUser1 == OBS_IN_EYE) ) + m_pip->value = INSET_OFF; + + // draw small border around inset view, adjust upper black bar + // gViewPort->m_pSpectatorPanel->EnableInsetView( m_pip->value != INSET_OFF ); +} + +int CHudSpectator::ToggleInset(bool allowOff) +{ + int newInsetMode = (int)m_pip->value + 1; + + if ( g_iUser1 < OBS_MAP_FREE ) + { + if ( newInsetMode > INSET_MAP_CHASE ) + { + if (allowOff) + newInsetMode = INSET_OFF; + else + newInsetMode = INSET_MAP_FREE; + } + + if ( newInsetMode == INSET_CHASE_FREE ) + newInsetMode = INSET_MAP_FREE; + } + else + { + if ( newInsetMode > INSET_IN_EYE ) + { + if (allowOff) + newInsetMode = INSET_OFF; + else + newInsetMode = INSET_CHASE_FREE; + } + } + + return newInsetMode; +} +void CHudSpectator::Reset() +{ + // Reset HUD + if ( strcmp( m_OverviewData.map, gEngfuncs.pfnGetLevelName() ) ) + { + // update level overview if level changed + ParseOverviewFile(); + LoadMapSprites(); + } + + memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities)); + + SetSpectatorStartPosition(); +} + +void CHudSpectator::InitHUDData() +{ + m_lastPrimaryObject = m_lastSecondaryObject = 0; + m_flNextObserverInput = 0.0f; + m_lastHudMessage = 0; + m_iSpectatorNumber = 0; + iJumpSpectator = 0; + g_iUser1 = g_iUser2 = 0; + + memset( &m_OverviewData, 0, sizeof(m_OverviewData)); + memset( &m_OverviewEntities, 0, sizeof(m_OverviewEntities)); + + if ( gEngfuncs.IsSpectateOnly() || gEngfuncs.pDemoAPI->IsPlayingback() ) + m_autoDirector->value = 1.0f; + else + m_autoDirector->value = 0.0f; + + Reset(); + + SetModes( OBS_CHASE_FREE, INSET_OFF ); + + g_iUser2 = 0; // fake not target until first camera command + + // reset HUD FOV + gHUD.m_iFOV = CVAR_GET_FLOAT("default_fov"); +} + +int CHudSpectator::MsgFunc_Spectator(const char *pszName, int iSize, void *buf) +{ + return 1; +} diff --git a/cl_dll/hud/hud_update.cpp b/cl_dll/hud/hud_update.cpp index b3da672..9facc8c 100644 --- a/cl_dll/hud/hud_update.cpp +++ b/cl_dll/hud/hud_update.cpp @@ -1,54 +1,54 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// hud_update.cpp -// - -#include -#include "hud.h" -#include "cl_util.h" -#include -#include - -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 = CL_ButtonBits( 0 ); - m_iWeaponBits = cdata->iWeaponBits; - - in_fov = cdata->fov; - - Think(); - - cdata->fov = m_iFOV; - - v_idlescale = m_iConcussionEffect; - - CL_ResetButtonBits( m_iKeyBits ); - - // return 1 if in anything in the client_data struct has been changed, 0 otherwise - return 1; -} - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// hud_update.cpp +// + +#include +#include "hud.h" +#include "cl_util.h" +#include +#include + +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 = CL_ButtonBits( 0 ); + m_iWeaponBits = cdata->iWeaponBits; + + in_fov = cdata->fov; + + Think(); + + cdata->fov = m_iFOV; + + v_idlescale = m_iConcussionEffect; + + CL_ResetButtonBits( m_iKeyBits ); + + // return 1 if in anything in the client_data struct has been changed, 0 otherwise + return 1; +} + + diff --git a/cl_dll/hud/menu.cpp b/cl_dll/hud/menu.cpp index 6f7cfbf..3d991e6 100644 --- a/cl_dll/hud/menu.cpp +++ b/cl_dll/hud/menu.cpp @@ -1,356 +1,356 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// menu.cpp -// -// generic menu handler -// -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" - -#include -#include - -//#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 ); -DECLARE_MESSAGE( m_Menu, VGUIMenu ); -DECLARE_MESSAGE( m_Menu, BuyClose ); -DECLARE_MESSAGE( m_Menu, AllowSpec ); - -DECLARE_COMMAND( m_Menu, OldStyleMenuOpen ); -DECLARE_COMMAND( m_Menu, OldStyleMenuClose ); -DECLARE_COMMAND( m_Menu, ShowVGUIMenu ); - -int CHudMenu :: Init( void ) -{ - gHUD.AddHudElem( this ); - - HOOK_MESSAGE( ShowMenu ); - HOOK_MESSAGE( VGUIMenu ); - HOOK_MESSAGE( BuyClose ); - HOOK_MESSAGE( AllowSpec ); - HOOK_COMMAND( "client_buy_open", OldStyleMenuOpen ); - HOOK_COMMAND( "client_buy_close", OldStyleMenuClose ); - HOOK_COMMAND( "showvguimenu", ShowVGUIMenu ); - - _extended_menus = CVAR_CREATE("_extended_menus", "0", FCVAR_ARCHIVE); - - InitHUDData(); - - m_bAllowSpec = true; // by default, spectating is allowed - - return 1; -} - -void CHudMenu :: InitHUDData( void ) -{ - m_fMenuDisplayed = 0; - m_bitsValidSlots = 0; - Reset(); -} - -void CHudMenu :: Reset( void ) -{ - g_szPrelocalisedMenuString[0] = 0; - m_fWaitingForMore = FALSE; -} - -int CHudMenu :: VidInit( void ) -{ - return 1; -} - -int CHudMenu :: Draw( float flTime ) -{ - // check for if menu is set to disappear - if ( m_flShutoffTime > 0 ) - { - if ( m_flShutoffTime <= gHUD.m_flTime ) - { // times up, shutoff - m_fMenuDisplayed = 0; - m_iFlags &= ~HUD_ACTIVE; - return 1; - } - } - - // don't draw the menu if the scoreboard is being shown - //if ( gViewPort && gViewPort->IsScoreBoardVisible() ) - //return 1; - - // draw the menu, along the left-hand side of the screen - - // count the number of newlines - int nlc = 0; - int i; - for ( i = 0; i < MAX_MENU_STRING && g_szMenuString[i] != '\0'; i++ ) - { - if ( g_szMenuString[i] == '\n' ) - nlc++; - } - - // center it - int y = (ScreenHeight/2) - ((nlc/2)*12) - 40; // make sure it is above the say text - int x = 20; - - i = 0; - while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' ) - { - DrawUtils::DrawHudString( x, y, 320, g_szMenuString + i, 255, 255, 255 ); - y += 24; - - while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' && g_szMenuString[i] != '\n' ) - i++; - if ( g_szMenuString[i] == '\n' ) - i++; - } - - return 1; -} - -// selects an item from the menu -void CHudMenu :: SelectMenuItem( int menu_item ) -{ - // if menu_item is in a valid slot, send a menuselect command to the server - if ( (menu_item > 0) && (m_bitsValidSlots & (1 << (menu_item-1))) ) - { - char szbuf[32]; - sprintf( szbuf, "menuselect %d\n", menu_item ); - ClientCmd( szbuf ); - - // remove the menu - m_fMenuDisplayed = 0; - m_iFlags &= ~HUD_ACTIVE; - } -} - - -// Message handler for ShowMenu message -// takes four values: -// short: a bitfield of keys that are valid input -// char : the duration, in seconds, the menu should stay up. -1 means is stays until something is chosen. -// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, FALSE if it's the last string -// string: menu string to display -// 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, *menustring; - - BEGIN_READ( pbuf, iSize ); - - m_bitsValidSlots = READ_SHORT(); - int DisplayTime = READ_CHAR(); - int NeedMore = READ_BYTE(); - - if ( DisplayTime > 0 ) - m_flShutoffTime = DisplayTime + gHUD.m_flTime; - else - m_flShutoffTime = -1; - - if ( !m_bitsValidSlots ) - { - m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off - m_iFlags &= ~HUD_ACTIVE; - ClientCmd("touch_removebutton _menu_*"); - return 1; - } - - menustring = READ_STRING(); - - // menu will be replaced by scripted touch config - // so execute it and exit - if( _extended_menus->value != 0.0f ) - { - if( !strcmp(menustring, "#RadioA") ) - { - ShowVGUIMenu(MENU_RADIOA); - return 1; - } - else if( !strcmp(menustring, "#RadioB")) - { - ShowVGUIMenu(MENU_RADIOB); - return 1; - } - else if( !strcmp(menustring, "#RadioC")) - { - ShowVGUIMenu(MENU_RADIOC); - return 1; - } - } - - if ( !m_fWaitingForMore ) // this is the start of a new menu - { - strncpy( g_szPrelocalisedMenuString, menustring, MAX_MENU_STRING ); - } - else - { // append to the current menu string - strncat( g_szPrelocalisedMenuString, menustring, MAX_MENU_STRING - strlen(g_szPrelocalisedMenuString) ); - } - g_szPrelocalisedMenuString[MAX_MENU_STRING-1] = 0; // ensure null termination (strncat/strncpy does not) - - if ( !NeedMore ) - { // we have the whole string, so we can localise it now - strncpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString( g_szPrelocalisedMenuString ), MAX_MENU_STRING ); - - // Swap in characters - if ( KB_ConvertString( g_szMenuString, &temp ) ) - { - strncpy( g_szMenuString, temp, MAX_MENU_STRING ); - free( temp ); - } - } - - m_fMenuDisplayed = 1; - m_iFlags |= HUD_ACTIVE; - - m_fWaitingForMore = NeedMore; - - return 1; -} - -int CHudMenu::MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ(pbuf, iSize); - - int menuType = READ_BYTE(); - m_bitsValidSlots = READ_SHORT(); // is ignored - - ShowVGUIMenu(menuType); - return 1; -} - -int CHudMenu::MsgFunc_BuyClose(const char *pszName, int iSize, void *pbuf) -{ - UserCmd_OldStyleMenuClose(); - ClientCmd("touch_removebutton _menu_*"); - return 1; -} - -int CHudMenu::MsgFunc_AllowSpec(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - m_bAllowSpec = !!READ_BYTE(); - - return 1; -} - -void CHudMenu::UserCmd_OldStyleMenuOpen() -{ - m_flShutoffTime = -1; // stay open until user will not close it - strncpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString("Buy"), MAX_MENU_STRING ); -} - -void CHudMenu::UserCmd_OldStyleMenuClose() -{ - m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off - m_iFlags &= ~HUD_ACTIVE; - ClientCmd("touch_removebutton _menu_*"); -} - -// lol, no real VGUI here -// it's really good only for touchscreen - -void CHudMenu::ShowVGUIMenu( int menuType ) -{ - char *szCmd; - - switch(menuType) - { - case MENU_TEAM: - szCmd = "exec touch/chooseteam.cfg"; - break; - case MENU_CLASS_T: - szCmd = "exec touch/chooseteam_tr.cfg"; - break; - case MENU_CLASS_CT: - szCmd = "exec touch/chooseteam_ct.cfg"; - break; - case MENU_BUY: - szCmd = "exec touch/buy.cfg"; - break; - case MENU_BUY_PISTOL: - if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) - szCmd = "exec touch/buy_pistol_t.cfg"; - else szCmd = "exec touch/buy_pistol_ct.cfg"; - break; - case MENU_BUY_SHOTGUN: - if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) - szCmd = "exec touch/buy_shotgun_t.cfg"; - else szCmd = "exec touch/buy_shotgun_ct.cfg"; - break; - case MENU_BUY_RIFLE: - if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) - szCmd = "exec touch/buy_rifle_t.cfg"; - else szCmd ="exec touch/buy_rifle_ct.cfg"; - break; - case MENU_BUY_SUBMACHINEGUN: - if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) - szCmd = "exec touch/buy_submachinegun_t.cfg"; - else szCmd = "exec touch/buy_submachinegun_ct.cfg"; - break; - case MENU_BUY_MACHINEGUN: - if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == 1 ) - szCmd = "exec touch/buy_machinegun_t.cfg"; - else szCmd = "exec touch/buy_machinegun_ct.cfg"; - break; - case MENU_BUY_ITEM: - if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == 1 ) - szCmd = "exec touch/buy_item_t.cfg"; - else szCmd = "exec touch/buy_item_ct.cfg"; - break; - case MENU_RADIOA: - szCmd = "exec touch/radioa.cfg"; - break; - case MENU_RADIOB: - szCmd = "exec touch/radiob.cfg"; - break; - case MENU_RADIOC: - szCmd = "exec touch/radioc.cfg"; - break; - case MENU_RADIOSELECTOR: - szCmd = "exec touch/radioselector.cfg"; - break; - default: - szCmd = "touch_removebutton _menu_*"; // back to the default touch page - m_fMenuDisplayed = 0; - break; - } - - m_fMenuDisplayed = 1; - ClientCmd(szCmd); -} - -void CHudMenu::UserCmd_ShowVGUIMenu() -{ - if( gEngfuncs.Cmd_Argc() != 1 ) - { - ConsolePrint("usage: showvguimenu \n"); - } - - if( gEngfuncs.pfnGetCvarFloat("_vgui_menus") == 0.0f ) - return; - - int menuType = atoi(gEngfuncs.Cmd_Argv(1)); - ShowVGUIMenu(menuType); -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// menu.cpp +// +// generic menu handler +// +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include + +//#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 ); +DECLARE_MESSAGE( m_Menu, VGUIMenu ); +DECLARE_MESSAGE( m_Menu, BuyClose ); +DECLARE_MESSAGE( m_Menu, AllowSpec ); + +DECLARE_COMMAND( m_Menu, OldStyleMenuOpen ); +DECLARE_COMMAND( m_Menu, OldStyleMenuClose ); +DECLARE_COMMAND( m_Menu, ShowVGUIMenu ); + +int CHudMenu :: Init( void ) +{ + gHUD.AddHudElem( this ); + + HOOK_MESSAGE( ShowMenu ); + HOOK_MESSAGE( VGUIMenu ); + HOOK_MESSAGE( BuyClose ); + HOOK_MESSAGE( AllowSpec ); + HOOK_COMMAND( "client_buy_open", OldStyleMenuOpen ); + HOOK_COMMAND( "client_buy_close", OldStyleMenuClose ); + HOOK_COMMAND( "showvguimenu", ShowVGUIMenu ); + + _extended_menus = CVAR_CREATE("_extended_menus", "0", FCVAR_ARCHIVE); + + InitHUDData(); + + m_bAllowSpec = true; // by default, spectating is allowed + + return 1; +} + +void CHudMenu :: InitHUDData( void ) +{ + m_fMenuDisplayed = 0; + m_bitsValidSlots = 0; + Reset(); +} + +void CHudMenu :: Reset( void ) +{ + g_szPrelocalisedMenuString[0] = 0; + m_fWaitingForMore = FALSE; +} + +int CHudMenu :: VidInit( void ) +{ + return 1; +} + +int CHudMenu :: Draw( float flTime ) +{ + // check for if menu is set to disappear + if ( m_flShutoffTime > 0 ) + { + if ( m_flShutoffTime <= gHUD.m_flTime ) + { // times up, shutoff + m_fMenuDisplayed = 0; + m_iFlags &= ~HUD_ACTIVE; + return 1; + } + } + + // don't draw the menu if the scoreboard is being shown + //if ( gViewPort && gViewPort->IsScoreBoardVisible() ) + //return 1; + + // draw the menu, along the left-hand side of the screen + + // count the number of newlines + int nlc = 0; + int i; + for ( i = 0; i < MAX_MENU_STRING && g_szMenuString[i] != '\0'; i++ ) + { + if ( g_szMenuString[i] == '\n' ) + nlc++; + } + + // center it + int y = (ScreenHeight/2) - ((nlc/2)*12) - 40; // make sure it is above the say text + int x = 20; + + i = 0; + while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' ) + { + DrawUtils::DrawHudString( x, y, 320, g_szMenuString + i, 255, 255, 255 ); + y += 24; + + while ( i < MAX_MENU_STRING && g_szMenuString[i] != '\0' && g_szMenuString[i] != '\n' ) + i++; + if ( g_szMenuString[i] == '\n' ) + i++; + } + + return 1; +} + +// selects an item from the menu +void CHudMenu :: SelectMenuItem( int menu_item ) +{ + // if menu_item is in a valid slot, send a menuselect command to the server + if ( (menu_item > 0) && (m_bitsValidSlots & (1 << (menu_item-1))) ) + { + char szbuf[32]; + sprintf( szbuf, "menuselect %d\n", menu_item ); + ClientCmd( szbuf ); + + // remove the menu + m_fMenuDisplayed = 0; + m_iFlags &= ~HUD_ACTIVE; + } +} + + +// Message handler for ShowMenu message +// takes four values: +// short: a bitfield of keys that are valid input +// char : the duration, in seconds, the menu should stay up. -1 means is stays until something is chosen. +// byte : a boolean, TRUE if there is more string yet to be received before displaying the menu, FALSE if it's the last string +// string: menu string to display +// 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, *menustring; + + BEGIN_READ( pbuf, iSize ); + + m_bitsValidSlots = READ_SHORT(); + int DisplayTime = READ_CHAR(); + int NeedMore = READ_BYTE(); + + if ( DisplayTime > 0 ) + m_flShutoffTime = DisplayTime + gHUD.m_flTime; + else + m_flShutoffTime = -1; + + if ( !m_bitsValidSlots ) + { + m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off + m_iFlags &= ~HUD_ACTIVE; + ClientCmd("touch_removebutton _menu_*"); + return 1; + } + + menustring = READ_STRING(); + + // menu will be replaced by scripted touch config + // so execute it and exit + if( _extended_menus->value != 0.0f ) + { + if( !strcmp(menustring, "#RadioA") ) + { + ShowVGUIMenu(MENU_RADIOA); + return 1; + } + else if( !strcmp(menustring, "#RadioB")) + { + ShowVGUIMenu(MENU_RADIOB); + return 1; + } + else if( !strcmp(menustring, "#RadioC")) + { + ShowVGUIMenu(MENU_RADIOC); + return 1; + } + } + + if ( !m_fWaitingForMore ) // this is the start of a new menu + { + strncpy( g_szPrelocalisedMenuString, menustring, MAX_MENU_STRING ); + } + else + { // append to the current menu string + strncat( g_szPrelocalisedMenuString, menustring, MAX_MENU_STRING - strlen(g_szPrelocalisedMenuString) ); + } + g_szPrelocalisedMenuString[MAX_MENU_STRING-1] = 0; // ensure null termination (strncat/strncpy does not) + + if ( !NeedMore ) + { // we have the whole string, so we can localise it now + strncpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString( g_szPrelocalisedMenuString ), MAX_MENU_STRING ); + + // Swap in characters + if ( KB_ConvertString( g_szMenuString, &temp ) ) + { + strncpy( g_szMenuString, temp, MAX_MENU_STRING ); + free( temp ); + } + } + + m_fMenuDisplayed = 1; + m_iFlags |= HUD_ACTIVE; + + m_fWaitingForMore = NeedMore; + + return 1; +} + +int CHudMenu::MsgFunc_VGUIMenu( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ(pbuf, iSize); + + int menuType = READ_BYTE(); + m_bitsValidSlots = READ_SHORT(); // is ignored + + ShowVGUIMenu(menuType); + return 1; +} + +int CHudMenu::MsgFunc_BuyClose(const char *pszName, int iSize, void *pbuf) +{ + UserCmd_OldStyleMenuClose(); + ClientCmd("touch_removebutton _menu_*"); + return 1; +} + +int CHudMenu::MsgFunc_AllowSpec(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + m_bAllowSpec = !!READ_BYTE(); + + return 1; +} + +void CHudMenu::UserCmd_OldStyleMenuOpen() +{ + m_flShutoffTime = -1; // stay open until user will not close it + strncpy( g_szMenuString, gHUD.m_TextMessage.BufferedLocaliseTextString("Buy"), MAX_MENU_STRING ); +} + +void CHudMenu::UserCmd_OldStyleMenuClose() +{ + m_fMenuDisplayed = 0; // no valid slots means that the menu should be turned off + m_iFlags &= ~HUD_ACTIVE; + ClientCmd("touch_removebutton _menu_*"); +} + +// lol, no real VGUI here +// it's really good only for touchscreen + +void CHudMenu::ShowVGUIMenu( int menuType ) +{ + char *szCmd; + + switch(menuType) + { + case MENU_TEAM: + szCmd = "exec touch/chooseteam.cfg"; + break; + case MENU_CLASS_T: + szCmd = "exec touch/chooseteam_tr.cfg"; + break; + case MENU_CLASS_CT: + szCmd = "exec touch/chooseteam_ct.cfg"; + break; + case MENU_BUY: + szCmd = "exec touch/buy.cfg"; + break; + case MENU_BUY_PISTOL: + if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) + szCmd = "exec touch/buy_pistol_t.cfg"; + else szCmd = "exec touch/buy_pistol_ct.cfg"; + break; + case MENU_BUY_SHOTGUN: + if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) + szCmd = "exec touch/buy_shotgun_t.cfg"; + else szCmd = "exec touch/buy_shotgun_ct.cfg"; + break; + case MENU_BUY_RIFLE: + if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) + szCmd = "exec touch/buy_rifle_t.cfg"; + else szCmd ="exec touch/buy_rifle_ct.cfg"; + break; + case MENU_BUY_SUBMACHINEGUN: + if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == TEAM_TERRORIST ) + szCmd = "exec touch/buy_submachinegun_t.cfg"; + else szCmd = "exec touch/buy_submachinegun_ct.cfg"; + break; + case MENU_BUY_MACHINEGUN: + if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == 1 ) + szCmd = "exec touch/buy_machinegun_t.cfg"; + else szCmd = "exec touch/buy_machinegun_ct.cfg"; + break; + case MENU_BUY_ITEM: + if( g_PlayerExtraInfo[gHUD.m_Scoreboard.m_iPlayerNum].teamnumber == 1 ) + szCmd = "exec touch/buy_item_t.cfg"; + else szCmd = "exec touch/buy_item_ct.cfg"; + break; + case MENU_RADIOA: + szCmd = "exec touch/radioa.cfg"; + break; + case MENU_RADIOB: + szCmd = "exec touch/radiob.cfg"; + break; + case MENU_RADIOC: + szCmd = "exec touch/radioc.cfg"; + break; + case MENU_RADIOSELECTOR: + szCmd = "exec touch/radioselector.cfg"; + break; + default: + szCmd = "touch_removebutton _menu_*"; // back to the default touch page + m_fMenuDisplayed = 0; + break; + } + + m_fMenuDisplayed = 1; + ClientCmd(szCmd); +} + +void CHudMenu::UserCmd_ShowVGUIMenu() +{ + if( gEngfuncs.Cmd_Argc() != 1 ) + { + ConsolePrint("usage: showvguimenu \n"); + } + + if( gEngfuncs.pfnGetCvarFloat("_vgui_menus") == 0.0f ) + return; + + int menuType = atoi(gEngfuncs.Cmd_Argv(1)); + ShowVGUIMenu(menuType); +} diff --git a/cl_dll/hud/message.cpp b/cl_dll/hud/message.cpp index 1d597c8..a3e3da1 100644 --- a/cl_dll/hud/message.cpp +++ b/cl_dll/hud/message.cpp @@ -1,548 +1,548 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// Message.cpp -// -// implementation of CHudMessage class -// - -#include "hud.h" -#include "cl_util.h" -#include -#include -#include "parsemsg.h" -#include "vgui_parser.h" - -DECLARE_MESSAGE( m_Message, HudText ) -DECLARE_MESSAGE( m_Message, GameTitle ) - -// 1 Global client_textmessage_t for custom messages that aren't in the titles.txt -client_textmessage_t g_pCustomMessage; -char *g_pCustomName = "Custom"; -char g_pCustomText[1024]; - -int CHudMessage::Init(void) -{ - HOOK_MESSAGE( HudText ); - HOOK_MESSAGE( GameTitle ); - - gHUD.AddHudElem(this); - Reset(); - - return 1; -}; - -int CHudMessage::VidInit( void ) -{ - m_HUD_title_half = gHUD.GetSpriteIndex( "title_half" ); - m_HUD_title_life = gHUD.GetSpriteIndex( "title_life" ); - - return 1; -}; - - -void CHudMessage::Reset( void ) -{ - memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages ); - memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages ); - - m_gameTitleTime = 0; - m_pGameTitle = NULL; -} - - -float CHudMessage::FadeBlend( float fadein, float fadeout, float hold, float localTime ) -{ - float fadeTime = fadein + hold; - float fadeBlend; - - if ( localTime < 0 ) - return 0; - - if ( localTime < fadein ) - { - fadeBlend = 1 - ((fadein - localTime) / fadein); - } - else if ( localTime > fadeTime ) - { - if ( fadeout > 0 ) - fadeBlend = 1 - ((localTime - fadeTime) / fadeout); - else - fadeBlend = 0; - } - else - fadeBlend = 1; - - return fadeBlend; -} - - -int CHudMessage::XPosition( float x, int width, int totalWidth ) -{ - int xPos; - - if ( x == -1 ) - { - xPos = (ScreenWidth - width) / 2; - } - else - { - if ( x < 0 ) - xPos = (1.0 + x) * ScreenWidth - totalWidth; // Alight right - else - xPos = x * ScreenWidth; - } - - if ( xPos + width > ScreenWidth ) - xPos = ScreenWidth - width; - else if ( xPos < 0 ) - xPos = 0; - - return xPos; -} - - -int CHudMessage::YPosition( float y, int height ) -{ - int yPos; - - if ( y == -1 ) // Centered? - yPos = (ScreenHeight - height) * 0.5; - else - { - // Alight bottom? - if ( y < 0 ) - yPos = (1.0 + y) * ScreenHeight - height; // Alight bottom - else // align top - yPos = y * ScreenHeight; - } - - if ( yPos + height > ScreenHeight ) - yPos = ScreenHeight - height; - else if ( yPos < 0 ) - yPos = 0; - - return yPos; -} - - -void CHudMessage::MessageScanNextChar( void ) -{ - int srcRed, srcGreen, srcBlue, destRed, destGreen, destBlue; - int blend; - - srcRed = srcGreen = srcBlue = destRed = destGreen = destBlue = blend = 0; - - srcRed = m_parms.pMessage->r1; - srcGreen = m_parms.pMessage->g1; - srcBlue = m_parms.pMessage->b1; - blend = 0; // Pure source - - switch( m_parms.pMessage->effect ) - { - // Fade-in / Fade-out - case 0: - case 1: - destRed = destGreen = destBlue = 0; - blend = m_parms.fadeBlend; - break; - - case 2: - m_parms.charTime += m_parms.pMessage->fadein; - if ( m_parms.charTime > m_parms.time ) - { - srcRed = srcGreen = srcBlue = 0; - blend = 0; // pure source - } - else - { - float deltaTime = m_parms.time - m_parms.charTime; - - destRed = destGreen = destBlue = 0; - if ( m_parms.time > m_parms.fadeTime ) - { - blend = m_parms.fadeBlend; - } - else if ( deltaTime > m_parms.pMessage->fxtime ) - blend = 0; // pure dest - else - { - destRed = m_parms.pMessage->r2; - destGreen = m_parms.pMessage->g2; - destBlue = m_parms.pMessage->b2; - blend = 255 - (deltaTime * (1.0/m_parms.pMessage->fxtime) * 255.0 + 0.5); - } - } - break; - } - if ( blend > 255 ) - blend = 255; - else if ( blend < 0 ) - blend = 0; - - m_parms.r = ((srcRed * (255-blend)) + (destRed * blend)) >> 8; - m_parms.g = ((srcGreen * (255-blend)) + (destGreen * blend)) >> 8; - m_parms.b = ((srcBlue * (255-blend)) + (destBlue * blend)) >> 8; - - if ( m_parms.pMessage->effect == 1 && m_parms.charTime != 0 ) - { - if ( m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]) <= ScreenWidth ) - DrawUtils::TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2 ); - } -} - - -void CHudMessage::MessageScanStart( void ) -{ - switch( m_parms.pMessage->effect ) - { - // Fade-in / out with flicker - case 1: - case 0: - m_parms.fadeTime = m_parms.pMessage->fadein + m_parms.pMessage->holdtime; - - - if ( m_parms.time < m_parms.pMessage->fadein ) - { - m_parms.fadeBlend = ((m_parms.pMessage->fadein - m_parms.time) * (1.0/m_parms.pMessage->fadein) * 255); - } - else if ( m_parms.time > m_parms.fadeTime ) - { - if ( m_parms.pMessage->fadeout > 0 ) - m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255); - else - m_parms.fadeBlend = 255; // Pure dest (off) - } - else - m_parms.fadeBlend = 0; // Pure source (on) - m_parms.charTime = 0; - - if ( m_parms.pMessage->effect == 1 && (rand()%100) < 10 ) - m_parms.charTime = 1; - break; - - case 2: - m_parms.fadeTime = (m_parms.pMessage->fadein * m_parms.length) + m_parms.pMessage->holdtime; - - if ( m_parms.time > m_parms.fadeTime && m_parms.pMessage->fadeout > 0 ) - m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255); - else - m_parms.fadeBlend = 0; - break; - } -} - - -void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time ) -{ - int i, j, length, width; - const char *pText; - unsigned char line[80]; - - pText = pMessage->pMessage; - // Count lines - m_parms.lines = 1; - m_parms.time = time; - m_parms.pMessage = pMessage; - length = 0; - width = 0; - m_parms.totalWidth = 0; - while ( *pText ) - { - if ( *pText == '\n' ) - { - m_parms.lines++; - if ( width > m_parms.totalWidth ) - m_parms.totalWidth = width; - width = 0; - } - else - width += gHUD.m_scrinfo.charWidths[*pText]; - pText++; - length++; - } - m_parms.length = length; - m_parms.totalHeight = (m_parms.lines * gHUD.m_scrinfo.iCharHeight); - - - m_parms.y = YPosition( pMessage->y, m_parms.totalHeight ); - pText = pMessage->pMessage; - - m_parms.charTime = 0; - - MessageScanStart(); - - for ( i = 0; i < m_parms.lines; i++ ) - { - m_parms.lineLength = 0; - m_parms.width = 0; - while ( *pText && *pText != '\n' ) - { - unsigned char c = *pText; - line[m_parms.lineLength] = c; - m_parms.width += gHUD.m_scrinfo.charWidths[c]; - m_parms.lineLength++; - pText++; - } - pText++; // Skip LF - line[m_parms.lineLength] = 0; - - m_parms.x = XPosition( pMessage->x, m_parms.width, m_parms.totalWidth ); - - for ( j = 0; j < m_parms.lineLength; j++ ) - { - m_parms.text = line[j]; - int next = m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]; - MessageScanNextChar(); - - if ( m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth ) - DrawUtils::TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b ); - m_parms.x = next; - } - - m_parms.y += gHUD.m_scrinfo.iCharHeight; - } -} - - -int CHudMessage::Draw( float fTime ) -{ - int i, drawn; - client_textmessage_t *pMessage; - float endTime; - - drawn = 0; - - if ( m_gameTitleTime > 0 ) - { - float localTime = gHUD.m_flTime - m_gameTitleTime; - float brightness; - - // Maybe timer isn't set yet - if ( m_gameTitleTime > gHUD.m_flTime ) - m_gameTitleTime = gHUD.m_flTime; - - if ( localTime > (m_pGameTitle->fadein + m_pGameTitle->holdtime + m_pGameTitle->fadeout) ) - m_gameTitleTime = 0; - else - { - brightness = FadeBlend( m_pGameTitle->fadein, m_pGameTitle->fadeout, m_pGameTitle->holdtime, localTime ); - - int halfWidth = gHUD.GetSpriteRect(m_HUD_title_half).right - gHUD.GetSpriteRect(m_HUD_title_half).left; - int fullWidth = halfWidth + gHUD.GetSpriteRect(m_HUD_title_life).right - gHUD.GetSpriteRect(m_HUD_title_life).left; - int fullHeight = gHUD.GetSpriteRect(m_HUD_title_half).bottom - gHUD.GetSpriteRect(m_HUD_title_half).top; - - int x = XPosition( m_pGameTitle->x, fullWidth, fullWidth ); - int y = YPosition( m_pGameTitle->y, fullHeight ); - - - SPR_Set( gHUD.GetSprite(m_HUD_title_half), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 ); - SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_title_half) ); - - SPR_Set( gHUD.GetSprite(m_HUD_title_life), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 ); - SPR_DrawAdditive( 0, x + halfWidth, y, &gHUD.GetSpriteRect(m_HUD_title_life) ); - - drawn = 1; - } - } - // Fixup level transitions - for ( i = 0; i < maxHUDMessages; i++ ) - { - // Assume m_parms.time contains last time - if ( m_pMessages[i] ) - { - pMessage = m_pMessages[i]; - if ( m_startTime[i] > gHUD.m_flTime ) - m_startTime[i] = gHUD.m_flTime + m_parms.time - m_startTime[i] + 0.2; // Server takes 0.2 seconds to spawn, adjust for this - } - } - - for ( i = 0; i < maxHUDMessages; i++ ) - { - if ( m_pMessages[i] ) - { - pMessage = m_pMessages[i]; - - // This is when the message is over - switch( pMessage->effect ) - { - case 0: - case 1: - endTime = m_startTime[i] + pMessage->fadein + pMessage->fadeout + pMessage->holdtime; - break; - - // Fade in is per character in scanning messages - case 2: - endTime = m_startTime[i] + (pMessage->fadein * strlen( pMessage->pMessage )) + pMessage->fadeout + pMessage->holdtime; - break; - } - - if ( fTime <= endTime ) - { - float messageTime = fTime - m_startTime[i]; - - // Draw the message - // effect 0 is fade in/fade out - // effect 1 is flickery credits - // effect 2 is write out (training room) - MessageDrawScan( pMessage, messageTime ); - - drawn++; - } - else - { - // The message is over - m_pMessages[i] = NULL; - } - } - } - - // Remember the time -- to fix up level transitions - m_parms.time = gHUD.m_flTime; - // Don't call until we get another message - if ( !drawn ) - m_iFlags &= ~HUD_ACTIVE; - - return 1; -} - - -void CHudMessage::MessageAdd( const char *pName, float time ) -{ - int i,j; - client_textmessage_t *tempMessage; - - for ( i = 0; i < maxHUDMessages; i++ ) - { - if ( !m_pMessages[i] ) - { - // Trim off a leading # if it's there - if ( pName[0] == '#' ) - tempMessage = TextMessageGet( pName+1 ); - else - tempMessage = TextMessageGet( pName ); - // If we couldnt find it in the titles.txt, just create it - if ( !tempMessage ) - { - g_pCustomMessage.effect = 2; - g_pCustomMessage.r1 = g_pCustomMessage.g1 = g_pCustomMessage.b1 = g_pCustomMessage.a1 = 100; - g_pCustomMessage.r2 = 240; - g_pCustomMessage.g2 = 110; - g_pCustomMessage.b2 = 0; - g_pCustomMessage.a2 = 0; - g_pCustomMessage.x = -1; // Centered - g_pCustomMessage.y = 0.7; - g_pCustomMessage.fadein = 0.01; - g_pCustomMessage.fadeout = 1.5; - g_pCustomMessage.fxtime = 0.25; - g_pCustomMessage.holdtime = 5; - g_pCustomMessage.pName = g_pCustomName; - strncpy( g_pCustomText, pName, sizeof(g_pCustomText) ); - g_pCustomMessage.pMessage = g_pCustomText; - - tempMessage = &g_pCustomMessage; - } - else - { - // we have found message in titles.txt, but it still need translating - if( tempMessage->pMessage[0] == '#' ) - { - char *temp = (char *)tempMessage->pMessage; - tempMessage->pMessage = Localize(temp+1); - free( temp ); - } - } - - for ( j = 0; j < maxHUDMessages; j++ ) - { - if ( m_pMessages[j] ) - { - // is this message already in the list - if ( !strcmp( tempMessage->pMessage, m_pMessages[j]->pMessage ) ) - { - return; - } - - // get rid of any other messages in same location (only one displays at a time) - if ( fabs( tempMessage->y - m_pMessages[j]->y ) < 0.0001 ) - { - if ( fabs( tempMessage->x - m_pMessages[j]->x ) < 0.0001 ) - { - m_pMessages[j] = NULL; - } - } - } - } - - m_pMessages[i] = tempMessage; - m_startTime[i] = time; - return; - } - } -} - - -int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - char *pString = READ_STRING(); - - MessageAdd( pString, gHUD.m_flTime ); - // Remember the time -- to fix up level transitions - m_parms.time = gHUD.m_flTime; - - // Turn on drawing - if ( !(m_iFlags & HUD_ACTIVE) ) - m_iFlags |= HUD_ACTIVE; - - return 1; -} - - -int CHudMessage::MsgFunc_GameTitle( const char *pszName, int iSize, void *pbuf ) -{ - m_pGameTitle = TextMessageGet( "GAMETITLE" ); - if ( m_pGameTitle != NULL ) - { - m_gameTitleTime = gHUD.m_flTime; - - // Turn on drawing - if ( !(m_iFlags & HUD_ACTIVE) ) - m_iFlags |= HUD_ACTIVE; - } - - return 1; -} - -void CHudMessage::MessageAdd(client_textmessage_t * newMessage ) -{ - m_parms.time = gHUD.m_flTime; - - // Turn on drawing - if ( !(m_iFlags & HUD_ACTIVE) ) - m_iFlags |= HUD_ACTIVE; - - for ( int i = 0; i < maxHUDMessages; i++ ) - { - if ( !m_pMessages[i] ) - { - m_pMessages[i] = newMessage; - m_startTime[i] = gHUD.m_flTime; - return; - } - } - -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// Message.cpp +// +// implementation of CHudMessage class +// + +#include "hud.h" +#include "cl_util.h" +#include +#include +#include "parsemsg.h" +#include "vgui_parser.h" + +DECLARE_MESSAGE( m_Message, HudText ) +DECLARE_MESSAGE( m_Message, GameTitle ) + +// 1 Global client_textmessage_t for custom messages that aren't in the titles.txt +client_textmessage_t g_pCustomMessage; +char *g_pCustomName = "Custom"; +char g_pCustomText[1024]; + +int CHudMessage::Init(void) +{ + HOOK_MESSAGE( HudText ); + HOOK_MESSAGE( GameTitle ); + + gHUD.AddHudElem(this); + Reset(); + + return 1; +}; + +int CHudMessage::VidInit( void ) +{ + m_HUD_title_half = gHUD.GetSpriteIndex( "title_half" ); + m_HUD_title_life = gHUD.GetSpriteIndex( "title_life" ); + + return 1; +}; + + +void CHudMessage::Reset( void ) +{ + memset( m_pMessages, 0, sizeof( m_pMessages[0] ) * maxHUDMessages ); + memset( m_startTime, 0, sizeof( m_startTime[0] ) * maxHUDMessages ); + + m_gameTitleTime = 0; + m_pGameTitle = NULL; +} + + +float CHudMessage::FadeBlend( float fadein, float fadeout, float hold, float localTime ) +{ + float fadeTime = fadein + hold; + float fadeBlend; + + if ( localTime < 0 ) + return 0; + + if ( localTime < fadein ) + { + fadeBlend = 1 - ((fadein - localTime) / fadein); + } + else if ( localTime > fadeTime ) + { + if ( fadeout > 0 ) + fadeBlend = 1 - ((localTime - fadeTime) / fadeout); + else + fadeBlend = 0; + } + else + fadeBlend = 1; + + return fadeBlend; +} + + +int CHudMessage::XPosition( float x, int width, int totalWidth ) +{ + int xPos; + + if ( x == -1 ) + { + xPos = (ScreenWidth - width) / 2; + } + else + { + if ( x < 0 ) + xPos = (1.0 + x) * ScreenWidth - totalWidth; // Alight right + else + xPos = x * ScreenWidth; + } + + if ( xPos + width > ScreenWidth ) + xPos = ScreenWidth - width; + else if ( xPos < 0 ) + xPos = 0; + + return xPos; +} + + +int CHudMessage::YPosition( float y, int height ) +{ + int yPos; + + if ( y == -1 ) // Centered? + yPos = (ScreenHeight - height) * 0.5; + else + { + // Alight bottom? + if ( y < 0 ) + yPos = (1.0 + y) * ScreenHeight - height; // Alight bottom + else // align top + yPos = y * ScreenHeight; + } + + if ( yPos + height > ScreenHeight ) + yPos = ScreenHeight - height; + else if ( yPos < 0 ) + yPos = 0; + + return yPos; +} + + +void CHudMessage::MessageScanNextChar( void ) +{ + int srcRed, srcGreen, srcBlue, destRed, destGreen, destBlue; + int blend; + + srcRed = srcGreen = srcBlue = destRed = destGreen = destBlue = blend = 0; + + srcRed = m_parms.pMessage->r1; + srcGreen = m_parms.pMessage->g1; + srcBlue = m_parms.pMessage->b1; + blend = 0; // Pure source + + switch( m_parms.pMessage->effect ) + { + // Fade-in / Fade-out + case 0: + case 1: + destRed = destGreen = destBlue = 0; + blend = m_parms.fadeBlend; + break; + + case 2: + m_parms.charTime += m_parms.pMessage->fadein; + if ( m_parms.charTime > m_parms.time ) + { + srcRed = srcGreen = srcBlue = 0; + blend = 0; // pure source + } + else + { + float deltaTime = m_parms.time - m_parms.charTime; + + destRed = destGreen = destBlue = 0; + if ( m_parms.time > m_parms.fadeTime ) + { + blend = m_parms.fadeBlend; + } + else if ( deltaTime > m_parms.pMessage->fxtime ) + blend = 0; // pure dest + else + { + destRed = m_parms.pMessage->r2; + destGreen = m_parms.pMessage->g2; + destBlue = m_parms.pMessage->b2; + blend = 255 - (deltaTime * (1.0/m_parms.pMessage->fxtime) * 255.0 + 0.5); + } + } + break; + } + if ( blend > 255 ) + blend = 255; + else if ( blend < 0 ) + blend = 0; + + m_parms.r = ((srcRed * (255-blend)) + (destRed * blend)) >> 8; + m_parms.g = ((srcGreen * (255-blend)) + (destGreen * blend)) >> 8; + m_parms.b = ((srcBlue * (255-blend)) + (destBlue * blend)) >> 8; + + if ( m_parms.pMessage->effect == 1 && m_parms.charTime != 0 ) + { + if ( m_parms.x >= 0 && m_parms.y >= 0 && (m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]) <= ScreenWidth ) + DrawUtils::TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.pMessage->r2, m_parms.pMessage->g2, m_parms.pMessage->b2 ); + } +} + + +void CHudMessage::MessageScanStart( void ) +{ + switch( m_parms.pMessage->effect ) + { + // Fade-in / out with flicker + case 1: + case 0: + m_parms.fadeTime = m_parms.pMessage->fadein + m_parms.pMessage->holdtime; + + + if ( m_parms.time < m_parms.pMessage->fadein ) + { + m_parms.fadeBlend = ((m_parms.pMessage->fadein - m_parms.time) * (1.0/m_parms.pMessage->fadein) * 255); + } + else if ( m_parms.time > m_parms.fadeTime ) + { + if ( m_parms.pMessage->fadeout > 0 ) + m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255); + else + m_parms.fadeBlend = 255; // Pure dest (off) + } + else + m_parms.fadeBlend = 0; // Pure source (on) + m_parms.charTime = 0; + + if ( m_parms.pMessage->effect == 1 && (rand()%100) < 10 ) + m_parms.charTime = 1; + break; + + case 2: + m_parms.fadeTime = (m_parms.pMessage->fadein * m_parms.length) + m_parms.pMessage->holdtime; + + if ( m_parms.time > m_parms.fadeTime && m_parms.pMessage->fadeout > 0 ) + m_parms.fadeBlend = (((m_parms.time - m_parms.fadeTime) / m_parms.pMessage->fadeout) * 255); + else + m_parms.fadeBlend = 0; + break; + } +} + + +void CHudMessage::MessageDrawScan( client_textmessage_t *pMessage, float time ) +{ + int i, j, length, width; + const char *pText; + unsigned char line[80]; + + pText = pMessage->pMessage; + // Count lines + m_parms.lines = 1; + m_parms.time = time; + m_parms.pMessage = pMessage; + length = 0; + width = 0; + m_parms.totalWidth = 0; + while ( *pText ) + { + if ( *pText == '\n' ) + { + m_parms.lines++; + if ( width > m_parms.totalWidth ) + m_parms.totalWidth = width; + width = 0; + } + else + width += gHUD.m_scrinfo.charWidths[*pText]; + pText++; + length++; + } + m_parms.length = length; + m_parms.totalHeight = (m_parms.lines * gHUD.m_scrinfo.iCharHeight); + + + m_parms.y = YPosition( pMessage->y, m_parms.totalHeight ); + pText = pMessage->pMessage; + + m_parms.charTime = 0; + + MessageScanStart(); + + for ( i = 0; i < m_parms.lines; i++ ) + { + m_parms.lineLength = 0; + m_parms.width = 0; + while ( *pText && *pText != '\n' ) + { + unsigned char c = *pText; + line[m_parms.lineLength] = c; + m_parms.width += gHUD.m_scrinfo.charWidths[c]; + m_parms.lineLength++; + pText++; + } + pText++; // Skip LF + line[m_parms.lineLength] = 0; + + m_parms.x = XPosition( pMessage->x, m_parms.width, m_parms.totalWidth ); + + for ( j = 0; j < m_parms.lineLength; j++ ) + { + m_parms.text = line[j]; + int next = m_parms.x + gHUD.m_scrinfo.charWidths[ m_parms.text ]; + MessageScanNextChar(); + + if ( m_parms.x >= 0 && m_parms.y >= 0 && next <= ScreenWidth ) + DrawUtils::TextMessageDrawChar( m_parms.x, m_parms.y, m_parms.text, m_parms.r, m_parms.g, m_parms.b ); + m_parms.x = next; + } + + m_parms.y += gHUD.m_scrinfo.iCharHeight; + } +} + + +int CHudMessage::Draw( float fTime ) +{ + int i, drawn; + client_textmessage_t *pMessage; + float endTime; + + drawn = 0; + + if ( m_gameTitleTime > 0 ) + { + float localTime = gHUD.m_flTime - m_gameTitleTime; + float brightness; + + // Maybe timer isn't set yet + if ( m_gameTitleTime > gHUD.m_flTime ) + m_gameTitleTime = gHUD.m_flTime; + + if ( localTime > (m_pGameTitle->fadein + m_pGameTitle->holdtime + m_pGameTitle->fadeout) ) + m_gameTitleTime = 0; + else + { + brightness = FadeBlend( m_pGameTitle->fadein, m_pGameTitle->fadeout, m_pGameTitle->holdtime, localTime ); + + int halfWidth = gHUD.GetSpriteRect(m_HUD_title_half).right - gHUD.GetSpriteRect(m_HUD_title_half).left; + int fullWidth = halfWidth + gHUD.GetSpriteRect(m_HUD_title_life).right - gHUD.GetSpriteRect(m_HUD_title_life).left; + int fullHeight = gHUD.GetSpriteRect(m_HUD_title_half).bottom - gHUD.GetSpriteRect(m_HUD_title_half).top; + + int x = XPosition( m_pGameTitle->x, fullWidth, fullWidth ); + int y = YPosition( m_pGameTitle->y, fullHeight ); + + + SPR_Set( gHUD.GetSprite(m_HUD_title_half), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 ); + SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect(m_HUD_title_half) ); + + SPR_Set( gHUD.GetSprite(m_HUD_title_life), brightness * m_pGameTitle->r1, brightness * m_pGameTitle->g1, brightness * m_pGameTitle->b1 ); + SPR_DrawAdditive( 0, x + halfWidth, y, &gHUD.GetSpriteRect(m_HUD_title_life) ); + + drawn = 1; + } + } + // Fixup level transitions + for ( i = 0; i < maxHUDMessages; i++ ) + { + // Assume m_parms.time contains last time + if ( m_pMessages[i] ) + { + pMessage = m_pMessages[i]; + if ( m_startTime[i] > gHUD.m_flTime ) + m_startTime[i] = gHUD.m_flTime + m_parms.time - m_startTime[i] + 0.2; // Server takes 0.2 seconds to spawn, adjust for this + } + } + + for ( i = 0; i < maxHUDMessages; i++ ) + { + if ( m_pMessages[i] ) + { + pMessage = m_pMessages[i]; + + // This is when the message is over + switch( pMessage->effect ) + { + case 0: + case 1: + endTime = m_startTime[i] + pMessage->fadein + pMessage->fadeout + pMessage->holdtime; + break; + + // Fade in is per character in scanning messages + case 2: + endTime = m_startTime[i] + (pMessage->fadein * strlen( pMessage->pMessage )) + pMessage->fadeout + pMessage->holdtime; + break; + } + + if ( fTime <= endTime ) + { + float messageTime = fTime - m_startTime[i]; + + // Draw the message + // effect 0 is fade in/fade out + // effect 1 is flickery credits + // effect 2 is write out (training room) + MessageDrawScan( pMessage, messageTime ); + + drawn++; + } + else + { + // The message is over + m_pMessages[i] = NULL; + } + } + } + + // Remember the time -- to fix up level transitions + m_parms.time = gHUD.m_flTime; + // Don't call until we get another message + if ( !drawn ) + m_iFlags &= ~HUD_ACTIVE; + + return 1; +} + + +void CHudMessage::MessageAdd( const char *pName, float time ) +{ + int i,j; + client_textmessage_t *tempMessage; + + for ( i = 0; i < maxHUDMessages; i++ ) + { + if ( !m_pMessages[i] ) + { + // Trim off a leading # if it's there + if ( pName[0] == '#' ) + tempMessage = TextMessageGet( pName+1 ); + else + tempMessage = TextMessageGet( pName ); + // If we couldnt find it in the titles.txt, just create it + if ( !tempMessage ) + { + g_pCustomMessage.effect = 2; + g_pCustomMessage.r1 = g_pCustomMessage.g1 = g_pCustomMessage.b1 = g_pCustomMessage.a1 = 100; + g_pCustomMessage.r2 = 240; + g_pCustomMessage.g2 = 110; + g_pCustomMessage.b2 = 0; + g_pCustomMessage.a2 = 0; + g_pCustomMessage.x = -1; // Centered + g_pCustomMessage.y = 0.7; + g_pCustomMessage.fadein = 0.01; + g_pCustomMessage.fadeout = 1.5; + g_pCustomMessage.fxtime = 0.25; + g_pCustomMessage.holdtime = 5; + g_pCustomMessage.pName = g_pCustomName; + strncpy( g_pCustomText, pName, sizeof(g_pCustomText) ); + g_pCustomMessage.pMessage = g_pCustomText; + + tempMessage = &g_pCustomMessage; + } + else + { + // we have found message in titles.txt, but it still need translating + if( tempMessage->pMessage[0] == '#' ) + { + char *temp = (char *)tempMessage->pMessage; + tempMessage->pMessage = Localize(temp+1); + free( temp ); + } + } + + for ( j = 0; j < maxHUDMessages; j++ ) + { + if ( m_pMessages[j] ) + { + // is this message already in the list + if ( !strcmp( tempMessage->pMessage, m_pMessages[j]->pMessage ) ) + { + return; + } + + // get rid of any other messages in same location (only one displays at a time) + if ( fabs( tempMessage->y - m_pMessages[j]->y ) < 0.0001 ) + { + if ( fabs( tempMessage->x - m_pMessages[j]->x ) < 0.0001 ) + { + m_pMessages[j] = NULL; + } + } + } + } + + m_pMessages[i] = tempMessage; + m_startTime[i] = time; + return; + } + } +} + + +int CHudMessage::MsgFunc_HudText( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + char *pString = READ_STRING(); + + MessageAdd( pString, gHUD.m_flTime ); + // Remember the time -- to fix up level transitions + m_parms.time = gHUD.m_flTime; + + // Turn on drawing + if ( !(m_iFlags & HUD_ACTIVE) ) + m_iFlags |= HUD_ACTIVE; + + return 1; +} + + +int CHudMessage::MsgFunc_GameTitle( const char *pszName, int iSize, void *pbuf ) +{ + m_pGameTitle = TextMessageGet( "GAMETITLE" ); + if ( m_pGameTitle != NULL ) + { + m_gameTitleTime = gHUD.m_flTime; + + // Turn on drawing + if ( !(m_iFlags & HUD_ACTIVE) ) + m_iFlags |= HUD_ACTIVE; + } + + return 1; +} + +void CHudMessage::MessageAdd(client_textmessage_t * newMessage ) +{ + m_parms.time = gHUD.m_flTime; + + // Turn on drawing + if ( !(m_iFlags & HUD_ACTIVE) ) + m_iFlags |= HUD_ACTIVE; + + for ( int i = 0; i < maxHUDMessages; i++ ) + { + if ( !m_pMessages[i] ) + { + m_pMessages[i] = newMessage; + m_startTime[i] = gHUD.m_flTime; + return; + } + } + +} diff --git a/cl_dll/hud/saytext.cpp b/cl_dll/hud/saytext.cpp index f54faaf..8273277 100644 --- a/cl_dll/hud/saytext.cpp +++ b/cl_dll/hud/saytext.cpp @@ -1,372 +1,372 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// saytext.cpp -// -// implementation of CHudSayText class -// - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" - -#include -#include -#include -#include "vgui_parser.h" - -//#include "vgui_TeamFortressViewport.h" - -extern float *GetClientColor( int clientIndex ); - -#define MAX_LINES 5 -#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 ) -#define LINE_START 10 -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; -static int line_height = 0; - -DECLARE_MESSAGE( m_SayText, SayText ); - -int CHudSayText :: Init( void ) -{ - gHUD.AddHudElem( this ); - - HOOK_MESSAGE( SayText ); - - InitHUDData(); - - m_HUD_saytext = gEngfuncs.pfnRegisterVariable( "hud_saytext", "1", 0 ); - m_HUD_saytext_time = gEngfuncs.pfnRegisterVariable( "hud_saytext_time", "5", 0 ); - - m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission - - return 1; -} - - -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 ) -{ - return 1; -} - - -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; - return 1 + ScrollTextUp(); - } - - return 1; -} - -int CHudSayText :: Draw( float flTime ) -{ - int y = Y_START; - - //if ( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE) || !m_HUD_saytext->value ) - //return 1; - - // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset - flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value ); - - // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset - flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value ); - - if ( flScrollTime <= flTime ) - { - if ( *g_szLineBuffer[0] ) - { - flScrollTime = flTime + m_HUD_saytext_time->value; - // push the console up - ScrollTextUp(); - } - else - { // buffer is empty, just disable drawing of this section - m_iFlags &= ~HUD_ACTIVE; - } - } - - for ( int i = 0; i < MAX_LINES; i++ ) - { - if ( *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; - DrawUtils::SetConsoleTextColor( g_pflNameColors[i][0], g_pflNameColors[i][1], g_pflNameColors[i][2] ); - int x = DrawUtils::DrawConsoleString( LINE_START, y, buf ); - - // color is reset after each string draw - DrawUtils::DrawConsoleString( x, y, g_szLineBuffer[i] + g_iNameLengths[i] ); - } - else - { - // normal draw - DrawUtils::DrawConsoleString( LINE_START, y, g_szLineBuffer[i] ); - } - } - - y += line_height; - } - - - return 1; -} - -struct CSimpleMap { - const char key[32]; - const char value[64]; -}; - -CSimpleMap sayTextFmt[] = -{ -{"#Cstrike_Chat_CT", "\x02(Counter-Terrorist) %s : %s"}, -{"#Cstrike_Chat_T", "\x02(Terrorist) %s : %s"}, -{"#Cstrike_Chat_CT_Dead", "\x02*DEAD*(Counter-Terrorist) %s : %s"}, -{"#Cstrike_Chat_T_Dead", "\x02*DEAD*(Terrorist) %s : %s"}, -{"#Cstrike_Chat_Spec", "\x02(Spectator) %s : %s"}, -{"#Cstrike_Chat_All", "\x02%s : %s"}, -{"#Cstrike_Chat_AllDead", "\x02*DEAD* %s: %s"}, -{"#Cstrike_Chat_AllSpec", "\x02*SPEC* %s: %s"}, -{"#Cstrike_Name_Change", "\x02* %s changed name to %s"}, -}; - -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 - char szBuf[3][64]; - strncpy( szBuf[0], READ_STRING(), sizeof(szBuf[0])); - strncpy( szBuf[1], READ_STRING(), sizeof(szBuf[1])); - strncpy( szBuf[2], READ_STRING(), sizeof(szBuf[2])); - - const char *fmt = "\x02%s: %s"; - int i = 0; - for( i; i < sizeof(sayTextFmt) / sizeof(CSimpleMap); i++ ) - { - if( !strncmp( szBuf[0], sayTextFmt[i].key, sizeof( szBuf ) ) ) - { - fmt = sayTextFmt[i].value; - break; - } - } - - char dst[256]; - if( i == 8 ) - { - snprintf( dst, sizeof( dst ), fmt, szBuf[1], szBuf[2]); - } - else - { - GetPlayerInfo( client_index, &g_PlayerInfoList[client_index] ); - const char *pName = g_PlayerInfoList[client_index].name; - snprintf( dst, sizeof( dst ), fmt, pName, szBuf[2]); - } - SayTextPrint( dst, strlen(dst), client_index ); - - return 1; -} - -void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex ) -{ - /*if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) - { - // Print it straight to the console - ConsolePrint( pszBuf ); - return; - }*/ - - // find an empty string slot - int i; - for ( i = 0; i < MAX_LINES; i++ ) - { - if ( ! *g_szLineBuffer[i] ) - break; - } - if ( i == MAX_LINES ) - { - // force scroll buffer up - ScrollTextUp(); - i = MAX_LINES - 1; - } - - g_iNameLengths[i] = 0; - g_pflNameColors[i] = NULL; - -#if 1 - // 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 ); - } - } - } -#endif - - - strncpy( g_szLineBuffer[i], pszBuf, max(iBufSize -1, MAX_CHARS_PER_LINE-1) ); - - // make sure the text fits in one line - EnsureTextFitsInOneLineAndWrapIfHaveTo( i ); - - // Set scroll time - if ( i == 0 ) - { - flScrollTime = gHUD.m_flTime + m_HUD_saytext_time->value; - } - - m_iFlags |= HUD_ACTIVE; - PlaySound( "misc/talk.wav", 1 ); - - if ( ScreenHeight >= 480 ) - Y_START = ScreenHeight - 60; - else - Y_START = ScreenHeight - 45; - Y_START -= (line_height * (MAX_LINES+1)); - -} - -void CHudSayText :: EnsureTextFitsInOneLineAndWrapIfHaveTo( int line ) -{ - int line_width = 0; - DrawUtils::ConsoleStringSize(g_szLineBuffer[line], &line_width, &line_height ); - - if ( (line_width + LINE_START) > MAX_LINE_WIDTH ) - { // string is too long to fit on line - // scan the string until we find what word is too long, and wrap the end of the sentence after the word - int length = LINE_START; - int tmp_len = 0; - 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; - - if ( *x == ' ' && x != g_szLineBuffer[line] ) // store each line break, except for the very first character - last_break = x; - - buf[0] = *x; // get the length of the current character - DrawUtils::ConsoleStringSize( buf, &tmp_len, &line_height ); - length += tmp_len; - - if ( length > MAX_LINE_WIDTH ) - { // needs to be broken up - if ( !last_break ) - last_break = x-1; - - x = last_break; - - // find an empty string slot - int j; - do - { - 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)' ' ) - { - int linelen = strlen(g_szLineBuffer[j]); - int remaininglen = strlen(last_break); - - if ( (linelen - remaininglen) <= MAX_CHARS_PER_LINE ) - strcat( g_szLineBuffer[j], last_break ); - } - else - { - if ( (strlen(g_szLineBuffer[j]) - strlen(last_break) - 2) < MAX_CHARS_PER_LINE ) - { - strcat( g_szLineBuffer[j], " " ); - strcat( g_szLineBuffer[j], last_break ); - } - } - - *last_break = 0; // cut off the last string - - EnsureTextFitsInOneLineAndWrapIfHaveTo( j ); - break; - } - } - } -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// saytext.cpp +// +// implementation of CHudSayText class +// + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include +#include +#include "vgui_parser.h" + +//#include "vgui_TeamFortressViewport.h" + +extern float *GetClientColor( int clientIndex ); + +#define MAX_LINES 5 +#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 ) +#define LINE_START 10 +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; +static int line_height = 0; + +DECLARE_MESSAGE( m_SayText, SayText ); + +int CHudSayText :: Init( void ) +{ + gHUD.AddHudElem( this ); + + HOOK_MESSAGE( SayText ); + + InitHUDData(); + + m_HUD_saytext = gEngfuncs.pfnRegisterVariable( "hud_saytext", "1", 0 ); + m_HUD_saytext_time = gEngfuncs.pfnRegisterVariable( "hud_saytext_time", "5", 0 ); + + m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission + + return 1; +} + + +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 ) +{ + return 1; +} + + +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; + return 1 + ScrollTextUp(); + } + + return 1; +} + +int CHudSayText :: Draw( float flTime ) +{ + int y = Y_START; + + //if ( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE) || !m_HUD_saytext->value ) + //return 1; + + // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset + flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value ); + + // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset + flScrollTime = min( flScrollTime, flTime + m_HUD_saytext_time->value ); + + if ( flScrollTime <= flTime ) + { + if ( *g_szLineBuffer[0] ) + { + flScrollTime = flTime + m_HUD_saytext_time->value; + // push the console up + ScrollTextUp(); + } + else + { // buffer is empty, just disable drawing of this section + m_iFlags &= ~HUD_ACTIVE; + } + } + + for ( int i = 0; i < MAX_LINES; i++ ) + { + if ( *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; + DrawUtils::SetConsoleTextColor( g_pflNameColors[i][0], g_pflNameColors[i][1], g_pflNameColors[i][2] ); + int x = DrawUtils::DrawConsoleString( LINE_START, y, buf ); + + // color is reset after each string draw + DrawUtils::DrawConsoleString( x, y, g_szLineBuffer[i] + g_iNameLengths[i] ); + } + else + { + // normal draw + DrawUtils::DrawConsoleString( LINE_START, y, g_szLineBuffer[i] ); + } + } + + y += line_height; + } + + + return 1; +} + +struct CSimpleMap { + const char key[32]; + const char value[64]; +}; + +CSimpleMap sayTextFmt[] = +{ +{"#Cstrike_Chat_CT", "\x02(Counter-Terrorist) %s : %s"}, +{"#Cstrike_Chat_T", "\x02(Terrorist) %s : %s"}, +{"#Cstrike_Chat_CT_Dead", "\x02*DEAD*(Counter-Terrorist) %s : %s"}, +{"#Cstrike_Chat_T_Dead", "\x02*DEAD*(Terrorist) %s : %s"}, +{"#Cstrike_Chat_Spec", "\x02(Spectator) %s : %s"}, +{"#Cstrike_Chat_All", "\x02%s : %s"}, +{"#Cstrike_Chat_AllDead", "\x02*DEAD* %s: %s"}, +{"#Cstrike_Chat_AllSpec", "\x02*SPEC* %s: %s"}, +{"#Cstrike_Name_Change", "\x02* %s changed name to %s"}, +}; + +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 + char szBuf[3][64]; + strncpy( szBuf[0], READ_STRING(), sizeof(szBuf[0])); + strncpy( szBuf[1], READ_STRING(), sizeof(szBuf[1])); + strncpy( szBuf[2], READ_STRING(), sizeof(szBuf[2])); + + const char *fmt = "\x02%s: %s"; + int i = 0; + for( i; i < sizeof(sayTextFmt) / sizeof(CSimpleMap); i++ ) + { + if( !strncmp( szBuf[0], sayTextFmt[i].key, sizeof( szBuf ) ) ) + { + fmt = sayTextFmt[i].value; + break; + } + } + + char dst[256]; + if( i == 8 ) + { + snprintf( dst, sizeof( dst ), fmt, szBuf[1], szBuf[2]); + } + else + { + GetPlayerInfo( client_index, &g_PlayerInfoList[client_index] ); + const char *pName = g_PlayerInfoList[client_index].name; + snprintf( dst, sizeof( dst ), fmt, pName, szBuf[2]); + } + SayTextPrint( dst, strlen(dst), client_index ); + + return 1; +} + +void CHudSayText :: SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex ) +{ + /*if ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) + { + // Print it straight to the console + ConsolePrint( pszBuf ); + return; + }*/ + + // find an empty string slot + int i; + for ( i = 0; i < MAX_LINES; i++ ) + { + if ( ! *g_szLineBuffer[i] ) + break; + } + if ( i == MAX_LINES ) + { + // force scroll buffer up + ScrollTextUp(); + i = MAX_LINES - 1; + } + + g_iNameLengths[i] = 0; + g_pflNameColors[i] = NULL; + +#if 1 + // 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 ); + } + } + } +#endif + + + strncpy( g_szLineBuffer[i], pszBuf, max(iBufSize -1, MAX_CHARS_PER_LINE-1) ); + + // make sure the text fits in one line + EnsureTextFitsInOneLineAndWrapIfHaveTo( i ); + + // Set scroll time + if ( i == 0 ) + { + flScrollTime = gHUD.m_flTime + m_HUD_saytext_time->value; + } + + m_iFlags |= HUD_ACTIVE; + PlaySound( "misc/talk.wav", 1 ); + + if ( ScreenHeight >= 480 ) + Y_START = ScreenHeight - 60; + else + Y_START = ScreenHeight - 45; + Y_START -= (line_height * (MAX_LINES+1)); + +} + +void CHudSayText :: EnsureTextFitsInOneLineAndWrapIfHaveTo( int line ) +{ + int line_width = 0; + DrawUtils::ConsoleStringSize(g_szLineBuffer[line], &line_width, &line_height ); + + if ( (line_width + LINE_START) > MAX_LINE_WIDTH ) + { // string is too long to fit on line + // scan the string until we find what word is too long, and wrap the end of the sentence after the word + int length = LINE_START; + int tmp_len = 0; + 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; + + if ( *x == ' ' && x != g_szLineBuffer[line] ) // store each line break, except for the very first character + last_break = x; + + buf[0] = *x; // get the length of the current character + DrawUtils::ConsoleStringSize( buf, &tmp_len, &line_height ); + length += tmp_len; + + if ( length > MAX_LINE_WIDTH ) + { // needs to be broken up + if ( !last_break ) + last_break = x-1; + + x = last_break; + + // find an empty string slot + int j; + do + { + 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)' ' ) + { + int linelen = strlen(g_szLineBuffer[j]); + int remaininglen = strlen(last_break); + + if ( (linelen - remaininglen) <= MAX_CHARS_PER_LINE ) + strcat( g_szLineBuffer[j], last_break ); + } + else + { + if ( (strlen(g_szLineBuffer[j]) - strlen(last_break) - 2) < MAX_CHARS_PER_LINE ) + { + strcat( g_szLineBuffer[j], " " ); + strcat( g_szLineBuffer[j], last_break ); + } + } + + *last_break = 0; // cut off the last string + + EnsureTextFitsInOneLineAndWrapIfHaveTo( j ); + break; + } + } + } +} diff --git a/cl_dll/hud/status_icons.cpp b/cl_dll/hud/status_icons.cpp index f945231..9c7af7f 100644 --- a/cl_dll/hud/status_icons.cpp +++ b/cl_dll/hud/status_icons.cpp @@ -1,166 +1,166 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// status_icons.cpp -// -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "entity_state.h" -#include "cl_entity.h" -#include -#include -#include "parsemsg.h" -#include "event_api.h" -#include "com_weapons.h" - -DECLARE_MESSAGE( m_StatusIcons, StatusIcon ); - -int CHudStatusIcons::Init( void ) -{ - HOOK_MESSAGE( StatusIcon ); - - gHUD.AddHudElem( this ); - - Reset(); - - return 1; -} - -int CHudStatusIcons::VidInit( void ) -{ - return 1; -} - -void CHudStatusIcons::Reset( void ) -{ - memset( m_IconList, 0, sizeof m_IconList ); - m_iFlags &= ~HUD_ACTIVE; -} - -// Draw status icons along the left-hand side of the screen -int CHudStatusIcons::Draw( float flTime ) -{ - if (gEngfuncs.IsSpectateOnly()) - return 1; - // find starting position to draw from, along right-hand side of screen - int x = 5; - int y = ScreenHeight / 2; - - // loop through icon list, and draw any valid icons drawing up from the middle of screen - for ( int i = 0; i < MAX_ICONSPRITES; i++ ) - { - if ( m_IconList[i].spr ) - { - y -= ( m_IconList[i].rc.bottom - m_IconList[i].rc.top ) + 5; - - if( g_bInBombZone && !strcmp(m_IconList[i].szSpriteName, "c4") && ((int)(flTime * 10) % 2)) - SPR_Set( m_IconList[i].spr, 255, 16, 16 ); - else SPR_Set( m_IconList[i].spr, m_IconList[i].r, m_IconList[i].g, m_IconList[i].b ); - SPR_DrawAdditive( 0, x, y, &m_IconList[i].rc ); - } - } - - return 1; -} - -// Message handler for StatusIcon message -// accepts five values: -// byte : TRUE = ENABLE icon, FALSE = DISABLE icon -// string : the sprite name to display -// byte : red -// byte : green -// byte : blue -int CHudStatusIcons::MsgFunc_StatusIcon( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int ShouldEnable = READ_BYTE(); - char *pszIconName = READ_STRING(); - - if ( ShouldEnable ) - { - int r = READ_BYTE(); - int g = READ_BYTE(); - int b = READ_BYTE(); - EnableIcon( pszIconName, r, g, b ); - m_iFlags |= HUD_ACTIVE; - } - else - { - DisableIcon( pszIconName ); - } - - return 1; -} - -// add the icon to the icon list, and set it's drawing color -void CHudStatusIcons::EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue ) -{ - // check to see if the sprite is in the current list - int i; - for ( i = 0; i < MAX_ICONSPRITES; i++ ) - { - if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) ) - break; - } - - if ( i == MAX_ICONSPRITES ) - { - // icon not in list, so find an empty slot to add to - for ( i = 0; i < MAX_ICONSPRITES; i++ ) - { - if ( !m_IconList[i].spr ) - break; - } - } - - // if we've run out of space in the list, overwrite the first icon - if ( i == MAX_ICONSPRITES ) - { - i = 0; - } - - // Load the sprite and add it to the list - // the sprite must be listed in hud.txt - int spr_index = gHUD.GetSpriteIndex( pszIconName ); - m_IconList[i].spr = gHUD.GetSprite( spr_index ); - m_IconList[i].rc = gHUD.GetSpriteRect( spr_index ); - m_IconList[i].r = red; - m_IconList[i].g = green; - m_IconList[i].b = blue; - strncpy( m_IconList[i].szSpriteName, pszIconName, MAX_ICONSPRITENAME_LENGTH ); - - // 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 ) -{ - // find the sprite is in the current list - for ( int i = 0; i < MAX_ICONSPRITES; i++ ) - { - if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) ) - { - // clear the item from the list - memset( &m_IconList[i], 0, sizeof( icon_sprite_t ) ); - return; - } - } -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// status_icons.cpp +// +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_state.h" +#include "cl_entity.h" +#include +#include +#include "parsemsg.h" +#include "event_api.h" +#include "com_weapons.h" + +DECLARE_MESSAGE( m_StatusIcons, StatusIcon ); + +int CHudStatusIcons::Init( void ) +{ + HOOK_MESSAGE( StatusIcon ); + + gHUD.AddHudElem( this ); + + Reset(); + + return 1; +} + +int CHudStatusIcons::VidInit( void ) +{ + return 1; +} + +void CHudStatusIcons::Reset( void ) +{ + memset( m_IconList, 0, sizeof m_IconList ); + m_iFlags &= ~HUD_ACTIVE; +} + +// Draw status icons along the left-hand side of the screen +int CHudStatusIcons::Draw( float flTime ) +{ + if (gEngfuncs.IsSpectateOnly()) + return 1; + // find starting position to draw from, along right-hand side of screen + int x = 5; + int y = ScreenHeight / 2; + + // loop through icon list, and draw any valid icons drawing up from the middle of screen + for ( int i = 0; i < MAX_ICONSPRITES; i++ ) + { + if ( m_IconList[i].spr ) + { + y -= ( m_IconList[i].rc.bottom - m_IconList[i].rc.top ) + 5; + + if( g_bInBombZone && !strcmp(m_IconList[i].szSpriteName, "c4") && ((int)(flTime * 10) % 2)) + SPR_Set( m_IconList[i].spr, 255, 16, 16 ); + else SPR_Set( m_IconList[i].spr, m_IconList[i].r, m_IconList[i].g, m_IconList[i].b ); + SPR_DrawAdditive( 0, x, y, &m_IconList[i].rc ); + } + } + + return 1; +} + +// Message handler for StatusIcon message +// accepts five values: +// byte : TRUE = ENABLE icon, FALSE = DISABLE icon +// string : the sprite name to display +// byte : red +// byte : green +// byte : blue +int CHudStatusIcons::MsgFunc_StatusIcon( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int ShouldEnable = READ_BYTE(); + char *pszIconName = READ_STRING(); + + if ( ShouldEnable ) + { + int r = READ_BYTE(); + int g = READ_BYTE(); + int b = READ_BYTE(); + EnableIcon( pszIconName, r, g, b ); + m_iFlags |= HUD_ACTIVE; + } + else + { + DisableIcon( pszIconName ); + } + + return 1; +} + +// add the icon to the icon list, and set it's drawing color +void CHudStatusIcons::EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue ) +{ + // check to see if the sprite is in the current list + int i; + for ( i = 0; i < MAX_ICONSPRITES; i++ ) + { + if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) ) + break; + } + + if ( i == MAX_ICONSPRITES ) + { + // icon not in list, so find an empty slot to add to + for ( i = 0; i < MAX_ICONSPRITES; i++ ) + { + if ( !m_IconList[i].spr ) + break; + } + } + + // if we've run out of space in the list, overwrite the first icon + if ( i == MAX_ICONSPRITES ) + { + i = 0; + } + + // Load the sprite and add it to the list + // the sprite must be listed in hud.txt + int spr_index = gHUD.GetSpriteIndex( pszIconName ); + m_IconList[i].spr = gHUD.GetSprite( spr_index ); + m_IconList[i].rc = gHUD.GetSpriteRect( spr_index ); + m_IconList[i].r = red; + m_IconList[i].g = green; + m_IconList[i].b = blue; + strncpy( m_IconList[i].szSpriteName, pszIconName, MAX_ICONSPRITENAME_LENGTH ); + + // 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 ) +{ + // find the sprite is in the current list + for ( int i = 0; i < MAX_ICONSPRITES; i++ ) + { + if ( !stricmp( m_IconList[i].szSpriteName, pszIconName ) ) + { + // clear the item from the list + memset( &m_IconList[i], 0, sizeof( icon_sprite_t ) ); + return; + } + } +} diff --git a/cl_dll/hud/statusbar.cpp b/cl_dll/hud/statusbar.cpp index 88b2b4c..8b965e6 100644 --- a/cl_dll/hud/statusbar.cpp +++ b/cl_dll/hud/statusbar.cpp @@ -1,298 +1,298 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// statusbar.cpp -// -// generic text status bar, set by game dll -// runs across bottom of screen -// - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" - -#include -#include - -DECLARE_MESSAGE( m_StatusBar, StatusText ); -DECLARE_MESSAGE( m_StatusBar, StatusValue ); - -extern float g_ColorYellow[3]; - -#define STATUSBAR_ID_LINE 0 - -inline void InsertTextMsg( char *szDst, size_t sLen, const char *szMsgName) -{ - client_textmessage_t *msg = TextMessageGet(szMsgName); - if( msg ) - { - strncpy( szDst, msg->pMessage, sLen ); - } - else strncpy( szDst, szMsgName, sLen ); -} - -int CHudStatusBar :: Init( void ) -{ - gHUD.AddHudElem( this ); - - HOOK_MESSAGE( StatusText ); - HOOK_MESSAGE( StatusValue ); - - Reset(); - - hud_centerid = CVAR_CREATE( "hud_centerid", "0", FCVAR_ARCHIVE ); - - return 1; -} - -int CHudStatusBar :: VidInit( void ) -{ - // Load sprites here - - return 1; -} - -void CHudStatusBar :: Reset( void ) -{ - int i = 0; - - m_iFlags &= ~HUD_ACTIVE; // start out inactive - for ( i = 0; i < MAX_STATUSBAR_LINES; i++ ) - m_szStatusText[i][0] = 0; - memset( m_iStatusValues, 0, sizeof m_iStatusValues ); - - m_iStatusValues[0] = 1; // 0 is the special index, which always returns true - - // reset our colors for the status bar lines (yellow is default) - for ( i = 0; i < MAX_STATUSBAR_LINES; i++ ) - m_pflNameColors[i] = g_ColorYellow; -} - -void CHudStatusBar :: ParseStatusString( int line_num ) -{ - // localise string first - char szBuffer[MAX_STATUSTEXT_LENGTH]; - memset( szBuffer, 0, sizeof szBuffer ); - gHUD.m_TextMessage.LocaliseTextString( m_szStatusText[line_num], szBuffer, MAX_STATUSTEXT_LENGTH ); - - // parse m_szStatusText & m_iStatusValues into m_szStatusBar - memset( m_szStatusBar[line_num], 0, MAX_STATUSTEXT_LENGTH ); - char *src = szBuffer; - char *dst = m_szStatusBar[line_num]; - - char *src_start = src, *dst_start = dst; - - while ( *src != 0 ) - { - while ( *src == '\n' ) - src++; // skip over any newlines - - if ( ((src - src_start) >= MAX_STATUSTEXT_LENGTH) || ((dst - dst_start) >= MAX_STATUSTEXT_LENGTH) ) - break; - - int index = atoi( src ); - // should we draw this line? - if ( (index >= 0 && index < MAX_STATUSBAR_VALUES) && (m_iStatusValues[index] != 0) ) - { // parse this line and append result to the status bar - while ( *src >= '0' && *src <= '9' ) - src++; - - if ( *src == '\n' || *src == 0 ) - continue; // no more left in this text line - - // copy the text, char by char, until we hit a % or a \n - while ( *src != '\n' && *src != 0 ) - { - if ( *src != '%' ) - { // just copy the character - *dst = *src; - dst++, src++; - } - else - { - // get the descriptor - char valtype = *(++src); // move over % - - // if it's a %, draw a % sign - if ( valtype == '%' ) - { - *dst = valtype; - dst++, src++; - continue; - } - - // move over descriptor, then get and move over the index - index = atoi( ++src ); - while ( *src >= '0' && *src <= '9' ) - src++; - - if ( index >= 0 && index < MAX_STATUSBAR_VALUES ) - { - int indexval = m_iStatusValues[index]; - - // get the string to substitute in place of the %XX - char szRepString[MAX_PLAYER_NAME_LENGTH]; - switch ( valtype ) - { - case 'p': // player name - GetPlayerInfo( indexval, &g_PlayerInfoList[indexval] ); - if ( g_PlayerInfoList[indexval].name != NULL ) - { - strncpy( szRepString, g_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH ); - m_pflNameColors[line_num] = GetClientColor( indexval ); - } - else - { - strncpy( szRepString, "******", MAX_PLAYER_NAME_LENGTH ); - } - - break; - case 'i': // number - sprintf( szRepString, "%d", indexval ); - break; - case 'h': // health - InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Health"); - break; - case 'c': - if( indexval == 1 ) - { - InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Friend"); - } - else if( indexval == 2 ) - { - InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Enemy"); - } - else if( indexval == 3 ) - { - InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Hostage"); - } - else szRepString[0] = 0; - break; - default: - szRepString[0] = 0; - } - - for ( char *cp = szRepString; *cp != 0 && ((dst - dst_start) < MAX_STATUSTEXT_LENGTH); cp++, dst++ ) - *dst = *cp; - } - } - } - } - else - { - // skip to next line of text - while ( *src != 0 && *src != '\n' ) - src++; - } - } -} - -int CHudStatusBar :: Draw( float fTime ) -{ - if ( m_bReparseString ) - { - for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ ) - { - m_pflNameColors[i] = g_ColorYellow; - ParseStatusString( i ); - } - m_bReparseString = FALSE; - } - - if( g_iUser1 > 0 ) - { - // this is a spectator, so don't draw any statusbars - return 1; - } - - int Y_START = ScreenHeight - YRES(32 + 4); - - // Draw the status bar lines - for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ ) - { - int TextHeight, TextWidth; - DrawUtils::ConsoleStringSize( m_szStatusBar[i], &TextWidth, &TextHeight ); - - int x = 4; - int y = Y_START - ( 4 + TextHeight * i ); // draw along bottom of screen - - // let user set status ID bar centering - if ( i == STATUSBAR_ID_LINE && - hud_centerid->value != 0.0f ) - { - x = max( 0, max(2, (ScreenWidth - TextWidth)) / 2 ); - y = (ScreenHeight / 2) + (TextHeight * hud_centerid->value ); - } - - if ( m_pflNameColors[i] ) - DrawUtils::SetConsoleTextColor( m_pflNameColors[i][0], m_pflNameColors[i][1], m_pflNameColors[i][2] ); - DrawUtils::DrawConsoleString( x, y, m_szStatusBar[i] ); - } - - return 1; -} - -// Message handler for StatusText message -// accepts two values: -// byte: line number of status bar text -// string: status bar text -// this string describes how the status bar should be drawn -// a semi-regular expression: -// ( slotnum ([a..z] [%pX] [%iX])*)* -// where slotnum is an index into the Value table (see below) -// if slotnum is 0, the string is always drawn -// if StatusValue[slotnum] != 0, the following string is drawn, upto the next newline - otherwise the text is skipped upto next newline -// %pX, where X is an integer, will substitute a player name here, getting the player index from StatusValue[X] -// %iX, where X is an integer, will substitute a number here, getting the number from StatusValue[X] -int CHudStatusBar :: MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int line = READ_BYTE(); - - if ( line < 0 || line >= MAX_STATUSBAR_LINES ) - return 1; - - strncpy( m_szStatusText[line], READ_STRING(), MAX_STATUSTEXT_LENGTH ); - m_szStatusText[line][MAX_STATUSTEXT_LENGTH-1] = 0; // ensure it's null terminated ( strncpy() won't null terminate if read string too long) - - if ( m_szStatusText[0] == 0 ) - m_iFlags &= ~HUD_ACTIVE; - else - m_iFlags |= HUD_ACTIVE; // we have status text, so turn on the status bar - - m_bReparseString = TRUE; - - return 1; -} - -// Message handler for StatusText message -// accepts two values: -// byte: index into the status value array -// short: value to store -int CHudStatusBar :: MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int index = READ_BYTE(); - if ( index < 1 || index >= MAX_STATUSBAR_VALUES ) - return 1; // index out of range - - m_iStatusValues[index] = READ_SHORT(); - - m_bReparseString = TRUE; - - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// statusbar.cpp +// +// generic text status bar, set by game dll +// runs across bottom of screen +// + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" + +#include +#include + +DECLARE_MESSAGE( m_StatusBar, StatusText ); +DECLARE_MESSAGE( m_StatusBar, StatusValue ); + +extern float g_ColorYellow[3]; + +#define STATUSBAR_ID_LINE 0 + +inline void InsertTextMsg( char *szDst, size_t sLen, const char *szMsgName) +{ + client_textmessage_t *msg = TextMessageGet(szMsgName); + if( msg ) + { + strncpy( szDst, msg->pMessage, sLen ); + } + else strncpy( szDst, szMsgName, sLen ); +} + +int CHudStatusBar :: Init( void ) +{ + gHUD.AddHudElem( this ); + + HOOK_MESSAGE( StatusText ); + HOOK_MESSAGE( StatusValue ); + + Reset(); + + hud_centerid = CVAR_CREATE( "hud_centerid", "0", FCVAR_ARCHIVE ); + + return 1; +} + +int CHudStatusBar :: VidInit( void ) +{ + // Load sprites here + + return 1; +} + +void CHudStatusBar :: Reset( void ) +{ + int i = 0; + + m_iFlags &= ~HUD_ACTIVE; // start out inactive + for ( i = 0; i < MAX_STATUSBAR_LINES; i++ ) + m_szStatusText[i][0] = 0; + memset( m_iStatusValues, 0, sizeof m_iStatusValues ); + + m_iStatusValues[0] = 1; // 0 is the special index, which always returns true + + // reset our colors for the status bar lines (yellow is default) + for ( i = 0; i < MAX_STATUSBAR_LINES; i++ ) + m_pflNameColors[i] = g_ColorYellow; +} + +void CHudStatusBar :: ParseStatusString( int line_num ) +{ + // localise string first + char szBuffer[MAX_STATUSTEXT_LENGTH]; + memset( szBuffer, 0, sizeof szBuffer ); + gHUD.m_TextMessage.LocaliseTextString( m_szStatusText[line_num], szBuffer, MAX_STATUSTEXT_LENGTH ); + + // parse m_szStatusText & m_iStatusValues into m_szStatusBar + memset( m_szStatusBar[line_num], 0, MAX_STATUSTEXT_LENGTH ); + char *src = szBuffer; + char *dst = m_szStatusBar[line_num]; + + char *src_start = src, *dst_start = dst; + + while ( *src != 0 ) + { + while ( *src == '\n' ) + src++; // skip over any newlines + + if ( ((src - src_start) >= MAX_STATUSTEXT_LENGTH) || ((dst - dst_start) >= MAX_STATUSTEXT_LENGTH) ) + break; + + int index = atoi( src ); + // should we draw this line? + if ( (index >= 0 && index < MAX_STATUSBAR_VALUES) && (m_iStatusValues[index] != 0) ) + { // parse this line and append result to the status bar + while ( *src >= '0' && *src <= '9' ) + src++; + + if ( *src == '\n' || *src == 0 ) + continue; // no more left in this text line + + // copy the text, char by char, until we hit a % or a \n + while ( *src != '\n' && *src != 0 ) + { + if ( *src != '%' ) + { // just copy the character + *dst = *src; + dst++, src++; + } + else + { + // get the descriptor + char valtype = *(++src); // move over % + + // if it's a %, draw a % sign + if ( valtype == '%' ) + { + *dst = valtype; + dst++, src++; + continue; + } + + // move over descriptor, then get and move over the index + index = atoi( ++src ); + while ( *src >= '0' && *src <= '9' ) + src++; + + if ( index >= 0 && index < MAX_STATUSBAR_VALUES ) + { + int indexval = m_iStatusValues[index]; + + // get the string to substitute in place of the %XX + char szRepString[MAX_PLAYER_NAME_LENGTH]; + switch ( valtype ) + { + case 'p': // player name + GetPlayerInfo( indexval, &g_PlayerInfoList[indexval] ); + if ( g_PlayerInfoList[indexval].name != NULL ) + { + strncpy( szRepString, g_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH ); + m_pflNameColors[line_num] = GetClientColor( indexval ); + } + else + { + strncpy( szRepString, "******", MAX_PLAYER_NAME_LENGTH ); + } + + break; + case 'i': // number + sprintf( szRepString, "%d", indexval ); + break; + case 'h': // health + InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Health"); + break; + case 'c': + if( indexval == 1 ) + { + InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Friend"); + } + else if( indexval == 2 ) + { + InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Enemy"); + } + else if( indexval == 3 ) + { + InsertTextMsg(szRepString, MAX_PLAYER_NAME_LENGTH, "Hostage"); + } + else szRepString[0] = 0; + break; + default: + szRepString[0] = 0; + } + + for ( char *cp = szRepString; *cp != 0 && ((dst - dst_start) < MAX_STATUSTEXT_LENGTH); cp++, dst++ ) + *dst = *cp; + } + } + } + } + else + { + // skip to next line of text + while ( *src != 0 && *src != '\n' ) + src++; + } + } +} + +int CHudStatusBar :: Draw( float fTime ) +{ + if ( m_bReparseString ) + { + for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ ) + { + m_pflNameColors[i] = g_ColorYellow; + ParseStatusString( i ); + } + m_bReparseString = FALSE; + } + + if( g_iUser1 > 0 ) + { + // this is a spectator, so don't draw any statusbars + return 1; + } + + int Y_START = ScreenHeight - YRES(32 + 4); + + // Draw the status bar lines + for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ ) + { + int TextHeight, TextWidth; + DrawUtils::ConsoleStringSize( m_szStatusBar[i], &TextWidth, &TextHeight ); + + int x = 4; + int y = Y_START - ( 4 + TextHeight * i ); // draw along bottom of screen + + // let user set status ID bar centering + if ( i == STATUSBAR_ID_LINE && + hud_centerid->value != 0.0f ) + { + x = max( 0, max(2, (ScreenWidth - TextWidth)) / 2 ); + y = (ScreenHeight / 2) + (TextHeight * hud_centerid->value ); + } + + if ( m_pflNameColors[i] ) + DrawUtils::SetConsoleTextColor( m_pflNameColors[i][0], m_pflNameColors[i][1], m_pflNameColors[i][2] ); + DrawUtils::DrawConsoleString( x, y, m_szStatusBar[i] ); + } + + return 1; +} + +// Message handler for StatusText message +// accepts two values: +// byte: line number of status bar text +// string: status bar text +// this string describes how the status bar should be drawn +// a semi-regular expression: +// ( slotnum ([a..z] [%pX] [%iX])*)* +// where slotnum is an index into the Value table (see below) +// if slotnum is 0, the string is always drawn +// if StatusValue[slotnum] != 0, the following string is drawn, upto the next newline - otherwise the text is skipped upto next newline +// %pX, where X is an integer, will substitute a player name here, getting the player index from StatusValue[X] +// %iX, where X is an integer, will substitute a number here, getting the number from StatusValue[X] +int CHudStatusBar :: MsgFunc_StatusText( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int line = READ_BYTE(); + + if ( line < 0 || line >= MAX_STATUSBAR_LINES ) + return 1; + + strncpy( m_szStatusText[line], READ_STRING(), MAX_STATUSTEXT_LENGTH ); + m_szStatusText[line][MAX_STATUSTEXT_LENGTH-1] = 0; // ensure it's null terminated ( strncpy() won't null terminate if read string too long) + + if ( m_szStatusText[0] == 0 ) + m_iFlags &= ~HUD_ACTIVE; + else + m_iFlags |= HUD_ACTIVE; // we have status text, so turn on the status bar + + m_bReparseString = TRUE; + + return 1; +} + +// Message handler for StatusText message +// accepts two values: +// byte: index into the status value array +// short: value to store +int CHudStatusBar :: MsgFunc_StatusValue( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int index = READ_BYTE(); + if ( index < 1 || index >= MAX_STATUSBAR_VALUES ) + return 1; // index out of range + + m_iStatusValues[index] = READ_SHORT(); + + m_bReparseString = TRUE; + + return 1; +} diff --git a/cl_dll/hud/text_message.cpp b/cl_dll/hud/text_message.cpp index 38b9ccd..6ccad3f 100644 --- a/cl_dll/hud/text_message.cpp +++ b/cl_dll/hud/text_message.cpp @@ -1,249 +1,249 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// text_message.cpp -// -// implementation of CHudTextMessage class -// -// this class routes messages through titles.txt for localisation -// - -#include "hud.h" -#include "cl_util.h" -#include -#include -#include "parsemsg.h" -#include "vgui_parser.h" -#include "ctype.h" - -DECLARE_MESSAGE( m_TextMessage, TextMsg ); - -int CHudTextMessage::Init(void) -{ - HOOK_MESSAGE( TextMsg ); - - gHUD.AddHudElem( this ); - - Reset(); - - return 1; -}; - -// Searches through the string for any msg names (indicated by a '#') -// any found are looked up in titles.txt and the new message substituted -// the new value is pushed into dst_buffer -char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ) -{ - char *dst = dst_buffer; - for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- ) - { - if ( *src == '#' ) - { - // cut msg name out of string - static char word_buf[255]; - char *wdst = word_buf, *word_start = src; - for ( ++src ; (*src >= 'A' && *src <= 'z') || (*src >= '0' && *src <= '9'); wdst++, src++ ) - { - *wdst = *src; - } - *wdst = 0; - - // lookup msg name in titles.txt - client_textmessage_t *clmsg = TextMessageGet( word_buf ); - if ( !clmsg || !(clmsg->pMessage) ) - { - src = word_start; - *dst = *src; - dst++, src++; - continue; - } - - if(clmsg->pMessage[0] == '#') strncpy(dst, Localize(clmsg->pMessage+1), sizeof( dst )); - - // copy string into message over the msg name - for ( char *wsrc = (char*)clmsg->pMessage; *wsrc != 0; wsrc++, dst++ ) - { - *dst = *wsrc; - } - *dst = 0; - } - else - { - *dst = *src; - dst++, src++; - *dst = 0; - } - } - - dst_buffer[buffer_size-1] = 0; // ensure null termination - return dst_buffer; -} - -// As above, but with a local static buffer -char *CHudTextMessage::BufferedLocaliseTextString( const char *msg ) -{ - static char dst_buffer[1024]; - LocaliseTextString( msg, dst_buffer, 1024 ); - return dst_buffer; -} - -// Simplified version of LocaliseTextString; assumes string is only one word -char *CHudTextMessage::LookupString( const char *msg, int *msg_dest ) -{ - if ( !msg ) - return ""; - - // '#' character indicates this is a reference to a string in titles.txt, and not the string itself - if ( msg[0] == '#' ) - { - // this is a message name, so look up the real message - client_textmessage_t *clmsg = TextMessageGet( msg+1 ); - - if ( !clmsg || !(clmsg->pMessage) ) - return (char*)msg; // lookup failed, so return the original string - - if ( msg_dest ) - { - // check to see if titles.txt info overrides msg destination - // if clmsg->effect is less than 0, then clmsg->effect holds -1 * message_destination - if ( clmsg->effect < 0 ) // - *msg_dest = -clmsg->effect; - } - - if( clmsg->pMessage[0] == '#') - return (char *)Localize( clmsg->pMessage + 1); - - return (char*)clmsg->pMessage; - } - else - { // nothing special about this message, so just return the same string - return (char*)msg; - } -} - -void StripEndNewlineFromString( char *str ) -{ - int s = strlen( str ) - 1; - if ( str[s] == '\n' || str[s] == '\r' ) - str[s] = 0; -} - -// converts all '\r' characters to '\n', so that the engine can deal with the properly -// returns a pointer to str -char* ConvertCRtoNL( char *str ) -{ - for ( char *ch = str; *ch != 0; ch++ ) - if ( *ch == '\r' ) - *ch = '\n'; - return str; -} - -// Message handler for text messages -// displays a string, looking them up from the titles.txt file, which can be localised -// parameters: -// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK ) -// string: message -// optional parameters: -// string: message parameter 1 -// string: message parameter 2 -// string: message parameter 3 -// string: message parameter 4 -// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt -// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#') -#define MAX_TEXTMSG_STRING 256 -int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf ) -{ - BEGIN_READ( pbuf, iSize ); - - int msg_dest = READ_BYTE(); - - static char szBuf[6][MAX_TEXTMSG_STRING]; - char *msg_text = LookupString( READ_STRING(), &msg_dest ); - msg_text = strncpy( szBuf[0], msg_text, MAX_TEXTMSG_STRING ); - - // keep reading strings and using C format strings for subsituting the strings into the localised text string - char *sstr1 = LookupString( READ_STRING() ); - sstr1 = strncpy( szBuf[1], sstr1, MAX_TEXTMSG_STRING ); - StripEndNewlineFromString( sstr1 ); // these strings are meant for subsitution into the main strings, so cull the automatic end newlines - char *sstr2 = LookupString( READ_STRING() ); - sstr2 = strncpy( szBuf[2], sstr2, MAX_TEXTMSG_STRING ); - StripEndNewlineFromString( sstr2 ); - char *sstr3 = LookupString( READ_STRING() ); - sstr3 = strncpy( szBuf[3], sstr3, MAX_TEXTMSG_STRING ); - StripEndNewlineFromString( sstr3 ); - char *sstr4 = LookupString( READ_STRING() ); - sstr4 = strncpy( szBuf[4], sstr4, MAX_TEXTMSG_STRING ); - StripEndNewlineFromString( sstr4 ); - char *psz = szBuf[5]; - - // Remove numbers after %s. - // VALVEWHY? - if( strlen(msg_text) >= 3 ) - { - for( int i = 0; i < strlen(msg_text) - 2; i++) - { - if( msg_text[i] == '%' && msg_text[i + 1] == 's' && isdigit(msg_text[i + 2])) - { - char *first = &msg_text[i + 2]; - char *second = &msg_text[i + 3]; - - memmove( first, second, strlen( second )); - first[strlen(first)] = '\0'; - } - } - } - - - switch ( msg_dest ) - { - case HUD_PRINTCENTER: - snprintf( psz, MAX_TEXTMSG_STRING, msg_text, sstr1, sstr2, sstr3, sstr4 ); - CenterPrint( ConvertCRtoNL( psz ) ); - break; - - case HUD_PRINTNOTIFY: - psz[0] = 1; // mark this message to go into the notify buffer - snprintf( psz+1, MAX_TEXTMSG_STRING - 1, msg_text, sstr1, sstr2, sstr3, sstr4 ); - ConsolePrint( ConvertCRtoNL( psz ) ); - break; - - case HUD_PRINTTALK: - psz[0] = 2; // mark, so SayTextPrint will color it - snprintf( psz+1, MAX_TEXTMSG_STRING-1, msg_text, sstr1, sstr2, sstr3, sstr4 ); - gHUD.m_SayText.SayTextPrint( ConvertCRtoNL( psz ), 128 ); - break; - - case HUD_PRINTCONSOLE: - snprintf( psz, MAX_TEXTMSG_STRING, msg_text, sstr1, sstr2, sstr3, sstr4 ); - ConsolePrint( ConvertCRtoNL( psz ) ); - break; - - case HUD_PRINTRADIO: - // For some reason, HUD_PRINTRADIO always have "1" in msg_text - for( int i = 1; i < MAX_PLAYERS; i++ ) - { - if( g_PlayerInfoList[i].name && !strcmp(g_PlayerInfoList[i].name, sstr2) ) - { - psz[0] = 2; - snprintf( psz + 1, MAX_TEXTMSG_STRING-1, sstr1, sstr2, sstr3, sstr4 ); - gHUD.m_SayText.SayTextPrint( ConvertCRtoNL( psz ), 128, i ); - break; - } - } - break; - } - - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// text_message.cpp +// +// implementation of CHudTextMessage class +// +// this class routes messages through titles.txt for localisation +// + +#include "hud.h" +#include "cl_util.h" +#include +#include +#include "parsemsg.h" +#include "vgui_parser.h" +#include "ctype.h" + +DECLARE_MESSAGE( m_TextMessage, TextMsg ); + +int CHudTextMessage::Init(void) +{ + HOOK_MESSAGE( TextMsg ); + + gHUD.AddHudElem( this ); + + Reset(); + + return 1; +}; + +// Searches through the string for any msg names (indicated by a '#') +// any found are looked up in titles.txt and the new message substituted +// the new value is pushed into dst_buffer +char *CHudTextMessage::LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ) +{ + char *dst = dst_buffer; + for ( char *src = (char*)msg; *src != 0 && buffer_size > 0; buffer_size-- ) + { + if ( *src == '#' ) + { + // cut msg name out of string + static char word_buf[255]; + char *wdst = word_buf, *word_start = src; + for ( ++src ; (*src >= 'A' && *src <= 'z') || (*src >= '0' && *src <= '9'); wdst++, src++ ) + { + *wdst = *src; + } + *wdst = 0; + + // lookup msg name in titles.txt + client_textmessage_t *clmsg = TextMessageGet( word_buf ); + if ( !clmsg || !(clmsg->pMessage) ) + { + src = word_start; + *dst = *src; + dst++, src++; + continue; + } + + if(clmsg->pMessage[0] == '#') strncpy(dst, Localize(clmsg->pMessage+1), sizeof( dst )); + + // copy string into message over the msg name + for ( char *wsrc = (char*)clmsg->pMessage; *wsrc != 0; wsrc++, dst++ ) + { + *dst = *wsrc; + } + *dst = 0; + } + else + { + *dst = *src; + dst++, src++; + *dst = 0; + } + } + + dst_buffer[buffer_size-1] = 0; // ensure null termination + return dst_buffer; +} + +// As above, but with a local static buffer +char *CHudTextMessage::BufferedLocaliseTextString( const char *msg ) +{ + static char dst_buffer[1024]; + LocaliseTextString( msg, dst_buffer, 1024 ); + return dst_buffer; +} + +// Simplified version of LocaliseTextString; assumes string is only one word +char *CHudTextMessage::LookupString( const char *msg, int *msg_dest ) +{ + if ( !msg ) + return ""; + + // '#' character indicates this is a reference to a string in titles.txt, and not the string itself + if ( msg[0] == '#' ) + { + // this is a message name, so look up the real message + client_textmessage_t *clmsg = TextMessageGet( msg+1 ); + + if ( !clmsg || !(clmsg->pMessage) ) + return (char*)msg; // lookup failed, so return the original string + + if ( msg_dest ) + { + // check to see if titles.txt info overrides msg destination + // if clmsg->effect is less than 0, then clmsg->effect holds -1 * message_destination + if ( clmsg->effect < 0 ) // + *msg_dest = -clmsg->effect; + } + + if( clmsg->pMessage[0] == '#') + return (char *)Localize( clmsg->pMessage + 1); + + return (char*)clmsg->pMessage; + } + else + { // nothing special about this message, so just return the same string + return (char*)msg; + } +} + +void StripEndNewlineFromString( char *str ) +{ + int s = strlen( str ) - 1; + if ( str[s] == '\n' || str[s] == '\r' ) + str[s] = 0; +} + +// converts all '\r' characters to '\n', so that the engine can deal with the properly +// returns a pointer to str +char* ConvertCRtoNL( char *str ) +{ + for ( char *ch = str; *ch != 0; ch++ ) + if ( *ch == '\r' ) + *ch = '\n'; + return str; +} + +// Message handler for text messages +// displays a string, looking them up from the titles.txt file, which can be localised +// parameters: +// byte: message direction ( HUD_PRINTCONSOLE, HUD_PRINTNOTIFY, HUD_PRINTCENTER, HUD_PRINTTALK ) +// string: message +// optional parameters: +// string: message parameter 1 +// string: message parameter 2 +// string: message parameter 3 +// string: message parameter 4 +// any string that starts with the character '#' is a message name, and is used to look up the real message in titles.txt +// the next (optional) one to four strings are parameters for that string (which can also be message names if they begin with '#') +#define MAX_TEXTMSG_STRING 256 +int CHudTextMessage::MsgFunc_TextMsg( const char *pszName, int iSize, void *pbuf ) +{ + BEGIN_READ( pbuf, iSize ); + + int msg_dest = READ_BYTE(); + + static char szBuf[6][MAX_TEXTMSG_STRING]; + char *msg_text = LookupString( READ_STRING(), &msg_dest ); + msg_text = strncpy( szBuf[0], msg_text, MAX_TEXTMSG_STRING ); + + // keep reading strings and using C format strings for subsituting the strings into the localised text string + char *sstr1 = LookupString( READ_STRING() ); + sstr1 = strncpy( szBuf[1], sstr1, MAX_TEXTMSG_STRING ); + StripEndNewlineFromString( sstr1 ); // these strings are meant for subsitution into the main strings, so cull the automatic end newlines + char *sstr2 = LookupString( READ_STRING() ); + sstr2 = strncpy( szBuf[2], sstr2, MAX_TEXTMSG_STRING ); + StripEndNewlineFromString( sstr2 ); + char *sstr3 = LookupString( READ_STRING() ); + sstr3 = strncpy( szBuf[3], sstr3, MAX_TEXTMSG_STRING ); + StripEndNewlineFromString( sstr3 ); + char *sstr4 = LookupString( READ_STRING() ); + sstr4 = strncpy( szBuf[4], sstr4, MAX_TEXTMSG_STRING ); + StripEndNewlineFromString( sstr4 ); + char *psz = szBuf[5]; + + // Remove numbers after %s. + // VALVEWHY? + if( strlen(msg_text) >= 3 ) + { + for( int i = 0; i < strlen(msg_text) - 2; i++) + { + if( msg_text[i] == '%' && msg_text[i + 1] == 's' && isdigit(msg_text[i + 2])) + { + char *first = &msg_text[i + 2]; + char *second = &msg_text[i + 3]; + + memmove( first, second, strlen( second )); + first[strlen(first)] = '\0'; + } + } + } + + + switch ( msg_dest ) + { + case HUD_PRINTCENTER: + snprintf( psz, MAX_TEXTMSG_STRING, msg_text, sstr1, sstr2, sstr3, sstr4 ); + CenterPrint( ConvertCRtoNL( psz ) ); + break; + + case HUD_PRINTNOTIFY: + psz[0] = 1; // mark this message to go into the notify buffer + snprintf( psz+1, MAX_TEXTMSG_STRING - 1, msg_text, sstr1, sstr2, sstr3, sstr4 ); + ConsolePrint( ConvertCRtoNL( psz ) ); + break; + + case HUD_PRINTTALK: + psz[0] = 2; // mark, so SayTextPrint will color it + snprintf( psz+1, MAX_TEXTMSG_STRING-1, msg_text, sstr1, sstr2, sstr3, sstr4 ); + gHUD.m_SayText.SayTextPrint( ConvertCRtoNL( psz ), 128 ); + break; + + case HUD_PRINTCONSOLE: + snprintf( psz, MAX_TEXTMSG_STRING, msg_text, sstr1, sstr2, sstr3, sstr4 ); + ConsolePrint( ConvertCRtoNL( psz ) ); + break; + + case HUD_PRINTRADIO: + // For some reason, HUD_PRINTRADIO always have "1" in msg_text + for( int i = 1; i < MAX_PLAYERS; i++ ) + { + if( g_PlayerInfoList[i].name && !strcmp(g_PlayerInfoList[i].name, sstr2) ) + { + psz[0] = 2; + snprintf( psz + 1, MAX_TEXTMSG_STRING-1, sstr1, sstr2, sstr3, sstr4 ); + gHUD.m_SayText.SayTextPrint( ConvertCRtoNL( psz ), 128, i ); + break; + } + } + break; + } + + return 1; +} diff --git a/cl_dll/hud/timer.cpp b/cl_dll/hud/timer.cpp index c2f17f2..31e8033 100644 --- a/cl_dll/hud/timer.cpp +++ b/cl_dll/hud/timer.cpp @@ -1,217 +1,217 @@ -#include "stdio.h" -#include "stdlib.h" -#include "math.h" - -#include "hud.h" -#include "cl_util.h" -#include "parsemsg.h" -#include "vgui_parser.h" -#include - -DECLARE_MESSAGE( m_Timer, RoundTime ) -DECLARE_MESSAGE( m_Timer, ShowTimer ) - -int CHudTimer::Init() -{ - HOOK_MESSAGE( RoundTime ); - HOOK_MESSAGE( ShowTimer ); - m_iFlags = 0; - m_bPanicColorChange = false; - gHUD.AddHudElem(this); - return 1; -} - -int CHudTimer::VidInit() -{ - m_HUD_timer = gHUD.GetSpriteIndex( "stopwatch" ); - return 1; -} - -int CHudTimer::Draw( float fTime ) -{ - if ( ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH ) ) - return 1; - - if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) - return 1; - int r, g, b; - // time must be positive - int minutes = max( 0, (int)( m_iTime + m_fStartTime - gHUD.m_flTime ) / 60); - int seconds = max( 0, (int)( m_iTime + m_fStartTime - gHUD.m_flTime ) - (minutes * 60)); - - if( minutes * 60 + seconds > 20 ) - { - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH ); - } - else - { - m_flPanicTime += gHUD.m_flTimeDelta; - // add 0.1 sec, so it's not flicker fast - if( m_flPanicTime > ((float)seconds / 40.0f) + 0.1f) - { - m_flPanicTime = 0; - m_bPanicColorChange = !m_bPanicColorChange; - } - DrawUtils::UnpackRGB( r, g, b, m_bPanicColorChange ? RGB_YELLOWISH : RGB_REDISH ); - } - - DrawUtils::ScaleColors( r, g, b, MIN_ALPHA ); - - - int iWatchWidth = gHUD.GetSpriteRect(m_HUD_timer).right - gHUD.GetSpriteRect(m_HUD_timer).left; - - int x = ScreenWidth/2; - int y = ScreenHeight - 1.5 * gHUD.m_iFontHeight ; - - SPR_Set(gHUD.GetSprite(m_HUD_timer), r, g, b); - SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_timer)); - - x = DrawUtils::DrawHudNumber2( x + iWatchWidth / 4, y, false, 2, minutes, r, g, b ); - // draw : - FillRGBA(x + iWatchWidth / 4, y + gHUD.m_iFontHeight / 4, 2, 2, r, g, b, 100); - FillRGBA(x + iWatchWidth / 4, y + gHUD.m_iFontHeight - gHUD.m_iFontHeight / 4, 2, 2, r, g, b, 100); - - DrawUtils::DrawHudNumber2( x + iWatchWidth / 2, y, true, 2, seconds, r, g, b ); - return 1; -} - -int CHudTimer::MsgFunc_RoundTime(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - m_iTime = READ_SHORT(); - m_fStartTime = gHUD.m_flTime; - m_iFlags = HUD_ACTIVE; - return 1; -} - -int CHudTimer::MsgFunc_ShowTimer(const char *pszName, int iSize, void *pbuf) -{ - m_iFlags = HUD_ACTIVE; - return 1; -} - -#define UPDATE_BOTPROGRESS 0 -#define CREATE_BOTPROGRESS 1 -#define REMOVE_BOTPROGRESS 2 - -DECLARE_MESSAGE( m_ProgressBar, BarTime ) -DECLARE_MESSAGE( m_ProgressBar, BarTime2 ) -DECLARE_MESSAGE( m_ProgressBar, BotProgress ) - -int CHudProgressBar::Init() -{ - HOOK_MESSAGE( BarTime ); - HOOK_MESSAGE( BarTime2 ); - HOOK_MESSAGE( BotProgress ); - m_iFlags = 0; - m_szLocalizedHeader = NULL; - m_szHeader[0] = '\0'; - m_fStartTime = m_fPercent = 0.0f; - - gHUD.AddHudElem(this); - return 1; -} - -int CHudProgressBar::VidInit() -{ - return 1; -} - -int CHudProgressBar::Draw( float flTime ) -{ - // allow only 0.0..1.0 - if( (m_fPercent < 0.0f) || (m_fPercent > 1.0f) ) - { - m_iFlags = 0; - m_fPercent = 0.0f; - return 1; - } - - if( m_szLocalizedHeader && m_szLocalizedHeader[0] ) - { - int r, g, b; - DrawUtils::UnpackRGB( r, g, b, RGB_YELLOWISH ); - DrawUtils::DrawHudString( ScreenWidth / 4, ScreenHeight / 2, ScreenWidth, (char*)m_szLocalizedHeader, r, g, b ); - - DrawUtils::DrawRectangle( ScreenWidth/ 4, ScreenHeight / 2 + gHUD.m_scrinfo.iCharHeight, ScreenWidth/2, ScreenHeight/30 ); - FillRGBA( ScreenWidth/4+2, ScreenHeight/2 + gHUD.m_scrinfo.iCharHeight + 2, m_fPercent * (ScreenWidth/2-4), ScreenHeight/30-4, 255, 140, 0, 255 ); - return 1; - } - - // prevent SIGFPE - if( m_iDuration != 0.0f ) - { - m_fPercent = ((flTime - m_fStartTime) / m_iDuration); - } - else - { - m_fPercent = 0.0f; - m_iFlags = 0; - return 1; - } - - DrawUtils::DrawRectangle( ScreenWidth/4, ScreenHeight*2/3, ScreenWidth/2, 10 ); - FillRGBA( ScreenWidth/4+2, ScreenHeight*2/3+2, m_fPercent * (ScreenWidth/2-4), 6, 255, 140, 0, 255 ); - - return 1; -} - -int CHudProgressBar::MsgFunc_BarTime(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - m_iDuration = READ_SHORT(); - m_fPercent = 0.0f; - - m_fStartTime = gHUD.m_flTime; - - m_iFlags = HUD_ACTIVE; - return 1; -} - -int CHudProgressBar::MsgFunc_BarTime2(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - m_iDuration = READ_SHORT(); - m_fPercent = (float)READ_SHORT() / 100.0f; - - m_fStartTime = gHUD.m_flTime; - - m_iFlags = HUD_ACTIVE; - return 1; -} - -int CHudProgressBar::MsgFunc_BotProgress(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - m_iDuration = 0.0f; // don't update our progress bar - m_iFlags = HUD_ACTIVE; - - float fNewPercent; - int flag = READ_BYTE(); - switch( flag ) - { - case UPDATE_BOTPROGRESS: - case CREATE_BOTPROGRESS: - fNewPercent = (float)READ_BYTE() / 100.0f; - // cs behavior: - // just don't decrease percent values - if( m_fPercent < fNewPercent ) - { - m_fPercent = fNewPercent; - } - strncpy(m_szHeader, READ_STRING(), sizeof(m_szHeader)); - m_szLocalizedHeader = Localize(m_szHeader + 1); - break; - case REMOVE_BOTPROGRESS: - default: - m_fPercent = 0.0f; - m_szHeader[0] = '\0'; - m_iFlags = 0; - m_szLocalizedHeader = NULL; - break; - } - - return 1; -} +#include "stdio.h" +#include "stdlib.h" +#include "math.h" + +#include "hud.h" +#include "cl_util.h" +#include "parsemsg.h" +#include "vgui_parser.h" +#include + +DECLARE_MESSAGE( m_Timer, RoundTime ) +DECLARE_MESSAGE( m_Timer, ShowTimer ) + +int CHudTimer::Init() +{ + HOOK_MESSAGE( RoundTime ); + HOOK_MESSAGE( ShowTimer ); + m_iFlags = 0; + m_bPanicColorChange = false; + gHUD.AddHudElem(this); + return 1; +} + +int CHudTimer::VidInit() +{ + m_HUD_timer = gHUD.GetSpriteIndex( "stopwatch" ); + return 1; +} + +int CHudTimer::Draw( float fTime ) +{ + if ( ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH ) ) + return 1; + + if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) + return 1; + int r, g, b; + // time must be positive + int minutes = max( 0, (int)( m_iTime + m_fStartTime - gHUD.m_flTime ) / 60); + int seconds = max( 0, (int)( m_iTime + m_fStartTime - gHUD.m_flTime ) - (minutes * 60)); + + if( minutes * 60 + seconds > 20 ) + { + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH ); + } + else + { + m_flPanicTime += gHUD.m_flTimeDelta; + // add 0.1 sec, so it's not flicker fast + if( m_flPanicTime > ((float)seconds / 40.0f) + 0.1f) + { + m_flPanicTime = 0; + m_bPanicColorChange = !m_bPanicColorChange; + } + DrawUtils::UnpackRGB( r, g, b, m_bPanicColorChange ? RGB_YELLOWISH : RGB_REDISH ); + } + + DrawUtils::ScaleColors( r, g, b, MIN_ALPHA ); + + + int iWatchWidth = gHUD.GetSpriteRect(m_HUD_timer).right - gHUD.GetSpriteRect(m_HUD_timer).left; + + int x = ScreenWidth/2; + int y = ScreenHeight - 1.5 * gHUD.m_iFontHeight ; + + SPR_Set(gHUD.GetSprite(m_HUD_timer), r, g, b); + SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_timer)); + + x = DrawUtils::DrawHudNumber2( x + iWatchWidth / 4, y, false, 2, minutes, r, g, b ); + // draw : + FillRGBA(x + iWatchWidth / 4, y + gHUD.m_iFontHeight / 4, 2, 2, r, g, b, 100); + FillRGBA(x + iWatchWidth / 4, y + gHUD.m_iFontHeight - gHUD.m_iFontHeight / 4, 2, 2, r, g, b, 100); + + DrawUtils::DrawHudNumber2( x + iWatchWidth / 2, y, true, 2, seconds, r, g, b ); + return 1; +} + +int CHudTimer::MsgFunc_RoundTime(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + m_iTime = READ_SHORT(); + m_fStartTime = gHUD.m_flTime; + m_iFlags = HUD_ACTIVE; + return 1; +} + +int CHudTimer::MsgFunc_ShowTimer(const char *pszName, int iSize, void *pbuf) +{ + m_iFlags = HUD_ACTIVE; + return 1; +} + +#define UPDATE_BOTPROGRESS 0 +#define CREATE_BOTPROGRESS 1 +#define REMOVE_BOTPROGRESS 2 + +DECLARE_MESSAGE( m_ProgressBar, BarTime ) +DECLARE_MESSAGE( m_ProgressBar, BarTime2 ) +DECLARE_MESSAGE( m_ProgressBar, BotProgress ) + +int CHudProgressBar::Init() +{ + HOOK_MESSAGE( BarTime ); + HOOK_MESSAGE( BarTime2 ); + HOOK_MESSAGE( BotProgress ); + m_iFlags = 0; + m_szLocalizedHeader = NULL; + m_szHeader[0] = '\0'; + m_fStartTime = m_fPercent = 0.0f; + + gHUD.AddHudElem(this); + return 1; +} + +int CHudProgressBar::VidInit() +{ + return 1; +} + +int CHudProgressBar::Draw( float flTime ) +{ + // allow only 0.0..1.0 + if( (m_fPercent < 0.0f) || (m_fPercent > 1.0f) ) + { + m_iFlags = 0; + m_fPercent = 0.0f; + return 1; + } + + if( m_szLocalizedHeader && m_szLocalizedHeader[0] ) + { + int r, g, b; + DrawUtils::UnpackRGB( r, g, b, RGB_YELLOWISH ); + DrawUtils::DrawHudString( ScreenWidth / 4, ScreenHeight / 2, ScreenWidth, (char*)m_szLocalizedHeader, r, g, b ); + + DrawUtils::DrawRectangle( ScreenWidth/ 4, ScreenHeight / 2 + gHUD.m_scrinfo.iCharHeight, ScreenWidth/2, ScreenHeight/30 ); + FillRGBA( ScreenWidth/4+2, ScreenHeight/2 + gHUD.m_scrinfo.iCharHeight + 2, m_fPercent * (ScreenWidth/2-4), ScreenHeight/30-4, 255, 140, 0, 255 ); + return 1; + } + + // prevent SIGFPE + if( m_iDuration != 0.0f ) + { + m_fPercent = ((flTime - m_fStartTime) / m_iDuration); + } + else + { + m_fPercent = 0.0f; + m_iFlags = 0; + return 1; + } + + DrawUtils::DrawRectangle( ScreenWidth/4, ScreenHeight*2/3, ScreenWidth/2, 10 ); + FillRGBA( ScreenWidth/4+2, ScreenHeight*2/3+2, m_fPercent * (ScreenWidth/2-4), 6, 255, 140, 0, 255 ); + + return 1; +} + +int CHudProgressBar::MsgFunc_BarTime(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + m_iDuration = READ_SHORT(); + m_fPercent = 0.0f; + + m_fStartTime = gHUD.m_flTime; + + m_iFlags = HUD_ACTIVE; + return 1; +} + +int CHudProgressBar::MsgFunc_BarTime2(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + m_iDuration = READ_SHORT(); + m_fPercent = (float)READ_SHORT() / 100.0f; + + m_fStartTime = gHUD.m_flTime; + + m_iFlags = HUD_ACTIVE; + return 1; +} + +int CHudProgressBar::MsgFunc_BotProgress(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + m_iDuration = 0.0f; // don't update our progress bar + m_iFlags = HUD_ACTIVE; + + float fNewPercent; + int flag = READ_BYTE(); + switch( flag ) + { + case UPDATE_BOTPROGRESS: + case CREATE_BOTPROGRESS: + fNewPercent = (float)READ_BYTE() / 100.0f; + // cs behavior: + // just don't decrease percent values + if( m_fPercent < fNewPercent ) + { + m_fPercent = fNewPercent; + } + strncpy(m_szHeader, READ_STRING(), sizeof(m_szHeader)); + m_szLocalizedHeader = Localize(m_szHeader + 1); + break; + case REMOVE_BOTPROGRESS: + default: + m_fPercent = 0.0f; + m_szHeader[0] = '\0'; + m_iFlags = 0; + m_szLocalizedHeader = NULL; + break; + } + + return 1; +} diff --git a/cl_dll/hud/train.cpp b/cl_dll/hud/train.cpp index 9e67c6d..22a6167 100644 --- a/cl_dll/hud/train.cpp +++ b/cl_dll/hud/train.cpp @@ -1,85 +1,85 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// Train.cpp -// -// implementation of CHudAmmo class -// - -#include "hud.h" -#include "cl_util.h" -#include -#include -#include "parsemsg.h" - -DECLARE_MESSAGE(m_Train, Train ) - - -int CHudTrain::Init(void) -{ - HOOK_MESSAGE( Train ); - - m_iPos = 0; - m_iFlags = 0; - gHUD.AddHudElem(this); - - return 1; -}; - -int CHudTrain::VidInit(void) -{ - m_hSprite = 0; - - return 1; -}; - -int CHudTrain::Draw(float fTime) -{ - if ( !m_hSprite ) - m_hSprite = LoadSprite("sprites/%d_train.spr"); - - if (m_iPos) - { - int r, g, b, x, y; - - DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); - SPR_Set(m_hSprite, r, g, b ); - - // This should show up to the right and part way up the armor number - y = ScreenHeight - SPR_Height(m_hSprite,0) - gHUD.m_iFontHeight; - x = ScreenWidth/3 + SPR_Width(m_hSprite,0)/4; - - SPR_DrawAdditive( m_iPos - 1, x, y, NULL); - - } - - return 1; -} - - -int CHudTrain::MsgFunc_Train(const char *pszName, int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - // update Train data - m_iPos = READ_BYTE(); - - if (m_iPos) - m_iFlags |= HUD_ACTIVE; - else - m_iFlags &= ~HUD_ACTIVE; - - return 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// Train.cpp +// +// implementation of CHudAmmo class +// + +#include "hud.h" +#include "cl_util.h" +#include +#include +#include "parsemsg.h" + +DECLARE_MESSAGE(m_Train, Train ) + + +int CHudTrain::Init(void) +{ + HOOK_MESSAGE( Train ); + + m_iPos = 0; + m_iFlags = 0; + gHUD.AddHudElem(this); + + return 1; +}; + +int CHudTrain::VidInit(void) +{ + m_hSprite = 0; + + return 1; +}; + +int CHudTrain::Draw(float fTime) +{ + if ( !m_hSprite ) + m_hSprite = LoadSprite("sprites/%d_train.spr"); + + if (m_iPos) + { + int r, g, b, x, y; + + DrawUtils::UnpackRGB(r,g,b, RGB_YELLOWISH); + SPR_Set(m_hSprite, r, g, b ); + + // This should show up to the right and part way up the armor number + y = ScreenHeight - SPR_Height(m_hSprite,0) - gHUD.m_iFontHeight; + x = ScreenWidth/3 + SPR_Width(m_hSprite,0)/4; + + SPR_DrawAdditive( m_iPos - 1, x, y, NULL); + + } + + return 1; +} + + +int CHudTrain::MsgFunc_Train(const char *pszName, int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + // update Train data + m_iPos = READ_BYTE(); + + if (m_iPos) + m_iFlags |= HUD_ACTIVE; + else + m_iFlags &= ~HUD_ACTIVE; + + return 1; +} diff --git a/cl_dll/in_camera.cpp b/cl_dll/in_camera.cpp index facd88f..d8dd0a9 100644 --- a/cl_dll/in_camera.cpp +++ b/cl_dll/in_camera.cpp @@ -1,621 +1,621 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#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" -#ifdef _WIN32 -#include "port.h" -#endif -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( fabs( 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]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.x225.0)) - if (camAngles[YAW]>c_minyaw->value) - { - camAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((gEngfuncs.GetWindowCenterX()-cam_mouse.x)/2); - - } - if (camAngles[YAW]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]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.yc_minpitch->value) - { - camAngles[PITCH] -= (CAM_ANGLE_MOVE)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2); - } - if (camAngles[PITCH]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(distvalue) - { - dist +=CAM_DIST_DELTA * ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2); - } - if (dist>c_maxdistance->value) - { - dist=c_maxdistance->value; - } - } - else if (cam_mouse.yc_mindistance->value) - { - dist -= (CAM_DIST_DELTA)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2); - } - if (distvalue) - { - 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( fabs( 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) || (g_iUser1 && (g_iUser2 == gEngfuncs.GetLocalPlayer()->index) ); -} - -void DLLEXPORT CL_CameraOffset( float *ofs ) -{ - VectorCopy( cam_ofs, ofs ); -} +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#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" +#ifdef _WIN32 +#include "port.h" +#endif +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( fabs( 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]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.x225.0)) + if (camAngles[YAW]>c_minyaw->value) + { + camAngles[ YAW ] -= (CAM_ANGLE_MOVE)* ((gEngfuncs.GetWindowCenterX()-cam_mouse.x)/2); + + } + if (camAngles[YAW]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]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.yc_minpitch->value) + { + camAngles[PITCH] -= (CAM_ANGLE_MOVE)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2); + } + if (camAngles[PITCH]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(distvalue) + { + dist +=CAM_DIST_DELTA * ((cam_mouse.y-gEngfuncs.GetWindowCenterY())/2); + } + if (dist>c_maxdistance->value) + { + dist=c_maxdistance->value; + } + } + else if (cam_mouse.yc_mindistance->value) + { + dist -= (CAM_DIST_DELTA)*((gEngfuncs.GetWindowCenterY()-cam_mouse.y)/2); + } + if (distvalue) + { + 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( fabs( 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) || (g_iUser1 && (g_iUser2 == gEngfuncs.GetLocalPlayer()->index) ); +} + +void DLLEXPORT CL_CameraOffset( float *ofs ) +{ + VectorCopy( cam_ofs, ofs ); +} diff --git a/cl_dll/include/camera.h b/cl_dll/include/camera.h index 644429b..0ef4ccd 100644 --- a/cl_dll/include/camera.h +++ b/cl_dll/include/camera.h @@ -1,24 +1,24 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// Camera.h -- defines and such for a 3rd person camera -// NOTE: must include quakedef.h first -#pragma once -#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_ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// Camera.h -- defines and such for a 3rd person camera +// NOTE: must include quakedef.h first +#pragma once +#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_ diff --git a/cl_dll/include/cl_dll.h b/cl_dll/include/cl_dll.h index dab8f1f..70832b4 100644 --- a/cl_dll/include/cl_dll.h +++ b/cl_dll/include/cl_dll.h @@ -1,50 +1,50 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// cl_dll.h -// - -// 4-23-98 JOHN -#pragma once -// -// This DLL is linked by the client when they first initialize. -// This DLL is responsible for the following tasks: -// - Loading the HUD graphics upon initialization -// - Drawing the HUD graphics every frame -// - Handling the custum HUD-update packets -// -typedef unsigned char byte; -typedef unsigned short word; -typedef float vec_t; -typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf); -#define _cdecl -#include "util_vector.h" -#ifdef _WIN32 -#define EXPORT _declspec( dllexport ) -#else -#define EXPORT -#define stricmp strcasecmp -#define strnicmp strncasecmp -#define stristr strcasestr -#define strnistr strncasestr -#endif -#include "../engine/cdll_int.h" -#include "../dlls/cdll_dll.h" -#include "render_api.h" -#include "mobility_int.h" -extern cl_enginefunc_t gEngfuncs; -extern render_api_t gRenderAPI; -extern mobile_engfuncs_t gMobileAPI; -extern int g_iXash; +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// cl_dll.h +// + +// 4-23-98 JOHN +#pragma once +// +// This DLL is linked by the client when they first initialize. +// This DLL is responsible for the following tasks: +// - Loading the HUD graphics upon initialization +// - Drawing the HUD graphics every frame +// - Handling the custum HUD-update packets +// +typedef unsigned char byte; +typedef unsigned short word; +typedef float vec_t; +typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf); +#define _cdecl +#include "util_vector.h" +#ifdef _WIN32 +#define EXPORT _declspec( dllexport ) +#else +#define EXPORT +#define stricmp strcasecmp +#define strnicmp strncasecmp +#define stristr strcasestr +#define strnistr strncasestr +#endif +#include "../engine/cdll_int.h" +#include "../dlls/cdll_dll.h" +#include "render_api.h" +#include "mobility_int.h" +extern cl_enginefunc_t gEngfuncs; +extern render_api_t gRenderAPI; +extern mobile_engfuncs_t gMobileAPI; +extern int g_iXash; diff --git a/cl_dll/include/cl_util.h b/cl_dll/include/cl_util.h index ab41680..6781234 100644 --- a/cl_dll/include/cl_util.h +++ b/cl_dll/include/cl_util.h @@ -1,141 +1,141 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// cl_util.h -// -#pragma once -#include "cvardef.h" -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -extern cvar_t *hud_textmode; - -#ifdef _MSC_VER -#pragma warning(disable : 4244) // 'argument': conversion from 'float' to 'int', possible loss of data -#pragma warning(disable : 4101) // unreferenced local variable -#endif - -// Macros to hook function calls into the HUD object -#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x ); - -#define DECLARE_MESSAGE(y, x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \ -{ \ - return gHUD.y.MsgFunc_##x(pszName, iSize, pbuf ); \ - } - -#define HOOK_COMMAND(x, y) gEngfuncs.pfnAddCommand( x, __CmdFunc_##y ); -#define DECLARE_COMMAND(y, x) void __CmdFunc_##x( void ) \ -{ \ - gHUD.y.UserCmd_##x( ); \ - } - -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 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) -#define SPR_Frames (*gEngfuncs.pfnSPR_Frames) -#define SPR_GetList (*gEngfuncs.pfnSPR_GetList) - -// SPR_Draw draws a the current sprite as solid -#define SPR_Draw (*gEngfuncs.pfnSPR_Draw) -// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent) -#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles) -// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency) -#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive) - -// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen. -#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor) -// SPR_DisableScissor disables the clipping rect -#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor) -// -#define FillRGBA (*gEngfuncs.pfnFillRGBA) -#define FillRGBABlend (*gEngfuncs.pfnFillRGBABlend) - - -// ScreenHeight returns the height of the screen, in pixels -#define ScreenHeight (gHUD.m_scrinfo.iHeight) -// ScreenWidth returns the width of the screen, in pixels -#define ScreenWidth (gHUD.m_scrinfo.iWidth) - -#define TrueHeight (gHUD.m_truescrinfo.iHeight) -#define TrueWidth (gHUD.m_truescrinfo.iWidth) - -// Use this to set any co-ords in 640x480 space -#define XRES(x) ((int)(float(x) * ((float)ScreenWidth / 640.0f) + 0.5f)) -#define YRES(y) ((int)(float(y) * ((float)ScreenHeight / 480.0f) + 0.5f)) - -// use this to project world coordinates to screen coordinates -#define XPROJECT(x) ( (1.0f+(x))*ScreenWidth*0.5f ) -#define YPROJECT(y) ( (1.0f-(y))*ScreenHeight*0.5f ) - -#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) -#define ServerCmd (*gEngfuncs.pfnServerCmd) -#define ClientCmd (*gEngfuncs.pfnClientCmd) -#define SetCrosshair (*gEngfuncs.pfnSetCrosshair) -#define AngleVectors (*gEngfuncs.pfnAngleVectors) -extern float color[3]; // hud.cpp - -// Gets the height & width of a sprite, at the specified frame -inline int SPR_Height( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Height(x, f); } -inline int SPR_Width( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Width(x, f); } - -inline client_textmessage_t *TextMessageGet( const char *pName ) { return gEngfuncs.pfnTextMessageGet( pName ); } - -inline void ConsolePrint( const char *string ) -{ - gEngfuncs.pfnConsolePrint( string ); -} - -inline void CenterPrint( const char *string ) -{ - gEngfuncs.pfnCenterPrint( string ); -} - -// returns the players name of entity no. -#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo) - -// sound functions -inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); } -inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); } - -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#define fabs(x) ((x) > 0 ? (x) : 0 - (x)) -#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];} -inline void VectorClear(float *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 ) -// disable 'truncation from 'const double' to 'float' warning message -#pragma warning( disable: 4305 ) - -HSPRITE LoadSprite(const char *pszName); -float *GetClientColor( int clientIndex ); -void GetTeamColor( int &r, int &g, int &b, int teamIndex ); -#define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min)) +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// cl_util.h +// +#pragma once +#include "cvardef.h" +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +extern cvar_t *hud_textmode; + +#ifdef _MSC_VER +#pragma warning(disable : 4244) // 'argument': conversion from 'float' to 'int', possible loss of data +#pragma warning(disable : 4101) // unreferenced local variable +#endif + +// Macros to hook function calls into the HUD object +#define HOOK_MESSAGE(x) gEngfuncs.pfnHookUserMsg(#x, __MsgFunc_##x ); + +#define DECLARE_MESSAGE(y, x) int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf) \ +{ \ + return gHUD.y.MsgFunc_##x(pszName, iSize, pbuf ); \ + } + +#define HOOK_COMMAND(x, y) gEngfuncs.pfnAddCommand( x, __CmdFunc_##y ); +#define DECLARE_COMMAND(y, x) void __CmdFunc_##x( void ) \ +{ \ + gHUD.y.UserCmd_##x( ); \ + } + +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 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) +#define SPR_Frames (*gEngfuncs.pfnSPR_Frames) +#define SPR_GetList (*gEngfuncs.pfnSPR_GetList) + +// SPR_Draw draws a the current sprite as solid +#define SPR_Draw (*gEngfuncs.pfnSPR_Draw) +// SPR_DrawHoles draws the current sprites, with color index255 not drawn (transparent) +#define SPR_DrawHoles (*gEngfuncs.pfnSPR_DrawHoles) +// SPR_DrawAdditive adds the sprites RGB values to the background (additive transulency) +#define SPR_DrawAdditive (*gEngfuncs.pfnSPR_DrawAdditive) + +// SPR_EnableScissor sets a clipping rect for HUD sprites. (0,0) is the top-left hand corner of the screen. +#define SPR_EnableScissor (*gEngfuncs.pfnSPR_EnableScissor) +// SPR_DisableScissor disables the clipping rect +#define SPR_DisableScissor (*gEngfuncs.pfnSPR_DisableScissor) +// +#define FillRGBA (*gEngfuncs.pfnFillRGBA) +#define FillRGBABlend (*gEngfuncs.pfnFillRGBABlend) + + +// ScreenHeight returns the height of the screen, in pixels +#define ScreenHeight (gHUD.m_scrinfo.iHeight) +// ScreenWidth returns the width of the screen, in pixels +#define ScreenWidth (gHUD.m_scrinfo.iWidth) + +#define TrueHeight (gHUD.m_truescrinfo.iHeight) +#define TrueWidth (gHUD.m_truescrinfo.iWidth) + +// Use this to set any co-ords in 640x480 space +#define XRES(x) ((int)(float(x) * ((float)ScreenWidth / 640.0f) + 0.5f)) +#define YRES(y) ((int)(float(y) * ((float)ScreenHeight / 480.0f) + 0.5f)) + +// use this to project world coordinates to screen coordinates +#define XPROJECT(x) ( (1.0f+(x))*ScreenWidth*0.5f ) +#define YPROJECT(y) ( (1.0f-(y))*ScreenHeight*0.5f ) + +#define GetScreenInfo (*gEngfuncs.pfnGetScreenInfo) +#define ServerCmd (*gEngfuncs.pfnServerCmd) +#define ClientCmd (*gEngfuncs.pfnClientCmd) +#define SetCrosshair (*gEngfuncs.pfnSetCrosshair) +#define AngleVectors (*gEngfuncs.pfnAngleVectors) +extern float color[3]; // hud.cpp + +// Gets the height & width of a sprite, at the specified frame +inline int SPR_Height( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Height(x, f); } +inline int SPR_Width( HSPRITE x, int f ) { return gEngfuncs.pfnSPR_Width(x, f); } + +inline client_textmessage_t *TextMessageGet( const char *pName ) { return gEngfuncs.pfnTextMessageGet( pName ); } + +inline void ConsolePrint( const char *string ) +{ + gEngfuncs.pfnConsolePrint( string ); +} + +inline void CenterPrint( const char *string ) +{ + gEngfuncs.pfnCenterPrint( string ); +} + +// returns the players name of entity no. +#define GetPlayerInfo (*gEngfuncs.pfnGetPlayerInfo) + +// sound functions +inline void PlaySound( char *szSound, float vol ) { gEngfuncs.pfnPlaySoundByName( szSound, vol ); } +inline void PlaySound( int iSound, float vol ) { gEngfuncs.pfnPlaySoundByIndex( iSound, vol ); } + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define fabs(x) ((x) > 0 ? (x) : 0 - (x)) +#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];} +inline void VectorClear(float *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 ) +// disable 'truncation from 'const double' to 'float' warning message +#pragma warning( disable: 4305 ) + +HSPRITE LoadSprite(const char *pszName); +float *GetClientColor( int clientIndex ); +void GetTeamColor( int &r, int &g, int &b, int teamIndex ); +#define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min)) diff --git a/cl_dll/include/com_weapons.h b/cl_dll/include/com_weapons.h index 3b092da..84458c0 100644 --- a/cl_dll/include/com_weapons.h +++ b/cl_dll/include/com_weapons.h @@ -1,79 +1,79 @@ -//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -// com_weapons.h -// Shared weapons common function prototypes -#if !defined( COM_WEAPONSH ) -#define COM_WEAPONSH - - -#include "hud_iface.h" - -#define PLAYER_CAN_SHOOT (1 << 0) -#define PLAYER_FREEZE_TIME_OVER ( 1 << 1 ) -#define PLAYER_IN_BOMB_ZONE (1 << 2) -#define PLAYER_HOLDING_SHIELD (1 << 3) - -#define CROSSHAIR_ -#define ACCURACY_AIR (1 << 0) // accuracy depends on FL_ONGROUND -#define ACCURACY_SPEED (1 << 1) -#define ACCURACY_DUCK (1 << 2) // more accurate when ducking -#define ACCURACY_MULTIPLY_BY_14 (1 << 3) // accuracy multiply to 1.4 -#define ACCURACY_MULTIPLY_BY_14_2 (1 << 4) // accuracy multiply to 1.4 - -#ifndef WPNSTATE_USP_SILENCED -#define WPNSTATE_USP_SILENCED (1<<0) -#define WPNSTATE_GLOCK18_BURST_MODE (1<<1) -#define WPNSTATE_M4A1_SILENCED (1<<2) -#define WPNSTATE_ELITE_LEFT (1<<3) -#define WPNSTATE_FAMAS_BURST_MODE (1<<4) -#define WPNSTATE_SHIELD_DRAWN (1<<5) -#endif - - -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 iWeaponId, int iBody, int iForce ); -int HUD_GetWeapon( void ); -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 int function ); -void stub_SetModel ( struct edict_s *e, const char *m ); -int GetWeaponAccuracyFlags( int weaponid ); - -extern cvar_t *cl_lw; - -extern int g_runfuncs; -extern vec3_t v_angles; -extern float g_lastFOV; -extern int g_iWeaponFlags; -extern bool g_bInBombZone; -extern int g_iFreezeTimeOver; -extern bool g_bHoldingShield; -extern bool g_bHoldingKnife; -extern int g_iPlayerFlags; -extern vec3_t g_vPlayerVelocity; -extern float g_flPlayerSpeed; -extern struct local_state_s *g_curstate; -extern struct local_state_s *g_finalstate; -extern int g_iShotsFired; - -#endif +//========= Copyright � 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +// com_weapons.h +// Shared weapons common function prototypes +#if !defined( COM_WEAPONSH ) +#define COM_WEAPONSH + + +#include "hud_iface.h" + +#define PLAYER_CAN_SHOOT (1 << 0) +#define PLAYER_FREEZE_TIME_OVER ( 1 << 1 ) +#define PLAYER_IN_BOMB_ZONE (1 << 2) +#define PLAYER_HOLDING_SHIELD (1 << 3) + +#define CROSSHAIR_ +#define ACCURACY_AIR (1 << 0) // accuracy depends on FL_ONGROUND +#define ACCURACY_SPEED (1 << 1) +#define ACCURACY_DUCK (1 << 2) // more accurate when ducking +#define ACCURACY_MULTIPLY_BY_14 (1 << 3) // accuracy multiply to 1.4 +#define ACCURACY_MULTIPLY_BY_14_2 (1 << 4) // accuracy multiply to 1.4 + +#ifndef WPNSTATE_USP_SILENCED +#define WPNSTATE_USP_SILENCED (1<<0) +#define WPNSTATE_GLOCK18_BURST_MODE (1<<1) +#define WPNSTATE_M4A1_SILENCED (1<<2) +#define WPNSTATE_ELITE_LEFT (1<<3) +#define WPNSTATE_FAMAS_BURST_MODE (1<<4) +#define WPNSTATE_SHIELD_DRAWN (1<<5) +#endif + + +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 iWeaponId, int iBody, int iForce ); +int HUD_GetWeapon( void ); +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 int function ); +void stub_SetModel ( struct edict_s *e, const char *m ); +int GetWeaponAccuracyFlags( int weaponid ); + +extern cvar_t *cl_lw; + +extern int g_runfuncs; +extern vec3_t v_angles; +extern float g_lastFOV; +extern int g_iWeaponFlags; +extern bool g_bInBombZone; +extern int g_iFreezeTimeOver; +extern bool g_bHoldingShield; +extern bool g_bHoldingKnife; +extern int g_iPlayerFlags; +extern vec3_t g_vPlayerVelocity; +extern float g_flPlayerSpeed; +extern struct local_state_s *g_curstate; +extern struct local_state_s *g_finalstate; +extern int g_iShotsFired; + +#endif diff --git a/cl_dll/include/demo.h b/cl_dll/include/demo.h index a337e40..b14ef22 100644 --- a/cl_dll/include/demo.h +++ b/cl_dll/include/demo.h @@ -1,26 +1,26 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined( DEMOH ) -#define DEMOH - -// 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; - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined( DEMOH ) +#define DEMOH + +// 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 \ No newline at end of file diff --git a/cl_dll/include/ev_hldm.h b/cl_dll/include/ev_hldm.h index de59007..5061483 100644 --- a/cl_dll/include/ev_hldm.h +++ b/cl_dll/include/ev_hldm.h @@ -1,44 +1,44 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined ( EV_HLDMH ) -#define EV_HLDMH - -// bullet types -typedef enum -{ - BULLET_NONE = 0, - BULLET_PLAYER_9MM, - BULLET_PLAYER_MP5, - BULLET_PLAYER_357, - BULLET_PLAYER_BUCKSHOT, - BULLET_PLAYER_CROWBAR, - - BULLET_MONSTER_9MM, - BULLET_MONSTER_MP5, - BULLET_MONSTER_12MM, - - BULLET_PLAYER_45ACP, - BULLET_PLAYER_338MAG, - BULLET_PLAYER_762MM, - BULLET_PLAYER_556MM, - BULLET_PLAYER_50AE, - BULLET_PLAYER_57MM, - BULLET_PLAYER_357SIG -} -Bullet; - -void EV_HLDM_GunshotDecalTrace(pmtrace_t *pTrace, char *decalName , char chTextureType); -void EV_HLDM_DecalGunshot(pmtrace_t *pTrace, int iBulletType, float scale, int r, int g, int b, bool bCreateSparks, char cTextureType); -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, int iPenetration); -void EV_CS16Client_KillEveryRound( struct tempent_s *te, float frametime, float currenttime ); -#endif // EV_HLDMH +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined ( EV_HLDMH ) +#define EV_HLDMH + +// bullet types +typedef enum +{ + BULLET_NONE = 0, + BULLET_PLAYER_9MM, + BULLET_PLAYER_MP5, + BULLET_PLAYER_357, + BULLET_PLAYER_BUCKSHOT, + BULLET_PLAYER_CROWBAR, + + BULLET_MONSTER_9MM, + BULLET_MONSTER_MP5, + BULLET_MONSTER_12MM, + + BULLET_PLAYER_45ACP, + BULLET_PLAYER_338MAG, + BULLET_PLAYER_762MM, + BULLET_PLAYER_556MM, + BULLET_PLAYER_50AE, + BULLET_PLAYER_57MM, + BULLET_PLAYER_357SIG +} +Bullet; + +void EV_HLDM_GunshotDecalTrace(pmtrace_t *pTrace, char *decalName , char chTextureType); +void EV_HLDM_DecalGunshot(pmtrace_t *pTrace, int iBulletType, float scale, int r, int g, int b, bool bCreateSparks, char cTextureType); +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, int iPenetration); +void EV_CS16Client_KillEveryRound( struct tempent_s *te, float frametime, float currenttime ); +#endif // EV_HLDMH diff --git a/cl_dll/include/eventscripts.h b/cl_dll/include/eventscripts.h index 07290ea..4849475 100644 --- a/cl_dll/include/eventscripts.h +++ b/cl_dll/include/eventscripts.h @@ -1,75 +1,75 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -// 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, int life = 2.5 ); -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 ); -void CreateCorpse(Vector *p_vOrigin, Vector *p_vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody); - - -struct cl_entity_s *GetEntity( int idx ); -struct cl_entity_s *GetViewEntity( void ); -void EV_MuzzleFlash( void ); - -#endif // EVENTSCRIPTSH +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +// 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, int life = 2.5 ); +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 ); +void CreateCorpse(Vector *p_vOrigin, Vector *p_vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody); + + +struct cl_entity_s *GetEntity( int idx ); +struct cl_entity_s *GetViewEntity( void ); +void EV_MuzzleFlash( void ); + +#endif // EVENTSCRIPTSH diff --git a/cl_dll/include/hud/ammo.h b/cl_dll/include/hud/ammo.h index 7577d1f..72bc8ae 100644 --- a/cl_dll/include/hud/ammo.h +++ b/cl_dll/include/hud/ammo.h @@ -1,62 +1,62 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#pragma once -#ifndef __AMMO_H__ -#define __AMMO_H__ - -#define MAX_WEAPON_NAME 128 - - -#define WEAPON_FLAGS_SELECTONEMPTY 1 - -#define WEAPON_IS_ONTARGET 0x40 - -struct WEAPON -{ - char szName[MAX_WEAPON_NAME]; - int iAmmoType; - int iAmmo2Type; - int iMax1; - int iMax2; - int iSlot; - int iSlotPos; - int iFlags; - int iId; - int iClip; - - int iCount; // # of itesm in plist - - HSPRITE hActive; - wrect_t rcActive; - HSPRITE hInactive; - wrect_t rcInactive; - HSPRITE hAmmo; - wrect_t rcAmmo; - HSPRITE hAmmo2; - wrect_t rcAmmo2; - HSPRITE hCrosshair; - wrect_t rcCrosshair; - HSPRITE hAutoaim; - wrect_t rcAutoaim; - HSPRITE hZoomedCrosshair; - wrect_t rcZoomedCrosshair; - HSPRITE hZoomedAutoaim; - wrect_t rcZoomedAutoaim; -}; - -typedef int AMMO; - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#pragma once +#ifndef __AMMO_H__ +#define __AMMO_H__ + +#define MAX_WEAPON_NAME 128 + + +#define WEAPON_FLAGS_SELECTONEMPTY 1 + +#define WEAPON_IS_ONTARGET 0x40 + +struct WEAPON +{ + char szName[MAX_WEAPON_NAME]; + int iAmmoType; + int iAmmo2Type; + int iMax1; + int iMax2; + int iSlot; + int iSlotPos; + int iFlags; + int iId; + int iClip; + + int iCount; // # of itesm in plist + + HSPRITE hActive; + wrect_t rcActive; + HSPRITE hInactive; + wrect_t rcInactive; + HSPRITE hAmmo; + wrect_t rcAmmo; + HSPRITE hAmmo2; + wrect_t rcAmmo2; + HSPRITE hCrosshair; + wrect_t rcCrosshair; + HSPRITE hAutoaim; + wrect_t rcAutoaim; + HSPRITE hZoomedCrosshair; + wrect_t rcZoomedCrosshair; + HSPRITE hZoomedAutoaim; + wrect_t rcZoomedAutoaim; +}; + +typedef int AMMO; + + #endif \ No newline at end of file diff --git a/cl_dll/include/hud/ammohistory.h b/cl_dll/include/hud/ammohistory.h index 6cec696..8c804df 100644 --- a/cl_dll/include/hud/ammohistory.h +++ b/cl_dll/include/hud/ammohistory.h @@ -1,143 +1,143 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// ammohistory.h -// -#pragma once -// this is the max number of items in each bucket -#define MAX_WEAPON_POSITIONS 19 - -class WeaponsResource -{ -private: - // Information about weapons & ammo - WEAPON rgWeapons[MAX_WEAPONS]; // Weapons Array - - // counts of weapons * ammo - WEAPON* rgSlots[MAX_WEAPON_SLOTS+1][MAX_WEAPON_POSITIONS+1]; // The slots currently in use by weapons. The value is a pointer to the weapon; if it's NULL, no weapon is there - int riAmmo[MAX_AMMO_TYPES]; // count of each ammo type - -public: - void Init( void ) - { - memset( rgWeapons, 0, sizeof rgWeapons ); - Reset(); - } - - void Reset( void ) - { - iOldWeaponBits = 0; - memset( rgSlots, 0, sizeof rgSlots ); - memset( riAmmo, 0, sizeof riAmmo ); - } - -///// WEAPON ///// - int iOldWeaponBits; - - WEAPON *GetWeapon( int iId ) { return &rgWeapons[iId]; } - void AddWeapon( WEAPON *wp ) - { - rgWeapons[ wp->iId ] = *wp; - LoadWeaponSprites( &rgWeapons[ wp->iId ] ); - } - - void PickupWeapon( WEAPON *wp ) - { - rgSlots[ wp->iSlot ][ wp->iSlotPos ] = wp; - } - - void DropWeapon( WEAPON *wp ) - { - rgSlots[ wp->iSlot ][ wp->iSlotPos ] = NULL; - } - - void DropAllWeapons( void ) - { - for ( int i = 0; i < MAX_WEAPONS; i++ ) - { - if ( rgWeapons[i].iId ) - DropWeapon( &rgWeapons[i] ); - } - } - - WEAPON* GetWeaponSlot( int slot, int pos ) { return rgSlots[slot][pos]; } - - void LoadWeaponSprites( WEAPON* wp ); - void LoadAllWeaponSprites( void ); - WEAPON* GetFirstPos( int iSlot ); - void SelectSlot( int iSlot, int fAdvance, int iDirection ); - WEAPON* GetNextActivePos( int iSlot, int iSlotPos ); - - int HasAmmo( WEAPON *p ); - -///// AMMO ///// - AMMO GetAmmo( int iId ) { return iId; } - - void SetAmmo( int iId, int iCount ) { riAmmo[ iId ] = iCount; } - - int CountAmmo( int iId ); - - HSPRITE* GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect ); -}; - -extern WeaponsResource gWR; - - -#define MAX_HISTORY 12 -enum { - HISTSLOT_EMPTY, - HISTSLOT_AMMO, - HISTSLOT_WEAP, - HISTSLOT_ITEM, -}; - -class HistoryResource -{ -private: - struct HIST_ITEM { - int type; - float DisplayTime; // the time at which this item should be removed from the history - int iCount; - int iId; - }; - - HIST_ITEM rgAmmoHistory[MAX_HISTORY]; - -public: - - void Init( void ) - { - Reset(); - } - - void Reset( void ) - { - memset( rgAmmoHistory, 0, sizeof rgAmmoHistory ); - } - - int iHistoryGap; - int iCurrentHistorySlot; - - void AddToHistory( int iType, int iId, int iCount = 0 ); - void AddToHistory( int iType, const char *szName, int iCount = 0 ); - - void CheckClearHistory( void ); - int DrawAmmoHistory( float flTime ); -}; - -extern HistoryResource gHR; - - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// ammohistory.h +// +#pragma once +// this is the max number of items in each bucket +#define MAX_WEAPON_POSITIONS 19 + +class WeaponsResource +{ +private: + // Information about weapons & ammo + WEAPON rgWeapons[MAX_WEAPONS]; // Weapons Array + + // counts of weapons * ammo + WEAPON* rgSlots[MAX_WEAPON_SLOTS+1][MAX_WEAPON_POSITIONS+1]; // The slots currently in use by weapons. The value is a pointer to the weapon; if it's NULL, no weapon is there + int riAmmo[MAX_AMMO_TYPES]; // count of each ammo type + +public: + void Init( void ) + { + memset( rgWeapons, 0, sizeof rgWeapons ); + Reset(); + } + + void Reset( void ) + { + iOldWeaponBits = 0; + memset( rgSlots, 0, sizeof rgSlots ); + memset( riAmmo, 0, sizeof riAmmo ); + } + +///// WEAPON ///// + int iOldWeaponBits; + + WEAPON *GetWeapon( int iId ) { return &rgWeapons[iId]; } + void AddWeapon( WEAPON *wp ) + { + rgWeapons[ wp->iId ] = *wp; + LoadWeaponSprites( &rgWeapons[ wp->iId ] ); + } + + void PickupWeapon( WEAPON *wp ) + { + rgSlots[ wp->iSlot ][ wp->iSlotPos ] = wp; + } + + void DropWeapon( WEAPON *wp ) + { + rgSlots[ wp->iSlot ][ wp->iSlotPos ] = NULL; + } + + void DropAllWeapons( void ) + { + for ( int i = 0; i < MAX_WEAPONS; i++ ) + { + if ( rgWeapons[i].iId ) + DropWeapon( &rgWeapons[i] ); + } + } + + WEAPON* GetWeaponSlot( int slot, int pos ) { return rgSlots[slot][pos]; } + + void LoadWeaponSprites( WEAPON* wp ); + void LoadAllWeaponSprites( void ); + WEAPON* GetFirstPos( int iSlot ); + void SelectSlot( int iSlot, int fAdvance, int iDirection ); + WEAPON* GetNextActivePos( int iSlot, int iSlotPos ); + + int HasAmmo( WEAPON *p ); + +///// AMMO ///// + AMMO GetAmmo( int iId ) { return iId; } + + void SetAmmo( int iId, int iCount ) { riAmmo[ iId ] = iCount; } + + int CountAmmo( int iId ); + + HSPRITE* GetAmmoPicFromWeapon( int iAmmoId, wrect_t& rect ); +}; + +extern WeaponsResource gWR; + + +#define MAX_HISTORY 12 +enum { + HISTSLOT_EMPTY, + HISTSLOT_AMMO, + HISTSLOT_WEAP, + HISTSLOT_ITEM, +}; + +class HistoryResource +{ +private: + struct HIST_ITEM { + int type; + float DisplayTime; // the time at which this item should be removed from the history + int iCount; + int iId; + }; + + HIST_ITEM rgAmmoHistory[MAX_HISTORY]; + +public: + + void Init( void ) + { + Reset(); + } + + void Reset( void ) + { + memset( rgAmmoHistory, 0, sizeof rgAmmoHistory ); + } + + int iHistoryGap; + int iCurrentHistorySlot; + + void AddToHistory( int iType, int iId, int iCount = 0 ); + void AddToHistory( int iType, const char *szName, int iCount = 0 ); + + void CheckClearHistory( void ); + int DrawAmmoHistory( float flTime ); +}; + +extern HistoryResource gHR; + + + diff --git a/cl_dll/include/hud/health.h b/cl_dll/include/hud/health.h index ea20e1b..3f4091b 100644 --- a/cl_dll/include/hud/health.h +++ b/cl_dll/include/hud/health.h @@ -1,133 +1,133 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#pragma once -#define DMG_IMAGE_LIFE 2 // seconds that image is up - -#define DMG_IMAGE_POISON 0 -#define DMG_IMAGE_ACID 1 -#define DMG_IMAGE_COLD 2 -#define DMG_IMAGE_DROWN 3 -#define DMG_IMAGE_BURN 4 -#define DMG_IMAGE_NERVE 5 -#define DMG_IMAGE_RAD 6 -#define DMG_IMAGE_SHOCK 7 -//tf defines -#define DMG_IMAGE_CALTROP 8 -#define DMG_IMAGE_TRANQ 9 -#define DMG_IMAGE_CONCUSS 10 -#define DMG_IMAGE_HALLUC 11 -#define NUM_DMG_TYPES 12 -// instant damage - -#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) - -// TF Healing Additions for TakeHealth -#define DMG_IGNORE_MAXHEALTH DMG_IGNITE -// TF Redefines since we never use the originals -#define DMG_NAIL DMG_SLASH -#define DMG_NOT_SELF DMG_FREEZE - - -#define DMG_TRANQ DMG_MORTAR -#define DMG_CONCUSS DMG_SONIC - - - -typedef struct -{ - float fExpire; - float fBaseline; - int x, y; -} DAMAGE_IMAGE; - -// -//----------------------------------------------------- -// -class CHudHealth: public CHudBase -{ -public: - virtual int Init( void ); - virtual int VidInit( void ); - virtual int Draw(float fTime); - virtual void Reset( void ); - - int MsgFunc_Health(const char *pszName, int iSize, void *pbuf); - int MsgFunc_Damage(const char *pszName, int iSize, void *pbuf); - int MsgFunc_ScoreAttrib(const char *pszName, int iSize, void *pbuf); - int MsgFunc_ClCorpse(const char *pszName, int iSize, void *pbuf); - - - 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; - HSPRITE m_hDamage; - - DAMAGE_IMAGE m_dmg[NUM_DMG_TYPES]; - float m_flTimeFlash; - int m_bitsDamage; - int DrawPain(float fTime); - int DrawDamage(float fTime); - void CalcDamageDirection(vec3_t vecFrom); - void UpdateTiles(float fTime, long bits); - void DrawPlayerLocation( void ); -}; +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#pragma once +#define DMG_IMAGE_LIFE 2 // seconds that image is up + +#define DMG_IMAGE_POISON 0 +#define DMG_IMAGE_ACID 1 +#define DMG_IMAGE_COLD 2 +#define DMG_IMAGE_DROWN 3 +#define DMG_IMAGE_BURN 4 +#define DMG_IMAGE_NERVE 5 +#define DMG_IMAGE_RAD 6 +#define DMG_IMAGE_SHOCK 7 +//tf defines +#define DMG_IMAGE_CALTROP 8 +#define DMG_IMAGE_TRANQ 9 +#define DMG_IMAGE_CONCUSS 10 +#define DMG_IMAGE_HALLUC 11 +#define NUM_DMG_TYPES 12 +// instant damage + +#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) + +// TF Healing Additions for TakeHealth +#define DMG_IGNORE_MAXHEALTH DMG_IGNITE +// TF Redefines since we never use the originals +#define DMG_NAIL DMG_SLASH +#define DMG_NOT_SELF DMG_FREEZE + + +#define DMG_TRANQ DMG_MORTAR +#define DMG_CONCUSS DMG_SONIC + + + +typedef struct +{ + float fExpire; + float fBaseline; + int x, y; +} DAMAGE_IMAGE; + +// +//----------------------------------------------------- +// +class CHudHealth: public CHudBase +{ +public: + virtual int Init( void ); + virtual int VidInit( void ); + virtual int Draw(float fTime); + virtual void Reset( void ); + + int MsgFunc_Health(const char *pszName, int iSize, void *pbuf); + int MsgFunc_Damage(const char *pszName, int iSize, void *pbuf); + int MsgFunc_ScoreAttrib(const char *pszName, int iSize, void *pbuf); + int MsgFunc_ClCorpse(const char *pszName, int iSize, void *pbuf); + + + 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; + HSPRITE m_hDamage; + + DAMAGE_IMAGE m_dmg[NUM_DMG_TYPES]; + float m_flTimeFlash; + int m_bitsDamage; + int DrawPain(float fTime); + int DrawDamage(float fTime); + void CalcDamageDirection(vec3_t vecFrom); + void UpdateTiles(float fTime, long bits); + void DrawPlayerLocation( void ); +}; diff --git a/cl_dll/include/hud/hud.h b/cl_dll/include/hud/hud.h index a615cb8..674e591 100644 --- a/cl_dll/include/hud/hud.h +++ b/cl_dll/include/hud/hud.h @@ -1,924 +1,924 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// hud.h -// -// class CHud declaration -// -// CHud handles the message, calculation, and drawing the HUD -// -#pragma once - -#define RGB_YELLOWISH 0x00FFA000 //255,160,0 -#define RGB_REDISH 0x00FF1010 //255,16,16 -#define RGB_GREENISH 0x0000A000 //0,160,0 -#define RGB_WHITE 0x00FFFFFF - -#include "wrect.h" -#include "cl_dll.h" -#include "ammo.h" - -#include "csprite.h" -#include "draw_util.h" - -#define DHN_DRAWZERO 1 -#define DHN_2DIGITS 2 -#define DHN_3DIGITS 4 -#define MIN_ALPHA 100 - -#define HUDELEM_ACTIVE 1 - -#define CHudMsgFunc(x) int MsgFunc_##x(const char *pszName, int iSize, void *buf) -#define CHudUserCmd(x) void UserCmd_##x() - -typedef struct { - int x, y; -} POSITION; - -enum -{ - MAX_PLAYERS = 64, - MAX_TEAMS = 8, - MAX_TEAM_NAME = 16, - MAX_HOSTAGES = 24, -}; - -typedef struct { - unsigned char r,g,b,a; -} RGBA; - -typedef struct cvar_s cvar_t; -extern cvar_t *cl_righthand; -extern cvar_t *cl_weather; -extern cvar_t *cl_minmodels; -extern cvar_t *cl_min_t; -extern cvar_t *cl_min_ct; -extern char *sPlayerModelFiles[]; - -class CClientSprite; - -inline bool BIsValidTModelIndex( int i ) -{ - if ( i == 1 || i == 5 || i == 6 || i == 8 || i == 11 ) - return true; - else - return false; -} - -inline bool BIsValidCTModelIndex( int i ) -{ - if ( i == 7 || i == 2 || i == 10 || i == 4 || i == 9) - return true; - else - return false; -} - -#define HUD_ACTIVE 1 -#define HUD_INTERMISSION 2 - -#define MAX_PLAYER_NAME_LENGTH 32 - -#define MAX_MOTD_LENGTH 1536 - -// -//----------------------------------------------------- -// -class CHudBase -{ -public: - POSITION m_pos; - int m_type; - int m_iFlags; // active, moving, - virtual ~CHudBase() {} - virtual int Init( void ) {return 0;} - virtual int VidInit( void ) {return 0;} - virtual int Draw(float flTime) {return 0;} - virtual void Think(void) {return;} - virtual void Reset(void) {return;} - virtual void InitHUDData( void ) {} // called every time a server is connected to - -}; - -struct HUDLIST { - CHudBase *p; - HUDLIST *pNext; -}; - - - -// -//----------------------------------------------------- -// -//#include "voice_status.h" -#include "hud_spectator.h" - - -// -//----------------------------------------------------- -// -class CHudAmmo: public CHudBase -{ - friend class WeaponsResource; - friend class HistoryResource; - -public: - int Init( void ); - int VidInit( void ); - int Draw(float flTime); - void Think(void); - void Reset(void); - - void DrawCrosshair( float flTime, int weaponId ); - void CalcCrosshairSize(); - void CalcCrosshairDrawMode(); - void CalcCrosshairColor(); - - int DrawWList(float flTime); - CHudMsgFunc(CurWeapon); - CHudMsgFunc(WeaponList); - CHudMsgFunc(AmmoX); - CHudMsgFunc(AmmoPickup); - CHudMsgFunc(WeapPickup); - CHudMsgFunc(ItemPickup); - CHudMsgFunc(HideWeapon); - CHudMsgFunc(Crosshair); - CHudMsgFunc(Brass); - - - void SlotInput( int iSlot ); - CHudUserCmd(Slot1); - CHudUserCmd(Slot2); - CHudUserCmd(Slot3); - CHudUserCmd(Slot4); - CHudUserCmd(Slot5); - CHudUserCmd(Slot6); - CHudUserCmd(Slot7); - CHudUserCmd(Slot8); - CHudUserCmd(Slot9); - CHudUserCmd(Slot10); - CHudUserCmd(Close); - CHudUserCmd(NextWeapon); - CHudUserCmd(PrevWeapon); - CHudUserCmd(Adjust_Crosshair); - CHudUserCmd(Rebuy); - CHudUserCmd(Autobuy); - -private: - float m_fFade; - RGBA m_rgba; - WEAPON *m_pWeapon; - int m_HUD_bucket0; - int m_HUD_selection; - - int m_iAlpha; - int m_R, m_G, m_B; - int m_cvarR, m_cvarG, m_cvarB; - int m_iCurrentCrosshair; - int m_iCrosshairScaleBase; - float m_flCrosshairDistance; - bool m_bAdditive; - bool m_bObserverCrosshair ; - bool m_bDrawCrosshair; - int m_iAmmoLastCheck; - - cvar_t *m_pClCrosshairColor; - cvar_t *m_pClCrosshairTranslucent; - cvar_t *m_pClCrosshairSize; - cvar_t *m_pClDynamicCrosshair; - cvar_t *m_pHud_FastSwitch; - cvar_t *m_pHud_DrawHistory_Time; - -}; - -// -//----------------------------------------------------- -// - -class CHudAmmoSecondary: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - void Reset( void ); - int Draw(float flTime); - - CHudMsgFunc(SecAmmoVal); - CHudMsgFunc(SecAmmoIcon); - -private: - enum { - MAX_SEC_AMMO_VALUES = 4 - }; - - int m_HUD_ammoicon; // sprite indices - int m_iAmmoAmounts[MAX_SEC_AMMO_VALUES]; - float m_fFade; -}; - - -#include "health.h" -#include "radar.h" - -#define FADE_TIME 100 - - -// -//----------------------------------------------------- -// -class CHudGeiger: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw(float flTime); - CHudMsgFunc(Geiger); - -private: - int m_iGeigerRange; - -}; - -// -//----------------------------------------------------- -// -class CHudTrain: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw(float flTime); - CHudMsgFunc(Train); - -private: - HSPRITE m_hSprite; - int m_iPos; - -}; - -// -//----------------------------------------------------- -// -// MOTD in cs16 must render HTML, so it disabled -// - -class CHudMOTD : public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw( float flTime ); - void Reset( void ); - - CHudMsgFunc(MOTD); - void Scroll( int dir ); - void Scroll( float amount ); - float scroll; - bool m_bShow; - -protected: - static int MOTD_DISPLAY_TIME; - char m_szMOTD[ MAX_MOTD_LENGTH ]; - cvar_t *cl_hide_motd; - - int m_iLines; - int m_iMaxLength; -}; - - -class CHudScoreboard: public CHudBase -{ -public: - int Init( void ); - void InitHUDData( void ); - int VidInit( void ); - int Draw( float flTime ); - - int DrawScoreboard( float flTime ); - int DrawTeams( float listslot ); - int DrawPlayers( float listslot, int nameoffset = 0, char *team = NULL ); // returns the ypos where it finishes drawing - - void DeathMsg( int killer, int victim ); - void SetScoreboardDefaults( void ); - void GetAllPlayersInfo( void ); - - CHudUserCmd(ShowScores); - CHudUserCmd(HideScores); - CHudUserCmd(ShowScoreboard2); - CHudUserCmd(HideScoreboard2); - - CHudMsgFunc(ScoreInfo); - CHudMsgFunc(TeamInfo); - CHudMsgFunc(TeamScore); - CHudMsgFunc(TeamScores); - CHudMsgFunc(TeamNames); - - int m_iPlayerNum; - -private: - int m_iLastKilledBy; - int m_fLastKillTime; - int m_iNumTeams; - RGBA m_colors; - bool m_bDrawStroke; - bool m_bForceDraw; // if called by showscoreboard2 - bool m_bShowscoresHeld; -}; - -// -//----------------------------------------------------- -// -class CHudStatusBar : public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw( float flTime ); - void Reset( void ); - void ParseStatusString( int line_num ); - - CHudMsgFunc(StatusText); - CHudMsgFunc(StatusValue); - -protected: - enum { - MAX_STATUSTEXT_LENGTH = 128, - MAX_STATUSBAR_VALUES = 8, - MAX_STATUSBAR_LINES = 2, - }; - - char m_szStatusText[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // a text string describing how the status bar is to be drawn - char m_szStatusBar[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // the constructed bar that is drawn - int m_iStatusValues[MAX_STATUSBAR_VALUES]; // an array of values for use in the status bar - - int m_bReparseString; // set to TRUE whenever the m_szStatusBar needs to be recalculated - - // an array of colors...one color for each line - float *m_pflNameColors[MAX_STATUSBAR_LINES]; - - cvar_t *hud_centerid; -}; - - -struct extra_player_info_t -{ - short frags; - short deaths; - short playerclass; - short teamnumber; - char teamname[MAX_TEAM_NAME]; - bool has_c4; - bool vip; - bool dead; - bool showhealth; - bool nextflash; - bool radarflashon; - Vector origin; - int health; - int radarflashes; - float radarflash; - char location[32]; -}; - -struct team_info_t -{ - char name[MAX_TEAM_NAME]; - short frags; - short deaths; - short ownteam; - short players; - int already_drawn; - int scores_overriden; - int sumping; - //int teamnumber; not used -}; - -struct hostage_info_t -{ - char teamname[MAX_TEAM_NAME]; - vec3_t origin; - float radarflash; - bool radarflashon; - bool dead; - bool nextflash; - int radarflashes; -}; - -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 hostage_info_t g_HostageInfo[MAX_HOSTAGES+1]; -extern int g_IsSpectator[MAX_PLAYERS+1]; - - -// -//----------------------------------------------------- -// -class CHudDeathNotice : public CHudBase -{ -public: - int Init( void ); - void InitHUDData( void ); - int VidInit( void ); - int Draw( float flTime ); - CHudMsgFunc(DeathMsg); - -private: - int m_HUD_d_skull; // sprite index of skull icon - int m_HUD_d_headshot; - cvar_t *hud_deathnotice_time; -}; - -// -//----------------------------------------------------- -// -class CHudMenu : public CHudBase -{ -public: - int Init( void ); - void InitHUDData( void ); - int VidInit( void ); - void Reset( void ); - int Draw( float flTime ); - - CHudMsgFunc(ShowMenu); - CHudMsgFunc(BuyClose); - CHudMsgFunc(VGUIMenu); - // server sends false when spectating is not allowed, and true when allowed - CHudMsgFunc(AllowSpec); - - CHudUserCmd(OldStyleMenuClose); - CHudUserCmd(OldStyleMenuOpen); - CHudUserCmd(ShowVGUIMenu); - - void ShowVGUIMenu( int menuType ); // cs16client extension - - void SelectMenuItem( int menu_item ); - - int m_fMenuDisplayed; - bool m_bAllowSpec; - cvar_t *_extended_menus; - int m_bitsValidSlots; - float m_flShutoffTime; - int m_fWaitingForMore; - -}; - -// -//----------------------------------------------------- -// -class CHudSayText : public CHudBase -{ -public: - int Init( void ); - void InitHUDData( void ); - int VidInit( void ); - int Draw( float flTime ); - CHudMsgFunc(SayText); - void SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex = -1 ); - void SayTextPrint( char szBuf[3][256] ); - void EnsureTextFitsInOneLineAndWrapIfHaveTo( int line ); - friend class CHudSpectator; - -private: - - struct cvar_s * m_HUD_saytext; - struct cvar_s * m_HUD_saytext_time; -}; - -// -//----------------------------------------------------- -// -class CHudBattery: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw(float flTime); - void InitHUDData( void ); - CHudMsgFunc(Battery); - CHudMsgFunc(ArmorType); - -private: - enum armortype_t { - Vest = 0, - VestHelm - } m_enArmorType; - - CClientSprite m_hEmpty[VestHelm + 1]; - CClientSprite m_hFull[VestHelm + 1]; - int m_iBat; - float m_fFade; - int m_iHeight; // width of the battery innards -}; - - -// -//----------------------------------------------------- -// -class CHudFlashlight: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw(float flTime); - void Reset( void ); - CHudMsgFunc(Flashlight); - CHudMsgFunc(FlashBat); - -private: - CClientSprite m_hSprite1; - CClientSprite m_hSprite2; - CClientSprite m_hBeam; - float m_flBat; - int m_iBat; - int m_fOn; - float m_fFade; - int m_iWidth; // width of the battery innards -}; - -// -//----------------------------------------------------- -// -const int maxHUDMessages = 16; -struct message_parms_t -{ - client_textmessage_t *pMessage; - float time; - int x, y; - int totalWidth, totalHeight; - int width; - int lines; - int lineLength; - int length; - int r, g, b; - int text; - int fadeBlend; - float charTime; - float fadeTime; -}; - -// -//----------------------------------------------------- -// - -class CHudTextMessage: public CHudBase -{ -public: - int Init( void ); - static char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ); - static char *BufferedLocaliseTextString( const char *msg ); - static char *LookupString( const char *msg_name, int *msg_dest = NULL ); - CHudMsgFunc(TextMsg); -}; - -// -//----------------------------------------------------- -// - -class CHudMessage: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw(float flTime); - CHudMsgFunc(HudText); - CHudMsgFunc(GameTitle); - - float FadeBlend( float fadein, float fadeout, float hold, float localTime ); - int XPosition( float x, int width, int lineWidth ); - int YPosition( float y, int height ); - - void MessageAdd( const char *pName, float time ); - void MessageAdd(client_textmessage_t * newMessage ); - void MessageDrawScan( client_textmessage_t *pMessage, float time ); - void MessageScanStart( void ); - void MessageScanNextChar( void ); - void Reset( void ); - -private: - client_textmessage_t *m_pMessages[maxHUDMessages]; - float m_startTime[maxHUDMessages]; - message_parms_t m_parms; - float m_gameTitleTime; - client_textmessage_t *m_pGameTitle; - - int m_HUD_title_life; - int m_HUD_title_half; -}; - -// -//----------------------------------------------------- -// -#define MAX_SPRITE_NAME_LENGTH 24 - -class CHudStatusIcons: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - void Reset( void ); - int Draw(float flTime); - CHudMsgFunc(StatusIcon); - - enum { - MAX_ICONSPRITENAME_LENGTH = MAX_SPRITE_NAME_LENGTH, - MAX_ICONSPRITES = 4, - }; - - - //had to make these public so CHud could access them (to enable concussion icon) - //could use a friend declaration instead... - void EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue ); - void DisableIcon( char *pszIconName ); - - friend class CHudScoreboard; - -private: - - typedef struct - { - char szSpriteName[MAX_ICONSPRITENAME_LENGTH]; - HSPRITE spr; - wrect_t rc; - unsigned char r, g, b; - unsigned char secR, secG, secB; - float flTimeToChange; - } icon_sprite_t; - - icon_sprite_t m_IconList[MAX_ICONSPRITES]; -}; - - -// -//----------------------------------------------------- -// -#define MONEY_YPOS ScreenHeight - 3 * gHUD.m_iFontHeight - -class CHudMoney : public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw( float flTime ); - CHudMsgFunc(Money); - CHudMsgFunc(BlinkAcct); - -private: - int m_iMoneyCount; - int m_iDelta; - int m_iBlinkAmt; - float m_fBlinkTime; - float m_fFade; - CClientSprite m_hDollar; - CClientSprite m_hPlus; - CClientSprite m_hMinus; -}; -// -//----------------------------------------------------- -// -class CHudRadio: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw( float flTime ); - // play a sentence from a radio - // [byte] unknown (always 1) - // [string] sentence name - // [short] unknown. (always 100, it's a volume?) - CHudMsgFunc(SendAudio); - CHudMsgFunc(ReloadSound); - CHudMsgFunc(BotVoice); -private: - int m_iSenderID; - char m_sentence[64]; - int m_iPitch; -}; - -// -//----------------------------------------------------- -// -class CHudTimer: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw(float fTime); - // set up the timer. - // [short] - CHudMsgFunc(RoundTime); - // show the timer - // [empty] - CHudMsgFunc(ShowTimer); -private: - int m_HUD_timer; - int m_iTime; - float m_fStartTime; - bool m_bPanicColorChange; - float m_flPanicTime; -}; -// -//----------------------------------------------------- -// -class CHudProgressBar: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw( float flTime ); - - // start progress bar - // [short] Duration - CHudMsgFunc(BarTime); - - // [short] Duration - // [short] percent - CHudMsgFunc(BarTime2); - CHudMsgFunc(BotProgress); - -private: - int m_iDuration; - float m_fPercent; - float m_fStartTime; - char m_szHeader[256]; - const char *m_szLocalizedHeader; -}; - -// -//----------------------------------------------------- -// -// class for drawing sniper scope -class CHudSniperScope: public CHudBase -{ -public: - int Init( void ); - int VidInit( void ); - int Draw( float flTime ); - -private: - float left, right, centerx, centery; - int m_iScopeArc[4]; - int blackTex; - -}; - -class CHudNVG: public CHudBase -{ -public: - int Init( void ); - int Draw( float flTime ); - CHudMsgFunc(NVGToggle); - - CHudUserCmd(NVGAdjustUp); - CHudUserCmd(NVGAdjustDown); - - int m_iEnable; -private: - int m_iAlpha; - -}; - -// -//----------------------------------------------------- -// - - - -class CHud -{ -public: - CHud() : m_iSpriteCount(0), m_pHudList(NULL) {} - ~CHud(); // destructor, frees allocated memory // thanks, Captain Obvious - - void Init( void ); - void VidInit( void ); - void Think(void); - int Redraw( float flTime, int intermission ); - int UpdateClientData( client_data_t *cdata, float time ); - void AddHudElem(CHudBase *p); - - float GetSensitivity(); - HSPRITE GetSprite( int index ); - wrect_t& GetSpriteRect( int index ); - int GetSpriteIndex( const char *SpriteName ); // gets a sprite index, for use in the m_rghSprites[] array - - - 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 - Vector m_vecOrigin; - Vector m_vecAngles; - int m_iKeyBits; - int m_iHideHUDDisplay; - int m_iFOV; - int m_Teamplay; - int m_iRes; - int RealSize; - float m_flScale; - cvar_t *m_pCvarStealMouse; - cvar_t *m_pCvarDraw; - cvar_t *cl_shadows; - - int m_iFontHeight; - CHudAmmo m_Ammo; - CHudHealth m_Health; - CHudSpectator m_Spectator; - CHudGeiger m_Geiger; - CHudBattery m_Battery; - CHudTrain m_Train; - CHudFlashlight m_Flash; - CHudMessage m_Message; - CHudStatusBar m_StatusBar; - CHudDeathNotice m_DeathNotice; - CHudSayText m_SayText; - CHudMenu m_Menu; - CHudAmmoSecondary m_AmmoSecondary; - CHudTextMessage m_TextMessage; - CHudStatusIcons m_StatusIcons; - CHudScoreboard m_Scoreboard; - CHudMOTD m_MOTD; - CHudMoney m_Money; - CHudTimer m_Timer; - CHudRadio m_Radio; - CHudProgressBar m_ProgressBar; - CHudSniperScope m_SniperScope; - CHudNVG m_NVG; - CHudRadar m_Radar; - - - - // user messages - CHudMsgFunc(Damage); - CHudMsgFunc(GameMode); - CHudMsgFunc(Logo); - CHudMsgFunc(ResetHUD); - CHudMsgFunc(InitHUD); - CHudMsgFunc(ViewMode); - CHudMsgFunc(SetFOV); - CHudMsgFunc(Concuss); - CHudMsgFunc(ReceiveW); - CHudMsgFunc(BombDrop); - CHudMsgFunc(BombPickup); - CHudMsgFunc(HostagePos); - CHudMsgFunc(HostageK); - CHudMsgFunc(ShadowIdx); - - - // Screen information - SCREENINFO m_scrinfo; - // As Xash3D can fake m_scrinfo for hud scailing - // we will use a real screen parameters - SCREENINFO m_truescrinfo; - - int m_iWeaponBits; - int m_fPlayerDead; - int m_iIntermission; - int m_iNoConsolePrint; - - // sprite indexes - int m_HUD_number_0; - -private: - HUDLIST *m_pHudList; - HSPRITE m_hsprLogo; - int m_iLogo; - client_sprite_t *m_pSpriteList; - int m_iSpriteCount; - int m_iSpriteCountAllRes; - float m_flMouseSensitivity; - int m_iConcussionEffect; - int m_iForceCamera; - int m_iForceChaseCam; - int m_iFadeToBlack; - - // the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded. - // freed in ~CHud() - HSPRITE *m_rghSprites; /*[HUD_SPRITE_COUNT]*/ // the sprites loaded from hud.txt - wrect_t *m_rgrcRects; /*[HUD_SPRITE_COUNT]*/ - char *m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/ - - struct cvar_s *default_fov; - -}; - -extern CHud gHUD; - -extern int g_iPlayerClass; -extern int g_iTeamNumber; -extern int g_iUser1; -extern int g_iUser2; -extern int g_iUser3; - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// hud.h +// +// class CHud declaration +// +// CHud handles the message, calculation, and drawing the HUD +// +#pragma once + +#define RGB_YELLOWISH 0x00FFA000 //255,160,0 +#define RGB_REDISH 0x00FF1010 //255,16,16 +#define RGB_GREENISH 0x0000A000 //0,160,0 +#define RGB_WHITE 0x00FFFFFF + +#include "wrect.h" +#include "cl_dll.h" +#include "ammo.h" + +#include "csprite.h" +#include "draw_util.h" + +#define DHN_DRAWZERO 1 +#define DHN_2DIGITS 2 +#define DHN_3DIGITS 4 +#define MIN_ALPHA 100 + +#define HUDELEM_ACTIVE 1 + +#define CHudMsgFunc(x) int MsgFunc_##x(const char *pszName, int iSize, void *buf) +#define CHudUserCmd(x) void UserCmd_##x() + +typedef struct { + int x, y; +} POSITION; + +enum +{ + MAX_PLAYERS = 64, + MAX_TEAMS = 8, + MAX_TEAM_NAME = 16, + MAX_HOSTAGES = 24, +}; + +typedef struct { + unsigned char r,g,b,a; +} RGBA; + +typedef struct cvar_s cvar_t; +extern cvar_t *cl_righthand; +extern cvar_t *cl_weather; +extern cvar_t *cl_minmodels; +extern cvar_t *cl_min_t; +extern cvar_t *cl_min_ct; +extern char *sPlayerModelFiles[]; + +class CClientSprite; + +inline bool BIsValidTModelIndex( int i ) +{ + if ( i == 1 || i == 5 || i == 6 || i == 8 || i == 11 ) + return true; + else + return false; +} + +inline bool BIsValidCTModelIndex( int i ) +{ + if ( i == 7 || i == 2 || i == 10 || i == 4 || i == 9) + return true; + else + return false; +} + +#define HUD_ACTIVE 1 +#define HUD_INTERMISSION 2 + +#define MAX_PLAYER_NAME_LENGTH 32 + +#define MAX_MOTD_LENGTH 1536 + +// +//----------------------------------------------------- +// +class CHudBase +{ +public: + POSITION m_pos; + int m_type; + int m_iFlags; // active, moving, + virtual ~CHudBase() {} + virtual int Init( void ) {return 0;} + virtual int VidInit( void ) {return 0;} + virtual int Draw(float flTime) {return 0;} + virtual void Think(void) {return;} + virtual void Reset(void) {return;} + virtual void InitHUDData( void ) {} // called every time a server is connected to + +}; + +struct HUDLIST { + CHudBase *p; + HUDLIST *pNext; +}; + + + +// +//----------------------------------------------------- +// +//#include "voice_status.h" +#include "hud_spectator.h" + + +// +//----------------------------------------------------- +// +class CHudAmmo: public CHudBase +{ + friend class WeaponsResource; + friend class HistoryResource; + +public: + int Init( void ); + int VidInit( void ); + int Draw(float flTime); + void Think(void); + void Reset(void); + + void DrawCrosshair( float flTime, int weaponId ); + void CalcCrosshairSize(); + void CalcCrosshairDrawMode(); + void CalcCrosshairColor(); + + int DrawWList(float flTime); + CHudMsgFunc(CurWeapon); + CHudMsgFunc(WeaponList); + CHudMsgFunc(AmmoX); + CHudMsgFunc(AmmoPickup); + CHudMsgFunc(WeapPickup); + CHudMsgFunc(ItemPickup); + CHudMsgFunc(HideWeapon); + CHudMsgFunc(Crosshair); + CHudMsgFunc(Brass); + + + void SlotInput( int iSlot ); + CHudUserCmd(Slot1); + CHudUserCmd(Slot2); + CHudUserCmd(Slot3); + CHudUserCmd(Slot4); + CHudUserCmd(Slot5); + CHudUserCmd(Slot6); + CHudUserCmd(Slot7); + CHudUserCmd(Slot8); + CHudUserCmd(Slot9); + CHudUserCmd(Slot10); + CHudUserCmd(Close); + CHudUserCmd(NextWeapon); + CHudUserCmd(PrevWeapon); + CHudUserCmd(Adjust_Crosshair); + CHudUserCmd(Rebuy); + CHudUserCmd(Autobuy); + +private: + float m_fFade; + RGBA m_rgba; + WEAPON *m_pWeapon; + int m_HUD_bucket0; + int m_HUD_selection; + + int m_iAlpha; + int m_R, m_G, m_B; + int m_cvarR, m_cvarG, m_cvarB; + int m_iCurrentCrosshair; + int m_iCrosshairScaleBase; + float m_flCrosshairDistance; + bool m_bAdditive; + bool m_bObserverCrosshair ; + bool m_bDrawCrosshair; + int m_iAmmoLastCheck; + + cvar_t *m_pClCrosshairColor; + cvar_t *m_pClCrosshairTranslucent; + cvar_t *m_pClCrosshairSize; + cvar_t *m_pClDynamicCrosshair; + cvar_t *m_pHud_FastSwitch; + cvar_t *m_pHud_DrawHistory_Time; + +}; + +// +//----------------------------------------------------- +// + +class CHudAmmoSecondary: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + void Reset( void ); + int Draw(float flTime); + + CHudMsgFunc(SecAmmoVal); + CHudMsgFunc(SecAmmoIcon); + +private: + enum { + MAX_SEC_AMMO_VALUES = 4 + }; + + int m_HUD_ammoicon; // sprite indices + int m_iAmmoAmounts[MAX_SEC_AMMO_VALUES]; + float m_fFade; +}; + + +#include "health.h" +#include "radar.h" + +#define FADE_TIME 100 + + +// +//----------------------------------------------------- +// +class CHudGeiger: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw(float flTime); + CHudMsgFunc(Geiger); + +private: + int m_iGeigerRange; + +}; + +// +//----------------------------------------------------- +// +class CHudTrain: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw(float flTime); + CHudMsgFunc(Train); + +private: + HSPRITE m_hSprite; + int m_iPos; + +}; + +// +//----------------------------------------------------- +// +// MOTD in cs16 must render HTML, so it disabled +// + +class CHudMOTD : public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw( float flTime ); + void Reset( void ); + + CHudMsgFunc(MOTD); + void Scroll( int dir ); + void Scroll( float amount ); + float scroll; + bool m_bShow; + +protected: + static int MOTD_DISPLAY_TIME; + char m_szMOTD[ MAX_MOTD_LENGTH ]; + cvar_t *cl_hide_motd; + + int m_iLines; + int m_iMaxLength; +}; + + +class CHudScoreboard: public CHudBase +{ +public: + int Init( void ); + void InitHUDData( void ); + int VidInit( void ); + int Draw( float flTime ); + + int DrawScoreboard( float flTime ); + int DrawTeams( float listslot ); + int DrawPlayers( float listslot, int nameoffset = 0, char *team = NULL ); // returns the ypos where it finishes drawing + + void DeathMsg( int killer, int victim ); + void SetScoreboardDefaults( void ); + void GetAllPlayersInfo( void ); + + CHudUserCmd(ShowScores); + CHudUserCmd(HideScores); + CHudUserCmd(ShowScoreboard2); + CHudUserCmd(HideScoreboard2); + + CHudMsgFunc(ScoreInfo); + CHudMsgFunc(TeamInfo); + CHudMsgFunc(TeamScore); + CHudMsgFunc(TeamScores); + CHudMsgFunc(TeamNames); + + int m_iPlayerNum; + +private: + int m_iLastKilledBy; + int m_fLastKillTime; + int m_iNumTeams; + RGBA m_colors; + bool m_bDrawStroke; + bool m_bForceDraw; // if called by showscoreboard2 + bool m_bShowscoresHeld; +}; + +// +//----------------------------------------------------- +// +class CHudStatusBar : public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw( float flTime ); + void Reset( void ); + void ParseStatusString( int line_num ); + + CHudMsgFunc(StatusText); + CHudMsgFunc(StatusValue); + +protected: + enum { + MAX_STATUSTEXT_LENGTH = 128, + MAX_STATUSBAR_VALUES = 8, + MAX_STATUSBAR_LINES = 2, + }; + + char m_szStatusText[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // a text string describing how the status bar is to be drawn + char m_szStatusBar[MAX_STATUSBAR_LINES][MAX_STATUSTEXT_LENGTH]; // the constructed bar that is drawn + int m_iStatusValues[MAX_STATUSBAR_VALUES]; // an array of values for use in the status bar + + int m_bReparseString; // set to TRUE whenever the m_szStatusBar needs to be recalculated + + // an array of colors...one color for each line + float *m_pflNameColors[MAX_STATUSBAR_LINES]; + + cvar_t *hud_centerid; +}; + + +struct extra_player_info_t +{ + short frags; + short deaths; + short playerclass; + short teamnumber; + char teamname[MAX_TEAM_NAME]; + bool has_c4; + bool vip; + bool dead; + bool showhealth; + bool nextflash; + bool radarflashon; + Vector origin; + int health; + int radarflashes; + float radarflash; + char location[32]; +}; + +struct team_info_t +{ + char name[MAX_TEAM_NAME]; + short frags; + short deaths; + short ownteam; + short players; + int already_drawn; + int scores_overriden; + int sumping; + //int teamnumber; not used +}; + +struct hostage_info_t +{ + char teamname[MAX_TEAM_NAME]; + vec3_t origin; + float radarflash; + bool radarflashon; + bool dead; + bool nextflash; + int radarflashes; +}; + +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 hostage_info_t g_HostageInfo[MAX_HOSTAGES+1]; +extern int g_IsSpectator[MAX_PLAYERS+1]; + + +// +//----------------------------------------------------- +// +class CHudDeathNotice : public CHudBase +{ +public: + int Init( void ); + void InitHUDData( void ); + int VidInit( void ); + int Draw( float flTime ); + CHudMsgFunc(DeathMsg); + +private: + int m_HUD_d_skull; // sprite index of skull icon + int m_HUD_d_headshot; + cvar_t *hud_deathnotice_time; +}; + +// +//----------------------------------------------------- +// +class CHudMenu : public CHudBase +{ +public: + int Init( void ); + void InitHUDData( void ); + int VidInit( void ); + void Reset( void ); + int Draw( float flTime ); + + CHudMsgFunc(ShowMenu); + CHudMsgFunc(BuyClose); + CHudMsgFunc(VGUIMenu); + // server sends false when spectating is not allowed, and true when allowed + CHudMsgFunc(AllowSpec); + + CHudUserCmd(OldStyleMenuClose); + CHudUserCmd(OldStyleMenuOpen); + CHudUserCmd(ShowVGUIMenu); + + void ShowVGUIMenu( int menuType ); // cs16client extension + + void SelectMenuItem( int menu_item ); + + int m_fMenuDisplayed; + bool m_bAllowSpec; + cvar_t *_extended_menus; + int m_bitsValidSlots; + float m_flShutoffTime; + int m_fWaitingForMore; + +}; + +// +//----------------------------------------------------- +// +class CHudSayText : public CHudBase +{ +public: + int Init( void ); + void InitHUDData( void ); + int VidInit( void ); + int Draw( float flTime ); + CHudMsgFunc(SayText); + void SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex = -1 ); + void SayTextPrint( char szBuf[3][256] ); + void EnsureTextFitsInOneLineAndWrapIfHaveTo( int line ); + friend class CHudSpectator; + +private: + + struct cvar_s * m_HUD_saytext; + struct cvar_s * m_HUD_saytext_time; +}; + +// +//----------------------------------------------------- +// +class CHudBattery: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw(float flTime); + void InitHUDData( void ); + CHudMsgFunc(Battery); + CHudMsgFunc(ArmorType); + +private: + enum armortype_t { + Vest = 0, + VestHelm + } m_enArmorType; + + CClientSprite m_hEmpty[VestHelm + 1]; + CClientSprite m_hFull[VestHelm + 1]; + int m_iBat; + float m_fFade; + int m_iHeight; // width of the battery innards +}; + + +// +//----------------------------------------------------- +// +class CHudFlashlight: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw(float flTime); + void Reset( void ); + CHudMsgFunc(Flashlight); + CHudMsgFunc(FlashBat); + +private: + CClientSprite m_hSprite1; + CClientSprite m_hSprite2; + CClientSprite m_hBeam; + float m_flBat; + int m_iBat; + int m_fOn; + float m_fFade; + int m_iWidth; // width of the battery innards +}; + +// +//----------------------------------------------------- +// +const int maxHUDMessages = 16; +struct message_parms_t +{ + client_textmessage_t *pMessage; + float time; + int x, y; + int totalWidth, totalHeight; + int width; + int lines; + int lineLength; + int length; + int r, g, b; + int text; + int fadeBlend; + float charTime; + float fadeTime; +}; + +// +//----------------------------------------------------- +// + +class CHudTextMessage: public CHudBase +{ +public: + int Init( void ); + static char *LocaliseTextString( const char *msg, char *dst_buffer, int buffer_size ); + static char *BufferedLocaliseTextString( const char *msg ); + static char *LookupString( const char *msg_name, int *msg_dest = NULL ); + CHudMsgFunc(TextMsg); +}; + +// +//----------------------------------------------------- +// + +class CHudMessage: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw(float flTime); + CHudMsgFunc(HudText); + CHudMsgFunc(GameTitle); + + float FadeBlend( float fadein, float fadeout, float hold, float localTime ); + int XPosition( float x, int width, int lineWidth ); + int YPosition( float y, int height ); + + void MessageAdd( const char *pName, float time ); + void MessageAdd(client_textmessage_t * newMessage ); + void MessageDrawScan( client_textmessage_t *pMessage, float time ); + void MessageScanStart( void ); + void MessageScanNextChar( void ); + void Reset( void ); + +private: + client_textmessage_t *m_pMessages[maxHUDMessages]; + float m_startTime[maxHUDMessages]; + message_parms_t m_parms; + float m_gameTitleTime; + client_textmessage_t *m_pGameTitle; + + int m_HUD_title_life; + int m_HUD_title_half; +}; + +// +//----------------------------------------------------- +// +#define MAX_SPRITE_NAME_LENGTH 24 + +class CHudStatusIcons: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + void Reset( void ); + int Draw(float flTime); + CHudMsgFunc(StatusIcon); + + enum { + MAX_ICONSPRITENAME_LENGTH = MAX_SPRITE_NAME_LENGTH, + MAX_ICONSPRITES = 4, + }; + + + //had to make these public so CHud could access them (to enable concussion icon) + //could use a friend declaration instead... + void EnableIcon( char *pszIconName, unsigned char red, unsigned char green, unsigned char blue ); + void DisableIcon( char *pszIconName ); + + friend class CHudScoreboard; + +private: + + typedef struct + { + char szSpriteName[MAX_ICONSPRITENAME_LENGTH]; + HSPRITE spr; + wrect_t rc; + unsigned char r, g, b; + unsigned char secR, secG, secB; + float flTimeToChange; + } icon_sprite_t; + + icon_sprite_t m_IconList[MAX_ICONSPRITES]; +}; + + +// +//----------------------------------------------------- +// +#define MONEY_YPOS ScreenHeight - 3 * gHUD.m_iFontHeight + +class CHudMoney : public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw( float flTime ); + CHudMsgFunc(Money); + CHudMsgFunc(BlinkAcct); + +private: + int m_iMoneyCount; + int m_iDelta; + int m_iBlinkAmt; + float m_fBlinkTime; + float m_fFade; + CClientSprite m_hDollar; + CClientSprite m_hPlus; + CClientSprite m_hMinus; +}; +// +//----------------------------------------------------- +// +class CHudRadio: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw( float flTime ); + // play a sentence from a radio + // [byte] unknown (always 1) + // [string] sentence name + // [short] unknown. (always 100, it's a volume?) + CHudMsgFunc(SendAudio); + CHudMsgFunc(ReloadSound); + CHudMsgFunc(BotVoice); +private: + int m_iSenderID; + char m_sentence[64]; + int m_iPitch; +}; + +// +//----------------------------------------------------- +// +class CHudTimer: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw(float fTime); + // set up the timer. + // [short] + CHudMsgFunc(RoundTime); + // show the timer + // [empty] + CHudMsgFunc(ShowTimer); +private: + int m_HUD_timer; + int m_iTime; + float m_fStartTime; + bool m_bPanicColorChange; + float m_flPanicTime; +}; +// +//----------------------------------------------------- +// +class CHudProgressBar: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw( float flTime ); + + // start progress bar + // [short] Duration + CHudMsgFunc(BarTime); + + // [short] Duration + // [short] percent + CHudMsgFunc(BarTime2); + CHudMsgFunc(BotProgress); + +private: + int m_iDuration; + float m_fPercent; + float m_fStartTime; + char m_szHeader[256]; + const char *m_szLocalizedHeader; +}; + +// +//----------------------------------------------------- +// +// class for drawing sniper scope +class CHudSniperScope: public CHudBase +{ +public: + int Init( void ); + int VidInit( void ); + int Draw( float flTime ); + +private: + float left, right, centerx, centery; + int m_iScopeArc[4]; + int blackTex; + +}; + +class CHudNVG: public CHudBase +{ +public: + int Init( void ); + int Draw( float flTime ); + CHudMsgFunc(NVGToggle); + + CHudUserCmd(NVGAdjustUp); + CHudUserCmd(NVGAdjustDown); + + int m_iEnable; +private: + int m_iAlpha; + +}; + +// +//----------------------------------------------------- +// + + + +class CHud +{ +public: + CHud() : m_iSpriteCount(0), m_pHudList(NULL) {} + ~CHud(); // destructor, frees allocated memory // thanks, Captain Obvious + + void Init( void ); + void VidInit( void ); + void Think(void); + int Redraw( float flTime, int intermission ); + int UpdateClientData( client_data_t *cdata, float time ); + void AddHudElem(CHudBase *p); + + float GetSensitivity(); + HSPRITE GetSprite( int index ); + wrect_t& GetSpriteRect( int index ); + int GetSpriteIndex( const char *SpriteName ); // gets a sprite index, for use in the m_rghSprites[] array + + + 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 + Vector m_vecOrigin; + Vector m_vecAngles; + int m_iKeyBits; + int m_iHideHUDDisplay; + int m_iFOV; + int m_Teamplay; + int m_iRes; + int RealSize; + float m_flScale; + cvar_t *m_pCvarStealMouse; + cvar_t *m_pCvarDraw; + cvar_t *cl_shadows; + + int m_iFontHeight; + CHudAmmo m_Ammo; + CHudHealth m_Health; + CHudSpectator m_Spectator; + CHudGeiger m_Geiger; + CHudBattery m_Battery; + CHudTrain m_Train; + CHudFlashlight m_Flash; + CHudMessage m_Message; + CHudStatusBar m_StatusBar; + CHudDeathNotice m_DeathNotice; + CHudSayText m_SayText; + CHudMenu m_Menu; + CHudAmmoSecondary m_AmmoSecondary; + CHudTextMessage m_TextMessage; + CHudStatusIcons m_StatusIcons; + CHudScoreboard m_Scoreboard; + CHudMOTD m_MOTD; + CHudMoney m_Money; + CHudTimer m_Timer; + CHudRadio m_Radio; + CHudProgressBar m_ProgressBar; + CHudSniperScope m_SniperScope; + CHudNVG m_NVG; + CHudRadar m_Radar; + + + + // user messages + CHudMsgFunc(Damage); + CHudMsgFunc(GameMode); + CHudMsgFunc(Logo); + CHudMsgFunc(ResetHUD); + CHudMsgFunc(InitHUD); + CHudMsgFunc(ViewMode); + CHudMsgFunc(SetFOV); + CHudMsgFunc(Concuss); + CHudMsgFunc(ReceiveW); + CHudMsgFunc(BombDrop); + CHudMsgFunc(BombPickup); + CHudMsgFunc(HostagePos); + CHudMsgFunc(HostageK); + CHudMsgFunc(ShadowIdx); + + + // Screen information + SCREENINFO m_scrinfo; + // As Xash3D can fake m_scrinfo for hud scailing + // we will use a real screen parameters + SCREENINFO m_truescrinfo; + + int m_iWeaponBits; + int m_fPlayerDead; + int m_iIntermission; + int m_iNoConsolePrint; + + // sprite indexes + int m_HUD_number_0; + +private: + HUDLIST *m_pHudList; + HSPRITE m_hsprLogo; + int m_iLogo; + client_sprite_t *m_pSpriteList; + int m_iSpriteCount; + int m_iSpriteCountAllRes; + float m_flMouseSensitivity; + int m_iConcussionEffect; + int m_iForceCamera; + int m_iForceChaseCam; + int m_iFadeToBlack; + + // the memory for these arrays are allocated in the first call to CHud::VidInit(), when the hud.txt and associated sprites are loaded. + // freed in ~CHud() + HSPRITE *m_rghSprites; /*[HUD_SPRITE_COUNT]*/ // the sprites loaded from hud.txt + wrect_t *m_rgrcRects; /*[HUD_SPRITE_COUNT]*/ + char *m_rgszSpriteNames; /*[HUD_SPRITE_COUNT][MAX_SPRITE_NAME_LENGTH]*/ + + struct cvar_s *default_fov; + +}; + +extern CHud gHUD; + +extern int g_iPlayerClass; +extern int g_iTeamNumber; +extern int g_iUser1; +extern int g_iUser2; +extern int g_iUser3; + diff --git a/cl_dll/include/hud/hud_iface.h b/cl_dll/include/hud/hud_iface.h index 0626f64..354e9c5 100644 --- a/cl_dll/include/hud/hud_iface.h +++ b/cl_dll/include/hud/hud_iface.h @@ -1,22 +1,22 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined( HUD_IFACEH ) -#define HUD_IFACEH -#ifdef _WIN32 -#define EXPORT _declspec( dllexport ) -#define _DLLEXPORT __declspec( dllexport ) -#else -#define EXPORT -#define _DLLEXPORT -#endif -typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf); -#include "wrect.h" -#include "../engine/cdll_int.h" -extern cl_enginefunc_t gEngfuncs; - -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined( HUD_IFACEH ) +#define HUD_IFACEH +#ifdef _WIN32 +#define EXPORT _declspec( dllexport ) +#define _DLLEXPORT __declspec( dllexport ) +#else +#define EXPORT +#define _DLLEXPORT +#endif +typedef int (*pfnUserMsgHook)(const char *pszName, int iSize, void *pbuf); +#include "wrect.h" +#include "../engine/cdll_int.h" +extern cl_enginefunc_t gEngfuncs; + +#endif diff --git a/cl_dll/include/hud/hud_spectator.h b/cl_dll/include/hud/hud_spectator.h index 983711e..504436a 100644 --- a/cl_dll/include/hud/hud_spectator.h +++ b/cl_dll/include/hud/hud_spectator.h @@ -1,139 +1,139 @@ -//========= Copyright ? 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#ifndef SPECTATOR_H -#define SPECTATOR_H - -#include "cl_entity.h" -#include "hud.h" - - -#define INSET_OFF 0 -#define INSET_CHASE_FREE 1 -#define INSET_IN_EYE 2 -#define INSET_MAP_FREE 3 -#define INSET_MAP_CHASE 4 - -#define MAX_SPEC_HUD_MESSAGES 8 - - - -#define OVERVIEW_TILE_SIZE 256 // don't change this -#define OVERVIEW_MAX_LAYERS 1 - -//----------------------------------------------------------------------------- -// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it ) -//----------------------------------------------------------------------------- - -typedef struct overviewInfo_s { - char map[64]; // cl.levelname or empty - vec3_t origin; // center of map - float zoom; // zoom of map images - int layers; // how may layers do we have - float layersHeights[OVERVIEW_MAX_LAYERS]; - char layersImages[OVERVIEW_MAX_LAYERS][255]; - qboolean rotated; // are map images rotated (90 degrees) ? - - int insetWindowX; - int insetWindowY; - int insetWindowHeight; - int insetWindowWidth; -} overviewInfo_t; - -typedef struct overviewEntity_s { - - HSPRITE hSprite; - struct cl_entity_s * entity; - double killTime; -} overviewEntity_t; - -#define MAX_OVERVIEW_ENTITIES 128 - -class CHudSpectator : public CHudBase -{ -public: - void Reset(); - int ToggleInset(bool allowOff); - void CheckSettings(); - void InitHUDData( void ); - bool AddOverviewEntityToList( HSPRITE sprite, cl_entity_t * ent, double killTime); - void DeathMessage(int victim); - bool AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname ); - void CheckOverviewEntities(); - void DrawOverview(); - void DrawOverviewEntities(); - void GetMapPosition( float * returnvec ); - void DrawOverviewLayer(); - void LoadMapSprites(); - bool ParseOverviewFile(); - bool IsActivePlayer(cl_entity_t * ent); - void SetModes(int iMainMode, int iInsetMode); - void HandleButtonsDown(int ButtonPressed); - void HandleButtonsUp(int ButtonPressed); - void FindNextPlayer( bool bReverse ); - void DirectorMessage( int iSize, void *pbuf ); - void SetSpectatorStartPosition(); - CHudMsgFunc(Spectator); - int Init(); - int VidInit(); - - int Draw(float flTime); - - int m_iDrawCycle; - client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES]; - char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128]; - int m_lastHudMessage; - overviewInfo_t m_OverviewData; - overviewEntity_t m_OverviewEntities[MAX_OVERVIEW_ENTITIES]; - int m_iObserverFlags; - int m_iSpectatorNumber; - - float m_mapZoom; // zoom the user currently uses - vec3_t m_mapOrigin; // origin where user rotates around - cvar_t * m_drawnames; - cvar_t * m_specmode; - cvar_t * m_drawcone; - cvar_t * m_drawstatus; - cvar_t * m_autoDirector; - float m_lastAutoDirector; - cvar_t * m_pip; - - - qboolean m_chatEnabled; - - vec3_t m_cameraOrigin; // a help camera - vec3_t m_cameraAngles; // and it's angles - - -private: - vec3_t m_vPlayerPos[MAX_PLAYERS]; - HSPRITE m_hsprPlayerC4; - HSPRITE m_hsprPlayerVIP; - HSPRITE m_hsprHostage; - HSPRITE m_hsprBackpack; - HSPRITE m_hsprBomb; - HSPRITE m_hsprPlayerBlue; - HSPRITE m_hsprPlayerRed; - HSPRITE m_hsprPlayer; - HSPRITE m_hsprCamera; - HSPRITE m_hsprPlayerDead; - HSPRITE m_hsprViewcone; - HSPRITE m_hsprUnkownMap; - HSPRITE m_hsprBeam; - HSPRITE m_hCrosshair; - - wrect_t m_crosshairRect; - - struct model_s * m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame - float m_flNextObserverInput; - float m_zoomDelta; - float m_moveDelta; - int m_lastPrimaryObject; - int m_lastSecondaryObject; -}; - -#endif // SPECTATOR_H +//========= Copyright ? 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#ifndef SPECTATOR_H +#define SPECTATOR_H + +#include "cl_entity.h" +#include "hud.h" + + +#define INSET_OFF 0 +#define INSET_CHASE_FREE 1 +#define INSET_IN_EYE 2 +#define INSET_MAP_FREE 3 +#define INSET_MAP_CHASE 4 + +#define MAX_SPEC_HUD_MESSAGES 8 + + + +#define OVERVIEW_TILE_SIZE 256 // don't change this +#define OVERVIEW_MAX_LAYERS 1 + +//----------------------------------------------------------------------------- +// Purpose: Handles the drawing of the spectator stuff (camera & top-down map and all the things on it ) +//----------------------------------------------------------------------------- + +typedef struct overviewInfo_s { + char map[64]; // cl.levelname or empty + vec3_t origin; // center of map + float zoom; // zoom of map images + int layers; // how may layers do we have + float layersHeights[OVERVIEW_MAX_LAYERS]; + char layersImages[OVERVIEW_MAX_LAYERS][255]; + qboolean rotated; // are map images rotated (90 degrees) ? + + int insetWindowX; + int insetWindowY; + int insetWindowHeight; + int insetWindowWidth; +} overviewInfo_t; + +typedef struct overviewEntity_s { + + HSPRITE hSprite; + struct cl_entity_s * entity; + double killTime; +} overviewEntity_t; + +#define MAX_OVERVIEW_ENTITIES 128 + +class CHudSpectator : public CHudBase +{ +public: + void Reset(); + int ToggleInset(bool allowOff); + void CheckSettings(); + void InitHUDData( void ); + bool AddOverviewEntityToList( HSPRITE sprite, cl_entity_t * ent, double killTime); + void DeathMessage(int victim); + bool AddOverviewEntity( int type, struct cl_entity_s *ent, const char *modelname ); + void CheckOverviewEntities(); + void DrawOverview(); + void DrawOverviewEntities(); + void GetMapPosition( float * returnvec ); + void DrawOverviewLayer(); + void LoadMapSprites(); + bool ParseOverviewFile(); + bool IsActivePlayer(cl_entity_t * ent); + void SetModes(int iMainMode, int iInsetMode); + void HandleButtonsDown(int ButtonPressed); + void HandleButtonsUp(int ButtonPressed); + void FindNextPlayer( bool bReverse ); + void DirectorMessage( int iSize, void *pbuf ); + void SetSpectatorStartPosition(); + CHudMsgFunc(Spectator); + int Init(); + int VidInit(); + + int Draw(float flTime); + + int m_iDrawCycle; + client_textmessage_t m_HUDMessages[MAX_SPEC_HUD_MESSAGES]; + char m_HUDMessageText[MAX_SPEC_HUD_MESSAGES][128]; + int m_lastHudMessage; + overviewInfo_t m_OverviewData; + overviewEntity_t m_OverviewEntities[MAX_OVERVIEW_ENTITIES]; + int m_iObserverFlags; + int m_iSpectatorNumber; + + float m_mapZoom; // zoom the user currently uses + vec3_t m_mapOrigin; // origin where user rotates around + cvar_t * m_drawnames; + cvar_t * m_specmode; + cvar_t * m_drawcone; + cvar_t * m_drawstatus; + cvar_t * m_autoDirector; + float m_lastAutoDirector; + cvar_t * m_pip; + + + qboolean m_chatEnabled; + + vec3_t m_cameraOrigin; // a help camera + vec3_t m_cameraAngles; // and it's angles + + +private: + vec3_t m_vPlayerPos[MAX_PLAYERS]; + HSPRITE m_hsprPlayerC4; + HSPRITE m_hsprPlayerVIP; + HSPRITE m_hsprHostage; + HSPRITE m_hsprBackpack; + HSPRITE m_hsprBomb; + HSPRITE m_hsprPlayerBlue; + HSPRITE m_hsprPlayerRed; + HSPRITE m_hsprPlayer; + HSPRITE m_hsprCamera; + HSPRITE m_hsprPlayerDead; + HSPRITE m_hsprViewcone; + HSPRITE m_hsprUnkownMap; + HSPRITE m_hsprBeam; + HSPRITE m_hCrosshair; + + wrect_t m_crosshairRect; + + struct model_s * m_MapSprite; // each layer image is saved in one sprite, where each tile is a sprite frame + float m_flNextObserverInput; + float m_zoomDelta; + float m_moveDelta; + int m_lastPrimaryObject; + int m_lastSecondaryObject; +}; + +#endif // SPECTATOR_H diff --git a/cl_dll/include/in_defs.h b/cl_dll/include/in_defs.h index f39da2a..11457f8 100644 --- a/cl_dll/include/in_defs.h +++ b/cl_dll/include/in_defs.h @@ -1,30 +1,30 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined( IN_DEFSH ) -#define IN_DEFSH - -// up / down -#define PITCH 0 -// left / right -#define YAW 1 -// fall over -#define ROLL 2 - -#ifdef _WIN32 -#define DLLEXPORT __declspec( dllexport ) -#else -#define DLLEXPORT -typedef struct point_s{ - int x; - int y; -} POINT; -#define GetCursorPos(x) -#define SetCursorPos(x,y) -#endif - -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined( IN_DEFSH ) +#define IN_DEFSH + +// up / down +#define PITCH 0 +// left / right +#define YAW 1 +// fall over +#define ROLL 2 + +#ifdef _WIN32 +#define DLLEXPORT __declspec( dllexport ) +#else +#define DLLEXPORT +typedef struct point_s{ + int x; + int y; +} POINT; +#define GetCursorPos(x) +#define SetCursorPos(x,y) +#endif + +#endif diff --git a/cl_dll/include/kbutton.h b/cl_dll/include/kbutton.h index bab692f..241c730 100644 --- a/cl_dll/include/kbutton.h +++ b/cl_dll/include/kbutton.h @@ -1,17 +1,17 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined( KBUTTONH ) -#define KBUTTONH - -typedef struct kbutton_s -{ - int down[2]; // key nums holding it down - int state; // low bit is down state -} kbutton_t; - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined( KBUTTONH ) +#define KBUTTONH + +typedef struct kbutton_s +{ + int down[2]; // key nums holding it down + int state; // low bit is down state +} kbutton_t; + #endif // !KBUTTONH \ No newline at end of file diff --git a/cl_dll/include/overview.h b/cl_dll/include/overview.h index 14c0705..d3b8ded 100644 --- a/cl_dll/include/overview.h +++ b/cl_dll/include/overview.h @@ -1,30 +1,30 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#ifndef OVERVIEW_H -#define OVERVIEW_H - - -//----------------------------------------------------------------------------- -// Purpose: Handles the drawing of the top-down map and all the things on it -//----------------------------------------------------------------------------- -class CHudOverview : public CHudBase -{ -public: - int Init(); - int VidInit(); - - int Draw(float flTime); - void InitHUDData( void ); - -private: - HSPRITE m_hsprPlayer; - HSPRITE m_hsprViewcone; -}; - - -#endif // OVERVIEW_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#ifndef OVERVIEW_H +#define OVERVIEW_H + + +//----------------------------------------------------------------------------- +// Purpose: Handles the drawing of the top-down map and all the things on it +//----------------------------------------------------------------------------- +class CHudOverview : public CHudBase +{ +public: + int Init(); + int VidInit(); + + int Draw(float flTime); + void InitHUDData( void ); + +private: + HSPRITE m_hsprPlayer; + HSPRITE m_hsprViewcone; +}; + + +#endif // OVERVIEW_H diff --git a/cl_dll/include/parsemsg.h b/cl_dll/include/parsemsg.h index 78eb93d..9239290 100644 --- a/cl_dll/include/parsemsg.h +++ b/cl_dll/include/parsemsg.h @@ -1,40 +1,40 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// parsemsg.h -// -#pragma once -#define ASSERT( x ) - -void BEGIN_READ( void *buf, int size ); -int READ_CHAR( void ); -int READ_BYTE( void ); -int READ_SHORT( void ); -int READ_WORD( void ); -int READ_LONG( void ); -float READ_FLOAT( void ); -char* READ_STRING( void ); -float READ_COORD( void ); -float READ_ANGLE( void ); -float READ_HIRESANGLE( void ); - - - - - - - - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// parsemsg.h +// +#pragma once +#define ASSERT( x ) + +void BEGIN_READ( void *buf, int size ); +int READ_CHAR( void ); +int READ_BYTE( void ); +int READ_SHORT( void ); +int READ_WORD( void ); +int READ_LONG( void ); +float READ_FLOAT( void ); +char* READ_STRING( void ); +float READ_COORD( void ); +float READ_ANGLE( void ); +float READ_HIRESANGLE( void ); + + + + + + + + + diff --git a/cl_dll/include/rain.h b/cl_dll/include/rain.h index 6918fa1..8587ee1 100644 --- a/cl_dll/include/rain.h +++ b/cl_dll/include/rain.h @@ -1,82 +1,82 @@ -/*** -* -* Copyright (c) 1996-2004, Shambler Team. 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 -* Shambler Team. All other use, distribution, or modification is prohibited -* without written permission from Shambler Team. -* -****/ -/* -====== rain.h ======================================================== -*/ -#pragma once -#ifndef __RAIN_H__ -#define __RAIN_H__ - -#define DRIPSPEED 900 // speed of raindrips (pixel per secs) -#define SNOWSPEED 200 // speed of snowflakes -#define SNOWFADEDIST 80 - -#define MAXDRIPS 2000 // max raindrops -#define MAXFX 3000 // max effects - -#define DRIP_SPRITE_HALFHEIGHT 64 -#define DRIP_SPRITE_HALFWIDTH 1 -#define SNOW_SPRITE_HALFSIZE 3 - -// radius water rings -#define MAXRINGHALFSIZE 25 - -typedef struct -{ - int dripsPerSecond; - float distFromPlayer; - float windX, windY; - float randX, randY; - int weatherMode; // 0 - snow, 1 - rain - float globalHeight; -} rain_properties; - -typedef struct cl_drip -{ - float birthTime; - float minHeight; // minimal height to kill raindrop - vec3_t origin; - float alpha; - - float xDelta; // side speed - float yDelta; - int landInWater; - - cl_drip* p_Next; // next drip in chain - cl_drip* p_Prev; // previous drip in chain -} cl_drip_t; - -typedef struct cl_rainfx -{ - float birthTime; - float life; - vec3_t origin; - float alpha; - - cl_rainfx* p_Next; // next fx in chain - cl_rainfx* p_Prev; // previous fx in chain -} cl_rainfx_t; - -extern rain_properties Rain; -extern cl_drip_t FirstChainDrip; -extern cl_rainfx_t FirstChainFX; - - -void ProcessRain( void ); -void ProcessFXObjects( void ); -void ResetRain( void ); -void InitRain( void ); - -#endif +/*** +* +* Copyright (c) 1996-2004, Shambler Team. 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 +* Shambler Team. All other use, distribution, or modification is prohibited +* without written permission from Shambler Team. +* +****/ +/* +====== rain.h ======================================================== +*/ +#pragma once +#ifndef __RAIN_H__ +#define __RAIN_H__ + +#define DRIPSPEED 900 // speed of raindrips (pixel per secs) +#define SNOWSPEED 200 // speed of snowflakes +#define SNOWFADEDIST 80 + +#define MAXDRIPS 2000 // max raindrops +#define MAXFX 3000 // max effects + +#define DRIP_SPRITE_HALFHEIGHT 64 +#define DRIP_SPRITE_HALFWIDTH 1 +#define SNOW_SPRITE_HALFSIZE 3 + +// radius water rings +#define MAXRINGHALFSIZE 25 + +typedef struct +{ + int dripsPerSecond; + float distFromPlayer; + float windX, windY; + float randX, randY; + int weatherMode; // 0 - snow, 1 - rain + float globalHeight; +} rain_properties; + +typedef struct cl_drip +{ + float birthTime; + float minHeight; // minimal height to kill raindrop + vec3_t origin; + float alpha; + + float xDelta; // side speed + float yDelta; + int landInWater; + + cl_drip* p_Next; // next drip in chain + cl_drip* p_Prev; // previous drip in chain +} cl_drip_t; + +typedef struct cl_rainfx +{ + float birthTime; + float life; + vec3_t origin; + float alpha; + + cl_rainfx* p_Next; // next fx in chain + cl_rainfx* p_Prev; // previous fx in chain +} cl_rainfx_t; + +extern rain_properties Rain; +extern cl_drip_t FirstChainDrip; +extern cl_rainfx_t FirstChainFX; + + +void ProcessRain( void ); +void ProcessFXObjects( void ); +void ResetRain( void ); +void InitRain( void ); + +#endif diff --git a/cl_dll/include/studio/GameStudioModelRenderer.h b/cl_dll/include/studio/GameStudioModelRenderer.h index 3b09792..53f9d76 100644 --- a/cl_dll/include/studio/GameStudioModelRenderer.h +++ b/cl_dll/include/studio/GameStudioModelRenderer.h @@ -1,85 +1,85 @@ - -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// Big thanks to Chicken Fortress developers -// for this code. - -#pragma once -#if !defined (GAMESTUDIOMODELRENDERER_H) -#define GAMESTUDIOMODELRENDERER_H - -enum BoneIndex -{ - BONE_HEAD, - BONE_PELVIS, - BONE_SPINE1, - BONE_SPINE2, - BONE_SPINE3, - BONE_MAX, -}; - -typedef struct -{ - vec3_t origin; - vec3_t angles; - - vec3_t realangles; - - float animtime; - float frame; - int sequence; - int gaitsequence; - float framerate; - - int m_fSequenceLoops; - int m_fSequenceFinished; - - byte controller[4]; - byte blending[2]; - - latchedvars_t lv; -}client_anim_state_t; - -class CGameStudioModelRenderer : public CStudioModelRenderer -{ -public: - CGameStudioModelRenderer(void); - -public: - virtual void StudioSetupBones(void); - virtual void StudioEstimateGait(entity_state_t *pplayer); - virtual void StudioProcessGait(entity_state_t *pplayer); - virtual int StudioDrawPlayer(int flags, entity_state_t *pplayer); - virtual int _StudioDrawPlayer(int flags, entity_state_t *pplayer); - virtual void StudioFxTransform(cl_entity_t *ent, float transform[3][4]); - virtual void StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch); - virtual void CalculateYawBlend(entity_state_t *pplayer); - virtual void CalculatePitchBlend(entity_state_t *pplayer); - -private: - void SavePlayerState(entity_state_t *pplayer); - void SetupClientAnimation(entity_state_t *pplayer); - void RestorePlayerState(entity_state_t *pplayer); - mstudioanim_t* LookupAnimation(mstudioseqdesc_t *pseqdesc, int index); - -private: - int m_nPlayerGaitSequences[MAX_CLIENTS]; - bool m_bLocal; -}; - -extern CGameStudioModelRenderer g_StudioRenderer; - -#endif + +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// Big thanks to Chicken Fortress developers +// for this code. + +#pragma once +#if !defined (GAMESTUDIOMODELRENDERER_H) +#define GAMESTUDIOMODELRENDERER_H + +enum BoneIndex +{ + BONE_HEAD, + BONE_PELVIS, + BONE_SPINE1, + BONE_SPINE2, + BONE_SPINE3, + BONE_MAX, +}; + +typedef struct +{ + vec3_t origin; + vec3_t angles; + + vec3_t realangles; + + float animtime; + float frame; + int sequence; + int gaitsequence; + float framerate; + + int m_fSequenceLoops; + int m_fSequenceFinished; + + byte controller[4]; + byte blending[2]; + + latchedvars_t lv; +}client_anim_state_t; + +class CGameStudioModelRenderer : public CStudioModelRenderer +{ +public: + CGameStudioModelRenderer(void); + +public: + virtual void StudioSetupBones(void); + virtual void StudioEstimateGait(entity_state_t *pplayer); + virtual void StudioProcessGait(entity_state_t *pplayer); + virtual int StudioDrawPlayer(int flags, entity_state_t *pplayer); + virtual int _StudioDrawPlayer(int flags, entity_state_t *pplayer); + virtual void StudioFxTransform(cl_entity_t *ent, float transform[3][4]); + virtual void StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch); + virtual void CalculateYawBlend(entity_state_t *pplayer); + virtual void CalculatePitchBlend(entity_state_t *pplayer); + +private: + void SavePlayerState(entity_state_t *pplayer); + void SetupClientAnimation(entity_state_t *pplayer); + void RestorePlayerState(entity_state_t *pplayer); + mstudioanim_t* LookupAnimation(mstudioseqdesc_t *pseqdesc, int index); + +private: + int m_nPlayerGaitSequences[MAX_CLIENTS]; + bool m_bLocal; +}; + +extern CGameStudioModelRenderer g_StudioRenderer; + +#endif diff --git a/cl_dll/include/studio/StudioModelRenderer.h b/cl_dll/include/studio/StudioModelRenderer.h index ce4fee0..2321f1a 100644 --- a/cl_dll/include/studio/StudioModelRenderer.h +++ b/cl_dll/include/studio/StudioModelRenderer.h @@ -1,97 +1,97 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// Big thanks to Chicken Fortress developers -// for this code. -#pragma once -#ifndef STUDIOMODELRENDERER_H -#define STUDIOMODELRENDERER_H - -class CStudioModelRenderer -{ -public: - CStudioModelRenderer(void); - virtual ~CStudioModelRenderer(void); - -public: - virtual void Init(void); - virtual int StudioDrawModel(int flags); - virtual int StudioDrawPlayer(int flags, struct entity_state_s *pplayer); - -public: - virtual mstudioanim_t *StudioGetAnim(model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc); - virtual void StudioSetUpTransform(int trivial_accept); - virtual void StudioSetupBones(void); - virtual void StudioCalcAttachments(void); - virtual void StudioSaveBones(void); - virtual void StudioMergeBones(model_t *m_pSubModel); - virtual float StudioEstimateInterpolant(void); - virtual float StudioEstimateFrame(mstudioseqdesc_t *pseqdesc); - virtual void StudioFxTransform(cl_entity_t *ent, float transform[3][4]); - virtual void StudioSlerpBones(vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s); - virtual void StudioCalcBoneAdj(float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen); - virtual void StudioCalcBoneQuaterion(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q); - virtual void StudioCalcBonePosition(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos); - virtual void StudioCalcRotations(float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f); - virtual void StudioRenderModel(float *lightdir); - virtual void StudioRenderFinal(void); - virtual void StudioRenderFinal_Software(void); - virtual void StudioRenderFinal_Hardware(void); - virtual void StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch); - virtual void StudioEstimateGait(entity_state_t *pplayer); - virtual void StudioProcessGait(entity_state_t *pplayer); - virtual void StudioSetShadowSprite(int idx); - virtual void StudioDrawShadow(Vector origin, float scale); - - -public: - double m_clTime; - double m_clOldTime; - int m_fDoInterp; - int m_iShadowSprite; - int m_fGaitEstimation; - int m_nFrameCount; - cvar_t *m_pCvarHiModels; - cvar_t *m_pCvarDeveloper; - cvar_t *m_pCvarDrawEntities; - cl_entity_t *m_pCurrentEntity; - model_t *m_pRenderModel; - player_info_t *m_pPlayerInfo; - int m_nPlayerIndex; - float m_flGaitMovement; - studiohdr_t *m_pStudioHeader; - mstudiobodyparts_t *m_pBodyPart; - mstudiomodel_t *m_pSubModel; - int m_nTopColor; - int m_nBottomColor; - model_t *m_pChromeSprite; - int m_nCachedBones; - char m_nCachedBoneNames[MAXSTUDIOBONES][32]; - float m_rgCachedBoneTransform[MAXSTUDIOBONES][3][4]; - float m_rgCachedLightTransform[MAXSTUDIOBONES][3][4]; - float m_fSoftwareXScale, m_fSoftwareYScale; - float m_vUp[3]; - float m_vRight[3]; - float m_vNormal[3]; - float m_vRenderOrigin[3]; - int *m_pStudioModelCount; - int *m_pModelsDrawn; - float (*m_protationmatrix)[3][4]; - float (*m_paliastransform)[3][4]; - float (*m_pbonetransform)[MAXSTUDIOBONES][3][4]; - float (*m_plighttransform)[MAXSTUDIOBONES][3][4]; -}; - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// Big thanks to Chicken Fortress developers +// for this code. +#pragma once +#ifndef STUDIOMODELRENDERER_H +#define STUDIOMODELRENDERER_H + +class CStudioModelRenderer +{ +public: + CStudioModelRenderer(void); + virtual ~CStudioModelRenderer(void); + +public: + virtual void Init(void); + virtual int StudioDrawModel(int flags); + virtual int StudioDrawPlayer(int flags, struct entity_state_s *pplayer); + +public: + virtual mstudioanim_t *StudioGetAnim(model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc); + virtual void StudioSetUpTransform(int trivial_accept); + virtual void StudioSetupBones(void); + virtual void StudioCalcAttachments(void); + virtual void StudioSaveBones(void); + virtual void StudioMergeBones(model_t *m_pSubModel); + virtual float StudioEstimateInterpolant(void); + virtual float StudioEstimateFrame(mstudioseqdesc_t *pseqdesc); + virtual void StudioFxTransform(cl_entity_t *ent, float transform[3][4]); + virtual void StudioSlerpBones(vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s); + virtual void StudioCalcBoneAdj(float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen); + virtual void StudioCalcBoneQuaterion(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q); + virtual void StudioCalcBonePosition(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos); + virtual void StudioCalcRotations(float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f); + virtual void StudioRenderModel(float *lightdir); + virtual void StudioRenderFinal(void); + virtual void StudioRenderFinal_Software(void); + virtual void StudioRenderFinal_Hardware(void); + virtual void StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch); + virtual void StudioEstimateGait(entity_state_t *pplayer); + virtual void StudioProcessGait(entity_state_t *pplayer); + virtual void StudioSetShadowSprite(int idx); + virtual void StudioDrawShadow(Vector origin, float scale); + + +public: + double m_clTime; + double m_clOldTime; + int m_fDoInterp; + int m_iShadowSprite; + int m_fGaitEstimation; + int m_nFrameCount; + cvar_t *m_pCvarHiModels; + cvar_t *m_pCvarDeveloper; + cvar_t *m_pCvarDrawEntities; + cl_entity_t *m_pCurrentEntity; + model_t *m_pRenderModel; + player_info_t *m_pPlayerInfo; + int m_nPlayerIndex; + float m_flGaitMovement; + studiohdr_t *m_pStudioHeader; + mstudiobodyparts_t *m_pBodyPart; + mstudiomodel_t *m_pSubModel; + int m_nTopColor; + int m_nBottomColor; + model_t *m_pChromeSprite; + int m_nCachedBones; + char m_nCachedBoneNames[MAXSTUDIOBONES][32]; + float m_rgCachedBoneTransform[MAXSTUDIOBONES][3][4]; + float m_rgCachedLightTransform[MAXSTUDIOBONES][3][4]; + float m_fSoftwareXScale, m_fSoftwareYScale; + float m_vUp[3]; + float m_vRight[3]; + float m_vNormal[3]; + float m_vRenderOrigin[3]; + int *m_pStudioModelCount; + int *m_pModelsDrawn; + float (*m_protationmatrix)[3][4]; + float (*m_paliastransform)[3][4]; + float (*m_pbonetransform)[MAXSTUDIOBONES][3][4]; + float (*m_plighttransform)[MAXSTUDIOBONES][3][4]; +}; + +#endif diff --git a/cl_dll/include/studio/studio_util.h b/cl_dll/include/studio/studio_util.h index a76dfb9..79d7d08 100644 --- a/cl_dll/include/studio/studio_util.h +++ b/cl_dll/include/studio/studio_util.h @@ -1,38 +1,38 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined( STUDIO_UTIL_H ) -#define STUDIO_UTIL_H - - -#ifndef M_PI -#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h -#endif - -#ifndef PITCH -// MOVEMENT INFO -// up / down -#define PITCH 0 -// left / right -#define YAW 1 -// fall over -#define ROLL 2 -#endif - -#define FDotProduct( a, b ) (fabs((a[0])*(b[0])) + fabs((a[1])*(b[1])) + fabs((a[2])*(b[2]))) - -void AngleMatrix (const float *angles, float (*matrix)[4] ); -int VectorCompare (const float *v1, const float *v2); -void CrossProduct (const float *v1, const float *v2, float *cross); -void VectorTransform (const float *in1, float in2[3][4], float *out); -void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); -void MatrixCopy( float in[3][4], float out[3][4] ); -void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ); -void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt ); -void AngleQuaternion( float *angles, vec4_t quaternion ); - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined( STUDIO_UTIL_H ) +#define STUDIO_UTIL_H + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif + +#ifndef PITCH +// MOVEMENT INFO +// up / down +#define PITCH 0 +// left / right +#define YAW 1 +// fall over +#define ROLL 2 +#endif + +#define FDotProduct( a, b ) (fabs((a[0])*(b[0])) + fabs((a[1])*(b[1])) + fabs((a[2])*(b[2]))) + +void AngleMatrix (const float *angles, float (*matrix)[4] ); +int VectorCompare (const float *v1, const float *v2); +void CrossProduct (const float *v1, const float *v2, float *cross); +void VectorTransform (const float *in1, float in2[3][4], float *out); +void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); +void MatrixCopy( float in[3][4], float out[3][4] ); +void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ); +void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt ); +void AngleQuaternion( float *angles, vec4_t quaternion ); + #endif // STUDIO_UTIL_H \ No newline at end of file diff --git a/cl_dll/include/tf_defs.h b/cl_dll/include/tf_defs.h index f178c55..06d9af0 100644 --- a/cl_dll/include/tf_defs.h +++ b/cl_dll/include/tf_defs.h @@ -1,1389 +1,1389 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#ifndef __TF_DEFS_H -#define __TF_DEFS_H - -//=========================================================================== -// OLD OPTIONS.QC -//=========================================================================== -#define DEFAULT_AUTOZOOM FALSE -#define WEINER_SNIPER // autoaiming for sniper rifle -#define FLAME_MAXWORLDNUM 20 // maximum number of flames in the world. DO NOT PUT BELOW 20. - -//#define MAX_WORLD_PIPEBOMBS 15 // This is divided between teams - this is the most you should have on a net server -#define MAX_PLAYER_PIPEBOMBS 8 // maximum number of pipebombs any 1 player can have active -#define MAX_PLAYER_AMMOBOXES 3 // maximum number of ammoboxes any 1 player can have active - -//#define MAX_WORLD_FLARES 9 // This is the total number of flares allowed in the world at one time -//#define MAX_WORLD_AMMOBOXES 20 // This is divided between teams - this is the most you should have on a net server -#define GR_TYPE_MIRV_NO 4 // Number of Mirvs a Mirv Grenade breaks into -#define GR_TYPE_NAPALM_NO 8 // Number of flames napalm grenade breaks into (unused if net server) -#define MEDIKIT_IS_BIOWEAPON // Medikit acts as a bioweapon against enemies - -#define TEAM_HELP_RATE 60 // used only if teamplay bit 64 (help team with lower score) is set. - // 60 is a mild setting, and won't make too much difference - // increasing it _decreases_ the amount of help the losing team gets - // Minimum setting is 1, which would really help the losing team - -#define DISPLAY_CLASS_HELP TRUE // Change this to #OFF if you don't want the class help to - // appear whenever a player connects -#define NEVER_TEAMFRAGS FALSE // teamfrags options always off -#define ALWAYS_TEAMFRAGS FALSE // teamfrags options always on -#define CHECK_SPEEDS TRUE // makes sure players aren't moving too fast -#define SNIPER_RIFLE_RELOAD_TIME 1.5 // seconds - -#define MAPBRIEFING_MAXTEXTLENGTH 512 -#define PLAYER_PUSH_VELOCITY 50 // Players push teammates if they're moving under this speed - -// Debug Options -//#define MAP_DEBUG // Debug for Map code. I suggest running in a hi-res - // mode and/or piping the output from the server to a file. -#ifdef MAP_DEBUG - #define MDEBUG(x) x -#else - #define MDEBUG(x) -#endif -//#define VERBOSE // Verbose Debugging on/off - -//=========================================================================== -// OLD QUAKE Defs -//=========================================================================== -// items -#define IT_AXE 4096 -#define IT_SHOTGUN 1 -#define IT_SUPER_SHOTGUN 2 -#define IT_NAILGUN 4 -#define IT_SUPER_NAILGUN 8 -#define IT_GRENADE_LAUNCHER 16 -#define IT_ROCKET_LAUNCHER 32 -#define IT_LIGHTNING 64 -#define IT_EXTRA_WEAPON 128 - -#define IT_SHELLS 256 -#define IT_NAILS 512 -#define IT_ROCKETS 1024 -#define IT_CELLS 2048 - -#define IT_ARMOR1 8192 -#define IT_ARMOR2 16384 -#define IT_ARMOR3 32768 -#define IT_SUPERHEALTH 65536 - -#define IT_KEY1 131072 -#define IT_KEY2 262144 - -#define IT_INVISIBILITY 524288 -#define IT_INVULNERABILITY 1048576 -#define IT_SUIT 2097152 -#define IT_QUAD 4194304 -#define IT_HOOK 8388608 - -#define IT_KEY3 16777216 // Stomp invisibility -#define IT_KEY4 33554432 // Stomp invulnerability - -//=========================================================================== -// TEAMFORTRESS Defs -//=========================================================================== -// TeamFortress State Flags -#define TFSTATE_GRENPRIMED 1 // Whether the player has a primed grenade -#define TFSTATE_RELOADING 2 // Whether the player is reloading -#define TFSTATE_ALTKILL 4 // #TRUE if killed with a weapon not in self.weapon: NOT USED ANYMORE -#define TFSTATE_RANDOMPC 8 // Whether Playerclass is random, new one each respawn -#define TFSTATE_INFECTED 16 // set when player is infected by the bioweapon -#define TFSTATE_INVINCIBLE 32 // Player has permanent Invincibility (Usually by GoalItem) -#define TFSTATE_INVISIBLE 64 // Player has permanent Invisibility (Usually by GoalItem) -#define TFSTATE_QUAD 128 // Player has permanent Quad Damage (Usually by GoalItem) -#define TFSTATE_RADSUIT 256 // Player has permanent Radsuit (Usually by GoalItem) -#define TFSTATE_BURNING 512 // Is on fire -#define TFSTATE_GRENTHROWING 1024 // is throwing a grenade -#define TFSTATE_AIMING 2048 // is using the laser sight -#define TFSTATE_ZOOMOFF 4096 // doesn't want the FOV changed when zooming -#define TFSTATE_RESPAWN_READY 8192 // is waiting for respawn, and has pressed fire -#define TFSTATE_HALLUCINATING 16384 // set when player is hallucinating -#define TFSTATE_TRANQUILISED 32768 // set when player is tranquilised -#define TFSTATE_CANT_MOVE 65536 // set when player is setting a detpack -#define TFSTATE_RESET_FLAMETIME 131072 // set when the player has to have his flames increased in health - -// Defines used by TF_T_Damage (see combat.qc) -#define TF_TD_IGNOREARMOUR 1 // Bypasses the armour of the target -#define TF_TD_NOTTEAM 2 // Doesn't damage a team member (indicates direct fire weapon) -#define TF_TD_NOTSELF 4 // Doesn't damage self - -#define TF_TD_OTHER 0 // Ignore armorclass -#define TF_TD_SHOT 1 // Bullet damage -#define TF_TD_NAIL 2 // Nail damage -#define TF_TD_EXPLOSION 4 // Explosion damage -#define TF_TD_ELECTRICITY 8 // Electric damage -#define TF_TD_FIRE 16 // Fire damage -#define TF_TD_NOSOUND 256 // Special damage. Makes no sound/painframe, etc - -/*==================================================*/ -/* Toggleable Game Settings */ -/*==================================================*/ -#define TF_RESPAWNDELAY1 5 // seconds of waiting before player can respawn -#define TF_RESPAWNDELAY2 10 // seconds of waiting before player can respawn -#define TF_RESPAWNDELAY3 20 // seconds of waiting before player can respawn - -#define TEAMPLAY_NORMAL 1 -#define TEAMPLAY_HALFDIRECT 2 -#define TEAMPLAY_NODIRECT 4 -#define TEAMPLAY_HALFEXPLOSIVE 8 -#define TEAMPLAY_NOEXPLOSIVE 16 -#define TEAMPLAY_LESSPLAYERSHELP 32 -#define TEAMPLAY_LESSSCOREHELP 64 -#define TEAMPLAY_HALFDIRECTARMOR 128 -#define TEAMPLAY_NODIRECTARMOR 256 -#define TEAMPLAY_HALFEXPARMOR 512 -#define TEAMPLAY_NOEXPARMOR 1024 -#define TEAMPLAY_HALFDIRMIRROR 2048 -#define TEAMPLAY_FULLDIRMIRROR 4096 -#define TEAMPLAY_HALFEXPMIRROR 8192 -#define TEAMPLAY_FULLEXPMIRROR 16384 - -#define TEAMPLAY_TEAMDAMAGE (TEAMPLAY_NODIRECT | TEAMPLAY_HALFDIRECT | TEAMPLAY_HALFEXPLOSIVE | TEAMPLAY_NOEXPLOSIVE) -// FortressMap stuff -#define TEAM1_CIVILIANS 1 -#define TEAM2_CIVILIANS 2 -#define TEAM3_CIVILIANS 4 -#define TEAM4_CIVILIANS 8 - -// Defines for the playerclass -#define PC_UNDEFINED 0 - -#define PC_SCOUT 1 -#define PC_SNIPER 2 -#define PC_SOLDIER 3 -#define PC_DEMOMAN 4 -#define PC_MEDIC 5 -#define PC_HVYWEAP 6 -#define PC_PYRO 7 -#define PC_SPY 8 -#define PC_ENGINEER 9 - -// Insert new class definitions here - -// PC_RANDOM _MUST_ be the third last class -#define PC_RANDOM 10 // Random playerclass -#define PC_CIVILIAN 11 // Civilians are a special class. They cannot - // be chosen by players, only enforced by maps -#define PC_LASTCLASS 12 // Use this as the high-boundary for any loops - // through the playerclass. - -#define SENTRY_COLOR 10 // will be in the PC_RANDOM slot for team colors - -// These are just for the scanner -#define SCAN_SENTRY 13 -#define SCAN_GOALITEM 14 - -// Values returned by CheckArea -enum -{ - CAREA_CLEAR, - CAREA_BLOCKED, - CAREA_NOBUILD -}; - -/*==================================================*/ -/* Impulse Defines */ -/*==================================================*/ -// Alias check to see whether they already have the aliases -#define TF_ALIAS_CHECK 13 - -// CTF Support Impulses -#define HOOK_IMP1 22 -#define FLAG_INFO 23 -#define HOOK_IMP2 39 - -// Axe -#define AXE_IMP 40 - -// Camera Impulse -#define TF_CAM_TARGET 50 -#define TF_CAM_ZOOM 51 -#define TF_CAM_ANGLE 52 -#define TF_CAM_VEC 53 -#define TF_CAM_PROJECTILE 54 -#define TF_CAM_PROJECTILE_Z 55 -#define TF_CAM_REVANGLE 56 -#define TF_CAM_OFFSET 57 -#define TF_CAM_DROP 58 -#define TF_CAM_FADETOBLACK 59 -#define TF_CAM_FADEFROMBLACK 60 -#define TF_CAM_FADETOWHITE 61 -#define TF_CAM_FADEFROMWHITE 62 - -// Last Weapon impulse -#define TF_LAST_WEAPON 69 - -// Status Bar Resolution Settings. Same as CTF to maintain ease of use. -#define TF_STATUSBAR_RES_START 71 -#define TF_STATUSBAR_RES_END 81 - -// Clan Messages -#define TF_MESSAGE_1 82 -#define TF_MESSAGE_2 83 -#define TF_MESSAGE_3 84 -#define TF_MESSAGE_4 85 -#define TF_MESSAGE_5 86 - -#define TF_CHANGE_CLASS 99 // Bring up the Class Change menu - -// Added to PC_??? to get impulse to use if this clashes with your -// own impulses, just change this value, not the PC_?? -#define TF_CHANGEPC 100 -// The next few impulses are all the class selections -//PC_SCOUT 101 -//PC_SNIPER 102 -//PC_SOLDIER 103 -//PC_DEMOMAN 104 -//PC_MEDIC 105 -//PC_HVYWEAP 106 -//PC_PYRO 107 -//PC_RANDOM 108 -//PC_CIVILIAN 109 // Cannot be used -//PC_SPY 110 -//PC_ENGINEER 111 - -// Help impulses -#define TF_DISPLAYLOCATION 118 -#define TF_STATUS_QUERY 119 - -#define TF_HELP_MAP 131 - -// Information impulses -#define TF_INVENTORY 135 -#define TF_SHOWTF 136 -#define TF_SHOWLEGALCLASSES 137 - -// Team Impulses -#define TF_TEAM_1 140 // Join Team 1 -#define TF_TEAM_2 141 // Join Team 2 -#define TF_TEAM_3 142 // Join Team 3 -#define TF_TEAM_4 143 // Join Team 4 -#define TF_TEAM_CLASSES 144 // Impulse to display team classes -#define TF_TEAM_SCORES 145 // Impulse to display team scores -#define TF_TEAM_LIST 146 // Impulse to display the players in each team. - -// Grenade Impulses -#define TF_GRENADE_1 150 // Prime grenade type 1 -#define TF_GRENADE_2 151 // Prime grenade type 2 -#define TF_GRENADE_T 152 // Throw primed grenade - -// Impulses for new items -//#define TF_SCAN 159 // Scanner Pre-Impulse -#define TF_AUTO_SCAN 159 // Scanner On/Off -#define TF_SCAN_ENEMY 160 // Impulses to toggle scanning of enemies -#define TF_SCAN_FRIENDLY 161 // Impulses to toggle scanning of friendlies -//#define TF_SCAN_10 162 // Scan using 10 enery (1 cell) -#define TF_SCAN_SOUND 162 // Scanner sounds on/off -#define TF_SCAN_30 163 // Scan using 30 energy (2 cells) -#define TF_SCAN_100 164 // Scan using 100 energy (5 cells) -#define TF_DETPACK_5 165 // Detpack set to 5 seconds -#define TF_DETPACK_20 166 // Detpack set to 20 seconds -#define TF_DETPACK_50 167 // Detpack set to 50 seconds -#define TF_DETPACK 168 // Detpack Pre-Impulse -#define TF_DETPACK_STOP 169 // Impulse to stop setting detpack -#define TF_PB_DETONATE 170 // Detonate Pipebombs - -// Special skill -#define TF_SPECIAL_SKILL 171 - -// Ammo Drop impulse -#define TF_DROP_AMMO 172 - -// Reload impulse -#define TF_RELOAD 173 - -// auto-zoom toggle -#define TF_AUTOZOOM 174 - -// drop/pass commands -#define TF_DROPKEY 175 - -// Select Medikit -#define TF_MEDIKIT 176 - -// Spy Impulses -#define TF_SPY_SPY 177 // On net, go invisible, on LAN, change skin/color -#define TF_SPY_DIE 178 // Feign Death - -// Engineer Impulses -#define TF_ENGINEER_BUILD 179 -#define TF_ENGINEER_SANDBAG 180 - -// Medic -#define TF_MEDIC_HELPME 181 - -// Status bar -#define TF_STATUSBAR_ON 182 -#define TF_STATUSBAR_OFF 183 - -// Discard impulse -#define TF_DISCARD 184 - -// ID Player impulse -#define TF_ID 185 - -// Clan Battle impulses -#define TF_SHOWIDS 186 - -// More Engineer Impulses -#define TF_ENGINEER_DETDISP 187 -#define TF_ENGINEER_DETSENT 188 - -// Admin Commands -#define TF_ADMIN_DEAL_CYCLE 189 -#define TF_ADMIN_KICK 190 -#define TF_ADMIN_BAN 191 -#define TF_ADMIN_COUNTPLAYERS 192 -#define TF_ADMIN_CEASEFIRE 193 - -// Drop Goal Items -#define TF_DROPGOALITEMS 194 - -// More Admin Commands -#define TF_ADMIN_NEXT 195 - -// More Engineer Impulses -#define TF_ENGINEER_DETEXIT 196 -#define TF_ENGINEER_DETENTRANCE 197 - -// Yet MORE Admin Commands -#define TF_ADMIN_LISTIPS 198 - -// Silent Spy Feign -#define TF_SPY_SILENTDIE 199 - - -/*==================================================*/ -/* Defines for the ENGINEER's Building ability */ -/*==================================================*/ -// Ammo costs -#define AMMO_COST_SHELLS 2 // Metal needed to make 1 shell -#define AMMO_COST_NAILS 1 -#define AMMO_COST_ROCKETS 2 -#define AMMO_COST_CELLS 2 - -// Building types -#define BUILD_DISPENSER 1 -#define BUILD_SENTRYGUN 2 -#define BUILD_MORTAR 3 -#define BUILD_TELEPORTER_ENTRANCE 4 -#define BUILD_TELEPORTER_EXIT 5 - -// Building metal costs -#define BUILD_COST_DISPENSER 100 // Metal needed to built -#define BUILD_COST_SENTRYGUN 130 -#define BUILD_COST_MORTAR 150 -#define BUILD_COST_TELEPORTER 125 - -#define BUILD_COST_SANDBAG 20 // Built with a separate alias - -// Building times -#define BUILD_TIME_DISPENSER 2 // seconds to build -#define BUILD_TIME_SENTRYGUN 5 -#define BUILD_TIME_MORTAR 5 -#define BUILD_TIME_TELEPORTER 4 - -// Building health levels -#define BUILD_HEALTH_DISPENSER 150 // Health of the building -#define BUILD_HEALTH_SENTRYGUN 150 -#define BUILD_HEALTH_MORTAR 200 -#define BUILD_HEALTH_TELEPORTER 80 - -// Dispenser's maximum carrying capability -#define BUILD_DISPENSER_MAX_SHELLS 400 -#define BUILD_DISPENSER_MAX_NAILS 600 -#define BUILD_DISPENSER_MAX_ROCKETS 300 -#define BUILD_DISPENSER_MAX_CELLS 400 -#define BUILD_DISPENSER_MAX_ARMOR 500 - -// Build state sent down to client -#define BS_BUILDING (1<<0) -#define BS_HAS_DISPENSER (1<<1) -#define BS_HAS_SENTRYGUN (1<<2) -#define BS_CANB_DISPENSER (1<<3) -#define BS_CANB_SENTRYGUN (1<<4) -/*==================================================*/ -/* Ammo quantities for dropping & dispenser use */ -/*==================================================*/ -#define DROP_SHELLS 20 -#define DROP_NAILS 20 -#define DROP_ROCKETS 10 -#define DROP_CELLS 10 -#define DROP_ARMOR 40 - -/*==================================================*/ -/* Team Defines */ -/*==================================================*/ -#define TM_MAX_NO 4 // Max number of teams. Simply changing this value isn't enough. - // A new global to hold new team colors is needed, and more flags - // in the spawnpoint spawnflags may need to be used. - // Basically, don't change this unless you know what you're doing :) - -/*==================================================*/ -/* New Weapon Defines */ -/*==================================================*/ -#define WEAP_HOOK 1 -#define WEAP_BIOWEAPON 2 -#define WEAP_MEDIKIT 4 -#define WEAP_SPANNER 8 -#define WEAP_AXE 16 -#define WEAP_SNIPER_RIFLE 32 -#define WEAP_AUTO_RIFLE 64 -#define WEAP_SHOTGUN 128 -#define WEAP_SUPER_SHOTGUN 256 -#define WEAP_NAILGUN 512 -#define WEAP_SUPER_NAILGUN 1024 -#define WEAP_GRENADE_LAUNCHER 2048 -#define WEAP_FLAMETHROWER 4096 -#define WEAP_ROCKET_LAUNCHER 8192 -#define WEAP_INCENDIARY 16384 -#define WEAP_ASSAULT_CANNON 32768 -#define WEAP_LIGHTNING 65536 -#define WEAP_DETPACK 131072 -#define WEAP_TRANQ 262144 -#define WEAP_LASER 524288 -// still room for 12 more weapons -// but we can remove some by giving the weapons -// a weapon mode (like the rifle) - -// HL-compatible weapon numbers -#define WEAPON_HOOK 1 -#define WEAPON_BIOWEAPON (WEAPON_HOOK+1) -#define WEAPON_MEDIKIT (WEAPON_HOOK+2) -#define WEAPON_SPANNER (WEAPON_HOOK+3) -#define WEAPON_AXE (WEAPON_HOOK+4) -#define WEAPON_SNIPER_RIFLE (WEAPON_HOOK+5) -#define WEAPON_AUTO_RIFLE (WEAPON_HOOK+6) -#define WEAPON_TF_SHOTGUN (WEAPON_HOOK+7) -#define WEAPON_SUPER_SHOTGUN (WEAPON_HOOK+8) -#define WEAPON_NAILGUN (WEAPON_HOOK+9) -#define WEAPON_SUPER_NAILGUN (WEAPON_HOOK+10) -#define WEAPON_GRENADE_LAUNCHER (WEAPON_HOOK+11) -#define WEAPON_FLAMETHROWER (WEAPON_HOOK+12) -#define WEAPON_ROCKET_LAUNCHER (WEAPON_HOOK+13) -#define WEAPON_INCENDIARY (WEAPON_HOOK+14) -#define WEAPON_ASSAULT_CANNON (WEAPON_HOOK+16) -#define WEAPON_LIGHTNING (WEAPON_HOOK+17) -#define WEAPON_DETPACK (WEAPON_HOOK+18) -#define WEAPON_TRANQ (WEAPON_HOOK+19) -#define WEAPON_LASER (WEAPON_HOOK+20) -#define WEAPON_PIPEBOMB_LAUNCHER (WEAPON_HOOK+21) -#define WEAPON_KNIFE (WEAPON_HOOK+22) -#define WEAPON_BENCHMARK (WEAPON_HOOK+23) - -/*==================================================*/ -/* New Weapon Related Defines */ -/*==================================================*/ -// shots per reload -#define RE_SHOTGUN 8 -#define RE_SUPER_SHOTGUN 16 // 8 shots -#define RE_GRENADE_LAUNCHER 6 -#define RE_ROCKET_LAUNCHER 4 - -// reload times -#define RE_SHOTGUN_TIME 2 -#define RE_SUPER_SHOTGUN_TIME 3 -#define RE_GRENADE_LAUNCHER_TIME 4 -#define RE_ROCKET_LAUNCHER_TIME 5 - -// Maximum velocity you can move and fire the Sniper Rifle -#define WEAP_SNIPER_RIFLE_MAX_MOVE 50 - -// Medikit -#define WEAP_MEDIKIT_HEAL 200 // Amount medikit heals per hit -#define WEAP_MEDIKIT_OVERHEAL 50 // Amount of superhealth over max_health the medikit will dispense - -// Spanner -#define WEAP_SPANNER_REPAIR 10 - -// Detpack -#define WEAP_DETPACK_DISARMTIME 3 // Time it takes to disarm a Detpack -#define WEAP_DETPACK_SETTIME 3 // Time it takes to set a Detpack -#define WEAP_DETPACK_SIZE 700 // Explosion Size -#define WEAP_DETPACK_GOAL_SIZE 1500 // Explosion Size for goal triggering -#define WEAP_DETPACK_BITS_NO 12 // Bits that detpack explodes into - -// Tranquiliser Gun -#define TRANQ_TIME 15 - -// Grenades -#define GR_PRIMETIME 3 -#define GR_CALTROP_PRIME 0.5 -#define GR_TYPE_NONE 0 -#define GR_TYPE_NORMAL 1 -#define GR_TYPE_CONCUSSION 2 -#define GR_TYPE_NAIL 3 -#define GR_TYPE_MIRV 4 -#define GR_TYPE_NAPALM 5 -//#define GR_TYPE_FLARE 6 -#define GR_TYPE_GAS 7 -#define GR_TYPE_EMP 8 -#define GR_TYPE_CALTROP 9 -//#define GR_TYPE_FLASH 10 - -// Defines for WeaponMode -#define GL_NORMAL 0 -#define GL_PIPEBOMB 1 - -// Defines for OLD Concussion Grenade -#define GR_OLD_CONCUSS_TIME 5 -#define GR_OLD_CONCUSS_DEC 20 - -// Defines for Concussion Grenade -#define GR_CONCUSS_TIME 0.25 -#define GR_CONCUSS_DEC 10 -#define MEDIUM_PING 150 -#define HIGH_PING 200 - -// Defines for the Gas Grenade -#define GR_HALLU_TIME 0.3 -#define GR_OLD_HALLU_TIME 0.5 -#define GR_HALLU_DEC 2.5 - -// Defines for the BioInfection -#define BIO_JUMP_RADIUS 128 // The distance the bioinfection can jump between players - -/*==================================================*/ -/* New Items */ -/*==================================================*/ -#define NIT_SCANNER 1 - -#define NIT_SILVER_DOOR_OPENED #IT_KEY1 // 131072 -#define NIT_GOLD_DOOR_OPENED #IT_KEY2 // 262144 - -/*==================================================*/ -/* New Item Flags */ -/*==================================================*/ -#define NIT_SCANNER_ENEMY 1 // Detect enemies -#define NIT_SCANNER_FRIENDLY 2 // Detect friendlies (team members) -#define NIT_SCANNER_SOUND 4 // Motion detection. Only report moving entities. - -/*==================================================*/ -/* New Item Related Defines */ -/*==================================================*/ -#define NIT_SCANNER_POWER 25 // The amount of power spent on a scan with the scanner - // is multiplied by this to get the scanrange. -#define NIT_SCANNER_MAXCELL 50 // The maximum number of cells than can be used in one scan -#define NIT_SCANNER_MIN_MOVEMENT 50 // The minimum velocity an entity must have to be detected - // by scanners that only detect movement - -/*==================================================*/ -/* Variables used for New Weapons and Reloading */ -/*==================================================*/ -// Armor Classes : Bitfields. Use the "armorclass" of armor for the Armor Type. -#define AT_SAVESHOT 1 // Kevlar : Reduces bullet damage by 15% -#define AT_SAVENAIL 2 // Wood :) : Reduces nail damage by 15% -#define AT_SAVEEXPLOSION 4 // Blast : Reduces explosion damage by 15% -#define AT_SAVEELECTRICITY 8 // Shock : Reduces electricity damage by 15% -#define AT_SAVEFIRE 16 // Asbestos : Reduces fire damage by 15% - -/*==========================================================================*/ -/* TEAMFORTRESS CLASS DETAILS */ -/*==========================================================================*/ -// Class Details for SCOUT -#define PC_SCOUT_SKIN 4 // Skin for this class when Classkin is on. -#define PC_SCOUT_MAXHEALTH 75 // Maximum Health Level -#define PC_SCOUT_MAXSPEED 400 // Maximum movement speed -#define PC_SCOUT_MAXSTRAFESPEED 400 // Maximum strafing movement speed -#define PC_SCOUT_MAXARMOR 50 // Maximum Armor Level, of any armor class -#define PC_SCOUT_INITARMOR 25 // Armor level when respawned -#define PC_SCOUT_MAXARMORTYPE 0.3 // Maximum level of Armor absorption -#define PC_SCOUT_INITARMORTYPE 0.3 // Absorption Level of armor when respawned -#define PC_SCOUT_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL <-Armor Classes allowed for this class -#define PC_SCOUT_INITARMORCLASS 0 // Armorclass worn when respawned -#define PC_SCOUT_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_NAILGUN -#define PC_SCOUT_MAXAMMO_SHOT 50 // Maximum amount of shot ammo this class can carry -#define PC_SCOUT_MAXAMMO_NAIL 200 // Maximum amount of nail ammo this class can carry -#define PC_SCOUT_MAXAMMO_CELL 100 // Maximum amount of cell ammo this class can carry -#define PC_SCOUT_MAXAMMO_ROCKET 25 // Maximum amount of rocket ammo this class can carry -#define PC_SCOUT_INITAMMO_SHOT 25 // Amount of shot ammo this class has when respawned -#define PC_SCOUT_INITAMMO_NAIL 100 // Amount of nail ammo this class has when respawned -#define PC_SCOUT_INITAMMO_CELL 50 // Amount of cell ammo this class has when respawned -#define PC_SCOUT_INITAMMO_ROCKET 0 // Amount of rocket ammo this class has when respawned -#define PC_SCOUT_GRENADE_TYPE_1 GR_TYPE_CALTROP // <- 1st Type of Grenade this class has -#define PC_SCOUT_GRENADE_TYPE_2 GR_TYPE_CONCUSSION // <- 2nd Type of Grenade this class has -#define PC_SCOUT_GRENADE_INIT_1 2 // Number of grenades of Type 1 this class has when respawned -#define PC_SCOUT_GRENADE_INIT_2 3 // Number of grenades of Type 2 this class has when respawned -#define PC_SCOUT_TF_ITEMS NIT_SCANNER // <- TeamFortress Items this class has - -#define PC_SCOUT_MOTION_MIN_I 0.5 // < Short range -#define PC_SCOUT_MOTION_MIN_MOVE 50 // Minimum vlen of player velocity to be picked up by motion detector -#define PC_SCOUT_SCAN_TIME 2 // # of seconds between each scan pulse -#define PC_SCOUT_SCAN_RANGE 100 // Default scanner range -#define PC_SCOUT_SCAN_COST 2 // Default scanner cell useage per scan - -// Class Details for SNIPER -#define PC_SNIPER_SKIN 5 -#define PC_SNIPER_MAXHEALTH 90 -#define PC_SNIPER_MAXSPEED 300 -#define PC_SNIPER_MAXSTRAFESPEED 300 -#define PC_SNIPER_MAXARMOR 50 -#define PC_SNIPER_INITARMOR 0 -#define PC_SNIPER_MAXARMORTYPE 0.3 -#define PC_SNIPER_INITARMORTYPE 0.3 -#define PC_SNIPER_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL -#define PC_SNIPER_INITARMORCLASS 0 -#define PC_SNIPER_WEAPONS WEAP_SNIPER_RIFLE | WEAP_AUTO_RIFLE | WEAP_AXE | WEAP_NAILGUN -#define PC_SNIPER_MAXAMMO_SHOT 75 -#define PC_SNIPER_MAXAMMO_NAIL 100 -#define PC_SNIPER_MAXAMMO_CELL 50 -#define PC_SNIPER_MAXAMMO_ROCKET 25 -#define PC_SNIPER_INITAMMO_SHOT 60 -#define PC_SNIPER_INITAMMO_NAIL 50 -#define PC_SNIPER_INITAMMO_CELL 0 -#define PC_SNIPER_INITAMMO_ROCKET 0 -#define PC_SNIPER_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_SNIPER_GRENADE_TYPE_2 GR_TYPE_NONE -#define PC_SNIPER_GRENADE_INIT_1 2 -#define PC_SNIPER_GRENADE_INIT_2 0 -#define PC_SNIPER_TF_ITEMS 0 - -// Class Details for SOLDIER -#define PC_SOLDIER_SKIN 6 -#define PC_SOLDIER_MAXHEALTH 100 -#define PC_SOLDIER_MAXSPEED 240 -#define PC_SOLDIER_MAXSTRAFESPEED 240 -#define PC_SOLDIER_MAXARMOR 200 -#define PC_SOLDIER_INITARMOR 100 -#define PC_SOLDIER_MAXARMORTYPE 0.8 -#define PC_SOLDIER_INITARMORTYPE 0.8 -#define PC_SOLDIER_ARMORCLASSES 31 // ALL -#define PC_SOLDIER_INITARMORCLASS 0 -#define PC_SOLDIER_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_ROCKET_LAUNCHER -#define PC_SOLDIER_MAXAMMO_SHOT 100 -#define PC_SOLDIER_MAXAMMO_NAIL 100 -#define PC_SOLDIER_MAXAMMO_CELL 50 -#define PC_SOLDIER_MAXAMMO_ROCKET 50 -#define PC_SOLDIER_INITAMMO_SHOT 50 -#define PC_SOLDIER_INITAMMO_NAIL 0 -#define PC_SOLDIER_INITAMMO_CELL 0 -#define PC_SOLDIER_INITAMMO_ROCKET 10 -#define PC_SOLDIER_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_SOLDIER_GRENADE_TYPE_2 GR_TYPE_NAIL -#define PC_SOLDIER_GRENADE_INIT_1 2 -#define PC_SOLDIER_GRENADE_INIT_2 1 -#define PC_SOLDIER_TF_ITEMS 0 - -#define MAX_NAIL_GRENS 2 // Can only have 2 Nail grens active -#define MAX_NAPALM_GRENS 2 // Can only have 2 Napalm grens active -#define MAX_GAS_GRENS 2 // Can only have 2 Gas grenades active -#define MAX_MIRV_GRENS 2 // Can only have 2 Mirv's -#define MAX_CONCUSSION_GRENS 3 -#define MAX_CALTROP_CANS 3 - -// Class Details for DEMOLITION MAN -#define PC_DEMOMAN_SKIN 1 -#define PC_DEMOMAN_MAXHEALTH 90 -#define PC_DEMOMAN_MAXSPEED 280 -#define PC_DEMOMAN_MAXSTRAFESPEED 280 -#define PC_DEMOMAN_MAXARMOR 120 -#define PC_DEMOMAN_INITARMOR 50 -#define PC_DEMOMAN_MAXARMORTYPE 0.6 -#define PC_DEMOMAN_INITARMORTYPE 0.6 -#define PC_DEMOMAN_ARMORCLASSES 31 // ALL -#define PC_DEMOMAN_INITARMORCLASS 0 -#define PC_DEMOMAN_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_GRENADE_LAUNCHER | WEAP_DETPACK -#define PC_DEMOMAN_MAXAMMO_SHOT 75 -#define PC_DEMOMAN_MAXAMMO_NAIL 50 -#define PC_DEMOMAN_MAXAMMO_CELL 50 -#define PC_DEMOMAN_MAXAMMO_ROCKET 50 -#define PC_DEMOMAN_MAXAMMO_DETPACK 1 -#define PC_DEMOMAN_INITAMMO_SHOT 30 -#define PC_DEMOMAN_INITAMMO_NAIL 0 -#define PC_DEMOMAN_INITAMMO_CELL 0 -#define PC_DEMOMAN_INITAMMO_ROCKET 20 -#define PC_DEMOMAN_INITAMMO_DETPACK 1 -#define PC_DEMOMAN_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_DEMOMAN_GRENADE_TYPE_2 GR_TYPE_MIRV -#define PC_DEMOMAN_GRENADE_INIT_1 2 -#define PC_DEMOMAN_GRENADE_INIT_2 2 -#define PC_DEMOMAN_TF_ITEMS 0 - -// Class Details for COMBAT MEDIC -#define PC_MEDIC_SKIN 3 -#define PC_MEDIC_MAXHEALTH 90 -#define PC_MEDIC_MAXSPEED 320 -#define PC_MEDIC_MAXSTRAFESPEED 320 -#define PC_MEDIC_MAXARMOR 100 -#define PC_MEDIC_INITARMOR 50 -#define PC_MEDIC_MAXARMORTYPE 0.6 -#define PC_MEDIC_INITARMORTYPE 0.3 -#define PC_MEDIC_ARMORCLASSES 11 // ALL except EXPLOSION -#define PC_MEDIC_INITARMORCLASS 0 -#define PC_MEDIC_WEAPONS WEAP_BIOWEAPON | WEAP_MEDIKIT | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_SUPER_NAILGUN -#define PC_MEDIC_MAXAMMO_SHOT 75 -#define PC_MEDIC_MAXAMMO_NAIL 150 -#define PC_MEDIC_MAXAMMO_CELL 50 -#define PC_MEDIC_MAXAMMO_ROCKET 25 -#define PC_MEDIC_MAXAMMO_MEDIKIT 100 -#define PC_MEDIC_INITAMMO_SHOT 50 -#define PC_MEDIC_INITAMMO_NAIL 50 -#define PC_MEDIC_INITAMMO_CELL 0 -#define PC_MEDIC_INITAMMO_ROCKET 0 -#define PC_MEDIC_INITAMMO_MEDIKIT 50 -#define PC_MEDIC_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_MEDIC_GRENADE_TYPE_2 GR_TYPE_CONCUSSION -#define PC_MEDIC_GRENADE_INIT_1 2 -#define PC_MEDIC_GRENADE_INIT_2 2 -#define PC_MEDIC_TF_ITEMS 0 -#define PC_MEDIC_REGEN_TIME 3 // Number of seconds between each regen. -#define PC_MEDIC_REGEN_AMOUNT 2 // Amount of health regenerated each regen. - -// Class Details for HVYWEAP -#define PC_HVYWEAP_SKIN 2 -#define PC_HVYWEAP_MAXHEALTH 100 -#define PC_HVYWEAP_MAXSPEED 230 -#define PC_HVYWEAP_MAXSTRAFESPEED 230 -#define PC_HVYWEAP_MAXARMOR 300 -#define PC_HVYWEAP_INITARMOR 150 -#define PC_HVYWEAP_MAXARMORTYPE 0.8 -#define PC_HVYWEAP_INITARMORTYPE 0.8 -#define PC_HVYWEAP_ARMORCLASSES 31 // ALL -#define PC_HVYWEAP_INITARMORCLASS 0 -#define PC_HVYWEAP_WEAPONS WEAP_ASSAULT_CANNON | WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN -#define PC_HVYWEAP_MAXAMMO_SHOT 200 -#define PC_HVYWEAP_MAXAMMO_NAIL 200 -#define PC_HVYWEAP_MAXAMMO_CELL 50 -#define PC_HVYWEAP_MAXAMMO_ROCKET 25 -#define PC_HVYWEAP_INITAMMO_SHOT 200 -#define PC_HVYWEAP_INITAMMO_NAIL 0 -#define PC_HVYWEAP_INITAMMO_CELL 30 -#define PC_HVYWEAP_INITAMMO_ROCKET 0 -#define PC_HVYWEAP_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_HVYWEAP_GRENADE_TYPE_2 GR_TYPE_MIRV -#define PC_HVYWEAP_GRENADE_INIT_1 2 -#define PC_HVYWEAP_GRENADE_INIT_2 1 -#define PC_HVYWEAP_TF_ITEMS 0 -#define PC_HVYWEAP_CELL_USAGE 7 // Amount of cells spent to power up assault cannon - - - -// Class Details for PYRO -#define PC_PYRO_SKIN 21 -#define PC_PYRO_MAXHEALTH 100 -#define PC_PYRO_MAXSPEED 300 -#define PC_PYRO_MAXSTRAFESPEED 300 -#define PC_PYRO_MAXARMOR 150 -#define PC_PYRO_INITARMOR 50 -#define PC_PYRO_MAXARMORTYPE 0.6 -#define PC_PYRO_INITARMORTYPE 0.6 -#define PC_PYRO_ARMORCLASSES 27 // ALL except EXPLOSION -#define PC_PYRO_INITARMORCLASS 16 // #AT_SAVEFIRE -#define PC_PYRO_WEAPONS WEAP_INCENDIARY | WEAP_FLAMETHROWER | WEAP_AXE | WEAP_SHOTGUN -#define PC_PYRO_MAXAMMO_SHOT 40 -#define PC_PYRO_MAXAMMO_NAIL 50 -#define PC_PYRO_MAXAMMO_CELL 200 -#define PC_PYRO_MAXAMMO_ROCKET 20 -#define PC_PYRO_INITAMMO_SHOT 20 -#define PC_PYRO_INITAMMO_NAIL 0 -#define PC_PYRO_INITAMMO_CELL 120 -#define PC_PYRO_INITAMMO_ROCKET 5 -#define PC_PYRO_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_PYRO_GRENADE_TYPE_2 GR_TYPE_NAPALM -#define PC_PYRO_GRENADE_INIT_1 2 -#define PC_PYRO_GRENADE_INIT_2 4 -#define PC_PYRO_TF_ITEMS 0 -#define PC_PYRO_ROCKET_USAGE 3 // Number of rockets per incendiary cannon shot - -// Class Details for SPY -#define PC_SPY_SKIN 22 -#define PC_SPY_MAXHEALTH 90 -#define PC_SPY_MAXSPEED 300 -#define PC_SPY_MAXSTRAFESPEED 300 -#define PC_SPY_MAXARMOR 100 -#define PC_SPY_INITARMOR 25 -#define PC_SPY_MAXARMORTYPE 0.6 // Was 0.3 -#define PC_SPY_INITARMORTYPE 0.6 // Was 0.3 -#define PC_SPY_ARMORCLASSES 27 // ALL except EXPLOSION -#define PC_SPY_INITARMORCLASS 0 -#define PC_SPY_WEAPONS WEAP_AXE | WEAP_TRANQ | WEAP_SUPER_SHOTGUN | WEAP_NAILGUN -#define PC_SPY_MAXAMMO_SHOT 40 -#define PC_SPY_MAXAMMO_NAIL 100 -#define PC_SPY_MAXAMMO_CELL 30 -#define PC_SPY_MAXAMMO_ROCKET 15 -#define PC_SPY_INITAMMO_SHOT 40 -#define PC_SPY_INITAMMO_NAIL 50 -#define PC_SPY_INITAMMO_CELL 10 -#define PC_SPY_INITAMMO_ROCKET 0 -#define PC_SPY_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_SPY_GRENADE_TYPE_2 GR_TYPE_GAS -#define PC_SPY_GRENADE_INIT_1 2 -#define PC_SPY_GRENADE_INIT_2 2 -#define PC_SPY_TF_ITEMS 0 -#define PC_SPY_CELL_REGEN_TIME 5 -#define PC_SPY_CELL_REGEN_AMOUNT 1 -#define PC_SPY_CELL_USAGE 3 // Amount of cells spent while invisible -#define PC_SPY_GO_UNDERCOVER_TIME 4 // Time it takes to go undercover - -// Class Details for ENGINEER -#define PC_ENGINEER_SKIN 22 // Not used anymore -#define PC_ENGINEER_MAXHEALTH 80 -#define PC_ENGINEER_MAXSPEED 300 -#define PC_ENGINEER_MAXSTRAFESPEED 300 -#define PC_ENGINEER_MAXARMOR 50 -#define PC_ENGINEER_INITARMOR 25 -#define PC_ENGINEER_MAXARMORTYPE 0.6 -#define PC_ENGINEER_INITARMORTYPE 0.3 -#define PC_ENGINEER_ARMORCLASSES 31 // ALL -#define PC_ENGINEER_INITARMORCLASS 0 -#define PC_ENGINEER_WEAPONS WEAP_SPANNER | WEAP_LASER | WEAP_SUPER_SHOTGUN -#define PC_ENGINEER_MAXAMMO_SHOT 50 -#define PC_ENGINEER_MAXAMMO_NAIL 50 -#define PC_ENGINEER_MAXAMMO_CELL 200 // synonymous with metal -#define PC_ENGINEER_MAXAMMO_ROCKET 30 -#define PC_ENGINEER_INITAMMO_SHOT 20 -#define PC_ENGINEER_INITAMMO_NAIL 25 -#define PC_ENGINEER_INITAMMO_CELL 100 // synonymous with metal -#define PC_ENGINEER_INITAMMO_ROCKET 0 -#define PC_ENGINEER_GRENADE_TYPE_1 GR_TYPE_NORMAL -#define PC_ENGINEER_GRENADE_TYPE_2 GR_TYPE_EMP -#define PC_ENGINEER_GRENADE_INIT_1 2 -#define PC_ENGINEER_GRENADE_INIT_2 2 -#define PC_ENGINEER_TF_ITEMS 0 - -// Class Details for CIVILIAN -#define PC_CIVILIAN_SKIN 22 -#define PC_CIVILIAN_MAXHEALTH 50 -#define PC_CIVILIAN_MAXSPEED 240 -#define PC_CIVILIAN_MAXSTRAFESPEED 240 -#define PC_CIVILIAN_MAXARMOR 0 -#define PC_CIVILIAN_INITARMOR 0 -#define PC_CIVILIAN_MAXARMORTYPE 0 -#define PC_CIVILIAN_INITARMORTYPE 0 -#define PC_CIVILIAN_ARMORCLASSES 0 -#define PC_CIVILIAN_INITARMORCLASS 0 -#define PC_CIVILIAN_WEAPONS WEAP_AXE -#define PC_CIVILIAN_MAXAMMO_SHOT 0 -#define PC_CIVILIAN_MAXAMMO_NAIL 0 -#define PC_CIVILIAN_MAXAMMO_CELL 0 -#define PC_CIVILIAN_MAXAMMO_ROCKET 0 -#define PC_CIVILIAN_INITAMMO_SHOT 0 -#define PC_CIVILIAN_INITAMMO_NAIL 0 -#define PC_CIVILIAN_INITAMMO_CELL 0 -#define PC_CIVILIAN_INITAMMO_ROCKET 0 -#define PC_CIVILIAN_GRENADE_TYPE_1 0 -#define PC_CIVILIAN_GRENADE_TYPE_2 0 -#define PC_CIVILIAN_GRENADE_INIT_1 0 -#define PC_CIVILIAN_GRENADE_INIT_2 0 -#define PC_CIVILIAN_TF_ITEMS 0 - - -/*==========================================================================*/ -/* TEAMFORTRESS GOALS */ -/*==========================================================================*/ -// For all these defines, see the tfortmap.txt that came with the zip -// for complete descriptions. -// Defines for Goal Activation types : goal_activation (in goals) -#define TFGA_TOUCH 1 // Activated when touched -#define TFGA_TOUCH_DETPACK 2 // Activated when touched by a detpack explosion -#define TFGA_REVERSE_AP 4 // Activated when AP details are _not_ met -#define TFGA_SPANNER 8 // Activated when hit by an engineer's spanner -#define TFGA_DROPTOGROUND 2048 // Drop to Ground when spawning - -// Defines for Goal Effects types : goal_effect -#define TFGE_AP 1 // AP is affected. Default. -#define TFGE_AP_TEAM 2 // All of the AP's team. -#define TFGE_NOT_AP_TEAM 4 // All except AP's team. -#define TFGE_NOT_AP 8 // All except AP. -#define TFGE_WALL 16 // If set, walls stop the Radius effects -#define TFGE_SAME_ENVIRONMENT 32 // If set, players in a different environment to the Goal are not affected -#define TFGE_TIMER_CHECK_AP 64 // If set, Timer Goals check their critera for all players fitting their effects - -// Defines for Goal Result types : goal_result -#define TFGR_SINGLE 1 // Goal can only be activated once -#define TFGR_ADD_BONUSES 2 // Any Goals activated by this one give their bonuses -#define TFGR_ENDGAME 4 // Goal fires Intermission, displays scores, and ends level -#define TFGR_NO_ITEM_RESULTS 8 // GoalItems given by this Goal don't do results -#define TFGR_REMOVE_DISGUISE 16 // Prevent/Remove undercover from any Spy -#define TFGR_FORCE_RESPAWN 32 // Forces the player to teleport to a respawn point -#define TFGR_DESTROY_BUILDINGS 64 // Destroys this player's buildings, if anys - -// Defines for Goal Group Result types : goal_group -// None! -// But I'm leaving this variable in there, since it's fairly likely -// that some will show up sometime. - -// Defines for Goal Item types, : goal_activation (in items) -#define TFGI_GLOW 1 // Players carrying this GoalItem will glow -#define TFGI_SLOW 2 // Players carrying this GoalItem will move at half-speed -#define TFGI_DROP 4 // Players dying with this item will drop it -#define TFGI_RETURN_DROP 8 // Return if a player with it dies -#define TFGI_RETURN_GOAL 16 // Return if a player with it has it removed by a goal's activation -#define TFGI_RETURN_REMOVE 32 // Return if it is removed by TFGI_REMOVE -#define TFGI_REVERSE_AP 64 // Only pickup if the player _doesn't_ match AP Details -#define TFGI_REMOVE 128 // Remove if left untouched for 2 minutes after being dropped -#define TFGI_KEEP 256 // Players keep this item even when they die -#define TFGI_ITEMGLOWS 512 // Item glows when on the ground -#define TFGI_DONTREMOVERES 1024 // Don't remove results when the item is removed -#define TFGI_DROPTOGROUND 2048 // Drop To Ground when spawning -#define TFGI_CANBEDROPPED 4096 // Can be voluntarily dropped by players -#define TFGI_SOLID 8192 // Is solid... blocks bullets, etc - -// Defines for methods of GoalItem returning -#define GI_RET_DROP_DEAD 0 // Dropped by a dead player -#define GI_RET_DROP_LIVING 1 // Dropped by a living player -#define GI_RET_GOAL 2 // Returned by a Goal -#define GI_RET_TIME 3 // Returned due to timeout - -// Defines for TeamSpawnpoints : goal_activation (in teamspawns) -#define TFSP_MULTIPLEITEMS 1 // Give out the GoalItem multiple times -#define TFSP_MULTIPLEMSGS 2 // Display the message multiple times - -// Defines for TeamSpawnpoints : goal_effects (in teamspawns) -#define TFSP_REMOVESELF 1 // Remove itself after being spawned on - -// Defines for Goal States -#define TFGS_ACTIVE 1 -#define TFGS_INACTIVE 2 -#define TFGS_REMOVED 3 -#define TFGS_DELAYED 4 - -// Defines for GoalItem Removing from Player Methods -#define GI_DROP_PLAYERDEATH 0 // Dropped by a dying player -#define GI_DROP_REMOVEGOAL 1 // Removed by a Goal -#define GI_DROP_PLAYERDROP 2 // Dropped by a player - -// Legal Playerclass Handling -#define TF_ILL_SCOUT 1 -#define TF_ILL_SNIPER 2 -#define TF_ILL_SOLDIER 4 -#define TF_ILL_DEMOMAN 8 -#define TF_ILL_MEDIC 16 -#define TF_ILL_HVYWEP 32 -#define TF_ILL_PYRO 64 -#define TF_ILL_RANDOMPC 128 -#define TF_ILL_SPY 256 -#define TF_ILL_ENGINEER 512 - -// Addition classes -#define CLASS_TFGOAL 128 -#define CLASS_TFGOAL_TIMER 129 -#define CLASS_TFGOAL_ITEM 130 -#define CLASS_TFSPAWN 131 - -/*==========================================================================*/ -/* Flamethrower */ -/*==========================================================================*/ -#define FLAME_PLYRMAXTIME 5.0 // lifetime in seconds of a flame on a player -#define FLAME_MAXBURNTIME 8 // lifetime in seconds of a flame on the world (big ones) -#define NAPALM_MAXBURNTIME 20 // lifetime in seconds of flame from a napalm grenade -#define FLAME_MAXPLYRFLAMES 4 // maximum number of flames on a player -#define FLAME_NUMLIGHTS 1 // maximum number of light flame -#define FLAME_BURNRATIO 0.3 // the chance of a flame not 'sticking' -#define GR_TYPE_FLAMES_NO 15 // number of flames spawned when a grenade explode -#define FLAME_DAMAGE_TIME 1 // Interval between damage burns from flames -#define FLAME_EFFECT_TIME 0.2 // frequency at which we display flame effects. -#define FLAME_THINK_TIME 0.1 // Seconds between times the flame checks burn -#define PER_FLAME_DAMAGE 2 // Damage taken per second per flame by burning players - -/*==================================================*/ -/* CTF Support defines */ -/*==================================================*/ -#define CTF_FLAG1 1 -#define CTF_FLAG2 2 -#define CTF_DROPOFF1 3 -#define CTF_DROPOFF2 4 -#define CTF_SCORE1 5 -#define CTF_SCORE2 6 - -//.float hook_out; - -/*==================================================*/ -/* Camera defines */ -/*==================================================*/ -/* -float live_camera; -.float camdist; -.vector camangle; -.entity camera_list; -*/ - -/*==================================================*/ -/* QuakeWorld defines */ -/*==================================================*/ -/* -float already_chosen_map; - -// grappling hook variables -.entity hook; -.float on_hook; -.float fire_held_down;// flag - TRUE if player is still holding down the - // fire button after throwing a hook. -*/ -/*==================================================*/ -/* Server Settings */ -/*==================================================*/ -// Admin modes -#define ADMIN_MODE_NONE 0 -#define ADMIN_MODE_DEAL 1 - -/*==================================================*/ -/* Death Message defines */ -/*==================================================*/ -#define DMSG_SHOTGUN 1 -#define DMSG_SSHOTGUN 2 -#define DMSG_NAILGUN 3 -#define DMSG_SNAILGUN 4 -#define DMSG_GRENADEL 5 -#define DMSG_ROCKETL 6 -#define DMSG_LIGHTNING 7 -#define DMSG_GREN_HAND 8 -#define DMSG_GREN_NAIL 9 -#define DMSG_GREN_MIRV 10 -#define DMSG_GREN_PIPE 11 -#define DMSG_DETPACK 12 -#define DMSG_BIOWEAPON 13 -#define DMSG_BIOWEAPON_ATT 14 -#define DMSG_FLAME 15 -#define DMSG_DETPACK_DIS 16 -#define DMSG_AXE 17 -#define DMSG_SNIPERRIFLE 18 -#define DMSG_AUTORIFLE 19 -#define DMSG_ASSAULTCANNON 20 -#define DMSG_HOOK 21 -#define DMSG_BACKSTAB 22 -#define DMSG_MEDIKIT 23 -#define DMSG_GREN_GAS 24 -#define DMSG_TRANQ 25 -#define DMSG_LASERBOLT 26 -#define DMSG_SENTRYGUN_BULLET 27 -#define DMSG_SNIPERLEGSHOT 28 -#define DMSG_SNIPERHEADSHOT 29 -#define DMSG_GREN_EMP 30 -#define DMSG_GREN_EMP_AMMO 31 -#define DMSG_SPANNER 32 -#define DMSG_INCENDIARY 33 -#define DMSG_SENTRYGUN_ROCKET 34 -#define DMSG_GREN_FLASH 35 -#define DMSG_TRIGGER 36 -#define DMSG_MIRROR 37 -#define DMSG_SENTRYDEATH 38 -#define DMSG_DISPENSERDEATH 39 -#define DMSG_GREN_AIRPIPE 40 -#define DMSG_CALTROP 41 - -/*==================================================*/ -// TOGGLEFLAGS -/*==================================================*/ -// Some of the toggleflags aren't used anymore, but the bits are still -// there to provide compatability with old maps -#define TFLAG_CLASS_PERSIST (1 << 0) // Persistent Classes Bit -#define TFLAG_CHEATCHECK (1 << 1) // Cheatchecking Bit -#define TFLAG_RESPAWNDELAY (1 << 2) // RespawnDelay bit -//#define TFLAG_UN (1 << 3) // NOT USED ANYMORE -#define TFLAG_OLD_GRENS (1 << 3) // Use old concussion grenade and flash grenade -#define TFLAG_UN2 (1 << 4) // NOT USED ANYMORE -#define TFLAG_UN3 (1 << 5) // NOT USED ANYMORE -#define TFLAG_UN4 (1 << 6) // NOT USED ANYMORE: Was Autoteam. CVAR tfc_autoteam used now. -#define TFLAG_TEAMFRAGS (1 << 7) // Individual Frags, or Frags = TeamScore -#define TFLAG_FIRSTENTRY (1 << 8) // Used to determine the first time toggleflags is set - // In a map. Cannot be toggled by players. -#define TFLAG_SPYINVIS (1 << 9) // Spy invisible only -#define TFLAG_GRAPPLE (1 << 10) // Grapple on/off -//#define TFLAG_FULLTEAMSCORE (1 << 11) // Each Team's score is TeamScore + Frags -#define TFLAG_FLAGEMULATION (1 << 12) // Flag emulation on for old TF maps -#define TFLAG_USE_STANDARD (1 << 13) // Use the TF War standard for Flag emulation - -#define TFLAG_FRAGSCORING (1 << 14) // Use frag scoring only - -/*======================*/ -// Menu stuff // -/*======================*/ - -#define MENU_DEFAULT 1 -#define MENU_TEAM 2 -#define MENU_CLASS 3 -#define MENU_MAPBRIEFING 4 -#define MENU_INTRO 5 -#define MENU_CLASSHELP 6 -#define MENU_CLASSHELP2 7 -#define MENU_REPEATHELP 8 - -#define MENU_SPECHELP 9 - - -#define MENU_SPY 12 -#define MENU_SPY_SKIN 13 -#define MENU_SPY_COLOR 14 -#define MENU_ENGINEER 15 -#define MENU_ENGINEER_FIX_DISPENSER 16 -#define MENU_ENGINEER_FIX_SENTRYGUN 17 -#define MENU_ENGINEER_FIX_MORTAR 18 -#define MENU_DISPENSER 19 -#define MENU_CLASS_CHANGE 20 -#define MENU_TEAM_CHANGE 21 - -#define MENU_REFRESH_RATE 25 - -#define MENU_VOICETWEAK 50 - -//============================ -// Timer Types -#define TF_TIMER_ANY 0 -#define TF_TIMER_CONCUSSION 1 -#define TF_TIMER_INFECTION 2 -#define TF_TIMER_HALLUCINATION 3 -#define TF_TIMER_TRANQUILISATION 4 -#define TF_TIMER_ROTHEALTH 5 -#define TF_TIMER_REGENERATION 6 -#define TF_TIMER_GRENPRIME 7 -#define TF_TIMER_CELLREGENERATION 8 -#define TF_TIMER_DETPACKSET 9 -#define TF_TIMER_DETPACKDISARM 10 -#define TF_TIMER_BUILD 11 -#define TF_TIMER_CHECKBUILDDISTANCE 12 -#define TF_TIMER_DISGUISE 13 -#define TF_TIMER_DISPENSERREFILL 14 - -// Non Player timers -#define TF_TIMER_RETURNITEM 100 -#define TF_TIMER_DELAYEDGOAL 101 -#define TF_TIMER_ENDROUND 102 - -//============================ -// Teamscore printing -#define TS_PRINT_SHORT 1 -#define TS_PRINT_LONG 2 -#define TS_PRINT_LONG_TO_ALL 3 - -#ifndef TF_DEFS_ONLY - -typedef struct -{ - int topColor; - int bottomColor; -} team_color_t; - - -/*==================================================*/ -/* GLOBAL VARIABLES */ -/*==================================================*/ -// FortressMap stuff -extern float number_of_teams; // number of teams supported by the map -extern int illegalclasses[5]; // Illegal playerclasses for all teams -extern int civilianteams; // Bitfield holding Civilian teams -extern Vector rgbcolors[5]; // RGB colors for each of the 4 teams - -extern team_color_t teamcolors[5][PC_LASTCLASS]; // Colors for each of the 4 teams - -extern int teamscores[5]; // Goal Score of each team -extern int g_iOrderedTeams[5]; // Teams ordered into order of winners->losers -extern int teamfrags[5]; // Total Frags for each team -extern int teamlives[5]; // Number of lives each team's players have -extern int teammaxplayers[5]; // Max number of players allowed in each team -extern float teamadvantage[5]; // only used if the teamplay equalisation bits are set - // stores the damage ratio players take/give -extern int teamallies[5]; // Keeps track of which teams are allied -extern string_t team_names[5]; - -extern BOOL CTF_Map; -extern BOOL birthday; -extern BOOL christmas; - -extern float num_world_flames; - -// Clan Battle stuff -extern float clan_scores_dumped; -extern float cb_prematch_time; -extern float fOldPrematch; -extern float fOldCeaseFire; -extern float cb_ceasefire_time; -extern float last_id; -extern float spy_off; -extern float old_grens; -extern float flagem_checked; -extern float flNextEqualisationCalc; -extern BOOL cease_fire; -extern BOOL no_cease_fire_text; -extern BOOL initial_cease_fire; -extern BOOL last_cease_fire; -// Autokick stuff -extern float autokick_kills; - -extern float deathmsg; // Global, which is set before every T_Damage, to indicate - // the death message that should be used. - -extern char *sTeamSpawnNames[]; -extern char *sClassNames[]; -extern char *sNewClassModelFiles[]; -extern char *sOldClassModelFiles[]; -extern char *sClassModels[]; -extern char *sClassCfgs[]; -extern char *sGrenadeNames[]; -extern string_t team_menu_string; - -extern int toggleflags; // toggleable flags - -extern CBaseEntity* g_pLastSpawns[5]; -extern BOOL g_bFirstClient; - -extern float g_fNextPrematchAlert; - -typedef struct -{ - int ip; - edict_t *pEdict; -} ip_storage_t; - -extern ip_storage_t g_IpStorage[32]; - -class CGhost; -/*==========================================================================*/ -BOOL ClassIsRestricted(float tno, int pc); -char* GetTeamName(int tno); -int TeamFortress_GetNoPlayers(); -void DestroyBuilding(CBaseEntity *eng, char *bld); -void teamsprint( int tno, CBaseEntity *ignore, int msg_dest, const char *st, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL ); -float anglemod( float v ); - -// Team Funcs -BOOL TeamFortress_TeamIsCivilian(float tno); -void TeamFortress_TeamShowScores(BOOL bLong, CBasePlayer *pPlayer); -BOOL TeamFortress_TeamPutPlayerInTeam(); -void TeamFortress_TeamSetColor(int tno); -void TeamFortress_TeamIncreaseScore(int tno, int scoretoadd); -int TeamFortress_TeamGetScoreFrags(int tno); -int TeamFortress_TeamGetNoPlayers(int tno); -float TeamEqualiseDamage(CBaseEntity *targ, CBaseEntity *attacker, float damage); -BOOL IsSpawnPointValid( Vector &pos ); -BOOL TeamFortress_SortTeams( void ); -void DumpClanScores( void ); -void CalculateTeamEqualiser(); - -// mapscript funcs -void ParseTFServerSettings(); -void ParseTFMapSettings(); -CBaseEntity* Finditem(int ino); -CBaseEntity* Findgoal(int gno); -CBaseEntity* Findteamspawn(int gno); -void RemoveGoal(CBaseEntity *Goal); -void tfgoalitem_GiveToPlayer(CBaseEntity *Item, CBasePlayer *AP, CBaseEntity *Goal); -void dremove( CBaseEntity *te ); -void tfgoalitem_RemoveFromPlayer(CBaseEntity *Item, CBasePlayer *AP, int iMethod); -void tfgoalitem_drop(CBaseEntity *Item, BOOL PAlive, CBasePlayer *P); -void DisplayItemStatus(CBaseEntity *Goal, CBasePlayer *Player, CBaseEntity *Item); -void tfgoalitem_checkgoalreturn(CBaseEntity *Item); -void DoGoalWork(CBaseEntity *Goal, CBasePlayer *AP); -void DoResults(CBaseEntity *Goal, CBasePlayer *AP, BOOL bAddBonuses); -void DoGroupWork(CBaseEntity *Goal, CBasePlayer *AP); -// hooks into the mapscript for all entities -BOOL ActivateDoResults(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal); -BOOL ActivationSucceeded(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal); - -// prematch & ceasefire -void Display_Prematch(); -void Check_Ceasefire(); - -// admin -void KickPlayer( CBaseEntity *pTarget ); -void BanPlayer( CBaseEntity *pTarget ); -CGhost *FindGhost( int iGhostID ); -int GetBattleID( edict_t *pEntity ); - -extern cvar_t tfc_spam_penalty1;// the initial gag penalty for a spammer (seconds) -extern cvar_t tfc_spam_penalty2;// incremental gag penalty (seconds) for each time gagged spammer continues to speak. -extern cvar_t tfc_spam_limit; // at this many points, gag the spammer -extern cvar_t tfc_clanbattle, tfc_clanbattle_prematch, tfc_prematch, tfc_clanbattle_ceasefire, tfc_balance_teams, tfc_balance_scores; -extern cvar_t tfc_clanbattle_locked, tfc_birthday, tfc_autokick_kills, tfc_fragscoring, tfc_autokick_time, tfc_adminpwd; -extern cvar_t weaponstay, footsteps, flashlight, aimcrosshair, falldamage, teamplay; -extern cvar_t allow_spectators; - -/*==========================================================================*/ -class CTFFlame : public CBaseMonster -{ -public: - void Spawn( void ); - void Precache( void ); - void EXPORT FlameThink( void ); - static CTFFlame *FlameSpawn( CBaseEntity *pOwner, CBaseEntity *pTarget ); - void FlameDestroy( void ); - - float m_flNextDamageTime; -}; - -/*==========================================================================*/ -// MAPSCRIPT CLASSES -class CTFGoal : public CBaseAnimating -{ -public: - void Spawn( void ); - void StartGoal( void ); - void EXPORT PlaceGoal( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - int Classify ( void ) { return CLASS_TFGOAL; } - - void SetObjectCollisionBox( void ); -}; - -class CTFGoalItem : public CTFGoal -{ -public: - void Spawn( void ); - void StartItem( void ); - void EXPORT PlaceItem( void ); - int Classify ( void ) { return CLASS_TFGOAL_ITEM; } - - float m_flDroppedAt; -}; - -class CTFTimerGoal : public CTFGoal -{ -public: - void Spawn( void ); - int Classify ( void ) { return CLASS_TFGOAL_TIMER; } -}; - -class CTFSpawn : public CBaseEntity -{ -public: - void Spawn( void ); - void Activate( void ); - int Classify ( void ) { return CLASS_TFSPAWN; } - BOOL CheckTeam( int iTeamNo ); - - EHANDLE m_pTeamCheck; -}; - -class CTFDetect : public CBaseEntity -{ -public: - void Spawn( void ); - int Classify ( void ) { return CLASS_TFGOAL; } -}; - -class CTelefragDeath : public CBaseEntity -{ -public: - void Spawn( void ); - void EXPORT DeathTouch( CBaseEntity *pOther ); -}; - -class CTeamCheck : public CBaseDelay -{ -public: - void Spawn( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - BOOL TeamMatches( int iTeam ); -}; - -class CTeamSet : public CBaseDelay -{ -public: - void Spawn( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); -}; - -#endif // TF_DEFS_ONLY -#endif // __TF_DEFS_H - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +#ifndef __TF_DEFS_H +#define __TF_DEFS_H + +//=========================================================================== +// OLD OPTIONS.QC +//=========================================================================== +#define DEFAULT_AUTOZOOM FALSE +#define WEINER_SNIPER // autoaiming for sniper rifle +#define FLAME_MAXWORLDNUM 20 // maximum number of flames in the world. DO NOT PUT BELOW 20. + +//#define MAX_WORLD_PIPEBOMBS 15 // This is divided between teams - this is the most you should have on a net server +#define MAX_PLAYER_PIPEBOMBS 8 // maximum number of pipebombs any 1 player can have active +#define MAX_PLAYER_AMMOBOXES 3 // maximum number of ammoboxes any 1 player can have active + +//#define MAX_WORLD_FLARES 9 // This is the total number of flares allowed in the world at one time +//#define MAX_WORLD_AMMOBOXES 20 // This is divided between teams - this is the most you should have on a net server +#define GR_TYPE_MIRV_NO 4 // Number of Mirvs a Mirv Grenade breaks into +#define GR_TYPE_NAPALM_NO 8 // Number of flames napalm grenade breaks into (unused if net server) +#define MEDIKIT_IS_BIOWEAPON // Medikit acts as a bioweapon against enemies + +#define TEAM_HELP_RATE 60 // used only if teamplay bit 64 (help team with lower score) is set. + // 60 is a mild setting, and won't make too much difference + // increasing it _decreases_ the amount of help the losing team gets + // Minimum setting is 1, which would really help the losing team + +#define DISPLAY_CLASS_HELP TRUE // Change this to #OFF if you don't want the class help to + // appear whenever a player connects +#define NEVER_TEAMFRAGS FALSE // teamfrags options always off +#define ALWAYS_TEAMFRAGS FALSE // teamfrags options always on +#define CHECK_SPEEDS TRUE // makes sure players aren't moving too fast +#define SNIPER_RIFLE_RELOAD_TIME 1.5 // seconds + +#define MAPBRIEFING_MAXTEXTLENGTH 512 +#define PLAYER_PUSH_VELOCITY 50 // Players push teammates if they're moving under this speed + +// Debug Options +//#define MAP_DEBUG // Debug for Map code. I suggest running in a hi-res + // mode and/or piping the output from the server to a file. +#ifdef MAP_DEBUG + #define MDEBUG(x) x +#else + #define MDEBUG(x) +#endif +//#define VERBOSE // Verbose Debugging on/off + +//=========================================================================== +// OLD QUAKE Defs +//=========================================================================== +// items +#define IT_AXE 4096 +#define IT_SHOTGUN 1 +#define IT_SUPER_SHOTGUN 2 +#define IT_NAILGUN 4 +#define IT_SUPER_NAILGUN 8 +#define IT_GRENADE_LAUNCHER 16 +#define IT_ROCKET_LAUNCHER 32 +#define IT_LIGHTNING 64 +#define IT_EXTRA_WEAPON 128 + +#define IT_SHELLS 256 +#define IT_NAILS 512 +#define IT_ROCKETS 1024 +#define IT_CELLS 2048 + +#define IT_ARMOR1 8192 +#define IT_ARMOR2 16384 +#define IT_ARMOR3 32768 +#define IT_SUPERHEALTH 65536 + +#define IT_KEY1 131072 +#define IT_KEY2 262144 + +#define IT_INVISIBILITY 524288 +#define IT_INVULNERABILITY 1048576 +#define IT_SUIT 2097152 +#define IT_QUAD 4194304 +#define IT_HOOK 8388608 + +#define IT_KEY3 16777216 // Stomp invisibility +#define IT_KEY4 33554432 // Stomp invulnerability + +//=========================================================================== +// TEAMFORTRESS Defs +//=========================================================================== +// TeamFortress State Flags +#define TFSTATE_GRENPRIMED 1 // Whether the player has a primed grenade +#define TFSTATE_RELOADING 2 // Whether the player is reloading +#define TFSTATE_ALTKILL 4 // #TRUE if killed with a weapon not in self.weapon: NOT USED ANYMORE +#define TFSTATE_RANDOMPC 8 // Whether Playerclass is random, new one each respawn +#define TFSTATE_INFECTED 16 // set when player is infected by the bioweapon +#define TFSTATE_INVINCIBLE 32 // Player has permanent Invincibility (Usually by GoalItem) +#define TFSTATE_INVISIBLE 64 // Player has permanent Invisibility (Usually by GoalItem) +#define TFSTATE_QUAD 128 // Player has permanent Quad Damage (Usually by GoalItem) +#define TFSTATE_RADSUIT 256 // Player has permanent Radsuit (Usually by GoalItem) +#define TFSTATE_BURNING 512 // Is on fire +#define TFSTATE_GRENTHROWING 1024 // is throwing a grenade +#define TFSTATE_AIMING 2048 // is using the laser sight +#define TFSTATE_ZOOMOFF 4096 // doesn't want the FOV changed when zooming +#define TFSTATE_RESPAWN_READY 8192 // is waiting for respawn, and has pressed fire +#define TFSTATE_HALLUCINATING 16384 // set when player is hallucinating +#define TFSTATE_TRANQUILISED 32768 // set when player is tranquilised +#define TFSTATE_CANT_MOVE 65536 // set when player is setting a detpack +#define TFSTATE_RESET_FLAMETIME 131072 // set when the player has to have his flames increased in health + +// Defines used by TF_T_Damage (see combat.qc) +#define TF_TD_IGNOREARMOUR 1 // Bypasses the armour of the target +#define TF_TD_NOTTEAM 2 // Doesn't damage a team member (indicates direct fire weapon) +#define TF_TD_NOTSELF 4 // Doesn't damage self + +#define TF_TD_OTHER 0 // Ignore armorclass +#define TF_TD_SHOT 1 // Bullet damage +#define TF_TD_NAIL 2 // Nail damage +#define TF_TD_EXPLOSION 4 // Explosion damage +#define TF_TD_ELECTRICITY 8 // Electric damage +#define TF_TD_FIRE 16 // Fire damage +#define TF_TD_NOSOUND 256 // Special damage. Makes no sound/painframe, etc + +/*==================================================*/ +/* Toggleable Game Settings */ +/*==================================================*/ +#define TF_RESPAWNDELAY1 5 // seconds of waiting before player can respawn +#define TF_RESPAWNDELAY2 10 // seconds of waiting before player can respawn +#define TF_RESPAWNDELAY3 20 // seconds of waiting before player can respawn + +#define TEAMPLAY_NORMAL 1 +#define TEAMPLAY_HALFDIRECT 2 +#define TEAMPLAY_NODIRECT 4 +#define TEAMPLAY_HALFEXPLOSIVE 8 +#define TEAMPLAY_NOEXPLOSIVE 16 +#define TEAMPLAY_LESSPLAYERSHELP 32 +#define TEAMPLAY_LESSSCOREHELP 64 +#define TEAMPLAY_HALFDIRECTARMOR 128 +#define TEAMPLAY_NODIRECTARMOR 256 +#define TEAMPLAY_HALFEXPARMOR 512 +#define TEAMPLAY_NOEXPARMOR 1024 +#define TEAMPLAY_HALFDIRMIRROR 2048 +#define TEAMPLAY_FULLDIRMIRROR 4096 +#define TEAMPLAY_HALFEXPMIRROR 8192 +#define TEAMPLAY_FULLEXPMIRROR 16384 + +#define TEAMPLAY_TEAMDAMAGE (TEAMPLAY_NODIRECT | TEAMPLAY_HALFDIRECT | TEAMPLAY_HALFEXPLOSIVE | TEAMPLAY_NOEXPLOSIVE) +// FortressMap stuff +#define TEAM1_CIVILIANS 1 +#define TEAM2_CIVILIANS 2 +#define TEAM3_CIVILIANS 4 +#define TEAM4_CIVILIANS 8 + +// Defines for the playerclass +#define PC_UNDEFINED 0 + +#define PC_SCOUT 1 +#define PC_SNIPER 2 +#define PC_SOLDIER 3 +#define PC_DEMOMAN 4 +#define PC_MEDIC 5 +#define PC_HVYWEAP 6 +#define PC_PYRO 7 +#define PC_SPY 8 +#define PC_ENGINEER 9 + +// Insert new class definitions here + +// PC_RANDOM _MUST_ be the third last class +#define PC_RANDOM 10 // Random playerclass +#define PC_CIVILIAN 11 // Civilians are a special class. They cannot + // be chosen by players, only enforced by maps +#define PC_LASTCLASS 12 // Use this as the high-boundary for any loops + // through the playerclass. + +#define SENTRY_COLOR 10 // will be in the PC_RANDOM slot for team colors + +// These are just for the scanner +#define SCAN_SENTRY 13 +#define SCAN_GOALITEM 14 + +// Values returned by CheckArea +enum +{ + CAREA_CLEAR, + CAREA_BLOCKED, + CAREA_NOBUILD +}; + +/*==================================================*/ +/* Impulse Defines */ +/*==================================================*/ +// Alias check to see whether they already have the aliases +#define TF_ALIAS_CHECK 13 + +// CTF Support Impulses +#define HOOK_IMP1 22 +#define FLAG_INFO 23 +#define HOOK_IMP2 39 + +// Axe +#define AXE_IMP 40 + +// Camera Impulse +#define TF_CAM_TARGET 50 +#define TF_CAM_ZOOM 51 +#define TF_CAM_ANGLE 52 +#define TF_CAM_VEC 53 +#define TF_CAM_PROJECTILE 54 +#define TF_CAM_PROJECTILE_Z 55 +#define TF_CAM_REVANGLE 56 +#define TF_CAM_OFFSET 57 +#define TF_CAM_DROP 58 +#define TF_CAM_FADETOBLACK 59 +#define TF_CAM_FADEFROMBLACK 60 +#define TF_CAM_FADETOWHITE 61 +#define TF_CAM_FADEFROMWHITE 62 + +// Last Weapon impulse +#define TF_LAST_WEAPON 69 + +// Status Bar Resolution Settings. Same as CTF to maintain ease of use. +#define TF_STATUSBAR_RES_START 71 +#define TF_STATUSBAR_RES_END 81 + +// Clan Messages +#define TF_MESSAGE_1 82 +#define TF_MESSAGE_2 83 +#define TF_MESSAGE_3 84 +#define TF_MESSAGE_4 85 +#define TF_MESSAGE_5 86 + +#define TF_CHANGE_CLASS 99 // Bring up the Class Change menu + +// Added to PC_??? to get impulse to use if this clashes with your +// own impulses, just change this value, not the PC_?? +#define TF_CHANGEPC 100 +// The next few impulses are all the class selections +//PC_SCOUT 101 +//PC_SNIPER 102 +//PC_SOLDIER 103 +//PC_DEMOMAN 104 +//PC_MEDIC 105 +//PC_HVYWEAP 106 +//PC_PYRO 107 +//PC_RANDOM 108 +//PC_CIVILIAN 109 // Cannot be used +//PC_SPY 110 +//PC_ENGINEER 111 + +// Help impulses +#define TF_DISPLAYLOCATION 118 +#define TF_STATUS_QUERY 119 + +#define TF_HELP_MAP 131 + +// Information impulses +#define TF_INVENTORY 135 +#define TF_SHOWTF 136 +#define TF_SHOWLEGALCLASSES 137 + +// Team Impulses +#define TF_TEAM_1 140 // Join Team 1 +#define TF_TEAM_2 141 // Join Team 2 +#define TF_TEAM_3 142 // Join Team 3 +#define TF_TEAM_4 143 // Join Team 4 +#define TF_TEAM_CLASSES 144 // Impulse to display team classes +#define TF_TEAM_SCORES 145 // Impulse to display team scores +#define TF_TEAM_LIST 146 // Impulse to display the players in each team. + +// Grenade Impulses +#define TF_GRENADE_1 150 // Prime grenade type 1 +#define TF_GRENADE_2 151 // Prime grenade type 2 +#define TF_GRENADE_T 152 // Throw primed grenade + +// Impulses for new items +//#define TF_SCAN 159 // Scanner Pre-Impulse +#define TF_AUTO_SCAN 159 // Scanner On/Off +#define TF_SCAN_ENEMY 160 // Impulses to toggle scanning of enemies +#define TF_SCAN_FRIENDLY 161 // Impulses to toggle scanning of friendlies +//#define TF_SCAN_10 162 // Scan using 10 enery (1 cell) +#define TF_SCAN_SOUND 162 // Scanner sounds on/off +#define TF_SCAN_30 163 // Scan using 30 energy (2 cells) +#define TF_SCAN_100 164 // Scan using 100 energy (5 cells) +#define TF_DETPACK_5 165 // Detpack set to 5 seconds +#define TF_DETPACK_20 166 // Detpack set to 20 seconds +#define TF_DETPACK_50 167 // Detpack set to 50 seconds +#define TF_DETPACK 168 // Detpack Pre-Impulse +#define TF_DETPACK_STOP 169 // Impulse to stop setting detpack +#define TF_PB_DETONATE 170 // Detonate Pipebombs + +// Special skill +#define TF_SPECIAL_SKILL 171 + +// Ammo Drop impulse +#define TF_DROP_AMMO 172 + +// Reload impulse +#define TF_RELOAD 173 + +// auto-zoom toggle +#define TF_AUTOZOOM 174 + +// drop/pass commands +#define TF_DROPKEY 175 + +// Select Medikit +#define TF_MEDIKIT 176 + +// Spy Impulses +#define TF_SPY_SPY 177 // On net, go invisible, on LAN, change skin/color +#define TF_SPY_DIE 178 // Feign Death + +// Engineer Impulses +#define TF_ENGINEER_BUILD 179 +#define TF_ENGINEER_SANDBAG 180 + +// Medic +#define TF_MEDIC_HELPME 181 + +// Status bar +#define TF_STATUSBAR_ON 182 +#define TF_STATUSBAR_OFF 183 + +// Discard impulse +#define TF_DISCARD 184 + +// ID Player impulse +#define TF_ID 185 + +// Clan Battle impulses +#define TF_SHOWIDS 186 + +// More Engineer Impulses +#define TF_ENGINEER_DETDISP 187 +#define TF_ENGINEER_DETSENT 188 + +// Admin Commands +#define TF_ADMIN_DEAL_CYCLE 189 +#define TF_ADMIN_KICK 190 +#define TF_ADMIN_BAN 191 +#define TF_ADMIN_COUNTPLAYERS 192 +#define TF_ADMIN_CEASEFIRE 193 + +// Drop Goal Items +#define TF_DROPGOALITEMS 194 + +// More Admin Commands +#define TF_ADMIN_NEXT 195 + +// More Engineer Impulses +#define TF_ENGINEER_DETEXIT 196 +#define TF_ENGINEER_DETENTRANCE 197 + +// Yet MORE Admin Commands +#define TF_ADMIN_LISTIPS 198 + +// Silent Spy Feign +#define TF_SPY_SILENTDIE 199 + + +/*==================================================*/ +/* Defines for the ENGINEER's Building ability */ +/*==================================================*/ +// Ammo costs +#define AMMO_COST_SHELLS 2 // Metal needed to make 1 shell +#define AMMO_COST_NAILS 1 +#define AMMO_COST_ROCKETS 2 +#define AMMO_COST_CELLS 2 + +// Building types +#define BUILD_DISPENSER 1 +#define BUILD_SENTRYGUN 2 +#define BUILD_MORTAR 3 +#define BUILD_TELEPORTER_ENTRANCE 4 +#define BUILD_TELEPORTER_EXIT 5 + +// Building metal costs +#define BUILD_COST_DISPENSER 100 // Metal needed to built +#define BUILD_COST_SENTRYGUN 130 +#define BUILD_COST_MORTAR 150 +#define BUILD_COST_TELEPORTER 125 + +#define BUILD_COST_SANDBAG 20 // Built with a separate alias + +// Building times +#define BUILD_TIME_DISPENSER 2 // seconds to build +#define BUILD_TIME_SENTRYGUN 5 +#define BUILD_TIME_MORTAR 5 +#define BUILD_TIME_TELEPORTER 4 + +// Building health levels +#define BUILD_HEALTH_DISPENSER 150 // Health of the building +#define BUILD_HEALTH_SENTRYGUN 150 +#define BUILD_HEALTH_MORTAR 200 +#define BUILD_HEALTH_TELEPORTER 80 + +// Dispenser's maximum carrying capability +#define BUILD_DISPENSER_MAX_SHELLS 400 +#define BUILD_DISPENSER_MAX_NAILS 600 +#define BUILD_DISPENSER_MAX_ROCKETS 300 +#define BUILD_DISPENSER_MAX_CELLS 400 +#define BUILD_DISPENSER_MAX_ARMOR 500 + +// Build state sent down to client +#define BS_BUILDING (1<<0) +#define BS_HAS_DISPENSER (1<<1) +#define BS_HAS_SENTRYGUN (1<<2) +#define BS_CANB_DISPENSER (1<<3) +#define BS_CANB_SENTRYGUN (1<<4) +/*==================================================*/ +/* Ammo quantities for dropping & dispenser use */ +/*==================================================*/ +#define DROP_SHELLS 20 +#define DROP_NAILS 20 +#define DROP_ROCKETS 10 +#define DROP_CELLS 10 +#define DROP_ARMOR 40 + +/*==================================================*/ +/* Team Defines */ +/*==================================================*/ +#define TM_MAX_NO 4 // Max number of teams. Simply changing this value isn't enough. + // A new global to hold new team colors is needed, and more flags + // in the spawnpoint spawnflags may need to be used. + // Basically, don't change this unless you know what you're doing :) + +/*==================================================*/ +/* New Weapon Defines */ +/*==================================================*/ +#define WEAP_HOOK 1 +#define WEAP_BIOWEAPON 2 +#define WEAP_MEDIKIT 4 +#define WEAP_SPANNER 8 +#define WEAP_AXE 16 +#define WEAP_SNIPER_RIFLE 32 +#define WEAP_AUTO_RIFLE 64 +#define WEAP_SHOTGUN 128 +#define WEAP_SUPER_SHOTGUN 256 +#define WEAP_NAILGUN 512 +#define WEAP_SUPER_NAILGUN 1024 +#define WEAP_GRENADE_LAUNCHER 2048 +#define WEAP_FLAMETHROWER 4096 +#define WEAP_ROCKET_LAUNCHER 8192 +#define WEAP_INCENDIARY 16384 +#define WEAP_ASSAULT_CANNON 32768 +#define WEAP_LIGHTNING 65536 +#define WEAP_DETPACK 131072 +#define WEAP_TRANQ 262144 +#define WEAP_LASER 524288 +// still room for 12 more weapons +// but we can remove some by giving the weapons +// a weapon mode (like the rifle) + +// HL-compatible weapon numbers +#define WEAPON_HOOK 1 +#define WEAPON_BIOWEAPON (WEAPON_HOOK+1) +#define WEAPON_MEDIKIT (WEAPON_HOOK+2) +#define WEAPON_SPANNER (WEAPON_HOOK+3) +#define WEAPON_AXE (WEAPON_HOOK+4) +#define WEAPON_SNIPER_RIFLE (WEAPON_HOOK+5) +#define WEAPON_AUTO_RIFLE (WEAPON_HOOK+6) +#define WEAPON_TF_SHOTGUN (WEAPON_HOOK+7) +#define WEAPON_SUPER_SHOTGUN (WEAPON_HOOK+8) +#define WEAPON_NAILGUN (WEAPON_HOOK+9) +#define WEAPON_SUPER_NAILGUN (WEAPON_HOOK+10) +#define WEAPON_GRENADE_LAUNCHER (WEAPON_HOOK+11) +#define WEAPON_FLAMETHROWER (WEAPON_HOOK+12) +#define WEAPON_ROCKET_LAUNCHER (WEAPON_HOOK+13) +#define WEAPON_INCENDIARY (WEAPON_HOOK+14) +#define WEAPON_ASSAULT_CANNON (WEAPON_HOOK+16) +#define WEAPON_LIGHTNING (WEAPON_HOOK+17) +#define WEAPON_DETPACK (WEAPON_HOOK+18) +#define WEAPON_TRANQ (WEAPON_HOOK+19) +#define WEAPON_LASER (WEAPON_HOOK+20) +#define WEAPON_PIPEBOMB_LAUNCHER (WEAPON_HOOK+21) +#define WEAPON_KNIFE (WEAPON_HOOK+22) +#define WEAPON_BENCHMARK (WEAPON_HOOK+23) + +/*==================================================*/ +/* New Weapon Related Defines */ +/*==================================================*/ +// shots per reload +#define RE_SHOTGUN 8 +#define RE_SUPER_SHOTGUN 16 // 8 shots +#define RE_GRENADE_LAUNCHER 6 +#define RE_ROCKET_LAUNCHER 4 + +// reload times +#define RE_SHOTGUN_TIME 2 +#define RE_SUPER_SHOTGUN_TIME 3 +#define RE_GRENADE_LAUNCHER_TIME 4 +#define RE_ROCKET_LAUNCHER_TIME 5 + +// Maximum velocity you can move and fire the Sniper Rifle +#define WEAP_SNIPER_RIFLE_MAX_MOVE 50 + +// Medikit +#define WEAP_MEDIKIT_HEAL 200 // Amount medikit heals per hit +#define WEAP_MEDIKIT_OVERHEAL 50 // Amount of superhealth over max_health the medikit will dispense + +// Spanner +#define WEAP_SPANNER_REPAIR 10 + +// Detpack +#define WEAP_DETPACK_DISARMTIME 3 // Time it takes to disarm a Detpack +#define WEAP_DETPACK_SETTIME 3 // Time it takes to set a Detpack +#define WEAP_DETPACK_SIZE 700 // Explosion Size +#define WEAP_DETPACK_GOAL_SIZE 1500 // Explosion Size for goal triggering +#define WEAP_DETPACK_BITS_NO 12 // Bits that detpack explodes into + +// Tranquiliser Gun +#define TRANQ_TIME 15 + +// Grenades +#define GR_PRIMETIME 3 +#define GR_CALTROP_PRIME 0.5 +#define GR_TYPE_NONE 0 +#define GR_TYPE_NORMAL 1 +#define GR_TYPE_CONCUSSION 2 +#define GR_TYPE_NAIL 3 +#define GR_TYPE_MIRV 4 +#define GR_TYPE_NAPALM 5 +//#define GR_TYPE_FLARE 6 +#define GR_TYPE_GAS 7 +#define GR_TYPE_EMP 8 +#define GR_TYPE_CALTROP 9 +//#define GR_TYPE_FLASH 10 + +// Defines for WeaponMode +#define GL_NORMAL 0 +#define GL_PIPEBOMB 1 + +// Defines for OLD Concussion Grenade +#define GR_OLD_CONCUSS_TIME 5 +#define GR_OLD_CONCUSS_DEC 20 + +// Defines for Concussion Grenade +#define GR_CONCUSS_TIME 0.25 +#define GR_CONCUSS_DEC 10 +#define MEDIUM_PING 150 +#define HIGH_PING 200 + +// Defines for the Gas Grenade +#define GR_HALLU_TIME 0.3 +#define GR_OLD_HALLU_TIME 0.5 +#define GR_HALLU_DEC 2.5 + +// Defines for the BioInfection +#define BIO_JUMP_RADIUS 128 // The distance the bioinfection can jump between players + +/*==================================================*/ +/* New Items */ +/*==================================================*/ +#define NIT_SCANNER 1 + +#define NIT_SILVER_DOOR_OPENED #IT_KEY1 // 131072 +#define NIT_GOLD_DOOR_OPENED #IT_KEY2 // 262144 + +/*==================================================*/ +/* New Item Flags */ +/*==================================================*/ +#define NIT_SCANNER_ENEMY 1 // Detect enemies +#define NIT_SCANNER_FRIENDLY 2 // Detect friendlies (team members) +#define NIT_SCANNER_SOUND 4 // Motion detection. Only report moving entities. + +/*==================================================*/ +/* New Item Related Defines */ +/*==================================================*/ +#define NIT_SCANNER_POWER 25 // The amount of power spent on a scan with the scanner + // is multiplied by this to get the scanrange. +#define NIT_SCANNER_MAXCELL 50 // The maximum number of cells than can be used in one scan +#define NIT_SCANNER_MIN_MOVEMENT 50 // The minimum velocity an entity must have to be detected + // by scanners that only detect movement + +/*==================================================*/ +/* Variables used for New Weapons and Reloading */ +/*==================================================*/ +// Armor Classes : Bitfields. Use the "armorclass" of armor for the Armor Type. +#define AT_SAVESHOT 1 // Kevlar : Reduces bullet damage by 15% +#define AT_SAVENAIL 2 // Wood :) : Reduces nail damage by 15% +#define AT_SAVEEXPLOSION 4 // Blast : Reduces explosion damage by 15% +#define AT_SAVEELECTRICITY 8 // Shock : Reduces electricity damage by 15% +#define AT_SAVEFIRE 16 // Asbestos : Reduces fire damage by 15% + +/*==========================================================================*/ +/* TEAMFORTRESS CLASS DETAILS */ +/*==========================================================================*/ +// Class Details for SCOUT +#define PC_SCOUT_SKIN 4 // Skin for this class when Classkin is on. +#define PC_SCOUT_MAXHEALTH 75 // Maximum Health Level +#define PC_SCOUT_MAXSPEED 400 // Maximum movement speed +#define PC_SCOUT_MAXSTRAFESPEED 400 // Maximum strafing movement speed +#define PC_SCOUT_MAXARMOR 50 // Maximum Armor Level, of any armor class +#define PC_SCOUT_INITARMOR 25 // Armor level when respawned +#define PC_SCOUT_MAXARMORTYPE 0.3 // Maximum level of Armor absorption +#define PC_SCOUT_INITARMORTYPE 0.3 // Absorption Level of armor when respawned +#define PC_SCOUT_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL <-Armor Classes allowed for this class +#define PC_SCOUT_INITARMORCLASS 0 // Armorclass worn when respawned +#define PC_SCOUT_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_NAILGUN +#define PC_SCOUT_MAXAMMO_SHOT 50 // Maximum amount of shot ammo this class can carry +#define PC_SCOUT_MAXAMMO_NAIL 200 // Maximum amount of nail ammo this class can carry +#define PC_SCOUT_MAXAMMO_CELL 100 // Maximum amount of cell ammo this class can carry +#define PC_SCOUT_MAXAMMO_ROCKET 25 // Maximum amount of rocket ammo this class can carry +#define PC_SCOUT_INITAMMO_SHOT 25 // Amount of shot ammo this class has when respawned +#define PC_SCOUT_INITAMMO_NAIL 100 // Amount of nail ammo this class has when respawned +#define PC_SCOUT_INITAMMO_CELL 50 // Amount of cell ammo this class has when respawned +#define PC_SCOUT_INITAMMO_ROCKET 0 // Amount of rocket ammo this class has when respawned +#define PC_SCOUT_GRENADE_TYPE_1 GR_TYPE_CALTROP // <- 1st Type of Grenade this class has +#define PC_SCOUT_GRENADE_TYPE_2 GR_TYPE_CONCUSSION // <- 2nd Type of Grenade this class has +#define PC_SCOUT_GRENADE_INIT_1 2 // Number of grenades of Type 1 this class has when respawned +#define PC_SCOUT_GRENADE_INIT_2 3 // Number of grenades of Type 2 this class has when respawned +#define PC_SCOUT_TF_ITEMS NIT_SCANNER // <- TeamFortress Items this class has + +#define PC_SCOUT_MOTION_MIN_I 0.5 // < Short range +#define PC_SCOUT_MOTION_MIN_MOVE 50 // Minimum vlen of player velocity to be picked up by motion detector +#define PC_SCOUT_SCAN_TIME 2 // # of seconds between each scan pulse +#define PC_SCOUT_SCAN_RANGE 100 // Default scanner range +#define PC_SCOUT_SCAN_COST 2 // Default scanner cell useage per scan + +// Class Details for SNIPER +#define PC_SNIPER_SKIN 5 +#define PC_SNIPER_MAXHEALTH 90 +#define PC_SNIPER_MAXSPEED 300 +#define PC_SNIPER_MAXSTRAFESPEED 300 +#define PC_SNIPER_MAXARMOR 50 +#define PC_SNIPER_INITARMOR 0 +#define PC_SNIPER_MAXARMORTYPE 0.3 +#define PC_SNIPER_INITARMORTYPE 0.3 +#define PC_SNIPER_ARMORCLASSES 3 // #AT_SAVESHOT | #AT_SAVENAIL +#define PC_SNIPER_INITARMORCLASS 0 +#define PC_SNIPER_WEAPONS WEAP_SNIPER_RIFLE | WEAP_AUTO_RIFLE | WEAP_AXE | WEAP_NAILGUN +#define PC_SNIPER_MAXAMMO_SHOT 75 +#define PC_SNIPER_MAXAMMO_NAIL 100 +#define PC_SNIPER_MAXAMMO_CELL 50 +#define PC_SNIPER_MAXAMMO_ROCKET 25 +#define PC_SNIPER_INITAMMO_SHOT 60 +#define PC_SNIPER_INITAMMO_NAIL 50 +#define PC_SNIPER_INITAMMO_CELL 0 +#define PC_SNIPER_INITAMMO_ROCKET 0 +#define PC_SNIPER_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_SNIPER_GRENADE_TYPE_2 GR_TYPE_NONE +#define PC_SNIPER_GRENADE_INIT_1 2 +#define PC_SNIPER_GRENADE_INIT_2 0 +#define PC_SNIPER_TF_ITEMS 0 + +// Class Details for SOLDIER +#define PC_SOLDIER_SKIN 6 +#define PC_SOLDIER_MAXHEALTH 100 +#define PC_SOLDIER_MAXSPEED 240 +#define PC_SOLDIER_MAXSTRAFESPEED 240 +#define PC_SOLDIER_MAXARMOR 200 +#define PC_SOLDIER_INITARMOR 100 +#define PC_SOLDIER_MAXARMORTYPE 0.8 +#define PC_SOLDIER_INITARMORTYPE 0.8 +#define PC_SOLDIER_ARMORCLASSES 31 // ALL +#define PC_SOLDIER_INITARMORCLASS 0 +#define PC_SOLDIER_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_ROCKET_LAUNCHER +#define PC_SOLDIER_MAXAMMO_SHOT 100 +#define PC_SOLDIER_MAXAMMO_NAIL 100 +#define PC_SOLDIER_MAXAMMO_CELL 50 +#define PC_SOLDIER_MAXAMMO_ROCKET 50 +#define PC_SOLDIER_INITAMMO_SHOT 50 +#define PC_SOLDIER_INITAMMO_NAIL 0 +#define PC_SOLDIER_INITAMMO_CELL 0 +#define PC_SOLDIER_INITAMMO_ROCKET 10 +#define PC_SOLDIER_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_SOLDIER_GRENADE_TYPE_2 GR_TYPE_NAIL +#define PC_SOLDIER_GRENADE_INIT_1 2 +#define PC_SOLDIER_GRENADE_INIT_2 1 +#define PC_SOLDIER_TF_ITEMS 0 + +#define MAX_NAIL_GRENS 2 // Can only have 2 Nail grens active +#define MAX_NAPALM_GRENS 2 // Can only have 2 Napalm grens active +#define MAX_GAS_GRENS 2 // Can only have 2 Gas grenades active +#define MAX_MIRV_GRENS 2 // Can only have 2 Mirv's +#define MAX_CONCUSSION_GRENS 3 +#define MAX_CALTROP_CANS 3 + +// Class Details for DEMOLITION MAN +#define PC_DEMOMAN_SKIN 1 +#define PC_DEMOMAN_MAXHEALTH 90 +#define PC_DEMOMAN_MAXSPEED 280 +#define PC_DEMOMAN_MAXSTRAFESPEED 280 +#define PC_DEMOMAN_MAXARMOR 120 +#define PC_DEMOMAN_INITARMOR 50 +#define PC_DEMOMAN_MAXARMORTYPE 0.6 +#define PC_DEMOMAN_INITARMORTYPE 0.6 +#define PC_DEMOMAN_ARMORCLASSES 31 // ALL +#define PC_DEMOMAN_INITARMORCLASS 0 +#define PC_DEMOMAN_WEAPONS WEAP_AXE | WEAP_SHOTGUN | WEAP_GRENADE_LAUNCHER | WEAP_DETPACK +#define PC_DEMOMAN_MAXAMMO_SHOT 75 +#define PC_DEMOMAN_MAXAMMO_NAIL 50 +#define PC_DEMOMAN_MAXAMMO_CELL 50 +#define PC_DEMOMAN_MAXAMMO_ROCKET 50 +#define PC_DEMOMAN_MAXAMMO_DETPACK 1 +#define PC_DEMOMAN_INITAMMO_SHOT 30 +#define PC_DEMOMAN_INITAMMO_NAIL 0 +#define PC_DEMOMAN_INITAMMO_CELL 0 +#define PC_DEMOMAN_INITAMMO_ROCKET 20 +#define PC_DEMOMAN_INITAMMO_DETPACK 1 +#define PC_DEMOMAN_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_DEMOMAN_GRENADE_TYPE_2 GR_TYPE_MIRV +#define PC_DEMOMAN_GRENADE_INIT_1 2 +#define PC_DEMOMAN_GRENADE_INIT_2 2 +#define PC_DEMOMAN_TF_ITEMS 0 + +// Class Details for COMBAT MEDIC +#define PC_MEDIC_SKIN 3 +#define PC_MEDIC_MAXHEALTH 90 +#define PC_MEDIC_MAXSPEED 320 +#define PC_MEDIC_MAXSTRAFESPEED 320 +#define PC_MEDIC_MAXARMOR 100 +#define PC_MEDIC_INITARMOR 50 +#define PC_MEDIC_MAXARMORTYPE 0.6 +#define PC_MEDIC_INITARMORTYPE 0.3 +#define PC_MEDIC_ARMORCLASSES 11 // ALL except EXPLOSION +#define PC_MEDIC_INITARMORCLASS 0 +#define PC_MEDIC_WEAPONS WEAP_BIOWEAPON | WEAP_MEDIKIT | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN | WEAP_SUPER_NAILGUN +#define PC_MEDIC_MAXAMMO_SHOT 75 +#define PC_MEDIC_MAXAMMO_NAIL 150 +#define PC_MEDIC_MAXAMMO_CELL 50 +#define PC_MEDIC_MAXAMMO_ROCKET 25 +#define PC_MEDIC_MAXAMMO_MEDIKIT 100 +#define PC_MEDIC_INITAMMO_SHOT 50 +#define PC_MEDIC_INITAMMO_NAIL 50 +#define PC_MEDIC_INITAMMO_CELL 0 +#define PC_MEDIC_INITAMMO_ROCKET 0 +#define PC_MEDIC_INITAMMO_MEDIKIT 50 +#define PC_MEDIC_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_MEDIC_GRENADE_TYPE_2 GR_TYPE_CONCUSSION +#define PC_MEDIC_GRENADE_INIT_1 2 +#define PC_MEDIC_GRENADE_INIT_2 2 +#define PC_MEDIC_TF_ITEMS 0 +#define PC_MEDIC_REGEN_TIME 3 // Number of seconds between each regen. +#define PC_MEDIC_REGEN_AMOUNT 2 // Amount of health regenerated each regen. + +// Class Details for HVYWEAP +#define PC_HVYWEAP_SKIN 2 +#define PC_HVYWEAP_MAXHEALTH 100 +#define PC_HVYWEAP_MAXSPEED 230 +#define PC_HVYWEAP_MAXSTRAFESPEED 230 +#define PC_HVYWEAP_MAXARMOR 300 +#define PC_HVYWEAP_INITARMOR 150 +#define PC_HVYWEAP_MAXARMORTYPE 0.8 +#define PC_HVYWEAP_INITARMORTYPE 0.8 +#define PC_HVYWEAP_ARMORCLASSES 31 // ALL +#define PC_HVYWEAP_INITARMORCLASS 0 +#define PC_HVYWEAP_WEAPONS WEAP_ASSAULT_CANNON | WEAP_AXE | WEAP_SHOTGUN | WEAP_SUPER_SHOTGUN +#define PC_HVYWEAP_MAXAMMO_SHOT 200 +#define PC_HVYWEAP_MAXAMMO_NAIL 200 +#define PC_HVYWEAP_MAXAMMO_CELL 50 +#define PC_HVYWEAP_MAXAMMO_ROCKET 25 +#define PC_HVYWEAP_INITAMMO_SHOT 200 +#define PC_HVYWEAP_INITAMMO_NAIL 0 +#define PC_HVYWEAP_INITAMMO_CELL 30 +#define PC_HVYWEAP_INITAMMO_ROCKET 0 +#define PC_HVYWEAP_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_HVYWEAP_GRENADE_TYPE_2 GR_TYPE_MIRV +#define PC_HVYWEAP_GRENADE_INIT_1 2 +#define PC_HVYWEAP_GRENADE_INIT_2 1 +#define PC_HVYWEAP_TF_ITEMS 0 +#define PC_HVYWEAP_CELL_USAGE 7 // Amount of cells spent to power up assault cannon + + + +// Class Details for PYRO +#define PC_PYRO_SKIN 21 +#define PC_PYRO_MAXHEALTH 100 +#define PC_PYRO_MAXSPEED 300 +#define PC_PYRO_MAXSTRAFESPEED 300 +#define PC_PYRO_MAXARMOR 150 +#define PC_PYRO_INITARMOR 50 +#define PC_PYRO_MAXARMORTYPE 0.6 +#define PC_PYRO_INITARMORTYPE 0.6 +#define PC_PYRO_ARMORCLASSES 27 // ALL except EXPLOSION +#define PC_PYRO_INITARMORCLASS 16 // #AT_SAVEFIRE +#define PC_PYRO_WEAPONS WEAP_INCENDIARY | WEAP_FLAMETHROWER | WEAP_AXE | WEAP_SHOTGUN +#define PC_PYRO_MAXAMMO_SHOT 40 +#define PC_PYRO_MAXAMMO_NAIL 50 +#define PC_PYRO_MAXAMMO_CELL 200 +#define PC_PYRO_MAXAMMO_ROCKET 20 +#define PC_PYRO_INITAMMO_SHOT 20 +#define PC_PYRO_INITAMMO_NAIL 0 +#define PC_PYRO_INITAMMO_CELL 120 +#define PC_PYRO_INITAMMO_ROCKET 5 +#define PC_PYRO_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_PYRO_GRENADE_TYPE_2 GR_TYPE_NAPALM +#define PC_PYRO_GRENADE_INIT_1 2 +#define PC_PYRO_GRENADE_INIT_2 4 +#define PC_PYRO_TF_ITEMS 0 +#define PC_PYRO_ROCKET_USAGE 3 // Number of rockets per incendiary cannon shot + +// Class Details for SPY +#define PC_SPY_SKIN 22 +#define PC_SPY_MAXHEALTH 90 +#define PC_SPY_MAXSPEED 300 +#define PC_SPY_MAXSTRAFESPEED 300 +#define PC_SPY_MAXARMOR 100 +#define PC_SPY_INITARMOR 25 +#define PC_SPY_MAXARMORTYPE 0.6 // Was 0.3 +#define PC_SPY_INITARMORTYPE 0.6 // Was 0.3 +#define PC_SPY_ARMORCLASSES 27 // ALL except EXPLOSION +#define PC_SPY_INITARMORCLASS 0 +#define PC_SPY_WEAPONS WEAP_AXE | WEAP_TRANQ | WEAP_SUPER_SHOTGUN | WEAP_NAILGUN +#define PC_SPY_MAXAMMO_SHOT 40 +#define PC_SPY_MAXAMMO_NAIL 100 +#define PC_SPY_MAXAMMO_CELL 30 +#define PC_SPY_MAXAMMO_ROCKET 15 +#define PC_SPY_INITAMMO_SHOT 40 +#define PC_SPY_INITAMMO_NAIL 50 +#define PC_SPY_INITAMMO_CELL 10 +#define PC_SPY_INITAMMO_ROCKET 0 +#define PC_SPY_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_SPY_GRENADE_TYPE_2 GR_TYPE_GAS +#define PC_SPY_GRENADE_INIT_1 2 +#define PC_SPY_GRENADE_INIT_2 2 +#define PC_SPY_TF_ITEMS 0 +#define PC_SPY_CELL_REGEN_TIME 5 +#define PC_SPY_CELL_REGEN_AMOUNT 1 +#define PC_SPY_CELL_USAGE 3 // Amount of cells spent while invisible +#define PC_SPY_GO_UNDERCOVER_TIME 4 // Time it takes to go undercover + +// Class Details for ENGINEER +#define PC_ENGINEER_SKIN 22 // Not used anymore +#define PC_ENGINEER_MAXHEALTH 80 +#define PC_ENGINEER_MAXSPEED 300 +#define PC_ENGINEER_MAXSTRAFESPEED 300 +#define PC_ENGINEER_MAXARMOR 50 +#define PC_ENGINEER_INITARMOR 25 +#define PC_ENGINEER_MAXARMORTYPE 0.6 +#define PC_ENGINEER_INITARMORTYPE 0.3 +#define PC_ENGINEER_ARMORCLASSES 31 // ALL +#define PC_ENGINEER_INITARMORCLASS 0 +#define PC_ENGINEER_WEAPONS WEAP_SPANNER | WEAP_LASER | WEAP_SUPER_SHOTGUN +#define PC_ENGINEER_MAXAMMO_SHOT 50 +#define PC_ENGINEER_MAXAMMO_NAIL 50 +#define PC_ENGINEER_MAXAMMO_CELL 200 // synonymous with metal +#define PC_ENGINEER_MAXAMMO_ROCKET 30 +#define PC_ENGINEER_INITAMMO_SHOT 20 +#define PC_ENGINEER_INITAMMO_NAIL 25 +#define PC_ENGINEER_INITAMMO_CELL 100 // synonymous with metal +#define PC_ENGINEER_INITAMMO_ROCKET 0 +#define PC_ENGINEER_GRENADE_TYPE_1 GR_TYPE_NORMAL +#define PC_ENGINEER_GRENADE_TYPE_2 GR_TYPE_EMP +#define PC_ENGINEER_GRENADE_INIT_1 2 +#define PC_ENGINEER_GRENADE_INIT_2 2 +#define PC_ENGINEER_TF_ITEMS 0 + +// Class Details for CIVILIAN +#define PC_CIVILIAN_SKIN 22 +#define PC_CIVILIAN_MAXHEALTH 50 +#define PC_CIVILIAN_MAXSPEED 240 +#define PC_CIVILIAN_MAXSTRAFESPEED 240 +#define PC_CIVILIAN_MAXARMOR 0 +#define PC_CIVILIAN_INITARMOR 0 +#define PC_CIVILIAN_MAXARMORTYPE 0 +#define PC_CIVILIAN_INITARMORTYPE 0 +#define PC_CIVILIAN_ARMORCLASSES 0 +#define PC_CIVILIAN_INITARMORCLASS 0 +#define PC_CIVILIAN_WEAPONS WEAP_AXE +#define PC_CIVILIAN_MAXAMMO_SHOT 0 +#define PC_CIVILIAN_MAXAMMO_NAIL 0 +#define PC_CIVILIAN_MAXAMMO_CELL 0 +#define PC_CIVILIAN_MAXAMMO_ROCKET 0 +#define PC_CIVILIAN_INITAMMO_SHOT 0 +#define PC_CIVILIAN_INITAMMO_NAIL 0 +#define PC_CIVILIAN_INITAMMO_CELL 0 +#define PC_CIVILIAN_INITAMMO_ROCKET 0 +#define PC_CIVILIAN_GRENADE_TYPE_1 0 +#define PC_CIVILIAN_GRENADE_TYPE_2 0 +#define PC_CIVILIAN_GRENADE_INIT_1 0 +#define PC_CIVILIAN_GRENADE_INIT_2 0 +#define PC_CIVILIAN_TF_ITEMS 0 + + +/*==========================================================================*/ +/* TEAMFORTRESS GOALS */ +/*==========================================================================*/ +// For all these defines, see the tfortmap.txt that came with the zip +// for complete descriptions. +// Defines for Goal Activation types : goal_activation (in goals) +#define TFGA_TOUCH 1 // Activated when touched +#define TFGA_TOUCH_DETPACK 2 // Activated when touched by a detpack explosion +#define TFGA_REVERSE_AP 4 // Activated when AP details are _not_ met +#define TFGA_SPANNER 8 // Activated when hit by an engineer's spanner +#define TFGA_DROPTOGROUND 2048 // Drop to Ground when spawning + +// Defines for Goal Effects types : goal_effect +#define TFGE_AP 1 // AP is affected. Default. +#define TFGE_AP_TEAM 2 // All of the AP's team. +#define TFGE_NOT_AP_TEAM 4 // All except AP's team. +#define TFGE_NOT_AP 8 // All except AP. +#define TFGE_WALL 16 // If set, walls stop the Radius effects +#define TFGE_SAME_ENVIRONMENT 32 // If set, players in a different environment to the Goal are not affected +#define TFGE_TIMER_CHECK_AP 64 // If set, Timer Goals check their critera for all players fitting their effects + +// Defines for Goal Result types : goal_result +#define TFGR_SINGLE 1 // Goal can only be activated once +#define TFGR_ADD_BONUSES 2 // Any Goals activated by this one give their bonuses +#define TFGR_ENDGAME 4 // Goal fires Intermission, displays scores, and ends level +#define TFGR_NO_ITEM_RESULTS 8 // GoalItems given by this Goal don't do results +#define TFGR_REMOVE_DISGUISE 16 // Prevent/Remove undercover from any Spy +#define TFGR_FORCE_RESPAWN 32 // Forces the player to teleport to a respawn point +#define TFGR_DESTROY_BUILDINGS 64 // Destroys this player's buildings, if anys + +// Defines for Goal Group Result types : goal_group +// None! +// But I'm leaving this variable in there, since it's fairly likely +// that some will show up sometime. + +// Defines for Goal Item types, : goal_activation (in items) +#define TFGI_GLOW 1 // Players carrying this GoalItem will glow +#define TFGI_SLOW 2 // Players carrying this GoalItem will move at half-speed +#define TFGI_DROP 4 // Players dying with this item will drop it +#define TFGI_RETURN_DROP 8 // Return if a player with it dies +#define TFGI_RETURN_GOAL 16 // Return if a player with it has it removed by a goal's activation +#define TFGI_RETURN_REMOVE 32 // Return if it is removed by TFGI_REMOVE +#define TFGI_REVERSE_AP 64 // Only pickup if the player _doesn't_ match AP Details +#define TFGI_REMOVE 128 // Remove if left untouched for 2 minutes after being dropped +#define TFGI_KEEP 256 // Players keep this item even when they die +#define TFGI_ITEMGLOWS 512 // Item glows when on the ground +#define TFGI_DONTREMOVERES 1024 // Don't remove results when the item is removed +#define TFGI_DROPTOGROUND 2048 // Drop To Ground when spawning +#define TFGI_CANBEDROPPED 4096 // Can be voluntarily dropped by players +#define TFGI_SOLID 8192 // Is solid... blocks bullets, etc + +// Defines for methods of GoalItem returning +#define GI_RET_DROP_DEAD 0 // Dropped by a dead player +#define GI_RET_DROP_LIVING 1 // Dropped by a living player +#define GI_RET_GOAL 2 // Returned by a Goal +#define GI_RET_TIME 3 // Returned due to timeout + +// Defines for TeamSpawnpoints : goal_activation (in teamspawns) +#define TFSP_MULTIPLEITEMS 1 // Give out the GoalItem multiple times +#define TFSP_MULTIPLEMSGS 2 // Display the message multiple times + +// Defines for TeamSpawnpoints : goal_effects (in teamspawns) +#define TFSP_REMOVESELF 1 // Remove itself after being spawned on + +// Defines for Goal States +#define TFGS_ACTIVE 1 +#define TFGS_INACTIVE 2 +#define TFGS_REMOVED 3 +#define TFGS_DELAYED 4 + +// Defines for GoalItem Removing from Player Methods +#define GI_DROP_PLAYERDEATH 0 // Dropped by a dying player +#define GI_DROP_REMOVEGOAL 1 // Removed by a Goal +#define GI_DROP_PLAYERDROP 2 // Dropped by a player + +// Legal Playerclass Handling +#define TF_ILL_SCOUT 1 +#define TF_ILL_SNIPER 2 +#define TF_ILL_SOLDIER 4 +#define TF_ILL_DEMOMAN 8 +#define TF_ILL_MEDIC 16 +#define TF_ILL_HVYWEP 32 +#define TF_ILL_PYRO 64 +#define TF_ILL_RANDOMPC 128 +#define TF_ILL_SPY 256 +#define TF_ILL_ENGINEER 512 + +// Addition classes +#define CLASS_TFGOAL 128 +#define CLASS_TFGOAL_TIMER 129 +#define CLASS_TFGOAL_ITEM 130 +#define CLASS_TFSPAWN 131 + +/*==========================================================================*/ +/* Flamethrower */ +/*==========================================================================*/ +#define FLAME_PLYRMAXTIME 5.0 // lifetime in seconds of a flame on a player +#define FLAME_MAXBURNTIME 8 // lifetime in seconds of a flame on the world (big ones) +#define NAPALM_MAXBURNTIME 20 // lifetime in seconds of flame from a napalm grenade +#define FLAME_MAXPLYRFLAMES 4 // maximum number of flames on a player +#define FLAME_NUMLIGHTS 1 // maximum number of light flame +#define FLAME_BURNRATIO 0.3 // the chance of a flame not 'sticking' +#define GR_TYPE_FLAMES_NO 15 // number of flames spawned when a grenade explode +#define FLAME_DAMAGE_TIME 1 // Interval between damage burns from flames +#define FLAME_EFFECT_TIME 0.2 // frequency at which we display flame effects. +#define FLAME_THINK_TIME 0.1 // Seconds between times the flame checks burn +#define PER_FLAME_DAMAGE 2 // Damage taken per second per flame by burning players + +/*==================================================*/ +/* CTF Support defines */ +/*==================================================*/ +#define CTF_FLAG1 1 +#define CTF_FLAG2 2 +#define CTF_DROPOFF1 3 +#define CTF_DROPOFF2 4 +#define CTF_SCORE1 5 +#define CTF_SCORE2 6 + +//.float hook_out; + +/*==================================================*/ +/* Camera defines */ +/*==================================================*/ +/* +float live_camera; +.float camdist; +.vector camangle; +.entity camera_list; +*/ + +/*==================================================*/ +/* QuakeWorld defines */ +/*==================================================*/ +/* +float already_chosen_map; + +// grappling hook variables +.entity hook; +.float on_hook; +.float fire_held_down;// flag - TRUE if player is still holding down the + // fire button after throwing a hook. +*/ +/*==================================================*/ +/* Server Settings */ +/*==================================================*/ +// Admin modes +#define ADMIN_MODE_NONE 0 +#define ADMIN_MODE_DEAL 1 + +/*==================================================*/ +/* Death Message defines */ +/*==================================================*/ +#define DMSG_SHOTGUN 1 +#define DMSG_SSHOTGUN 2 +#define DMSG_NAILGUN 3 +#define DMSG_SNAILGUN 4 +#define DMSG_GRENADEL 5 +#define DMSG_ROCKETL 6 +#define DMSG_LIGHTNING 7 +#define DMSG_GREN_HAND 8 +#define DMSG_GREN_NAIL 9 +#define DMSG_GREN_MIRV 10 +#define DMSG_GREN_PIPE 11 +#define DMSG_DETPACK 12 +#define DMSG_BIOWEAPON 13 +#define DMSG_BIOWEAPON_ATT 14 +#define DMSG_FLAME 15 +#define DMSG_DETPACK_DIS 16 +#define DMSG_AXE 17 +#define DMSG_SNIPERRIFLE 18 +#define DMSG_AUTORIFLE 19 +#define DMSG_ASSAULTCANNON 20 +#define DMSG_HOOK 21 +#define DMSG_BACKSTAB 22 +#define DMSG_MEDIKIT 23 +#define DMSG_GREN_GAS 24 +#define DMSG_TRANQ 25 +#define DMSG_LASERBOLT 26 +#define DMSG_SENTRYGUN_BULLET 27 +#define DMSG_SNIPERLEGSHOT 28 +#define DMSG_SNIPERHEADSHOT 29 +#define DMSG_GREN_EMP 30 +#define DMSG_GREN_EMP_AMMO 31 +#define DMSG_SPANNER 32 +#define DMSG_INCENDIARY 33 +#define DMSG_SENTRYGUN_ROCKET 34 +#define DMSG_GREN_FLASH 35 +#define DMSG_TRIGGER 36 +#define DMSG_MIRROR 37 +#define DMSG_SENTRYDEATH 38 +#define DMSG_DISPENSERDEATH 39 +#define DMSG_GREN_AIRPIPE 40 +#define DMSG_CALTROP 41 + +/*==================================================*/ +// TOGGLEFLAGS +/*==================================================*/ +// Some of the toggleflags aren't used anymore, but the bits are still +// there to provide compatability with old maps +#define TFLAG_CLASS_PERSIST (1 << 0) // Persistent Classes Bit +#define TFLAG_CHEATCHECK (1 << 1) // Cheatchecking Bit +#define TFLAG_RESPAWNDELAY (1 << 2) // RespawnDelay bit +//#define TFLAG_UN (1 << 3) // NOT USED ANYMORE +#define TFLAG_OLD_GRENS (1 << 3) // Use old concussion grenade and flash grenade +#define TFLAG_UN2 (1 << 4) // NOT USED ANYMORE +#define TFLAG_UN3 (1 << 5) // NOT USED ANYMORE +#define TFLAG_UN4 (1 << 6) // NOT USED ANYMORE: Was Autoteam. CVAR tfc_autoteam used now. +#define TFLAG_TEAMFRAGS (1 << 7) // Individual Frags, or Frags = TeamScore +#define TFLAG_FIRSTENTRY (1 << 8) // Used to determine the first time toggleflags is set + // In a map. Cannot be toggled by players. +#define TFLAG_SPYINVIS (1 << 9) // Spy invisible only +#define TFLAG_GRAPPLE (1 << 10) // Grapple on/off +//#define TFLAG_FULLTEAMSCORE (1 << 11) // Each Team's score is TeamScore + Frags +#define TFLAG_FLAGEMULATION (1 << 12) // Flag emulation on for old TF maps +#define TFLAG_USE_STANDARD (1 << 13) // Use the TF War standard for Flag emulation + +#define TFLAG_FRAGSCORING (1 << 14) // Use frag scoring only + +/*======================*/ +// Menu stuff // +/*======================*/ + +#define MENU_DEFAULT 1 +#define MENU_TEAM 2 +#define MENU_CLASS 3 +#define MENU_MAPBRIEFING 4 +#define MENU_INTRO 5 +#define MENU_CLASSHELP 6 +#define MENU_CLASSHELP2 7 +#define MENU_REPEATHELP 8 + +#define MENU_SPECHELP 9 + + +#define MENU_SPY 12 +#define MENU_SPY_SKIN 13 +#define MENU_SPY_COLOR 14 +#define MENU_ENGINEER 15 +#define MENU_ENGINEER_FIX_DISPENSER 16 +#define MENU_ENGINEER_FIX_SENTRYGUN 17 +#define MENU_ENGINEER_FIX_MORTAR 18 +#define MENU_DISPENSER 19 +#define MENU_CLASS_CHANGE 20 +#define MENU_TEAM_CHANGE 21 + +#define MENU_REFRESH_RATE 25 + +#define MENU_VOICETWEAK 50 + +//============================ +// Timer Types +#define TF_TIMER_ANY 0 +#define TF_TIMER_CONCUSSION 1 +#define TF_TIMER_INFECTION 2 +#define TF_TIMER_HALLUCINATION 3 +#define TF_TIMER_TRANQUILISATION 4 +#define TF_TIMER_ROTHEALTH 5 +#define TF_TIMER_REGENERATION 6 +#define TF_TIMER_GRENPRIME 7 +#define TF_TIMER_CELLREGENERATION 8 +#define TF_TIMER_DETPACKSET 9 +#define TF_TIMER_DETPACKDISARM 10 +#define TF_TIMER_BUILD 11 +#define TF_TIMER_CHECKBUILDDISTANCE 12 +#define TF_TIMER_DISGUISE 13 +#define TF_TIMER_DISPENSERREFILL 14 + +// Non Player timers +#define TF_TIMER_RETURNITEM 100 +#define TF_TIMER_DELAYEDGOAL 101 +#define TF_TIMER_ENDROUND 102 + +//============================ +// Teamscore printing +#define TS_PRINT_SHORT 1 +#define TS_PRINT_LONG 2 +#define TS_PRINT_LONG_TO_ALL 3 + +#ifndef TF_DEFS_ONLY + +typedef struct +{ + int topColor; + int bottomColor; +} team_color_t; + + +/*==================================================*/ +/* GLOBAL VARIABLES */ +/*==================================================*/ +// FortressMap stuff +extern float number_of_teams; // number of teams supported by the map +extern int illegalclasses[5]; // Illegal playerclasses for all teams +extern int civilianteams; // Bitfield holding Civilian teams +extern Vector rgbcolors[5]; // RGB colors for each of the 4 teams + +extern team_color_t teamcolors[5][PC_LASTCLASS]; // Colors for each of the 4 teams + +extern int teamscores[5]; // Goal Score of each team +extern int g_iOrderedTeams[5]; // Teams ordered into order of winners->losers +extern int teamfrags[5]; // Total Frags for each team +extern int teamlives[5]; // Number of lives each team's players have +extern int teammaxplayers[5]; // Max number of players allowed in each team +extern float teamadvantage[5]; // only used if the teamplay equalisation bits are set + // stores the damage ratio players take/give +extern int teamallies[5]; // Keeps track of which teams are allied +extern string_t team_names[5]; + +extern BOOL CTF_Map; +extern BOOL birthday; +extern BOOL christmas; + +extern float num_world_flames; + +// Clan Battle stuff +extern float clan_scores_dumped; +extern float cb_prematch_time; +extern float fOldPrematch; +extern float fOldCeaseFire; +extern float cb_ceasefire_time; +extern float last_id; +extern float spy_off; +extern float old_grens; +extern float flagem_checked; +extern float flNextEqualisationCalc; +extern BOOL cease_fire; +extern BOOL no_cease_fire_text; +extern BOOL initial_cease_fire; +extern BOOL last_cease_fire; +// Autokick stuff +extern float autokick_kills; + +extern float deathmsg; // Global, which is set before every T_Damage, to indicate + // the death message that should be used. + +extern char *sTeamSpawnNames[]; +extern char *sClassNames[]; +extern char *sNewClassModelFiles[]; +extern char *sOldClassModelFiles[]; +extern char *sClassModels[]; +extern char *sClassCfgs[]; +extern char *sGrenadeNames[]; +extern string_t team_menu_string; + +extern int toggleflags; // toggleable flags + +extern CBaseEntity* g_pLastSpawns[5]; +extern BOOL g_bFirstClient; + +extern float g_fNextPrematchAlert; + +typedef struct +{ + int ip; + edict_t *pEdict; +} ip_storage_t; + +extern ip_storage_t g_IpStorage[32]; + +class CGhost; +/*==========================================================================*/ +BOOL ClassIsRestricted(float tno, int pc); +char* GetTeamName(int tno); +int TeamFortress_GetNoPlayers(); +void DestroyBuilding(CBaseEntity *eng, char *bld); +void teamsprint( int tno, CBaseEntity *ignore, int msg_dest, const char *st, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL ); +float anglemod( float v ); + +// Team Funcs +BOOL TeamFortress_TeamIsCivilian(float tno); +void TeamFortress_TeamShowScores(BOOL bLong, CBasePlayer *pPlayer); +BOOL TeamFortress_TeamPutPlayerInTeam(); +void TeamFortress_TeamSetColor(int tno); +void TeamFortress_TeamIncreaseScore(int tno, int scoretoadd); +int TeamFortress_TeamGetScoreFrags(int tno); +int TeamFortress_TeamGetNoPlayers(int tno); +float TeamEqualiseDamage(CBaseEntity *targ, CBaseEntity *attacker, float damage); +BOOL IsSpawnPointValid( Vector &pos ); +BOOL TeamFortress_SortTeams( void ); +void DumpClanScores( void ); +void CalculateTeamEqualiser(); + +// mapscript funcs +void ParseTFServerSettings(); +void ParseTFMapSettings(); +CBaseEntity* Finditem(int ino); +CBaseEntity* Findgoal(int gno); +CBaseEntity* Findteamspawn(int gno); +void RemoveGoal(CBaseEntity *Goal); +void tfgoalitem_GiveToPlayer(CBaseEntity *Item, CBasePlayer *AP, CBaseEntity *Goal); +void dremove( CBaseEntity *te ); +void tfgoalitem_RemoveFromPlayer(CBaseEntity *Item, CBasePlayer *AP, int iMethod); +void tfgoalitem_drop(CBaseEntity *Item, BOOL PAlive, CBasePlayer *P); +void DisplayItemStatus(CBaseEntity *Goal, CBasePlayer *Player, CBaseEntity *Item); +void tfgoalitem_checkgoalreturn(CBaseEntity *Item); +void DoGoalWork(CBaseEntity *Goal, CBasePlayer *AP); +void DoResults(CBaseEntity *Goal, CBasePlayer *AP, BOOL bAddBonuses); +void DoGroupWork(CBaseEntity *Goal, CBasePlayer *AP); +// hooks into the mapscript for all entities +BOOL ActivateDoResults(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal); +BOOL ActivationSucceeded(CBaseEntity *Goal, CBasePlayer *AP, CBaseEntity *ActivatingGoal); + +// prematch & ceasefire +void Display_Prematch(); +void Check_Ceasefire(); + +// admin +void KickPlayer( CBaseEntity *pTarget ); +void BanPlayer( CBaseEntity *pTarget ); +CGhost *FindGhost( int iGhostID ); +int GetBattleID( edict_t *pEntity ); + +extern cvar_t tfc_spam_penalty1;// the initial gag penalty for a spammer (seconds) +extern cvar_t tfc_spam_penalty2;// incremental gag penalty (seconds) for each time gagged spammer continues to speak. +extern cvar_t tfc_spam_limit; // at this many points, gag the spammer +extern cvar_t tfc_clanbattle, tfc_clanbattle_prematch, tfc_prematch, tfc_clanbattle_ceasefire, tfc_balance_teams, tfc_balance_scores; +extern cvar_t tfc_clanbattle_locked, tfc_birthday, tfc_autokick_kills, tfc_fragscoring, tfc_autokick_time, tfc_adminpwd; +extern cvar_t weaponstay, footsteps, flashlight, aimcrosshair, falldamage, teamplay; +extern cvar_t allow_spectators; + +/*==========================================================================*/ +class CTFFlame : public CBaseMonster +{ +public: + void Spawn( void ); + void Precache( void ); + void EXPORT FlameThink( void ); + static CTFFlame *FlameSpawn( CBaseEntity *pOwner, CBaseEntity *pTarget ); + void FlameDestroy( void ); + + float m_flNextDamageTime; +}; + +/*==========================================================================*/ +// MAPSCRIPT CLASSES +class CTFGoal : public CBaseAnimating +{ +public: + void Spawn( void ); + void StartGoal( void ); + void EXPORT PlaceGoal( void ); + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + int Classify ( void ) { return CLASS_TFGOAL; } + + void SetObjectCollisionBox( void ); +}; + +class CTFGoalItem : public CTFGoal +{ +public: + void Spawn( void ); + void StartItem( void ); + void EXPORT PlaceItem( void ); + int Classify ( void ) { return CLASS_TFGOAL_ITEM; } + + float m_flDroppedAt; +}; + +class CTFTimerGoal : public CTFGoal +{ +public: + void Spawn( void ); + int Classify ( void ) { return CLASS_TFGOAL_TIMER; } +}; + +class CTFSpawn : public CBaseEntity +{ +public: + void Spawn( void ); + void Activate( void ); + int Classify ( void ) { return CLASS_TFSPAWN; } + BOOL CheckTeam( int iTeamNo ); + + EHANDLE m_pTeamCheck; +}; + +class CTFDetect : public CBaseEntity +{ +public: + void Spawn( void ); + int Classify ( void ) { return CLASS_TFGOAL; } +}; + +class CTelefragDeath : public CBaseEntity +{ +public: + void Spawn( void ); + void EXPORT DeathTouch( CBaseEntity *pOther ); +}; + +class CTeamCheck : public CBaseDelay +{ +public: + void Spawn( void ); + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + BOOL TeamMatches( int iTeam ); +}; + +class CTeamSet : public CBaseDelay +{ +public: + void Spawn( void ); + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); +}; + +#endif // TF_DEFS_ONLY +#endif // __TF_DEFS_H + + diff --git a/cl_dll/include/unicode_strtools.h b/cl_dll/include/unicode_strtools.h index 8085fa0..cf7f96d 100644 --- a/cl_dll/include/unicode_strtools.h +++ b/cl_dll/include/unicode_strtools.h @@ -1,88 +1,88 @@ -/* -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by the -* Free Software Foundation; either version 2 of the License, or (at -* your option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software Foundation, -* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -* -* In addition, as a special exception, the author gives permission to -* link the code of this program with the Half-Life Game Engine ("HL -* Engine") and Modified Game Libraries ("MODs") developed by Valve, -* L.L.C ("Valve"). You must obey the GNU General Public License in all -* respects for all of the code used other than the HL Engine and MODs -* from Valve. If you modify this file, you may extend this exception -* to your version of the file, but you are not obligated to do so. If -* you do not wish to do so, delete this exception statement from your -* version. -* -*/ -#pragma once -#ifndef UNICODE_STR_TOOLS_H -#define UNICODE_STR_TOOLS_H - - -#ifdef _WIN32 - -typedef wchar_t uchar16; -typedef unsigned int uchar32; - -#else - -typedef unsigned short uchar16; -typedef wchar_t uchar32; - -#endif // _WIN32 - -enum EStringConvertErrorPolicy -{ - _STRINGCONVERTFLAG_SKIP = 1, - _STRINGCONVERTFLAG_FAIL = 2, - _STRINGCONVERTFLAG_ASSERT = 4, - - STRINGCONVERT_REPLACE = 0, - STRINGCONVERT_SKIP = 1, - STRINGCONVERT_FAIL = 2, - - STRINGCONVERT_ASSERT_REPLACE = 4, - STRINGCONVERT_ASSERT_SKIP = 5, - STRINGCONVERT_ASSERT_FAIL = 6, -}; - -bool Q_IsValidUChar32(uchar32 uVal); -int Q_UTF32ToUChar32(const uchar32 *pUTF32, uchar32 &uVal, bool &bErr); -int Q_UChar32ToUTF32Len(uchar32 uVal); -int Q_UChar32ToUTF32(uchar32 uVal, uchar32 *pUTF32); -int Q_UChar32ToUTF8Len(uchar32 uVal); -int Q_UChar32ToUTF16Len(uchar32 uVal); -int Q_UChar32ToUTF16(uchar32 uVal, uchar16 *pUTF16Out); -int Q_UChar32ToUTF8(uchar32 uVal, char *pUTF8Out); -int Q_UTF16ToUChar32(const uchar16 *pUTF16, uchar32 &uValueOut, bool &bErrorOut); -int Q_UTF8ToUTF16(const char *pUTF8, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); -int Q_UTF8ToUTF32(const char *pUTF8, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); -int Q_UTF16ToUTF8(const uchar16 *pUTF16, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); -int Q_UTF16ToUTF32(const uchar16 *pUTF16, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); -int Q_UTF32ToUTF8(const uchar32 *pUTF32, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); -int Q_UTF32ToUTF16(const uchar32 *pUTF32, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); -int Q_UTF8ToUChar32(const char *pUTF8_, uchar32 &uValueOut, bool &bErrorOut); -qboolean Q_UnicodeValidate(const char *pUTF8); -int Q_UnicodeLength(const char *pUTF8); -char *Q_UnicodeAdvance(char *pUTF8, int nChars); -//bool Q_IsMeanSpaceW(uchar16 wch); -bool Q_IsDeprecatedW(uchar16 wch); -uchar16 *StripUnprintableWorker(uchar16 *pwch, bool *pbStrippedAny); -qboolean Q_StripUnprintableAndSpace(char *pch); -qboolean V_UTF8ToUChar32(const char *pUTF8_, uchar32 *uValueOut); -int Q_UnicodeRepair(char *pUTF8); -wchar_t *Q_AdvanceSpace (wchar_t *start); -wchar_t *Q_ReadUToken (wchar_t *start, wchar_t *token, int tokenBufferSize, bool "ed); - -#endif // UNICODE_STR_TOOLS_H +/* +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at +* your option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +* In addition, as a special exception, the author gives permission to +* link the code of this program with the Half-Life Game Engine ("HL +* Engine") and Modified Game Libraries ("MODs") developed by Valve, +* L.L.C ("Valve"). You must obey the GNU General Public License in all +* respects for all of the code used other than the HL Engine and MODs +* from Valve. If you modify this file, you may extend this exception +* to your version of the file, but you are not obligated to do so. If +* you do not wish to do so, delete this exception statement from your +* version. +* +*/ +#pragma once +#ifndef UNICODE_STR_TOOLS_H +#define UNICODE_STR_TOOLS_H + + +#ifdef _WIN32 + +typedef wchar_t uchar16; +typedef unsigned int uchar32; + +#else + +typedef unsigned short uchar16; +typedef wchar_t uchar32; + +#endif // _WIN32 + +enum EStringConvertErrorPolicy +{ + _STRINGCONVERTFLAG_SKIP = 1, + _STRINGCONVERTFLAG_FAIL = 2, + _STRINGCONVERTFLAG_ASSERT = 4, + + STRINGCONVERT_REPLACE = 0, + STRINGCONVERT_SKIP = 1, + STRINGCONVERT_FAIL = 2, + + STRINGCONVERT_ASSERT_REPLACE = 4, + STRINGCONVERT_ASSERT_SKIP = 5, + STRINGCONVERT_ASSERT_FAIL = 6, +}; + +bool Q_IsValidUChar32(uchar32 uVal); +int Q_UTF32ToUChar32(const uchar32 *pUTF32, uchar32 &uVal, bool &bErr); +int Q_UChar32ToUTF32Len(uchar32 uVal); +int Q_UChar32ToUTF32(uchar32 uVal, uchar32 *pUTF32); +int Q_UChar32ToUTF8Len(uchar32 uVal); +int Q_UChar32ToUTF16Len(uchar32 uVal); +int Q_UChar32ToUTF16(uchar32 uVal, uchar16 *pUTF16Out); +int Q_UChar32ToUTF8(uchar32 uVal, char *pUTF8Out); +int Q_UTF16ToUChar32(const uchar16 *pUTF16, uchar32 &uValueOut, bool &bErrorOut); +int Q_UTF8ToUTF16(const char *pUTF8, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); +int Q_UTF8ToUTF32(const char *pUTF8, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); +int Q_UTF16ToUTF8(const uchar16 *pUTF16, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); +int Q_UTF16ToUTF32(const uchar16 *pUTF16, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); +int Q_UTF32ToUTF8(const uchar32 *pUTF32, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); +int Q_UTF32ToUTF16(const uchar32 *pUTF32, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy); +int Q_UTF8ToUChar32(const char *pUTF8_, uchar32 &uValueOut, bool &bErrorOut); +qboolean Q_UnicodeValidate(const char *pUTF8); +int Q_UnicodeLength(const char *pUTF8); +char *Q_UnicodeAdvance(char *pUTF8, int nChars); +//bool Q_IsMeanSpaceW(uchar16 wch); +bool Q_IsDeprecatedW(uchar16 wch); +uchar16 *StripUnprintableWorker(uchar16 *pwch, bool *pbStrippedAny); +qboolean Q_StripUnprintableAndSpace(char *pch); +qboolean V_UTF8ToUChar32(const char *pUTF8_, uchar32 *uValueOut); +int Q_UnicodeRepair(char *pUTF8); +wchar_t *Q_AdvanceSpace (wchar_t *start); +wchar_t *Q_ReadUToken (wchar_t *start, wchar_t *token, int tokenBufferSize, bool "ed); + +#endif // UNICODE_STR_TOOLS_H diff --git a/cl_dll/include/util_vector.h b/cl_dll/include/util_vector.h index ef3a32f..d9ef0d7 100644 --- a/cl_dll/include/util_vector.h +++ b/cl_dll/include/util_vector.h @@ -1,121 +1,121 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// Vector.h -// A subset of the extdll.h in the project HL Entity DLL -// -#pragma once -// Misc C-runtime library headers -#include "stdio.h" -#include "stdlib.h" -#include "math.h" - -// Header file containing definition of globalvars_t and entvars_t -typedef int func_t; // -typedef int string_t; // from engine's pr_comp.h; -typedef float vec_t; // needed before including progdefs.h - -//========================================================= -// 2DVector - used for many pathfinding and many other -// operations that are treated as planar rather than 3d. -//========================================================= -class Vector2D -{ -public: - inline Vector2D(void) { } - inline Vector2D(float X, float Y) { x = X; y = Y; } - inline Vector2D operator+(const Vector2D& v) const { return Vector2D(x+v.x, y+v.y); } - inline Vector2D operator-(const Vector2D& v) const { return Vector2D(x-v.x, y-v.y); } - inline Vector2D operator*(float fl) const { return Vector2D(x*fl, y*fl); } - inline Vector2D operator/(float fl) const { return Vector2D(x/fl, y/fl); } - - inline float Length(void) const { return (float)sqrt(x*x + y*y ); } - - inline Vector2D Normalize ( void ) const - { - Vector2D vec2; - - float flLen = Length(); - if ( flLen == 0 ) - { - return Vector2D( (float)0, (float)0 ); - } - else - { - flLen = 1 / flLen; - return Vector2D( x * flLen, y * flLen ); - } - } - - vec_t x, y; -}; - -inline float DotProduct(const Vector2D& a, const Vector2D& b) { return( a.x*b.x + a.y*b.y ); } -inline Vector2D operator*(float fl, const Vector2D& v) { return v * fl; } - -//========================================================= -// 3D Vector -//========================================================= -class Vector // same data-layout as engine's vec3_t, -{ // which is a vec_t[3] -public: - // Construction/destruction - inline Vector(void) { } - inline Vector(float X, float Y, float Z) { x = X; y = Y; z = Z; } - inline Vector(double X, double Y, double Z) { x = (float)X; y = (float)Y; z = (float)Z; } - inline Vector(int X, int Y, int Z) { x = (float)X; y = (float)Y; z = (float)Z; } - inline Vector(const Vector& v) { x = v.x; y = v.y; z = v.z; } - inline Vector(float rgfl[3]) { x = rgfl[0]; y = rgfl[1]; z = rgfl[2]; } - - // Operators - inline Vector operator-(void) const { return Vector(-x,-y,-z); } - inline int operator==(const Vector& v) const { return x==v.x && y==v.y && z==v.z; } - inline int operator!=(const Vector& v) const { return !(*this==v); } - inline Vector operator+(const Vector& v) const { return Vector(x+v.x, y+v.y, z+v.z); } - inline Vector operator-(const Vector& v) const { return Vector(x-v.x, y-v.y, z-v.z); } - inline Vector operator*(float fl) const { return Vector(x*fl, y*fl, z*fl); } - inline Vector operator/(float fl) const { return Vector(x/fl, y/fl, z/fl); } - - // Methods - inline void CopyToArray(float* rgfl) const { rgfl[0] = x, rgfl[1] = y, rgfl[2] = z; } - inline float Length(void) const { return (float)sqrt(x*x + y*y + z*z); } - operator float *() { return &x; } // Vectors will now automatically convert to float * when needed - operator const float *() const { return &x; } // Vectors will now automatically convert to float * when needed - inline Vector Normalize(void) const - { - float flLen = Length(); - if (flLen == 0) return Vector(0,0,1); // ???? - flLen = 1 / flLen; - return Vector(x * flLen, y * flLen, z * flLen); - } - - inline Vector2D Make2D ( void ) const - { - Vector2D Vec2; - - Vec2.x = x; - Vec2.y = y; - - return Vec2; - } - inline float Length2D(void) const { return (float)sqrt(x*x + y*y); } - - // Members - vec_t x, y, z; -}; -inline Vector operator*(float fl, const Vector& v) { return v * fl; } -inline float DotProduct(const Vector& a, const Vector& b) { return(a.x*b.x+a.y*b.y+a.z*b.z); } -inline Vector CrossProduct(const Vector& a, const Vector& b) { return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); } - -#define vec3_t Vector +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// Vector.h +// A subset of the extdll.h in the project HL Entity DLL +// +#pragma once +// Misc C-runtime library headers +#include "stdio.h" +#include "stdlib.h" +#include "math.h" + +// Header file containing definition of globalvars_t and entvars_t +typedef int func_t; // +typedef int string_t; // from engine's pr_comp.h; +typedef float vec_t; // needed before including progdefs.h + +//========================================================= +// 2DVector - used for many pathfinding and many other +// operations that are treated as planar rather than 3d. +//========================================================= +class Vector2D +{ +public: + inline Vector2D(void) { } + inline Vector2D(float X, float Y) { x = X; y = Y; } + inline Vector2D operator+(const Vector2D& v) const { return Vector2D(x+v.x, y+v.y); } + inline Vector2D operator-(const Vector2D& v) const { return Vector2D(x-v.x, y-v.y); } + inline Vector2D operator*(float fl) const { return Vector2D(x*fl, y*fl); } + inline Vector2D operator/(float fl) const { return Vector2D(x/fl, y/fl); } + + inline float Length(void) const { return (float)sqrt(x*x + y*y ); } + + inline Vector2D Normalize ( void ) const + { + Vector2D vec2; + + float flLen = Length(); + if ( flLen == 0 ) + { + return Vector2D( (float)0, (float)0 ); + } + else + { + flLen = 1 / flLen; + return Vector2D( x * flLen, y * flLen ); + } + } + + vec_t x, y; +}; + +inline float DotProduct(const Vector2D& a, const Vector2D& b) { return( a.x*b.x + a.y*b.y ); } +inline Vector2D operator*(float fl, const Vector2D& v) { return v * fl; } + +//========================================================= +// 3D Vector +//========================================================= +class Vector // same data-layout as engine's vec3_t, +{ // which is a vec_t[3] +public: + // Construction/destruction + inline Vector(void) { } + inline Vector(float X, float Y, float Z) { x = X; y = Y; z = Z; } + inline Vector(double X, double Y, double Z) { x = (float)X; y = (float)Y; z = (float)Z; } + inline Vector(int X, int Y, int Z) { x = (float)X; y = (float)Y; z = (float)Z; } + inline Vector(const Vector& v) { x = v.x; y = v.y; z = v.z; } + inline Vector(float rgfl[3]) { x = rgfl[0]; y = rgfl[1]; z = rgfl[2]; } + + // Operators + inline Vector operator-(void) const { return Vector(-x,-y,-z); } + inline int operator==(const Vector& v) const { return x==v.x && y==v.y && z==v.z; } + inline int operator!=(const Vector& v) const { return !(*this==v); } + inline Vector operator+(const Vector& v) const { return Vector(x+v.x, y+v.y, z+v.z); } + inline Vector operator-(const Vector& v) const { return Vector(x-v.x, y-v.y, z-v.z); } + inline Vector operator*(float fl) const { return Vector(x*fl, y*fl, z*fl); } + inline Vector operator/(float fl) const { return Vector(x/fl, y/fl, z/fl); } + + // Methods + inline void CopyToArray(float* rgfl) const { rgfl[0] = x, rgfl[1] = y, rgfl[2] = z; } + inline float Length(void) const { return (float)sqrt(x*x + y*y + z*z); } + operator float *() { return &x; } // Vectors will now automatically convert to float * when needed + operator const float *() const { return &x; } // Vectors will now automatically convert to float * when needed + inline Vector Normalize(void) const + { + float flLen = Length(); + if (flLen == 0) return Vector(0,0,1); // ???? + flLen = 1 / flLen; + return Vector(x * flLen, y * flLen, z * flLen); + } + + inline Vector2D Make2D ( void ) const + { + Vector2D Vec2; + + Vec2.x = x; + Vec2.y = y; + + return Vec2; + } + inline float Length2D(void) const { return (float)sqrt(x*x + y*y); } + + // Members + vec_t x, y, z; +}; +inline Vector operator*(float fl, const Vector& v) { return v * fl; } +inline float DotProduct(const Vector& a, const Vector& b) { return(a.x*b.x+a.y*b.y+a.z*b.z); } +inline Vector CrossProduct(const Vector& a, const Vector& b) { return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); } + +#define vec3_t Vector diff --git a/cl_dll/include/view.h b/cl_dll/include/view.h index d82e4e0..eeae450 100644 --- a/cl_dll/include/view.h +++ b/cl_dll/include/view.h @@ -1,14 +1,14 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#pragma once -#if !defined ( VIEWH ) -#define VIEWH - -void V_StartPitchDrift( void ); -void V_StopPitchDrift( void ); - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= +#pragma once +#if !defined ( VIEWH ) +#define VIEWH + +void V_StartPitchDrift( void ); +void V_StopPitchDrift( void ); + #endif // !VIEWH \ No newline at end of file diff --git a/cl_dll/include/wrect.h b/cl_dll/include/wrect.h index a9d7b5e..9c1d96c 100644 --- a/cl_dll/include/wrect.h +++ b/cl_dll/include/wrect.h @@ -1,17 +1,17 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#pragma once -#if !defined( WRECTH ) -#define WRECTH - -typedef struct rect_s -{ - int left, right, top, bottom; -} wrect_t; - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#pragma once +#if !defined( WRECTH ) +#define WRECTH + +typedef struct rect_s +{ + int left, right, top, bottom; +} wrect_t; + #endif \ No newline at end of file diff --git a/cl_dll/input.cpp b/cl_dll/input.cpp index b304950..d79acb3 100644 --- a/cl_dll/input.cpp +++ b/cl_dll/input.cpp @@ -1,1022 +1,1022 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// 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 -#include - - -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_iAlive; - -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 ) -{ - 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); - gHUD.m_Spectator.HandleButtonsDown( IN_FORWARD ); -} - -void IN_ForwardUp(void) -{ - KeyUp(&in_forward); - gHUD.m_Spectator.HandleButtonsUp( IN_FORWARD ); -} - -void IN_BackDown(void) -{ - KeyDown(&in_back); - gHUD.m_Spectator.HandleButtonsDown( IN_BACK ); -} - -void IN_BackUp(void) -{ - KeyUp(&in_back); - gHUD.m_Spectator.HandleButtonsUp( 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); - gHUD.m_Spectator.HandleButtonsDown( IN_MOVELEFT ); -} - -void IN_MoveleftUp(void) -{ - KeyUp(&in_moveleft); - gHUD.m_Spectator.HandleButtonsUp( IN_MOVELEFT ); -} - -void IN_MoverightDown(void) -{ - KeyDown(&in_moveright); - gHUD.m_Spectator.HandleButtonsDown( IN_MOVERIGHT ); -} - -void IN_MoverightUp(void) -{ - KeyUp(&in_moveright); - gHUD.m_Spectator.HandleButtonsUp( 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); - - gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK2 ); -} - -void IN_Attack2Up(void) {KeyUp(&in_attack2);} -void IN_UseDown (void) -{ - KeyDown(&in_use); - gHUD.m_Spectator.HandleButtonsDown( IN_USE ); -} -void IN_UseUp (void) {KeyUp(&in_use);} -void IN_JumpDown (void) -{ - KeyDown(&in_jump); - gHUD.m_Spectator.HandleButtonsDown( IN_JUMP ); - -} -void IN_JumpUp (void) {KeyUp(&in_jump);} -void IN_DuckDown(void) -{ - KeyDown(&in_duck); - gHUD.m_Spectator.HandleButtonsDown( 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 ); - gHUD.m_Spectator.HandleButtonsDown( 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); -} - -void IN_ScoreUp(void) -{ - KeyUp(&in_score); -} - -void IN_MLookUp (void) -{ - KeyUp( &in_mlook ); -#if 0 - if ( !( in_mlook.state & 1 ) && lookspring->value ) - { - V_StartPitchDrift(); - } -#endif -} - -/* -=============== -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 0 - if (up || down) - V_StopPitchDrift (); -#endif - 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 ) ) - { - if(gHUD.m_MOTD.m_bShow) - { - gHUD.m_MOTD.scroll -= CL_KeyState (&in_forward); - gHUD.m_MOTD.scroll += CL_KeyState (&in_back); - } - else - { - 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 ( g_iAlive ) - { - 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 ) - { - if(gHUD.m_MOTD.m_bShow) - gHUD.m_MOTD.Reset(); - else - 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 ("+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(); -} +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// 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 +#include + + +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_iAlive; + +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 ) +{ + 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); + gHUD.m_Spectator.HandleButtonsDown( IN_FORWARD ); +} + +void IN_ForwardUp(void) +{ + KeyUp(&in_forward); + gHUD.m_Spectator.HandleButtonsUp( IN_FORWARD ); +} + +void IN_BackDown(void) +{ + KeyDown(&in_back); + gHUD.m_Spectator.HandleButtonsDown( IN_BACK ); +} + +void IN_BackUp(void) +{ + KeyUp(&in_back); + gHUD.m_Spectator.HandleButtonsUp( 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); + gHUD.m_Spectator.HandleButtonsDown( IN_MOVELEFT ); +} + +void IN_MoveleftUp(void) +{ + KeyUp(&in_moveleft); + gHUD.m_Spectator.HandleButtonsUp( IN_MOVELEFT ); +} + +void IN_MoverightDown(void) +{ + KeyDown(&in_moveright); + gHUD.m_Spectator.HandleButtonsDown( IN_MOVERIGHT ); +} + +void IN_MoverightUp(void) +{ + KeyUp(&in_moveright); + gHUD.m_Spectator.HandleButtonsUp( 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); + + gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK2 ); +} + +void IN_Attack2Up(void) {KeyUp(&in_attack2);} +void IN_UseDown (void) +{ + KeyDown(&in_use); + gHUD.m_Spectator.HandleButtonsDown( IN_USE ); +} +void IN_UseUp (void) {KeyUp(&in_use);} +void IN_JumpDown (void) +{ + KeyDown(&in_jump); + gHUD.m_Spectator.HandleButtonsDown( IN_JUMP ); + +} +void IN_JumpUp (void) {KeyUp(&in_jump);} +void IN_DuckDown(void) +{ + KeyDown(&in_duck); + gHUD.m_Spectator.HandleButtonsDown( 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 ); + gHUD.m_Spectator.HandleButtonsDown( 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); +} + +void IN_ScoreUp(void) +{ + KeyUp(&in_score); +} + +void IN_MLookUp (void) +{ + KeyUp( &in_mlook ); +#if 0 + if ( !( in_mlook.state & 1 ) && lookspring->value ) + { + V_StartPitchDrift(); + } +#endif +} + +/* +=============== +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 0 + if (up || down) + V_StopPitchDrift (); +#endif + 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 ) ) + { + if(gHUD.m_MOTD.m_bShow) + { + gHUD.m_MOTD.scroll -= CL_KeyState (&in_forward); + gHUD.m_MOTD.scroll += CL_KeyState (&in_back); + } + else + { + 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 ( g_iAlive ) + { + 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 ) + { + if(gHUD.m_MOTD.m_bShow) + gHUD.m_MOTD.Reset(); + else + 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 ("+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(); +} diff --git a/cl_dll/inputw32.cpp b/cl_dll/inputw32.cpp index e8bcc6d..16494f5 100644 --- a/cl_dll/inputw32.cpp +++ b/cl_dll/inputw32.cpp @@ -1,957 +1,957 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// 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 "port.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 ; ivalue) - { - 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 (¤t_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_idvalue == 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<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 * powf(fabs(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; - } -#if 0 - V_StopPitchDrift(); -#endif - } -#if 0 - 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(); - } - } -#endif - } - 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; - } -#if 0 - V_StopPitchDrift(); -#endif - } -#if 0 - 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(); - } - } -#endif - } - 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 (); +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// 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 "port.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 ; ivalue) + { + 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 (¤t_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_idvalue == 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<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 * powf(fabs(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; + } +#if 0 + V_StopPitchDrift(); +#endif + } +#if 0 + 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(); + } + } +#endif + } + 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; + } +#if 0 + V_StopPitchDrift(); +#endif + } +#if 0 + 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(); + } + } +#endif + } + 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 (); } \ No newline at end of file diff --git a/cl_dll/overview.cpp b/cl_dll/overview.cpp index f62a4e8..bc1852b 100644 --- a/cl_dll/overview.cpp +++ b/cl_dll/overview.cpp @@ -1,160 +1,160 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include "hud.h" -#include "cl_util.h" -#include "cl_entity.h" -#include "triangleapi.h" - -// these are included for the math functions -#include "com_model.h" -#include "studio_util.h" - -#pragma warning(disable: 4244) -//seems not used -#if 0 -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CHudOverview::Init() -{ - gHUD.AddHudElem(this); - - m_iFlags |= HUD_ACTIVE; - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Loads new icons -//----------------------------------------------------------------------------- -int CHudOverview::VidInit() -{ - m_hsprPlayer = gEngfuncs.pfnSPR_Load("sprites/ring.spr"); - m_hsprViewcone = gEngfuncs.pfnSPR_Load("sprites/camera.spr"); - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flTime - -// intermission - -//----------------------------------------------------------------------------- -int CHudOverview::Draw(float flTime) -{ - // only draw in overview mode - if (!gEngfuncs.Overview_GetOverviewState()) - return 1; - - // make sure we have player info - gHUD.m_Scoreboard.GetAllPlayersInfo(); - - // calculate player size on the overview - int x1, y1, x2, y2; - float v0[3]={0,0,0}, v1[3]={64,64,0}; - gEngfuncs.Overview_WorldToScreen(v0, &x1, &y1); - gEngfuncs.Overview_WorldToScreen(v1, &x2, &y2); - float scale = abs(x2 - x1); - - // loop through all the players and draw them on the map - for (int i = 1; i < MAX_PLAYERS; i++) - { - cl_entity_t *pl = gEngfuncs.GetEntityByIndex(i); - - if (pl && pl->player && pl->curstate.health > 0 && pl->curstate.solid != SOLID_NOT) - { - int x, y, z = 0; - float v[3]={pl->origin[0], pl->origin[1], 0}; - gEngfuncs.Overview_WorldToScreen(v, &x, &y); - - // hack in some team colors - float r, g, bc; - if (g_PlayerExtraInfo[i].teamnumber == 1) - { - r = 0.0f; g = 0.0f; bc = 1.0f; - } - else if (g_PlayerExtraInfo[i].teamnumber == 2) - { - r = 1.0f; g = 0.0f; bc = 0.0f; - } - else - { - // just use the default orange color if the team isn't set - r = 1.0f; g = 0.7f; bc = 0.0f; - } - - // set the current texture - gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(m_hsprPlayer), 0); - - // additive render mode - gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); - - // no culling - gEngfuncs.pTriAPI->CullFace(TRI_NONE); - - // draw a square - gEngfuncs.pTriAPI->Begin(TRI_QUADS); - - // set the color to be that of the team - gEngfuncs.pTriAPI->Color4f(r, g, bc, 1.0f); - - // calculate rotational matrix - vec3_t a, b, angles; - float rmatrix[3][4]; // transformation matrix - VectorCopy(pl->angles, angles); - angles[0] = 0.0f; - angles[1] += 90.f; - angles[1] = -angles[1]; - angles[2] = 0.0f; - AngleMatrix(angles, rmatrix); - a[2] = 0; - - a[0] = -scale; a[1] = -scale; - VectorTransform(a, rmatrix , b ); - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - gEngfuncs.pTriAPI->Vertex3f(x + b[0], y + b[1], z); - - a[0]=-scale; a[1] = scale; - VectorTransform(a, rmatrix , b ); - gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z); - - a[0]=scale; a[1] = scale; - VectorTransform(a, rmatrix , b ); - gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); - gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z); - - a[0]=scale; a[1] = -scale; - VectorTransform(a, rmatrix , b ); - gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); - gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z); - - // finish up - gEngfuncs.pTriAPI->End(); - gEngfuncs.pTriAPI->RenderMode( kRenderNormal ); - - // draw the players name and health underneath - char string[256]; - sprintf(string, "%s (%i%%)", g_PlayerInfoList[i].name, pl->curstate.health); - DrawConsoleString(x, y + (1.1 * scale), string); - } - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: called every time a server is connected to -//----------------------------------------------------------------------------- -void CHudOverview::InitHUDData() -{ -// this block would force the spectator view to be on -// gEngfuncs.Overview_SetDrawOverview( 1 ); -// gEngfuncs.Overview_SetDrawInset( 0 ); -} -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "hud.h" +#include "cl_util.h" +#include "cl_entity.h" +#include "triangleapi.h" + +// these are included for the math functions +#include "com_model.h" +#include "studio_util.h" + +#pragma warning(disable: 4244) +//seems not used +#if 0 +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CHudOverview::Init() +{ + gHUD.AddHudElem(this); + + m_iFlags |= HUD_ACTIVE; + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: Loads new icons +//----------------------------------------------------------------------------- +int CHudOverview::VidInit() +{ + m_hsprPlayer = gEngfuncs.pfnSPR_Load("sprites/ring.spr"); + m_hsprViewcone = gEngfuncs.pfnSPR_Load("sprites/camera.spr"); + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : flTime - +// intermission - +//----------------------------------------------------------------------------- +int CHudOverview::Draw(float flTime) +{ + // only draw in overview mode + if (!gEngfuncs.Overview_GetOverviewState()) + return 1; + + // make sure we have player info + gHUD.m_Scoreboard.GetAllPlayersInfo(); + + // calculate player size on the overview + int x1, y1, x2, y2; + float v0[3]={0,0,0}, v1[3]={64,64,0}; + gEngfuncs.Overview_WorldToScreen(v0, &x1, &y1); + gEngfuncs.Overview_WorldToScreen(v1, &x2, &y2); + float scale = abs(x2 - x1); + + // loop through all the players and draw them on the map + for (int i = 1; i < MAX_PLAYERS; i++) + { + cl_entity_t *pl = gEngfuncs.GetEntityByIndex(i); + + if (pl && pl->player && pl->curstate.health > 0 && pl->curstate.solid != SOLID_NOT) + { + int x, y, z = 0; + float v[3]={pl->origin[0], pl->origin[1], 0}; + gEngfuncs.Overview_WorldToScreen(v, &x, &y); + + // hack in some team colors + float r, g, bc; + if (g_PlayerExtraInfo[i].teamnumber == 1) + { + r = 0.0f; g = 0.0f; bc = 1.0f; + } + else if (g_PlayerExtraInfo[i].teamnumber == 2) + { + r = 1.0f; g = 0.0f; bc = 0.0f; + } + else + { + // just use the default orange color if the team isn't set + r = 1.0f; g = 0.7f; bc = 0.0f; + } + + // set the current texture + gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(m_hsprPlayer), 0); + + // additive render mode + gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); + + // no culling + gEngfuncs.pTriAPI->CullFace(TRI_NONE); + + // draw a square + gEngfuncs.pTriAPI->Begin(TRI_QUADS); + + // set the color to be that of the team + gEngfuncs.pTriAPI->Color4f(r, g, bc, 1.0f); + + // calculate rotational matrix + vec3_t a, b, angles; + float rmatrix[3][4]; // transformation matrix + VectorCopy(pl->angles, angles); + angles[0] = 0.0f; + angles[1] += 90.f; + angles[1] = -angles[1]; + angles[2] = 0.0f; + AngleMatrix(angles, rmatrix); + a[2] = 0; + + a[0] = -scale; a[1] = -scale; + VectorTransform(a, rmatrix , b ); + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + gEngfuncs.pTriAPI->Vertex3f(x + b[0], y + b[1], z); + + a[0]=-scale; a[1] = scale; + VectorTransform(a, rmatrix , b ); + gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z); + + a[0]=scale; a[1] = scale; + VectorTransform(a, rmatrix , b ); + gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); + gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z); + + a[0]=scale; a[1] = -scale; + VectorTransform(a, rmatrix , b ); + gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); + gEngfuncs.pTriAPI->Vertex3f (x + b[0], y + b[1], z); + + // finish up + gEngfuncs.pTriAPI->End(); + gEngfuncs.pTriAPI->RenderMode( kRenderNormal ); + + // draw the players name and health underneath + char string[256]; + sprintf(string, "%s (%i%%)", g_PlayerInfoList[i].name, pl->curstate.health); + DrawConsoleString(x, y + (1.1 * scale), string); + } + } + + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: called every time a server is connected to +//----------------------------------------------------------------------------- +void CHudOverview::InitHUDData() +{ +// this block would force the spectator view to be on +// gEngfuncs.Overview_SetDrawOverview( 1 ); +// gEngfuncs.Overview_SetDrawInset( 0 ); +} +#endif diff --git a/cl_dll/parsemsg.cpp b/cl_dll/parsemsg.cpp index 3bfeeb1..8b5f4cc 100644 --- a/cl_dll/parsemsg.cpp +++ b/cl_dll/parsemsg.cpp @@ -1,166 +1,166 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// parsemsg.cpp -// -typedef unsigned char byte; -#define true 1 - -#include - -static byte *gpBuf; -static size_t giSize; -static int giRead; -static bool giBadRead; - -void BEGIN_READ( void *buf, int size ) -{ - giRead = 0; - giBadRead = false; - giSize = size; - gpBuf = (byte*)buf; -} - -int READ_CHAR( void ) -{ - int c; - - if (giRead + 1 > giSize) - { - giBadRead = true; - return -1; - } - - c = (signed char)gpBuf[giRead]; - giRead++; - - return c; -} - -int READ_BYTE( void ) -{ - int c; - - if (giRead+1 > giSize) - { - giBadRead = true; - return -1; - } - - c = (unsigned char)gpBuf[giRead]; - giRead++; - - return c; -} - -int READ_SHORT( void ) -{ - int c; - - if (giRead+2 > giSize) - { - giBadRead = true; - return -1; - } - - c = (short)( gpBuf[giRead] + ( gpBuf[giRead+1] << 8 ) ); - - giRead += 2; - - return c; -} - -int READ_WORD( void ) -{ - return READ_SHORT(); -} - - -int READ_LONG( void ) -{ - int c; - - if (giRead+4 > giSize) - { - giBadRead = true; - return -1; - } - - c = gpBuf[giRead] + (gpBuf[giRead + 1] << 8) + (gpBuf[giRead + 2] << 16) + (gpBuf[giRead + 3] << 24); - - giRead += 4; - - return c; -} - -float READ_FLOAT( void ) -{ - union - { - byte b[4]; - float f; - int l; - } dat; - - dat.b[0] = gpBuf[giRead]; - dat.b[1] = gpBuf[giRead+1]; - dat.b[2] = gpBuf[giRead+2]; - dat.b[3] = gpBuf[giRead+3]; - giRead += 4; - -// dat.l = LittleLong (dat.l); - - return dat.f; -} - -char* READ_STRING( void ) -{ - static char string[2048]; - int l,c; - - string[0] = 0; - - l = 0; - do - { - if ( giRead+1 > giSize ) - break; // no more characters - - c = READ_CHAR(); - if (c == -1 || c == 0) - break; - string[l] = c; - l++; - } while (l < sizeof(string)-1); - - string[l] = 0; - - return string; -} - -float READ_COORD( void ) -{ - return (float)(READ_SHORT() * (1.0/8)); -} - -float READ_ANGLE( void ) -{ - return (float)(READ_CHAR() * (360.0/256)); -} - -float READ_HIRESANGLE( void ) -{ - return (float)(READ_SHORT() * (360.0/65536)); -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// parsemsg.cpp +// +typedef unsigned char byte; +#define true 1 + +#include + +static byte *gpBuf; +static size_t giSize; +static int giRead; +static bool giBadRead; + +void BEGIN_READ( void *buf, int size ) +{ + giRead = 0; + giBadRead = false; + giSize = size; + gpBuf = (byte*)buf; +} + +int READ_CHAR( void ) +{ + int c; + + if (giRead + 1 > giSize) + { + giBadRead = true; + return -1; + } + + c = (signed char)gpBuf[giRead]; + giRead++; + + return c; +} + +int READ_BYTE( void ) +{ + int c; + + if (giRead+1 > giSize) + { + giBadRead = true; + return -1; + } + + c = (unsigned char)gpBuf[giRead]; + giRead++; + + return c; +} + +int READ_SHORT( void ) +{ + int c; + + if (giRead+2 > giSize) + { + giBadRead = true; + return -1; + } + + c = (short)( gpBuf[giRead] + ( gpBuf[giRead+1] << 8 ) ); + + giRead += 2; + + return c; +} + +int READ_WORD( void ) +{ + return READ_SHORT(); +} + + +int READ_LONG( void ) +{ + int c; + + if (giRead+4 > giSize) + { + giBadRead = true; + return -1; + } + + c = gpBuf[giRead] + (gpBuf[giRead + 1] << 8) + (gpBuf[giRead + 2] << 16) + (gpBuf[giRead + 3] << 24); + + giRead += 4; + + return c; +} + +float READ_FLOAT( void ) +{ + union + { + byte b[4]; + float f; + int l; + } dat; + + dat.b[0] = gpBuf[giRead]; + dat.b[1] = gpBuf[giRead+1]; + dat.b[2] = gpBuf[giRead+2]; + dat.b[3] = gpBuf[giRead+3]; + giRead += 4; + +// dat.l = LittleLong (dat.l); + + return dat.f; +} + +char* READ_STRING( void ) +{ + static char string[2048]; + int l,c; + + string[0] = 0; + + l = 0; + do + { + if ( giRead+1 > giSize ) + break; // no more characters + + c = READ_CHAR(); + if (c == -1 || c == 0) + break; + string[l] = c; + l++; + } while (l < sizeof(string)-1); + + string[l] = 0; + + return string; +} + +float READ_COORD( void ) +{ + return (float)(READ_SHORT() * (1.0/8)); +} + +float READ_ANGLE( void ) +{ + return (float)(READ_CHAR() * (360.0/256)); +} + +float READ_HIRESANGLE( void ) +{ + return (float)(READ_SHORT() * (360.0/65536)); +} diff --git a/cl_dll/rain.cpp b/cl_dll/rain.cpp index 3094e09..8cfa4c8 100644 --- a/cl_dll/rain.cpp +++ b/cl_dll/rain.cpp @@ -1,405 +1,405 @@ -/*** -* -* Copyright (c) 2005, BUzer. -* -* Used with permission for Spirit of Half-Life 1.5 -* -****/ -/* -====== rain.cpp ======================================================== -*/ - -#include -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "entity_types.h" -#include "cdll_int.h" -#include "pm_defs.h" -#include "event_api.h" - -#include "rain.h" - -void WaterLandingEffect(cl_drip *drip); - -rain_properties Rain; - -cl_drip FirstChainDrip; -cl_rainfx FirstChainFX; - -double rain_curtime; // current time -double rain_oldtime; // last time we have updated drips -double rain_timedelta; // difference between old time and current time -double rain_nextspawntime; // when the next drip should be spawned - -int dripcounter = 0; -int fxcounter = 0; -int RainInfo = 0; - -/* -================================= -ProcessRain - -Must think every frame. -================================= -*/ -void ProcessRain( void ) -{ - rain_oldtime = rain_curtime; // save old time - rain_curtime = gEngfuncs.GetClientTime(); - rain_timedelta = rain_curtime - rain_oldtime; - - // first frame - if (rain_oldtime == 0) - { - // fix first frame bug with nextspawntime - rain_nextspawntime = gEngfuncs.GetClientTime(); - return; - } - - if (Rain.dripsPerSecond == 0 && FirstChainDrip.p_Next == NULL) - { - // keep nextspawntime correct - rain_nextspawntime = rain_curtime; - return; - } - - if (rain_timedelta == 0) - return; // not in pause - - double timeBetweenDrips = 1 / (double)Rain.dripsPerSecond; - - cl_drip* curDrip = FirstChainDrip.p_Next; - cl_drip* nextDrip = NULL; - - - // save debug info - float debug_lifetime = 0; - int debug_howmany = 0; - int debug_attempted = 0; - int debug_dropped = 0; - - while (curDrip != NULL) // go through list - { - nextDrip = curDrip->p_Next; // save pointer to next drip - - if (Rain.weatherMode == 0) - curDrip->origin.z -= rain_timedelta * DRIPSPEED; // rain - else - curDrip->origin.z -= rain_timedelta * SNOWSPEED; // snow - - curDrip->origin.x += rain_timedelta * curDrip->xDelta; - curDrip->origin.y += rain_timedelta * curDrip->yDelta; - - // remove drip if its origin lower than minHeight - if (curDrip->origin.z < curDrip->minHeight) - { - if (curDrip->landInWater/* && Rain.weatherMode == 0*/) - WaterLandingEffect(curDrip); // create water rings - - if (RainInfo) - { - debug_lifetime += (rain_curtime - curDrip->birthTime); - debug_howmany++; - } - - curDrip->p_Prev->p_Next = curDrip->p_Next; // link chain - if (nextDrip != NULL) - nextDrip->p_Prev = curDrip->p_Prev; - delete curDrip; - - dripcounter--; - } - - curDrip = nextDrip; // restore pointer, so we can continue moving through chain - } - - int maxDelta; // maximum height randomize distance - float falltime; - if (Rain.weatherMode == 0) - { - maxDelta = DRIPSPEED * rain_timedelta; // for rain - falltime = (Rain.globalHeight + 4096) / DRIPSPEED; - } - else - { - maxDelta = SNOWSPEED * rain_timedelta; // for snow - falltime = (Rain.globalHeight + 4096) / SNOWSPEED; - } - - while (rain_nextspawntime < rain_curtime) - { - rain_nextspawntime += timeBetweenDrips; - if (RainInfo) - debug_attempted++; - - if (dripcounter < MAXDRIPS) // check for overflow - { - float deathHeight; - vec3_t vecStart, vecEnd; - - vecStart[0] = gEngfuncs.pfnRandomFloat(gHUD.m_vecOrigin.x - Rain.distFromPlayer, gHUD.m_vecOrigin.x + Rain.distFromPlayer); - vecStart[1] = gEngfuncs.pfnRandomFloat(gHUD.m_vecOrigin.y - Rain.distFromPlayer, gHUD.m_vecOrigin.y + Rain.distFromPlayer); - vecStart[2] = Rain.globalHeight; - - float xDelta = Rain.windX + gEngfuncs.pfnRandomFloat(Rain.randX * -1, Rain.randX); - float yDelta = Rain.windY + gEngfuncs.pfnRandomFloat(Rain.randY * -1, Rain.randY); - - // find a point at bottom of map - vecEnd[0] = falltime * xDelta; - vecEnd[1] = falltime * yDelta; - vecEnd[2] = -4096; - - pmtrace_t pmtrace; - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( vecStart, vecEnd, PM_STUDIO_IGNORE, -1, &pmtrace ); - - if (pmtrace.startsolid) - { - if (RainInfo) - debug_dropped++; - - continue; // drip cannot be placed - } - - // falling to water? - int contents = gEngfuncs.PM_PointContents( pmtrace.endpos, NULL ); - if (contents == CONTENTS_WATER) - { - int waterEntity = gEngfuncs.PM_WaterEntity( pmtrace.endpos ); - if ( waterEntity > 0 ) - { - cl_entity_t *pwater = gEngfuncs.GetEntityByIndex( waterEntity ); - if ( pwater && ( pwater->model != NULL ) ) - { - deathHeight = pwater->curstate.maxs[2]; - } - else - { - gEngfuncs.Con_Printf("Rain error: can't get water entity\n"); - continue; - } - } - else - { - gEngfuncs.Con_Printf("Rain error: water is not func_water entity\n"); - continue; - } - } - else - { - deathHeight = pmtrace.endpos[2]; - } - - // just in case.. - if (deathHeight > vecStart[2]) - { - gEngfuncs.Con_Printf("Rain error: can't create drip in water\n"); - continue; - } - - - cl_drip *newClDrip = new cl_drip; - if (!newClDrip) - { - Rain.dripsPerSecond = 0; // disable rain - gEngfuncs.Con_Printf( "Rain error: failed to allocate object!\n"); - return; - } - - vecStart[2] -= gEngfuncs.pfnRandomFloat(0, maxDelta); // randomize a bit - - newClDrip->alpha = gEngfuncs.pfnRandomFloat(0.12, 0.2); - VectorCopy(vecStart, newClDrip->origin); - - newClDrip->xDelta = xDelta; - newClDrip->yDelta = yDelta; - - newClDrip->birthTime = rain_curtime; // store time when it was spawned - newClDrip->minHeight = deathHeight; - - if (contents == CONTENTS_WATER) - newClDrip->landInWater = 1; - else - newClDrip->landInWater = 0; - - // add to first place in chain - newClDrip->p_Next = FirstChainDrip.p_Next; - newClDrip->p_Prev = &FirstChainDrip; - if (newClDrip->p_Next != NULL) - newClDrip->p_Next->p_Prev = newClDrip; - FirstChainDrip.p_Next = newClDrip; - - dripcounter++; - } - else - { - gEngfuncs.Con_Printf( "Rain error: Drip limit overflow!\n" ); - return; - } - } - - if (RainInfo) // print debug info - { - gEngfuncs.Con_Printf( "Rain info: Drips exist: %i\n", dripcounter ); - gEngfuncs.Con_Printf( "Rain info: FX's exist: %i\n", fxcounter ); - gEngfuncs.Con_Printf( "Rain info: Attempted/Dropped: %i, %i\n", debug_attempted, debug_dropped); - if (debug_howmany) - { - float ave = debug_lifetime / (float)debug_howmany; - gEngfuncs.Con_Printf( "Rain info: Average drip life time: %f\n", ave); - } - else - gEngfuncs.Con_Printf( "Rain info: Average drip life time: --\n"); - } - return; -} - -/* -================================= -WaterLandingEffect -================================= -*/ -void WaterLandingEffect(cl_drip *drip) -{ - if (fxcounter >= MAXFX) - { - gEngfuncs.Con_Printf( "Rain error: FX limit overflow!\n" ); - return; - } - - cl_rainfx *newFX = new cl_rainfx; - if (!newFX) - { - gEngfuncs.Con_Printf( "Rain error: failed to allocate FX object!\n"); - return; - } - - newFX->alpha = gEngfuncs.pfnRandomFloat(0.6, 0.9); - VectorCopy(drip->origin, newFX->origin); - newFX->origin[2] = drip->minHeight; // correct position - - newFX->birthTime = gEngfuncs.GetClientTime(); - newFX->life = gEngfuncs.pfnRandomFloat(0.7, 1); - - // add to first place in chain - newFX->p_Next = FirstChainFX.p_Next; - newFX->p_Prev = &FirstChainFX; - if (newFX->p_Next != NULL) - newFX->p_Next->p_Prev = newFX; - FirstChainFX.p_Next = newFX; - - fxcounter++; -} - -/* -================================= -ProcessFXObjects - -Remove all fx objects with out time to live -Call every frame before ProcessRain -================================= -*/ -void ProcessFXObjects( void ) -{ - float curtime = gEngfuncs.GetClientTime(); - - cl_rainfx* curFX = FirstChainFX.p_Next; - cl_rainfx* nextFX = NULL; - - while (curFX != NULL) // go through FX objects list - { - nextFX = curFX->p_Next; // save pointer to next - - // delete current? - if ((curFX->birthTime + curFX->life) < curtime) - { - curFX->p_Prev->p_Next = curFX->p_Next; // link chain - if (nextFX != NULL) - nextFX->p_Prev = curFX->p_Prev; - delete curFX; - fxcounter--; - } - curFX = nextFX; // restore pointer - } -} - -/* -================================= -ResetRain -clear memory, delete all objects -================================= -*/ -void ResetRain( void ) -{ -// delete all drips - cl_drip* delDrip = FirstChainDrip.p_Next; - FirstChainDrip.p_Next = NULL; - - while (delDrip != NULL) - { - cl_drip* nextDrip = delDrip->p_Next; // save pointer to next drip in chain - delete delDrip; - delDrip = nextDrip; // restore pointer - dripcounter--; - } -// delete all FX objects - cl_rainfx* delFX = FirstChainFX.p_Next; - FirstChainFX.p_Next = NULL; - - while (delFX != NULL) - { - cl_rainfx* nextFX = delFX->p_Next; - delete delFX; - delFX = nextFX; - fxcounter--; - } - - InitRain(); - return; -} - -/* -================================= -InitRain -initialze system -================================= -*/ -void InitRain( void ) -{ - Rain.dripsPerSecond = 0; - Rain.distFromPlayer = 0; - Rain.windX = 0; - Rain.windY = 0; - Rain.randX = 0; - Rain.randY = 0; - Rain.weatherMode = 0; - Rain.globalHeight = 0; - - FirstChainDrip.birthTime = 0; - FirstChainDrip.minHeight = 0; - FirstChainDrip.origin[0]=0; - FirstChainDrip.origin[1]=0; - FirstChainDrip.origin[2]=0; - FirstChainDrip.alpha = 0; - FirstChainDrip.xDelta = 0; - FirstChainDrip.yDelta = 0; - FirstChainDrip.landInWater = 0; - FirstChainDrip.p_Next = NULL; - FirstChainDrip.p_Prev = NULL; - - FirstChainFX.alpha = 0; - FirstChainFX.birthTime = 0; - FirstChainFX.life = 0; - FirstChainFX.origin[0] = 0; - FirstChainFX.origin[1] = 0; - FirstChainFX.origin[2] = 0; - FirstChainFX.p_Next = NULL; - FirstChainFX.p_Prev = NULL; - - rain_oldtime = 0; - rain_curtime = 0; - rain_nextspawntime = 0; - - return; -} +/*** +* +* Copyright (c) 2005, BUzer. +* +* Used with permission for Spirit of Half-Life 1.5 +* +****/ +/* +====== rain.cpp ======================================================== +*/ + +#include +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "entity_types.h" +#include "cdll_int.h" +#include "pm_defs.h" +#include "event_api.h" + +#include "rain.h" + +void WaterLandingEffect(cl_drip *drip); + +rain_properties Rain; + +cl_drip FirstChainDrip; +cl_rainfx FirstChainFX; + +double rain_curtime; // current time +double rain_oldtime; // last time we have updated drips +double rain_timedelta; // difference between old time and current time +double rain_nextspawntime; // when the next drip should be spawned + +int dripcounter = 0; +int fxcounter = 0; +int RainInfo = 0; + +/* +================================= +ProcessRain + +Must think every frame. +================================= +*/ +void ProcessRain( void ) +{ + rain_oldtime = rain_curtime; // save old time + rain_curtime = gEngfuncs.GetClientTime(); + rain_timedelta = rain_curtime - rain_oldtime; + + // first frame + if (rain_oldtime == 0) + { + // fix first frame bug with nextspawntime + rain_nextspawntime = gEngfuncs.GetClientTime(); + return; + } + + if (Rain.dripsPerSecond == 0 && FirstChainDrip.p_Next == NULL) + { + // keep nextspawntime correct + rain_nextspawntime = rain_curtime; + return; + } + + if (rain_timedelta == 0) + return; // not in pause + + double timeBetweenDrips = 1 / (double)Rain.dripsPerSecond; + + cl_drip* curDrip = FirstChainDrip.p_Next; + cl_drip* nextDrip = NULL; + + + // save debug info + float debug_lifetime = 0; + int debug_howmany = 0; + int debug_attempted = 0; + int debug_dropped = 0; + + while (curDrip != NULL) // go through list + { + nextDrip = curDrip->p_Next; // save pointer to next drip + + if (Rain.weatherMode == 0) + curDrip->origin.z -= rain_timedelta * DRIPSPEED; // rain + else + curDrip->origin.z -= rain_timedelta * SNOWSPEED; // snow + + curDrip->origin.x += rain_timedelta * curDrip->xDelta; + curDrip->origin.y += rain_timedelta * curDrip->yDelta; + + // remove drip if its origin lower than minHeight + if (curDrip->origin.z < curDrip->minHeight) + { + if (curDrip->landInWater/* && Rain.weatherMode == 0*/) + WaterLandingEffect(curDrip); // create water rings + + if (RainInfo) + { + debug_lifetime += (rain_curtime - curDrip->birthTime); + debug_howmany++; + } + + curDrip->p_Prev->p_Next = curDrip->p_Next; // link chain + if (nextDrip != NULL) + nextDrip->p_Prev = curDrip->p_Prev; + delete curDrip; + + dripcounter--; + } + + curDrip = nextDrip; // restore pointer, so we can continue moving through chain + } + + int maxDelta; // maximum height randomize distance + float falltime; + if (Rain.weatherMode == 0) + { + maxDelta = DRIPSPEED * rain_timedelta; // for rain + falltime = (Rain.globalHeight + 4096) / DRIPSPEED; + } + else + { + maxDelta = SNOWSPEED * rain_timedelta; // for snow + falltime = (Rain.globalHeight + 4096) / SNOWSPEED; + } + + while (rain_nextspawntime < rain_curtime) + { + rain_nextspawntime += timeBetweenDrips; + if (RainInfo) + debug_attempted++; + + if (dripcounter < MAXDRIPS) // check for overflow + { + float deathHeight; + vec3_t vecStart, vecEnd; + + vecStart[0] = gEngfuncs.pfnRandomFloat(gHUD.m_vecOrigin.x - Rain.distFromPlayer, gHUD.m_vecOrigin.x + Rain.distFromPlayer); + vecStart[1] = gEngfuncs.pfnRandomFloat(gHUD.m_vecOrigin.y - Rain.distFromPlayer, gHUD.m_vecOrigin.y + Rain.distFromPlayer); + vecStart[2] = Rain.globalHeight; + + float xDelta = Rain.windX + gEngfuncs.pfnRandomFloat(Rain.randX * -1, Rain.randX); + float yDelta = Rain.windY + gEngfuncs.pfnRandomFloat(Rain.randY * -1, Rain.randY); + + // find a point at bottom of map + vecEnd[0] = falltime * xDelta; + vecEnd[1] = falltime * yDelta; + vecEnd[2] = -4096; + + pmtrace_t pmtrace; + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( vecStart, vecEnd, PM_STUDIO_IGNORE, -1, &pmtrace ); + + if (pmtrace.startsolid) + { + if (RainInfo) + debug_dropped++; + + continue; // drip cannot be placed + } + + // falling to water? + int contents = gEngfuncs.PM_PointContents( pmtrace.endpos, NULL ); + if (contents == CONTENTS_WATER) + { + int waterEntity = gEngfuncs.PM_WaterEntity( pmtrace.endpos ); + if ( waterEntity > 0 ) + { + cl_entity_t *pwater = gEngfuncs.GetEntityByIndex( waterEntity ); + if ( pwater && ( pwater->model != NULL ) ) + { + deathHeight = pwater->curstate.maxs[2]; + } + else + { + gEngfuncs.Con_Printf("Rain error: can't get water entity\n"); + continue; + } + } + else + { + gEngfuncs.Con_Printf("Rain error: water is not func_water entity\n"); + continue; + } + } + else + { + deathHeight = pmtrace.endpos[2]; + } + + // just in case.. + if (deathHeight > vecStart[2]) + { + gEngfuncs.Con_Printf("Rain error: can't create drip in water\n"); + continue; + } + + + cl_drip *newClDrip = new cl_drip; + if (!newClDrip) + { + Rain.dripsPerSecond = 0; // disable rain + gEngfuncs.Con_Printf( "Rain error: failed to allocate object!\n"); + return; + } + + vecStart[2] -= gEngfuncs.pfnRandomFloat(0, maxDelta); // randomize a bit + + newClDrip->alpha = gEngfuncs.pfnRandomFloat(0.12, 0.2); + VectorCopy(vecStart, newClDrip->origin); + + newClDrip->xDelta = xDelta; + newClDrip->yDelta = yDelta; + + newClDrip->birthTime = rain_curtime; // store time when it was spawned + newClDrip->minHeight = deathHeight; + + if (contents == CONTENTS_WATER) + newClDrip->landInWater = 1; + else + newClDrip->landInWater = 0; + + // add to first place in chain + newClDrip->p_Next = FirstChainDrip.p_Next; + newClDrip->p_Prev = &FirstChainDrip; + if (newClDrip->p_Next != NULL) + newClDrip->p_Next->p_Prev = newClDrip; + FirstChainDrip.p_Next = newClDrip; + + dripcounter++; + } + else + { + gEngfuncs.Con_Printf( "Rain error: Drip limit overflow!\n" ); + return; + } + } + + if (RainInfo) // print debug info + { + gEngfuncs.Con_Printf( "Rain info: Drips exist: %i\n", dripcounter ); + gEngfuncs.Con_Printf( "Rain info: FX's exist: %i\n", fxcounter ); + gEngfuncs.Con_Printf( "Rain info: Attempted/Dropped: %i, %i\n", debug_attempted, debug_dropped); + if (debug_howmany) + { + float ave = debug_lifetime / (float)debug_howmany; + gEngfuncs.Con_Printf( "Rain info: Average drip life time: %f\n", ave); + } + else + gEngfuncs.Con_Printf( "Rain info: Average drip life time: --\n"); + } + return; +} + +/* +================================= +WaterLandingEffect +================================= +*/ +void WaterLandingEffect(cl_drip *drip) +{ + if (fxcounter >= MAXFX) + { + gEngfuncs.Con_Printf( "Rain error: FX limit overflow!\n" ); + return; + } + + cl_rainfx *newFX = new cl_rainfx; + if (!newFX) + { + gEngfuncs.Con_Printf( "Rain error: failed to allocate FX object!\n"); + return; + } + + newFX->alpha = gEngfuncs.pfnRandomFloat(0.6, 0.9); + VectorCopy(drip->origin, newFX->origin); + newFX->origin[2] = drip->minHeight; // correct position + + newFX->birthTime = gEngfuncs.GetClientTime(); + newFX->life = gEngfuncs.pfnRandomFloat(0.7, 1); + + // add to first place in chain + newFX->p_Next = FirstChainFX.p_Next; + newFX->p_Prev = &FirstChainFX; + if (newFX->p_Next != NULL) + newFX->p_Next->p_Prev = newFX; + FirstChainFX.p_Next = newFX; + + fxcounter++; +} + +/* +================================= +ProcessFXObjects + +Remove all fx objects with out time to live +Call every frame before ProcessRain +================================= +*/ +void ProcessFXObjects( void ) +{ + float curtime = gEngfuncs.GetClientTime(); + + cl_rainfx* curFX = FirstChainFX.p_Next; + cl_rainfx* nextFX = NULL; + + while (curFX != NULL) // go through FX objects list + { + nextFX = curFX->p_Next; // save pointer to next + + // delete current? + if ((curFX->birthTime + curFX->life) < curtime) + { + curFX->p_Prev->p_Next = curFX->p_Next; // link chain + if (nextFX != NULL) + nextFX->p_Prev = curFX->p_Prev; + delete curFX; + fxcounter--; + } + curFX = nextFX; // restore pointer + } +} + +/* +================================= +ResetRain +clear memory, delete all objects +================================= +*/ +void ResetRain( void ) +{ +// delete all drips + cl_drip* delDrip = FirstChainDrip.p_Next; + FirstChainDrip.p_Next = NULL; + + while (delDrip != NULL) + { + cl_drip* nextDrip = delDrip->p_Next; // save pointer to next drip in chain + delete delDrip; + delDrip = nextDrip; // restore pointer + dripcounter--; + } +// delete all FX objects + cl_rainfx* delFX = FirstChainFX.p_Next; + FirstChainFX.p_Next = NULL; + + while (delFX != NULL) + { + cl_rainfx* nextFX = delFX->p_Next; + delete delFX; + delFX = nextFX; + fxcounter--; + } + + InitRain(); + return; +} + +/* +================================= +InitRain +initialze system +================================= +*/ +void InitRain( void ) +{ + Rain.dripsPerSecond = 0; + Rain.distFromPlayer = 0; + Rain.windX = 0; + Rain.windY = 0; + Rain.randX = 0; + Rain.randY = 0; + Rain.weatherMode = 0; + Rain.globalHeight = 0; + + FirstChainDrip.birthTime = 0; + FirstChainDrip.minHeight = 0; + FirstChainDrip.origin[0]=0; + FirstChainDrip.origin[1]=0; + FirstChainDrip.origin[2]=0; + FirstChainDrip.alpha = 0; + FirstChainDrip.xDelta = 0; + FirstChainDrip.yDelta = 0; + FirstChainDrip.landInWater = 0; + FirstChainDrip.p_Next = NULL; + FirstChainDrip.p_Prev = NULL; + + FirstChainFX.alpha = 0; + FirstChainFX.birthTime = 0; + FirstChainFX.life = 0; + FirstChainFX.origin[0] = 0; + FirstChainFX.origin[1] = 0; + FirstChainFX.origin[2] = 0; + FirstChainFX.p_Next = NULL; + FirstChainFX.p_Prev = NULL; + + rain_oldtime = 0; + rain_curtime = 0; + rain_nextspawntime = 0; + + return; +} diff --git a/cl_dll/studio/GameStudioModelRenderer.cpp b/cl_dll/studio/GameStudioModelRenderer.cpp index a026753..f058ca7 100644 --- a/cl_dll/studio/GameStudioModelRenderer.cpp +++ b/cl_dll/studio/GameStudioModelRenderer.cpp @@ -1,1091 +1,1091 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// Big thanks to Chicken Fortress developers -// for this code. -#include -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "com_model.h" -#include "studio.h" -#include "entity_state.h" -#include "cl_entity.h" -#include "dlight.h" -#include "triangleapi.h" - -#include -#include -#include -#include - -#include "studio_util.h" -#include "r_studioint.h" - -#include "StudioModelRenderer.h" -#include "GameStudioModelRenderer.h" -#include "pm_defs.h" - -#define ANIM_WALK_SEQUENCE 3 -#define ANIM_JUMP_SEQUENCE 6 -#define ANIM_SWIM_1 8 -#define ANIM_SWIM_2 9 -#define ANIM_FIRST_DEATH_SEQUENCE 101 -#define ANIM_LAST_DEATH_SEQUENCE 159 -#define ANIM_FIRST_EMOTION_SEQUENCE 198 -#define ANIM_LAST_EMOTION_SEQUENCE 207 - -CGameStudioModelRenderer g_StudioRenderer; - -int g_rseq; -int g_gaitseq; -vec3_t g_clorg; -vec3_t g_clang; - -void CounterStrike_GetSequence(int *seq, int *gaitseq) -{ - *seq = g_rseq; - *gaitseq = g_gaitseq; -} - -void CounterStrike_GetOrientation(float *o, float *a) -{ - VectorCopy(g_clorg, o); - VectorCopy(g_clang, a); -} - -float g_flStartScaleTime; -int iPrevRenderState; -int iRenderStateChanged; - -engine_studio_api_t IEngineStudio; - -static client_anim_state_t g_state; -static client_anim_state_t g_clientstate; - -CGameStudioModelRenderer::CGameStudioModelRenderer(void) -{ - m_bLocal = false; -} - -mstudioanim_t *CGameStudioModelRenderer::LookupAnimation(mstudioseqdesc_t *pseqdesc, int index) -{ - mstudioanim_t *panim = NULL; - - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - - if (index < 0) - return panim; - - if (index > (pseqdesc->numblends - 1)) - return panim; - - panim += index * m_pStudioHeader->numbones; - return panim; -} - -void CGameStudioModelRenderer::StudioSetupBones(void) -{ - int i; - double f; - - mstudiobone_t *pbones; - mstudioseqdesc_t *pseqdesc; - mstudioanim_t *panim; - - static float pos[MAXSTUDIOBONES][3]; - static vec4_t q[MAXSTUDIOBONES]; - float bonematrix[3][4]; - - static float pos2[MAXSTUDIOBONES][3]; - static vec4_t q2[MAXSTUDIOBONES]; - static float pos3[MAXSTUDIOBONES][3]; - static vec4_t q3[MAXSTUDIOBONES]; - static float pos4[MAXSTUDIOBONES][3]; - static vec4_t q4[MAXSTUDIOBONES]; - - if (!m_pCurrentEntity->player) - { - CStudioModelRenderer::StudioSetupBones(); - return; - } - - if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) - m_pCurrentEntity->curstate.sequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - - f = StudioEstimateFrame(pseqdesc); - - if (m_pPlayerInfo->gaitsequence == ANIM_WALK_SEQUENCE) - { - if (m_pCurrentEntity->curstate.blending[0] <= 26) - { - m_pCurrentEntity->curstate.blending[0] = 0; - m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; - } - else - { - m_pCurrentEntity->curstate.blending[0] -= 26; - m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; - } - } - - if (pseqdesc->numblends == 9) - { - float s = m_pCurrentEntity->curstate.blending[0]; - float t = m_pCurrentEntity->curstate.blending[1]; - - if (s <= 127.0) - { - s = (s * 2.0); - - if (t <= 127.0) - { - t = (t * 2.0); - - StudioCalcRotations(pos, q, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 1); - StudioCalcRotations(pos2, q2, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 3); - StudioCalcRotations(pos3, q3, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos4, q4, pseqdesc, panim, f); - } - else - { - t = 2.0 * (t - 127.0); - - panim = LookupAnimation(pseqdesc, 3); - StudioCalcRotations(pos, q, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos2, q2, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 6); - StudioCalcRotations(pos3, q3, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 7); - StudioCalcRotations(pos4, q4, pseqdesc, panim, f); - } - } - else - { - s = 2.0 * (s - 127.0); - - if (t <= 127.0) - { - t = (t * 2.0); - - panim = LookupAnimation(pseqdesc, 1); - StudioCalcRotations(pos, q, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 2); - StudioCalcRotations(pos2, q2, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos3, q3, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 5); - StudioCalcRotations(pos4, q4, pseqdesc, panim, f); - } - else - { - t = 2.0 * (t - 127.0); - - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos, q, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 5); - StudioCalcRotations(pos2, q2, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 7); - StudioCalcRotations(pos3, q3, pseqdesc, panim, f); - panim = LookupAnimation(pseqdesc, 8); - StudioCalcRotations(pos4, q4, pseqdesc, panim, f); - } - } - - s /= 255.0; - t /= 255.0; - - StudioSlerpBones(q, pos, q2, pos2, s); - StudioSlerpBones(q3, pos3, q4, pos4, s); - StudioSlerpBones(q, pos, q3, pos3, t); - } - else - { - StudioCalcRotations(pos, q, pseqdesc, panim, f); - } - - if (m_fDoInterp && m_pCurrentEntity->latched.sequencetime && (m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime) && (m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq)) - { - static float pos1b[MAXSTUDIOBONES][3]; - static vec4_t q1b[MAXSTUDIOBONES]; - float s = m_pCurrentEntity->latched.prevseqblending[0]; - float t = m_pCurrentEntity->latched.prevseqblending[1]; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - - if (pseqdesc->numblends == 9) - { - if (s <= 127.0) - { - s = (s * 2.0); - - if (t <= 127.0) - { - t = (t * 2.0); - - StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 1); - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 3); - StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - } - else - { - t = 2.0 * (t - 127.0); - - panim = LookupAnimation(pseqdesc, 3); - StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 6); - StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 7); - StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - } - } - else - { - s = 2.0 * (s - 127.0); - - if (t <= 127.0) - { - t = (t * 2.0); - - panim = LookupAnimation(pseqdesc, 1); - StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 2); - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 5); - StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - } - else - { - t = 2.0 * (t - 127.0); - - panim = LookupAnimation(pseqdesc, 4); - StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 5); - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 7); - StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - panim = LookupAnimation(pseqdesc, 8); - StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - } - } - - s /= 255.0; - t /= 255.0; - - StudioSlerpBones(q1b, pos1b, q2, pos2, s); - StudioSlerpBones(q3, pos3, q4, pos4, s); - StudioSlerpBones(q1b, pos1b, q3, pos3, t); - } - else - { - StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - } - - s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; - StudioSlerpBones(q, pos, q1b, pos1b, s); - } - else - { - m_pCurrentEntity->latched.prevframe = f; - } - - pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - if (m_pPlayerInfo && (m_pCurrentEntity->curstate.sequence < ANIM_FIRST_DEATH_SEQUENCE || m_pCurrentEntity->curstate.sequence > ANIM_LAST_DEATH_SEQUENCE) && (m_pCurrentEntity->curstate.sequence < ANIM_FIRST_EMOTION_SEQUENCE || m_pCurrentEntity->curstate.sequence > ANIM_LAST_EMOTION_SEQUENCE) && m_pCurrentEntity->curstate.sequence != ANIM_SWIM_1 && m_pCurrentEntity->curstate.sequence != ANIM_SWIM_2) - { - int copy = 1; - - if (m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq) - m_pPlayerInfo->gaitsequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex ) + m_pPlayerInfo->gaitsequence; - - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe); - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - if (!strcmp(pbones[i].name, "Bip01 Spine")) - copy = 0; - else if (!strcmp(pbones[pbones[i].parent].name, "Bip01 Pelvis")) - copy = 1; - - if (copy) - { - memcpy(pos[i], pos2[i], sizeof(pos[i])); - memcpy(q[i], q2[i], sizeof(q[i])); - } - } - } - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - QuaternionMatrix(q[i], bonematrix); - - bonematrix[0][3] = pos[i][0]; - bonematrix[1][3] = pos[i][1]; - bonematrix[2][3] = pos[i][2]; - - if (pbones[i].parent == -1) - { - if (IEngineStudio.IsHardware()) - { - ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); - MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]); - } - else - { - ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); - ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); - } - - StudioFxTransform(m_pCurrentEntity, (*m_pbonetransform)[i]); - } - else - { - ConcatTransforms((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); - ConcatTransforms((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); - } - } -} - -void CGameStudioModelRenderer::StudioEstimateGait(entity_state_t *pplayer) -{ - float dt; - vec3_t est_velocity; - - dt = (m_clTime - m_clOldTime); - dt = max(0.0, dt); - dt = min(1.0, dt); - - if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount) - { - m_flGaitMovement = 0; - return; - } - - if (m_fGaitEstimation) - { - VectorSubtract(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity); - VectorCopy(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin); - m_flGaitMovement = est_velocity.Length(); - - if (dt <= 0 || m_flGaitMovement / dt < 5) - { - m_flGaitMovement = 0; - est_velocity[0] = 0; - est_velocity[1] = 0; - } - } - else - { - VectorCopy(pplayer->velocity, est_velocity); - m_flGaitMovement = est_velocity.Length() * dt; - } - - if (est_velocity[1] == 0 && est_velocity[0] == 0) - { - float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; - flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; - - if (flYawDiff > 180) - flYawDiff -= 360; - - if (flYawDiff < -180) - flYawDiff += 360; - - if (dt < 0.25) - flYawDiff *= dt * 4; - else - flYawDiff *= dt; - - m_pPlayerInfo->gaityaw += flYawDiff; - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360; - - m_flGaitMovement = 0; - } - else - { - m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); - - if (m_pPlayerInfo->gaityaw > 180) - m_pPlayerInfo->gaityaw = 180; - - if (m_pPlayerInfo->gaityaw < -180) - m_pPlayerInfo->gaityaw = -180; - } -} - -void CGameStudioModelRenderer::StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch) -{ - float range = 45.0; - - *pBlend = (*pPitch * 3); - - if (*pBlend <= -range) - *pBlend = 255; - else if (*pBlend >= range) - *pBlend = 0; - else - *pBlend = 255 * (range - *pBlend) / (2 * range); - - *pPitch = 0; -} - -void CGameStudioModelRenderer::CalculatePitchBlend(entity_state_t *pplayer) -{ - mstudioseqdesc_t *pseqdesc; - int iBlend; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; - - StudioPlayerBlend(pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH]); - - m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH]; - m_pCurrentEntity->curstate.blending[1] = iBlend; - m_pCurrentEntity->latched.prevblending[1] = m_pCurrentEntity->curstate.blending[1]; - m_pCurrentEntity->latched.prevseqblending[1] = m_pCurrentEntity->curstate.blending[1]; -} - -void CGameStudioModelRenderer::CalculateYawBlend(entity_state_t *pplayer) -{ - float dt; - float flYaw; - - dt = (m_clTime - m_clOldTime); - dt = max(0.0, dt); - dt = min(1.0, dt); - - StudioEstimateGait(pplayer); - - flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; - flYaw = fmod(flYaw, 360.0f); - - if (flYaw < -180) - flYaw = flYaw + 360; - else if (flYaw > 180) - flYaw = flYaw - 360; - - float maxyaw = 120.0; - - if (flYaw > maxyaw) - { - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180; - m_flGaitMovement = -m_flGaitMovement; - flYaw = flYaw - 180; - } - else if (flYaw < -maxyaw) - { - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180; - m_flGaitMovement = -m_flGaitMovement; - flYaw = flYaw + 180; - } - - float blend_yaw = (flYaw / 90.0) * 128.0 + 127.0; - - blend_yaw = min(255.0, blend_yaw); - blend_yaw = max(0.0, blend_yaw); - - blend_yaw = 255.0 - blend_yaw; - - m_pCurrentEntity->curstate.blending[0] = (int)(blend_yaw); - m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0]; - m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; - - m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw; - - if (m_pCurrentEntity->angles[YAW] < -0) - m_pCurrentEntity->angles[YAW] += 360; - - m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW]; -} - -void CGameStudioModelRenderer::StudioProcessGait(entity_state_t *pplayer) -{ - mstudioseqdesc_t *pseqdesc; - float dt; - - CalculateYawBlend(pplayer); - CalculatePitchBlend(pplayer); - - dt = (m_clTime - m_clOldTime); - dt = max(0.0, dt); - dt = min(1.0, dt); - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence; - - if (pseqdesc->linearmovement[0] > 0) - m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes; - else - m_pPlayerInfo->gaitframe += pseqdesc->fps * dt * m_pCurrentEntity->curstate.framerate; - - m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes; - - if (m_pPlayerInfo->gaitframe < 0) - m_pPlayerInfo->gaitframe += pseqdesc->numframes; -} - -void CGameStudioModelRenderer::SavePlayerState(entity_state_t *pplayer) -{ - client_anim_state_t *st; - cl_entity_t *ent = IEngineStudio.GetCurrentEntity(); - - if (!ent) - return; - - st = &g_state; - - VectorCopy(ent->curstate.angles, st->angles); - VectorCopy(ent->curstate.origin, st->origin); - - VectorCopy(ent->angles, st->realangles); - - st->sequence = ent->curstate.sequence; - st->gaitsequence = pplayer->gaitsequence; - st->animtime = ent->curstate.animtime; - st->frame = ent->curstate.frame; - st->framerate = ent->curstate.framerate; - - memcpy(st->blending, ent->curstate.blending, 2); - memcpy(st->controller, ent->curstate.controller, 4); - - st->lv = ent->latched; -} - -void GetSequenceInfo(void *pmodel, client_anim_state_t *pev, float *pflFrameRate, float *pflGroundSpeed) -{ - studiohdr_t *pstudiohdr; - pstudiohdr = (studiohdr_t *)pmodel; - - if (!pstudiohdr) - return; - - mstudioseqdesc_t *pseqdesc; - - if (pev->sequence >= pstudiohdr->numseq) - { - *pflFrameRate = 0.0; - *pflGroundSpeed = 0.0; - return; - } - - pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence; - - if (pseqdesc->numframes > 1) - { - *pflFrameRate = 256 * pseqdesc->fps / (pseqdesc->numframes - 1); - *pflGroundSpeed = sqrt(pseqdesc->linearmovement[0] * pseqdesc->linearmovement[0] + pseqdesc->linearmovement[1] * pseqdesc->linearmovement[1] + pseqdesc->linearmovement[2] * pseqdesc->linearmovement[2]); - *pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1); - } - else - { - *pflFrameRate = 256.0; - *pflGroundSpeed = 0.0; - } -} - -int GetSequenceFlags(void *pmodel, client_anim_state_t *pev) -{ - studiohdr_t *pstudiohdr; - pstudiohdr = (studiohdr_t *)pmodel; - - if (!pstudiohdr || pev->sequence >= pstudiohdr->numseq) - return 0; - - mstudioseqdesc_t *pseqdesc; - pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence; - - return pseqdesc->flags; -} - -float StudioFrameAdvance(client_anim_state_t *st, float framerate, float flInterval) -{ - if (flInterval == 0.0) - { - flInterval = (gEngfuncs.GetClientTime() - st->animtime); - - if (flInterval <= 0.001) - { - st->animtime = gEngfuncs.GetClientTime(); - return 0.0; - } - } - - if (!st->animtime) - flInterval = 0.0; - - st->frame += flInterval * framerate * st->framerate; - st->animtime = gEngfuncs.GetClientTime(); - - if (st->frame < 0.0 || st->frame >= 256.0) - { - if (st->m_fSequenceLoops) - st->frame -= (int)(st->frame / 256.0) * 256.0; - else - st->frame = (st->frame < 0.0) ? 0 : 255; - - st->m_fSequenceFinished = TRUE; - } - - return flInterval; -} - -void CGameStudioModelRenderer::SetupClientAnimation(entity_state_t *pplayer) -{ - static double oldtime; - double curtime, dt; - - client_anim_state_t *st; - float fr, gs; - - cl_entity_t *ent = IEngineStudio.GetCurrentEntity(); - - if (!ent) - return; - - curtime = gEngfuncs.GetClientTime(); - dt = curtime - oldtime; - dt = min(1.0, max(0.0, dt)); - - oldtime = curtime; - st = &g_clientstate; - - st->framerate = 1.0; - - int oldseq = st->sequence; - CounterStrike_GetSequence(&st->sequence, &st->gaitsequence); - CounterStrike_GetOrientation((float *)&st->origin, (float *)&st->angles); - VectorCopy(st->angles, st->realangles); - - if (st->sequence != oldseq) - { - st->frame = 0.0; - st->lv.prevsequence = oldseq; - st->lv.sequencetime = st->animtime; - - memcpy(st->lv.prevseqblending, st->blending, 2); - memcpy(st->lv.prevcontroller, st->controller, 4); - } - - void *pmodel = (studiohdr_t *)IEngineStudio.Mod_Extradata(ent->model); - - GetSequenceInfo(pmodel, st, &fr, &gs); - st->m_fSequenceLoops = ((GetSequenceFlags(pmodel, st) & STUDIO_LOOPING) != 0); - StudioFrameAdvance(st, fr, dt); - - VectorCopy(st->realangles, ent->angles); - VectorCopy(st->angles, ent->curstate.angles); - VectorCopy(st->origin, ent->curstate.origin); - - ent->curstate.sequence = st->sequence; - pplayer->gaitsequence = st->gaitsequence; - ent->curstate.animtime = st->animtime; - ent->curstate.frame = st->frame; - ent->curstate.framerate = st->framerate; - - memcpy(ent->curstate.blending, st->blending, 2); - memcpy(ent->curstate.controller, st->controller, 4); - - ent->latched = st->lv; -} - -void CGameStudioModelRenderer::RestorePlayerState(entity_state_t *pplayer) -{ - client_anim_state_t *st; - cl_entity_t *ent = IEngineStudio.GetCurrentEntity(); - - if (!ent) - return; - - st = &g_clientstate; - - VectorCopy(ent->curstate.angles, st->angles); - VectorCopy(ent->curstate.origin, st->origin); - VectorCopy(ent->angles, st->realangles); - - st->sequence = ent->curstate.sequence; - st->gaitsequence = pplayer->gaitsequence; - st->animtime = ent->curstate.animtime; - st->frame = ent->curstate.frame; - st->framerate = ent->curstate.framerate; - - memcpy(st->blending, ent->curstate.blending, 2); - memcpy(st->controller, ent->curstate.controller, 4); - - st->lv = ent->latched; - - st = &g_state; - - VectorCopy(st->angles, ent->curstate.angles); - VectorCopy(st->origin, ent->curstate.origin); - VectorCopy(st->realangles, ent->angles); - - ent->curstate.sequence = st->sequence; - pplayer->gaitsequence = st->gaitsequence; - ent->curstate.animtime = st->animtime; - ent->curstate.frame = st->frame; - ent->curstate.framerate = st->framerate; - - memcpy(ent->curstate.blending, st->blending, 2); - memcpy(ent->curstate.controller, st->controller, 4); - - ent->latched = st->lv; -} - -int CGameStudioModelRenderer::StudioDrawPlayer(int flags, entity_state_t *pplayer) -{ - int iret = 0; - bool isLocalPlayer = false; - - if (m_bLocal && IEngineStudio.GetCurrentEntity() == gEngfuncs.GetLocalPlayer()) - isLocalPlayer = true; - - if (isLocalPlayer) - { - SavePlayerState(pplayer); - SetupClientAnimation(pplayer); - } - - iret = _StudioDrawPlayer(flags, pplayer); - - if (isLocalPlayer) - RestorePlayerState(pplayer); - - if( gHUD.cl_shadows->value != 0.0f ) - { - Vector chestpos; - - for( int i = 0; i < m_nCachedBones; i++ ) - { - if( !stricmp(m_nCachedBoneNames[i], "Bip01 Spine3") ) - { - chestpos.x = m_rgCachedBoneTransform[i][0][3]; - chestpos.y = m_rgCachedBoneTransform[i][1][3]; - chestpos.z = m_rgCachedBoneTransform[i][2][3]; - StudioDrawShadow(chestpos, 20.0f); - break; - } - } - } - - return iret; -} - -bool WeaponHasAttachments(entity_state_t *pplayer) -{ - studiohdr_t *modelheader = NULL; - model_t *pweaponmodel; - - if (!pplayer) - return false; - - pweaponmodel = IEngineStudio.GetModelByIndex(pplayer->weaponmodel); - modelheader = (studiohdr_t *)IEngineStudio.Mod_Extradata(pweaponmodel); - - return (modelheader->numattachments != 0); -} - -int CGameStudioModelRenderer::_StudioDrawPlayer(int flags, entity_state_t *pplayer) -{ - m_pCurrentEntity = IEngineStudio.GetCurrentEntity(); - - IEngineStudio.GetTimes(&m_nFrameCount, &m_clTime, &m_clOldTime); - IEngineStudio.GetViewInfo(m_vRenderOrigin, m_vUp, m_vRight, m_vNormal); - IEngineStudio.GetAliasScale(&m_fSoftwareXScale, &m_fSoftwareYScale); - - m_nPlayerIndex = pplayer->number - 1; - - if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients()) - return 0; - - m_pRenderModel = IEngineStudio.SetupPlayerModel(m_nPlayerIndex); - - if (m_pRenderModel == NULL) - return 0; - - m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(m_pRenderModel); - IEngineStudio.StudioSetHeader(m_pStudioHeader); - IEngineStudio.SetRenderModel(m_pRenderModel); - - if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) - m_pCurrentEntity->curstate.sequence = 0; - - if (pplayer->sequence >= m_pStudioHeader->numseq) - pplayer->sequence = 0; - - if (m_pCurrentEntity->curstate.gaitsequence >= m_pStudioHeader->numseq) - m_pCurrentEntity->curstate.gaitsequence = 0; - - if (pplayer->gaitsequence >= m_pStudioHeader->numseq) - pplayer->gaitsequence = 0; - - if (pplayer->gaitsequence) - { - vec3_t orig_angles; - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - - VectorCopy(m_pCurrentEntity->angles, orig_angles); - - StudioProcessGait(pplayer); - - m_pPlayerInfo->gaitsequence = pplayer->gaitsequence; - m_pPlayerInfo = NULL; - - StudioSetUpTransform(0); - VectorCopy(orig_angles, m_pCurrentEntity->angles); - } - else - { - m_pCurrentEntity->curstate.controller[0] = 127; - m_pCurrentEntity->curstate.controller[1] = 127; - m_pCurrentEntity->curstate.controller[2] = 127; - m_pCurrentEntity->curstate.controller[3] = 127; - m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0]; - m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1]; - m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2]; - m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3]; - - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - - CalculatePitchBlend(pplayer); - CalculateYawBlend(pplayer); - - m_pPlayerInfo->gaitsequence = 0; - StudioSetUpTransform(0); - } - - if (flags & STUDIO_RENDER) - { - (*m_pModelsDrawn)++; - (*m_pStudioModelCount)++; - - if (m_pStudioHeader->numbodyparts == 0) - return 1; - } - - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - - StudioSetupBones(); - StudioSaveBones(); - - m_pPlayerInfo->renderframe = m_nFrameCount; - m_pPlayerInfo = NULL; - - if (flags & STUDIO_EVENTS && (!(flags & STUDIO_RENDER) || !pplayer->weaponmodel || !WeaponHasAttachments(pplayer))) - { - StudioCalcAttachments(); - IEngineStudio.StudioClientEvents(); - - if (m_pCurrentEntity->index > 0) - { - cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index); - memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * 4); - } - } - - if (flags & STUDIO_RENDER) - { - alight_t lighting; - vec3_t dir; - - lighting.plightvec = dir; - - IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting); - IEngineStudio.StudioEntityLight(&lighting); - IEngineStudio.StudioSetupLighting(&lighting); - - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - m_nTopColor = m_pPlayerInfo->topcolor; - - if (m_nTopColor < 0) - m_nTopColor = 0; - - if (m_nTopColor > 360) - m_nTopColor = 360; - - m_nBottomColor = m_pPlayerInfo->bottomcolor; - - if (m_nBottomColor < 0) - m_nBottomColor = 0; - - if (m_nBottomColor > 360) - m_nBottomColor = 360; - - IEngineStudio.StudioSetRemapColors(m_nTopColor, m_nBottomColor); - - StudioRenderModel(dir); - m_pPlayerInfo = NULL; - - if (pplayer->weaponmodel) - { - studiohdr_t *saveheader = m_pStudioHeader; - cl_entity_t saveent = *m_pCurrentEntity; - - model_t *pweaponmodel = IEngineStudio.GetModelByIndex(pplayer->weaponmodel); - - m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(pweaponmodel); - IEngineStudio.StudioSetHeader(m_pStudioHeader); - - StudioMergeBones(pweaponmodel); - - IEngineStudio.StudioSetupLighting(&lighting); - - StudioRenderModel(dir); - - StudioCalcAttachments(); - - if (m_pCurrentEntity->index > 0) - memcpy(saveent.attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * m_pStudioHeader->numattachments); - - *m_pCurrentEntity = saveent; - m_pStudioHeader = saveheader; - IEngineStudio.StudioSetHeader(m_pStudioHeader); - - if (flags & STUDIO_EVENTS) - IEngineStudio.StudioClientEvents(); - } - } - - return 1; -} - - -void CGameStudioModelRenderer::StudioFxTransform(cl_entity_t *ent, float transform[3][4]) -{ - switch (ent->curstate.renderfx) - { - case kRenderFxDistort: - case kRenderFxHologram: - { - if (gEngfuncs.pfnRandomLong(0, 49) == 0) - { - int axis = gEngfuncs.pfnRandomLong(0, 1); - - if (axis == 1) - axis = 2; - VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] ); - } - else if (gEngfuncs.pfnRandomLong(0, 49) == 0) - { - float offset; - int axis = gEngfuncs.pfnRandomLong(0, 1); - - if (axis == 1) - axis = 2; - - offset = gEngfuncs.pfnRandomFloat(-10, 10); - transform[gEngfuncs.pfnRandomLong(0, 2)][3] += offset; - } - - break; - } - - case kRenderFxExplode: - { - if (iRenderStateChanged) - { - g_flStartScaleTime = m_clTime; - iRenderStateChanged = FALSE; - } - - float flTimeDelta = m_clTime - g_flStartScaleTime; - - if (flTimeDelta > 0) - { - float flScale = 0.001; - - if (flTimeDelta <= 2.0) - flScale = 1.0 - (flTimeDelta / 2.0); - - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 3; j++) - transform[i][j] *= flScale; - } - } - - break; - } - } -} - -void R_StudioInit(void) -{ - g_StudioRenderer.Init(); -} - -int R_StudioDrawPlayer(int flags, entity_state_t *pplayer) -{ - return g_StudioRenderer.StudioDrawPlayer(flags, pplayer); -} - -int R_StudioDrawModel(int flags) -{ - return g_StudioRenderer.StudioDrawModel(flags); -} -// The simple drawing interface we'll pass back to the engine -r_studio_interface_t studio = -{ - STUDIO_INTERFACE_VERSION, - R_StudioDrawModel, - R_StudioDrawPlayer, -}; - -#ifdef _WIN32 -#define DLLEXPORT __declspec( dllexport ) -#else -#define DLLEXPORT -#endif - -/* -==================== -HUD_GetStudioModelInterface -Export this function for the engine to use the studio renderer class to render objects. -==================== -*/ -extern "C" int DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio ) -{ - if ( version != STUDIO_INTERFACE_VERSION ) - return 0; - - // Point the engine to our callbacks - *ppinterface = &studio; - - // Copy in engine helper functions - memcpy( &IEngineStudio, pstudio, sizeof( IEngineStudio ) ); - - // Initialize local variables, etc. - R_StudioInit(); - - // Success - return 1; -} - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// Big thanks to Chicken Fortress developers +// for this code. +#include +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "com_model.h" +#include "studio.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "dlight.h" +#include "triangleapi.h" + +#include +#include +#include +#include + +#include "studio_util.h" +#include "r_studioint.h" + +#include "StudioModelRenderer.h" +#include "GameStudioModelRenderer.h" +#include "pm_defs.h" + +#define ANIM_WALK_SEQUENCE 3 +#define ANIM_JUMP_SEQUENCE 6 +#define ANIM_SWIM_1 8 +#define ANIM_SWIM_2 9 +#define ANIM_FIRST_DEATH_SEQUENCE 101 +#define ANIM_LAST_DEATH_SEQUENCE 159 +#define ANIM_FIRST_EMOTION_SEQUENCE 198 +#define ANIM_LAST_EMOTION_SEQUENCE 207 + +CGameStudioModelRenderer g_StudioRenderer; + +int g_rseq; +int g_gaitseq; +vec3_t g_clorg; +vec3_t g_clang; + +void CounterStrike_GetSequence(int *seq, int *gaitseq) +{ + *seq = g_rseq; + *gaitseq = g_gaitseq; +} + +void CounterStrike_GetOrientation(float *o, float *a) +{ + VectorCopy(g_clorg, o); + VectorCopy(g_clang, a); +} + +float g_flStartScaleTime; +int iPrevRenderState; +int iRenderStateChanged; + +engine_studio_api_t IEngineStudio; + +static client_anim_state_t g_state; +static client_anim_state_t g_clientstate; + +CGameStudioModelRenderer::CGameStudioModelRenderer(void) +{ + m_bLocal = false; +} + +mstudioanim_t *CGameStudioModelRenderer::LookupAnimation(mstudioseqdesc_t *pseqdesc, int index) +{ + mstudioanim_t *panim = NULL; + + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + + if (index < 0) + return panim; + + if (index > (pseqdesc->numblends - 1)) + return panim; + + panim += index * m_pStudioHeader->numbones; + return panim; +} + +void CGameStudioModelRenderer::StudioSetupBones(void) +{ + int i; + double f; + + mstudiobone_t *pbones; + mstudioseqdesc_t *pseqdesc; + mstudioanim_t *panim; + + static float pos[MAXSTUDIOBONES][3]; + static vec4_t q[MAXSTUDIOBONES]; + float bonematrix[3][4]; + + static float pos2[MAXSTUDIOBONES][3]; + static vec4_t q2[MAXSTUDIOBONES]; + static float pos3[MAXSTUDIOBONES][3]; + static vec4_t q3[MAXSTUDIOBONES]; + static float pos4[MAXSTUDIOBONES][3]; + static vec4_t q4[MAXSTUDIOBONES]; + + if (!m_pCurrentEntity->player) + { + CStudioModelRenderer::StudioSetupBones(); + return; + } + + if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) + m_pCurrentEntity->curstate.sequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + + f = StudioEstimateFrame(pseqdesc); + + if (m_pPlayerInfo->gaitsequence == ANIM_WALK_SEQUENCE) + { + if (m_pCurrentEntity->curstate.blending[0] <= 26) + { + m_pCurrentEntity->curstate.blending[0] = 0; + m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; + } + else + { + m_pCurrentEntity->curstate.blending[0] -= 26; + m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; + } + } + + if (pseqdesc->numblends == 9) + { + float s = m_pCurrentEntity->curstate.blending[0]; + float t = m_pCurrentEntity->curstate.blending[1]; + + if (s <= 127.0) + { + s = (s * 2.0); + + if (t <= 127.0) + { + t = (t * 2.0); + + StudioCalcRotations(pos, q, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 1); + StudioCalcRotations(pos2, q2, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 3); + StudioCalcRotations(pos3, q3, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos4, q4, pseqdesc, panim, f); + } + else + { + t = 2.0 * (t - 127.0); + + panim = LookupAnimation(pseqdesc, 3); + StudioCalcRotations(pos, q, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos2, q2, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 6); + StudioCalcRotations(pos3, q3, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 7); + StudioCalcRotations(pos4, q4, pseqdesc, panim, f); + } + } + else + { + s = 2.0 * (s - 127.0); + + if (t <= 127.0) + { + t = (t * 2.0); + + panim = LookupAnimation(pseqdesc, 1); + StudioCalcRotations(pos, q, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 2); + StudioCalcRotations(pos2, q2, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos3, q3, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 5); + StudioCalcRotations(pos4, q4, pseqdesc, panim, f); + } + else + { + t = 2.0 * (t - 127.0); + + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos, q, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 5); + StudioCalcRotations(pos2, q2, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 7); + StudioCalcRotations(pos3, q3, pseqdesc, panim, f); + panim = LookupAnimation(pseqdesc, 8); + StudioCalcRotations(pos4, q4, pseqdesc, panim, f); + } + } + + s /= 255.0; + t /= 255.0; + + StudioSlerpBones(q, pos, q2, pos2, s); + StudioSlerpBones(q3, pos3, q4, pos4, s); + StudioSlerpBones(q, pos, q3, pos3, t); + } + else + { + StudioCalcRotations(pos, q, pseqdesc, panim, f); + } + + if (m_fDoInterp && m_pCurrentEntity->latched.sequencetime && (m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime) && (m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq)) + { + static float pos1b[MAXSTUDIOBONES][3]; + static vec4_t q1b[MAXSTUDIOBONES]; + float s = m_pCurrentEntity->latched.prevseqblending[0]; + float t = m_pCurrentEntity->latched.prevseqblending[1]; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + + if (pseqdesc->numblends == 9) + { + if (s <= 127.0) + { + s = (s * 2.0); + + if (t <= 127.0) + { + t = (t * 2.0); + + StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 1); + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 3); + StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + } + else + { + t = 2.0 * (t - 127.0); + + panim = LookupAnimation(pseqdesc, 3); + StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 6); + StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 7); + StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + } + } + else + { + s = 2.0 * (s - 127.0); + + if (t <= 127.0) + { + t = (t * 2.0); + + panim = LookupAnimation(pseqdesc, 1); + StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 2); + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 5); + StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + } + else + { + t = 2.0 * (t - 127.0); + + panim = LookupAnimation(pseqdesc, 4); + StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 5); + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 7); + StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + panim = LookupAnimation(pseqdesc, 8); + StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + } + } + + s /= 255.0; + t /= 255.0; + + StudioSlerpBones(q1b, pos1b, q2, pos2, s); + StudioSlerpBones(q3, pos3, q4, pos4, s); + StudioSlerpBones(q1b, pos1b, q3, pos3, t); + } + else + { + StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + } + + s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; + StudioSlerpBones(q, pos, q1b, pos1b, s); + } + else + { + m_pCurrentEntity->latched.prevframe = f; + } + + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + if (m_pPlayerInfo && (m_pCurrentEntity->curstate.sequence < ANIM_FIRST_DEATH_SEQUENCE || m_pCurrentEntity->curstate.sequence > ANIM_LAST_DEATH_SEQUENCE) && (m_pCurrentEntity->curstate.sequence < ANIM_FIRST_EMOTION_SEQUENCE || m_pCurrentEntity->curstate.sequence > ANIM_LAST_EMOTION_SEQUENCE) && m_pCurrentEntity->curstate.sequence != ANIM_SWIM_1 && m_pCurrentEntity->curstate.sequence != ANIM_SWIM_2) + { + int copy = 1; + + if (m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq) + m_pPlayerInfo->gaitsequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex ) + m_pPlayerInfo->gaitsequence; + + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe); + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + if (!strcmp(pbones[i].name, "Bip01 Spine")) + copy = 0; + else if (!strcmp(pbones[pbones[i].parent].name, "Bip01 Pelvis")) + copy = 1; + + if (copy) + { + memcpy(pos[i], pos2[i], sizeof(pos[i])); + memcpy(q[i], q2[i], sizeof(q[i])); + } + } + } + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + QuaternionMatrix(q[i], bonematrix); + + bonematrix[0][3] = pos[i][0]; + bonematrix[1][3] = pos[i][1]; + bonematrix[2][3] = pos[i][2]; + + if (pbones[i].parent == -1) + { + if (IEngineStudio.IsHardware()) + { + ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); + MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]); + } + else + { + ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); + ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); + } + + StudioFxTransform(m_pCurrentEntity, (*m_pbonetransform)[i]); + } + else + { + ConcatTransforms((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); + ConcatTransforms((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); + } + } +} + +void CGameStudioModelRenderer::StudioEstimateGait(entity_state_t *pplayer) +{ + float dt; + vec3_t est_velocity; + + dt = (m_clTime - m_clOldTime); + dt = max(0.0, dt); + dt = min(1.0, dt); + + if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount) + { + m_flGaitMovement = 0; + return; + } + + if (m_fGaitEstimation) + { + VectorSubtract(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity); + VectorCopy(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin); + m_flGaitMovement = est_velocity.Length(); + + if (dt <= 0 || m_flGaitMovement / dt < 5) + { + m_flGaitMovement = 0; + est_velocity[0] = 0; + est_velocity[1] = 0; + } + } + else + { + VectorCopy(pplayer->velocity, est_velocity); + m_flGaitMovement = est_velocity.Length() * dt; + } + + if (est_velocity[1] == 0 && est_velocity[0] == 0) + { + float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; + flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; + + if (flYawDiff > 180) + flYawDiff -= 360; + + if (flYawDiff < -180) + flYawDiff += 360; + + if (dt < 0.25) + flYawDiff *= dt * 4; + else + flYawDiff *= dt; + + m_pPlayerInfo->gaityaw += flYawDiff; + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360; + + m_flGaitMovement = 0; + } + else + { + m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); + + if (m_pPlayerInfo->gaityaw > 180) + m_pPlayerInfo->gaityaw = 180; + + if (m_pPlayerInfo->gaityaw < -180) + m_pPlayerInfo->gaityaw = -180; + } +} + +void CGameStudioModelRenderer::StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch) +{ + float range = 45.0; + + *pBlend = (*pPitch * 3); + + if (*pBlend <= -range) + *pBlend = 255; + else if (*pBlend >= range) + *pBlend = 0; + else + *pBlend = 255 * (range - *pBlend) / (2 * range); + + *pPitch = 0; +} + +void CGameStudioModelRenderer::CalculatePitchBlend(entity_state_t *pplayer) +{ + mstudioseqdesc_t *pseqdesc; + int iBlend; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; + + StudioPlayerBlend(pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH]); + + m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH]; + m_pCurrentEntity->curstate.blending[1] = iBlend; + m_pCurrentEntity->latched.prevblending[1] = m_pCurrentEntity->curstate.blending[1]; + m_pCurrentEntity->latched.prevseqblending[1] = m_pCurrentEntity->curstate.blending[1]; +} + +void CGameStudioModelRenderer::CalculateYawBlend(entity_state_t *pplayer) +{ + float dt; + float flYaw; + + dt = (m_clTime - m_clOldTime); + dt = max(0.0, dt); + dt = min(1.0, dt); + + StudioEstimateGait(pplayer); + + flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; + flYaw = fmod(flYaw, 360.0f); + + if (flYaw < -180) + flYaw = flYaw + 360; + else if (flYaw > 180) + flYaw = flYaw - 360; + + float maxyaw = 120.0; + + if (flYaw > maxyaw) + { + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180; + m_flGaitMovement = -m_flGaitMovement; + flYaw = flYaw - 180; + } + else if (flYaw < -maxyaw) + { + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180; + m_flGaitMovement = -m_flGaitMovement; + flYaw = flYaw + 180; + } + + float blend_yaw = (flYaw / 90.0) * 128.0 + 127.0; + + blend_yaw = min(255.0, blend_yaw); + blend_yaw = max(0.0, blend_yaw); + + blend_yaw = 255.0 - blend_yaw; + + m_pCurrentEntity->curstate.blending[0] = (int)(blend_yaw); + m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0]; + m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; + + m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw; + + if (m_pCurrentEntity->angles[YAW] < -0) + m_pCurrentEntity->angles[YAW] += 360; + + m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW]; +} + +void CGameStudioModelRenderer::StudioProcessGait(entity_state_t *pplayer) +{ + mstudioseqdesc_t *pseqdesc; + float dt; + + CalculateYawBlend(pplayer); + CalculatePitchBlend(pplayer); + + dt = (m_clTime - m_clOldTime); + dt = max(0.0, dt); + dt = min(1.0, dt); + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence; + + if (pseqdesc->linearmovement[0] > 0) + m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes; + else + m_pPlayerInfo->gaitframe += pseqdesc->fps * dt * m_pCurrentEntity->curstate.framerate; + + m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes; + + if (m_pPlayerInfo->gaitframe < 0) + m_pPlayerInfo->gaitframe += pseqdesc->numframes; +} + +void CGameStudioModelRenderer::SavePlayerState(entity_state_t *pplayer) +{ + client_anim_state_t *st; + cl_entity_t *ent = IEngineStudio.GetCurrentEntity(); + + if (!ent) + return; + + st = &g_state; + + VectorCopy(ent->curstate.angles, st->angles); + VectorCopy(ent->curstate.origin, st->origin); + + VectorCopy(ent->angles, st->realangles); + + st->sequence = ent->curstate.sequence; + st->gaitsequence = pplayer->gaitsequence; + st->animtime = ent->curstate.animtime; + st->frame = ent->curstate.frame; + st->framerate = ent->curstate.framerate; + + memcpy(st->blending, ent->curstate.blending, 2); + memcpy(st->controller, ent->curstate.controller, 4); + + st->lv = ent->latched; +} + +void GetSequenceInfo(void *pmodel, client_anim_state_t *pev, float *pflFrameRate, float *pflGroundSpeed) +{ + studiohdr_t *pstudiohdr; + pstudiohdr = (studiohdr_t *)pmodel; + + if (!pstudiohdr) + return; + + mstudioseqdesc_t *pseqdesc; + + if (pev->sequence >= pstudiohdr->numseq) + { + *pflFrameRate = 0.0; + *pflGroundSpeed = 0.0; + return; + } + + pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence; + + if (pseqdesc->numframes > 1) + { + *pflFrameRate = 256 * pseqdesc->fps / (pseqdesc->numframes - 1); + *pflGroundSpeed = sqrt(pseqdesc->linearmovement[0] * pseqdesc->linearmovement[0] + pseqdesc->linearmovement[1] * pseqdesc->linearmovement[1] + pseqdesc->linearmovement[2] * pseqdesc->linearmovement[2]); + *pflGroundSpeed = *pflGroundSpeed * pseqdesc->fps / (pseqdesc->numframes - 1); + } + else + { + *pflFrameRate = 256.0; + *pflGroundSpeed = 0.0; + } +} + +int GetSequenceFlags(void *pmodel, client_anim_state_t *pev) +{ + studiohdr_t *pstudiohdr; + pstudiohdr = (studiohdr_t *)pmodel; + + if (!pstudiohdr || pev->sequence >= pstudiohdr->numseq) + return 0; + + mstudioseqdesc_t *pseqdesc; + pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + (int)pev->sequence; + + return pseqdesc->flags; +} + +float StudioFrameAdvance(client_anim_state_t *st, float framerate, float flInterval) +{ + if (flInterval == 0.0) + { + flInterval = (gEngfuncs.GetClientTime() - st->animtime); + + if (flInterval <= 0.001) + { + st->animtime = gEngfuncs.GetClientTime(); + return 0.0; + } + } + + if (!st->animtime) + flInterval = 0.0; + + st->frame += flInterval * framerate * st->framerate; + st->animtime = gEngfuncs.GetClientTime(); + + if (st->frame < 0.0 || st->frame >= 256.0) + { + if (st->m_fSequenceLoops) + st->frame -= (int)(st->frame / 256.0) * 256.0; + else + st->frame = (st->frame < 0.0) ? 0 : 255; + + st->m_fSequenceFinished = TRUE; + } + + return flInterval; +} + +void CGameStudioModelRenderer::SetupClientAnimation(entity_state_t *pplayer) +{ + static double oldtime; + double curtime, dt; + + client_anim_state_t *st; + float fr, gs; + + cl_entity_t *ent = IEngineStudio.GetCurrentEntity(); + + if (!ent) + return; + + curtime = gEngfuncs.GetClientTime(); + dt = curtime - oldtime; + dt = min(1.0, max(0.0, dt)); + + oldtime = curtime; + st = &g_clientstate; + + st->framerate = 1.0; + + int oldseq = st->sequence; + CounterStrike_GetSequence(&st->sequence, &st->gaitsequence); + CounterStrike_GetOrientation((float *)&st->origin, (float *)&st->angles); + VectorCopy(st->angles, st->realangles); + + if (st->sequence != oldseq) + { + st->frame = 0.0; + st->lv.prevsequence = oldseq; + st->lv.sequencetime = st->animtime; + + memcpy(st->lv.prevseqblending, st->blending, 2); + memcpy(st->lv.prevcontroller, st->controller, 4); + } + + void *pmodel = (studiohdr_t *)IEngineStudio.Mod_Extradata(ent->model); + + GetSequenceInfo(pmodel, st, &fr, &gs); + st->m_fSequenceLoops = ((GetSequenceFlags(pmodel, st) & STUDIO_LOOPING) != 0); + StudioFrameAdvance(st, fr, dt); + + VectorCopy(st->realangles, ent->angles); + VectorCopy(st->angles, ent->curstate.angles); + VectorCopy(st->origin, ent->curstate.origin); + + ent->curstate.sequence = st->sequence; + pplayer->gaitsequence = st->gaitsequence; + ent->curstate.animtime = st->animtime; + ent->curstate.frame = st->frame; + ent->curstate.framerate = st->framerate; + + memcpy(ent->curstate.blending, st->blending, 2); + memcpy(ent->curstate.controller, st->controller, 4); + + ent->latched = st->lv; +} + +void CGameStudioModelRenderer::RestorePlayerState(entity_state_t *pplayer) +{ + client_anim_state_t *st; + cl_entity_t *ent = IEngineStudio.GetCurrentEntity(); + + if (!ent) + return; + + st = &g_clientstate; + + VectorCopy(ent->curstate.angles, st->angles); + VectorCopy(ent->curstate.origin, st->origin); + VectorCopy(ent->angles, st->realangles); + + st->sequence = ent->curstate.sequence; + st->gaitsequence = pplayer->gaitsequence; + st->animtime = ent->curstate.animtime; + st->frame = ent->curstate.frame; + st->framerate = ent->curstate.framerate; + + memcpy(st->blending, ent->curstate.blending, 2); + memcpy(st->controller, ent->curstate.controller, 4); + + st->lv = ent->latched; + + st = &g_state; + + VectorCopy(st->angles, ent->curstate.angles); + VectorCopy(st->origin, ent->curstate.origin); + VectorCopy(st->realangles, ent->angles); + + ent->curstate.sequence = st->sequence; + pplayer->gaitsequence = st->gaitsequence; + ent->curstate.animtime = st->animtime; + ent->curstate.frame = st->frame; + ent->curstate.framerate = st->framerate; + + memcpy(ent->curstate.blending, st->blending, 2); + memcpy(ent->curstate.controller, st->controller, 4); + + ent->latched = st->lv; +} + +int CGameStudioModelRenderer::StudioDrawPlayer(int flags, entity_state_t *pplayer) +{ + int iret = 0; + bool isLocalPlayer = false; + + if (m_bLocal && IEngineStudio.GetCurrentEntity() == gEngfuncs.GetLocalPlayer()) + isLocalPlayer = true; + + if (isLocalPlayer) + { + SavePlayerState(pplayer); + SetupClientAnimation(pplayer); + } + + iret = _StudioDrawPlayer(flags, pplayer); + + if (isLocalPlayer) + RestorePlayerState(pplayer); + + if( gHUD.cl_shadows->value != 0.0f ) + { + Vector chestpos; + + for( int i = 0; i < m_nCachedBones; i++ ) + { + if( !stricmp(m_nCachedBoneNames[i], "Bip01 Spine3") ) + { + chestpos.x = m_rgCachedBoneTransform[i][0][3]; + chestpos.y = m_rgCachedBoneTransform[i][1][3]; + chestpos.z = m_rgCachedBoneTransform[i][2][3]; + StudioDrawShadow(chestpos, 20.0f); + break; + } + } + } + + return iret; +} + +bool WeaponHasAttachments(entity_state_t *pplayer) +{ + studiohdr_t *modelheader = NULL; + model_t *pweaponmodel; + + if (!pplayer) + return false; + + pweaponmodel = IEngineStudio.GetModelByIndex(pplayer->weaponmodel); + modelheader = (studiohdr_t *)IEngineStudio.Mod_Extradata(pweaponmodel); + + return (modelheader->numattachments != 0); +} + +int CGameStudioModelRenderer::_StudioDrawPlayer(int flags, entity_state_t *pplayer) +{ + m_pCurrentEntity = IEngineStudio.GetCurrentEntity(); + + IEngineStudio.GetTimes(&m_nFrameCount, &m_clTime, &m_clOldTime); + IEngineStudio.GetViewInfo(m_vRenderOrigin, m_vUp, m_vRight, m_vNormal); + IEngineStudio.GetAliasScale(&m_fSoftwareXScale, &m_fSoftwareYScale); + + m_nPlayerIndex = pplayer->number - 1; + + if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients()) + return 0; + + m_pRenderModel = IEngineStudio.SetupPlayerModel(m_nPlayerIndex); + + if (m_pRenderModel == NULL) + return 0; + + m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(m_pRenderModel); + IEngineStudio.StudioSetHeader(m_pStudioHeader); + IEngineStudio.SetRenderModel(m_pRenderModel); + + if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) + m_pCurrentEntity->curstate.sequence = 0; + + if (pplayer->sequence >= m_pStudioHeader->numseq) + pplayer->sequence = 0; + + if (m_pCurrentEntity->curstate.gaitsequence >= m_pStudioHeader->numseq) + m_pCurrentEntity->curstate.gaitsequence = 0; + + if (pplayer->gaitsequence >= m_pStudioHeader->numseq) + pplayer->gaitsequence = 0; + + if (pplayer->gaitsequence) + { + vec3_t orig_angles; + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + + VectorCopy(m_pCurrentEntity->angles, orig_angles); + + StudioProcessGait(pplayer); + + m_pPlayerInfo->gaitsequence = pplayer->gaitsequence; + m_pPlayerInfo = NULL; + + StudioSetUpTransform(0); + VectorCopy(orig_angles, m_pCurrentEntity->angles); + } + else + { + m_pCurrentEntity->curstate.controller[0] = 127; + m_pCurrentEntity->curstate.controller[1] = 127; + m_pCurrentEntity->curstate.controller[2] = 127; + m_pCurrentEntity->curstate.controller[3] = 127; + m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0]; + m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1]; + m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2]; + m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3]; + + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + + CalculatePitchBlend(pplayer); + CalculateYawBlend(pplayer); + + m_pPlayerInfo->gaitsequence = 0; + StudioSetUpTransform(0); + } + + if (flags & STUDIO_RENDER) + { + (*m_pModelsDrawn)++; + (*m_pStudioModelCount)++; + + if (m_pStudioHeader->numbodyparts == 0) + return 1; + } + + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + + StudioSetupBones(); + StudioSaveBones(); + + m_pPlayerInfo->renderframe = m_nFrameCount; + m_pPlayerInfo = NULL; + + if (flags & STUDIO_EVENTS && (!(flags & STUDIO_RENDER) || !pplayer->weaponmodel || !WeaponHasAttachments(pplayer))) + { + StudioCalcAttachments(); + IEngineStudio.StudioClientEvents(); + + if (m_pCurrentEntity->index > 0) + { + cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index); + memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * 4); + } + } + + if (flags & STUDIO_RENDER) + { + alight_t lighting; + vec3_t dir; + + lighting.plightvec = dir; + + IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting); + IEngineStudio.StudioEntityLight(&lighting); + IEngineStudio.StudioSetupLighting(&lighting); + + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + m_nTopColor = m_pPlayerInfo->topcolor; + + if (m_nTopColor < 0) + m_nTopColor = 0; + + if (m_nTopColor > 360) + m_nTopColor = 360; + + m_nBottomColor = m_pPlayerInfo->bottomcolor; + + if (m_nBottomColor < 0) + m_nBottomColor = 0; + + if (m_nBottomColor > 360) + m_nBottomColor = 360; + + IEngineStudio.StudioSetRemapColors(m_nTopColor, m_nBottomColor); + + StudioRenderModel(dir); + m_pPlayerInfo = NULL; + + if (pplayer->weaponmodel) + { + studiohdr_t *saveheader = m_pStudioHeader; + cl_entity_t saveent = *m_pCurrentEntity; + + model_t *pweaponmodel = IEngineStudio.GetModelByIndex(pplayer->weaponmodel); + + m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(pweaponmodel); + IEngineStudio.StudioSetHeader(m_pStudioHeader); + + StudioMergeBones(pweaponmodel); + + IEngineStudio.StudioSetupLighting(&lighting); + + StudioRenderModel(dir); + + StudioCalcAttachments(); + + if (m_pCurrentEntity->index > 0) + memcpy(saveent.attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * m_pStudioHeader->numattachments); + + *m_pCurrentEntity = saveent; + m_pStudioHeader = saveheader; + IEngineStudio.StudioSetHeader(m_pStudioHeader); + + if (flags & STUDIO_EVENTS) + IEngineStudio.StudioClientEvents(); + } + } + + return 1; +} + + +void CGameStudioModelRenderer::StudioFxTransform(cl_entity_t *ent, float transform[3][4]) +{ + switch (ent->curstate.renderfx) + { + case kRenderFxDistort: + case kRenderFxHologram: + { + if (gEngfuncs.pfnRandomLong(0, 49) == 0) + { + int axis = gEngfuncs.pfnRandomLong(0, 1); + + if (axis == 1) + axis = 2; + VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] ); + } + else if (gEngfuncs.pfnRandomLong(0, 49) == 0) + { + float offset; + int axis = gEngfuncs.pfnRandomLong(0, 1); + + if (axis == 1) + axis = 2; + + offset = gEngfuncs.pfnRandomFloat(-10, 10); + transform[gEngfuncs.pfnRandomLong(0, 2)][3] += offset; + } + + break; + } + + case kRenderFxExplode: + { + if (iRenderStateChanged) + { + g_flStartScaleTime = m_clTime; + iRenderStateChanged = FALSE; + } + + float flTimeDelta = m_clTime - g_flStartScaleTime; + + if (flTimeDelta > 0) + { + float flScale = 0.001; + + if (flTimeDelta <= 2.0) + flScale = 1.0 - (flTimeDelta / 2.0); + + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + transform[i][j] *= flScale; + } + } + + break; + } + } +} + +void R_StudioInit(void) +{ + g_StudioRenderer.Init(); +} + +int R_StudioDrawPlayer(int flags, entity_state_t *pplayer) +{ + return g_StudioRenderer.StudioDrawPlayer(flags, pplayer); +} + +int R_StudioDrawModel(int flags) +{ + return g_StudioRenderer.StudioDrawModel(flags); +} +// The simple drawing interface we'll pass back to the engine +r_studio_interface_t studio = +{ + STUDIO_INTERFACE_VERSION, + R_StudioDrawModel, + R_StudioDrawPlayer, +}; + +#ifdef _WIN32 +#define DLLEXPORT __declspec( dllexport ) +#else +#define DLLEXPORT +#endif + +/* +==================== +HUD_GetStudioModelInterface +Export this function for the engine to use the studio renderer class to render objects. +==================== +*/ +extern "C" int DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio ) +{ + if ( version != STUDIO_INTERFACE_VERSION ) + return 0; + + // Point the engine to our callbacks + *ppinterface = &studio; + + // Copy in engine helper functions + memcpy( &IEngineStudio, pstudio, sizeof( IEngineStudio ) ); + + // Initialize local variables, etc. + R_StudioInit(); + + // Success + return 1; +} + diff --git a/cl_dll/studio/StudioModelRenderer.cpp b/cl_dll/studio/StudioModelRenderer.cpp index 40094d6..caed02f 100644 --- a/cl_dll/studio/StudioModelRenderer.cpp +++ b/cl_dll/studio/StudioModelRenderer.cpp @@ -1,1430 +1,1430 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// Big thanks to Chicken Fortress developers -// for this code. -#include -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "com_model.h" -#include "studio.h" -#include "entity_state.h" -#include "cl_entity.h" -#include "dlight.h" -#include "triangleapi.h" - -#include -#include -#include -#include - -#include "studio_util.h" -#include "r_studioint.h" - -#include "StudioModelRenderer.h" -#include "GameStudioModelRenderer.h" - -#include "event_api.h" -#include "pm_defs.h" - -extern CGameStudioModelRenderer g_StudioRenderer; -extern engine_studio_api_t IEngineStudio; -typedef struct pmtrace_s pmtrace_t; - -void CStudioModelRenderer::Init(void) -{ - m_pCvarHiModels = IEngineStudio.GetCvar("cl_himodels"); - m_pCvarDeveloper = IEngineStudio.GetCvar("developer"); - m_pCvarDrawEntities = IEngineStudio.GetCvar("r_drawentities"); - - m_pChromeSprite = IEngineStudio.GetChromeSprite(); - - IEngineStudio.GetModelCounters(&m_pStudioModelCount, &m_pModelsDrawn); - - m_pbonetransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetBoneTransform(); - m_plighttransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetLightTransform(); - m_paliastransform = (float (*)[3][4])IEngineStudio.StudioGetAliasTransform(); - m_protationmatrix = (float (*)[3][4])IEngineStudio.StudioGetRotationMatrix(); -} - -CStudioModelRenderer::CStudioModelRenderer(void) -{ - m_fDoInterp = 1; - m_fGaitEstimation = 1; - m_pCurrentEntity = NULL; - m_pCvarHiModels = NULL; - m_pCvarDeveloper = NULL; - m_pCvarDrawEntities = NULL; - m_pChromeSprite = NULL; - m_pStudioModelCount = NULL; - m_pModelsDrawn = NULL; - m_protationmatrix = NULL; - m_paliastransform = NULL; - m_pbonetransform = NULL; - m_plighttransform = NULL; - m_pStudioHeader = NULL; - m_pBodyPart = NULL; - m_pSubModel = NULL; - m_pPlayerInfo = NULL; - m_pRenderModel = NULL; - m_iShadowSprite = 0; -} - -CStudioModelRenderer::~CStudioModelRenderer(void) -{ -} - -void CStudioModelRenderer::StudioCalcBoneAdj(float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen) -{ - int i, j; - float value; - mstudiobonecontroller_t *pbonecontroller; - - pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex); - - for (j = 0; j < m_pStudioHeader->numbonecontrollers; j++) - { - i = pbonecontroller[j].index; - - if (i <= 3) - { - if (pbonecontroller[j].type & STUDIO_RLOOP) - { - if (abs(pcontroller1[i] - pcontroller2[i]) > 128) - { - int a, b; - a = (pcontroller1[j] + 128) % 256; - b = (pcontroller2[j] + 128) % 256; - value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0 / 256.0) + pbonecontroller[j].start; - } - else - { - value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0 / 256.0) + pbonecontroller[j].start; - } - } - else - { - value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0; - - if (value < 0) - value = 0; - - if (value > 1.0) - value = 1.0; - - value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; - } - } - else - { - value = mouthopen / 64.0; - - if (value > 1.0) - value = 1.0; - - value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; - } - - switch (pbonecontroller[j].type & STUDIO_TYPES) - { - case STUDIO_XR: - case STUDIO_YR: - case STUDIO_ZR: - { - adj[j] = value * (M_PI / 180.0); - break; - } - case STUDIO_X: - case STUDIO_Y: - case STUDIO_Z: - { - adj[j] = value; - break; - } - } - } -} - -void CStudioModelRenderer::StudioCalcBoneQuaterion(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q) -{ - int j, k; - vec4_t q1, q2; - vec3_t angle1, angle2; - mstudioanimvalue_t *panimvalue; - - for (j = 0; j < 3; j++) - { - if (panim->offset[j + 3] == 0) - { - angle2[j] = angle1[j] = pbone->value[j + 3]; - } - else - { - panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j + 3]); - k = frame; - - if (panimvalue->num.total < panimvalue->num.valid) - k = 0; - - while (panimvalue->num.total <= k) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - if (panimvalue->num.total < panimvalue->num.valid) - k = 0; - } - - if (panimvalue->num.valid > k) - { - angle1[j] = panimvalue[k + 1].value; - - if (panimvalue->num.valid > k + 1) - { - angle2[j] = panimvalue[k + 2].value; - } - else - { - if (panimvalue->num.total > k + 1) - angle2[j] = angle1[j]; - else - angle2[j] = panimvalue[panimvalue->num.valid + 2].value; - } - } - else - { - angle1[j] = panimvalue[panimvalue->num.valid].value; - - if (panimvalue->num.total > k + 1) - angle2[j] = angle1[j]; - else - angle2[j] = panimvalue[panimvalue->num.valid + 2].value; - } - - angle1[j] = pbone->value[j + 3] + angle1[j] * pbone->scale[j + 3]; - angle2[j] = pbone->value[j + 3] + angle2[j] * pbone->scale[j + 3]; - } - - if (pbone->bonecontroller[j + 3] != -1) - { - angle1[j] += adj[pbone->bonecontroller[j + 3]]; - angle2[j] += adj[pbone->bonecontroller[j + 3]]; - } - } - - if (!VectorCompare(angle1, angle2)) - { - AngleQuaternion(angle1, q1); - AngleQuaternion(angle2, q2); - QuaternionSlerp(q1, q2, s, q); - } - else - { - AngleQuaternion(angle1, q); - } -} - -void CStudioModelRenderer::StudioCalcBonePosition(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos) -{ - int j, k; - mstudioanimvalue_t *panimvalue; - - for (j = 0; j < 3; j++) - { - pos[j] = pbone->value[j]; - - if (panim->offset[j] != 0) - { - panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); - k = frame; - - if (panimvalue->num.total < panimvalue->num.valid) - k = 0; - - while (panimvalue->num.total <= k) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - if (panimvalue->num.total < panimvalue->num.valid) - k = 0; - } - - if (panimvalue->num.valid > k) - { - if (panimvalue->num.valid > k + 1) - pos[j] += (panimvalue[k + 1].value * (1.0 - s) + s * panimvalue[k + 2].value) * pbone->scale[j]; - else - pos[j] += panimvalue[k + 1].value * pbone->scale[j]; - } - else - { - if (panimvalue->num.total <= k + 1) - pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j]; - else - pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j]; - } - } - - if (pbone->bonecontroller[j] != -1 && adj) - pos[j] += adj[pbone->bonecontroller[j]]; - } -} - -void CStudioModelRenderer::StudioSlerpBones(vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s) -{ - int i; - vec4_t q3; - float s1; - - if (s < 0) - s = 0; - else if (s > 1.0) - s = 1.0; - - s1 = 1.0 - s; - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - QuaternionSlerp(q1[i], q2[i], s, q3); - - q1[i][0] = q3[0]; - q1[i][1] = q3[1]; - q1[i][2] = q3[2]; - q1[i][3] = q3[3]; - pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s; - pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s; - pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s; - } -} - -mstudioanim_t *CStudioModelRenderer::StudioGetAnim(model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc) -{ - mstudioseqgroup_t *pseqgroup; - cache_user_t *paSequences; - - pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup; - - if (pseqdesc->seqgroup == 0) - return (mstudioanim_t *)((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex); - - paSequences = (cache_user_t *)m_pSubModel->submodels; - - if (paSequences == NULL) - { - paSequences = (cache_user_t *)IEngineStudio.Mem_Calloc(16, sizeof(cache_user_t)); - m_pSubModel->submodels = (dmodel_t *)paSequences; - } - - if (!IEngineStudio.Cache_Check((struct cache_user_s *)&(paSequences[pseqdesc->seqgroup]))) - { - gEngfuncs.Con_DPrintf("loading %s\n", pseqgroup->name); - IEngineStudio.LoadCacheFile(pseqgroup->name, (struct cache_user_s *)&paSequences[pseqdesc->seqgroup]); - } - - return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex); -} - -void CStudioModelRenderer::StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch) -{ - *pBlend = (*pPitch * 3); - - if (*pBlend < pseqdesc->blendstart[0]) - { - *pPitch -= pseqdesc->blendstart[0] / 3.0; - *pBlend = 0; - } - else if (*pBlend > pseqdesc->blendend[0]) - { - *pPitch -= pseqdesc->blendend[0] / 3.0; - *pBlend = 255; - } - else - { - if (pseqdesc->blendend[0] - pseqdesc->blendstart[0] < 0.1) - *pBlend = 127; - else - *pBlend = 255 * (*pBlend - pseqdesc->blendstart[0]) / (pseqdesc->blendend[0] - pseqdesc->blendstart[0]); - - *pPitch = 0; - } -} - -void CStudioModelRenderer::StudioSetUpTransform(int trivial_accept) -{ - int i; - vec3_t angles; - vec3_t modelpos; - - VectorCopy(m_pCurrentEntity->origin, modelpos); - - angles[ROLL] = m_pCurrentEntity->curstate.angles[ROLL]; - angles[PITCH] = m_pCurrentEntity->curstate.angles[PITCH]; - angles[YAW] = m_pCurrentEntity->curstate.angles[YAW]; - - if (m_pCurrentEntity->curstate.movetype == MOVETYPE_STEP) - { - float f = 0; - float d; - - if ((m_clTime < m_pCurrentEntity->curstate.animtime + 1.0f) && (m_pCurrentEntity->curstate.animtime != m_pCurrentEntity->latched.prevanimtime)) - f = (m_clTime - m_pCurrentEntity->curstate.animtime) / (m_pCurrentEntity->curstate.animtime - m_pCurrentEntity->latched.prevanimtime); - - if (m_fDoInterp) - f = f - 1.0; - else - f = 0; - - for (i = 0; i < 3; i++) - modelpos[i] += (m_pCurrentEntity->origin[i] - m_pCurrentEntity->latched.prevorigin[i]) * f; - - for (i = 0; i < 3; i++) - { - float ang1, ang2; - - ang1 = m_pCurrentEntity->angles[i]; - ang2 = m_pCurrentEntity->latched.prevangles[i]; - - d = ang1 - ang2; - - if (d > 180) - d -= 360; - else if (d < -180) - d += 360; - - angles[i] += d * f; - } - } - else if (m_pCurrentEntity->curstate.movetype != MOVETYPE_NONE) - { - VectorCopy(m_pCurrentEntity->angles, angles); - } - - angles[PITCH] = -angles[PITCH]; - AngleMatrix(angles, (*m_protationmatrix)); - - if (!IEngineStudio.IsHardware()) - { - static float viewmatrix[3][4]; - - VectorCopy(m_vRight, viewmatrix[0]); - VectorCopy(m_vUp, viewmatrix[1]); - VectorInverse(viewmatrix[1]); - VectorCopy(m_vNormal, viewmatrix[2]); - - (*m_protationmatrix)[0][3] = modelpos[0] - m_vRenderOrigin[0]; - (*m_protationmatrix)[1][3] = modelpos[1] - m_vRenderOrigin[1]; - (*m_protationmatrix)[2][3] = modelpos[2] - m_vRenderOrigin[2]; - - ConcatTransforms(viewmatrix, (*m_protationmatrix), (*m_paliastransform)); - - if (trivial_accept) - { - for (i = 0; i < 4; i++) - { - (*m_paliastransform)[0][i] *= m_fSoftwareXScale * (1.0 / (ZISCALE * 0x10000)); - (*m_paliastransform)[1][i] *= m_fSoftwareYScale * (1.0 / (ZISCALE * 0x10000)); - (*m_paliastransform)[2][i] *= 1.0 / (ZISCALE * 0x10000); - } - } - } - - (*m_protationmatrix)[0][3] = modelpos[0]; - (*m_protationmatrix)[1][3] = modelpos[1]; - (*m_protationmatrix)[2][3] = modelpos[2]; -} - -float CStudioModelRenderer::StudioEstimateInterpolant(void) -{ - float dadt = 1.0; - - if (m_fDoInterp && (m_pCurrentEntity->curstate.animtime >= m_pCurrentEntity->latched.prevanimtime + 0.01)) - { - dadt = (m_clTime - m_pCurrentEntity->curstate.animtime) / 0.1; - - if (dadt > 2.0) - dadt = 2.0; - } - - return dadt; -} - -void CStudioModelRenderer::StudioCalcRotations(float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f) -{ - int i; - int frame; - mstudiobone_t *pbone; - - float s; - float adj[MAXSTUDIOCONTROLLERS]; - float dadt; - - if (f > pseqdesc->numframes - 1) - f = 0; - else if (f < -0.01) - f = -0.01; - - frame = (int)f; - dadt = StudioEstimateInterpolant(); - s = (f - frame); - - pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - StudioCalcBoneAdj(dadt, adj, m_pCurrentEntity->curstate.controller, m_pCurrentEntity->latched.prevcontroller, m_pCurrentEntity->mouth.mouthopen); - - for (i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++) - { - StudioCalcBoneQuaterion(frame, s, pbone, panim, adj, q[i]); - StudioCalcBonePosition(frame, s, pbone, panim, adj, pos[i]); - } - - if (pseqdesc->motiontype & STUDIO_X) - pos[pseqdesc->motionbone][0] = 0.0; - - if (pseqdesc->motiontype & STUDIO_Y) - pos[pseqdesc->motionbone][1] = 0.0; - - if (pseqdesc->motiontype & STUDIO_Z) - pos[pseqdesc->motionbone][2] = 0.0; - - s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * m_pCurrentEntity->curstate.framerate; - - if (pseqdesc->motiontype & STUDIO_LX) - pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0]; - - if (pseqdesc->motiontype & STUDIO_LY) - pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1]; - - if (pseqdesc->motiontype & STUDIO_LZ) - pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2]; -} - -void CStudioModelRenderer::StudioFxTransform(cl_entity_t *ent, float transform[3][4]) -{ - switch (ent->curstate.renderfx) - { - case kRenderFxDistort: - case kRenderFxHologram: - { - if (gEngfuncs.pfnRandomLong(0, 49) == 0) - { - int axis = gEngfuncs.pfnRandomLong(0, 1); - - if (axis == 1) - axis = 2; - - VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] ); - } - else if (gEngfuncs.pfnRandomLong(0, 49) == 0) - { - float offset; - int axis = gEngfuncs.pfnRandomLong(0, 1); - - if (axis == 1) - axis = 2; - - offset = gEngfuncs.pfnRandomFloat(-10, 10); - transform[gEngfuncs.pfnRandomLong(0, 2)][3] += offset; - } - - break; - } - - case kRenderFxExplode: - { - float scale; - - scale = 1.0 + (m_clTime - ent->curstate.animtime) * 10.0; - - if (scale > 2) - scale = 2; - - transform[0][1] *= scale; - transform[1][1] *= scale; - transform[2][1] *= scale; - break; - } - } -} - -float CStudioModelRenderer::StudioEstimateFrame(mstudioseqdesc_t *pseqdesc) -{ - double dfdt, f; - - if (m_fDoInterp) - { - if (m_clTime < m_pCurrentEntity->curstate.animtime) - dfdt = 0; - else - dfdt = (m_clTime - m_pCurrentEntity->curstate.animtime) * m_pCurrentEntity->curstate.framerate * pseqdesc->fps; - } - else - dfdt = 0; - - if (pseqdesc->numframes <= 1) - f = 0; - else - f = (m_pCurrentEntity->curstate.frame * (pseqdesc->numframes - 1)) / 256.0; - - f += dfdt; - - if (pseqdesc->flags & STUDIO_LOOPING) - { - if (pseqdesc->numframes > 1) - f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1); - - if (f < 0) - f += (pseqdesc->numframes - 1); - } - else - { - if (f >= pseqdesc->numframes - 1.001) - f = pseqdesc->numframes - 1.001; - - if (f < 0.0) - f = 0.0; - } - - return f; -} - -void CStudioModelRenderer::StudioSetupBones(void) -{ - int i; - double f; - - mstudiobone_t *pbones; - mstudioseqdesc_t *pseqdesc; - mstudioanim_t *panim; - - static float pos[MAXSTUDIOBONES][3]; - static vec4_t q[MAXSTUDIOBONES]; - float bonematrix[3][4]; - - static float pos2[MAXSTUDIOBONES][3]; - static vec4_t q2[MAXSTUDIOBONES]; - static float pos3[MAXSTUDIOBONES][3]; - static vec4_t q3[MAXSTUDIOBONES]; - static float pos4[MAXSTUDIOBONES][3]; - static vec4_t q4[MAXSTUDIOBONES]; - - if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) - m_pCurrentEntity->curstate.sequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; - - f = StudioEstimateFrame(pseqdesc); - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - - StudioCalcRotations(pos, q, pseqdesc, panim, f); - - if (pseqdesc->numblends > 1) - { - float s; - float dadt; - - panim += m_pStudioHeader->numbones; - StudioCalcRotations(pos2, q2, pseqdesc, panim, f); - - dadt = StudioEstimateInterpolant(); - s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0; - - StudioSlerpBones(q, pos, q2, pos2, s); - - if (pseqdesc->numblends == 4) - { - panim += m_pStudioHeader->numbones; - StudioCalcRotations(pos3, q3, pseqdesc, panim, f); - - panim += m_pStudioHeader->numbones; - StudioCalcRotations(pos4, q4, pseqdesc, panim, f); - - s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0; - StudioSlerpBones(q3, pos3, q4, pos4, s); - - s = (m_pCurrentEntity->curstate.blending[1] * dadt + m_pCurrentEntity->latched.prevblending[1] * (1.0 - dadt)) / 255.0; - StudioSlerpBones(q, pos, q3, pos3, s); - } - } - - if (m_fDoInterp && m_pCurrentEntity->latched.sequencetime && (m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime) && (m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq)) - { - static float pos1b[MAXSTUDIOBONES][3]; - static vec4_t q1b[MAXSTUDIOBONES]; - float s; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - - StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - - if (pseqdesc->numblends > 1) - { - panim += m_pStudioHeader->numbones; - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - - s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0; - StudioSlerpBones(q1b, pos1b, q2, pos2, s); - - if (pseqdesc->numblends == 4) - { - panim += m_pStudioHeader->numbones; - StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - - panim += m_pStudioHeader->numbones; - StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); - - s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0; - StudioSlerpBones(q3, pos3, q4, pos4, s); - - s = (m_pCurrentEntity->latched.prevseqblending[1]) / 255.0; - StudioSlerpBones(q1b, pos1b, q3, pos3, s); - } - } - - s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; - StudioSlerpBones(q, pos, q1b, pos1b, s); - } - else - { - m_pCurrentEntity->latched.prevframe = f; - } - - pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - if (m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0) - { - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence; - - panim = StudioGetAnim(m_pRenderModel, pseqdesc); - StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe); - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - if (strcmp(pbones[i].name, "Bip01 Spine") == 0) - break; - - memcpy(pos[i], pos2[i], sizeof( pos[i])); - memcpy(q[i], q2[i], sizeof( q[i])); - } - } - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - QuaternionMatrix(q[i], bonematrix); - - bonematrix[0][3] = pos[i][0]; - bonematrix[1][3] = pos[i][1]; - bonematrix[2][3] = pos[i][2]; - - if (pbones[i].parent == -1) - { - if (IEngineStudio.IsHardware()) - { - ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); - MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]); - } - else - { - ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); - ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); - } - - StudioFxTransform(m_pCurrentEntity, (*m_pbonetransform)[i]); - } - else - { - ConcatTransforms((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); - ConcatTransforms((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); - } - } -} - -void CStudioModelRenderer::StudioSaveBones(void) -{ - int i; - - mstudiobone_t *pbones; - pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - m_nCachedBones = m_pStudioHeader->numbones; - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - strncpy(m_nCachedBoneNames[i], pbones[i].name, 32); - MatrixCopy((*m_pbonetransform)[i], m_rgCachedBoneTransform[i]); - MatrixCopy((*m_plighttransform)[i], m_rgCachedLightTransform[i]); - } - -} - -void CStudioModelRenderer::StudioMergeBones(model_t *m_pSubModel) -{ - int i, j; - double f; - int do_hunt = true; - - mstudiobone_t *pbones; - mstudioseqdesc_t *pseqdesc; - mstudioanim_t *panim; - - static float pos[MAXSTUDIOBONES][3]; - float bonematrix[3][4]; - static vec4_t q[MAXSTUDIOBONES]; - - if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) - m_pCurrentEntity->curstate.sequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; - - f = StudioEstimateFrame(pseqdesc); - - if (m_pCurrentEntity->latched.prevframe > f) - { - } - - panim = StudioGetAnim(m_pSubModel, pseqdesc); - StudioCalcRotations(pos, q, pseqdesc, panim, f); - - pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - for (i = 0; i < m_pStudioHeader->numbones; i++) - { - for (j = 0; j < m_nCachedBones; j++) - { - if (stricmp(pbones[i].name, m_nCachedBoneNames[j]) == 0) - { - MatrixCopy(m_rgCachedBoneTransform[j], (*m_pbonetransform)[i]); - MatrixCopy(m_rgCachedLightTransform[j], (*m_plighttransform)[i]); - break; - } - } - - if (j >= m_nCachedBones) - { - QuaternionMatrix(q[i], bonematrix); - - bonematrix[0][3] = pos[i][0]; - bonematrix[1][3] = pos[i][1]; - bonematrix[2][3] = pos[i][2]; - - if (pbones[i].parent == -1) - { - if (IEngineStudio.IsHardware()) - { - ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); - MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]); - } - else - { - ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); - ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); - } - - StudioFxTransform(m_pCurrentEntity, (*m_pbonetransform)[i]); - } - else - { - ConcatTransforms((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); - ConcatTransforms((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); - } - } - } -} - -int CStudioModelRenderer::StudioDrawModel(int flags) -{ - m_pCurrentEntity = IEngineStudio.GetCurrentEntity(); - - IEngineStudio.GetTimes(&m_nFrameCount, &m_clTime, &m_clOldTime); - IEngineStudio.GetViewInfo(m_vRenderOrigin, m_vUp, m_vRight, m_vNormal); - IEngineStudio.GetAliasScale(&m_fSoftwareXScale, &m_fSoftwareYScale); - - if (m_pCurrentEntity->curstate.renderfx == kRenderFxDeadPlayer) - { - entity_state_t deadplayer; - - int result; - int save_interp; - - if (m_pCurrentEntity->curstate.renderamt <= 0 || m_pCurrentEntity->curstate.renderamt > gEngfuncs.GetMaxClients()) - return 0; - - deadplayer = *(IEngineStudio.GetPlayerState(m_pCurrentEntity->curstate.renderamt - 1)); - - deadplayer.number = m_pCurrentEntity->curstate.renderamt; - deadplayer.weaponmodel = 0; - deadplayer.gaitsequence = 0; - - deadplayer.movetype = MOVETYPE_NONE; - VectorCopy(m_pCurrentEntity->curstate.angles, deadplayer.angles); - VectorCopy(m_pCurrentEntity->curstate.origin, deadplayer.origin); - - save_interp = m_fDoInterp; - m_fDoInterp = 0; - - result = StudioDrawPlayer(flags, &deadplayer); - - m_fDoInterp = save_interp; - return result; - } - - m_pRenderModel = m_pCurrentEntity->model; - m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(m_pRenderModel); - - IEngineStudio.StudioSetHeader(m_pStudioHeader); - IEngineStudio.SetRenderModel(m_pRenderModel); - - StudioSetUpTransform(0); - - if(m_pCurrentEntity == gEngfuncs.GetViewModel() && (cl_righthand->value)) - { - (*m_protationmatrix)[0][1] *= -1; - (*m_protationmatrix)[1][1] *= -1; - (*m_protationmatrix)[2][1] *= -1; - - //IEngineStudio.StudioSetCullState(true); - } - - if (flags & STUDIO_RENDER) - { - if (!IEngineStudio.StudioCheckBBox()) - return 0; - - (*m_pModelsDrawn)++; - (*m_pStudioModelCount)++; - - if (m_pStudioHeader->numbodyparts == 0) - return 1; - } - - if (m_pCurrentEntity->curstate.movetype == MOVETYPE_FOLLOW) - StudioMergeBones(m_pRenderModel); - else - StudioSetupBones(); - - StudioSaveBones(); - - if (flags & STUDIO_EVENTS) - { - StudioCalcAttachments(); - IEngineStudio.StudioClientEvents(); - - if (m_pCurrentEntity->index > 0) - { - cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index); - memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * 4); - } - } - - if (flags & STUDIO_RENDER) - { - alight_t lighting; - vec3_t dir; - lighting.plightvec = dir; - - IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting); - - IEngineStudio.StudioEntityLight(&lighting); - IEngineStudio.StudioSetupLighting(&lighting); - - m_nTopColor = m_pCurrentEntity->curstate.colormap & 0xFF; - m_nBottomColor = (m_pCurrentEntity->curstate.colormap & 0xFF00) >> 8; - - IEngineStudio.StudioSetRemapColors(m_nTopColor, m_nBottomColor); - - StudioRenderModel(dir); - } - - return 1; -} - -void CStudioModelRenderer::StudioEstimateGait(entity_state_t *pplayer) -{ - float dt; - vec3_t est_velocity; - - dt = (m_clTime - m_clOldTime); - - if (dt < 0) - dt = 0; - else if (dt > 1.0) - dt = 1; - - if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount) - { - m_flGaitMovement = 0; - return; - } - - if (m_fGaitEstimation) - { - VectorSubtract(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity); - VectorCopy(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin); - m_flGaitMovement = est_velocity.Length(); - - if (dt <= 0 || m_flGaitMovement / dt < 5) - { - m_flGaitMovement = 0; - est_velocity[0] = 0; - est_velocity[1] = 0; - } - } - else - { - VectorCopy(pplayer->velocity, est_velocity); - m_flGaitMovement = est_velocity.Length() * dt; - } - - if (est_velocity[1] == 0 && est_velocity[0] == 0) - { - float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; - flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; - - if (flYawDiff > 180) - flYawDiff -= 360; - if (flYawDiff < -180) - flYawDiff += 360; - - if (dt < 0.25) - flYawDiff *= dt * 4; - else - flYawDiff *= dt; - - m_pPlayerInfo->gaityaw += flYawDiff; - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360; - m_flGaitMovement = 0; - } - else - { - m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); - - if (m_pPlayerInfo->gaityaw > 180) - m_pPlayerInfo->gaityaw = 180; - - if (m_pPlayerInfo->gaityaw < -180) - m_pPlayerInfo->gaityaw = -180; - } -} - -void CStudioModelRenderer::StudioProcessGait(entity_state_t *pplayer) -{ - mstudioseqdesc_t *pseqdesc; - float dt; - int iBlend; - float flYaw; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; - - StudioPlayerBlend(pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH]); - - m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH]; - m_pCurrentEntity->curstate.blending[0] = iBlend; - m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0]; - m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; - - dt = (m_clTime - m_clOldTime); - - if (dt < 0) - dt = 0; - else if (dt > 1.0) - dt = 1; - - StudioEstimateGait(pplayer); - - flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; - flYaw = flYaw - (int)(flYaw / 360) * 360; - - if (flYaw < -180) - flYaw = flYaw + 360; - - if (flYaw > 180) - flYaw = flYaw - 360; - - if (flYaw > 120) - { - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180; - m_flGaitMovement = -m_flGaitMovement; - flYaw = flYaw - 180; - } - else if (flYaw < -120) - { - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180; - m_flGaitMovement = -m_flGaitMovement; - flYaw = flYaw + 180; - } - - m_pCurrentEntity->curstate.controller[0] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - m_pCurrentEntity->curstate.controller[1] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - m_pCurrentEntity->curstate.controller[2] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - m_pCurrentEntity->curstate.controller[3] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0]; - m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1]; - m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2]; - m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3]; - - m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw; - - if (m_pCurrentEntity->angles[YAW] < -0) - m_pCurrentEntity->angles[YAW] += 360; - - m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW]; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence; - - if (pseqdesc->linearmovement[0] > 0) - m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes; - else - m_pPlayerInfo->gaitframe += pseqdesc->fps * dt; - - m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes; - - if (m_pPlayerInfo->gaitframe < 0) - m_pPlayerInfo->gaitframe += pseqdesc->numframes; -} - -int CStudioModelRenderer::StudioDrawPlayer(int flags, entity_state_t *pplayer) -{ - m_pCurrentEntity = IEngineStudio.GetCurrentEntity(); - - IEngineStudio.GetTimes(&m_nFrameCount, &m_clTime, &m_clOldTime); - IEngineStudio.GetViewInfo(m_vRenderOrigin, m_vUp, m_vRight, m_vNormal); - IEngineStudio.GetAliasScale(&m_fSoftwareXScale, &m_fSoftwareYScale); - - m_nPlayerIndex = pplayer->number - 1; - - if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients()) - return 0; - - m_pRenderModel = IEngineStudio.SetupPlayerModel(m_nPlayerIndex); - - if (m_pRenderModel == NULL) - return 0; - - m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(m_pRenderModel); - - IEngineStudio.StudioSetHeader(m_pStudioHeader); - IEngineStudio.SetRenderModel(m_pRenderModel); - - if (pplayer->gaitsequence) - { - vec3_t orig_angles; - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - - VectorCopy(m_pCurrentEntity->angles, orig_angles); - - StudioProcessGait(pplayer); - - m_pPlayerInfo->gaitsequence = pplayer->gaitsequence; - m_pPlayerInfo = NULL; - - StudioSetUpTransform(0); - VectorCopy(orig_angles, m_pCurrentEntity->angles); - } - else - { - m_pCurrentEntity->curstate.controller[0] = 127; - m_pCurrentEntity->curstate.controller[1] = 127; - m_pCurrentEntity->curstate.controller[2] = 127; - m_pCurrentEntity->curstate.controller[3] = 127; - m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0]; - m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1]; - m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2]; - m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3]; - - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - m_pPlayerInfo->gaitsequence = 0; - - StudioSetUpTransform(0); - } - - if (flags & STUDIO_RENDER) - { - if (!IEngineStudio.StudioCheckBBox()) - return 0; - - (*m_pModelsDrawn)++; - (*m_pStudioModelCount)++; - - if (m_pStudioHeader->numbodyparts == 0) - return 1; - } - - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - - StudioSetupBones(); - StudioSaveBones(); - - m_pPlayerInfo->renderframe = m_nFrameCount; - m_pPlayerInfo = NULL; - - if (flags & STUDIO_EVENTS) - { - StudioCalcAttachments(); - IEngineStudio.StudioClientEvents(); - - if (m_pCurrentEntity->index > 0) - { - cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index); - memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * 4); - } - } - - if (flags & STUDIO_RENDER) - { - if (m_pCvarHiModels->value && m_pRenderModel != m_pCurrentEntity->model) - m_pCurrentEntity->curstate.body = 255; - - if (!(m_pCvarDeveloper->value == 0 && gEngfuncs.GetMaxClients() == 1) && (m_pRenderModel == m_pCurrentEntity->model)) - m_pCurrentEntity->curstate.body = 1; - - alight_t lighting; - vec3_t dir; - lighting.plightvec = dir; - - IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting); - IEngineStudio.StudioEntityLight(&lighting); - IEngineStudio.StudioSetupLighting(&lighting); - - m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); - - m_nTopColor = m_pPlayerInfo->topcolor; - - if (m_nTopColor < 0) - m_nTopColor = 0; - - if (m_nTopColor > 360) - m_nTopColor = 360; - - m_nBottomColor = m_pPlayerInfo->bottomcolor; - - if (m_nBottomColor < 0) - m_nBottomColor = 0; - - if (m_nBottomColor > 360) - m_nBottomColor = 360; - - IEngineStudio.StudioSetRemapColors(m_nTopColor, m_nBottomColor); - - StudioRenderModel(dir); - m_pPlayerInfo = NULL; - - if (pplayer->weaponmodel) - { - cl_entity_t saveent = *m_pCurrentEntity; - model_t *pweaponmodel = IEngineStudio.GetModelByIndex(pplayer->weaponmodel); - - m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(pweaponmodel); - IEngineStudio.StudioSetHeader(m_pStudioHeader); - - StudioMergeBones(pweaponmodel); - - IEngineStudio.StudioSetupLighting(&lighting); - - StudioRenderModel(dir); - - StudioCalcAttachments(); - - *m_pCurrentEntity = saveent; - } - } - - return 1; -} - -void CStudioModelRenderer::StudioCalcAttachments(void) -{ - int i; - mstudioattachment_t *pattachment; - - if (m_pStudioHeader->numattachments > 4) - gEngfuncs.Con_DPrintf("Too many attachments on %s\n", m_pCurrentEntity->model->name); - - pattachment = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex); - - for (i = 0; i < m_pStudioHeader->numattachments; i++) - VectorTransform(pattachment[i].org, (*m_plighttransform)[pattachment[i].bone], m_pCurrentEntity->attachment[i]); -} - -void CStudioModelRenderer::StudioRenderModel(float *lightdir) -{ - IEngineStudio.SetChromeOrigin(); - - int iSaveRenderMode = m_pCurrentEntity->curstate.rendermode; - int iSaveRenderFx = m_pCurrentEntity->curstate.renderfx; - int iSaveRenderAmt = m_pCurrentEntity->curstate.renderamt; - - - IEngineStudio.SetForceFaceFlags(0); - StudioRenderFinal(); - - if (iSaveRenderFx == kRenderFxGlowShell) - { - m_pCurrentEntity->curstate.renderfx = kRenderFxGlowShell; - - gEngfuncs.pTriAPI->SpriteTexture(m_pChromeSprite, 0); - - IEngineStudio.SetForceFaceFlags(STUDIO_NF_CHROME); - StudioRenderFinal(); - } - - - m_pCurrentEntity->curstate.rendermode = iSaveRenderMode; - m_pCurrentEntity->curstate.renderfx = iSaveRenderFx; - m_pCurrentEntity->curstate.renderamt = iSaveRenderAmt; -} - -void CStudioModelRenderer::StudioRenderFinal_Software(void) -{ - int i; - - IEngineStudio.SetupRenderer(0); - - if (m_pCvarDrawEntities->value == 2) - { - IEngineStudio.StudioDrawBones(); - } - else if (m_pCvarDrawEntities->value == 3) - { - IEngineStudio.StudioDrawHulls(); - } - else - { - for (i = 0; i < m_pStudioHeader->numbodyparts; i++) - { - IEngineStudio.StudioSetupModel(i, (void **)&m_pBodyPart, (void **)&m_pSubModel); - IEngineStudio.StudioDrawPoints(); - } - } - - if (m_pCvarDrawEntities->value == 4) - { - gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); - IEngineStudio.StudioDrawHulls(); - gEngfuncs.pTriAPI->RenderMode(kRenderNormal); - } - - if (m_pCvarDrawEntities->value == 5) - IEngineStudio.StudioDrawAbsBBox(); - - IEngineStudio.RestoreRenderer(); -} - -void CStudioModelRenderer::StudioRenderFinal_Hardware(void) -{ - int i; - int rendermode; - - rendermode = IEngineStudio.GetForceFaceFlags() ? kRenderTransAdd : m_pCurrentEntity->curstate.rendermode; - IEngineStudio.SetupRenderer(rendermode); - - if (m_pCvarDrawEntities->value == 2) - { - IEngineStudio.StudioDrawBones(); - } - else if (m_pCvarDrawEntities->value == 3) - { - IEngineStudio.StudioDrawHulls(); - } - else - { - for (i = 0; i < m_pStudioHeader->numbodyparts; i++) - { - IEngineStudio.StudioSetupModel(i, (void **)&m_pBodyPart, (void **)&m_pSubModel); - - if (m_fDoInterp) - m_pCurrentEntity->trivial_accept = 0; - - IEngineStudio.GL_SetRenderMode(rendermode); - IEngineStudio.StudioSetRenderamt(m_pCurrentEntity->curstate.renderamt); - IEngineStudio.StudioDrawPoints(); - } - } - - if (m_pCvarDrawEntities->value == 4) - { - gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); - IEngineStudio.StudioDrawHulls(); - gEngfuncs.pTriAPI->RenderMode(kRenderNormal); - } - - IEngineStudio.RestoreRenderer(); -} - -void CStudioModelRenderer::StudioRenderFinal(void) -{ - if (IEngineStudio.IsHardware()) - StudioRenderFinal_Hardware(); - else - StudioRenderFinal_Software(); -} - -void CStudioModelRenderer::StudioSetShadowSprite(int idx) -{ - m_iShadowSprite = idx; -} - -void CStudioModelRenderer::StudioDrawShadow( Vector origin, float scale ) -{ - Vector endPoint = origin; - Vector p1, p2, p3, p4; - pmtrace_t pmtrace; - - endPoint.z -= 150.0f; - - gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true ); - gEngfuncs.pEventAPI->EV_PushPMStates( ); - gEngfuncs.pEventAPI->EV_SetSolidPlayers( -1 ); - gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); - gEngfuncs.pEventAPI->EV_PlayerTrace( origin, endPoint, PM_STUDIO_IGNORE | PM_GLASS_IGNORE, -1, &pmtrace ); - gEngfuncs.pEventAPI->EV_PopPMStates( ); - - // don't allow shadow if player in solid area - if( pmtrace.startsolid ) - return; - - // don't allow shadow if doesn't hit anything - if( pmtrace.fraction >= 1.0f ) - return; - - pmtrace.plane.normal = pmtrace.plane.normal.Normalize( ); - - // don't allow shadow on too lean planes - if( pmtrace.plane.normal.z <= 0.7 ) - return; - - pmtrace.plane.normal = pmtrace.plane.normal * scale * ( 1.0 - pmtrace.fraction ); - - - // add 2.0f to Z, for avoid Z-fighting - p1.x = pmtrace.endpos.x - pmtrace.plane.normal.z; - p1.y = pmtrace.endpos.y + pmtrace.plane.normal.z; - p1.z = pmtrace.endpos.z + 2.0f + pmtrace.plane.normal.x - pmtrace.plane.normal.y; - - p2.x = pmtrace.endpos.x + pmtrace.plane.normal.z; - p2.y = pmtrace.endpos.y + pmtrace.plane.normal.z; - p2.z = pmtrace.endpos.z + 2.0f - pmtrace.plane.normal.x - pmtrace.plane.normal.y; - - p3.x = pmtrace.endpos.x + pmtrace.plane.normal.z; - p3.y = pmtrace.endpos.y - pmtrace.plane.normal.z; - p3.z = pmtrace.endpos.z + 2.0f - pmtrace.plane.normal.x + pmtrace.plane.normal.y; - - p4.x = pmtrace.endpos.x - pmtrace.plane.normal.z; - p4.y = pmtrace.endpos.y - pmtrace.plane.normal.z; - p4.z = pmtrace.endpos.z + 2.0f + pmtrace.plane.normal.x + pmtrace.plane.normal.y; - - IEngineStudio.StudioRenderShadow( m_iShadowSprite, p1, p2, p3, p4 ); -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// Big thanks to Chicken Fortress developers +// for this code. +#include +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "com_model.h" +#include "studio.h" +#include "entity_state.h" +#include "cl_entity.h" +#include "dlight.h" +#include "triangleapi.h" + +#include +#include +#include +#include + +#include "studio_util.h" +#include "r_studioint.h" + +#include "StudioModelRenderer.h" +#include "GameStudioModelRenderer.h" + +#include "event_api.h" +#include "pm_defs.h" + +extern CGameStudioModelRenderer g_StudioRenderer; +extern engine_studio_api_t IEngineStudio; +typedef struct pmtrace_s pmtrace_t; + +void CStudioModelRenderer::Init(void) +{ + m_pCvarHiModels = IEngineStudio.GetCvar("cl_himodels"); + m_pCvarDeveloper = IEngineStudio.GetCvar("developer"); + m_pCvarDrawEntities = IEngineStudio.GetCvar("r_drawentities"); + + m_pChromeSprite = IEngineStudio.GetChromeSprite(); + + IEngineStudio.GetModelCounters(&m_pStudioModelCount, &m_pModelsDrawn); + + m_pbonetransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetBoneTransform(); + m_plighttransform = (float (*)[MAXSTUDIOBONES][3][4])IEngineStudio.StudioGetLightTransform(); + m_paliastransform = (float (*)[3][4])IEngineStudio.StudioGetAliasTransform(); + m_protationmatrix = (float (*)[3][4])IEngineStudio.StudioGetRotationMatrix(); +} + +CStudioModelRenderer::CStudioModelRenderer(void) +{ + m_fDoInterp = 1; + m_fGaitEstimation = 1; + m_pCurrentEntity = NULL; + m_pCvarHiModels = NULL; + m_pCvarDeveloper = NULL; + m_pCvarDrawEntities = NULL; + m_pChromeSprite = NULL; + m_pStudioModelCount = NULL; + m_pModelsDrawn = NULL; + m_protationmatrix = NULL; + m_paliastransform = NULL; + m_pbonetransform = NULL; + m_plighttransform = NULL; + m_pStudioHeader = NULL; + m_pBodyPart = NULL; + m_pSubModel = NULL; + m_pPlayerInfo = NULL; + m_pRenderModel = NULL; + m_iShadowSprite = 0; +} + +CStudioModelRenderer::~CStudioModelRenderer(void) +{ +} + +void CStudioModelRenderer::StudioCalcBoneAdj(float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen) +{ + int i, j; + float value; + mstudiobonecontroller_t *pbonecontroller; + + pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex); + + for (j = 0; j < m_pStudioHeader->numbonecontrollers; j++) + { + i = pbonecontroller[j].index; + + if (i <= 3) + { + if (pbonecontroller[j].type & STUDIO_RLOOP) + { + if (abs(pcontroller1[i] - pcontroller2[i]) > 128) + { + int a, b; + a = (pcontroller1[j] + 128) % 256; + b = (pcontroller2[j] + 128) % 256; + value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0 / 256.0) + pbonecontroller[j].start; + } + else + { + value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0 / 256.0) + pbonecontroller[j].start; + } + } + else + { + value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0; + + if (value < 0) + value = 0; + + if (value > 1.0) + value = 1.0; + + value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; + } + } + else + { + value = mouthopen / 64.0; + + if (value > 1.0) + value = 1.0; + + value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; + } + + switch (pbonecontroller[j].type & STUDIO_TYPES) + { + case STUDIO_XR: + case STUDIO_YR: + case STUDIO_ZR: + { + adj[j] = value * (M_PI / 180.0); + break; + } + case STUDIO_X: + case STUDIO_Y: + case STUDIO_Z: + { + adj[j] = value; + break; + } + } + } +} + +void CStudioModelRenderer::StudioCalcBoneQuaterion(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q) +{ + int j, k; + vec4_t q1, q2; + vec3_t angle1, angle2; + mstudioanimvalue_t *panimvalue; + + for (j = 0; j < 3; j++) + { + if (panim->offset[j + 3] == 0) + { + angle2[j] = angle1[j] = pbone->value[j + 3]; + } + else + { + panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j + 3]); + k = frame; + + if (panimvalue->num.total < panimvalue->num.valid) + k = 0; + + while (panimvalue->num.total <= k) + { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + if (panimvalue->num.total < panimvalue->num.valid) + k = 0; + } + + if (panimvalue->num.valid > k) + { + angle1[j] = panimvalue[k + 1].value; + + if (panimvalue->num.valid > k + 1) + { + angle2[j] = panimvalue[k + 2].value; + } + else + { + if (panimvalue->num.total > k + 1) + angle2[j] = angle1[j]; + else + angle2[j] = panimvalue[panimvalue->num.valid + 2].value; + } + } + else + { + angle1[j] = panimvalue[panimvalue->num.valid].value; + + if (panimvalue->num.total > k + 1) + angle2[j] = angle1[j]; + else + angle2[j] = panimvalue[panimvalue->num.valid + 2].value; + } + + angle1[j] = pbone->value[j + 3] + angle1[j] * pbone->scale[j + 3]; + angle2[j] = pbone->value[j + 3] + angle2[j] * pbone->scale[j + 3]; + } + + if (pbone->bonecontroller[j + 3] != -1) + { + angle1[j] += adj[pbone->bonecontroller[j + 3]]; + angle2[j] += adj[pbone->bonecontroller[j + 3]]; + } + } + + if (!VectorCompare(angle1, angle2)) + { + AngleQuaternion(angle1, q1); + AngleQuaternion(angle2, q2); + QuaternionSlerp(q1, q2, s, q); + } + else + { + AngleQuaternion(angle1, q); + } +} + +void CStudioModelRenderer::StudioCalcBonePosition(int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos) +{ + int j, k; + mstudioanimvalue_t *panimvalue; + + for (j = 0; j < 3; j++) + { + pos[j] = pbone->value[j]; + + if (panim->offset[j] != 0) + { + panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); + k = frame; + + if (panimvalue->num.total < panimvalue->num.valid) + k = 0; + + while (panimvalue->num.total <= k) + { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + if (panimvalue->num.total < panimvalue->num.valid) + k = 0; + } + + if (panimvalue->num.valid > k) + { + if (panimvalue->num.valid > k + 1) + pos[j] += (panimvalue[k + 1].value * (1.0 - s) + s * panimvalue[k + 2].value) * pbone->scale[j]; + else + pos[j] += panimvalue[k + 1].value * pbone->scale[j]; + } + else + { + if (panimvalue->num.total <= k + 1) + pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j]; + else + pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j]; + } + } + + if (pbone->bonecontroller[j] != -1 && adj) + pos[j] += adj[pbone->bonecontroller[j]]; + } +} + +void CStudioModelRenderer::StudioSlerpBones(vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s) +{ + int i; + vec4_t q3; + float s1; + + if (s < 0) + s = 0; + else if (s > 1.0) + s = 1.0; + + s1 = 1.0 - s; + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + QuaternionSlerp(q1[i], q2[i], s, q3); + + q1[i][0] = q3[0]; + q1[i][1] = q3[1]; + q1[i][2] = q3[2]; + q1[i][3] = q3[3]; + pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s; + pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s; + pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s; + } +} + +mstudioanim_t *CStudioModelRenderer::StudioGetAnim(model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc) +{ + mstudioseqgroup_t *pseqgroup; + cache_user_t *paSequences; + + pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup; + + if (pseqdesc->seqgroup == 0) + return (mstudioanim_t *)((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex); + + paSequences = (cache_user_t *)m_pSubModel->submodels; + + if (paSequences == NULL) + { + paSequences = (cache_user_t *)IEngineStudio.Mem_Calloc(16, sizeof(cache_user_t)); + m_pSubModel->submodels = (dmodel_t *)paSequences; + } + + if (!IEngineStudio.Cache_Check((struct cache_user_s *)&(paSequences[pseqdesc->seqgroup]))) + { + gEngfuncs.Con_DPrintf("loading %s\n", pseqgroup->name); + IEngineStudio.LoadCacheFile(pseqgroup->name, (struct cache_user_s *)&paSequences[pseqdesc->seqgroup]); + } + + return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex); +} + +void CStudioModelRenderer::StudioPlayerBlend(mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch) +{ + *pBlend = (*pPitch * 3); + + if (*pBlend < pseqdesc->blendstart[0]) + { + *pPitch -= pseqdesc->blendstart[0] / 3.0; + *pBlend = 0; + } + else if (*pBlend > pseqdesc->blendend[0]) + { + *pPitch -= pseqdesc->blendend[0] / 3.0; + *pBlend = 255; + } + else + { + if (pseqdesc->blendend[0] - pseqdesc->blendstart[0] < 0.1) + *pBlend = 127; + else + *pBlend = 255 * (*pBlend - pseqdesc->blendstart[0]) / (pseqdesc->blendend[0] - pseqdesc->blendstart[0]); + + *pPitch = 0; + } +} + +void CStudioModelRenderer::StudioSetUpTransform(int trivial_accept) +{ + int i; + vec3_t angles; + vec3_t modelpos; + + VectorCopy(m_pCurrentEntity->origin, modelpos); + + angles[ROLL] = m_pCurrentEntity->curstate.angles[ROLL]; + angles[PITCH] = m_pCurrentEntity->curstate.angles[PITCH]; + angles[YAW] = m_pCurrentEntity->curstate.angles[YAW]; + + if (m_pCurrentEntity->curstate.movetype == MOVETYPE_STEP) + { + float f = 0; + float d; + + if ((m_clTime < m_pCurrentEntity->curstate.animtime + 1.0f) && (m_pCurrentEntity->curstate.animtime != m_pCurrentEntity->latched.prevanimtime)) + f = (m_clTime - m_pCurrentEntity->curstate.animtime) / (m_pCurrentEntity->curstate.animtime - m_pCurrentEntity->latched.prevanimtime); + + if (m_fDoInterp) + f = f - 1.0; + else + f = 0; + + for (i = 0; i < 3; i++) + modelpos[i] += (m_pCurrentEntity->origin[i] - m_pCurrentEntity->latched.prevorigin[i]) * f; + + for (i = 0; i < 3; i++) + { + float ang1, ang2; + + ang1 = m_pCurrentEntity->angles[i]; + ang2 = m_pCurrentEntity->latched.prevangles[i]; + + d = ang1 - ang2; + + if (d > 180) + d -= 360; + else if (d < -180) + d += 360; + + angles[i] += d * f; + } + } + else if (m_pCurrentEntity->curstate.movetype != MOVETYPE_NONE) + { + VectorCopy(m_pCurrentEntity->angles, angles); + } + + angles[PITCH] = -angles[PITCH]; + AngleMatrix(angles, (*m_protationmatrix)); + + if (!IEngineStudio.IsHardware()) + { + static float viewmatrix[3][4]; + + VectorCopy(m_vRight, viewmatrix[0]); + VectorCopy(m_vUp, viewmatrix[1]); + VectorInverse(viewmatrix[1]); + VectorCopy(m_vNormal, viewmatrix[2]); + + (*m_protationmatrix)[0][3] = modelpos[0] - m_vRenderOrigin[0]; + (*m_protationmatrix)[1][3] = modelpos[1] - m_vRenderOrigin[1]; + (*m_protationmatrix)[2][3] = modelpos[2] - m_vRenderOrigin[2]; + + ConcatTransforms(viewmatrix, (*m_protationmatrix), (*m_paliastransform)); + + if (trivial_accept) + { + for (i = 0; i < 4; i++) + { + (*m_paliastransform)[0][i] *= m_fSoftwareXScale * (1.0 / (ZISCALE * 0x10000)); + (*m_paliastransform)[1][i] *= m_fSoftwareYScale * (1.0 / (ZISCALE * 0x10000)); + (*m_paliastransform)[2][i] *= 1.0 / (ZISCALE * 0x10000); + } + } + } + + (*m_protationmatrix)[0][3] = modelpos[0]; + (*m_protationmatrix)[1][3] = modelpos[1]; + (*m_protationmatrix)[2][3] = modelpos[2]; +} + +float CStudioModelRenderer::StudioEstimateInterpolant(void) +{ + float dadt = 1.0; + + if (m_fDoInterp && (m_pCurrentEntity->curstate.animtime >= m_pCurrentEntity->latched.prevanimtime + 0.01)) + { + dadt = (m_clTime - m_pCurrentEntity->curstate.animtime) / 0.1; + + if (dadt > 2.0) + dadt = 2.0; + } + + return dadt; +} + +void CStudioModelRenderer::StudioCalcRotations(float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f) +{ + int i; + int frame; + mstudiobone_t *pbone; + + float s; + float adj[MAXSTUDIOCONTROLLERS]; + float dadt; + + if (f > pseqdesc->numframes - 1) + f = 0; + else if (f < -0.01) + f = -0.01; + + frame = (int)f; + dadt = StudioEstimateInterpolant(); + s = (f - frame); + + pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + StudioCalcBoneAdj(dadt, adj, m_pCurrentEntity->curstate.controller, m_pCurrentEntity->latched.prevcontroller, m_pCurrentEntity->mouth.mouthopen); + + for (i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++) + { + StudioCalcBoneQuaterion(frame, s, pbone, panim, adj, q[i]); + StudioCalcBonePosition(frame, s, pbone, panim, adj, pos[i]); + } + + if (pseqdesc->motiontype & STUDIO_X) + pos[pseqdesc->motionbone][0] = 0.0; + + if (pseqdesc->motiontype & STUDIO_Y) + pos[pseqdesc->motionbone][1] = 0.0; + + if (pseqdesc->motiontype & STUDIO_Z) + pos[pseqdesc->motionbone][2] = 0.0; + + s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * m_pCurrentEntity->curstate.framerate; + + if (pseqdesc->motiontype & STUDIO_LX) + pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0]; + + if (pseqdesc->motiontype & STUDIO_LY) + pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1]; + + if (pseqdesc->motiontype & STUDIO_LZ) + pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2]; +} + +void CStudioModelRenderer::StudioFxTransform(cl_entity_t *ent, float transform[3][4]) +{ + switch (ent->curstate.renderfx) + { + case kRenderFxDistort: + case kRenderFxHologram: + { + if (gEngfuncs.pfnRandomLong(0, 49) == 0) + { + int axis = gEngfuncs.pfnRandomLong(0, 1); + + if (axis == 1) + axis = 2; + + VectorScale( transform[axis], gEngfuncs.pfnRandomFloat(1,1.484), transform[axis] ); + } + else if (gEngfuncs.pfnRandomLong(0, 49) == 0) + { + float offset; + int axis = gEngfuncs.pfnRandomLong(0, 1); + + if (axis == 1) + axis = 2; + + offset = gEngfuncs.pfnRandomFloat(-10, 10); + transform[gEngfuncs.pfnRandomLong(0, 2)][3] += offset; + } + + break; + } + + case kRenderFxExplode: + { + float scale; + + scale = 1.0 + (m_clTime - ent->curstate.animtime) * 10.0; + + if (scale > 2) + scale = 2; + + transform[0][1] *= scale; + transform[1][1] *= scale; + transform[2][1] *= scale; + break; + } + } +} + +float CStudioModelRenderer::StudioEstimateFrame(mstudioseqdesc_t *pseqdesc) +{ + double dfdt, f; + + if (m_fDoInterp) + { + if (m_clTime < m_pCurrentEntity->curstate.animtime) + dfdt = 0; + else + dfdt = (m_clTime - m_pCurrentEntity->curstate.animtime) * m_pCurrentEntity->curstate.framerate * pseqdesc->fps; + } + else + dfdt = 0; + + if (pseqdesc->numframes <= 1) + f = 0; + else + f = (m_pCurrentEntity->curstate.frame * (pseqdesc->numframes - 1)) / 256.0; + + f += dfdt; + + if (pseqdesc->flags & STUDIO_LOOPING) + { + if (pseqdesc->numframes > 1) + f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1); + + if (f < 0) + f += (pseqdesc->numframes - 1); + } + else + { + if (f >= pseqdesc->numframes - 1.001) + f = pseqdesc->numframes - 1.001; + + if (f < 0.0) + f = 0.0; + } + + return f; +} + +void CStudioModelRenderer::StudioSetupBones(void) +{ + int i; + double f; + + mstudiobone_t *pbones; + mstudioseqdesc_t *pseqdesc; + mstudioanim_t *panim; + + static float pos[MAXSTUDIOBONES][3]; + static vec4_t q[MAXSTUDIOBONES]; + float bonematrix[3][4]; + + static float pos2[MAXSTUDIOBONES][3]; + static vec4_t q2[MAXSTUDIOBONES]; + static float pos3[MAXSTUDIOBONES][3]; + static vec4_t q3[MAXSTUDIOBONES]; + static float pos4[MAXSTUDIOBONES][3]; + static vec4_t q4[MAXSTUDIOBONES]; + + if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) + m_pCurrentEntity->curstate.sequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; + + f = StudioEstimateFrame(pseqdesc); + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + + StudioCalcRotations(pos, q, pseqdesc, panim, f); + + if (pseqdesc->numblends > 1) + { + float s; + float dadt; + + panim += m_pStudioHeader->numbones; + StudioCalcRotations(pos2, q2, pseqdesc, panim, f); + + dadt = StudioEstimateInterpolant(); + s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0; + + StudioSlerpBones(q, pos, q2, pos2, s); + + if (pseqdesc->numblends == 4) + { + panim += m_pStudioHeader->numbones; + StudioCalcRotations(pos3, q3, pseqdesc, panim, f); + + panim += m_pStudioHeader->numbones; + StudioCalcRotations(pos4, q4, pseqdesc, panim, f); + + s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0; + StudioSlerpBones(q3, pos3, q4, pos4, s); + + s = (m_pCurrentEntity->curstate.blending[1] * dadt + m_pCurrentEntity->latched.prevblending[1] * (1.0 - dadt)) / 255.0; + StudioSlerpBones(q, pos, q3, pos3, s); + } + } + + if (m_fDoInterp && m_pCurrentEntity->latched.sequencetime && (m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime) && (m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq)) + { + static float pos1b[MAXSTUDIOBONES][3]; + static vec4_t q1b[MAXSTUDIOBONES]; + float s; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + + StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + + if (pseqdesc->numblends > 1) + { + panim += m_pStudioHeader->numbones; + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + + s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0; + StudioSlerpBones(q1b, pos1b, q2, pos2, s); + + if (pseqdesc->numblends == 4) + { + panim += m_pStudioHeader->numbones; + StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + + panim += m_pStudioHeader->numbones; + StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); + + s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0; + StudioSlerpBones(q3, pos3, q4, pos4, s); + + s = (m_pCurrentEntity->latched.prevseqblending[1]) / 255.0; + StudioSlerpBones(q1b, pos1b, q3, pos3, s); + } + } + + s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; + StudioSlerpBones(q, pos, q1b, pos1b, s); + } + else + { + m_pCurrentEntity->latched.prevframe = f; + } + + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + if (m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0) + { + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence; + + panim = StudioGetAnim(m_pRenderModel, pseqdesc); + StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe); + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + if (strcmp(pbones[i].name, "Bip01 Spine") == 0) + break; + + memcpy(pos[i], pos2[i], sizeof( pos[i])); + memcpy(q[i], q2[i], sizeof( q[i])); + } + } + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + QuaternionMatrix(q[i], bonematrix); + + bonematrix[0][3] = pos[i][0]; + bonematrix[1][3] = pos[i][1]; + bonematrix[2][3] = pos[i][2]; + + if (pbones[i].parent == -1) + { + if (IEngineStudio.IsHardware()) + { + ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); + MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]); + } + else + { + ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); + ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); + } + + StudioFxTransform(m_pCurrentEntity, (*m_pbonetransform)[i]); + } + else + { + ConcatTransforms((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); + ConcatTransforms((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); + } + } +} + +void CStudioModelRenderer::StudioSaveBones(void) +{ + int i; + + mstudiobone_t *pbones; + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + m_nCachedBones = m_pStudioHeader->numbones; + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + strncpy(m_nCachedBoneNames[i], pbones[i].name, 32); + MatrixCopy((*m_pbonetransform)[i], m_rgCachedBoneTransform[i]); + MatrixCopy((*m_plighttransform)[i], m_rgCachedLightTransform[i]); + } + +} + +void CStudioModelRenderer::StudioMergeBones(model_t *m_pSubModel) +{ + int i, j; + double f; + int do_hunt = true; + + mstudiobone_t *pbones; + mstudioseqdesc_t *pseqdesc; + mstudioanim_t *panim; + + static float pos[MAXSTUDIOBONES][3]; + float bonematrix[3][4]; + static vec4_t q[MAXSTUDIOBONES]; + + if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) + m_pCurrentEntity->curstate.sequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; + + f = StudioEstimateFrame(pseqdesc); + + if (m_pCurrentEntity->latched.prevframe > f) + { + } + + panim = StudioGetAnim(m_pSubModel, pseqdesc); + StudioCalcRotations(pos, q, pseqdesc, panim, f); + + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + for (i = 0; i < m_pStudioHeader->numbones; i++) + { + for (j = 0; j < m_nCachedBones; j++) + { + if (stricmp(pbones[i].name, m_nCachedBoneNames[j]) == 0) + { + MatrixCopy(m_rgCachedBoneTransform[j], (*m_pbonetransform)[i]); + MatrixCopy(m_rgCachedLightTransform[j], (*m_plighttransform)[i]); + break; + } + } + + if (j >= m_nCachedBones) + { + QuaternionMatrix(q[i], bonematrix); + + bonematrix[0][3] = pos[i][0]; + bonematrix[1][3] = pos[i][1]; + bonematrix[2][3] = pos[i][2]; + + if (pbones[i].parent == -1) + { + if (IEngineStudio.IsHardware()) + { + ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); + MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]); + } + else + { + ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); + ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); + } + + StudioFxTransform(m_pCurrentEntity, (*m_pbonetransform)[i]); + } + else + { + ConcatTransforms((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); + ConcatTransforms((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); + } + } + } +} + +int CStudioModelRenderer::StudioDrawModel(int flags) +{ + m_pCurrentEntity = IEngineStudio.GetCurrentEntity(); + + IEngineStudio.GetTimes(&m_nFrameCount, &m_clTime, &m_clOldTime); + IEngineStudio.GetViewInfo(m_vRenderOrigin, m_vUp, m_vRight, m_vNormal); + IEngineStudio.GetAliasScale(&m_fSoftwareXScale, &m_fSoftwareYScale); + + if (m_pCurrentEntity->curstate.renderfx == kRenderFxDeadPlayer) + { + entity_state_t deadplayer; + + int result; + int save_interp; + + if (m_pCurrentEntity->curstate.renderamt <= 0 || m_pCurrentEntity->curstate.renderamt > gEngfuncs.GetMaxClients()) + return 0; + + deadplayer = *(IEngineStudio.GetPlayerState(m_pCurrentEntity->curstate.renderamt - 1)); + + deadplayer.number = m_pCurrentEntity->curstate.renderamt; + deadplayer.weaponmodel = 0; + deadplayer.gaitsequence = 0; + + deadplayer.movetype = MOVETYPE_NONE; + VectorCopy(m_pCurrentEntity->curstate.angles, deadplayer.angles); + VectorCopy(m_pCurrentEntity->curstate.origin, deadplayer.origin); + + save_interp = m_fDoInterp; + m_fDoInterp = 0; + + result = StudioDrawPlayer(flags, &deadplayer); + + m_fDoInterp = save_interp; + return result; + } + + m_pRenderModel = m_pCurrentEntity->model; + m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(m_pRenderModel); + + IEngineStudio.StudioSetHeader(m_pStudioHeader); + IEngineStudio.SetRenderModel(m_pRenderModel); + + StudioSetUpTransform(0); + + if(m_pCurrentEntity == gEngfuncs.GetViewModel() && (cl_righthand->value)) + { + (*m_protationmatrix)[0][1] *= -1; + (*m_protationmatrix)[1][1] *= -1; + (*m_protationmatrix)[2][1] *= -1; + + //IEngineStudio.StudioSetCullState(true); + } + + if (flags & STUDIO_RENDER) + { + if (!IEngineStudio.StudioCheckBBox()) + return 0; + + (*m_pModelsDrawn)++; + (*m_pStudioModelCount)++; + + if (m_pStudioHeader->numbodyparts == 0) + return 1; + } + + if (m_pCurrentEntity->curstate.movetype == MOVETYPE_FOLLOW) + StudioMergeBones(m_pRenderModel); + else + StudioSetupBones(); + + StudioSaveBones(); + + if (flags & STUDIO_EVENTS) + { + StudioCalcAttachments(); + IEngineStudio.StudioClientEvents(); + + if (m_pCurrentEntity->index > 0) + { + cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index); + memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * 4); + } + } + + if (flags & STUDIO_RENDER) + { + alight_t lighting; + vec3_t dir; + lighting.plightvec = dir; + + IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting); + + IEngineStudio.StudioEntityLight(&lighting); + IEngineStudio.StudioSetupLighting(&lighting); + + m_nTopColor = m_pCurrentEntity->curstate.colormap & 0xFF; + m_nBottomColor = (m_pCurrentEntity->curstate.colormap & 0xFF00) >> 8; + + IEngineStudio.StudioSetRemapColors(m_nTopColor, m_nBottomColor); + + StudioRenderModel(dir); + } + + return 1; +} + +void CStudioModelRenderer::StudioEstimateGait(entity_state_t *pplayer) +{ + float dt; + vec3_t est_velocity; + + dt = (m_clTime - m_clOldTime); + + if (dt < 0) + dt = 0; + else if (dt > 1.0) + dt = 1; + + if (dt == 0 || m_pPlayerInfo->renderframe == m_nFrameCount) + { + m_flGaitMovement = 0; + return; + } + + if (m_fGaitEstimation) + { + VectorSubtract(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity); + VectorCopy(m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin); + m_flGaitMovement = est_velocity.Length(); + + if (dt <= 0 || m_flGaitMovement / dt < 5) + { + m_flGaitMovement = 0; + est_velocity[0] = 0; + est_velocity[1] = 0; + } + } + else + { + VectorCopy(pplayer->velocity, est_velocity); + m_flGaitMovement = est_velocity.Length() * dt; + } + + if (est_velocity[1] == 0 && est_velocity[0] == 0) + { + float flYawDiff = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; + flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; + + if (flYawDiff > 180) + flYawDiff -= 360; + if (flYawDiff < -180) + flYawDiff += 360; + + if (dt < 0.25) + flYawDiff *= dt * 4; + else + flYawDiff *= dt; + + m_pPlayerInfo->gaityaw += flYawDiff; + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360; + m_flGaitMovement = 0; + } + else + { + m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); + + if (m_pPlayerInfo->gaityaw > 180) + m_pPlayerInfo->gaityaw = 180; + + if (m_pPlayerInfo->gaityaw < -180) + m_pPlayerInfo->gaityaw = -180; + } +} + +void CStudioModelRenderer::StudioProcessGait(entity_state_t *pplayer) +{ + mstudioseqdesc_t *pseqdesc; + float dt; + int iBlend; + float flYaw; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; + + StudioPlayerBlend(pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH]); + + m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH]; + m_pCurrentEntity->curstate.blending[0] = iBlend; + m_pCurrentEntity->latched.prevblending[0] = m_pCurrentEntity->curstate.blending[0]; + m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; + + dt = (m_clTime - m_clOldTime); + + if (dt < 0) + dt = 0; + else if (dt > 1.0) + dt = 1; + + StudioEstimateGait(pplayer); + + flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw; + flYaw = flYaw - (int)(flYaw / 360) * 360; + + if (flYaw < -180) + flYaw = flYaw + 360; + + if (flYaw > 180) + flYaw = flYaw - 360; + + if (flYaw > 120) + { + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180; + m_flGaitMovement = -m_flGaitMovement; + flYaw = flYaw - 180; + } + else if (flYaw < -120) + { + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180; + m_flGaitMovement = -m_flGaitMovement; + flYaw = flYaw + 180; + } + + m_pCurrentEntity->curstate.controller[0] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); + m_pCurrentEntity->curstate.controller[1] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); + m_pCurrentEntity->curstate.controller[2] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); + m_pCurrentEntity->curstate.controller[3] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); + m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0]; + m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1]; + m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2]; + m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3]; + + m_pCurrentEntity->angles[YAW] = m_pPlayerInfo->gaityaw; + + if (m_pCurrentEntity->angles[YAW] < -0) + m_pCurrentEntity->angles[YAW] += 360; + + m_pCurrentEntity->latched.prevangles[YAW] = m_pCurrentEntity->angles[YAW]; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence; + + if (pseqdesc->linearmovement[0] > 0) + m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes; + else + m_pPlayerInfo->gaitframe += pseqdesc->fps * dt; + + m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes; + + if (m_pPlayerInfo->gaitframe < 0) + m_pPlayerInfo->gaitframe += pseqdesc->numframes; +} + +int CStudioModelRenderer::StudioDrawPlayer(int flags, entity_state_t *pplayer) +{ + m_pCurrentEntity = IEngineStudio.GetCurrentEntity(); + + IEngineStudio.GetTimes(&m_nFrameCount, &m_clTime, &m_clOldTime); + IEngineStudio.GetViewInfo(m_vRenderOrigin, m_vUp, m_vRight, m_vNormal); + IEngineStudio.GetAliasScale(&m_fSoftwareXScale, &m_fSoftwareYScale); + + m_nPlayerIndex = pplayer->number - 1; + + if (m_nPlayerIndex < 0 || m_nPlayerIndex >= gEngfuncs.GetMaxClients()) + return 0; + + m_pRenderModel = IEngineStudio.SetupPlayerModel(m_nPlayerIndex); + + if (m_pRenderModel == NULL) + return 0; + + m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(m_pRenderModel); + + IEngineStudio.StudioSetHeader(m_pStudioHeader); + IEngineStudio.SetRenderModel(m_pRenderModel); + + if (pplayer->gaitsequence) + { + vec3_t orig_angles; + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + + VectorCopy(m_pCurrentEntity->angles, orig_angles); + + StudioProcessGait(pplayer); + + m_pPlayerInfo->gaitsequence = pplayer->gaitsequence; + m_pPlayerInfo = NULL; + + StudioSetUpTransform(0); + VectorCopy(orig_angles, m_pCurrentEntity->angles); + } + else + { + m_pCurrentEntity->curstate.controller[0] = 127; + m_pCurrentEntity->curstate.controller[1] = 127; + m_pCurrentEntity->curstate.controller[2] = 127; + m_pCurrentEntity->curstate.controller[3] = 127; + m_pCurrentEntity->latched.prevcontroller[0] = m_pCurrentEntity->curstate.controller[0]; + m_pCurrentEntity->latched.prevcontroller[1] = m_pCurrentEntity->curstate.controller[1]; + m_pCurrentEntity->latched.prevcontroller[2] = m_pCurrentEntity->curstate.controller[2]; + m_pCurrentEntity->latched.prevcontroller[3] = m_pCurrentEntity->curstate.controller[3]; + + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + m_pPlayerInfo->gaitsequence = 0; + + StudioSetUpTransform(0); + } + + if (flags & STUDIO_RENDER) + { + if (!IEngineStudio.StudioCheckBBox()) + return 0; + + (*m_pModelsDrawn)++; + (*m_pStudioModelCount)++; + + if (m_pStudioHeader->numbodyparts == 0) + return 1; + } + + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + + StudioSetupBones(); + StudioSaveBones(); + + m_pPlayerInfo->renderframe = m_nFrameCount; + m_pPlayerInfo = NULL; + + if (flags & STUDIO_EVENTS) + { + StudioCalcAttachments(); + IEngineStudio.StudioClientEvents(); + + if (m_pCurrentEntity->index > 0) + { + cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index); + memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(vec3_t) * 4); + } + } + + if (flags & STUDIO_RENDER) + { + if (m_pCvarHiModels->value && m_pRenderModel != m_pCurrentEntity->model) + m_pCurrentEntity->curstate.body = 255; + + if (!(m_pCvarDeveloper->value == 0 && gEngfuncs.GetMaxClients() == 1) && (m_pRenderModel == m_pCurrentEntity->model)) + m_pCurrentEntity->curstate.body = 1; + + alight_t lighting; + vec3_t dir; + lighting.plightvec = dir; + + IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting); + IEngineStudio.StudioEntityLight(&lighting); + IEngineStudio.StudioSetupLighting(&lighting); + + m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex); + + m_nTopColor = m_pPlayerInfo->topcolor; + + if (m_nTopColor < 0) + m_nTopColor = 0; + + if (m_nTopColor > 360) + m_nTopColor = 360; + + m_nBottomColor = m_pPlayerInfo->bottomcolor; + + if (m_nBottomColor < 0) + m_nBottomColor = 0; + + if (m_nBottomColor > 360) + m_nBottomColor = 360; + + IEngineStudio.StudioSetRemapColors(m_nTopColor, m_nBottomColor); + + StudioRenderModel(dir); + m_pPlayerInfo = NULL; + + if (pplayer->weaponmodel) + { + cl_entity_t saveent = *m_pCurrentEntity; + model_t *pweaponmodel = IEngineStudio.GetModelByIndex(pplayer->weaponmodel); + + m_pStudioHeader = (studiohdr_t *)IEngineStudio.Mod_Extradata(pweaponmodel); + IEngineStudio.StudioSetHeader(m_pStudioHeader); + + StudioMergeBones(pweaponmodel); + + IEngineStudio.StudioSetupLighting(&lighting); + + StudioRenderModel(dir); + + StudioCalcAttachments(); + + *m_pCurrentEntity = saveent; + } + } + + return 1; +} + +void CStudioModelRenderer::StudioCalcAttachments(void) +{ + int i; + mstudioattachment_t *pattachment; + + if (m_pStudioHeader->numattachments > 4) + gEngfuncs.Con_DPrintf("Too many attachments on %s\n", m_pCurrentEntity->model->name); + + pattachment = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex); + + for (i = 0; i < m_pStudioHeader->numattachments; i++) + VectorTransform(pattachment[i].org, (*m_plighttransform)[pattachment[i].bone], m_pCurrentEntity->attachment[i]); +} + +void CStudioModelRenderer::StudioRenderModel(float *lightdir) +{ + IEngineStudio.SetChromeOrigin(); + + int iSaveRenderMode = m_pCurrentEntity->curstate.rendermode; + int iSaveRenderFx = m_pCurrentEntity->curstate.renderfx; + int iSaveRenderAmt = m_pCurrentEntity->curstate.renderamt; + + + IEngineStudio.SetForceFaceFlags(0); + StudioRenderFinal(); + + if (iSaveRenderFx == kRenderFxGlowShell) + { + m_pCurrentEntity->curstate.renderfx = kRenderFxGlowShell; + + gEngfuncs.pTriAPI->SpriteTexture(m_pChromeSprite, 0); + + IEngineStudio.SetForceFaceFlags(STUDIO_NF_CHROME); + StudioRenderFinal(); + } + + + m_pCurrentEntity->curstate.rendermode = iSaveRenderMode; + m_pCurrentEntity->curstate.renderfx = iSaveRenderFx; + m_pCurrentEntity->curstate.renderamt = iSaveRenderAmt; +} + +void CStudioModelRenderer::StudioRenderFinal_Software(void) +{ + int i; + + IEngineStudio.SetupRenderer(0); + + if (m_pCvarDrawEntities->value == 2) + { + IEngineStudio.StudioDrawBones(); + } + else if (m_pCvarDrawEntities->value == 3) + { + IEngineStudio.StudioDrawHulls(); + } + else + { + for (i = 0; i < m_pStudioHeader->numbodyparts; i++) + { + IEngineStudio.StudioSetupModel(i, (void **)&m_pBodyPart, (void **)&m_pSubModel); + IEngineStudio.StudioDrawPoints(); + } + } + + if (m_pCvarDrawEntities->value == 4) + { + gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); + IEngineStudio.StudioDrawHulls(); + gEngfuncs.pTriAPI->RenderMode(kRenderNormal); + } + + if (m_pCvarDrawEntities->value == 5) + IEngineStudio.StudioDrawAbsBBox(); + + IEngineStudio.RestoreRenderer(); +} + +void CStudioModelRenderer::StudioRenderFinal_Hardware(void) +{ + int i; + int rendermode; + + rendermode = IEngineStudio.GetForceFaceFlags() ? kRenderTransAdd : m_pCurrentEntity->curstate.rendermode; + IEngineStudio.SetupRenderer(rendermode); + + if (m_pCvarDrawEntities->value == 2) + { + IEngineStudio.StudioDrawBones(); + } + else if (m_pCvarDrawEntities->value == 3) + { + IEngineStudio.StudioDrawHulls(); + } + else + { + for (i = 0; i < m_pStudioHeader->numbodyparts; i++) + { + IEngineStudio.StudioSetupModel(i, (void **)&m_pBodyPart, (void **)&m_pSubModel); + + if (m_fDoInterp) + m_pCurrentEntity->trivial_accept = 0; + + IEngineStudio.GL_SetRenderMode(rendermode); + IEngineStudio.StudioSetRenderamt(m_pCurrentEntity->curstate.renderamt); + IEngineStudio.StudioDrawPoints(); + } + } + + if (m_pCvarDrawEntities->value == 4) + { + gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd); + IEngineStudio.StudioDrawHulls(); + gEngfuncs.pTriAPI->RenderMode(kRenderNormal); + } + + IEngineStudio.RestoreRenderer(); +} + +void CStudioModelRenderer::StudioRenderFinal(void) +{ + if (IEngineStudio.IsHardware()) + StudioRenderFinal_Hardware(); + else + StudioRenderFinal_Software(); +} + +void CStudioModelRenderer::StudioSetShadowSprite(int idx) +{ + m_iShadowSprite = idx; +} + +void CStudioModelRenderer::StudioDrawShadow( Vector origin, float scale ) +{ + Vector endPoint = origin; + Vector p1, p2, p3, p4; + pmtrace_t pmtrace; + + endPoint.z -= 150.0f; + + gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true ); + gEngfuncs.pEventAPI->EV_PushPMStates( ); + gEngfuncs.pEventAPI->EV_SetSolidPlayers( -1 ); + gEngfuncs.pEventAPI->EV_SetTraceHull( 2 ); + gEngfuncs.pEventAPI->EV_PlayerTrace( origin, endPoint, PM_STUDIO_IGNORE | PM_GLASS_IGNORE, -1, &pmtrace ); + gEngfuncs.pEventAPI->EV_PopPMStates( ); + + // don't allow shadow if player in solid area + if( pmtrace.startsolid ) + return; + + // don't allow shadow if doesn't hit anything + if( pmtrace.fraction >= 1.0f ) + return; + + pmtrace.plane.normal = pmtrace.plane.normal.Normalize( ); + + // don't allow shadow on too lean planes + if( pmtrace.plane.normal.z <= 0.7 ) + return; + + pmtrace.plane.normal = pmtrace.plane.normal * scale * ( 1.0 - pmtrace.fraction ); + + + // add 2.0f to Z, for avoid Z-fighting + p1.x = pmtrace.endpos.x - pmtrace.plane.normal.z; + p1.y = pmtrace.endpos.y + pmtrace.plane.normal.z; + p1.z = pmtrace.endpos.z + 2.0f + pmtrace.plane.normal.x - pmtrace.plane.normal.y; + + p2.x = pmtrace.endpos.x + pmtrace.plane.normal.z; + p2.y = pmtrace.endpos.y + pmtrace.plane.normal.z; + p2.z = pmtrace.endpos.z + 2.0f - pmtrace.plane.normal.x - pmtrace.plane.normal.y; + + p3.x = pmtrace.endpos.x + pmtrace.plane.normal.z; + p3.y = pmtrace.endpos.y - pmtrace.plane.normal.z; + p3.z = pmtrace.endpos.z + 2.0f - pmtrace.plane.normal.x + pmtrace.plane.normal.y; + + p4.x = pmtrace.endpos.x - pmtrace.plane.normal.z; + p4.y = pmtrace.endpos.y - pmtrace.plane.normal.z; + p4.z = pmtrace.endpos.z + 2.0f + pmtrace.plane.normal.x + pmtrace.plane.normal.y; + + IEngineStudio.StudioRenderShadow( m_iShadowSprite, p1, p2, p3, p4 ); +} diff --git a/cl_dll/studio/studio_util.cpp b/cl_dll/studio/studio_util.cpp index ab14d96..df5fc4b 100644 --- a/cl_dll/studio/studio_util.cpp +++ b/cl_dll/studio/studio_util.cpp @@ -1,251 +1,251 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include -#include "hud.h" -#include "cl_util.h" -#include "const.h" -#include "com_model.h" -#include "studio_util.h" - -/* -==================== -AngleMatrix - -==================== -*/ -void AngleMatrix (const float *angles, float (*matrix)[4] ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - // matrix = (YAW * PITCH) * ROLL - matrix[0][0] = cp*cy; - matrix[1][0] = cp*sy; - matrix[2][0] = -sp; - matrix[0][1] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[2][1] = sr*cp; - matrix[0][2] = (cr*sp*cy+-sr*-sy); - matrix[1][2] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; - matrix[0][3] = 0.0; - matrix[1][3] = 0.0; - matrix[2][3] = 0.0; -} - -/* -==================== -VectorCompare - -==================== -*/ -int VectorCompare (const float *v1, const float *v2) -{ - int i; - - for (i=0 ; i<3 ; i++) - if (v1[i] != v2[i]) - return 0; - - return 1; -} - -/* -==================== -CrossProduct - -==================== -*/ -void CrossProduct (const float *v1, const float *v2, float *cross) -{ - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -/* -==================== -VectorTransform - -==================== -*/ -void VectorTransform (const float *in1, float in2[3][4], float *out) -{ - out[0] = DotProduct(in1, in2[0]) + in2[0][3]; - out[1] = DotProduct(in1, in2[1]) + in2[1][3]; - out[2] = DotProduct(in1, in2[2]) + in2[2][3]; -} - -/* -================ -ConcatTransforms - -================ -*/ -void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) -{ - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + - in1[0][2] * in2[2][3] + in1[0][3]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + - in1[1][2] * in2[2][3] + in1[1][3]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; - out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + - in1[2][2] * in2[2][3] + in1[2][3]; -} - -// angles index are not the same as ROLL, PITCH, YAW - -/* -==================== -AngleQuaternion - -==================== -*/ -void AngleQuaternion( float *angles, vec4_t quaternion ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - // FIXME: rescale the inputs to 1/2 angle - angle = angles[2] * 0.5; - sy = sin(angle); - cy = cos(angle); - angle = angles[1] * 0.5; - sp = sin(angle); - cp = cos(angle); - angle = angles[0] * 0.5; - sr = sin(angle); - cr = cos(angle); - - quaternion[0] = sr*cp*cy-cr*sp*sy; // X - quaternion[1] = cr*sp*cy+sr*cp*sy; // Y - quaternion[2] = cr*cp*sy-sr*sp*cy; // Z - quaternion[3] = cr*cp*cy+sr*sp*sy; // W -} - -/* -==================== -QuaternionSlerp - -==================== -*/ -void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt ) -{ - int i; - float omega, cosom, sinom, sclp, sclq; - - // decide if one of the quaternions is backwards - float a = 0; - float b = 0; - - for (i = 0; i < 4; i++) - { - a += (p[i]-q[i])*(p[i]-q[i]); - b += (p[i]+q[i])*(p[i]+q[i]); - } - if (a > b) - { - for (i = 0; i < 4; i++) - { - q[i] = -q[i]; - } - } - - cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; - - if ((1.0 + cosom) > 0.000001) - { - if ((1.0 - cosom) > 0.000001) - { - omega = acos( cosom ); - sinom = sin( omega ); - sclp = sin( (1.0 - t)*omega) / sinom; - sclq = sin( t*omega ) / sinom; - } - else - { - sclp = 1.0 - t; - sclq = t; - } - for (i = 0; i < 4; i++) { - qt[i] = sclp * p[i] + sclq * q[i]; - } - } - else - { - qt[0] = -q[1]; - qt[1] = q[0]; - qt[2] = -q[3]; - qt[3] = q[2]; - sclp = sin( (1.0 - t) * (0.5 * M_PI)); - sclq = sin( t * (0.5 * M_PI)); - for (i = 0; i < 3; i++) - { - qt[i] = sclp * p[i] + sclq * qt[i]; - } - } -} - -/* -==================== -QuaternionMatrix - -==================== -*/ -void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ) -{ - matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2]; - matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2]; - matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1]; - - matrix[0][1] = 2.0 * quaternion[0] * quaternion[1] - 2.0 * quaternion[3] * quaternion[2]; - matrix[1][1] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[2] * quaternion[2]; - matrix[2][1] = 2.0 * quaternion[1] * quaternion[2] + 2.0 * quaternion[3] * quaternion[0]; - - matrix[0][2] = 2.0 * quaternion[0] * quaternion[2] + 2.0 * quaternion[3] * quaternion[1]; - matrix[1][2] = 2.0 * quaternion[1] * quaternion[2] - 2.0 * quaternion[3] * quaternion[0]; - matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1]; -} - -/* -==================== -MatrixCopy - -==================== -*/ -void MatrixCopy( float in[3][4], float out[3][4] ) -{ - memcpy( out, in, sizeof( float ) * 3 * 4 ); +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include +#include "hud.h" +#include "cl_util.h" +#include "const.h" +#include "com_model.h" +#include "studio_util.h" + +/* +==================== +AngleMatrix + +==================== +*/ +void AngleMatrix (const float *angles, float (*matrix)[4] ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + // matrix = (YAW * PITCH) * ROLL + matrix[0][0] = cp*cy; + matrix[1][0] = cp*sy; + matrix[2][0] = -sp; + matrix[0][1] = sr*sp*cy+cr*-sy; + matrix[1][1] = sr*sp*sy+cr*cy; + matrix[2][1] = sr*cp; + matrix[0][2] = (cr*sp*cy+-sr*-sy); + matrix[1][2] = (cr*sp*sy+-sr*cy); + matrix[2][2] = cr*cp; + matrix[0][3] = 0.0; + matrix[1][3] = 0.0; + matrix[2][3] = 0.0; +} + +/* +==================== +VectorCompare + +==================== +*/ +int VectorCompare (const float *v1, const float *v2) +{ + int i; + + for (i=0 ; i<3 ; i++) + if (v1[i] != v2[i]) + return 0; + + return 1; +} + +/* +==================== +CrossProduct + +==================== +*/ +void CrossProduct (const float *v1, const float *v2, float *cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +/* +==================== +VectorTransform + +==================== +*/ +void VectorTransform (const float *in1, float in2[3][4], float *out) +{ + out[0] = DotProduct(in1, in2[0]) + in2[0][3]; + out[1] = DotProduct(in1, in2[1]) + in2[1][3]; + out[2] = DotProduct(in1, in2[2]) + in2[2][3]; +} + +/* +================ +ConcatTransforms + +================ +*/ +void ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + + in1[0][2] * in2[2][3] + in1[0][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + + in1[1][2] * in2[2][3] + in1[1][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + + in1[2][2] * in2[2][3] + in1[2][3]; +} + +// angles index are not the same as ROLL, PITCH, YAW + +/* +==================== +AngleQuaternion + +==================== +*/ +void AngleQuaternion( float *angles, vec4_t quaternion ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + // FIXME: rescale the inputs to 1/2 angle + angle = angles[2] * 0.5; + sy = sin(angle); + cy = cos(angle); + angle = angles[1] * 0.5; + sp = sin(angle); + cp = cos(angle); + angle = angles[0] * 0.5; + sr = sin(angle); + cr = cos(angle); + + quaternion[0] = sr*cp*cy-cr*sp*sy; // X + quaternion[1] = cr*sp*cy+sr*cp*sy; // Y + quaternion[2] = cr*cp*sy-sr*sp*cy; // Z + quaternion[3] = cr*cp*cy+sr*sp*sy; // W +} + +/* +==================== +QuaternionSlerp + +==================== +*/ +void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt ) +{ + int i; + float omega, cosom, sinom, sclp, sclq; + + // decide if one of the quaternions is backwards + float a = 0; + float b = 0; + + for (i = 0; i < 4; i++) + { + a += (p[i]-q[i])*(p[i]-q[i]); + b += (p[i]+q[i])*(p[i]+q[i]); + } + if (a > b) + { + for (i = 0; i < 4; i++) + { + q[i] = -q[i]; + } + } + + cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; + + if ((1.0 + cosom) > 0.000001) + { + if ((1.0 - cosom) > 0.000001) + { + omega = acos( cosom ); + sinom = sin( omega ); + sclp = sin( (1.0 - t)*omega) / sinom; + sclq = sin( t*omega ) / sinom; + } + else + { + sclp = 1.0 - t; + sclq = t; + } + for (i = 0; i < 4; i++) { + qt[i] = sclp * p[i] + sclq * q[i]; + } + } + else + { + qt[0] = -q[1]; + qt[1] = q[0]; + qt[2] = -q[3]; + qt[3] = q[2]; + sclp = sin( (1.0 - t) * (0.5 * M_PI)); + sclq = sin( t * (0.5 * M_PI)); + for (i = 0; i < 3; i++) + { + qt[i] = sclp * p[i] + sclq * qt[i]; + } + } +} + +/* +==================== +QuaternionMatrix + +==================== +*/ +void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ) +{ + matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2]; + matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2]; + matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1]; + + matrix[0][1] = 2.0 * quaternion[0] * quaternion[1] - 2.0 * quaternion[3] * quaternion[2]; + matrix[1][1] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[2] * quaternion[2]; + matrix[2][1] = 2.0 * quaternion[1] * quaternion[2] + 2.0 * quaternion[3] * quaternion[0]; + + matrix[0][2] = 2.0 * quaternion[0] * quaternion[2] + 2.0 * quaternion[3] * quaternion[1]; + matrix[1][2] = 2.0 * quaternion[1] * quaternion[2] - 2.0 * quaternion[3] * quaternion[0]; + matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1]; +} + +/* +==================== +MatrixCopy + +==================== +*/ +void MatrixCopy( float in[3][4], float out[3][4] ) +{ + memcpy( out, in, sizeof( float ) * 3 * 4 ); } \ No newline at end of file diff --git a/cl_dll/tri.cpp b/cl_dll/tri.cpp index aef6894..b20d1c2 100644 --- a/cl_dll/tri.cpp +++ b/cl_dll/tri.cpp @@ -1,312 +1,312 @@ -//========= Copyright ? 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// 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" -#include "rain.h" - -#ifdef _WIN32 -#define DLLEXPORT __declspec( dllexport ) -#else -#define DLLEXPORT -#endif - -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 - -#ifdef _MSC_VER -extern "C" { -#endif -void AngleMatrix (const float angles[3], float (*matrix)[4]); -void VectorTransform (const float in1[3], float in2[3][4], float out[3]); -#ifdef _MSC_VER -} -#endif - -void SetPoint( float x, float y, float z, float (*matrix)[4]) -{ - vec3_t point, result; - point[0] = x; - point[1] = y; - point[2] = z; - - VectorTransform(point, matrix, result); - - gEngfuncs.pTriAPI->Vertex3f(result[0], result[1], result[2]); -} - -/* -================================= -DrawRain -draw raindrips and snowflakes -================================= -*/ - -void DrawRain( void ) -{ - if (FirstChainDrip.p_Next == NULL) - return; // no drips to draw - - float visibleHeight = Rain.globalHeight - SNOWFADEDIST; - - // usual triapi stuff - HSPRITE hsprTexture; - if( Rain.weatherMode == 0 ) - hsprTexture = LoadSprite("sprites/effects/rain.spr"); - else - hsprTexture = LoadSprite("sprites/effects/snowflake.spr"); - const model_s *pTexture = gEngfuncs.GetSpritePointer(hsprTexture); - gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)pTexture, 0 ); - gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); - gEngfuncs.pTriAPI->CullFace( TRI_NONE ); - - // go through drips list - cl_drip* Drip = FirstChainDrip.p_Next; - cl_entity_t *player = gEngfuncs.GetLocalPlayer(); - - if ( Rain.weatherMode == 0 ) // draw rain - { - while (Drip != NULL) - { - cl_drip* nextdDrip = Drip->p_Next; - - Vector2D toPlayer; - toPlayer.x = player->origin[0] - Drip->origin[0]; - toPlayer.y = player->origin[1] - Drip->origin[1]; - toPlayer = toPlayer.Normalize(); - - toPlayer.x *= DRIP_SPRITE_HALFWIDTH; - toPlayer.y *= DRIP_SPRITE_HALFWIDTH; - - float shiftX = (Drip->xDelta / DRIPSPEED) * DRIP_SPRITE_HALFHEIGHT; - float shiftY = (Drip->yDelta / DRIPSPEED) * DRIP_SPRITE_HALFHEIGHT; - - // --- draw triangle -------------------------- - gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, Drip->alpha ); - gEngfuncs.pTriAPI->Begin( TRI_TRIANGLES ); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - gEngfuncs.pTriAPI->Vertex3f( Drip->origin[0]-toPlayer.y - shiftX, Drip->origin[1]+toPlayer.x - shiftY,Drip->origin[2] + DRIP_SPRITE_HALFHEIGHT ); - - gEngfuncs.pTriAPI->TexCoord2f( 0.5, 1 ); - gEngfuncs.pTriAPI->Vertex3f( Drip->origin[0] + shiftX, Drip->origin[1] + shiftY, Drip->origin[2]-DRIP_SPRITE_HALFHEIGHT ); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); - gEngfuncs.pTriAPI->Vertex3f( Drip->origin[0]+toPlayer.y - shiftX, Drip->origin[1]-toPlayer.x - shiftY, Drip->origin[2]+DRIP_SPRITE_HALFHEIGHT); - - gEngfuncs.pTriAPI->End(); - // --- draw triangle end ---------------------- - - Drip = nextdDrip; - } - } - - else // draw snow - { - vec3_t normal; - gEngfuncs.GetViewAngles((float*)normal); - - float matrix[3][4]; - AngleMatrix (normal, matrix); // calc view matrix - - while (Drip != NULL) - { - cl_drip* nextdDrip = Drip->p_Next; - - matrix[0][3] = Drip->origin[0]; // write origin to matrix - matrix[1][3] = Drip->origin[1]; - matrix[2][3] = Drip->origin[2]; - - // apply start fading effect - float alpha = (Drip->origin[2] <= visibleHeight) ? Drip->alpha : ((Rain.globalHeight - Drip->origin[2]) / (float)SNOWFADEDIST) * Drip->alpha; - - // --- draw quad -------------------------- - gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, alpha ); - gEngfuncs.pTriAPI->Begin( TRI_QUADS ); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - SetPoint(0, SNOW_SPRITE_HALFSIZE ,SNOW_SPRITE_HALFSIZE, matrix); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); - SetPoint(0, SNOW_SPRITE_HALFSIZE ,-SNOW_SPRITE_HALFSIZE, matrix); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); - SetPoint(0, -SNOW_SPRITE_HALFSIZE ,-SNOW_SPRITE_HALFSIZE, matrix); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); - SetPoint(0, -SNOW_SPRITE_HALFSIZE ,SNOW_SPRITE_HALFSIZE, matrix); - - gEngfuncs.pTriAPI->End(); - // --- draw quad end ---------------------- - - Drip = nextdDrip; - } - } -} - -/* -================================= -DrawFXObjects -================================= -*/ -void DrawFXObjects( void ) -{ - if (FirstChainFX.p_Next == NULL) - return; // no objects to draw - - float curtime = gEngfuncs.GetClientTime(); - - // usual triapi stuff - HSPRITE hsprTexture = LoadSprite("sprites/effects/ripple.spr"); - const model_s *pTexture = gEngfuncs.GetSpritePointer( hsprTexture ); - gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)pTexture, 0 ); - gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); - gEngfuncs.pTriAPI->CullFace( TRI_NONE ); - - // go through objects list - cl_rainfx* curFX = FirstChainFX.p_Next; - while (curFX != NULL) - { - cl_rainfx* nextFX = curFX->p_Next; - - // fadeout - float alpha = ((curFX->birthTime + curFX->life - curtime) / curFX->life) * curFX->alpha; - float size = (curtime - curFX->birthTime) * MAXRINGHALFSIZE; - - - // --- draw quad -------------------------- - gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, alpha ); - gEngfuncs.pTriAPI->Begin( TRI_QUADS ); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); - gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] - size, curFX->origin[1] - size, curFX->origin[2]); - - gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); - gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] - size, curFX->origin[1] + size, curFX->origin[2]); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); - gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] + size, curFX->origin[1] + size, curFX->origin[2]); - - gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); - gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] + size, curFX->origin[1] - size, curFX->origin[2]); - - gEngfuncs.pTriAPI->End(); - // --- draw quad end ---------------------- - - curFX = nextFX; - } -} -/* -================= -HUD_DrawNormalTriangles - -Non-transparent triangles-- add them here -================= -*/ -void DLLEXPORT HUD_DrawNormalTriangles( void ) -{ - - gHUD.m_Spectator.DrawOverview(); - -#if defined( TEST_IT ) -// Draw_Triangles(); -#endif -} - -/* -================= -HUD_DrawTransparentTriangles - -Render any triangles with transparent rendermode needs here -================= -*/ -void DLLEXPORT HUD_DrawTransparentTriangles( void ) -{ - ProcessFXObjects(); - ProcessRain(); - DrawRain(); - DrawFXObjects(); -#if defined( TEST_IT ) -// Draw_Triangles(); -#endif -} +//========= Copyright ? 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// 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" +#include "rain.h" + +#ifdef _WIN32 +#define DLLEXPORT __declspec( dllexport ) +#else +#define DLLEXPORT +#endif + +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 + +#ifdef _MSC_VER +extern "C" { +#endif +void AngleMatrix (const float angles[3], float (*matrix)[4]); +void VectorTransform (const float in1[3], float in2[3][4], float out[3]); +#ifdef _MSC_VER +} +#endif + +void SetPoint( float x, float y, float z, float (*matrix)[4]) +{ + vec3_t point, result; + point[0] = x; + point[1] = y; + point[2] = z; + + VectorTransform(point, matrix, result); + + gEngfuncs.pTriAPI->Vertex3f(result[0], result[1], result[2]); +} + +/* +================================= +DrawRain +draw raindrips and snowflakes +================================= +*/ + +void DrawRain( void ) +{ + if (FirstChainDrip.p_Next == NULL) + return; // no drips to draw + + float visibleHeight = Rain.globalHeight - SNOWFADEDIST; + + // usual triapi stuff + HSPRITE hsprTexture; + if( Rain.weatherMode == 0 ) + hsprTexture = LoadSprite("sprites/effects/rain.spr"); + else + hsprTexture = LoadSprite("sprites/effects/snowflake.spr"); + const model_s *pTexture = gEngfuncs.GetSpritePointer(hsprTexture); + gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)pTexture, 0 ); + gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); + gEngfuncs.pTriAPI->CullFace( TRI_NONE ); + + // go through drips list + cl_drip* Drip = FirstChainDrip.p_Next; + cl_entity_t *player = gEngfuncs.GetLocalPlayer(); + + if ( Rain.weatherMode == 0 ) // draw rain + { + while (Drip != NULL) + { + cl_drip* nextdDrip = Drip->p_Next; + + Vector2D toPlayer; + toPlayer.x = player->origin[0] - Drip->origin[0]; + toPlayer.y = player->origin[1] - Drip->origin[1]; + toPlayer = toPlayer.Normalize(); + + toPlayer.x *= DRIP_SPRITE_HALFWIDTH; + toPlayer.y *= DRIP_SPRITE_HALFWIDTH; + + float shiftX = (Drip->xDelta / DRIPSPEED) * DRIP_SPRITE_HALFHEIGHT; + float shiftY = (Drip->yDelta / DRIPSPEED) * DRIP_SPRITE_HALFHEIGHT; + + // --- draw triangle -------------------------- + gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, Drip->alpha ); + gEngfuncs.pTriAPI->Begin( TRI_TRIANGLES ); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + gEngfuncs.pTriAPI->Vertex3f( Drip->origin[0]-toPlayer.y - shiftX, Drip->origin[1]+toPlayer.x - shiftY,Drip->origin[2] + DRIP_SPRITE_HALFHEIGHT ); + + gEngfuncs.pTriAPI->TexCoord2f( 0.5, 1 ); + gEngfuncs.pTriAPI->Vertex3f( Drip->origin[0] + shiftX, Drip->origin[1] + shiftY, Drip->origin[2]-DRIP_SPRITE_HALFHEIGHT ); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); + gEngfuncs.pTriAPI->Vertex3f( Drip->origin[0]+toPlayer.y - shiftX, Drip->origin[1]-toPlayer.x - shiftY, Drip->origin[2]+DRIP_SPRITE_HALFHEIGHT); + + gEngfuncs.pTriAPI->End(); + // --- draw triangle end ---------------------- + + Drip = nextdDrip; + } + } + + else // draw snow + { + vec3_t normal; + gEngfuncs.GetViewAngles((float*)normal); + + float matrix[3][4]; + AngleMatrix (normal, matrix); // calc view matrix + + while (Drip != NULL) + { + cl_drip* nextdDrip = Drip->p_Next; + + matrix[0][3] = Drip->origin[0]; // write origin to matrix + matrix[1][3] = Drip->origin[1]; + matrix[2][3] = Drip->origin[2]; + + // apply start fading effect + float alpha = (Drip->origin[2] <= visibleHeight) ? Drip->alpha : ((Rain.globalHeight - Drip->origin[2]) / (float)SNOWFADEDIST) * Drip->alpha; + + // --- draw quad -------------------------- + gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, alpha ); + gEngfuncs.pTriAPI->Begin( TRI_QUADS ); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + SetPoint(0, SNOW_SPRITE_HALFSIZE ,SNOW_SPRITE_HALFSIZE, matrix); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); + SetPoint(0, SNOW_SPRITE_HALFSIZE ,-SNOW_SPRITE_HALFSIZE, matrix); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); + SetPoint(0, -SNOW_SPRITE_HALFSIZE ,-SNOW_SPRITE_HALFSIZE, matrix); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); + SetPoint(0, -SNOW_SPRITE_HALFSIZE ,SNOW_SPRITE_HALFSIZE, matrix); + + gEngfuncs.pTriAPI->End(); + // --- draw quad end ---------------------- + + Drip = nextdDrip; + } + } +} + +/* +================================= +DrawFXObjects +================================= +*/ +void DrawFXObjects( void ) +{ + if (FirstChainFX.p_Next == NULL) + return; // no objects to draw + + float curtime = gEngfuncs.GetClientTime(); + + // usual triapi stuff + HSPRITE hsprTexture = LoadSprite("sprites/effects/ripple.spr"); + const model_s *pTexture = gEngfuncs.GetSpritePointer( hsprTexture ); + gEngfuncs.pTriAPI->SpriteTexture( (struct model_s *)pTexture, 0 ); + gEngfuncs.pTriAPI->RenderMode( kRenderTransAdd ); + gEngfuncs.pTriAPI->CullFace( TRI_NONE ); + + // go through objects list + cl_rainfx* curFX = FirstChainFX.p_Next; + while (curFX != NULL) + { + cl_rainfx* nextFX = curFX->p_Next; + + // fadeout + float alpha = ((curFX->birthTime + curFX->life - curtime) / curFX->life) * curFX->alpha; + float size = (curtime - curFX->birthTime) * MAXRINGHALFSIZE; + + + // --- draw quad -------------------------- + gEngfuncs.pTriAPI->Color4f( 1.0, 1.0, 1.0, alpha ); + gEngfuncs.pTriAPI->Begin( TRI_QUADS ); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 0 ); + gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] - size, curFX->origin[1] - size, curFX->origin[2]); + + gEngfuncs.pTriAPI->TexCoord2f( 0, 1 ); + gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] - size, curFX->origin[1] + size, curFX->origin[2]); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 1 ); + gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] + size, curFX->origin[1] + size, curFX->origin[2]); + + gEngfuncs.pTriAPI->TexCoord2f( 1, 0 ); + gEngfuncs.pTriAPI->Vertex3f(curFX->origin[0] + size, curFX->origin[1] - size, curFX->origin[2]); + + gEngfuncs.pTriAPI->End(); + // --- draw quad end ---------------------- + + curFX = nextFX; + } +} +/* +================= +HUD_DrawNormalTriangles + +Non-transparent triangles-- add them here +================= +*/ +void DLLEXPORT HUD_DrawNormalTriangles( void ) +{ + + gHUD.m_Spectator.DrawOverview(); + +#if defined( TEST_IT ) +// Draw_Triangles(); +#endif +} + +/* +================= +HUD_DrawTransparentTriangles + +Render any triangles with transparent rendermode needs here +================= +*/ +void DLLEXPORT HUD_DrawTransparentTriangles( void ) +{ + ProcessFXObjects(); + ProcessRain(); + DrawRain(); + DrawFXObjects(); +#if defined( TEST_IT ) +// Draw_Triangles(); +#endif +} diff --git a/cl_dll/util.cpp b/cl_dll/util.cpp index ad20c31..30fe5a5 100644 --- a/cl_dll/util.cpp +++ b/cl_dll/util.cpp @@ -1,198 +1,198 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// util.cpp -// -// implementation of class-less helper functions -// - -#include "stdio.h" -#include "stdlib.h" -#include "math.h" - -#include "hud.h" -#include "cl_util.h" -#include - -#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) -{ - int i; - char sz[256]; - - if (ScreenWidth < 640) - i = 320; - else - i = 640; - - sprintf(sz, pszName, i); - - return SPR_Load(sz); -} - -int HUD_GetSpriteIndexByName( const char *sz ) -{ - return gHUD.GetSpriteIndex(sz); -} - -HSPRITE HUD_GetSprite( int index ) -{ - return gHUD.GetSprite(index); -} - -wrect_t HUD_GetSpriteRect( int index ) -{ - return gHUD.GetSpriteRect( index ); -} - -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 g_ColorGrey[3] = { 0.8, 0.8, 0.8 }; - -float *GetClientColor( int clientIndex ) -{ - switch ( g_PlayerExtraInfo[clientIndex].teamnumber ) - { - case TEAM_TERRORIST: return g_ColorRed; - case TEAM_CT: return g_ColorBlue; - case TEAM_SPECTATOR: - case TEAM_UNASSIGNED: return g_ColorYellow; - case 4: return g_ColorGreen; - default: return g_ColorGrey; - } -} - -void GetTeamColor(int &r, int &g, int &b, int teamIndex) -{ - r = 255; - g = 255; - b = 255; - switch( teamIndex ) - { - case TEAM_TERRORIST: - r *= g_ColorRed[0]; - g *= g_ColorRed[1]; - b *= g_ColorRed[2]; - break; - case TEAM_CT: - r *= g_ColorBlue[0]; - g *= g_ColorBlue[1]; - b *= g_ColorBlue[2]; - break; - case TEAM_SPECTATOR: - case TEAM_UNASSIGNED: - r *= g_ColorYellow[0]; - g *= g_ColorYellow[1]; - b *= g_ColorYellow[2]; - break; - default: - r *= g_ColorGrey[0]; - g *= g_ColorGrey[1]; - b *= g_ColorGrey[2]; - break; - } -} - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// util.cpp +// +// implementation of class-less helper functions +// + +#include "stdio.h" +#include "stdlib.h" +#include "math.h" + +#include "hud.h" +#include "cl_util.h" +#include + +#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) +{ + int i; + char sz[256]; + + if (ScreenWidth < 640) + i = 320; + else + i = 640; + + sprintf(sz, pszName, i); + + return SPR_Load(sz); +} + +int HUD_GetSpriteIndexByName( const char *sz ) +{ + return gHUD.GetSpriteIndex(sz); +} + +HSPRITE HUD_GetSprite( int index ) +{ + return gHUD.GetSprite(index); +} + +wrect_t HUD_GetSpriteRect( int index ) +{ + return gHUD.GetSpriteRect( index ); +} + +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 g_ColorGrey[3] = { 0.8, 0.8, 0.8 }; + +float *GetClientColor( int clientIndex ) +{ + switch ( g_PlayerExtraInfo[clientIndex].teamnumber ) + { + case TEAM_TERRORIST: return g_ColorRed; + case TEAM_CT: return g_ColorBlue; + case TEAM_SPECTATOR: + case TEAM_UNASSIGNED: return g_ColorYellow; + case 4: return g_ColorGreen; + default: return g_ColorGrey; + } +} + +void GetTeamColor(int &r, int &g, int &b, int teamIndex) +{ + r = 255; + g = 255; + b = 255; + switch( teamIndex ) + { + case TEAM_TERRORIST: + r *= g_ColorRed[0]; + g *= g_ColorRed[1]; + b *= g_ColorRed[2]; + break; + case TEAM_CT: + r *= g_ColorBlue[0]; + g *= g_ColorBlue[1]; + b *= g_ColorBlue[2]; + break; + case TEAM_SPECTATOR: + case TEAM_UNASSIGNED: + r *= g_ColorYellow[0]; + g *= g_ColorYellow[1]; + b *= g_ColorYellow[2]; + break; + default: + r *= g_ColorGrey[0]; + g *= g_ColorGrey[1]; + b *= g_ColorGrey[2]; + break; + } +} + diff --git a/cl_dll/view.cpp b/cl_dll/view.cpp index 0d22555..6215321 100644 --- a/cl_dll/view.cpp +++ b/cl_dll/view.cpp @@ -1,1799 +1,1799 @@ -//========= Copyright ? 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// view/refresh setup functions - -#include "hud.h" -#include "cl_util.h" -#include "cvardef.h" -#include "usercmd.h" -#include "const.h" -#include - -#include "entity_state.h" -#include "cl_entity.h" -#include "ref_params.h" -#include "in_defs.h" // PITCH YAW ROLL -#include "pm_movevars.h" -#include "pm_shared.h" -#include "pm_defs.h" -#include "event_api.h" -#include "pmtrace.h" -#include "screenfade.h" -#include "shake.h" -#include "hltv.h" - -// Spectator Mode -extern "C" -{ -float vecNewViewAngles[3]; -int iHasNewViewAngles; -float vecNewViewOrigin[3]; -int iHasNewViewOrigin; -int iIsSpectator; -} - -#ifndef M_PI -#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h -#endif - -extern "C" -{ -int CL_IsThirdPerson( void ); -void CL_CameraOffset( float *ofs ); - -void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams ); - -void PM_ParticleLine( float *start, float *end, int pcolor, float life, float vert); -int PM_GetVisEntInfo( int ent ); -int PM_GetPhysEntInfo( int ent ); -void InterpolateAngles( float * start, float * end, float * output, float frac ); -void NormalizeAngles( float * angles ); -float Distance(const float * v1, const float * v2); -float AngleBetweenVectors( const float * v1, const float * v2 ); - -float vJumpOrigin[3]; -float vJumpAngles[3]; -} - -void V_DropPunchAngle ( float frametime, float *ev_punchangle ); -void VectorAngles( const float *forward, float *angles ); - -#include "r_studioint.h" -#include "com_model.h" - -extern engine_studio_api_t IEngineStudio; - -/* -The view is allowed to move slightly from it's true position for bobbing, -but if it exceeds 8 pixels linear distance (spherical, not box), the list of -entities sent from the server may not include everything in the pvs, especially -when crossing a water boudnary. -*/ - -extern cvar_t *cl_forwardspeed; -extern cvar_t *chase_active; -extern cvar_t *scr_ofsx, *scr_ofsy, *scr_ofsz; -extern cvar_t *cl_vsmoothing; - -#define CAM_MODE_RELAX 1 -#define CAM_MODE_FOCUS 2 - -vec3_t v_origin, v_angles, v_cl_angles, v_sim_org, v_lastAngles; -float v_frametime, v_lastDistance; -float v_cameraRelaxAngle = 5.0f; -float v_cameraFocusAngle = 35.0f; -int v_cameraMode = CAM_MODE_FOCUS; -qboolean v_resetCamera = 1; - -vec3_t ev_punchangle; - -cvar_t *scr_ofsx; -cvar_t *scr_ofsy; -cvar_t *scr_ofsz; - -cvar_t *v_centermove; -cvar_t *v_centerspeed; - -cvar_t *cl_bobcycle; -cvar_t *cl_bob; -cvar_t *cl_bobup; -cvar_t *cl_waterdist; -cvar_t *cl_chasedist; - -// These cvars are not registered (so users can't cheat), so set the ->value field directly -// Register these cvars in V_Init() if needed for easy tweaking -cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", 0, 2}; -cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", 0, 0.5}; -cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", 0, 1}; -cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", 0, 0.3}; -cvar_t v_iroll_level = {"v_iroll_level", "0.1", 0, 0.1}; -cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", 0, 0.3}; - -float v_idlescale; // used by TFC for concussion grenade effect - -//============================================================================= -/* -void V_NormalizeAngles( float *angles ) -{ - int i; - // Normalize angles - for ( i = 0; i < 3; i++ ) - { - if ( angles[i] > 180.0 ) - { - angles[i] -= 360.0; - } - else if ( angles[i] < -180.0 ) - { - angles[i] += 360.0; - } - } -} - -/* -=================== -V_InterpolateAngles - -Interpolate Euler angles. -FIXME: Use Quaternions to avoid discontinuities -Frac is 0.0 to 1.0 ( i.e., should probably be clamped, but doesn't have to be ) -=================== - -void V_InterpolateAngles( float *start, float *end, float *output, float frac ) -{ - int i; - float ang1, ang2; - float d; - - V_NormalizeAngles( start ); - V_NormalizeAngles( end ); - - for ( i = 0 ; i < 3 ; i++ ) - { - ang1 = start[i]; - ang2 = end[i]; - - d = ang2 - ang1; - if ( d > 180 ) - { - d -= 360; - } - else if ( d < -180 ) - { - d += 360; - } - - output[i] = ang1 + d * frac; - } - - V_NormalizeAngles( output ); -} */ - -// Quakeworld bob code, this fixes jitters in the mutliplayer since the clock (pparams->time) isn't quite linear -float V_CalcBob ( struct ref_params_s *pparams ) -{ - static double bobtime; - static float bob; - float cycle; - static float lasttime; - vec3_t vel; - - - if ( pparams->onground == -1 || - pparams->time == lasttime ) - { - // just use old value - return bob; - } - - lasttime = pparams->time; - - bobtime += pparams->frametime; - cycle = bobtime - (int)( bobtime / cl_bobcycle->value ) * cl_bobcycle->value; - cycle /= cl_bobcycle->value; - - if ( cycle < cl_bobup->value ) - { - cycle = M_PI * cycle / cl_bobup->value; - } - else - { - cycle = M_PI + M_PI * ( cycle - cl_bobup->value )/( 1.0 - cl_bobup->value ); - } - - // bob is proportional to simulated velocity in the xy plane - // (don't count Z, or jumping messes it up) - VectorCopy( pparams->simvel, vel ); - vel[2] = 0; - - bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value; - bob = bob * 0.3 + bob * 0.7 * sin(cycle); - bob = min( bob, 4 ); - bob = max( bob, -7 ); - return bob; - -} - -/* -=============== -V_CalcRoll -Used by view and sv_user -=============== -*/ -float V_CalcRoll (vec3_t angles, vec3_t velocity, float rollangle, float rollspeed ) -{ - float sign; - float side; - float value; - vec3_t forward, right, up; - - AngleVectors ( angles, forward, right, up ); - - side = DotProduct (velocity, right); - sign = side < 0 ? -1 : 1; - side = fabs( side ); - - value = rollangle; - if (side < rollspeed) - { - side = side * value / rollspeed; - } - else - { - side = value; - } - return side * sign; -} -#if 0 -typedef struct pitchdrift_s -{ - float pitchvel; - int nodrift; - float driftmove; - double laststop; -} pitchdrift_t; - -static pitchdrift_t pd; - -void V_StartPitchDrift( void ) -{ - if ( pd.laststop == gEngfuncs.GetClientTime() ) - { - return; // something else is keeping it from drifting - } - - if ( pd.nodrift || !pd.pitchvel ) - { - pd.pitchvel = v_centerspeed->value; - pd.nodrift = 0; - pd.driftmove = 0; - } -} - -void V_StopPitchDrift ( void ) -{ - pd.laststop = gEngfuncs.GetClientTime(); - pd.nodrift = 1; - pd.pitchvel = 0; -} - -/* -=============== -V_DriftPitch - -Moves the client pitch angle towards idealpitch sent by the server. - -If the user is adjusting pitch manually, either with lookup/lookdown, -mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped. -=============== -*/ -void V_DriftPitch ( struct ref_params_s *pparams ) -{ - float delta, move; - - if ( gEngfuncs.IsNoClipping() || !pparams->onground || pparams->demoplayback || pparams->spectator ) - { - pd.driftmove = 0; - pd.pitchvel = 0; - return; - } - - // don't count small mouse motion - if (pd.nodrift) - { - if ( fabs( pparams->cmd->forwardmove ) < cl_forwardspeed->value ) - pd.driftmove = 0; - else - pd.driftmove += pparams->frametime; - - if ( pd.driftmove > v_centermove->value) - { - V_StartPitchDrift (); - } - return; - } - - delta = pparams->idealpitch - pparams->cl_viewangles[PITCH]; - - if (!delta) - { - pd.pitchvel = 0; - return; - } - - move = pparams->frametime * pd.pitchvel; - pd.pitchvel += pparams->frametime * v_centerspeed->value; - - if (delta > 0) - { - if (move > delta) - { - pd.pitchvel = 0; - move = delta; - } - pparams->cl_viewangles[PITCH] += move; - } - else if (delta < 0) - { - if (move > -delta) - { - pd.pitchvel = 0; - move = -delta; - } - pparams->cl_viewangles[PITCH] -= move; - } -} -#endif -/* -============================================================================== - VIEW RENDERING -============================================================================== -*/ - -/* -================== -V_CalcGunAngle -================== -*/ -void V_CalcGunAngle ( struct ref_params_s *pparams ) -{ - cl_entity_t *viewent; - - viewent = gEngfuncs.GetViewModel(); - if ( !viewent ) - return; - - viewent->angles[YAW] = pparams->viewangles[YAW] + pparams->crosshairangle[YAW]; - viewent->angles[PITCH] = -pparams->viewangles[PITCH] + pparams->crosshairangle[PITCH] * 0.25; - viewent->angles[ROLL] -= v_idlescale * sin(pparams->time*v_iroll_cycle.value) * v_iroll_level.value; - - // don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view. - viewent->angles[PITCH] -= v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * (v_ipitch_level.value * 0.5); - viewent->angles[YAW] -= v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; - - VectorCopy( viewent->angles, viewent->curstate.angles ); - VectorCopy( viewent->angles, viewent->latched.prevangles ); -} - -/* -============== -V_AddIdle - -Idle swaying -============== -*/ -void V_AddIdle ( struct ref_params_s *pparams ) -{ - pparams->viewangles[ROLL] += v_idlescale * sin(pparams->time*v_iroll_cycle.value) * v_iroll_level.value; - pparams->viewangles[PITCH] += v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * v_ipitch_level.value; - pparams->viewangles[YAW] += v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; -} - - -/* -============== -V_CalcViewRoll - -Roll is induced by movement and damage -============== -*/ -void V_CalcViewRoll ( struct ref_params_s *pparams ) -{ - float side; - cl_entity_t *viewentity; - - viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity ); - if ( !viewentity ) - return; - - side = V_CalcRoll ( viewentity->angles, pparams->simvel, pparams->movevars->rollangle, pparams->movevars->rollspeed ); - - pparams->viewangles[ROLL] += side; - - if ( pparams->health <= 0 && ( pparams->viewheight[2] != 0 ) ) - { - // only roll the view if the player is dead and the viewheight[2] is nonzero - // this is so deadcam in multiplayer will work. - pparams->viewangles[ROLL] = 80; // dead view angle - return; - } -} - - -/* -================== -V_CalcIntermissionRefdef - -================== -*/ -void V_CalcIntermissionRefdef ( struct ref_params_s *pparams ) -{ - cl_entity_t *ent, *view; - float old; - - // ent is the player model ( visible when out of body ) - ent = gEngfuncs.GetLocalPlayer(); - - // view is the weapon model (only visible from inside body ) - view = gEngfuncs.GetViewModel(); - - VectorCopy ( pparams->simorg, pparams->vieworg ); - VectorCopy ( pparams->cl_viewangles, pparams->viewangles ); - - view->model = NULL; - - // allways idle in intermission - old = v_idlescale; - v_idlescale = 1; - - V_AddIdle ( pparams ); - - if ( gEngfuncs.IsSpectateOnly() ) - { - // in HLTV we must go to 'intermission' position by ourself - VectorCopy( gHUD.m_Spectator.m_cameraOrigin, pparams->vieworg ); - VectorCopy( gHUD.m_Spectator.m_cameraAngles, pparams->viewangles ); - } - - v_idlescale = old; - - v_cl_angles = pparams->cl_viewangles; - v_origin = pparams->vieworg; - v_angles = pparams->viewangles; -} - -#define ORIGIN_BACKUP 64 -#define ORIGIN_MASK ( ORIGIN_BACKUP - 1 ) - -typedef struct -{ - float Origins[ ORIGIN_BACKUP ][3]; - float OriginTime[ ORIGIN_BACKUP ]; - - float Angles[ ORIGIN_BACKUP ][3]; - float AngleTime[ ORIGIN_BACKUP ]; - - int CurrentOrigin; - int CurrentAngle; -} viewinterp_t; - -/* -================== -V_CalcRefdef - -================== -*/ -void V_CalcNormalRefdef ( struct ref_params_s *pparams ) -{ - cl_entity_t *ent, *view; - int i; - vec3_t angles; - float bob, waterOffset; - static viewinterp_t ViewInterp; - - static float oldz = 0; - static float lasttime; - - vec3_t camAngles, camForward, camRight, camUp; - cl_entity_t *pwater; - - //V_DriftPitch ( pparams ); - - if ( gEngfuncs.IsSpectateOnly() ) - { - ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); - } - else - { - // ent is the player model ( visible when out of body ) - ent = gEngfuncs.GetLocalPlayer(); - } - - // view is the weapon model (only visible from inside body ) - view = gEngfuncs.GetViewModel(); - - // transform the view offset by the model's matrix to get the offset from - // model origin for the view - bob = V_CalcBob ( pparams ); - - // refresh position - VectorCopy ( pparams->simorg, pparams->vieworg ); - pparams->vieworg[2] += ( bob ); - VectorAdd( pparams->vieworg, pparams->viewheight, pparams->vieworg ); - - VectorCopy ( pparams->cl_viewangles, pparams->viewangles ); - - gEngfuncs.V_CalcShake(); - gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0 ); - - // never let view origin sit exactly on a node line, because a water plane can - // dissapear when viewed with the eye exactly on it. - // FIXME, we send origin at 1/128 now, change this? - // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis - - pparams->vieworg[0] += 1.0/32; - pparams->vieworg[1] += 1.0/32; - pparams->vieworg[2] += 1.0/32; - - // Check for problems around water, move the viewer artificially if necessary - // -- this prevents drawing errors in GL due to waves - - waterOffset = 0; - if ( pparams->waterlevel >= 2 ) - { - int i, contents, waterDist, waterEntity; - vec3_t point; - waterDist = cl_waterdist->value; - - if ( pparams->hardware ) - { - waterEntity = gEngfuncs.PM_WaterEntity( pparams->simorg ); - if ( waterEntity >= 0 && waterEntity < pparams->max_entities ) - { - pwater = gEngfuncs.GetEntityByIndex( waterEntity ); - if ( pwater && ( pwater->model != NULL ) ) - { - waterDist += ( pwater->curstate.scale * 16 ); // Add in wave height - } - } - } - else - { - waterEntity = 0; // Don't need this in software - } - - VectorCopy( pparams->vieworg, point ); - - // Eyes are above water, make sure we're above the waves - if ( pparams->waterlevel == 2 ) - { - point[2] -= waterDist; - for ( i = 0; i < waterDist; i++ ) - { - contents = gEngfuncs.PM_PointContents( point, NULL ); - if ( contents > CONTENTS_WATER ) - break; - point[2] += 1; - } - waterOffset = (point[2] + waterDist) - pparams->vieworg[2]; - } - else - { - // eyes are under water. Make sure we're far enough under - point[2] += waterDist; - - for ( i = 0; i < waterDist; i++ ) - { - contents = gEngfuncs.PM_PointContents( point, NULL ); - if ( contents <= CONTENTS_WATER ) - break; - point[2] -= 1; - } - waterOffset = (point[2] - waterDist) - pparams->vieworg[2]; - } - } - - pparams->vieworg[2] += waterOffset; - - V_CalcViewRoll ( pparams ); - - V_AddIdle ( pparams ); - - // offsets - VectorCopy( pparams->cl_viewangles, angles ); - - AngleVectors ( angles, pparams->forward, pparams->right, pparams->up ); - - // don't allow cheats in multiplayer - if ( pparams->maxclients <= 1 ) - { - for ( i=0 ; i<3 ; i++ ) - { - pparams->vieworg[i] += scr_ofsx->value*pparams->forward[i] + scr_ofsy->value*pparams->right[i] + scr_ofsz->value*pparams->up[i]; - } - } - - // Treating cam_ofs[2] as the distance - if( CL_IsThirdPerson() ) - { - vec3_t ofs; - - ofs[0] = ofs[1] = ofs[2] = 0.0; - - CL_CameraOffset( (float *)&ofs ); - - VectorCopy( ofs, camAngles ); - camAngles[ ROLL ] = 0; - - AngleVectors( camAngles, camForward, camRight, camUp ); - - for ( i = 0; i < 3; i++ ) - { - pparams->vieworg[ i ] += -ofs[2] * camForward[ i ]; - } - } - - // Give gun our viewangles - VectorCopy ( pparams->cl_viewangles, view->angles ); - - // set up gun position - V_CalcGunAngle ( pparams ); - - // Use predicted origin as view origin. - VectorCopy ( pparams->simorg, view->origin ); - view->origin[2] += ( waterOffset ); - VectorAdd( view->origin, pparams->viewheight, view->origin ); - - // Let the viewmodel shake at about 10% of the amplitude - gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9 ); - - for ( i = 0; i < 3; i++ ) - { - view->origin[ i ] += bob * 0.4 * pparams->forward[ i ]; - } - view->origin[2] += bob; - - // throw in a little tilt. - view->angles[YAW] -= bob * 0.5; - view->angles[ROLL] -= bob * 1; - view->angles[PITCH] -= bob * 0.3; - - // pushing the view origin down off of the same X/Z plane as the ent's origin will give the - // gun a very nice 'shifting' effect when the player looks up/down. If there is a problem - // with view model distortion, this may be a cause. (SJB). - view->origin[2] -= 1; - - // fudge position around to keep amount of weapon visible - // roughly equal with different FOV - if (pparams->viewsize == 110) - { - view->origin[2] += 1; - } - else if (pparams->viewsize == 100) - { - view->origin[2] += 2; - } - else if (pparams->viewsize == 90) - { - view->origin[2] += 1; - } - else if (pparams->viewsize == 80) - { - view->origin[2] += 0.5; - } - - // Add in the punchangle, if any - VectorAdd ( pparams->viewangles, pparams->punchangle, pparams->viewangles ); - - // Include client side punch, too - VectorAdd ( pparams->viewangles, (float *)&ev_punchangle, pparams->viewangles); - - V_DropPunchAngle ( pparams->frametime, (float *)&ev_punchangle ); - - // smooth out stair step ups -#if 1 - if ( !pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0) - { - float steptime; - - steptime = pparams->time - lasttime; - if (steptime < 0) - //FIXME I_Error ("steptime < 0"); - steptime = 0; - - oldz += steptime * 150; - if (oldz > pparams->simorg[2]) - oldz = pparams->simorg[2]; - if (pparams->simorg[2] - oldz > 18) - oldz = pparams->simorg[2]- 18; - pparams->vieworg[2] += oldz - pparams->simorg[2]; - view->origin[2] += oldz - pparams->simorg[2]; - } - else - { - oldz = pparams->simorg[2]; - } -#endif - - { - static float lastorg[3]; - vec3_t delta; - - VectorSubtract( pparams->simorg, lastorg, delta ); - - if ( Length( delta ) != 0.0 ) - { - VectorCopy( pparams->simorg, ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] ); - ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time; - ViewInterp.CurrentOrigin++; - - VectorCopy( pparams->simorg, lastorg ); - } - } - - // Smooth out whole view in multiplayer when on trains, lifts - if ( cl_vsmoothing && cl_vsmoothing->value && - ( pparams->smoothing && ( pparams->maxclients > 1 ) ) ) - { - int foundidx; - int i; - float t; - - if ( cl_vsmoothing->value < 0.0 ) - { - gEngfuncs.Cvar_SetValue( "cl_vsmoothing", 0.0 ); - } - - t = pparams->time - cl_vsmoothing->value; - - for ( i = 1; i < ORIGIN_MASK; i++ ) - { - foundidx = ViewInterp.CurrentOrigin - 1 - i; - if ( ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] <= t ) - break; - } - - if ( i < ORIGIN_MASK && ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] != 0.0 ) - { - // Interpolate - vec3_t delta; - double frac; - double dt; - vec3_t neworg; - - dt = ViewInterp.OriginTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ]; - if ( dt > 0.0 ) - { - frac = ( t - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK] ) / dt; - frac = min( 1.0, frac ); - VectorSubtract( ViewInterp.Origins[ ( foundidx + 1 ) & ORIGIN_MASK ], ViewInterp.Origins[ foundidx & ORIGIN_MASK ], delta ); - VectorMA( ViewInterp.Origins[ foundidx & ORIGIN_MASK ], frac, delta, neworg ); - - // Dont interpolate large changes - if ( Length( delta ) < 64 ) - { - VectorSubtract( neworg, pparams->simorg, delta ); - - VectorAdd( pparams->simorg, delta, pparams->simorg ); - VectorAdd( pparams->vieworg, delta, pparams->vieworg ); - VectorAdd( view->origin, delta, view->origin ); - - } - } - } - } - - // Store off v_angles before munging for third person - v_angles = pparams->viewangles; - v_lastAngles = pparams->viewangles; - // v_cl_angles = pparams->cl_viewangles; // keep old user mouse angles ! - if ( CL_IsThirdPerson() ) - { - VectorCopy( camAngles, pparams->viewangles); - float pitch = camAngles[ 0 ]; - - // Normalize angles - if ( pitch > 180 ) - pitch -= 360.0; - else if ( pitch < -180 ) - pitch += 360; - - // Player pitch is inverted - pitch /= -3.0; - - // Slam local player's pitch value - ent->angles[ 0 ] = pitch; - ent->curstate.angles[ 0 ] = pitch; - ent->prevstate.angles[ 0 ] = pitch; - ent->latched.prevangles[ 0 ] = pitch; - } - - // override all previous settings if the viewent isn't the client - if ( pparams->viewentity > pparams->maxclients ) - { - cl_entity_t *viewentity; - viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity ); - if ( viewentity ) - { - VectorCopy( viewentity->origin, pparams->vieworg ); - VectorCopy( viewentity->angles, pparams->viewangles ); - - // Store off overridden viewangles - v_angles = pparams->viewangles; - } - } - - lasttime = pparams->time; - - v_origin = pparams->vieworg; -} - -void V_SmoothInterpolateAngles( float * startAngle, float * endAngle, float * finalAngle, float degreesPerSec ) -{ - float absd,frac,d,threshhold; - - NormalizeAngles( startAngle ); - NormalizeAngles( endAngle ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - d = endAngle[i] - startAngle[i]; - - if ( d > 180.0f ) - { - d -= 360.0f; - } - else if ( d < -180.0f ) - { - d += 360.0f; - } - - absd = fabs(d); - - if ( absd > 0.01f ) - { - frac = degreesPerSec * v_frametime; - - threshhold= degreesPerSec / 4; - - if ( absd < threshhold ) - { - float h = absd / threshhold; - h *= h; - frac*= h; // slow down last degrees - } - - if ( frac > absd ) - { - finalAngle[i] = endAngle[i]; - } - else - { - if ( d>0) - finalAngle[i] = startAngle[i] + frac; - else - finalAngle[i] = startAngle[i] - frac; - } - } - else - { - finalAngle[i] = endAngle[i]; - } - - } - - NormalizeAngles( finalAngle ); -} - -// Get the origin of the Observer based around the target's position and angles -void V_GetChaseOrigin( float * angles, float * origin, float distance, float * returnvec ) -{ - vec3_t vecEnd; - vec3_t forward; - vec3_t vecStart; - pmtrace_t * trace; - int maxLoops = 8; - - int ignoreent = -1; // first, ignore no entity - - cl_entity_t * ent = NULL; - - // Trace back from the target using the player's view angles - AngleVectors(angles, forward, NULL, NULL); - - VectorScale(forward,-1,forward); - - VectorCopy( origin, vecStart ); - - VectorMA(vecStart, distance , forward, vecEnd); - - while ( maxLoops > 0) - { - trace = gEngfuncs.PM_TraceLine( vecStart, vecEnd, PM_TRACELINE_PHYSENTSONLY, 2, ignoreent ); - - // WARNING! trace->ent is is the number in physent list not the normal entity number - - if ( trace->ent <= 0) - break; // we hit the world or nothing, stop trace - - ent = gEngfuncs.GetEntityByIndex( PM_GetPhysEntInfo( trace->ent ) ); - - // hit non-player solid BSP , stop here - if ( ent == NULL && ent->curstate.solid == SOLID_BSP && !ent->player ) - break; - - // if close enought to end pos, stop, otherwise continue trace - if( Distance(trace->endpos, vecEnd ) < 1.0f ) - { - break; - } - else - { - ignoreent = trace->ent; // ignore last hit entity - VectorCopy( trace->endpos, vecStart); - } - - maxLoops--; - } - - /*if ( ent ) - { - gEngfuncs.Con_Printf("Trace loops %i , entity %i, model %s, solid %i\n",(8-maxLoops),ent->curstate.number, ent->model->name , ent->curstate.solid ); - }*/ - - VectorMA( trace->endpos, 8, trace->plane.normal, returnvec ); - - //gEngfuncs.Con_DPrintf("origin(%f %f %f) returnvec(%f %f %f)\n", origin[0], origin[1], origin[2], returnvec[0], returnvec[1], returnvec[2]); - - v_lastDistance = Distance(trace->endpos, origin); // real distance without offset -} - -void V_GetDeathCam(cl_entity_t * ent1, cl_entity_t * ent2, float * angle, float * origin) -{ - float newAngle[3]; - float newOrigin[3]; - static vec3_t nonDestructedOrigin; - float distance = 168.0f; - - v_lastDistance+= v_frametime * 96.0f; // move unit per seconds back - - if ( v_resetCamera ) - v_lastDistance = 64.0f; - - if ( distance > v_lastDistance ) - distance = v_lastDistance; - - if (ent1->origin.x == 0 && ent1->origin.y == 0 && ent1->origin.z == 0) - nonDestructedOrigin.CopyToArray(newOrigin); - else - { - nonDestructedOrigin = ent1->origin; - VectorCopy(ent1->origin, newOrigin); - } - - if ( ent1->player ) - newOrigin[2]+= 17; // head level of living player - - // get new angle towards second target - if ( ent2 ) - { - VectorSubtract(ent2->origin, nonDestructedOrigin, newAngle); - VectorAngles( newAngle, newAngle ); - newAngle[0] = -newAngle[0]; - } - else - { - // if no second target is given, look down to dead player - newAngle[0] = 90.0f; - newAngle[1] = 0.0f; - newAngle[2] = 0; - } - - // and smooth view - V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 120.0f ); - - V_GetChaseOrigin( angle, newOrigin, distance, origin ); - - VectorCopy(angle, v_lastAngles); -} - -void V_GetSingleTargetCam(cl_entity_t * ent1, float * angle, float * origin) -{ - float newAngle[3]; float newOrigin[3]; - - int flags = gHUD.m_Spectator.m_iObserverFlags; - - // see is target is a dead player - qboolean deadPlayer = ent1->player && (ent1->curstate.solid == SOLID_NOT); - - float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; - - float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; - - // go away in final scenes or if player just died - if ( flags & DRC_FLAG_FINAL ) - distance*=2.0f; - else if ( deadPlayer ) - distance*=1.5f; - - // let v_lastDistance float smoothly away - v_lastDistance+= v_frametime * 32.0f; // move unit per seconds back - - if ( distance > v_lastDistance ) - distance = v_lastDistance; - - VectorCopy(ent1->origin, newOrigin); - - if ( ent1->player ) - { - if ( deadPlayer ) - newOrigin[2]+= 2; //laying on ground - else - newOrigin[2]+= 17; // head level of living player - - } - else - newOrigin[2]+= 8; // object, tricky, must be above bomb in CS - - // we have no second target, choose view direction based on - // show front of primary target - VectorCopy(ent1->angles, newAngle); - - // show dead players from front, normal players back - if ( flags & DRC_FLAG_FACEPLAYER ) - newAngle[1]+= 180.0f; - - - newAngle[0]+= 12.5f * dfactor; // lower angle if dramatic - - // if final scene (bomb), show from real high pos - if ( flags & DRC_FLAG_FINAL ) - newAngle[0] = 22.5f; - - // choose side of object/player - if ( flags & DRC_FLAG_SIDE ) - newAngle[1]+=22.5f; - else - newAngle[1]-=22.5f; - - V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 120.0f ); - - // HACK, if player is dead don't clip against his dead body, can't check this - V_GetChaseOrigin( angle, newOrigin, distance, origin ); -} - -float MaxAngleBetweenAngles( float * a1, float * a2 ) -{ - float d, maxd = 0.0f; - - NormalizeAngles( a1 ); - NormalizeAngles( a2 ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - d = a2[i] - a1[i]; - if ( d > 180 ) - { - d -= 360; - } - else if ( d < -180 ) - { - d += 360; - } - - d = fabs(d); - - if ( d > maxd ) - maxd=d; - } - - return maxd; -} - -void V_GetDoubleTargetsCam(cl_entity_t * ent1, cl_entity_t * ent2,float * angle, float * origin) -{ - float newAngle[3]; float newOrigin[3]; float tempVec[3]; - - int flags = gHUD.m_Spectator.m_iObserverFlags; - - float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; - - float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; - - // go away in final scenes or if player just died - if ( flags & DRC_FLAG_FINAL ) - distance*=2.0f; - - // let v_lastDistance float smoothly away - v_lastDistance+= v_frametime * 32.0f; // move unit per seconds back - - if ( distance > v_lastDistance ) - distance = v_lastDistance; - - VectorCopy(ent1->origin, newOrigin); - - if ( ent1->player ) - newOrigin[2]+= 17; // head level of living player - else - newOrigin[2]+= 8; // object, tricky, must be above bomb in CS - - // get new angle towards second target - VectorSubtract( ent2->origin, ent1->origin, newAngle ); - - VectorAngles( newAngle, newAngle ); - newAngle[0] = -newAngle[0]; - - // set angle diffrent in Dramtaic scenes - newAngle[0]+= 12.5f * dfactor; // lower angle if dramatic - - if ( flags & DRC_FLAG_SIDE ) - newAngle[1]+=22.5f; - else - newAngle[1]-=22.5f; - - float d = MaxAngleBetweenAngles( v_lastAngles, newAngle ); - - if ( ( d < v_cameraFocusAngle) && ( v_cameraMode == CAM_MODE_RELAX ) ) - { - // difference is to small and we are in relax camera mode, keep viewangles - VectorCopy(v_lastAngles, newAngle ); - } - else if ( (d < v_cameraRelaxAngle) && (v_cameraMode == CAM_MODE_FOCUS) ) - { - // we catched up with our target, relax again - v_cameraMode = CAM_MODE_RELAX; - } - else - { - // target move too far away, focus camera again - v_cameraMode = CAM_MODE_FOCUS; - } - - // and smooth view, if not a scene cut - if ( v_resetCamera || (v_cameraMode == CAM_MODE_RELAX) ) - { - VectorCopy( newAngle, angle ); - } - else - { - V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 180.0f ); - } - - V_GetChaseOrigin( newAngle, newOrigin, distance, origin ); - - // move position up, if very close at target - if ( v_lastDistance < 64.0f ) - origin[2]+= 16.0f*( 1.0f - (v_lastDistance / 64.0f ) ); - - // calculate angle to second target - VectorSubtract( ent2->origin, origin, tempVec ); - VectorAngles( tempVec, tempVec ); - tempVec[0] = -tempVec[0]; - - /* take middle between two viewangles - InterpolateAngles( newAngle, tempVec, newAngle, 0.5f); */ - - - -} - -void V_GetDirectedChasePosition(cl_entity_t * ent1, cl_entity_t * ent2,float * angle, float * origin) -{ - - if ( v_resetCamera ) - { - v_lastDistance = 4096.0f; - // v_cameraMode = CAM_MODE_FOCUS; - } - - if ( ( ent2 == (cl_entity_t*)0xFFFFFFFF ) || ( ent1->player && (ent1->curstate.solid == SOLID_NOT) ) ) - { - // we have no second target or player just died - V_GetSingleTargetCam(ent1, angle, origin); - } - else if ( ent2 ) - { - // keep both target in view - V_GetDoubleTargetsCam( ent1, ent2, angle, origin ); - } - else - { - // second target disappeard somehow (dead) - - // keep last good viewangle - float newOrigin[3]; - - int flags = gHUD.m_Spectator.m_iObserverFlags; - - float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; - - float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; - - // go away in final scenes or if player just died - if ( flags & DRC_FLAG_FINAL ) - distance*=2.0f; - - // let v_lastDistance float smoothly away - v_lastDistance+= v_frametime * 32.0f; // move unit per seconds back - - if ( distance > v_lastDistance ) - distance = v_lastDistance; - - VectorCopy(ent1->origin, newOrigin); - - if ( ent1->player ) - newOrigin[2]+= 17; // head level of living player - else - newOrigin[2]+= 8; // object, tricky, must be above bomb in CS - - V_GetChaseOrigin( angle, newOrigin, distance, origin ); - } - - VectorCopy(angle, v_lastAngles); -} - -void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles) -{ - cl_entity_t * ent = NULL; - cl_entity_t *local = gEngfuncs.GetLocalPlayer(); - - if ( target ) - { - ent = gEngfuncs.GetEntityByIndex( target ); - } - - if (!ent) - { - // just copy a save in-map position - VectorCopy ( vJumpAngles, angles ); - VectorCopy ( vJumpOrigin, origin ); - return; - } - - - if( ent->index == local->index ) - { - if ( g_iUser3 && g_iUser3 != 1 ) - V_GetDeathCam( ent, gEngfuncs.GetEntityByIndex( g_iUser3 ), - angles, origin ); - else - V_GetDeathCam( ent, NULL, - angles, origin ); - } - else if ( gHUD.m_Spectator.m_autoDirector->value ) - { - if ( g_iUser3 && g_iUser3 != 1 ) - V_GetDirectedChasePosition( ent, gEngfuncs.GetEntityByIndex( g_iUser3 ), - angles, origin ); - else - V_GetDirectedChasePosition( ent, (cl_entity_t*)0xFFFFFFFF, - angles, origin ); - } - else - { - if ( cl_angles == NULL ) // no mouse angles given, use entity angles ( locked mode ) - { - VectorCopy ( ent->angles, angles); - angles[0]*=-1; - } - else - VectorCopy ( cl_angles, angles); - - - VectorCopy ( ent->origin, origin); - - origin[2]+= 28; // DEFAULT_VIEWHEIGHT - some offset - - V_GetChaseOrigin( angles, origin, cl_chasedist->value, origin ); - } - - v_resetCamera = false; -} - -void V_ResetChaseCam() -{ - v_resetCamera = true; -} - - -void V_GetInEyePos(int target, float * origin, float * angles ) -{ - if ( !target) - { - // just copy a save in-map position - VectorCopy ( vJumpAngles, angles ); - VectorCopy ( vJumpOrigin, origin ); - return; - }; - - - cl_entity_t * ent = gEngfuncs.GetEntityByIndex( target ); - - if ( !ent ) - return; - - VectorCopy ( ent->origin, origin ); - VectorCopy ( ent->angles, angles ); - - angles[PITCH]*=-3.0f; // see CL_ProcessEntityUpdate() - - if ( ent->curstate.solid == SOLID_NOT ) - { - angles[ROLL] = 80; // dead view angle - origin[2]+= -8 ; // PM_DEAD_VIEWHEIGHT - } - else if (ent->curstate.usehull == 1 ) - origin[2]+= 12; // VEC_DUCK_VIEW; - else - // exacty eye position can't be caluculated since it depends on - // client values like cl_bobcycle, this offset matches the default values - origin[2]+= 28; // DEFAULT_VIEWHEIGHT -} - -void V_GetMapFreePosition( float * cl_angles, float * origin, float * angles ) -{ - vec3_t forward; - vec3_t zScaledTarget; - - VectorCopy(cl_angles, angles); - - // modify angles since we don't wanna see map's bottom - angles[0] = 51.25f + 38.75f*(angles[0]/90.0f); - - zScaledTarget[0] = gHUD.m_Spectator.m_mapOrigin[0]; - zScaledTarget[1] = gHUD.m_Spectator.m_mapOrigin[1]; - zScaledTarget[2] = gHUD.m_Spectator.m_mapOrigin[2] * (( 90.0f - angles[0] ) / 90.0f ); - - - AngleVectors(angles, forward, NULL, NULL); - - VectorNormalize(forward); - - VectorMA(zScaledTarget, -( 4096.0f / gHUD.m_Spectator.m_mapZoom ), forward , origin); -} - -void V_GetMapChasePosition(int target, float * cl_angles, float * origin, float * angles) -{ - vec3_t forward; - - if ( target ) - { - cl_entity_t * ent = gEngfuncs.GetEntityByIndex( target ); - - if ( gHUD.m_Spectator.m_autoDirector->value ) - { - // this is done to get the angles made by director mode - V_GetChasePos(target, cl_angles, origin, angles); - VectorCopy(ent->origin, origin); - - // keep fix chase angle horizontal - angles[0] = 45.0f; - } - else - { - VectorCopy(cl_angles, angles); - VectorCopy(ent->origin, origin); - - // modify angles since we don't wanna see map's bottom - angles[0] = 51.25f + 38.75f*(angles[0]/90.0f); - } - } - else - { - // keep out roaming position, but modify angles - VectorCopy(cl_angles, angles); - angles[0] = 51.25f + 38.75f*(angles[0]/90.0f); - } - - origin[2] *= (( 90.0f - angles[0] ) / 90.0f ); - angles[2] = 0.0f; // don't roll angle (if chased player is dead) - - AngleVectors(angles, forward, NULL, NULL); - - VectorNormalize(forward); - - VectorMA(origin, -1536, forward, origin); -} - -int V_FindViewModelByWeaponModel(int weaponindex) -{ - - static char * modelmap[][2] = { - { "models/p_crossbow.mdl", "models/v_crossbow.mdl" }, - { "models/p_crowbar.mdl", "models/v_crowbar.mdl" }, - { "models/p_egon.mdl", "models/v_egon.mdl" }, - { "models/p_gauss.mdl", "models/v_gauss.mdl" }, - { "models/p_9mmhandgun.mdl", "models/v_9mmhandgun.mdl" }, - { "models/p_grenade.mdl", "models/v_grenade.mdl" }, - { "models/p_hgun.mdl", "models/v_hgun.mdl" }, - { "models/p_9mmAR.mdl", "models/v_9mmAR.mdl" }, - { "models/p_357.mdl", "models/v_357.mdl" }, - { "models/p_rpg.mdl", "models/v_rpg.mdl" }, - { "models/p_shotgun.mdl", "models/v_shotgun.mdl" }, - { "models/p_squeak.mdl", "models/v_squeak.mdl" }, - { "models/p_tripmine.mdl", "models/v_tripmine.mdl" }, - { "models/p_satchel_radio.mdl", "models/v_satchel_radio.mdl"}, - { "models/p_satchel.mdl", "models/v_satchel.mdl" }, - { NULL, NULL } }; - - struct model_s * weaponModel = IEngineStudio.GetModelByIndex( weaponindex ); - - if ( weaponModel ) - { - int len = strlen( weaponModel->name ); - int i = 0; - - while ( modelmap[i] != NULL ) - { - if ( !strnicmp( weaponModel->name, modelmap[i][0], len ) ) - { - return gEngfuncs.pEventAPI->EV_FindModelIndex( modelmap[i][1] ); - } - i++; - } - - return 0; - } - else - return 0; - -} - - -/* -================== -V_CalcSpectatorRefdef - -================== -*/ -void V_CalcSpectatorRefdef ( struct ref_params_s * pparams ) -{ - static vec3_t velocity ( 0.0f, 0.0f, 0.0f); - - static int lastWeaponModelIndex = 0; - static int lastViewModelIndex = 0; - - cl_entity_t * ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); - - pparams->onlyClientDraw = false; - - // refresh position - VectorCopy ( pparams->simorg, v_sim_org ); - - // get old values - VectorCopy ( pparams->cl_viewangles, v_cl_angles ); - VectorCopy ( pparams->viewangles, v_angles ); - VectorCopy ( pparams->vieworg, v_origin ); - - if ( ( g_iUser1 == OBS_IN_EYE || gHUD.m_Spectator.m_pip->value == INSET_IN_EYE ) && ent ) - { - // calculate player velocity - float timeDiff = ent->curstate.msg_time - ent->prevstate.msg_time; - - if ( timeDiff > 0 ) - { - vec3_t distance; - VectorSubtract(ent->prevstate.origin, ent->curstate.origin, distance); - VectorScale(distance, 1/timeDiff, distance ); - - velocity[0] = velocity[0]*0.9f + distance[0]*0.1f; - velocity[1] = velocity[1]*0.9f + distance[1]*0.1f; - velocity[2] = velocity[2]*0.9f + distance[2]*0.1f; - - VectorCopy(velocity, pparams->simvel); - } - - // predict missing client data and set weapon model ( in HLTV mode or inset in eye mode ) - if ( gEngfuncs.IsSpectateOnly() ) - { - V_GetInEyePos( g_iUser2, pparams->simorg, pparams->cl_viewangles ); - - pparams->health = 1; - - cl_entity_t * gunModel = gEngfuncs.GetViewModel(); - - if ( lastWeaponModelIndex != ent->curstate.weaponmodel ) - { - // weapon model changed - - lastWeaponModelIndex = ent->curstate.weaponmodel; - lastViewModelIndex = V_FindViewModelByWeaponModel( lastWeaponModelIndex ); - if ( lastViewModelIndex ) - { - gEngfuncs.pfnWeaponAnim(0,0); // reset weapon animation - } - else - { - // model not found - gunModel->model = NULL; // disable weapon model - lastWeaponModelIndex = lastViewModelIndex = 0; - } - } - - if ( lastViewModelIndex ) - { - gunModel->model = IEngineStudio.GetModelByIndex( lastViewModelIndex ); - gunModel->curstate.modelindex = lastViewModelIndex; - gunModel->curstate.frame = 0; - gunModel->curstate.colormap = 0; - gunModel->index = g_iUser2; - } - else - { - gunModel->model = NULL; // disable weaopn model - } - } - else - { - // only get viewangles from entity - VectorCopy ( ent->angles, pparams->cl_viewangles ); - pparams->cl_viewangles[PITCH]*=-3.0f; // see CL_ProcessEntityUpdate() - } - } - - v_frametime = pparams->frametime; - - if ( pparams->nextView == 0 ) - { - // first renderer cycle, full screen - - switch ( g_iUser1 ) - { - case OBS_CHASE_LOCKED: - V_GetChasePos( g_iUser2, NULL, v_origin, v_angles ); - break; - - case OBS_CHASE_FREE: - V_GetChasePos( g_iUser2, v_cl_angles, v_origin, v_angles ); - break; - - case OBS_ROAMING: - VectorCopy (v_cl_angles, v_angles); - VectorCopy (v_sim_org, v_origin); - break; - - case OBS_IN_EYE: - V_CalcNormalRefdef ( pparams ); - break; - - case OBS_MAP_FREE: - pparams->onlyClientDraw = true; - V_GetMapFreePosition( v_cl_angles, v_origin, v_angles ); - break; - - case OBS_MAP_CHASE: - pparams->onlyClientDraw = true; - V_GetMapChasePosition( g_iUser2, v_cl_angles, v_origin, v_angles ); - break; - } - - if ( gHUD.m_Spectator.m_pip->value ) - pparams->nextView = 1; // force a second renderer view - - gHUD.m_Spectator.m_iDrawCycle = 0; - - } - else - { - // second renderer cycle, inset window - - // set inset parameters - pparams->viewport[0] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowX); // change viewport to inset window - pparams->viewport[1] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowY); - pparams->viewport[2] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowWidth); - pparams->viewport[3] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowHeight); - pparams->nextView = 0; // on further view - - // override some settings in certain modes - switch ( (int)gHUD.m_Spectator.m_pip->value ) - { - case INSET_CHASE_FREE: - V_GetChasePos( g_iUser2, v_cl_angles, v_origin, v_angles ); - break; - - case INSET_IN_EYE: - V_CalcNormalRefdef ( pparams ); - break; - - case INSET_MAP_FREE: - pparams->onlyClientDraw = true; - V_GetMapFreePosition( v_cl_angles, v_origin, v_angles ); - break; - - case INSET_MAP_CHASE: - pparams->onlyClientDraw = true; - - if ( g_iUser1 == OBS_ROAMING ) - V_GetMapChasePosition( 0, v_cl_angles, v_origin, v_angles ); - else - V_GetMapChasePosition( g_iUser2, v_cl_angles, v_origin, v_angles ); - - break; - } - - gHUD.m_Spectator.m_iDrawCycle = 1; - } - - // write back new values into pparams - VectorCopy ( v_cl_angles, pparams->cl_viewangles ); - VectorCopy ( v_angles, pparams->viewangles ) - VectorCopy ( v_origin, pparams->vieworg ); - -} - - - -void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams ) -{ - // intermission / finale rendering - if ( pparams->intermission ) - { - V_CalcIntermissionRefdef ( pparams ); - } - else if ( pparams->spectator || g_iUser1 ) // g_iUser true if in spectator mode - { - V_CalcSpectatorRefdef ( pparams ); - } - else if ( !pparams->paused ) - { - V_CalcNormalRefdef ( pparams ); - } - - /* -// Example of how to overlay the whole screen with red at 50 % alpha -#define SF_TEST -#if defined SF_TEST - { - screenfade_t sf; - gEngfuncs.pfnGetScreenFade( &sf ); - - sf.fader = 255; - sf.fadeg = 0; - sf.fadeb = 0; - sf.fadealpha = 128; - sf.fadeFlags = FFADE_STAYOUT | FFADE_OUT; - - gEngfuncs.pfnSetScreenFade( &sf ); - } -#endif -*/ -} - -/* -============= -V_DropPunchAngle - -============= -*/ -void V_DropPunchAngle ( float frametime, float *ev_punchangle ) -{ - float len; - - len = VectorNormalize ( ev_punchangle ); - len -= (10.0 + len * 0.5) * frametime; - len = max( len, 0.0 ); - VectorScale ( ev_punchangle, len, ev_punchangle ); -} - -/* -============= -V_PunchAxis - -Client side punch effect -============= -*/ -void V_PunchAxis( int axis, float punch ) -{ - ev_punchangle[ axis ] = punch; -} - -/* -============= -V_Init -============= -*/ -void V_Init (void) -{ - //gEngfuncs.pfnAddCommand ("centerview", V_StartPitchDrift ); - - scr_ofsx = gEngfuncs.pfnRegisterVariable( "scr_ofsx","0", 0 ); - scr_ofsy = gEngfuncs.pfnRegisterVariable( "scr_ofsy","0", 0 ); - scr_ofsz = gEngfuncs.pfnRegisterVariable( "scr_ofsz","0", 0 ); - - v_centermove = gEngfuncs.pfnRegisterVariable( "v_centermove", "0.15", 0 ); - v_centerspeed = gEngfuncs.pfnRegisterVariable( "v_centerspeed","500", 0 ); - - cl_bobcycle = gEngfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0 );// best default for my experimental gun wag (sjb) - cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", 0 );// best default for my experimental gun wag (sjb) - cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 ); - cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 ); - cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 ); -} - - -//#define TRACE_TEST -#if defined( TRACE_TEST ) - -extern float in_fov; -/* -==================== -CalcFov -==================== -*/ -float CalcFov (float fov_x, float width, float height) -{ - float a; - float x; - - if (fov_x < 1 || fov_x > 179) - fov_x = 90; // error, set to 90 - - x = width/tan(fov_x/360*M_PI); - - a = atan (height/x); - - a = a*360/M_PI; - - return a; -} - -int hitent = -1; - -void V_Move( int mx, int my ) -{ - float fov; - float fx, fy; - float dx, dy; - float c_x, c_y; - float dX, dY; - vec3_t forward, up, right; - vec3_t newangles; - - vec3_t farpoint; - pmtrace_t tr; - - fov = CalcFov( in_fov, (float)ScreenWidth, (float)ScreenHeight ); - - c_x = (float)ScreenWidth / 2.0; - c_y = (float)ScreenHeight / 2.0; - - dx = (float)mx - c_x; - dy = (float)my - c_y; - - // Proportion we moved in each direction - fx = dx / c_x; - fy = dy / c_y; - - dX = fx * in_fov / 2.0 ; - dY = fy * fov / 2.0; - - newangles = v_angles; - - newangles[ YAW ] -= dX; - newangles[ PITCH ] += dY; - - // Now rotate v_forward around that point - AngleVectors ( newangles, forward, right, up ); - - farpoint = v_origin + 8192 * forward; - - // Trace - tr = *(gEngfuncs.PM_TraceLine( (float *)&v_origin, (float *)&farpoint, PM_TRACELINE_PHYSENTSONLY, 2 /*point sized hull*/, -1 )); - - if ( tr.fraction != 1.0 && tr.ent != 0 ) - { - hitent = PM_GetPhysEntInfo( tr.ent ); - PM_ParticleLine( (float *)&v_origin, (float *)&tr.endpos, 5, 1.0, 0.0 ); - } - else - { - hitent = -1; - } -} - -#endif +//========= Copyright ? 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// view/refresh setup functions + +#include "hud.h" +#include "cl_util.h" +#include "cvardef.h" +#include "usercmd.h" +#include "const.h" +#include + +#include "entity_state.h" +#include "cl_entity.h" +#include "ref_params.h" +#include "in_defs.h" // PITCH YAW ROLL +#include "pm_movevars.h" +#include "pm_shared.h" +#include "pm_defs.h" +#include "event_api.h" +#include "pmtrace.h" +#include "screenfade.h" +#include "shake.h" +#include "hltv.h" + +// Spectator Mode +extern "C" +{ +float vecNewViewAngles[3]; +int iHasNewViewAngles; +float vecNewViewOrigin[3]; +int iHasNewViewOrigin; +int iIsSpectator; +} + +#ifndef M_PI +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif + +extern "C" +{ +int CL_IsThirdPerson( void ); +void CL_CameraOffset( float *ofs ); + +void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams ); + +void PM_ParticleLine( float *start, float *end, int pcolor, float life, float vert); +int PM_GetVisEntInfo( int ent ); +int PM_GetPhysEntInfo( int ent ); +void InterpolateAngles( float * start, float * end, float * output, float frac ); +void NormalizeAngles( float * angles ); +float Distance(const float * v1, const float * v2); +float AngleBetweenVectors( const float * v1, const float * v2 ); + +float vJumpOrigin[3]; +float vJumpAngles[3]; +} + +void V_DropPunchAngle ( float frametime, float *ev_punchangle ); +void VectorAngles( const float *forward, float *angles ); + +#include "r_studioint.h" +#include "com_model.h" + +extern engine_studio_api_t IEngineStudio; + +/* +The view is allowed to move slightly from it's true position for bobbing, +but if it exceeds 8 pixels linear distance (spherical, not box), the list of +entities sent from the server may not include everything in the pvs, especially +when crossing a water boudnary. +*/ + +extern cvar_t *cl_forwardspeed; +extern cvar_t *chase_active; +extern cvar_t *scr_ofsx, *scr_ofsy, *scr_ofsz; +extern cvar_t *cl_vsmoothing; + +#define CAM_MODE_RELAX 1 +#define CAM_MODE_FOCUS 2 + +vec3_t v_origin, v_angles, v_cl_angles, v_sim_org, v_lastAngles; +float v_frametime, v_lastDistance; +float v_cameraRelaxAngle = 5.0f; +float v_cameraFocusAngle = 35.0f; +int v_cameraMode = CAM_MODE_FOCUS; +qboolean v_resetCamera = 1; + +vec3_t ev_punchangle; + +cvar_t *scr_ofsx; +cvar_t *scr_ofsy; +cvar_t *scr_ofsz; + +cvar_t *v_centermove; +cvar_t *v_centerspeed; + +cvar_t *cl_bobcycle; +cvar_t *cl_bob; +cvar_t *cl_bobup; +cvar_t *cl_waterdist; +cvar_t *cl_chasedist; + +// These cvars are not registered (so users can't cheat), so set the ->value field directly +// Register these cvars in V_Init() if needed for easy tweaking +cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", 0, 2}; +cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", 0, 0.5}; +cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", 0, 1}; +cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", 0, 0.3}; +cvar_t v_iroll_level = {"v_iroll_level", "0.1", 0, 0.1}; +cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", 0, 0.3}; + +float v_idlescale; // used by TFC for concussion grenade effect + +//============================================================================= +/* +void V_NormalizeAngles( float *angles ) +{ + int i; + // Normalize angles + for ( i = 0; i < 3; i++ ) + { + if ( angles[i] > 180.0 ) + { + angles[i] -= 360.0; + } + else if ( angles[i] < -180.0 ) + { + angles[i] += 360.0; + } + } +} + +/* +=================== +V_InterpolateAngles + +Interpolate Euler angles. +FIXME: Use Quaternions to avoid discontinuities +Frac is 0.0 to 1.0 ( i.e., should probably be clamped, but doesn't have to be ) +=================== + +void V_InterpolateAngles( float *start, float *end, float *output, float frac ) +{ + int i; + float ang1, ang2; + float d; + + V_NormalizeAngles( start ); + V_NormalizeAngles( end ); + + for ( i = 0 ; i < 3 ; i++ ) + { + ang1 = start[i]; + ang2 = end[i]; + + d = ang2 - ang1; + if ( d > 180 ) + { + d -= 360; + } + else if ( d < -180 ) + { + d += 360; + } + + output[i] = ang1 + d * frac; + } + + V_NormalizeAngles( output ); +} */ + +// Quakeworld bob code, this fixes jitters in the mutliplayer since the clock (pparams->time) isn't quite linear +float V_CalcBob ( struct ref_params_s *pparams ) +{ + static double bobtime; + static float bob; + float cycle; + static float lasttime; + vec3_t vel; + + + if ( pparams->onground == -1 || + pparams->time == lasttime ) + { + // just use old value + return bob; + } + + lasttime = pparams->time; + + bobtime += pparams->frametime; + cycle = bobtime - (int)( bobtime / cl_bobcycle->value ) * cl_bobcycle->value; + cycle /= cl_bobcycle->value; + + if ( cycle < cl_bobup->value ) + { + cycle = M_PI * cycle / cl_bobup->value; + } + else + { + cycle = M_PI + M_PI * ( cycle - cl_bobup->value )/( 1.0 - cl_bobup->value ); + } + + // bob is proportional to simulated velocity in the xy plane + // (don't count Z, or jumping messes it up) + VectorCopy( pparams->simvel, vel ); + vel[2] = 0; + + bob = sqrt( vel[0] * vel[0] + vel[1] * vel[1] ) * cl_bob->value; + bob = bob * 0.3 + bob * 0.7 * sin(cycle); + bob = min( bob, 4 ); + bob = max( bob, -7 ); + return bob; + +} + +/* +=============== +V_CalcRoll +Used by view and sv_user +=============== +*/ +float V_CalcRoll (vec3_t angles, vec3_t velocity, float rollangle, float rollspeed ) +{ + float sign; + float side; + float value; + vec3_t forward, right, up; + + AngleVectors ( angles, forward, right, up ); + + side = DotProduct (velocity, right); + sign = side < 0 ? -1 : 1; + side = fabs( side ); + + value = rollangle; + if (side < rollspeed) + { + side = side * value / rollspeed; + } + else + { + side = value; + } + return side * sign; +} +#if 0 +typedef struct pitchdrift_s +{ + float pitchvel; + int nodrift; + float driftmove; + double laststop; +} pitchdrift_t; + +static pitchdrift_t pd; + +void V_StartPitchDrift( void ) +{ + if ( pd.laststop == gEngfuncs.GetClientTime() ) + { + return; // something else is keeping it from drifting + } + + if ( pd.nodrift || !pd.pitchvel ) + { + pd.pitchvel = v_centerspeed->value; + pd.nodrift = 0; + pd.driftmove = 0; + } +} + +void V_StopPitchDrift ( void ) +{ + pd.laststop = gEngfuncs.GetClientTime(); + pd.nodrift = 1; + pd.pitchvel = 0; +} + +/* +=============== +V_DriftPitch + +Moves the client pitch angle towards idealpitch sent by the server. + +If the user is adjusting pitch manually, either with lookup/lookdown, +mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped. +=============== +*/ +void V_DriftPitch ( struct ref_params_s *pparams ) +{ + float delta, move; + + if ( gEngfuncs.IsNoClipping() || !pparams->onground || pparams->demoplayback || pparams->spectator ) + { + pd.driftmove = 0; + pd.pitchvel = 0; + return; + } + + // don't count small mouse motion + if (pd.nodrift) + { + if ( fabs( pparams->cmd->forwardmove ) < cl_forwardspeed->value ) + pd.driftmove = 0; + else + pd.driftmove += pparams->frametime; + + if ( pd.driftmove > v_centermove->value) + { + V_StartPitchDrift (); + } + return; + } + + delta = pparams->idealpitch - pparams->cl_viewangles[PITCH]; + + if (!delta) + { + pd.pitchvel = 0; + return; + } + + move = pparams->frametime * pd.pitchvel; + pd.pitchvel += pparams->frametime * v_centerspeed->value; + + if (delta > 0) + { + if (move > delta) + { + pd.pitchvel = 0; + move = delta; + } + pparams->cl_viewangles[PITCH] += move; + } + else if (delta < 0) + { + if (move > -delta) + { + pd.pitchvel = 0; + move = -delta; + } + pparams->cl_viewangles[PITCH] -= move; + } +} +#endif +/* +============================================================================== + VIEW RENDERING +============================================================================== +*/ + +/* +================== +V_CalcGunAngle +================== +*/ +void V_CalcGunAngle ( struct ref_params_s *pparams ) +{ + cl_entity_t *viewent; + + viewent = gEngfuncs.GetViewModel(); + if ( !viewent ) + return; + + viewent->angles[YAW] = pparams->viewangles[YAW] + pparams->crosshairangle[YAW]; + viewent->angles[PITCH] = -pparams->viewangles[PITCH] + pparams->crosshairangle[PITCH] * 0.25; + viewent->angles[ROLL] -= v_idlescale * sin(pparams->time*v_iroll_cycle.value) * v_iroll_level.value; + + // don't apply all of the v_ipitch to prevent normally unseen parts of viewmodel from coming into view. + viewent->angles[PITCH] -= v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * (v_ipitch_level.value * 0.5); + viewent->angles[YAW] -= v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; + + VectorCopy( viewent->angles, viewent->curstate.angles ); + VectorCopy( viewent->angles, viewent->latched.prevangles ); +} + +/* +============== +V_AddIdle + +Idle swaying +============== +*/ +void V_AddIdle ( struct ref_params_s *pparams ) +{ + pparams->viewangles[ROLL] += v_idlescale * sin(pparams->time*v_iroll_cycle.value) * v_iroll_level.value; + pparams->viewangles[PITCH] += v_idlescale * sin(pparams->time*v_ipitch_cycle.value) * v_ipitch_level.value; + pparams->viewangles[YAW] += v_idlescale * sin(pparams->time*v_iyaw_cycle.value) * v_iyaw_level.value; +} + + +/* +============== +V_CalcViewRoll + +Roll is induced by movement and damage +============== +*/ +void V_CalcViewRoll ( struct ref_params_s *pparams ) +{ + float side; + cl_entity_t *viewentity; + + viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity ); + if ( !viewentity ) + return; + + side = V_CalcRoll ( viewentity->angles, pparams->simvel, pparams->movevars->rollangle, pparams->movevars->rollspeed ); + + pparams->viewangles[ROLL] += side; + + if ( pparams->health <= 0 && ( pparams->viewheight[2] != 0 ) ) + { + // only roll the view if the player is dead and the viewheight[2] is nonzero + // this is so deadcam in multiplayer will work. + pparams->viewangles[ROLL] = 80; // dead view angle + return; + } +} + + +/* +================== +V_CalcIntermissionRefdef + +================== +*/ +void V_CalcIntermissionRefdef ( struct ref_params_s *pparams ) +{ + cl_entity_t *ent, *view; + float old; + + // ent is the player model ( visible when out of body ) + ent = gEngfuncs.GetLocalPlayer(); + + // view is the weapon model (only visible from inside body ) + view = gEngfuncs.GetViewModel(); + + VectorCopy ( pparams->simorg, pparams->vieworg ); + VectorCopy ( pparams->cl_viewangles, pparams->viewangles ); + + view->model = NULL; + + // allways idle in intermission + old = v_idlescale; + v_idlescale = 1; + + V_AddIdle ( pparams ); + + if ( gEngfuncs.IsSpectateOnly() ) + { + // in HLTV we must go to 'intermission' position by ourself + VectorCopy( gHUD.m_Spectator.m_cameraOrigin, pparams->vieworg ); + VectorCopy( gHUD.m_Spectator.m_cameraAngles, pparams->viewangles ); + } + + v_idlescale = old; + + v_cl_angles = pparams->cl_viewangles; + v_origin = pparams->vieworg; + v_angles = pparams->viewangles; +} + +#define ORIGIN_BACKUP 64 +#define ORIGIN_MASK ( ORIGIN_BACKUP - 1 ) + +typedef struct +{ + float Origins[ ORIGIN_BACKUP ][3]; + float OriginTime[ ORIGIN_BACKUP ]; + + float Angles[ ORIGIN_BACKUP ][3]; + float AngleTime[ ORIGIN_BACKUP ]; + + int CurrentOrigin; + int CurrentAngle; +} viewinterp_t; + +/* +================== +V_CalcRefdef + +================== +*/ +void V_CalcNormalRefdef ( struct ref_params_s *pparams ) +{ + cl_entity_t *ent, *view; + int i; + vec3_t angles; + float bob, waterOffset; + static viewinterp_t ViewInterp; + + static float oldz = 0; + static float lasttime; + + vec3_t camAngles, camForward, camRight, camUp; + cl_entity_t *pwater; + + //V_DriftPitch ( pparams ); + + if ( gEngfuncs.IsSpectateOnly() ) + { + ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); + } + else + { + // ent is the player model ( visible when out of body ) + ent = gEngfuncs.GetLocalPlayer(); + } + + // view is the weapon model (only visible from inside body ) + view = gEngfuncs.GetViewModel(); + + // transform the view offset by the model's matrix to get the offset from + // model origin for the view + bob = V_CalcBob ( pparams ); + + // refresh position + VectorCopy ( pparams->simorg, pparams->vieworg ); + pparams->vieworg[2] += ( bob ); + VectorAdd( pparams->vieworg, pparams->viewheight, pparams->vieworg ); + + VectorCopy ( pparams->cl_viewangles, pparams->viewangles ); + + gEngfuncs.V_CalcShake(); + gEngfuncs.V_ApplyShake( pparams->vieworg, pparams->viewangles, 1.0 ); + + // never let view origin sit exactly on a node line, because a water plane can + // dissapear when viewed with the eye exactly on it. + // FIXME, we send origin at 1/128 now, change this? + // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis + + pparams->vieworg[0] += 1.0/32; + pparams->vieworg[1] += 1.0/32; + pparams->vieworg[2] += 1.0/32; + + // Check for problems around water, move the viewer artificially if necessary + // -- this prevents drawing errors in GL due to waves + + waterOffset = 0; + if ( pparams->waterlevel >= 2 ) + { + int i, contents, waterDist, waterEntity; + vec3_t point; + waterDist = cl_waterdist->value; + + if ( pparams->hardware ) + { + waterEntity = gEngfuncs.PM_WaterEntity( pparams->simorg ); + if ( waterEntity >= 0 && waterEntity < pparams->max_entities ) + { + pwater = gEngfuncs.GetEntityByIndex( waterEntity ); + if ( pwater && ( pwater->model != NULL ) ) + { + waterDist += ( pwater->curstate.scale * 16 ); // Add in wave height + } + } + } + else + { + waterEntity = 0; // Don't need this in software + } + + VectorCopy( pparams->vieworg, point ); + + // Eyes are above water, make sure we're above the waves + if ( pparams->waterlevel == 2 ) + { + point[2] -= waterDist; + for ( i = 0; i < waterDist; i++ ) + { + contents = gEngfuncs.PM_PointContents( point, NULL ); + if ( contents > CONTENTS_WATER ) + break; + point[2] += 1; + } + waterOffset = (point[2] + waterDist) - pparams->vieworg[2]; + } + else + { + // eyes are under water. Make sure we're far enough under + point[2] += waterDist; + + for ( i = 0; i < waterDist; i++ ) + { + contents = gEngfuncs.PM_PointContents( point, NULL ); + if ( contents <= CONTENTS_WATER ) + break; + point[2] -= 1; + } + waterOffset = (point[2] - waterDist) - pparams->vieworg[2]; + } + } + + pparams->vieworg[2] += waterOffset; + + V_CalcViewRoll ( pparams ); + + V_AddIdle ( pparams ); + + // offsets + VectorCopy( pparams->cl_viewangles, angles ); + + AngleVectors ( angles, pparams->forward, pparams->right, pparams->up ); + + // don't allow cheats in multiplayer + if ( pparams->maxclients <= 1 ) + { + for ( i=0 ; i<3 ; i++ ) + { + pparams->vieworg[i] += scr_ofsx->value*pparams->forward[i] + scr_ofsy->value*pparams->right[i] + scr_ofsz->value*pparams->up[i]; + } + } + + // Treating cam_ofs[2] as the distance + if( CL_IsThirdPerson() ) + { + vec3_t ofs; + + ofs[0] = ofs[1] = ofs[2] = 0.0; + + CL_CameraOffset( (float *)&ofs ); + + VectorCopy( ofs, camAngles ); + camAngles[ ROLL ] = 0; + + AngleVectors( camAngles, camForward, camRight, camUp ); + + for ( i = 0; i < 3; i++ ) + { + pparams->vieworg[ i ] += -ofs[2] * camForward[ i ]; + } + } + + // Give gun our viewangles + VectorCopy ( pparams->cl_viewangles, view->angles ); + + // set up gun position + V_CalcGunAngle ( pparams ); + + // Use predicted origin as view origin. + VectorCopy ( pparams->simorg, view->origin ); + view->origin[2] += ( waterOffset ); + VectorAdd( view->origin, pparams->viewheight, view->origin ); + + // Let the viewmodel shake at about 10% of the amplitude + gEngfuncs.V_ApplyShake( view->origin, view->angles, 0.9 ); + + for ( i = 0; i < 3; i++ ) + { + view->origin[ i ] += bob * 0.4 * pparams->forward[ i ]; + } + view->origin[2] += bob; + + // throw in a little tilt. + view->angles[YAW] -= bob * 0.5; + view->angles[ROLL] -= bob * 1; + view->angles[PITCH] -= bob * 0.3; + + // pushing the view origin down off of the same X/Z plane as the ent's origin will give the + // gun a very nice 'shifting' effect when the player looks up/down. If there is a problem + // with view model distortion, this may be a cause. (SJB). + view->origin[2] -= 1; + + // fudge position around to keep amount of weapon visible + // roughly equal with different FOV + if (pparams->viewsize == 110) + { + view->origin[2] += 1; + } + else if (pparams->viewsize == 100) + { + view->origin[2] += 2; + } + else if (pparams->viewsize == 90) + { + view->origin[2] += 1; + } + else if (pparams->viewsize == 80) + { + view->origin[2] += 0.5; + } + + // Add in the punchangle, if any + VectorAdd ( pparams->viewangles, pparams->punchangle, pparams->viewangles ); + + // Include client side punch, too + VectorAdd ( pparams->viewangles, (float *)&ev_punchangle, pparams->viewangles); + + V_DropPunchAngle ( pparams->frametime, (float *)&ev_punchangle ); + + // smooth out stair step ups +#if 1 + if ( !pparams->smoothing && pparams->onground && pparams->simorg[2] - oldz > 0) + { + float steptime; + + steptime = pparams->time - lasttime; + if (steptime < 0) + //FIXME I_Error ("steptime < 0"); + steptime = 0; + + oldz += steptime * 150; + if (oldz > pparams->simorg[2]) + oldz = pparams->simorg[2]; + if (pparams->simorg[2] - oldz > 18) + oldz = pparams->simorg[2]- 18; + pparams->vieworg[2] += oldz - pparams->simorg[2]; + view->origin[2] += oldz - pparams->simorg[2]; + } + else + { + oldz = pparams->simorg[2]; + } +#endif + + { + static float lastorg[3]; + vec3_t delta; + + VectorSubtract( pparams->simorg, lastorg, delta ); + + if ( Length( delta ) != 0.0 ) + { + VectorCopy( pparams->simorg, ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] ); + ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time; + ViewInterp.CurrentOrigin++; + + VectorCopy( pparams->simorg, lastorg ); + } + } + + // Smooth out whole view in multiplayer when on trains, lifts + if ( cl_vsmoothing && cl_vsmoothing->value && + ( pparams->smoothing && ( pparams->maxclients > 1 ) ) ) + { + int foundidx; + int i; + float t; + + if ( cl_vsmoothing->value < 0.0 ) + { + gEngfuncs.Cvar_SetValue( "cl_vsmoothing", 0.0 ); + } + + t = pparams->time - cl_vsmoothing->value; + + for ( i = 1; i < ORIGIN_MASK; i++ ) + { + foundidx = ViewInterp.CurrentOrigin - 1 - i; + if ( ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] <= t ) + break; + } + + if ( i < ORIGIN_MASK && ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ] != 0.0 ) + { + // Interpolate + vec3_t delta; + double frac; + double dt; + vec3_t neworg; + + dt = ViewInterp.OriginTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK ]; + if ( dt > 0.0 ) + { + frac = ( t - ViewInterp.OriginTime[ foundidx & ORIGIN_MASK] ) / dt; + frac = min( 1.0, frac ); + VectorSubtract( ViewInterp.Origins[ ( foundidx + 1 ) & ORIGIN_MASK ], ViewInterp.Origins[ foundidx & ORIGIN_MASK ], delta ); + VectorMA( ViewInterp.Origins[ foundidx & ORIGIN_MASK ], frac, delta, neworg ); + + // Dont interpolate large changes + if ( Length( delta ) < 64 ) + { + VectorSubtract( neworg, pparams->simorg, delta ); + + VectorAdd( pparams->simorg, delta, pparams->simorg ); + VectorAdd( pparams->vieworg, delta, pparams->vieworg ); + VectorAdd( view->origin, delta, view->origin ); + + } + } + } + } + + // Store off v_angles before munging for third person + v_angles = pparams->viewangles; + v_lastAngles = pparams->viewangles; + // v_cl_angles = pparams->cl_viewangles; // keep old user mouse angles ! + if ( CL_IsThirdPerson() ) + { + VectorCopy( camAngles, pparams->viewangles); + float pitch = camAngles[ 0 ]; + + // Normalize angles + if ( pitch > 180 ) + pitch -= 360.0; + else if ( pitch < -180 ) + pitch += 360; + + // Player pitch is inverted + pitch /= -3.0; + + // Slam local player's pitch value + ent->angles[ 0 ] = pitch; + ent->curstate.angles[ 0 ] = pitch; + ent->prevstate.angles[ 0 ] = pitch; + ent->latched.prevangles[ 0 ] = pitch; + } + + // override all previous settings if the viewent isn't the client + if ( pparams->viewentity > pparams->maxclients ) + { + cl_entity_t *viewentity; + viewentity = gEngfuncs.GetEntityByIndex( pparams->viewentity ); + if ( viewentity ) + { + VectorCopy( viewentity->origin, pparams->vieworg ); + VectorCopy( viewentity->angles, pparams->viewangles ); + + // Store off overridden viewangles + v_angles = pparams->viewangles; + } + } + + lasttime = pparams->time; + + v_origin = pparams->vieworg; +} + +void V_SmoothInterpolateAngles( float * startAngle, float * endAngle, float * finalAngle, float degreesPerSec ) +{ + float absd,frac,d,threshhold; + + NormalizeAngles( startAngle ); + NormalizeAngles( endAngle ); + + for ( int i = 0 ; i < 3 ; i++ ) + { + d = endAngle[i] - startAngle[i]; + + if ( d > 180.0f ) + { + d -= 360.0f; + } + else if ( d < -180.0f ) + { + d += 360.0f; + } + + absd = fabs(d); + + if ( absd > 0.01f ) + { + frac = degreesPerSec * v_frametime; + + threshhold= degreesPerSec / 4; + + if ( absd < threshhold ) + { + float h = absd / threshhold; + h *= h; + frac*= h; // slow down last degrees + } + + if ( frac > absd ) + { + finalAngle[i] = endAngle[i]; + } + else + { + if ( d>0) + finalAngle[i] = startAngle[i] + frac; + else + finalAngle[i] = startAngle[i] - frac; + } + } + else + { + finalAngle[i] = endAngle[i]; + } + + } + + NormalizeAngles( finalAngle ); +} + +// Get the origin of the Observer based around the target's position and angles +void V_GetChaseOrigin( float * angles, float * origin, float distance, float * returnvec ) +{ + vec3_t vecEnd; + vec3_t forward; + vec3_t vecStart; + pmtrace_t * trace; + int maxLoops = 8; + + int ignoreent = -1; // first, ignore no entity + + cl_entity_t * ent = NULL; + + // Trace back from the target using the player's view angles + AngleVectors(angles, forward, NULL, NULL); + + VectorScale(forward,-1,forward); + + VectorCopy( origin, vecStart ); + + VectorMA(vecStart, distance , forward, vecEnd); + + while ( maxLoops > 0) + { + trace = gEngfuncs.PM_TraceLine( vecStart, vecEnd, PM_TRACELINE_PHYSENTSONLY, 2, ignoreent ); + + // WARNING! trace->ent is is the number in physent list not the normal entity number + + if ( trace->ent <= 0) + break; // we hit the world or nothing, stop trace + + ent = gEngfuncs.GetEntityByIndex( PM_GetPhysEntInfo( trace->ent ) ); + + // hit non-player solid BSP , stop here + if ( ent == NULL && ent->curstate.solid == SOLID_BSP && !ent->player ) + break; + + // if close enought to end pos, stop, otherwise continue trace + if( Distance(trace->endpos, vecEnd ) < 1.0f ) + { + break; + } + else + { + ignoreent = trace->ent; // ignore last hit entity + VectorCopy( trace->endpos, vecStart); + } + + maxLoops--; + } + + /*if ( ent ) + { + gEngfuncs.Con_Printf("Trace loops %i , entity %i, model %s, solid %i\n",(8-maxLoops),ent->curstate.number, ent->model->name , ent->curstate.solid ); + }*/ + + VectorMA( trace->endpos, 8, trace->plane.normal, returnvec ); + + //gEngfuncs.Con_DPrintf("origin(%f %f %f) returnvec(%f %f %f)\n", origin[0], origin[1], origin[2], returnvec[0], returnvec[1], returnvec[2]); + + v_lastDistance = Distance(trace->endpos, origin); // real distance without offset +} + +void V_GetDeathCam(cl_entity_t * ent1, cl_entity_t * ent2, float * angle, float * origin) +{ + float newAngle[3]; + float newOrigin[3]; + static vec3_t nonDestructedOrigin; + float distance = 168.0f; + + v_lastDistance+= v_frametime * 96.0f; // move unit per seconds back + + if ( v_resetCamera ) + v_lastDistance = 64.0f; + + if ( distance > v_lastDistance ) + distance = v_lastDistance; + + if (ent1->origin.x == 0 && ent1->origin.y == 0 && ent1->origin.z == 0) + nonDestructedOrigin.CopyToArray(newOrigin); + else + { + nonDestructedOrigin = ent1->origin; + VectorCopy(ent1->origin, newOrigin); + } + + if ( ent1->player ) + newOrigin[2]+= 17; // head level of living player + + // get new angle towards second target + if ( ent2 ) + { + VectorSubtract(ent2->origin, nonDestructedOrigin, newAngle); + VectorAngles( newAngle, newAngle ); + newAngle[0] = -newAngle[0]; + } + else + { + // if no second target is given, look down to dead player + newAngle[0] = 90.0f; + newAngle[1] = 0.0f; + newAngle[2] = 0; + } + + // and smooth view + V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 120.0f ); + + V_GetChaseOrigin( angle, newOrigin, distance, origin ); + + VectorCopy(angle, v_lastAngles); +} + +void V_GetSingleTargetCam(cl_entity_t * ent1, float * angle, float * origin) +{ + float newAngle[3]; float newOrigin[3]; + + int flags = gHUD.m_Spectator.m_iObserverFlags; + + // see is target is a dead player + qboolean deadPlayer = ent1->player && (ent1->curstate.solid == SOLID_NOT); + + float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; + + float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; + + // go away in final scenes or if player just died + if ( flags & DRC_FLAG_FINAL ) + distance*=2.0f; + else if ( deadPlayer ) + distance*=1.5f; + + // let v_lastDistance float smoothly away + v_lastDistance+= v_frametime * 32.0f; // move unit per seconds back + + if ( distance > v_lastDistance ) + distance = v_lastDistance; + + VectorCopy(ent1->origin, newOrigin); + + if ( ent1->player ) + { + if ( deadPlayer ) + newOrigin[2]+= 2; //laying on ground + else + newOrigin[2]+= 17; // head level of living player + + } + else + newOrigin[2]+= 8; // object, tricky, must be above bomb in CS + + // we have no second target, choose view direction based on + // show front of primary target + VectorCopy(ent1->angles, newAngle); + + // show dead players from front, normal players back + if ( flags & DRC_FLAG_FACEPLAYER ) + newAngle[1]+= 180.0f; + + + newAngle[0]+= 12.5f * dfactor; // lower angle if dramatic + + // if final scene (bomb), show from real high pos + if ( flags & DRC_FLAG_FINAL ) + newAngle[0] = 22.5f; + + // choose side of object/player + if ( flags & DRC_FLAG_SIDE ) + newAngle[1]+=22.5f; + else + newAngle[1]-=22.5f; + + V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 120.0f ); + + // HACK, if player is dead don't clip against his dead body, can't check this + V_GetChaseOrigin( angle, newOrigin, distance, origin ); +} + +float MaxAngleBetweenAngles( float * a1, float * a2 ) +{ + float d, maxd = 0.0f; + + NormalizeAngles( a1 ); + NormalizeAngles( a2 ); + + for ( int i = 0 ; i < 3 ; i++ ) + { + d = a2[i] - a1[i]; + if ( d > 180 ) + { + d -= 360; + } + else if ( d < -180 ) + { + d += 360; + } + + d = fabs(d); + + if ( d > maxd ) + maxd=d; + } + + return maxd; +} + +void V_GetDoubleTargetsCam(cl_entity_t * ent1, cl_entity_t * ent2,float * angle, float * origin) +{ + float newAngle[3]; float newOrigin[3]; float tempVec[3]; + + int flags = gHUD.m_Spectator.m_iObserverFlags; + + float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; + + float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; + + // go away in final scenes or if player just died + if ( flags & DRC_FLAG_FINAL ) + distance*=2.0f; + + // let v_lastDistance float smoothly away + v_lastDistance+= v_frametime * 32.0f; // move unit per seconds back + + if ( distance > v_lastDistance ) + distance = v_lastDistance; + + VectorCopy(ent1->origin, newOrigin); + + if ( ent1->player ) + newOrigin[2]+= 17; // head level of living player + else + newOrigin[2]+= 8; // object, tricky, must be above bomb in CS + + // get new angle towards second target + VectorSubtract( ent2->origin, ent1->origin, newAngle ); + + VectorAngles( newAngle, newAngle ); + newAngle[0] = -newAngle[0]; + + // set angle diffrent in Dramtaic scenes + newAngle[0]+= 12.5f * dfactor; // lower angle if dramatic + + if ( flags & DRC_FLAG_SIDE ) + newAngle[1]+=22.5f; + else + newAngle[1]-=22.5f; + + float d = MaxAngleBetweenAngles( v_lastAngles, newAngle ); + + if ( ( d < v_cameraFocusAngle) && ( v_cameraMode == CAM_MODE_RELAX ) ) + { + // difference is to small and we are in relax camera mode, keep viewangles + VectorCopy(v_lastAngles, newAngle ); + } + else if ( (d < v_cameraRelaxAngle) && (v_cameraMode == CAM_MODE_FOCUS) ) + { + // we catched up with our target, relax again + v_cameraMode = CAM_MODE_RELAX; + } + else + { + // target move too far away, focus camera again + v_cameraMode = CAM_MODE_FOCUS; + } + + // and smooth view, if not a scene cut + if ( v_resetCamera || (v_cameraMode == CAM_MODE_RELAX) ) + { + VectorCopy( newAngle, angle ); + } + else + { + V_SmoothInterpolateAngles( v_lastAngles, newAngle, angle, 180.0f ); + } + + V_GetChaseOrigin( newAngle, newOrigin, distance, origin ); + + // move position up, if very close at target + if ( v_lastDistance < 64.0f ) + origin[2]+= 16.0f*( 1.0f - (v_lastDistance / 64.0f ) ); + + // calculate angle to second target + VectorSubtract( ent2->origin, origin, tempVec ); + VectorAngles( tempVec, tempVec ); + tempVec[0] = -tempVec[0]; + + /* take middle between two viewangles + InterpolateAngles( newAngle, tempVec, newAngle, 0.5f); */ + + + +} + +void V_GetDirectedChasePosition(cl_entity_t * ent1, cl_entity_t * ent2,float * angle, float * origin) +{ + + if ( v_resetCamera ) + { + v_lastDistance = 4096.0f; + // v_cameraMode = CAM_MODE_FOCUS; + } + + if ( ( ent2 == (cl_entity_t*)0xFFFFFFFF ) || ( ent1->player && (ent1->curstate.solid == SOLID_NOT) ) ) + { + // we have no second target or player just died + V_GetSingleTargetCam(ent1, angle, origin); + } + else if ( ent2 ) + { + // keep both target in view + V_GetDoubleTargetsCam( ent1, ent2, angle, origin ); + } + else + { + // second target disappeard somehow (dead) + + // keep last good viewangle + float newOrigin[3]; + + int flags = gHUD.m_Spectator.m_iObserverFlags; + + float dfactor = ( flags & DRC_FLAG_DRAMATIC )? -1.0f : 1.0f; + + float distance = 112.0f + ( 16.0f * dfactor ); // get close if dramatic; + + // go away in final scenes or if player just died + if ( flags & DRC_FLAG_FINAL ) + distance*=2.0f; + + // let v_lastDistance float smoothly away + v_lastDistance+= v_frametime * 32.0f; // move unit per seconds back + + if ( distance > v_lastDistance ) + distance = v_lastDistance; + + VectorCopy(ent1->origin, newOrigin); + + if ( ent1->player ) + newOrigin[2]+= 17; // head level of living player + else + newOrigin[2]+= 8; // object, tricky, must be above bomb in CS + + V_GetChaseOrigin( angle, newOrigin, distance, origin ); + } + + VectorCopy(angle, v_lastAngles); +} + +void V_GetChasePos(int target, float * cl_angles, float * origin, float * angles) +{ + cl_entity_t * ent = NULL; + cl_entity_t *local = gEngfuncs.GetLocalPlayer(); + + if ( target ) + { + ent = gEngfuncs.GetEntityByIndex( target ); + } + + if (!ent) + { + // just copy a save in-map position + VectorCopy ( vJumpAngles, angles ); + VectorCopy ( vJumpOrigin, origin ); + return; + } + + + if( ent->index == local->index ) + { + if ( g_iUser3 && g_iUser3 != 1 ) + V_GetDeathCam( ent, gEngfuncs.GetEntityByIndex( g_iUser3 ), + angles, origin ); + else + V_GetDeathCam( ent, NULL, + angles, origin ); + } + else if ( gHUD.m_Spectator.m_autoDirector->value ) + { + if ( g_iUser3 && g_iUser3 != 1 ) + V_GetDirectedChasePosition( ent, gEngfuncs.GetEntityByIndex( g_iUser3 ), + angles, origin ); + else + V_GetDirectedChasePosition( ent, (cl_entity_t*)0xFFFFFFFF, + angles, origin ); + } + else + { + if ( cl_angles == NULL ) // no mouse angles given, use entity angles ( locked mode ) + { + VectorCopy ( ent->angles, angles); + angles[0]*=-1; + } + else + VectorCopy ( cl_angles, angles); + + + VectorCopy ( ent->origin, origin); + + origin[2]+= 28; // DEFAULT_VIEWHEIGHT - some offset + + V_GetChaseOrigin( angles, origin, cl_chasedist->value, origin ); + } + + v_resetCamera = false; +} + +void V_ResetChaseCam() +{ + v_resetCamera = true; +} + + +void V_GetInEyePos(int target, float * origin, float * angles ) +{ + if ( !target) + { + // just copy a save in-map position + VectorCopy ( vJumpAngles, angles ); + VectorCopy ( vJumpOrigin, origin ); + return; + }; + + + cl_entity_t * ent = gEngfuncs.GetEntityByIndex( target ); + + if ( !ent ) + return; + + VectorCopy ( ent->origin, origin ); + VectorCopy ( ent->angles, angles ); + + angles[PITCH]*=-3.0f; // see CL_ProcessEntityUpdate() + + if ( ent->curstate.solid == SOLID_NOT ) + { + angles[ROLL] = 80; // dead view angle + origin[2]+= -8 ; // PM_DEAD_VIEWHEIGHT + } + else if (ent->curstate.usehull == 1 ) + origin[2]+= 12; // VEC_DUCK_VIEW; + else + // exacty eye position can't be caluculated since it depends on + // client values like cl_bobcycle, this offset matches the default values + origin[2]+= 28; // DEFAULT_VIEWHEIGHT +} + +void V_GetMapFreePosition( float * cl_angles, float * origin, float * angles ) +{ + vec3_t forward; + vec3_t zScaledTarget; + + VectorCopy(cl_angles, angles); + + // modify angles since we don't wanna see map's bottom + angles[0] = 51.25f + 38.75f*(angles[0]/90.0f); + + zScaledTarget[0] = gHUD.m_Spectator.m_mapOrigin[0]; + zScaledTarget[1] = gHUD.m_Spectator.m_mapOrigin[1]; + zScaledTarget[2] = gHUD.m_Spectator.m_mapOrigin[2] * (( 90.0f - angles[0] ) / 90.0f ); + + + AngleVectors(angles, forward, NULL, NULL); + + VectorNormalize(forward); + + VectorMA(zScaledTarget, -( 4096.0f / gHUD.m_Spectator.m_mapZoom ), forward , origin); +} + +void V_GetMapChasePosition(int target, float * cl_angles, float * origin, float * angles) +{ + vec3_t forward; + + if ( target ) + { + cl_entity_t * ent = gEngfuncs.GetEntityByIndex( target ); + + if ( gHUD.m_Spectator.m_autoDirector->value ) + { + // this is done to get the angles made by director mode + V_GetChasePos(target, cl_angles, origin, angles); + VectorCopy(ent->origin, origin); + + // keep fix chase angle horizontal + angles[0] = 45.0f; + } + else + { + VectorCopy(cl_angles, angles); + VectorCopy(ent->origin, origin); + + // modify angles since we don't wanna see map's bottom + angles[0] = 51.25f + 38.75f*(angles[0]/90.0f); + } + } + else + { + // keep out roaming position, but modify angles + VectorCopy(cl_angles, angles); + angles[0] = 51.25f + 38.75f*(angles[0]/90.0f); + } + + origin[2] *= (( 90.0f - angles[0] ) / 90.0f ); + angles[2] = 0.0f; // don't roll angle (if chased player is dead) + + AngleVectors(angles, forward, NULL, NULL); + + VectorNormalize(forward); + + VectorMA(origin, -1536, forward, origin); +} + +int V_FindViewModelByWeaponModel(int weaponindex) +{ + + static char * modelmap[][2] = { + { "models/p_crossbow.mdl", "models/v_crossbow.mdl" }, + { "models/p_crowbar.mdl", "models/v_crowbar.mdl" }, + { "models/p_egon.mdl", "models/v_egon.mdl" }, + { "models/p_gauss.mdl", "models/v_gauss.mdl" }, + { "models/p_9mmhandgun.mdl", "models/v_9mmhandgun.mdl" }, + { "models/p_grenade.mdl", "models/v_grenade.mdl" }, + { "models/p_hgun.mdl", "models/v_hgun.mdl" }, + { "models/p_9mmAR.mdl", "models/v_9mmAR.mdl" }, + { "models/p_357.mdl", "models/v_357.mdl" }, + { "models/p_rpg.mdl", "models/v_rpg.mdl" }, + { "models/p_shotgun.mdl", "models/v_shotgun.mdl" }, + { "models/p_squeak.mdl", "models/v_squeak.mdl" }, + { "models/p_tripmine.mdl", "models/v_tripmine.mdl" }, + { "models/p_satchel_radio.mdl", "models/v_satchel_radio.mdl"}, + { "models/p_satchel.mdl", "models/v_satchel.mdl" }, + { NULL, NULL } }; + + struct model_s * weaponModel = IEngineStudio.GetModelByIndex( weaponindex ); + + if ( weaponModel ) + { + int len = strlen( weaponModel->name ); + int i = 0; + + while ( modelmap[i] != NULL ) + { + if ( !strnicmp( weaponModel->name, modelmap[i][0], len ) ) + { + return gEngfuncs.pEventAPI->EV_FindModelIndex( modelmap[i][1] ); + } + i++; + } + + return 0; + } + else + return 0; + +} + + +/* +================== +V_CalcSpectatorRefdef + +================== +*/ +void V_CalcSpectatorRefdef ( struct ref_params_s * pparams ) +{ + static vec3_t velocity ( 0.0f, 0.0f, 0.0f); + + static int lastWeaponModelIndex = 0; + static int lastViewModelIndex = 0; + + cl_entity_t * ent = gEngfuncs.GetEntityByIndex( g_iUser2 ); + + pparams->onlyClientDraw = false; + + // refresh position + VectorCopy ( pparams->simorg, v_sim_org ); + + // get old values + VectorCopy ( pparams->cl_viewangles, v_cl_angles ); + VectorCopy ( pparams->viewangles, v_angles ); + VectorCopy ( pparams->vieworg, v_origin ); + + if ( ( g_iUser1 == OBS_IN_EYE || gHUD.m_Spectator.m_pip->value == INSET_IN_EYE ) && ent ) + { + // calculate player velocity + float timeDiff = ent->curstate.msg_time - ent->prevstate.msg_time; + + if ( timeDiff > 0 ) + { + vec3_t distance; + VectorSubtract(ent->prevstate.origin, ent->curstate.origin, distance); + VectorScale(distance, 1/timeDiff, distance ); + + velocity[0] = velocity[0]*0.9f + distance[0]*0.1f; + velocity[1] = velocity[1]*0.9f + distance[1]*0.1f; + velocity[2] = velocity[2]*0.9f + distance[2]*0.1f; + + VectorCopy(velocity, pparams->simvel); + } + + // predict missing client data and set weapon model ( in HLTV mode or inset in eye mode ) + if ( gEngfuncs.IsSpectateOnly() ) + { + V_GetInEyePos( g_iUser2, pparams->simorg, pparams->cl_viewangles ); + + pparams->health = 1; + + cl_entity_t * gunModel = gEngfuncs.GetViewModel(); + + if ( lastWeaponModelIndex != ent->curstate.weaponmodel ) + { + // weapon model changed + + lastWeaponModelIndex = ent->curstate.weaponmodel; + lastViewModelIndex = V_FindViewModelByWeaponModel( lastWeaponModelIndex ); + if ( lastViewModelIndex ) + { + gEngfuncs.pfnWeaponAnim(0,0); // reset weapon animation + } + else + { + // model not found + gunModel->model = NULL; // disable weapon model + lastWeaponModelIndex = lastViewModelIndex = 0; + } + } + + if ( lastViewModelIndex ) + { + gunModel->model = IEngineStudio.GetModelByIndex( lastViewModelIndex ); + gunModel->curstate.modelindex = lastViewModelIndex; + gunModel->curstate.frame = 0; + gunModel->curstate.colormap = 0; + gunModel->index = g_iUser2; + } + else + { + gunModel->model = NULL; // disable weaopn model + } + } + else + { + // only get viewangles from entity + VectorCopy ( ent->angles, pparams->cl_viewangles ); + pparams->cl_viewangles[PITCH]*=-3.0f; // see CL_ProcessEntityUpdate() + } + } + + v_frametime = pparams->frametime; + + if ( pparams->nextView == 0 ) + { + // first renderer cycle, full screen + + switch ( g_iUser1 ) + { + case OBS_CHASE_LOCKED: + V_GetChasePos( g_iUser2, NULL, v_origin, v_angles ); + break; + + case OBS_CHASE_FREE: + V_GetChasePos( g_iUser2, v_cl_angles, v_origin, v_angles ); + break; + + case OBS_ROAMING: + VectorCopy (v_cl_angles, v_angles); + VectorCopy (v_sim_org, v_origin); + break; + + case OBS_IN_EYE: + V_CalcNormalRefdef ( pparams ); + break; + + case OBS_MAP_FREE: + pparams->onlyClientDraw = true; + V_GetMapFreePosition( v_cl_angles, v_origin, v_angles ); + break; + + case OBS_MAP_CHASE: + pparams->onlyClientDraw = true; + V_GetMapChasePosition( g_iUser2, v_cl_angles, v_origin, v_angles ); + break; + } + + if ( gHUD.m_Spectator.m_pip->value ) + pparams->nextView = 1; // force a second renderer view + + gHUD.m_Spectator.m_iDrawCycle = 0; + + } + else + { + // second renderer cycle, inset window + + // set inset parameters + pparams->viewport[0] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowX); // change viewport to inset window + pparams->viewport[1] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowY); + pparams->viewport[2] = XRES(gHUD.m_Spectator.m_OverviewData.insetWindowWidth); + pparams->viewport[3] = YRES(gHUD.m_Spectator.m_OverviewData.insetWindowHeight); + pparams->nextView = 0; // on further view + + // override some settings in certain modes + switch ( (int)gHUD.m_Spectator.m_pip->value ) + { + case INSET_CHASE_FREE: + V_GetChasePos( g_iUser2, v_cl_angles, v_origin, v_angles ); + break; + + case INSET_IN_EYE: + V_CalcNormalRefdef ( pparams ); + break; + + case INSET_MAP_FREE: + pparams->onlyClientDraw = true; + V_GetMapFreePosition( v_cl_angles, v_origin, v_angles ); + break; + + case INSET_MAP_CHASE: + pparams->onlyClientDraw = true; + + if ( g_iUser1 == OBS_ROAMING ) + V_GetMapChasePosition( 0, v_cl_angles, v_origin, v_angles ); + else + V_GetMapChasePosition( g_iUser2, v_cl_angles, v_origin, v_angles ); + + break; + } + + gHUD.m_Spectator.m_iDrawCycle = 1; + } + + // write back new values into pparams + VectorCopy ( v_cl_angles, pparams->cl_viewangles ); + VectorCopy ( v_angles, pparams->viewangles ) + VectorCopy ( v_origin, pparams->vieworg ); + +} + + + +void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams ) +{ + // intermission / finale rendering + if ( pparams->intermission ) + { + V_CalcIntermissionRefdef ( pparams ); + } + else if ( pparams->spectator || g_iUser1 ) // g_iUser true if in spectator mode + { + V_CalcSpectatorRefdef ( pparams ); + } + else if ( !pparams->paused ) + { + V_CalcNormalRefdef ( pparams ); + } + + /* +// Example of how to overlay the whole screen with red at 50 % alpha +#define SF_TEST +#if defined SF_TEST + { + screenfade_t sf; + gEngfuncs.pfnGetScreenFade( &sf ); + + sf.fader = 255; + sf.fadeg = 0; + sf.fadeb = 0; + sf.fadealpha = 128; + sf.fadeFlags = FFADE_STAYOUT | FFADE_OUT; + + gEngfuncs.pfnSetScreenFade( &sf ); + } +#endif +*/ +} + +/* +============= +V_DropPunchAngle + +============= +*/ +void V_DropPunchAngle ( float frametime, float *ev_punchangle ) +{ + float len; + + len = VectorNormalize ( ev_punchangle ); + len -= (10.0 + len * 0.5) * frametime; + len = max( len, 0.0 ); + VectorScale ( ev_punchangle, len, ev_punchangle ); +} + +/* +============= +V_PunchAxis + +Client side punch effect +============= +*/ +void V_PunchAxis( int axis, float punch ) +{ + ev_punchangle[ axis ] = punch; +} + +/* +============= +V_Init +============= +*/ +void V_Init (void) +{ + //gEngfuncs.pfnAddCommand ("centerview", V_StartPitchDrift ); + + scr_ofsx = gEngfuncs.pfnRegisterVariable( "scr_ofsx","0", 0 ); + scr_ofsy = gEngfuncs.pfnRegisterVariable( "scr_ofsy","0", 0 ); + scr_ofsz = gEngfuncs.pfnRegisterVariable( "scr_ofsz","0", 0 ); + + v_centermove = gEngfuncs.pfnRegisterVariable( "v_centermove", "0.15", 0 ); + v_centerspeed = gEngfuncs.pfnRegisterVariable( "v_centerspeed","500", 0 ); + + cl_bobcycle = gEngfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0 );// best default for my experimental gun wag (sjb) + cl_bob = gEngfuncs.pfnRegisterVariable( "cl_bob","0.01", 0 );// best default for my experimental gun wag (sjb) + cl_bobup = gEngfuncs.pfnRegisterVariable( "cl_bobup","0.5", 0 ); + cl_waterdist = gEngfuncs.pfnRegisterVariable( "cl_waterdist","4", 0 ); + cl_chasedist = gEngfuncs.pfnRegisterVariable( "cl_chasedist","112", 0 ); +} + + +//#define TRACE_TEST +#if defined( TRACE_TEST ) + +extern float in_fov; +/* +==================== +CalcFov +==================== +*/ +float CalcFov (float fov_x, float width, float height) +{ + float a; + float x; + + if (fov_x < 1 || fov_x > 179) + fov_x = 90; // error, set to 90 + + x = width/tan(fov_x/360*M_PI); + + a = atan (height/x); + + a = a*360/M_PI; + + return a; +} + +int hitent = -1; + +void V_Move( int mx, int my ) +{ + float fov; + float fx, fy; + float dx, dy; + float c_x, c_y; + float dX, dY; + vec3_t forward, up, right; + vec3_t newangles; + + vec3_t farpoint; + pmtrace_t tr; + + fov = CalcFov( in_fov, (float)ScreenWidth, (float)ScreenHeight ); + + c_x = (float)ScreenWidth / 2.0; + c_y = (float)ScreenHeight / 2.0; + + dx = (float)mx - c_x; + dy = (float)my - c_y; + + // Proportion we moved in each direction + fx = dx / c_x; + fy = dy / c_y; + + dX = fx * in_fov / 2.0 ; + dY = fy * fov / 2.0; + + newangles = v_angles; + + newangles[ YAW ] -= dX; + newangles[ PITCH ] += dY; + + // Now rotate v_forward around that point + AngleVectors ( newangles, forward, right, up ); + + farpoint = v_origin + 8192 * forward; + + // Trace + tr = *(gEngfuncs.PM_TraceLine( (float *)&v_origin, (float *)&farpoint, PM_TRACELINE_PHYSENTSONLY, 2 /*point sized hull*/, -1 )); + + if ( tr.fraction != 1.0 && tr.ent != 0 ) + { + hitent = PM_GetPhysEntInfo( tr.ent ); + PM_ParticleLine( (float *)&v_origin, (float *)&tr.endpos, 5, 1.0, 0.0 ); + } + else + { + hitent = -1; + } +} + +#endif diff --git a/common/beamdef.h b/common/beamdef.h index acbe6de..e0d1096 100644 --- a/common/beamdef.h +++ b/common/beamdef.h @@ -1,64 +1,64 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined ( BEAMDEFH ) -#define BEAMDEFH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined ( BEAMDEFH ) +#define BEAMDEFH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/cl_entity.h b/common/cl_entity.h index d3cc0da..0371a68 100644 --- a/common/cl_entity.h +++ b/common/cl_entity.h @@ -1,117 +1,117 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// cl_entity.h -#if !defined( CL_ENTITYH ) -#define CL_ENTITYH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// cl_entity.h +#if !defined( CL_ENTITYH ) +#define CL_ENTITYH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/com_model.h b/common/com_model.h index 36990e4..33a2fdb 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -1,353 +1,353 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// com_model.h -#if !defined( COM_MODEL_H ) -#define COM_MODEL_H -#if defined( _WIN32 ) -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -#define STUDIO_RENDER 1 -#define STUDIO_EVENTS 2 - -#define MAX_CLIENTS 32 -#define MAX_EDICTS 900 - -#define MAX_MODEL_NAME 64 -#define MAX_MAP_HULLS 4 -#define MIPLEVELS 4 -#define NUM_AMBIENTS 4 // automatic ambient sounds -#define MAXLIGHTMAPS 4 -#define PLANE_ANYZ 5 - -#define ALIAS_Z_CLIP_PLANE 5 - -// flags in finalvert_t.flags -#define ALIAS_LEFT_CLIP 0x0001 -#define ALIAS_TOP_CLIP 0x0002 -#define ALIAS_RIGHT_CLIP 0x0004 -#define ALIAS_BOTTOM_CLIP 0x0008 -#define ALIAS_Z_CLIP 0x0010 -#define ALIAS_ONSEAM 0x0020 -#define ALIAS_XY_CLIP_MASK 0x000F - -#define ZISCALE ((float)0x8000) - -#define CACHE_SIZE 32 // used to align key data structures - -typedef enum -{ - mod_brush, - mod_sprite, - mod_alias, - mod_studio -} modtype_t; - -// must match definition in modelgen.h -#ifndef SYNCTYPE_T -#define SYNCTYPE_T - -typedef enum -{ - ST_SYNC=0, - ST_RAND -} synctype_t; - -#endif - -typedef struct -{ - float mins[3], maxs[3]; - float origin[3]; - int headnode[MAX_MAP_HULLS]; - int visleafs; // not including the solid leaf 0 - int firstface, numfaces; -} dmodel_t; - -// plane_t structure -typedef struct mplane_s -{ - vec3_t normal; // surface normal - float dist; // closest appoach to origin - byte type; // for texture axis selection and fast side tests - byte signbits; // signx + signy<<1 + signz<<1 - byte pad[2]; -} mplane_t; - -typedef struct -{ - vec3_t position; -} mvertex_t; - -typedef struct -{ - unsigned short v[2]; - unsigned int cachededgeoffset; -} medge_t; - -typedef struct texture_s -{ - char name[16]; - unsigned width, height; - int anim_total; // total tenths in sequence ( 0 = no) - int anim_min, anim_max; // time for this frame min <=time< max - struct texture_s *anim_next; // in the animation sequence - struct texture_s *alternate_anims; // bmodels in frame 1 use these - unsigned offsets[MIPLEVELS]; // four mip maps stored - unsigned paloffset; -} texture_t; - -typedef struct -{ - float vecs[2][4]; // [s/t] unit vectors in world space. - // [i][3] is the s/t offset relative to the origin. - // s or t = dot(3Dpoint,vecs[i])+vecs[i][3] - float mipadjust; // ?? mipmap limits for very small surfaces - texture_t *texture; - int flags; // sky or slime, no lightmap or 256 subdivision -} mtexinfo_t; - -typedef struct mnode_s -{ -// common with leaf - int contents; // 0, to differentiate from leafs - int visframe; // node needs to be traversed if current - - short minmaxs[6]; // for bounding box culling - - struct mnode_s *parent; - -// node specific - mplane_t *plane; - struct mnode_s *children[2]; - - unsigned short firstsurface; - unsigned short numsurfaces; -} mnode_t; - -typedef struct msurface_s msurface_t; -typedef struct decal_s decal_t; - -// JAY: Compress this as much as possible -struct decal_s -{ - decal_t *pnext; // linked list for each surface - msurface_t *psurface; // Surface id for persistence / unlinking - short dx; // Offsets into surface texture (in texture coordinates, so we don't need floats) - short dy; - short texture; // Decal texture - byte scale; // Pixel scale - byte flags; // Decal flags - - short entityIndex; // Entity this is attached to -}; - -typedef struct mleaf_s -{ -// common with node - int contents; // wil be a negative contents number - int visframe; // node needs to be traversed if current - - short minmaxs[6]; // for bounding box culling - - struct mnode_s *parent; - -// leaf specific - byte *compressed_vis; - struct efrag_s *efrags; - - msurface_t **firstmarksurface; - int nummarksurfaces; - int key; // BSP sequence number for leaf's contents - byte ambient_sound_level[NUM_AMBIENTS]; -} mleaf_t; - -struct msurface_s -{ - int visframe; // should be drawn when node is crossed - - int dlightframe; // last frame the surface was checked by an animated light - int dlightbits; // dynamically generated. Indicates if the surface illumination - // is modified by an animated light. - - mplane_t *plane; // pointer to shared plane - int flags; // see SURF_ #defines - - int firstedge; // look up in model->surfedges[], negative numbers - int numedges; // are backwards edges - -// surface generation data - struct surfcache_s *cachespots[MIPLEVELS]; - - short texturemins[2]; // smallest s/t position on the surface. - short extents[2]; // ?? s/t texture size, 1..256 for all non-sky surfaces - - mtexinfo_t *texinfo; - -// lighting info - byte styles[MAXLIGHTMAPS]; // index into d_lightstylevalue[] for animated lights - // no one surface can be effected by more than 4 - // animated lights. - color24 *samples; - - decal_t *pdecals; -}; - -typedef struct -{ - int planenum; - short children[2]; // negative numbers are contents -} dclipnode_t; - -typedef struct hull_s -{ - dclipnode_t *clipnodes; - mplane_t *planes; - int firstclipnode; - int lastclipnode; - vec3_t clip_mins; - vec3_t clip_maxs; -} hull_t; - -#if !defined( CACHE_USER ) && !defined( QUAKEDEF_H ) -#define CACHE_USER -typedef struct cache_user_s -{ - void *data; -} cache_user_t; -#endif - -typedef struct model_s -{ - char name[ MAX_MODEL_NAME ]; - qboolean needload; // bmodels and sprites don't cache normally - - modtype_t type; - int numframes; - synctype_t synctype; - - int flags; - -// -// volume occupied by the model -// - vec3_t mins, maxs; - float radius; - -// -// brush model -// - int firstmodelsurface, nummodelsurfaces; - - int numsubmodels; - dmodel_t *submodels; - - int numplanes; - mplane_t *planes; - - int numleafs; // number of visible leafs, not counting 0 - struct mleaf_s *leafs; - - int numvertexes; - mvertex_t *vertexes; - - int numedges; - medge_t *edges; - - int numnodes; - mnode_t *nodes; - - int numtexinfo; - mtexinfo_t *texinfo; - - int numsurfaces; - msurface_t *surfaces; - - int numsurfedges; - int *surfedges; - - int numclipnodes; - dclipnode_t *clipnodes; - - int nummarksurfaces; - msurface_t **marksurfaces; - - hull_t hulls[MAX_MAP_HULLS]; - - int numtextures; - texture_t **textures; - - byte *visdata; - - color24 *lightdata; - - char *entities; - -// -// additional model data -// - cache_user_t cache; // only access through Mod_Extradata - -} model_t; - -typedef vec_t vec4_t[4]; - -typedef struct alight_s -{ - int ambientlight; // clip at 128 - int shadelight; // clip at 192 - ambientlight - vec3_t color; - float *plightvec; -} alight_t; - -typedef struct auxvert_s -{ - float fv[3]; // viewspace x, y -} auxvert_t; - -#include "custom.h" - -#define MAX_INFO_STRING 256 -#define MAX_SCOREBOARDNAME 32 -typedef struct player_info_s -{ - // User id on server - int userid; - - // User info string - char userinfo[ MAX_INFO_STRING ]; - - // Name - char name[ MAX_SCOREBOARDNAME ]; - - // Spectator or not, unused - int spectator; - - int ping; - int packet_loss; - - // skin information - char model[MAX_QPATH]; - int topcolor; - int bottomcolor; - - // last frame rendered - int renderframe; - - // Gait frame estimation - int gaitsequence; - float gaitframe; - float gaityaw; - vec3_t prevgaitorigin; - - customization_t customdata; -} player_info_t; - -#endif // #define COM_MODEL_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// com_model.h +#if !defined( COM_MODEL_H ) +#define COM_MODEL_H +#if defined( _WIN32 ) +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +#define STUDIO_RENDER 1 +#define STUDIO_EVENTS 2 + +#define MAX_CLIENTS 32 +#define MAX_EDICTS 900 + +#define MAX_MODEL_NAME 64 +#define MAX_MAP_HULLS 4 +#define MIPLEVELS 4 +#define NUM_AMBIENTS 4 // automatic ambient sounds +#define MAXLIGHTMAPS 4 +#define PLANE_ANYZ 5 + +#define ALIAS_Z_CLIP_PLANE 5 + +// flags in finalvert_t.flags +#define ALIAS_LEFT_CLIP 0x0001 +#define ALIAS_TOP_CLIP 0x0002 +#define ALIAS_RIGHT_CLIP 0x0004 +#define ALIAS_BOTTOM_CLIP 0x0008 +#define ALIAS_Z_CLIP 0x0010 +#define ALIAS_ONSEAM 0x0020 +#define ALIAS_XY_CLIP_MASK 0x000F + +#define ZISCALE ((float)0x8000) + +#define CACHE_SIZE 32 // used to align key data structures + +typedef enum +{ + mod_brush, + mod_sprite, + mod_alias, + mod_studio +} modtype_t; + +// must match definition in modelgen.h +#ifndef SYNCTYPE_T +#define SYNCTYPE_T + +typedef enum +{ + ST_SYNC=0, + ST_RAND +} synctype_t; + +#endif + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; + int headnode[MAX_MAP_HULLS]; + int visleafs; // not including the solid leaf 0 + int firstface, numfaces; +} dmodel_t; + +// plane_t structure +typedef struct mplane_s +{ + vec3_t normal; // surface normal + float dist; // closest appoach to origin + byte type; // for texture axis selection and fast side tests + byte signbits; // signx + signy<<1 + signz<<1 + byte pad[2]; +} mplane_t; + +typedef struct +{ + vec3_t position; +} mvertex_t; + +typedef struct +{ + unsigned short v[2]; + unsigned int cachededgeoffset; +} medge_t; + +typedef struct texture_s +{ + char name[16]; + unsigned width, height; + int anim_total; // total tenths in sequence ( 0 = no) + int anim_min, anim_max; // time for this frame min <=time< max + struct texture_s *anim_next; // in the animation sequence + struct texture_s *alternate_anims; // bmodels in frame 1 use these + unsigned offsets[MIPLEVELS]; // four mip maps stored + unsigned paloffset; +} texture_t; + +typedef struct +{ + float vecs[2][4]; // [s/t] unit vectors in world space. + // [i][3] is the s/t offset relative to the origin. + // s or t = dot(3Dpoint,vecs[i])+vecs[i][3] + float mipadjust; // ?? mipmap limits for very small surfaces + texture_t *texture; + int flags; // sky or slime, no lightmap or 256 subdivision +} mtexinfo_t; + +typedef struct mnode_s +{ +// common with leaf + int contents; // 0, to differentiate from leafs + int visframe; // node needs to be traversed if current + + short minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// node specific + mplane_t *plane; + struct mnode_s *children[2]; + + unsigned short firstsurface; + unsigned short numsurfaces; +} mnode_t; + +typedef struct msurface_s msurface_t; +typedef struct decal_s decal_t; + +// JAY: Compress this as much as possible +struct decal_s +{ + decal_t *pnext; // linked list for each surface + msurface_t *psurface; // Surface id for persistence / unlinking + short dx; // Offsets into surface texture (in texture coordinates, so we don't need floats) + short dy; + short texture; // Decal texture + byte scale; // Pixel scale + byte flags; // Decal flags + + short entityIndex; // Entity this is attached to +}; + +typedef struct mleaf_s +{ +// common with node + int contents; // wil be a negative contents number + int visframe; // node needs to be traversed if current + + short minmaxs[6]; // for bounding box culling + + struct mnode_s *parent; + +// leaf specific + byte *compressed_vis; + struct efrag_s *efrags; + + msurface_t **firstmarksurface; + int nummarksurfaces; + int key; // BSP sequence number for leaf's contents + byte ambient_sound_level[NUM_AMBIENTS]; +} mleaf_t; + +struct msurface_s +{ + int visframe; // should be drawn when node is crossed + + int dlightframe; // last frame the surface was checked by an animated light + int dlightbits; // dynamically generated. Indicates if the surface illumination + // is modified by an animated light. + + mplane_t *plane; // pointer to shared plane + int flags; // see SURF_ #defines + + int firstedge; // look up in model->surfedges[], negative numbers + int numedges; // are backwards edges + +// surface generation data + struct surfcache_s *cachespots[MIPLEVELS]; + + short texturemins[2]; // smallest s/t position on the surface. + short extents[2]; // ?? s/t texture size, 1..256 for all non-sky surfaces + + mtexinfo_t *texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; // index into d_lightstylevalue[] for animated lights + // no one surface can be effected by more than 4 + // animated lights. + color24 *samples; + + decal_t *pdecals; +}; + +typedef struct +{ + int planenum; + short children[2]; // negative numbers are contents +} dclipnode_t; + +typedef struct hull_s +{ + dclipnode_t *clipnodes; + mplane_t *planes; + int firstclipnode; + int lastclipnode; + vec3_t clip_mins; + vec3_t clip_maxs; +} hull_t; + +#if !defined( CACHE_USER ) && !defined( QUAKEDEF_H ) +#define CACHE_USER +typedef struct cache_user_s +{ + void *data; +} cache_user_t; +#endif + +typedef struct model_s +{ + char name[ MAX_MODEL_NAME ]; + qboolean needload; // bmodels and sprites don't cache normally + + modtype_t type; + int numframes; + synctype_t synctype; + + int flags; + +// +// volume occupied by the model +// + vec3_t mins, maxs; + float radius; + +// +// brush model +// + int firstmodelsurface, nummodelsurfaces; + + int numsubmodels; + dmodel_t *submodels; + + int numplanes; + mplane_t *planes; + + int numleafs; // number of visible leafs, not counting 0 + struct mleaf_s *leafs; + + int numvertexes; + mvertex_t *vertexes; + + int numedges; + medge_t *edges; + + int numnodes; + mnode_t *nodes; + + int numtexinfo; + mtexinfo_t *texinfo; + + int numsurfaces; + msurface_t *surfaces; + + int numsurfedges; + int *surfedges; + + int numclipnodes; + dclipnode_t *clipnodes; + + int nummarksurfaces; + msurface_t **marksurfaces; + + hull_t hulls[MAX_MAP_HULLS]; + + int numtextures; + texture_t **textures; + + byte *visdata; + + color24 *lightdata; + + char *entities; + +// +// additional model data +// + cache_user_t cache; // only access through Mod_Extradata + +} model_t; + +typedef vec_t vec4_t[4]; + +typedef struct alight_s +{ + int ambientlight; // clip at 128 + int shadelight; // clip at 192 - ambientlight + vec3_t color; + float *plightvec; +} alight_t; + +typedef struct auxvert_s +{ + float fv[3]; // viewspace x, y +} auxvert_t; + +#include "custom.h" + +#define MAX_INFO_STRING 256 +#define MAX_SCOREBOARDNAME 32 +typedef struct player_info_s +{ + // User id on server + int userid; + + // User info string + char userinfo[ MAX_INFO_STRING ]; + + // Name + char name[ MAX_SCOREBOARDNAME ]; + + // Spectator or not, unused + int spectator; + + int ping; + int packet_loss; + + // skin information + char model[MAX_QPATH]; + int topcolor; + int bottomcolor; + + // last frame rendered + int renderframe; + + // Gait frame estimation + int gaitsequence; + float gaitframe; + float gaityaw; + vec3_t prevgaitorigin; + + customization_t customdata; +} player_info_t; + +#endif // #define COM_MODEL_H diff --git a/common/con_nprint.h b/common/con_nprint.h index aef6f0e..c563138 100644 --- a/common/con_nprint.h +++ b/common/con_nprint.h @@ -1,33 +1,33 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( CON_NPRINTH ) -#define CON_NPRINTH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( CON_NPRINTH ) +#define CON_NPRINTH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/crc.h b/common/crc.h index 06df7c5..55cb234 100644 --- a/common/crc.h +++ b/common/crc.h @@ -1,54 +1,54 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -/* crc.h */ -#ifndef CRC_H -#define CRC_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +/* crc.h */ +#ifndef CRC_H +#define CRC_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/cvardef.h b/common/cvardef.h index 9e34363..8390134 100644 --- a/common/cvardef.h +++ b/common/cvardef.h @@ -1,36 +1,36 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#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 diff --git a/common/demo_api.h b/common/demo_api.h index 72d3b7b..0130679 100644 --- a/common/demo_api.h +++ b/common/demo_api.h @@ -1,33 +1,33 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined ( DEMO_APIH ) -#define DEMO_APIH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined ( DEMO_APIH ) +#define DEMO_APIH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/director_cmds.h b/common/director_cmds.h index da99929..7593ebf 100644 --- a/common/director_cmds.h +++ b/common/director_cmds.h @@ -1,38 +1,38 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// director_cmds.h -// sub commands for svc_director - -#define DRC_ACTIVE 0 // tells client that he's an spectator and will get director command -#define DRC_STATUS 1 // send status infos about proxy -#define DRC_CAMERA 2 // set the actual director camera position -#define DRC_EVENT 3 // informs the dircetor about ann important game event - - -#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important) -#define DRC_FLAG_SIDE (1<<4) -#define DRC_FLAG_DRAMATIC (1<<5) - - - -// commands of the director API function CallDirectorProc(...) - -#define DRCAPI_NOP 0 // no operation -#define DRCAPI_ACTIVE 1 // de/acivates director mode in engine -#define DRCAPI_STATUS 2 // request proxy information -#define DRCAPI_SETCAM 3 // set camera n to given position and angle -#define DRCAPI_GETCAM 4 // request camera n position and angle -#define DRCAPI_DIRPLAY 5 // set director time and play with normal speed -#define DRCAPI_DIRFREEZE 6 // freeze directo at this time -#define DRCAPI_SETVIEWMODE 7 // overview or 4 cameras -#define DRCAPI_SETOVERVIEWPARAMS 8 // sets parameter for overview mode -#define DRCAPI_SETFOCUS 9 // set the camera which has the input focus -#define DRCAPI_GETTARGETS 10 // queries engine for player list -#define DRCAPI_SETVIEWPOINTS 11 // gives engine all waypoints - - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// director_cmds.h +// sub commands for svc_director + +#define DRC_ACTIVE 0 // tells client that he's an spectator and will get director command +#define DRC_STATUS 1 // send status infos about proxy +#define DRC_CAMERA 2 // set the actual director camera position +#define DRC_EVENT 3 // informs the dircetor about ann important game event + + +#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important) +#define DRC_FLAG_SIDE (1<<4) +#define DRC_FLAG_DRAMATIC (1<<5) + + + +// commands of the director API function CallDirectorProc(...) + +#define DRCAPI_NOP 0 // no operation +#define DRCAPI_ACTIVE 1 // de/acivates director mode in engine +#define DRCAPI_STATUS 2 // request proxy information +#define DRCAPI_SETCAM 3 // set camera n to given position and angle +#define DRCAPI_GETCAM 4 // request camera n position and angle +#define DRCAPI_DIRPLAY 5 // set director time and play with normal speed +#define DRCAPI_DIRFREEZE 6 // freeze directo at this time +#define DRCAPI_SETVIEWMODE 7 // overview or 4 cameras +#define DRCAPI_SETOVERVIEWPARAMS 8 // sets parameter for overview mode +#define DRCAPI_SETFOCUS 9 // set the camera which has the input focus +#define DRCAPI_GETTARGETS 10 // queries engine for player list +#define DRCAPI_SETVIEWPOINTS 11 // gives engine all waypoints + + diff --git a/common/dlight.h b/common/dlight.h index 0de4c4e..6a4f5b3 100644 --- a/common/dlight.h +++ b/common/dlight.h @@ -1,35 +1,35 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined ( DLIGHTH ) -#define DLIGHTH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef struct dlight_s -{ - 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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined ( DLIGHTH ) +#define DLIGHTH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef struct dlight_s +{ + 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 diff --git a/common/dll_state.h b/common/dll_state.h index a929c79..2058a26 100644 --- a/common/dll_state.h +++ b/common/dll_state.h @@ -1,23 +1,23 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -//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 -#define DLL_RESTART 6 // Switch to launcher for linux, does a quit but returns 1 - -// DLL Substate info ( not relevant ) -#define ENG_NORMAL (1<<0) +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +//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 +#define DLL_RESTART 6 // Switch to launcher for linux, does a quit but returns 1 + +// DLL Substate info ( not relevant ) +#define ENG_NORMAL (1<<0) diff --git a/common/engine_launcher_api.h b/common/engine_launcher_api.h index 5378211..2ddc472 100644 --- a/common/engine_launcher_api.h +++ b/common/engine_launcher_api.h @@ -1,112 +1,112 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// engine/launcher interface -#if !defined( ENGINE_LAUNCHER_APIH ) -#define ENGINE_LAUNCHER_APIH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 ); - void ( *DirectorProc ) ( unsigned int cmd, void * params ); -#else - // NOT USED IN LINUX!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - void ( *GL_Init ) ( void ); - void ( *GL_SetMode ) ( void ); - void ( *GL_Shutdown ) ( void ); - void ( *QGL_D3DShared ) ( void ); - void ( *glSwapBuffers ) ( void ); - void ( *DirectorProc ) ( void ); - // LINUX -#endif - -} engine_api_t; - -#endif // ENGINE_LAUNCHER_APIH +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// engine/launcher interface +#if !defined( ENGINE_LAUNCHER_APIH ) +#define ENGINE_LAUNCHER_APIH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 ); + void ( *DirectorProc ) ( unsigned int cmd, void * params ); +#else + // NOT USED IN LINUX!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + void ( *GL_Init ) ( void ); + void ( *GL_SetMode ) ( void ); + void ( *GL_Shutdown ) ( void ); + void ( *QGL_D3DShared ) ( void ); + void ( *glSwapBuffers ) ( void ); + void ( *DirectorProc ) ( void ); + // LINUX +#endif + +} engine_api_t; + +#endif // ENGINE_LAUNCHER_APIH diff --git a/common/entity_state.h b/common/entity_state.h index b517df7..fe4c097 100644 --- a/common/entity_state.h +++ b/common/entity_state.h @@ -1,195 +1,195 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( ENTITY_STATEH ) -#define ENTITY_STATEH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( ENTITY_STATEH ) +#define ENTITY_STATEH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/entity_types.h b/common/entity_types.h index 2ab96e3..ff783df 100644 --- a/common/entity_types.h +++ b/common/entity_types.h @@ -1,26 +1,26 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// 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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// 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 diff --git a/common/event_api.h b/common/event_api.h index a639ec0..c49c25d 100644 --- a/common/event_api.h +++ b/common/event_api.h @@ -1,53 +1,53 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined ( EVENT_APIH ) -#define EVENT_APIH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined ( EVENT_APIH ) +#define EVENT_APIH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/event_args.h b/common/event_args.h index 9ce46ae..7d7d9b3 100644 --- a/common/event_args.h +++ b/common/event_args.h @@ -1,52 +1,52 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( EVENT_ARGSH ) -#define EVENT_ARGSH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( EVENT_ARGSH ) +#define EVENT_ARGSH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/event_flags.h b/common/event_flags.h index e5d6424..fb19ae3 100644 --- a/common/event_flags.h +++ b/common/event_flags.h @@ -1,49 +1,49 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( EVENT_FLAGSH ) -#define EVENT_FLAGSH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( EVENT_FLAGSH ) +#define EVENT_FLAGSH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/exefuncs.h b/common/exefuncs.h index 353c015..a3a0523 100644 --- a/common/exefuncs.h +++ b/common/exefuncs.h @@ -1,50 +1,50 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// 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); - void (*unused26)(void); - void (*unused27)(void); -} exefuncs_t; - -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// 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); + void (*unused26)(void); + void (*unused27)(void); +} exefuncs_t; + +#endif diff --git a/common/hltv.h b/common/hltv.h index ff00d24..6211eb5 100644 --- a/common/hltv.h +++ b/common/hltv.h @@ -1,57 +1,57 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// hltv.h -// all shared consts between server, clients and proxy - -#ifndef HLTV_H -#define HLTV_H - -#define TYPE_CLIENT 0 // client is a normal HL client (default) -#define TYPE_PROXY 1 // client is another proxy -#define TYPE_COMMENTATOR 3 // client is a commentator -#define TYPE_DEMO 4 // client is a demo file -// sub commands of svc_hltv: -#define HLTV_ACTIVE 0 // tells client that he's an spectator and will get director commands -#define HLTV_STATUS 1 // send status infos about proxy -#define HLTV_LISTEN 2 // tell client to listen to a multicast stream - -// sub commands of svc_director: -#define DRC_CMD_NONE 0 // NULL director command -#define DRC_CMD_START 1 // start director mode -#define DRC_CMD_EVENT 2 // informs about director command -#define DRC_CMD_MODE 3 // switches camera modes -#define DRC_CMD_CAMERA 4 // sets camera registers -#define DRC_CMD_TIMESCALE 5 // sets time scale -#define DRC_CMD_MESSAGE 6 // send HUD centerprint -#define DRC_CMD_SOUND 7 // plays a particular sound -#define DRC_CMD_STATUS 8 // status info about broadcast -#define DRC_CMD_BANNER 9 // banner file name for HLTV gui -#define DRC_CMD_FADE 10 // send screen fade command -#define DRC_CMD_SHAKE 11 // send screen shake command -#define DRC_CMD_STUFFTEXT 12 // like the normal svc_stufftext but as director command - -#define DRC_CMD_LAST 12 - - - -// HLTV_EVENT event flags -#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important) -#define DRC_FLAG_SIDE (1<<4) // -#define DRC_FLAG_DRAMATIC (1<<5) // is a dramatic scene -#define DRC_FLAG_SLOWMOTION (1<<6) // would look good in SloMo -#define DRC_FLAG_FACEPLAYER (1<<7) // player is doning something (reload/defuse bomb etc) -#define DRC_FLAG_INTRO (1<<8) // is a introduction scene -#define DRC_FLAG_FINAL (1<<9) // is a final scene -#define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data - - -#define MAX_DIRECTOR_CMD_PARAMETERS 4 -#define MAX_DIRECTOR_CMD_STRING 128 - - -#endif // HLTV_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// hltv.h +// all shared consts between server, clients and proxy + +#ifndef HLTV_H +#define HLTV_H + +#define TYPE_CLIENT 0 // client is a normal HL client (default) +#define TYPE_PROXY 1 // client is another proxy +#define TYPE_COMMENTATOR 3 // client is a commentator +#define TYPE_DEMO 4 // client is a demo file +// sub commands of svc_hltv: +#define HLTV_ACTIVE 0 // tells client that he's an spectator and will get director commands +#define HLTV_STATUS 1 // send status infos about proxy +#define HLTV_LISTEN 2 // tell client to listen to a multicast stream + +// sub commands of svc_director: +#define DRC_CMD_NONE 0 // NULL director command +#define DRC_CMD_START 1 // start director mode +#define DRC_CMD_EVENT 2 // informs about director command +#define DRC_CMD_MODE 3 // switches camera modes +#define DRC_CMD_CAMERA 4 // sets camera registers +#define DRC_CMD_TIMESCALE 5 // sets time scale +#define DRC_CMD_MESSAGE 6 // send HUD centerprint +#define DRC_CMD_SOUND 7 // plays a particular sound +#define DRC_CMD_STATUS 8 // status info about broadcast +#define DRC_CMD_BANNER 9 // banner file name for HLTV gui +#define DRC_CMD_FADE 10 // send screen fade command +#define DRC_CMD_SHAKE 11 // send screen shake command +#define DRC_CMD_STUFFTEXT 12 // like the normal svc_stufftext but as director command + +#define DRC_CMD_LAST 12 + + + +// HLTV_EVENT event flags +#define DRC_FLAG_PRIO_MASK 0x0F // priorities between 0 and 15 (15 most important) +#define DRC_FLAG_SIDE (1<<4) // +#define DRC_FLAG_DRAMATIC (1<<5) // is a dramatic scene +#define DRC_FLAG_SLOWMOTION (1<<6) // would look good in SloMo +#define DRC_FLAG_FACEPLAYER (1<<7) // player is doning something (reload/defuse bomb etc) +#define DRC_FLAG_INTRO (1<<8) // is a introduction scene +#define DRC_FLAG_FINAL (1<<9) // is a final scene +#define DRC_FLAG_NO_RANDOM (1<<10) // don't randomize event data + + +#define MAX_DIRECTOR_CMD_PARAMETERS 4 +#define MAX_DIRECTOR_CMD_STRING 128 + + +#endif // HLTV_H diff --git a/common/in_buttons.h b/common/in_buttons.h index 597f908..9d220bd 100644 --- a/common/in_buttons.h +++ b/common/in_buttons.h @@ -1,43 +1,43 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef IN_BUTTONS_H -#define IN_BUTTONS_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - - -#ifndef CONST_H -#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 - -#endif // IN_BUTTONS_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef IN_BUTTONS_H +#define IN_BUTTONS_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + + +#ifndef CONST_H +#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 + +#endif // IN_BUTTONS_H diff --git a/common/interface.cpp b/common/interface.cpp index 980d7ff..10777c0 100644 --- a/common/interface.cpp +++ b/common/interface.cpp @@ -1,150 +1,150 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include -#include -#include "interface.h" - -#ifndef _WIN32 // LINUX -#include -#include // getcwd -#include // sprintf -#endif - - -// ------------------------------------------------------------------------------------ // -// InterfaceReg. -// ------------------------------------------------------------------------------------ // -InterfaceReg *InterfaceReg::s_pInterfaceRegs = NULL; - - -InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) : - m_pName(pName) -{ - m_CreateFn = fn; - m_pNext = s_pInterfaceRegs; - s_pInterfaceRegs = this; -} - - - -// ------------------------------------------------------------------------------------ // -// CreateInterface. -// ------------------------------------------------------------------------------------ // -EXPORT_FUNCTION IBaseInterface *CreateInterface( const char *pName, int *pReturnCode ) -{ - InterfaceReg *pCur; - - for(pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext) - { - if(strcmp(pCur->m_pName, pName) == 0) - { - if ( pReturnCode ) - { - *pReturnCode = IFACE_OK; - } - return pCur->m_CreateFn(); - } - } - - if ( pReturnCode ) - { - *pReturnCode = IFACE_FAILED; - } - return NULL; -} - - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include "windows.h" -#endif - - -#ifdef _WIN32 -HINTERFACEMODULE Sys_LoadModule(const char *pModuleName) -{ - return (HINTERFACEMODULE)LoadLibrary(pModuleName); -} - -#else // LINUX -HINTERFACEMODULE Sys_LoadModule(const char *pModuleName) -{ - // Linux dlopen() doesn't look in the current directory for libraries. - // We tell it to, so people don't have to 'install' libraries as root. - - char szCwd[1024]; - char szAbsoluteLibFilename[1024]; - - getcwd( szCwd, sizeof( szCwd ) ); - if ( szCwd[ strlen( szCwd ) - 1 ] == '/' ) - szCwd[ strlen( szCwd ) - 1 ] = 0; - - sprintf( szAbsoluteLibFilename, "%s/%s", szCwd, pModuleName ); - - return (HINTERFACEMODULE)dlopen( szAbsoluteLibFilename, RTLD_NOW ); -} - -#endif - - -#ifdef _WIN32 -void Sys_FreeModule(HINTERFACEMODULE hModule) -{ - if(!hModule) - return; - - FreeLibrary((HMODULE)hModule); -} - -#else // LINUX -void Sys_FreeModule(HINTERFACEMODULE hModule) -{ - if(!hModule) - return; - - dlclose( (void *)hModule ); -} - -#endif - - -//----------------------------------------------------------------------------- -// Purpose: returns the instance of this module -// Output : interface_instance_t -//----------------------------------------------------------------------------- -CreateInterfaceFn Sys_GetFactoryThis( void ) -{ - return CreateInterface; -} - - -//----------------------------------------------------------------------------- -// Purpose: returns the instance of the named module -// Input : *pModuleName - name of the module -// Output : interface_instance_t - instance of that module -//----------------------------------------------------------------------------- - -#ifdef _WIN32 -CreateInterfaceFn Sys_GetFactory( HINTERFACEMODULE hModule ) -{ - if(!hModule) - return NULL; - - return (CreateInterfaceFn)GetProcAddress((HMODULE)hModule, CREATEINTERFACE_PROCNAME); -} - -#else // LINUX -CreateInterfaceFn Sys_GetFactory( HINTERFACEMODULE hModule ) -{ - if(!hModule) - return NULL; - - return (CreateInterfaceFn)dlsym( (void *)hModule, CREATEINTERFACE_PROCNAME ); -} - -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include +#include +#include "interface.h" + +#ifndef _WIN32 // LINUX +#include +#include // getcwd +#include // sprintf +#endif + + +// ------------------------------------------------------------------------------------ // +// InterfaceReg. +// ------------------------------------------------------------------------------------ // +InterfaceReg *InterfaceReg::s_pInterfaceRegs = NULL; + + +InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) : + m_pName(pName) +{ + m_CreateFn = fn; + m_pNext = s_pInterfaceRegs; + s_pInterfaceRegs = this; +} + + + +// ------------------------------------------------------------------------------------ // +// CreateInterface. +// ------------------------------------------------------------------------------------ // +EXPORT_FUNCTION IBaseInterface *CreateInterface( const char *pName, int *pReturnCode ) +{ + InterfaceReg *pCur; + + for(pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext) + { + if(strcmp(pCur->m_pName, pName) == 0) + { + if ( pReturnCode ) + { + *pReturnCode = IFACE_OK; + } + return pCur->m_CreateFn(); + } + } + + if ( pReturnCode ) + { + *pReturnCode = IFACE_FAILED; + } + return NULL; +} + + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include "windows.h" +#endif + + +#ifdef _WIN32 +HINTERFACEMODULE Sys_LoadModule(const char *pModuleName) +{ + return (HINTERFACEMODULE)LoadLibrary(pModuleName); +} + +#else // LINUX +HINTERFACEMODULE Sys_LoadModule(const char *pModuleName) +{ + // Linux dlopen() doesn't look in the current directory for libraries. + // We tell it to, so people don't have to 'install' libraries as root. + + char szCwd[1024]; + char szAbsoluteLibFilename[1024]; + + getcwd( szCwd, sizeof( szCwd ) ); + if ( szCwd[ strlen( szCwd ) - 1 ] == '/' ) + szCwd[ strlen( szCwd ) - 1 ] = 0; + + sprintf( szAbsoluteLibFilename, "%s/%s", szCwd, pModuleName ); + + return (HINTERFACEMODULE)dlopen( szAbsoluteLibFilename, RTLD_NOW ); +} + +#endif + + +#ifdef _WIN32 +void Sys_FreeModule(HINTERFACEMODULE hModule) +{ + if(!hModule) + return; + + FreeLibrary((HMODULE)hModule); +} + +#else // LINUX +void Sys_FreeModule(HINTERFACEMODULE hModule) +{ + if(!hModule) + return; + + dlclose( (void *)hModule ); +} + +#endif + + +//----------------------------------------------------------------------------- +// Purpose: returns the instance of this module +// Output : interface_instance_t +//----------------------------------------------------------------------------- +CreateInterfaceFn Sys_GetFactoryThis( void ) +{ + return CreateInterface; +} + + +//----------------------------------------------------------------------------- +// Purpose: returns the instance of the named module +// Input : *pModuleName - name of the module +// Output : interface_instance_t - instance of that module +//----------------------------------------------------------------------------- + +#ifdef _WIN32 +CreateInterfaceFn Sys_GetFactory( HINTERFACEMODULE hModule ) +{ + if(!hModule) + return NULL; + + return (CreateInterfaceFn)GetProcAddress((HMODULE)hModule, CREATEINTERFACE_PROCNAME); +} + +#else // LINUX +CreateInterfaceFn Sys_GetFactory( HINTERFACEMODULE hModule ) +{ + if(!hModule) + return NULL; + + return (CreateInterfaceFn)dlsym( (void *)hModule, CREATEINTERFACE_PROCNAME ); +} + +#endif diff --git a/common/interface.h b/common/interface.h index 9b8e340..c7d5caf 100644 --- a/common/interface.h +++ b/common/interface.h @@ -1,129 +1,129 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// This header defines the interface convention used in the valve engine. -// To make an interface and expose it: -// 1. Derive from IBaseInterface. -// 2. The interface must be ALL pure virtuals, and have no data members. -// 3. Define a name for it. -// 4. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE. - -// Versioning -// There are two versioning cases that are handled by this: -// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case, -// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface. -// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface -// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and -// expose it for the old interface. - -#ifndef INTERFACE_H -#define INTERFACE_H - -#ifdef __cplusplus - -// All interfaces derive from this. -class IBaseInterface -{ -public: - - virtual ~IBaseInterface() {} -}; - - -#define CREATEINTERFACE_PROCNAME "CreateInterface" -typedef IBaseInterface* (*CreateInterfaceFn)(const char *pName, int *pReturnCode); - - -typedef IBaseInterface* (*InstantiateInterfaceFn)(); - - -// Used internally to register classes. -class InterfaceReg -{ -public: - InterfaceReg(InstantiateInterfaceFn fn, const char *pName); - -public: - - InstantiateInterfaceFn m_CreateFn; - const char *m_pName; - - InterfaceReg *m_pNext; // For the global list. - static InterfaceReg *s_pInterfaceRegs; -}; - - -// Use this to expose an interface that can have multiple instances. -// e.g.: -// EXPOSE_INTERFACE( CInterfaceImp, IInterface, "MyInterface001" ) -// This will expose a class called CInterfaceImp that implements IInterface (a pure class) -// clients can receive a pointer to this class by calling CreateInterface( "MyInterface001" ) -// -// In practice, the shared header file defines the interface (IInterface) and version name ("MyInterface001") -// so that each component can use these names/vtables to communicate -// -// A single class can support multiple interfaces through multiple inheritance -// -#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \ - static InterfaceReg __g_Create##className##_reg(functionName, versionName); - -#define EXPOSE_INTERFACE(className, interfaceName, versionName) \ - static IBaseInterface* __Create##className##_interface() {return (interfaceName *)new className;}\ - static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName ); - -// Use this to expose a singleton interface with a global variable you've created. -#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ - static IBaseInterface* __Create##className##interfaceName##_interface() {return (interfaceName *)&globalVarName;}\ - static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); - -// Use this to expose a singleton interface. This creates the global variable for you automatically. -#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ - static className __g_##className##_singleton;\ - EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton) - - -#ifdef WIN32 - #define EXPORT_FUNCTION __declspec(dllexport) -#else - #define EXPORT_FUNCTION -#endif - - -// This function is automatically exported and allows you to access any interfaces exposed with the above macros. -// if pReturnCode is set, it will return one of the following values -// extend this for other error conditions/code -enum -{ - IFACE_OK = 0, - IFACE_FAILED -}; - - -extern "C" -{ - EXPORT_FUNCTION IBaseInterface* CreateInterface(const char *pName, int *pReturnCode); -}; - - -// Handle to an interface (HInterfaceModule_t* is just there for type safety). -typedef struct HInterfaceModule_t* HINTERFACEMODULE; - - -// Use these to load and unload a module. -extern HINTERFACEMODULE Sys_LoadModule(const char *pModuleName); -extern void Sys_FreeModule(HINTERFACEMODULE hModule); - -// Use these to get the factory function from either a loaded module or the current module. -extern CreateInterfaceFn Sys_GetFactory( HINTERFACEMODULE hModule ); -extern CreateInterfaceFn Sys_GetFactoryThis( void ); - -#endif // __cplusplus - -#endif - - - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// This header defines the interface convention used in the valve engine. +// To make an interface and expose it: +// 1. Derive from IBaseInterface. +// 2. The interface must be ALL pure virtuals, and have no data members. +// 3. Define a name for it. +// 4. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE. + +// Versioning +// There are two versioning cases that are handled by this: +// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case, +// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface. +// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface +// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and +// expose it for the old interface. + +#ifndef INTERFACE_H +#define INTERFACE_H + +#ifdef __cplusplus + +// All interfaces derive from this. +class IBaseInterface +{ +public: + + virtual ~IBaseInterface() {} +}; + + +#define CREATEINTERFACE_PROCNAME "CreateInterface" +typedef IBaseInterface* (*CreateInterfaceFn)(const char *pName, int *pReturnCode); + + +typedef IBaseInterface* (*InstantiateInterfaceFn)(); + + +// Used internally to register classes. +class InterfaceReg +{ +public: + InterfaceReg(InstantiateInterfaceFn fn, const char *pName); + +public: + + InstantiateInterfaceFn m_CreateFn; + const char *m_pName; + + InterfaceReg *m_pNext; // For the global list. + static InterfaceReg *s_pInterfaceRegs; +}; + + +// Use this to expose an interface that can have multiple instances. +// e.g.: +// EXPOSE_INTERFACE( CInterfaceImp, IInterface, "MyInterface001" ) +// This will expose a class called CInterfaceImp that implements IInterface (a pure class) +// clients can receive a pointer to this class by calling CreateInterface( "MyInterface001" ) +// +// In practice, the shared header file defines the interface (IInterface) and version name ("MyInterface001") +// so that each component can use these names/vtables to communicate +// +// A single class can support multiple interfaces through multiple inheritance +// +#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \ + static InterfaceReg __g_Create##className##_reg(functionName, versionName); + +#define EXPOSE_INTERFACE(className, interfaceName, versionName) \ + static IBaseInterface* __Create##className##_interface() {return (interfaceName *)new className;}\ + static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName ); + +// Use this to expose a singleton interface with a global variable you've created. +#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ + static IBaseInterface* __Create##className##interfaceName##_interface() {return (interfaceName *)&globalVarName;}\ + static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); + +// Use this to expose a singleton interface. This creates the global variable for you automatically. +#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ + static className __g_##className##_singleton;\ + EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton) + + +#ifdef WIN32 + #define EXPORT_FUNCTION __declspec(dllexport) +#else + #define EXPORT_FUNCTION +#endif + + +// This function is automatically exported and allows you to access any interfaces exposed with the above macros. +// if pReturnCode is set, it will return one of the following values +// extend this for other error conditions/code +enum +{ + IFACE_OK = 0, + IFACE_FAILED +}; + + +extern "C" +{ + EXPORT_FUNCTION IBaseInterface* CreateInterface(const char *pName, int *pReturnCode); +}; + + +// Handle to an interface (HInterfaceModule_t* is just there for type safety). +typedef struct HInterfaceModule_t* HINTERFACEMODULE; + + +// Use these to load and unload a module. +extern HINTERFACEMODULE Sys_LoadModule(const char *pModuleName); +extern void Sys_FreeModule(HINTERFACEMODULE hModule); + +// Use these to get the factory function from either a loaded module or the current module. +extern CreateInterfaceFn Sys_GetFactory( HINTERFACEMODULE hModule ); +extern CreateInterfaceFn Sys_GetFactoryThis( void ); + +#endif // __cplusplus + +#endif + + + diff --git a/common/ivoicetweak.h b/common/ivoicetweak.h index 21e93f3..643c925 100644 --- a/common/ivoicetweak.h +++ b/common/ivoicetweak.h @@ -1,37 +1,37 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef IVOICETWEAK_H -#define IVOICETWEAK_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -// These provide access to the voice controls. -typedef enum -{ - MicrophoneVolume=0, // values 0-1. - OtherSpeakerScale // values 0-1. Scales how loud other players are. -} VoiceTweakControl; - - -typedef struct IVoiceTweak_s -{ - // These turn voice tweak mode on and off. While in voice tweak mode, the user's voice is echoed back - // without sending to the server. - int (*StartVoiceTweakMode)(); // Returns 0 on error. - void (*EndVoiceTweakMode)(); - - // Get/set control values. - void (*SetControlFloat)(VoiceTweakControl iControl, float value); - float (*GetControlFloat)(VoiceTweakControl iControl); -} IVoiceTweak; - - -#endif // IVOICETWEAK_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef IVOICETWEAK_H +#define IVOICETWEAK_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +// These provide access to the voice controls. +typedef enum +{ + MicrophoneVolume=0, // values 0-1. + OtherSpeakerScale // values 0-1. Scales how loud other players are. +} VoiceTweakControl; + + +typedef struct IVoiceTweak_s +{ + // These turn voice tweak mode on and off. While in voice tweak mode, the user's voice is echoed back + // without sending to the server. + int (*StartVoiceTweakMode)(); // Returns 0 on error. + void (*EndVoiceTweakMode)(); + + // Get/set control values. + void (*SetControlFloat)(VoiceTweakControl iControl, float value); + float (*GetControlFloat)(VoiceTweakControl iControl); +} IVoiceTweak; + + +#endif // IVOICETWEAK_H diff --git a/common/kbutton.h b/common/kbutton.h index 23cd8ac..29081a5 100644 --- a/common/kbutton.h +++ b/common/kbutton.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ // // Purpose: // diff --git a/common/mathlib.h b/common/mathlib.h index 9fe0bff..908e631 100644 --- a/common/mathlib.h +++ b/common/mathlib.h @@ -1,156 +1,156 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// 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) - -#ifndef VECTOR_H - #define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) -#endif - -#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 NormalizeAngles( vec3_t angles ); -void InterpolateAngles( vec3_t start, vec3_t end, vec3_t output, float frac ); -float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 ); - - -void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up); -void VectorAngles( const vec3_t forward, vec3_t angles ); - -int InvertMatrix( const float * m, float *out ); - -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))) +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// 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) + +#ifndef VECTOR_H + #define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) +#endif + +#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 NormalizeAngles( vec3_t angles ); +void InterpolateAngles( vec3_t start, vec3_t end, vec3_t output, float frac ); +float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 ); + + +void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up); +void VectorAngles( const vec3_t forward, vec3_t angles ); + +int InvertMatrix( const float * m, float *out ); + +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))) diff --git a/common/net_api.h b/common/net_api.h index 677d381..59b7f27 100644 --- a/common/net_api.h +++ b/common/net_api.h @@ -1,101 +1,101 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#if !defined( NET_APIH ) -#define NET_APIH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#if !defined( NET_APIH ) +#define NET_APIH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/netadr.h b/common/netadr.h index 24b42c6..f320f93 100644 --- a/common/netadr.h +++ b/common/netadr.h @@ -1,42 +1,42 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// netadr.h -#ifndef NETADR_H -#define NETADR_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// netadr.h +#ifndef NETADR_H +#define NETADR_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/nowin.h b/common/nowin.h index ffc9a78..0d836c5 100644 --- a/common/nowin.h +++ b/common/nowin.h @@ -1,15 +1,15 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef INC_NOWIN_H -#define INC_NOWIN_H -#ifndef _WIN32 - -#include - -#endif //!_WIN32 -#endif //INC_NOWIN_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef INC_NOWIN_H +#define INC_NOWIN_H +#ifndef _WIN32 + +#include + +#endif //!_WIN32 +#endif //INC_NOWIN_H diff --git a/common/particledef.h b/common/particledef.h index 0226a10..66fc920 100644 --- a/common/particledef.h +++ b/common/particledef.h @@ -1,59 +1,59 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( PARTICLEDEFH ) -#define PARTICLEDEFH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#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 +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( PARTICLEDEFH ) +#define PARTICLEDEFH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#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 diff --git a/common/pmtrace.h b/common/pmtrace.h index 404ddab..24eb062 100644 --- a/common/pmtrace.h +++ b/common/pmtrace.h @@ -1,45 +1,45 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( PMTRACEH ) -#define PMTRACEH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef struct -{ - vec3_t normal; - float dist; -} pmplane_t; - -typedef struct pmtrace_s pmtrace_t; - -struct pmtrace_s -{ - qboolean allsolid; // if true, plane is not valid - qboolean startsolid; // if true, the initial point was in a solid area - qboolean inopen, inwater; // End point is in empty space or in water - float fraction; // time completed, 1.0 = didn't hit anything - vec3_t endpos; // final position - pmplane_t plane; // surface normal at impact - int ent; // entity at impact - vec3_t deltavelocity; // Change in player's velocity caused by impact. - // Only run on server. - int hitgroup; -}; - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( PMTRACEH ) +#define PMTRACEH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef struct +{ + vec3_t normal; + float dist; +} pmplane_t; + +typedef struct pmtrace_s pmtrace_t; + +struct pmtrace_s +{ + qboolean allsolid; // if true, plane is not valid + qboolean startsolid; // if true, the initial point was in a solid area + qboolean inopen, inwater; // End point is in empty space or in water + float fraction; // time completed, 1.0 = didn't hit anything + vec3_t endpos; // final position + pmplane_t plane; // surface normal at impact + int ent; // entity at impact + vec3_t deltavelocity; // Change in player's velocity caused by impact. + // Only run on server. + int hitgroup; +}; + +#endif diff --git a/common/qfont.h b/common/qfont.h index b1d4ec5..3866030 100644 --- a/common/qfont.h +++ b/common/qfont.h @@ -1,42 +1,42 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( QFONTH ) -#define QFONTH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -// Font stuff - -#define NUM_GLYPHS 256 - -typedef struct -{ - short startoffset; - short charwidth; -} charinfo; - -typedef struct qfont_s -{ - int width, height; - int rowcount; - int rowheight; - charinfo fontinfo[ NUM_GLYPHS ]; - byte data[4]; -} qfont_t; - -#endif // qfont.h +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( QFONTH ) +#define QFONTH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +// Font stuff + +#define NUM_GLYPHS 256 + +typedef struct +{ + short startoffset; + short charwidth; +} charinfo; + +typedef struct qfont_s +{ + int width, height; + int rowcount; + int rowheight; + charinfo fontinfo[ NUM_GLYPHS ]; + byte data[4]; +} qfont_t; + +#endif // qfont.h diff --git a/common/r_efx.h b/common/r_efx.h index 9706cac..5c3adbe 100644 --- a/common/r_efx.h +++ b/common/r_efx.h @@ -1,200 +1,200 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined ( R_EFXH ) -#define R_EFXH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -// particle_t -#if !defined( PARTICLEDEFH ) -#include "particledef.h" -#endif - -// BEAM -#if !defined( BEAMDEFH ) -#include "beamdef.h" -#endif - -// dlight_t -#if !defined ( DLIGHTH ) -#include "dlight.h" -#endif - -// cl_entity_t -#if !defined( CL_ENTITYH ) -#include "cl_entity.h" -#endif - -/* -// FOR REFERENCE, These are the built-in tracer colors. Note, color 4 is the one -// that uses the tracerred/tracergreen/tracerblue and traceralpha cvar settings -color24 gTracerColors[] = -{ - { 255, 255, 255 }, // White - { 255, 0, 0 }, // Red - { 0, 255, 0 }, // Green - { 0, 0, 255 }, // Blue - { 0, 0, 0 }, // Tracer default, filled in from cvars, etc. - { 255, 167, 17 }, // Yellow-orange sparks - { 255, 130, 90 }, // Yellowish streaks (garg) - { 55, 60, 144 }, // Blue egon streak - { 255, 130, 90 }, // More Yellowish streaks (garg) - { 255, 140, 90 }, // More Yellowish streaks (garg) - { 200, 130, 90 }, // More red streaks (garg) - { 255, 120, 70 }, // Darker red streaks (garg) -}; -*/ - -// Temporary entity array -#define TENTPRIORITY_LOW 0 -#define TENTPRIORITY_HIGH 1 - -// TEMPENTITY flags -#define FTENT_NONE 0x00000000 -#define FTENT_SINEWAVE 0x00000001 -#define FTENT_GRAVITY 0x00000002 -#define FTENT_ROTATE 0x00000004 -#define FTENT_SLOWGRAVITY 0x00000008 -#define FTENT_SMOKETRAIL 0x00000010 -#define FTENT_COLLIDEWORLD 0x00000020 -#define FTENT_FLICKER 0x00000040 -#define FTENT_FADEOUT 0x00000080 -#define FTENT_SPRANIMATE 0x00000100 -#define FTENT_HITSOUND 0x00000200 -#define FTENT_SPIRAL 0x00000400 -#define FTENT_SPRCYCLE 0x00000800 -#define FTENT_COLLIDEALL 0x00001000 // will collide with world and slideboxes -#define FTENT_PERSIST 0x00002000 // tent is not removed when unable to draw -#define FTENT_COLLIDEKILL 0x00004000 // tent is removed upon collision with anything -#define FTENT_PLYRATTACHMENT 0x00008000 // tent is attached to a player (owner) -#define FTENT_SPRANIMATELOOP 0x00010000 // animating sprite doesn't die when last frame is displayed -#define FTENT_SPARKSHOWER 0x00020000 -#define FTENT_NOMODEL 0x00040000 // Doesn't have a model, never try to draw ( it just triggers other things ) -#define FTENT_CLIENTCUSTOM 0x00080000 // Must specify callback. Callback function is responsible for killing tempent and updating fields ( unless other flags specify how to do things ) -#define FTENT_IGNOREGRAVITY 0x00200000 // CS1.6 - -typedef struct tempent_s TEMPENTITY; -typedef struct tempent_s -{ - int flags; - float die; - float frameMax; - float x; - float y; - float z; - float fadeSpeed; - float bounceFactor; - int hitSound; - void ( *hitcallback ) ( struct tempent_s *ent, struct pmtrace_s *ptr ); - void ( *callback ) ( struct tempent_s *ent, float frametime, float currenttime ); - TEMPENTITY *next; - int priority; - short clientIndex; // if attached, this is the index of the client to stick to - // if COLLIDEALL, this is the index of the client to ignore - // TENTS with FTENT_PLYRATTACHMENT MUST set the clientindex! - - vec3_t tentOffset; // if attached, client origin + tentOffset = tent origin. - cl_entity_t entity; - - // baseline.origin - velocity - // baseline.renderamt - starting fadeout intensity - // baseline.angles - angle velocity -} TEMPENTITY; - -typedef struct efx_api_s efx_api_t; - -struct efx_api_s -{ - particle_t *( *R_AllocParticle ) ( void ( *callback ) ( struct particle_s *particle, float frametime ) ); - void ( *R_BlobExplosion ) ( float * org ); - void ( *R_Blood ) ( float * org, float * dir, int pcolor, int speed ); - void ( *R_BloodSprite ) ( float * org, int colorindex, int modelIndex, int modelIndex2, float size ); - void ( *R_BloodStream ) ( float * org, float * dir, int pcolor, int speed ); - void ( *R_BreakModel ) ( float *pos, float *size, float *dir, float random, float life, int count, int modelIndex, char flags ); - void ( *R_Bubbles ) ( float * mins, float * maxs, float height, int modelIndex, int count, float speed ); - void ( *R_BubbleTrail ) ( float * start, float * end, float height, int modelIndex, int count, float speed ); - void ( *R_BulletImpactParticles ) ( float * pos ); - void ( *R_EntityParticles ) ( struct cl_entity_s *ent ); - void ( *R_Explosion ) ( float *pos, int model, float scale, float framerate, int flags ); - void ( *R_FizzEffect ) ( struct cl_entity_s *pent, int modelIndex, int density ); - void ( *R_FireField ) ( float * org, int radius, int modelIndex, int count, int flags, float life ); - void ( *R_FlickerParticles ) ( float * org ); - void ( *R_FunnelSprite ) ( float *org, int modelIndex, int reverse ); - void ( *R_Implosion ) ( float * end, float radius, int count, float life ); - void ( *R_LargeFunnel ) ( float * org, int reverse ); - void ( *R_LavaSplash ) ( float * org ); - void ( *R_MultiGunshot ) ( float * org, float * dir, float * noise, int count, int decalCount, int *decalIndices ); - void ( *R_MuzzleFlash ) ( float *pos1, int type ); - void ( *R_ParticleBox ) ( float *mins, float *maxs, unsigned char r, unsigned char g, unsigned char b, float life ); - void ( *R_ParticleBurst ) ( float * pos, int size, int color, float life ); - void ( *R_ParticleExplosion ) ( float * org ); - void ( *R_ParticleExplosion2 ) ( float * org, int colorStart, int colorLength ); - void ( *R_ParticleLine ) ( float * start, float *end, unsigned char r, unsigned char g, unsigned char b, float life ); - void ( *R_PlayerSprites ) ( int client, int modelIndex, int count, int size ); - void ( *R_Projectile ) ( float * origin, float * velocity, int modelIndex, int life, int owner, void (*hitcallback)( struct tempent_s *ent, struct pmtrace_s *ptr ) ); - void ( *R_RicochetSound ) ( float * pos ); - void ( *R_RicochetSprite ) ( float *pos, struct model_s *pmodel, float duration, float scale ); - void ( *R_RocketFlare ) ( float *pos ); - void ( *R_RocketTrail ) ( float * start, float * end, int type ); - void ( *R_RunParticleEffect ) ( float * org, float * dir, int color, int count ); - void ( *R_ShowLine ) ( float * start, float * end ); - void ( *R_SparkEffect ) ( float *pos, int count, int velocityMin, int velocityMax ); - void ( *R_SparkShower ) ( float *pos ); - void ( *R_SparkStreaks ) ( float * pos, int count, int velocityMin, int velocityMax ); - void ( *R_Spray ) ( float * pos, float * dir, int modelIndex, int count, int speed, int spread, int rendermode ); - void ( *R_Sprite_Explode ) ( TEMPENTITY *pTemp, float scale, int flags ); - void ( *R_Sprite_Smoke ) ( TEMPENTITY *pTemp, float scale ); - void ( *R_Sprite_Spray ) ( float * pos, float * dir, int modelIndex, int count, int speed, int iRand ); - void ( *R_Sprite_Trail ) ( int type, float * start, float * end, int modelIndex, int count, float life, float size, float amplitude, int renderamt, float speed ); - void ( *R_Sprite_WallPuff ) ( TEMPENTITY *pTemp, float scale ); - void ( *R_StreakSplash ) ( float * pos, float * dir, int color, int count, float speed, int velocityMin, int velocityMax ); - void ( *R_TracerEffect ) ( float * start, float * end ); - void ( *R_UserTracerParticle ) ( float * org, float * vel, float life, int colorIndex, float length, unsigned char deathcontext, void ( *deathfunc)( struct particle_s *particle ) ); - particle_t *( *R_TracerParticles ) ( float * org, float * vel, float life ); - void ( *R_TeleportSplash ) ( float * org ); - void ( *R_TempSphereModel ) ( float *pos, float speed, float life, int count, int modelIndex ); - TEMPENTITY *( *R_TempModel ) ( float *pos, float *dir, float *angles, float life, int modelIndex, int soundtype ); - TEMPENTITY *( *R_DefaultSprite ) ( float *pos, int spriteIndex, float framerate ); - TEMPENTITY *( *R_TempSprite ) ( float *pos, float *dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags ); - int ( *Draw_DecalIndex ) ( int id ); - int ( *Draw_DecalIndexFromName ) ( char *name ); - void ( *R_DecalShoot ) ( int textureIndex, int entity, int modelIndex, float * position, int flags ); - void ( *R_AttachTentToPlayer ) ( int client, int modelIndex, float zoffset, float life ); - void ( *R_KillAttachedTents ) ( int client ); - BEAM *( *R_BeamCirclePoints ) ( int type, float * start, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); - BEAM *( *R_BeamEntPoint ) ( int startEnt, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); - BEAM *( *R_BeamEnts ) ( int startEnt, int endEnt, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); - BEAM *( *R_BeamFollow ) ( int startEnt, int modelIndex, float life, float width, float r, float g, float b, float brightness ); - void ( *R_BeamKill ) ( int deadEntity ); - BEAM *( *R_BeamLightning ) ( float * start, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed ); - BEAM *( *R_BeamPoints ) ( float * start, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); - BEAM *( *R_BeamRing ) ( int startEnt, int endEnt, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); - dlight_t *( *CL_AllocDlight ) ( int key ); - dlight_t *( *CL_AllocElight ) ( int key ); - TEMPENTITY *( *CL_TempEntAlloc ) ( float * org, struct model_s *model ); - TEMPENTITY *( *CL_TempEntAllocNoModel ) ( float * org ); - TEMPENTITY *( *CL_TempEntAllocHigh ) ( float * org, struct model_s *model ); - TEMPENTITY *( *CL_TentEntAllocCustom ) ( float *origin, struct model_s *model, int high, void ( *callback ) ( struct tempent_s *ent, float frametime, float currenttime ) ); - void ( *R_GetPackedColor ) ( short *packed, short color ); - short ( *R_LookupColor ) ( unsigned char r, unsigned char g, unsigned char b ); - void ( *R_DecalRemoveAll ) ( int textureIndex ); //textureIndex points to the decal index in the array, not the actual texture index. -}; - -extern efx_api_t efx; - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined ( R_EFXH ) +#define R_EFXH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +// particle_t +#if !defined( PARTICLEDEFH ) +#include "particledef.h" +#endif + +// BEAM +#if !defined( BEAMDEFH ) +#include "beamdef.h" +#endif + +// dlight_t +#if !defined ( DLIGHTH ) +#include "dlight.h" +#endif + +// cl_entity_t +#if !defined( CL_ENTITYH ) +#include "cl_entity.h" +#endif + +/* +// FOR REFERENCE, These are the built-in tracer colors. Note, color 4 is the one +// that uses the tracerred/tracergreen/tracerblue and traceralpha cvar settings +color24 gTracerColors[] = +{ + { 255, 255, 255 }, // White + { 255, 0, 0 }, // Red + { 0, 255, 0 }, // Green + { 0, 0, 255 }, // Blue + { 0, 0, 0 }, // Tracer default, filled in from cvars, etc. + { 255, 167, 17 }, // Yellow-orange sparks + { 255, 130, 90 }, // Yellowish streaks (garg) + { 55, 60, 144 }, // Blue egon streak + { 255, 130, 90 }, // More Yellowish streaks (garg) + { 255, 140, 90 }, // More Yellowish streaks (garg) + { 200, 130, 90 }, // More red streaks (garg) + { 255, 120, 70 }, // Darker red streaks (garg) +}; +*/ + +// Temporary entity array +#define TENTPRIORITY_LOW 0 +#define TENTPRIORITY_HIGH 1 + +// TEMPENTITY flags +#define FTENT_NONE 0x00000000 +#define FTENT_SINEWAVE 0x00000001 +#define FTENT_GRAVITY 0x00000002 +#define FTENT_ROTATE 0x00000004 +#define FTENT_SLOWGRAVITY 0x00000008 +#define FTENT_SMOKETRAIL 0x00000010 +#define FTENT_COLLIDEWORLD 0x00000020 +#define FTENT_FLICKER 0x00000040 +#define FTENT_FADEOUT 0x00000080 +#define FTENT_SPRANIMATE 0x00000100 +#define FTENT_HITSOUND 0x00000200 +#define FTENT_SPIRAL 0x00000400 +#define FTENT_SPRCYCLE 0x00000800 +#define FTENT_COLLIDEALL 0x00001000 // will collide with world and slideboxes +#define FTENT_PERSIST 0x00002000 // tent is not removed when unable to draw +#define FTENT_COLLIDEKILL 0x00004000 // tent is removed upon collision with anything +#define FTENT_PLYRATTACHMENT 0x00008000 // tent is attached to a player (owner) +#define FTENT_SPRANIMATELOOP 0x00010000 // animating sprite doesn't die when last frame is displayed +#define FTENT_SPARKSHOWER 0x00020000 +#define FTENT_NOMODEL 0x00040000 // Doesn't have a model, never try to draw ( it just triggers other things ) +#define FTENT_CLIENTCUSTOM 0x00080000 // Must specify callback. Callback function is responsible for killing tempent and updating fields ( unless other flags specify how to do things ) +#define FTENT_IGNOREGRAVITY 0x00200000 // CS1.6 + +typedef struct tempent_s TEMPENTITY; +typedef struct tempent_s +{ + int flags; + float die; + float frameMax; + float x; + float y; + float z; + float fadeSpeed; + float bounceFactor; + int hitSound; + void ( *hitcallback ) ( struct tempent_s *ent, struct pmtrace_s *ptr ); + void ( *callback ) ( struct tempent_s *ent, float frametime, float currenttime ); + TEMPENTITY *next; + int priority; + short clientIndex; // if attached, this is the index of the client to stick to + // if COLLIDEALL, this is the index of the client to ignore + // TENTS with FTENT_PLYRATTACHMENT MUST set the clientindex! + + vec3_t tentOffset; // if attached, client origin + tentOffset = tent origin. + cl_entity_t entity; + + // baseline.origin - velocity + // baseline.renderamt - starting fadeout intensity + // baseline.angles - angle velocity +} TEMPENTITY; + +typedef struct efx_api_s efx_api_t; + +struct efx_api_s +{ + particle_t *( *R_AllocParticle ) ( void ( *callback ) ( struct particle_s *particle, float frametime ) ); + void ( *R_BlobExplosion ) ( float * org ); + void ( *R_Blood ) ( float * org, float * dir, int pcolor, int speed ); + void ( *R_BloodSprite ) ( float * org, int colorindex, int modelIndex, int modelIndex2, float size ); + void ( *R_BloodStream ) ( float * org, float * dir, int pcolor, int speed ); + void ( *R_BreakModel ) ( float *pos, float *size, float *dir, float random, float life, int count, int modelIndex, char flags ); + void ( *R_Bubbles ) ( float * mins, float * maxs, float height, int modelIndex, int count, float speed ); + void ( *R_BubbleTrail ) ( float * start, float * end, float height, int modelIndex, int count, float speed ); + void ( *R_BulletImpactParticles ) ( float * pos ); + void ( *R_EntityParticles ) ( struct cl_entity_s *ent ); + void ( *R_Explosion ) ( float *pos, int model, float scale, float framerate, int flags ); + void ( *R_FizzEffect ) ( struct cl_entity_s *pent, int modelIndex, int density ); + void ( *R_FireField ) ( float * org, int radius, int modelIndex, int count, int flags, float life ); + void ( *R_FlickerParticles ) ( float * org ); + void ( *R_FunnelSprite ) ( float *org, int modelIndex, int reverse ); + void ( *R_Implosion ) ( float * end, float radius, int count, float life ); + void ( *R_LargeFunnel ) ( float * org, int reverse ); + void ( *R_LavaSplash ) ( float * org ); + void ( *R_MultiGunshot ) ( float * org, float * dir, float * noise, int count, int decalCount, int *decalIndices ); + void ( *R_MuzzleFlash ) ( float *pos1, int type ); + void ( *R_ParticleBox ) ( float *mins, float *maxs, unsigned char r, unsigned char g, unsigned char b, float life ); + void ( *R_ParticleBurst ) ( float * pos, int size, int color, float life ); + void ( *R_ParticleExplosion ) ( float * org ); + void ( *R_ParticleExplosion2 ) ( float * org, int colorStart, int colorLength ); + void ( *R_ParticleLine ) ( float * start, float *end, unsigned char r, unsigned char g, unsigned char b, float life ); + void ( *R_PlayerSprites ) ( int client, int modelIndex, int count, int size ); + void ( *R_Projectile ) ( float * origin, float * velocity, int modelIndex, int life, int owner, void (*hitcallback)( struct tempent_s *ent, struct pmtrace_s *ptr ) ); + void ( *R_RicochetSound ) ( float * pos ); + void ( *R_RicochetSprite ) ( float *pos, struct model_s *pmodel, float duration, float scale ); + void ( *R_RocketFlare ) ( float *pos ); + void ( *R_RocketTrail ) ( float * start, float * end, int type ); + void ( *R_RunParticleEffect ) ( float * org, float * dir, int color, int count ); + void ( *R_ShowLine ) ( float * start, float * end ); + void ( *R_SparkEffect ) ( float *pos, int count, int velocityMin, int velocityMax ); + void ( *R_SparkShower ) ( float *pos ); + void ( *R_SparkStreaks ) ( float * pos, int count, int velocityMin, int velocityMax ); + void ( *R_Spray ) ( float * pos, float * dir, int modelIndex, int count, int speed, int spread, int rendermode ); + void ( *R_Sprite_Explode ) ( TEMPENTITY *pTemp, float scale, int flags ); + void ( *R_Sprite_Smoke ) ( TEMPENTITY *pTemp, float scale ); + void ( *R_Sprite_Spray ) ( float * pos, float * dir, int modelIndex, int count, int speed, int iRand ); + void ( *R_Sprite_Trail ) ( int type, float * start, float * end, int modelIndex, int count, float life, float size, float amplitude, int renderamt, float speed ); + void ( *R_Sprite_WallPuff ) ( TEMPENTITY *pTemp, float scale ); + void ( *R_StreakSplash ) ( float * pos, float * dir, int color, int count, float speed, int velocityMin, int velocityMax ); + void ( *R_TracerEffect ) ( float * start, float * end ); + void ( *R_UserTracerParticle ) ( float * org, float * vel, float life, int colorIndex, float length, unsigned char deathcontext, void ( *deathfunc)( struct particle_s *particle ) ); + particle_t *( *R_TracerParticles ) ( float * org, float * vel, float life ); + void ( *R_TeleportSplash ) ( float * org ); + void ( *R_TempSphereModel ) ( float *pos, float speed, float life, int count, int modelIndex ); + TEMPENTITY *( *R_TempModel ) ( float *pos, float *dir, float *angles, float life, int modelIndex, int soundtype ); + TEMPENTITY *( *R_DefaultSprite ) ( float *pos, int spriteIndex, float framerate ); + TEMPENTITY *( *R_TempSprite ) ( float *pos, float *dir, float scale, int modelIndex, int rendermode, int renderfx, float a, float life, int flags ); + int ( *Draw_DecalIndex ) ( int id ); + int ( *Draw_DecalIndexFromName ) ( char *name ); + void ( *R_DecalShoot ) ( int textureIndex, int entity, int modelIndex, float * position, int flags ); + void ( *R_AttachTentToPlayer ) ( int client, int modelIndex, float zoffset, float life ); + void ( *R_KillAttachedTents ) ( int client ); + BEAM *( *R_BeamCirclePoints ) ( int type, float * start, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); + BEAM *( *R_BeamEntPoint ) ( int startEnt, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); + BEAM *( *R_BeamEnts ) ( int startEnt, int endEnt, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); + BEAM *( *R_BeamFollow ) ( int startEnt, int modelIndex, float life, float width, float r, float g, float b, float brightness ); + void ( *R_BeamKill ) ( int deadEntity ); + BEAM *( *R_BeamLightning ) ( float * start, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed ); + BEAM *( *R_BeamPoints ) ( float * start, float * end, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); + BEAM *( *R_BeamRing ) ( int startEnt, int endEnt, int modelIndex, float life, float width, float amplitude, float brightness, float speed, int startFrame, float framerate, float r, float g, float b ); + dlight_t *( *CL_AllocDlight ) ( int key ); + dlight_t *( *CL_AllocElight ) ( int key ); + TEMPENTITY *( *CL_TempEntAlloc ) ( float * org, struct model_s *model ); + TEMPENTITY *( *CL_TempEntAllocNoModel ) ( float * org ); + TEMPENTITY *( *CL_TempEntAllocHigh ) ( float * org, struct model_s *model ); + TEMPENTITY *( *CL_TentEntAllocCustom ) ( float *origin, struct model_s *model, int high, void ( *callback ) ( struct tempent_s *ent, float frametime, float currenttime ) ); + void ( *R_GetPackedColor ) ( short *packed, short color ); + short ( *R_LookupColor ) ( unsigned char r, unsigned char g, unsigned char b ); + void ( *R_DecalRemoveAll ) ( int textureIndex ); //textureIndex points to the decal index in the array, not the actual texture index. +}; + +extern efx_api_t efx; + +#endif diff --git a/common/r_studioint.h b/common/r_studioint.h index 44139b4..ee2182d 100644 --- a/common/r_studioint.h +++ b/common/r_studioint.h @@ -1,153 +1,153 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#if !defined( R_STUDIOINT_H ) -#define R_STUDIOINT_H -#if defined( _WIN32 ) -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -#define STUDIO_INTERFACE_VERSION 1 - -typedef struct engine_studio_api_s -{ - // Allocate number*size bytes and zero it - void *( *Mem_Calloc ) ( int number, size_t size ); - // Check to see if pointer is in the cache - void *( *Cache_Check ) ( struct cache_user_s *c ); - // Load file into cache ( can be swapped out on demand ) - void ( *LoadCacheFile ) ( char *path, struct cache_user_s *cu ); - // Retrieve model pointer for the named model - struct model_s *( *Mod_ForName ) ( const char *name, int crash_if_missing ); - // Retrieve pointer to studio model data block from a model - void *( *Mod_Extradata ) ( struct model_s *mod ); - // Retrieve indexed model from client side model precache list - struct model_s *( *GetModelByIndex ) ( int index ); - // Get entity that is set for rendering - struct cl_entity_s * ( *GetCurrentEntity ) ( void ); - // Get referenced player_info_t - struct player_info_s *( *PlayerInfo ) ( int index ); - // Get most recently received player state data from network system - struct entity_state_s *( *GetPlayerState ) ( int index ); - // Get viewentity - struct cl_entity_s * ( *GetViewEntity ) ( void ); - // Get current frame count, and last two timestampes on client - void ( *GetTimes ) ( int *framecount, double *current, double *old ); - // Get a pointer to a cvar by name - struct cvar_s *( *GetCvar ) ( const char *name ); - // Get current render origin and view vectors ( up, right and vpn ) - void ( *GetViewInfo ) ( float *origin, float *upv, float *rightv, float *vpnv ); - // Get sprite model used for applying chrome effect - struct model_s *( *GetChromeSprite ) ( void ); - // Get model counters so we can incement instrumentation - void ( *GetModelCounters ) ( int **s, int **a ); - // Get software scaling coefficients - void ( *GetAliasScale ) ( float *x, float *y ); - - // Get bone, light, alias, and rotation matrices - float ****( *StudioGetBoneTransform ) ( void ); - float ****( *StudioGetLightTransform )( void ); - float ***( *StudioGetAliasTransform ) ( void ); - float ***( *StudioGetRotationMatrix ) ( void ); - - // Set up body part, and get submodel pointers - void ( *StudioSetupModel ) ( int bodypart, void **ppbodypart, void **ppsubmodel ); - // Check if entity's bbox is in the view frustum - int ( *StudioCheckBBox ) ( void ); - // Apply lighting effects to model - void ( *StudioDynamicLight ) ( struct cl_entity_s *ent, struct alight_s *plight ); - void ( *StudioEntityLight ) ( struct alight_s *plight ); - void ( *StudioSetupLighting ) ( struct alight_s *plighting ); - - // Draw mesh vertices - void ( *StudioDrawPoints ) ( void ); - - // Draw hulls around bones - void ( *StudioDrawHulls ) ( void ); - // Draw bbox around studio models - void ( *StudioDrawAbsBBox ) ( void ); - // Draws bones - void ( *StudioDrawBones ) ( void ); - // Loads in appropriate texture for model - void ( *StudioSetupSkin ) ( void *ptexturehdr, int index ); - // Sets up for remapped colors - void ( *StudioSetRemapColors ) ( int top, int bottom ); - // Set's player model and returns model pointer - struct model_s *( *SetupPlayerModel ) ( int index ); - // Fires any events embedded in animation - void ( *StudioClientEvents ) ( void ); - // Retrieve/set forced render effects flags - int ( *GetForceFaceFlags ) ( void ); - void ( *SetForceFaceFlags ) ( int flags ); - // Tell engine the value of the studio model header - void ( *StudioSetHeader ) ( void *header ); - // Tell engine which model_t * is being renderered - void ( *SetRenderModel ) ( struct model_s *model ); - - // Final state setup and restore for rendering - void ( *SetupRenderer ) ( int rendermode ); - void ( *RestoreRenderer ) ( void ); - - // Set render origin for applying chrome effect - void ( *SetChromeOrigin ) ( void ); - - // True if using D3D/OpenGL - int ( *IsHardware ) ( void ); - - // Only called by hardware interface - void ( *GL_StudioDrawShadow ) ( void ); - void ( *GL_SetRenderMode ) ( int mode ); - - void ( *StudioSetRenderamt )( int iRenderamt ); - void ( *StudioSetCullState )( int iCull ); - void ( *StudioRenderShadow )( int iSprite, float *p1, float *p2, float *p3, float *p4 ); -} engine_studio_api_t; - -typedef struct server_studio_api_s -{ - // Allocate number*size bytes and zero it - void *( *Mem_Calloc ) ( int number, size_t size ); - // Check to see if pointer is in the cache - void *( *Cache_Check ) ( struct cache_user_s *c ); - // Load file into cache ( can be swapped out on demand ) - void ( *LoadCacheFile ) ( char *path, struct cache_user_s *cu ); - // Retrieve pointer to studio model data block from a model - void *( *Mod_Extradata ) ( struct model_s *mod ); -} server_studio_api_t; - - -// client blending -typedef struct r_studio_interface_s -{ - int version; - int ( *StudioDrawModel ) ( int flags ); - int ( *StudioDrawPlayer ) ( int flags, struct entity_state_s *pplayer ); -} r_studio_interface_t; - -extern r_studio_interface_t *pStudioAPI; - -// server blending -#define SV_BLENDING_INTERFACE_VERSION 1 - -typedef struct sv_blending_interface_s -{ - int version; - - void ( *SV_StudioSetupBones )( struct model_s *pModel, - float frame, - int sequence, - const vec3_t angles, - const vec3_t origin, - const byte *pcontroller, - const byte *pblending, - int iBone, - const edict_t *pEdict ); -} sv_blending_interface_t; - -#endif // R_STUDIOINT_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#if !defined( R_STUDIOINT_H ) +#define R_STUDIOINT_H +#if defined( _WIN32 ) +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +#define STUDIO_INTERFACE_VERSION 1 + +typedef struct engine_studio_api_s +{ + // Allocate number*size bytes and zero it + void *( *Mem_Calloc ) ( int number, size_t size ); + // Check to see if pointer is in the cache + void *( *Cache_Check ) ( struct cache_user_s *c ); + // Load file into cache ( can be swapped out on demand ) + void ( *LoadCacheFile ) ( char *path, struct cache_user_s *cu ); + // Retrieve model pointer for the named model + struct model_s *( *Mod_ForName ) ( const char *name, int crash_if_missing ); + // Retrieve pointer to studio model data block from a model + void *( *Mod_Extradata ) ( struct model_s *mod ); + // Retrieve indexed model from client side model precache list + struct model_s *( *GetModelByIndex ) ( int index ); + // Get entity that is set for rendering + struct cl_entity_s * ( *GetCurrentEntity ) ( void ); + // Get referenced player_info_t + struct player_info_s *( *PlayerInfo ) ( int index ); + // Get most recently received player state data from network system + struct entity_state_s *( *GetPlayerState ) ( int index ); + // Get viewentity + struct cl_entity_s * ( *GetViewEntity ) ( void ); + // Get current frame count, and last two timestampes on client + void ( *GetTimes ) ( int *framecount, double *current, double *old ); + // Get a pointer to a cvar by name + struct cvar_s *( *GetCvar ) ( const char *name ); + // Get current render origin and view vectors ( up, right and vpn ) + void ( *GetViewInfo ) ( float *origin, float *upv, float *rightv, float *vpnv ); + // Get sprite model used for applying chrome effect + struct model_s *( *GetChromeSprite ) ( void ); + // Get model counters so we can incement instrumentation + void ( *GetModelCounters ) ( int **s, int **a ); + // Get software scaling coefficients + void ( *GetAliasScale ) ( float *x, float *y ); + + // Get bone, light, alias, and rotation matrices + float ****( *StudioGetBoneTransform ) ( void ); + float ****( *StudioGetLightTransform )( void ); + float ***( *StudioGetAliasTransform ) ( void ); + float ***( *StudioGetRotationMatrix ) ( void ); + + // Set up body part, and get submodel pointers + void ( *StudioSetupModel ) ( int bodypart, void **ppbodypart, void **ppsubmodel ); + // Check if entity's bbox is in the view frustum + int ( *StudioCheckBBox ) ( void ); + // Apply lighting effects to model + void ( *StudioDynamicLight ) ( struct cl_entity_s *ent, struct alight_s *plight ); + void ( *StudioEntityLight ) ( struct alight_s *plight ); + void ( *StudioSetupLighting ) ( struct alight_s *plighting ); + + // Draw mesh vertices + void ( *StudioDrawPoints ) ( void ); + + // Draw hulls around bones + void ( *StudioDrawHulls ) ( void ); + // Draw bbox around studio models + void ( *StudioDrawAbsBBox ) ( void ); + // Draws bones + void ( *StudioDrawBones ) ( void ); + // Loads in appropriate texture for model + void ( *StudioSetupSkin ) ( void *ptexturehdr, int index ); + // Sets up for remapped colors + void ( *StudioSetRemapColors ) ( int top, int bottom ); + // Set's player model and returns model pointer + struct model_s *( *SetupPlayerModel ) ( int index ); + // Fires any events embedded in animation + void ( *StudioClientEvents ) ( void ); + // Retrieve/set forced render effects flags + int ( *GetForceFaceFlags ) ( void ); + void ( *SetForceFaceFlags ) ( int flags ); + // Tell engine the value of the studio model header + void ( *StudioSetHeader ) ( void *header ); + // Tell engine which model_t * is being renderered + void ( *SetRenderModel ) ( struct model_s *model ); + + // Final state setup and restore for rendering + void ( *SetupRenderer ) ( int rendermode ); + void ( *RestoreRenderer ) ( void ); + + // Set render origin for applying chrome effect + void ( *SetChromeOrigin ) ( void ); + + // True if using D3D/OpenGL + int ( *IsHardware ) ( void ); + + // Only called by hardware interface + void ( *GL_StudioDrawShadow ) ( void ); + void ( *GL_SetRenderMode ) ( int mode ); + + void ( *StudioSetRenderamt )( int iRenderamt ); + void ( *StudioSetCullState )( int iCull ); + void ( *StudioRenderShadow )( int iSprite, float *p1, float *p2, float *p3, float *p4 ); +} engine_studio_api_t; + +typedef struct server_studio_api_s +{ + // Allocate number*size bytes and zero it + void *( *Mem_Calloc ) ( int number, size_t size ); + // Check to see if pointer is in the cache + void *( *Cache_Check ) ( struct cache_user_s *c ); + // Load file into cache ( can be swapped out on demand ) + void ( *LoadCacheFile ) ( char *path, struct cache_user_s *cu ); + // Retrieve pointer to studio model data block from a model + void *( *Mod_Extradata ) ( struct model_s *mod ); +} server_studio_api_t; + + +// client blending +typedef struct r_studio_interface_s +{ + int version; + int ( *StudioDrawModel ) ( int flags ); + int ( *StudioDrawPlayer ) ( int flags, struct entity_state_s *pplayer ); +} r_studio_interface_t; + +extern r_studio_interface_t *pStudioAPI; + +// server blending +#define SV_BLENDING_INTERFACE_VERSION 1 + +typedef struct sv_blending_interface_s +{ + int version; + + void ( *SV_StudioSetupBones )( struct model_s *pModel, + float frame, + int sequence, + const vec3_t angles, + const vec3_t origin, + const byte *pcontroller, + const byte *pblending, + int iBone, + const edict_t *pEdict ); +} sv_blending_interface_t; + +#endif // R_STUDIOINT_H diff --git a/common/screenfade.h b/common/screenfade.h index 78894ac..b9072be 100644 --- a/common/screenfade.h +++ b/common/screenfade.h @@ -1,26 +1,26 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#if !defined( SCREENFADEH ) -#define SCREENFADEH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef struct screenfade_s -{ - float fadeSpeed; // How fast to fade (tics / second) (+ fade in, - fade out) - float fadeEnd; // When the fading hits maximum - float fadeTotalEnd; // Total End Time of the fade (used for FFADE_OUT) - float fadeReset; // When to reset to not fading (for fadeout and hold) - byte fader, fadeg, fadeb, fadealpha; // Fade color - int fadeFlags; // Fading flags -} screenfade_t; - -#endif // !SCREENFADEH +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#if !defined( SCREENFADEH ) +#define SCREENFADEH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef struct screenfade_s +{ + float fadeSpeed; // How fast to fade (tics / second) (+ fade in, - fade out) + float fadeEnd; // When the fading hits maximum + float fadeTotalEnd; // Total End Time of the fade (used for FFADE_OUT) + float fadeReset; // When to reset to not fading (for fadeout and hold) + byte fader, fadeg, fadeb, fadealpha; // Fade color + int fadeFlags; // Fading flags +} screenfade_t; + +#endif // !SCREENFADEH diff --git a/common/studio_event.h b/common/studio_event.h index 77007e3..0756c65 100644 --- a/common/studio_event.h +++ b/common/studio_event.h @@ -1,31 +1,31 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( STUDIO_EVENTH ) -#define STUDIO_EVENTH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef struct mstudioevent_s -{ - int frame; - int event; - int type; - char options[64]; -} mstudioevent_t; - -#endif // STUDIO_EVENTH +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( STUDIO_EVENTH ) +#define STUDIO_EVENTH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef struct mstudioevent_s +{ + int frame; + int event; + int type; + char options[64]; +} mstudioevent_t; + +#endif // STUDIO_EVENTH diff --git a/common/triangleapi.h b/common/triangleapi.h index 0bf2793..14a9973 100644 --- a/common/triangleapi.h +++ b/common/triangleapi.h @@ -1,68 +1,68 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined( TRIANGLEAPIH ) -#define TRIANGLEAPIH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef enum -{ - TRI_FRONT = 0, - TRI_NONE = 1, -} TRICULLSTYLE; - -#define TRI_API_VERSION 1 - -#define TRI_TRIANGLES 0 -#define TRI_TRIANGLE_FAN 1 -#define TRI_QUADS 2 -#define TRI_POLYGON 3 -#define TRI_LINES 4 -#define TRI_TRIANGLE_STRIP 5 -#define TRI_QUAD_STRIP 6 -#define TRI_POINTS 7 // Xash3D added - -typedef struct triangleapi_s -{ - int version; - - void ( *RenderMode )( int mode ); - void ( *Begin )( int primitiveCode ); - void ( *End ) ( void ); - - void ( *Color4f ) ( float r, float g, float b, float a ); - void ( *Color4ub ) ( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); - void ( *TexCoord2f ) ( float u, float v ); - void ( *Vertex3fv ) ( float *worldPnt ); - void ( *Vertex3f ) ( float x, float y, float z ); - void ( *Brightness ) ( float brightness ); - void ( *CullFace ) ( TRICULLSTYLE style ); - int ( *SpriteTexture ) ( struct model_s *pSpriteModel, int frame ); - int ( *WorldToScreen ) ( float *world, float *screen ); // Returns 1 if it's z clipped - void ( *Fog ) ( float flFogColor[3], float flStart, float flEnd, int bOn ); //Works just like GL_FOG, flFogColor is r/g/b. - void ( *ScreenToWorld ) ( float *screen, float *world ); - void (*GetMatrix)( const int pname, float *matrix ); - int (*BoxInPVS)( float *mins, float *maxs ); - void (*LightAtPoint)( float *pos, float *value ); - void (*Color4fRendermode)( float r, float g, float b, float a, int rendermode ); - void (*FogParams)( float flDensity, int iFogSkybox ); - - -} triangleapi_t; - -#endif // !TRIANGLEAPIH +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined( TRIANGLEAPIH ) +#define TRIANGLEAPIH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef enum +{ + TRI_FRONT = 0, + TRI_NONE = 1, +} TRICULLSTYLE; + +#define TRI_API_VERSION 1 + +#define TRI_TRIANGLES 0 +#define TRI_TRIANGLE_FAN 1 +#define TRI_QUADS 2 +#define TRI_POLYGON 3 +#define TRI_LINES 4 +#define TRI_TRIANGLE_STRIP 5 +#define TRI_QUAD_STRIP 6 +#define TRI_POINTS 7 // Xash3D added + +typedef struct triangleapi_s +{ + int version; + + void ( *RenderMode )( int mode ); + void ( *Begin )( int primitiveCode ); + void ( *End ) ( void ); + + void ( *Color4f ) ( float r, float g, float b, float a ); + void ( *Color4ub ) ( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); + void ( *TexCoord2f ) ( float u, float v ); + void ( *Vertex3fv ) ( float *worldPnt ); + void ( *Vertex3f ) ( float x, float y, float z ); + void ( *Brightness ) ( float brightness ); + void ( *CullFace ) ( TRICULLSTYLE style ); + int ( *SpriteTexture ) ( struct model_s *pSpriteModel, int frame ); + int ( *WorldToScreen ) ( float *world, float *screen ); // Returns 1 if it's z clipped + void ( *Fog ) ( float flFogColor[3], float flStart, float flEnd, int bOn ); //Works just like GL_FOG, flFogColor is r/g/b. + void ( *ScreenToWorld ) ( float *screen, float *world ); + void (*GetMatrix)( const int pname, float *matrix ); + int (*BoxInPVS)( float *mins, float *maxs ); + void (*LightAtPoint)( float *pos, float *value ); + void (*Color4fRendermode)( float r, float g, float b, float a, int rendermode ); + void (*FogParams)( float flDensity, int iFogSkybox ); + + +} triangleapi_t; + +#endif // !TRIANGLEAPIH diff --git a/common/usercmd.h b/common/usercmd.h index 641dd31..daf78c3 100644 --- a/common/usercmd.h +++ b/common/usercmd.h @@ -1,43 +1,43 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef USERCMD_H -#define USERCMD_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef struct usercmd_s -{ - short lerp_msec; // Interpolation time on client - byte msec; // Duration in ms of command - vec3_t viewangles; // Command view angles. - -// intended velocities - float forwardmove; // Forward velocity. - float sidemove; // Sideways velocity. - float upmove; // Upward velocity. - byte lightlevel; // Light level at spot where we are standing. - unsigned short buttons; // Attack buttons - byte impulse; // Impulse command issued. - byte weaponselect; // Current weapon id - -// Experimental player impact stuff. - int impact_index; - vec3_t impact_position; -} usercmd_t; - -#endif // USERCMD_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef USERCMD_H +#define USERCMD_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef struct usercmd_s +{ + short lerp_msec; // Interpolation time on client + byte msec; // Duration in ms of command + vec3_t viewangles; // Command view angles. + +// intended velocities + float forwardmove; // Forward velocity. + float sidemove; // Sideways velocity. + float upmove; // Upward velocity. + byte lightlevel; // Light level at spot where we are standing. + unsigned short buttons; // Attack buttons + byte impulse; // Impulse command issued. + byte weaponselect; // Current weapon id + +// Experimental player impact stuff. + int impact_index; + vec3_t impact_position; +} usercmd_t; + +#endif // USERCMD_H diff --git a/common/weaponinfo.h b/common/weaponinfo.h index d41c861..4b6af25 100644 --- a/common/weaponinfo.h +++ b/common/weaponinfo.h @@ -1,54 +1,54 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined ( WEAPONINFOH ) -#define WEAPONINFOH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -// Info about weapons player might have in his/her possession -typedef struct weapon_data_s -{ - int m_iId; - int m_iClip; - - float m_flNextPrimaryAttack; - float m_flNextSecondaryAttack; - float m_flTimeWeaponIdle; - - int m_fInReload; - int m_fInSpecialReload; - float m_flNextReload; - float m_flPumpTime; - float m_fReloadTime; - - float m_fAimedDamage; - float m_fNextAimBonus; - int m_fInZoom; - int m_iWeaponState; - - int iuser1; - int iuser2; - int iuser3; - int iuser4; - float fuser1; - float fuser2; - float fuser3; - float fuser4; -} weapon_data_t; - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined ( WEAPONINFOH ) +#define WEAPONINFOH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +// Info about weapons player might have in his/her possession +typedef struct weapon_data_s +{ + int m_iId; + int m_iClip; + + float m_flNextPrimaryAttack; + float m_flNextSecondaryAttack; + float m_flTimeWeaponIdle; + + int m_fInReload; + int m_fInSpecialReload; + float m_flNextReload; + float m_flPumpTime; + float m_fReloadTime; + + float m_fAimedDamage; + float m_fNextAimBonus; + int m_fInZoom; + int m_iWeaponState; + + int iuser1; + int iuser2; + int iuser3; + int iuser4; + float fuser1; + float fuser2; + float fuser3; + float fuser4; +} weapon_data_t; + +#endif diff --git a/dlls/client.cpp b/dlls/client.cpp index fd2f6f9..dcfc15e 100644 --- a/dlls/client.cpp +++ b/dlls/client.cpp @@ -4573,7 +4573,7 @@ void RegisterEncoders(void) #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif -//GCC почему-то не видит Ñтот дефайн в extdll.h +//GCC почему-то РЅРµ РІРёРґРёС‚ этот дефайн РІ extdll.h int GetWeaponData(struct edict_s *player, struct weapon_data_s *info) { diff --git a/dlls/combat.cpp b/dlls/combat.cpp index ea8c8e5..b0d6b44 100644 --- a/dlls/combat.cpp +++ b/dlls/combat.cpp @@ -489,7 +489,7 @@ void CGib::WaitTillLand(void) #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif -//GCC почему-то не видит Ñтот дефайн в extdll.h +//GCC почему-то РЅРµ РІРёРґРёС‚ этот дефайн РІ extdll.h void CGib::BounceGibTouch(CBaseEntity *pOther) { if (pev->flags & FL_ONGROUND) diff --git a/dlls/func_break.cpp b/dlls/func_break.cpp index a5d6e54..9a76362 100644 --- a/dlls/func_break.cpp +++ b/dlls/func_break.cpp @@ -70,7 +70,7 @@ void CBreakable::KeyValue(KeyValueData *pkvd) m_Explosion = expRandom; else */ - // if è else îäèíàêîâûå + // if и else одинаковые m_Explosion = expRandom; pkvd->fHandled = TRUE; diff --git a/dlls/h_export.cpp b/dlls/h_export.cpp index 25d3582..d149403 100644 --- a/dlls/h_export.cpp +++ b/dlls/h_export.cpp @@ -41,9 +41,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } -#if defined(_WIN32) && !defined(__GNUC__) && defined (_MSC_VER) -#pragma comment(linker, "/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1") -#pragma comment(linker, "/SECTION:.data,RW") +#if defined(_WIN32) && !defined(__GNUC__) && defined (_MSC_VER) +#pragma comment(linker, "/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1") +#pragma comment(linker, "/SECTION:.data,RW") #endif extern "C" void DLLEXPORT GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine, globalvars_t *pGlobals) diff --git a/dlls/player.cpp b/dlls/player.cpp index fd36501..977baad 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -3870,7 +3870,7 @@ void CBasePlayer::PostThink(void) { if (pev->velocity.x || pev->velocity.y) { - if (/*(pev->velocity.x || pev->velocity.y) &&*/ FBitSet(pev->flags, FL_ONGROUND))//(pev->velocity.x || pev->velocity.y) ïðîâåðåíû ñòðîêîé âûøå... + if (/*(pev->velocity.x || pev->velocity.y) &&*/ FBitSet(pev->flags, FL_ONGROUND))//(pev->velocity.x || pev->velocity.y) проверены Ñтрокой выше... SetAnimation(PLAYER_WALK); else if (pev->waterlevel > 1) SetAnimation(PLAYER_WALK); diff --git a/dlls/sound.cpp b/dlls/sound.cpp index e8614e3..6fa8330 100644 --- a/dlls/sound.cpp +++ b/dlls/sound.cpp @@ -1006,7 +1006,7 @@ int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg, float volume, float atte int ipick = USENTENCEG_Pick(isentenceg, name); - if (ipick > 0 && *name)//Ïîõîæå, òóò õîòåëè ïðîâåðèòü íå óêàçàòåëü íà name, à çàïèñàëîñü ëè òóäà ÷òî-íèáóäü. Ïîýòîìó *name áóäåò ïðàâèëüíåå, ÷åì ïðîñòî name. + if (ipick > 0 && *name)//Похоже, тут хотели проверить не указатель на name, а запиÑалоÑÑŒ ли туда что-нибудь. ПоÑтому *name будет правильнее, чем проÑто name. EMIT_SOUND_DYN(entity, CHAN_VOICE, name, volume, attenuation, flags, pitch); return ipick; diff --git a/engine/Sequence.h b/engine/Sequence.h index e46934a..4fcfa59 100644 --- a/engine/Sequence.h +++ b/engine/Sequence.h @@ -1,203 +1,203 @@ -//--------------------------------------------------------------------------- -// -// S c r i p t e d S e q u e n c e s -// -//--------------------------------------------------------------------------- -#ifndef _INCLUDE_SEQUENCE_H_ -#define _INCLUDE_SEQUENCE_H_ - - -#ifndef _DEF_BYTE_ -typedef unsigned char byte; -#endif - -//--------------------------------------------------------------------------- -// client_textmessage_t -//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// +// S c r i p t e d S e q u e n c e s +// +//--------------------------------------------------------------------------- +#ifndef _INCLUDE_SEQUENCE_H_ +#define _INCLUDE_SEQUENCE_H_ + + +#ifndef _DEF_BYTE_ +typedef unsigned char byte; +#endif + +//--------------------------------------------------------------------------- +// client_textmessage_t +//--------------------------------------------------------------------------- #define CLIENT_TEXTMESAGE_S -typedef struct client_textmessage_s -{ - int effect; - byte r1, g1, b1, a1; // 2 colors for effects - byte r2, g2, b2, a2; - float x; - float y; - float fadein; - float fadeout; - float holdtime; - float fxtime; - const char *pName; - const char *pMessage; -} client_textmessage_t; - - -//-------------------------------------------------------------------------- -// sequenceDefaultBits_e -// -// Enumerated list of possible modifiers for a command. This enumeration -// is used in a bitarray controlling what modifiers are specified for a command. -//--------------------------------------------------------------------------- -enum sequenceModifierBits -{ - SEQUENCE_MODIFIER_EFFECT_BIT = (1 << 1), - SEQUENCE_MODIFIER_POSITION_BIT = (1 << 2), - SEQUENCE_MODIFIER_COLOR_BIT = (1 << 3), - SEQUENCE_MODIFIER_COLOR2_BIT = (1 << 4), - SEQUENCE_MODIFIER_FADEIN_BIT = (1 << 5), - SEQUENCE_MODIFIER_FADEOUT_BIT = (1 << 6), - SEQUENCE_MODIFIER_HOLDTIME_BIT = (1 << 7), - SEQUENCE_MODIFIER_FXTIME_BIT = (1 << 8), - SEQUENCE_MODIFIER_SPEAKER_BIT = (1 << 9), - SEQUENCE_MODIFIER_LISTENER_BIT = (1 << 10), - SEQUENCE_MODIFIER_TEXTCHANNEL_BIT = (1 << 11), -}; -typedef enum sequenceModifierBits sequenceModifierBits_e ; - - -//--------------------------------------------------------------------------- -// sequenceCommandEnum_e -// -// Enumerated sequence command types. -//--------------------------------------------------------------------------- -enum sequenceCommandEnum_ -{ - SEQUENCE_COMMAND_ERROR = -1, - SEQUENCE_COMMAND_PAUSE = 0, - SEQUENCE_COMMAND_FIRETARGETS, - SEQUENCE_COMMAND_KILLTARGETS, - SEQUENCE_COMMAND_TEXT, - SEQUENCE_COMMAND_SOUND, - SEQUENCE_COMMAND_GOSUB, - SEQUENCE_COMMAND_SENTENCE, - SEQUENCE_COMMAND_REPEAT, - SEQUENCE_COMMAND_SETDEFAULTS, - SEQUENCE_COMMAND_MODIFIER, - SEQUENCE_COMMAND_POSTMODIFIER, - SEQUENCE_COMMAND_NOOP, - - SEQUENCE_MODIFIER_EFFECT, - SEQUENCE_MODIFIER_POSITION, - SEQUENCE_MODIFIER_COLOR, - SEQUENCE_MODIFIER_COLOR2, - SEQUENCE_MODIFIER_FADEIN, - SEQUENCE_MODIFIER_FADEOUT, - SEQUENCE_MODIFIER_HOLDTIME, - SEQUENCE_MODIFIER_FXTIME, - SEQUENCE_MODIFIER_SPEAKER, - SEQUENCE_MODIFIER_LISTENER, - SEQUENCE_MODIFIER_TEXTCHANNEL, -}; -typedef enum sequenceCommandEnum_ sequenceCommandEnum_e; - - -//--------------------------------------------------------------------------- -// sequenceCommandType_e -// -// Typeerated sequence command types. -//--------------------------------------------------------------------------- -enum sequenceCommandType_ -{ - SEQUENCE_TYPE_COMMAND, - SEQUENCE_TYPE_MODIFIER, -}; -typedef enum sequenceCommandType_ sequenceCommandType_e; - - -//--------------------------------------------------------------------------- -// sequenceCommandMapping_s -// -// A mapping of a command enumerated-value to its name. -//--------------------------------------------------------------------------- -typedef struct sequenceCommandMapping_ sequenceCommandMapping_s; -struct sequenceCommandMapping_ -{ - sequenceCommandEnum_e commandEnum; - const char* commandName; - sequenceCommandType_e commandType; -}; - - -//--------------------------------------------------------------------------- -// sequenceCommandLine_s -// -// Structure representing a single command (usually 1 line) from a -// .SEQ file entry. -//--------------------------------------------------------------------------- -typedef struct sequenceCommandLine_ sequenceCommandLine_s; -struct sequenceCommandLine_ -{ - int commandType; // Specifies the type of command - client_textmessage_t clientMessage; // Text HUD message struct - char* speakerName; // Targetname of speaking entity - char* listenerName; // Targetname of entity being spoken to - char* soundFileName; // Name of sound file to play - char* sentenceName; // Name of sentences.txt to play - char* fireTargetNames; // List of targetnames to fire - char* killTargetNames; // List of targetnames to remove - float delay; // Seconds 'till next command - int repeatCount; // If nonzero, reset execution pointer to top of block (N times, -1 = infinite) - int textChannel; // Display channel on which text message is sent - int modifierBitField; // Bit field to specify what clientmessage fields are valid - sequenceCommandLine_s* nextCommandLine; // Next command (linked list) -}; - - -//--------------------------------------------------------------------------- -// sequenceEntry_s -// -// Structure representing a single command (usually 1 line) from a -// .SEQ file entry. -//--------------------------------------------------------------------------- -typedef struct sequenceEntry_ sequenceEntry_s; -struct sequenceEntry_ -{ - char* fileName; // Name of sequence file without .SEQ extension - char* entryName; // Name of entry label in file - sequenceCommandLine_s* firstCommand; // Linked list of commands in entry - sequenceEntry_s* nextEntry; // Next loaded entry - qboolean isGlobal; // Is entry retained over level transitions? -}; - - - -//--------------------------------------------------------------------------- -// sentenceEntry_s -// Structure representing a single sentence of a group from a .SEQ -// file entry. Sentences are identical to entries in sentences.txt, but -// can be unique per level and are loaded/unloaded with the level. -//--------------------------------------------------------------------------- -typedef struct sentenceEntry_ sentenceEntry_s; -struct sentenceEntry_ -{ - char* data; // sentence data (ie "We have hostiles" ) - sentenceEntry_s* nextEntry; // Next loaded entry - qboolean isGlobal; // Is entry retained over level transitions? - unsigned int index; // this entry's position in the file. -}; - -//-------------------------------------------------------------------------- -// sentenceGroupEntry_s -// Structure representing a group of sentences found in a .SEQ file. -// A sentence group is defined by all sentences with the same name, ignoring -// the number at the end of the sentence name. Groups enable a sentence -// to be picked at random across a group. -//-------------------------------------------------------------------------- -typedef struct sentenceGroupEntry_ sentenceGroupEntry_s; -struct sentenceGroupEntry_ -{ - char* groupName; // name of the group (ie CT_ALERT ) - unsigned int numSentences; // number of sentences in group - sentenceEntry_s* firstSentence; // head of linked list of sentences in group - sentenceGroupEntry_s* nextEntry; // next loaded group -}; - -//--------------------------------------------------------------------------- -// Function declarations -//--------------------------------------------------------------------------- -sequenceEntry_s* SequenceGet( const char* fileName, const char* entryName ); -void Sequence_ParseFile( const char* fileName, qboolean isGlobal ); -void Sequence_OnLevelLoad( const char* mapName ); -sentenceEntry_s* SequencePickSentence( const char *groupName, int pickMethod, int *picked ); - -#endif /* _INCLUDE_SEQUENCE_H_ */ +typedef struct client_textmessage_s +{ + int effect; + byte r1, g1, b1, a1; // 2 colors for effects + byte r2, g2, b2, a2; + float x; + float y; + float fadein; + float fadeout; + float holdtime; + float fxtime; + const char *pName; + const char *pMessage; +} client_textmessage_t; + + +//-------------------------------------------------------------------------- +// sequenceDefaultBits_e +// +// Enumerated list of possible modifiers for a command. This enumeration +// is used in a bitarray controlling what modifiers are specified for a command. +//--------------------------------------------------------------------------- +enum sequenceModifierBits +{ + SEQUENCE_MODIFIER_EFFECT_BIT = (1 << 1), + SEQUENCE_MODIFIER_POSITION_BIT = (1 << 2), + SEQUENCE_MODIFIER_COLOR_BIT = (1 << 3), + SEQUENCE_MODIFIER_COLOR2_BIT = (1 << 4), + SEQUENCE_MODIFIER_FADEIN_BIT = (1 << 5), + SEQUENCE_MODIFIER_FADEOUT_BIT = (1 << 6), + SEQUENCE_MODIFIER_HOLDTIME_BIT = (1 << 7), + SEQUENCE_MODIFIER_FXTIME_BIT = (1 << 8), + SEQUENCE_MODIFIER_SPEAKER_BIT = (1 << 9), + SEQUENCE_MODIFIER_LISTENER_BIT = (1 << 10), + SEQUENCE_MODIFIER_TEXTCHANNEL_BIT = (1 << 11), +}; +typedef enum sequenceModifierBits sequenceModifierBits_e ; + + +//--------------------------------------------------------------------------- +// sequenceCommandEnum_e +// +// Enumerated sequence command types. +//--------------------------------------------------------------------------- +enum sequenceCommandEnum_ +{ + SEQUENCE_COMMAND_ERROR = -1, + SEQUENCE_COMMAND_PAUSE = 0, + SEQUENCE_COMMAND_FIRETARGETS, + SEQUENCE_COMMAND_KILLTARGETS, + SEQUENCE_COMMAND_TEXT, + SEQUENCE_COMMAND_SOUND, + SEQUENCE_COMMAND_GOSUB, + SEQUENCE_COMMAND_SENTENCE, + SEQUENCE_COMMAND_REPEAT, + SEQUENCE_COMMAND_SETDEFAULTS, + SEQUENCE_COMMAND_MODIFIER, + SEQUENCE_COMMAND_POSTMODIFIER, + SEQUENCE_COMMAND_NOOP, + + SEQUENCE_MODIFIER_EFFECT, + SEQUENCE_MODIFIER_POSITION, + SEQUENCE_MODIFIER_COLOR, + SEQUENCE_MODIFIER_COLOR2, + SEQUENCE_MODIFIER_FADEIN, + SEQUENCE_MODIFIER_FADEOUT, + SEQUENCE_MODIFIER_HOLDTIME, + SEQUENCE_MODIFIER_FXTIME, + SEQUENCE_MODIFIER_SPEAKER, + SEQUENCE_MODIFIER_LISTENER, + SEQUENCE_MODIFIER_TEXTCHANNEL, +}; +typedef enum sequenceCommandEnum_ sequenceCommandEnum_e; + + +//--------------------------------------------------------------------------- +// sequenceCommandType_e +// +// Typeerated sequence command types. +//--------------------------------------------------------------------------- +enum sequenceCommandType_ +{ + SEQUENCE_TYPE_COMMAND, + SEQUENCE_TYPE_MODIFIER, +}; +typedef enum sequenceCommandType_ sequenceCommandType_e; + + +//--------------------------------------------------------------------------- +// sequenceCommandMapping_s +// +// A mapping of a command enumerated-value to its name. +//--------------------------------------------------------------------------- +typedef struct sequenceCommandMapping_ sequenceCommandMapping_s; +struct sequenceCommandMapping_ +{ + sequenceCommandEnum_e commandEnum; + const char* commandName; + sequenceCommandType_e commandType; +}; + + +//--------------------------------------------------------------------------- +// sequenceCommandLine_s +// +// Structure representing a single command (usually 1 line) from a +// .SEQ file entry. +//--------------------------------------------------------------------------- +typedef struct sequenceCommandLine_ sequenceCommandLine_s; +struct sequenceCommandLine_ +{ + int commandType; // Specifies the type of command + client_textmessage_t clientMessage; // Text HUD message struct + char* speakerName; // Targetname of speaking entity + char* listenerName; // Targetname of entity being spoken to + char* soundFileName; // Name of sound file to play + char* sentenceName; // Name of sentences.txt to play + char* fireTargetNames; // List of targetnames to fire + char* killTargetNames; // List of targetnames to remove + float delay; // Seconds 'till next command + int repeatCount; // If nonzero, reset execution pointer to top of block (N times, -1 = infinite) + int textChannel; // Display channel on which text message is sent + int modifierBitField; // Bit field to specify what clientmessage fields are valid + sequenceCommandLine_s* nextCommandLine; // Next command (linked list) +}; + + +//--------------------------------------------------------------------------- +// sequenceEntry_s +// +// Structure representing a single command (usually 1 line) from a +// .SEQ file entry. +//--------------------------------------------------------------------------- +typedef struct sequenceEntry_ sequenceEntry_s; +struct sequenceEntry_ +{ + char* fileName; // Name of sequence file without .SEQ extension + char* entryName; // Name of entry label in file + sequenceCommandLine_s* firstCommand; // Linked list of commands in entry + sequenceEntry_s* nextEntry; // Next loaded entry + qboolean isGlobal; // Is entry retained over level transitions? +}; + + + +//--------------------------------------------------------------------------- +// sentenceEntry_s +// Structure representing a single sentence of a group from a .SEQ +// file entry. Sentences are identical to entries in sentences.txt, but +// can be unique per level and are loaded/unloaded with the level. +//--------------------------------------------------------------------------- +typedef struct sentenceEntry_ sentenceEntry_s; +struct sentenceEntry_ +{ + char* data; // sentence data (ie "We have hostiles" ) + sentenceEntry_s* nextEntry; // Next loaded entry + qboolean isGlobal; // Is entry retained over level transitions? + unsigned int index; // this entry's position in the file. +}; + +//-------------------------------------------------------------------------- +// sentenceGroupEntry_s +// Structure representing a group of sentences found in a .SEQ file. +// A sentence group is defined by all sentences with the same name, ignoring +// the number at the end of the sentence name. Groups enable a sentence +// to be picked at random across a group. +//-------------------------------------------------------------------------- +typedef struct sentenceGroupEntry_ sentenceGroupEntry_s; +struct sentenceGroupEntry_ +{ + char* groupName; // name of the group (ie CT_ALERT ) + unsigned int numSentences; // number of sentences in group + sentenceEntry_s* firstSentence; // head of linked list of sentences in group + sentenceGroupEntry_s* nextEntry; // next loaded group +}; + +//--------------------------------------------------------------------------- +// Function declarations +//--------------------------------------------------------------------------- +sequenceEntry_s* SequenceGet( const char* fileName, const char* entryName ); +void Sequence_ParseFile( const char* fileName, qboolean isGlobal ); +void Sequence_OnLevelLoad( const char* mapName ); +sentenceEntry_s* SequencePickSentence( const char *groupName, int pickMethod, int *picked ); + +#endif /* _INCLUDE_SEQUENCE_H_ */ diff --git a/engine/anorms.h b/engine/anorms.h index c90f8d6..d147aea 100644 --- a/engine/anorms.h +++ b/engine/anorms.h @@ -1,177 +1,177 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -{-0.525731, 0.000000, 0.850651}, -{-0.442863, 0.238856, 0.864188}, -{-0.295242, 0.000000, 0.955423}, -{-0.309017, 0.500000, 0.809017}, -{-0.162460, 0.262866, 0.951056}, -{0.000000, 0.000000, 1.000000}, -{0.000000, 0.850651, 0.525731}, -{-0.147621, 0.716567, 0.681718}, -{0.147621, 0.716567, 0.681718}, -{0.000000, 0.525731, 0.850651}, -{0.309017, 0.500000, 0.809017}, -{0.525731, 0.000000, 0.850651}, -{0.295242, 0.000000, 0.955423}, -{0.442863, 0.238856, 0.864188}, -{0.162460, 0.262866, 0.951056}, -{-0.681718, 0.147621, 0.716567}, -{-0.809017, 0.309017, 0.500000}, -{-0.587785, 0.425325, 0.688191}, -{-0.850651, 0.525731, 0.000000}, -{-0.864188, 0.442863, 0.238856}, -{-0.716567, 0.681718, 0.147621}, -{-0.688191, 0.587785, 0.425325}, -{-0.500000, 0.809017, 0.309017}, -{-0.238856, 0.864188, 0.442863}, -{-0.425325, 0.688191, 0.587785}, -{-0.716567, 0.681718, -0.147621}, -{-0.500000, 0.809017, -0.309017}, -{-0.525731, 0.850651, 0.000000}, -{0.000000, 0.850651, -0.525731}, -{-0.238856, 0.864188, -0.442863}, -{0.000000, 0.955423, -0.295242}, -{-0.262866, 0.951056, -0.162460}, -{0.000000, 1.000000, 0.000000}, -{0.000000, 0.955423, 0.295242}, -{-0.262866, 0.951056, 0.162460}, -{0.238856, 0.864188, 0.442863}, -{0.262866, 0.951056, 0.162460}, -{0.500000, 0.809017, 0.309017}, -{0.238856, 0.864188, -0.442863}, -{0.262866, 0.951056, -0.162460}, -{0.500000, 0.809017, -0.309017}, -{0.850651, 0.525731, 0.000000}, -{0.716567, 0.681718, 0.147621}, -{0.716567, 0.681718, -0.147621}, -{0.525731, 0.850651, 0.000000}, -{0.425325, 0.688191, 0.587785}, -{0.864188, 0.442863, 0.238856}, -{0.688191, 0.587785, 0.425325}, -{0.809017, 0.309017, 0.500000}, -{0.681718, 0.147621, 0.716567}, -{0.587785, 0.425325, 0.688191}, -{0.955423, 0.295242, 0.000000}, -{1.000000, 0.000000, 0.000000}, -{0.951056, 0.162460, 0.262866}, -{0.850651, -0.525731, 0.000000}, -{0.955423, -0.295242, 0.000000}, -{0.864188, -0.442863, 0.238856}, -{0.951056, -0.162460, 0.262866}, -{0.809017, -0.309017, 0.500000}, -{0.681718, -0.147621, 0.716567}, -{0.850651, 0.000000, 0.525731}, -{0.864188, 0.442863, -0.238856}, -{0.809017, 0.309017, -0.500000}, -{0.951056, 0.162460, -0.262866}, -{0.525731, 0.000000, -0.850651}, -{0.681718, 0.147621, -0.716567}, -{0.681718, -0.147621, -0.716567}, -{0.850651, 0.000000, -0.525731}, -{0.809017, -0.309017, -0.500000}, -{0.864188, -0.442863, -0.238856}, -{0.951056, -0.162460, -0.262866}, -{0.147621, 0.716567, -0.681718}, -{0.309017, 0.500000, -0.809017}, -{0.425325, 0.688191, -0.587785}, -{0.442863, 0.238856, -0.864188}, -{0.587785, 0.425325, -0.688191}, -{0.688191, 0.587785, -0.425325}, -{-0.147621, 0.716567, -0.681718}, -{-0.309017, 0.500000, -0.809017}, -{0.000000, 0.525731, -0.850651}, -{-0.525731, 0.000000, -0.850651}, -{-0.442863, 0.238856, -0.864188}, -{-0.295242, 0.000000, -0.955423}, -{-0.162460, 0.262866, -0.951056}, -{0.000000, 0.000000, -1.000000}, -{0.295242, 0.000000, -0.955423}, -{0.162460, 0.262866, -0.951056}, -{-0.442863, -0.238856, -0.864188}, -{-0.309017, -0.500000, -0.809017}, -{-0.162460, -0.262866, -0.951056}, -{0.000000, -0.850651, -0.525731}, -{-0.147621, -0.716567, -0.681718}, -{0.147621, -0.716567, -0.681718}, -{0.000000, -0.525731, -0.850651}, -{0.309017, -0.500000, -0.809017}, -{0.442863, -0.238856, -0.864188}, -{0.162460, -0.262866, -0.951056}, -{0.238856, -0.864188, -0.442863}, -{0.500000, -0.809017, -0.309017}, -{0.425325, -0.688191, -0.587785}, -{0.716567, -0.681718, -0.147621}, -{0.688191, -0.587785, -0.425325}, -{0.587785, -0.425325, -0.688191}, -{0.000000, -0.955423, -0.295242}, -{0.000000, -1.000000, 0.000000}, -{0.262866, -0.951056, -0.162460}, -{0.000000, -0.850651, 0.525731}, -{0.000000, -0.955423, 0.295242}, -{0.238856, -0.864188, 0.442863}, -{0.262866, -0.951056, 0.162460}, -{0.500000, -0.809017, 0.309017}, -{0.716567, -0.681718, 0.147621}, -{0.525731, -0.850651, 0.000000}, -{-0.238856, -0.864188, -0.442863}, -{-0.500000, -0.809017, -0.309017}, -{-0.262866, -0.951056, -0.162460}, -{-0.850651, -0.525731, 0.000000}, -{-0.716567, -0.681718, -0.147621}, -{-0.716567, -0.681718, 0.147621}, -{-0.525731, -0.850651, 0.000000}, -{-0.500000, -0.809017, 0.309017}, -{-0.238856, -0.864188, 0.442863}, -{-0.262866, -0.951056, 0.162460}, -{-0.864188, -0.442863, 0.238856}, -{-0.809017, -0.309017, 0.500000}, -{-0.688191, -0.587785, 0.425325}, -{-0.681718, -0.147621, 0.716567}, -{-0.442863, -0.238856, 0.864188}, -{-0.587785, -0.425325, 0.688191}, -{-0.309017, -0.500000, 0.809017}, -{-0.147621, -0.716567, 0.681718}, -{-0.425325, -0.688191, 0.587785}, -{-0.162460, -0.262866, 0.951056}, -{0.442863, -0.238856, 0.864188}, -{0.162460, -0.262866, 0.951056}, -{0.309017, -0.500000, 0.809017}, -{0.147621, -0.716567, 0.681718}, -{0.000000, -0.525731, 0.850651}, -{0.425325, -0.688191, 0.587785}, -{0.587785, -0.425325, 0.688191}, -{0.688191, -0.587785, 0.425325}, -{-0.955423, 0.295242, 0.000000}, -{-0.951056, 0.162460, 0.262866}, -{-1.000000, 0.000000, 0.000000}, -{-0.850651, 0.000000, 0.525731}, -{-0.955423, -0.295242, 0.000000}, -{-0.951056, -0.162460, 0.262866}, -{-0.864188, 0.442863, -0.238856}, -{-0.951056, 0.162460, -0.262866}, -{-0.809017, 0.309017, -0.500000}, -{-0.864188, -0.442863, -0.238856}, -{-0.951056, -0.162460, -0.262866}, -{-0.809017, -0.309017, -0.500000}, -{-0.681718, 0.147621, -0.716567}, -{-0.681718, -0.147621, -0.716567}, -{-0.850651, 0.000000, -0.525731}, -{-0.688191, 0.587785, -0.425325}, -{-0.587785, 0.425325, -0.688191}, -{-0.425325, 0.688191, -0.587785}, -{-0.425325, -0.688191, -0.587785}, -{-0.587785, -0.425325, -0.688191}, -{-0.688191, -0.587785, -0.425325}, +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +{-0.525731, 0.000000, 0.850651}, +{-0.442863, 0.238856, 0.864188}, +{-0.295242, 0.000000, 0.955423}, +{-0.309017, 0.500000, 0.809017}, +{-0.162460, 0.262866, 0.951056}, +{0.000000, 0.000000, 1.000000}, +{0.000000, 0.850651, 0.525731}, +{-0.147621, 0.716567, 0.681718}, +{0.147621, 0.716567, 0.681718}, +{0.000000, 0.525731, 0.850651}, +{0.309017, 0.500000, 0.809017}, +{0.525731, 0.000000, 0.850651}, +{0.295242, 0.000000, 0.955423}, +{0.442863, 0.238856, 0.864188}, +{0.162460, 0.262866, 0.951056}, +{-0.681718, 0.147621, 0.716567}, +{-0.809017, 0.309017, 0.500000}, +{-0.587785, 0.425325, 0.688191}, +{-0.850651, 0.525731, 0.000000}, +{-0.864188, 0.442863, 0.238856}, +{-0.716567, 0.681718, 0.147621}, +{-0.688191, 0.587785, 0.425325}, +{-0.500000, 0.809017, 0.309017}, +{-0.238856, 0.864188, 0.442863}, +{-0.425325, 0.688191, 0.587785}, +{-0.716567, 0.681718, -0.147621}, +{-0.500000, 0.809017, -0.309017}, +{-0.525731, 0.850651, 0.000000}, +{0.000000, 0.850651, -0.525731}, +{-0.238856, 0.864188, -0.442863}, +{0.000000, 0.955423, -0.295242}, +{-0.262866, 0.951056, -0.162460}, +{0.000000, 1.000000, 0.000000}, +{0.000000, 0.955423, 0.295242}, +{-0.262866, 0.951056, 0.162460}, +{0.238856, 0.864188, 0.442863}, +{0.262866, 0.951056, 0.162460}, +{0.500000, 0.809017, 0.309017}, +{0.238856, 0.864188, -0.442863}, +{0.262866, 0.951056, -0.162460}, +{0.500000, 0.809017, -0.309017}, +{0.850651, 0.525731, 0.000000}, +{0.716567, 0.681718, 0.147621}, +{0.716567, 0.681718, -0.147621}, +{0.525731, 0.850651, 0.000000}, +{0.425325, 0.688191, 0.587785}, +{0.864188, 0.442863, 0.238856}, +{0.688191, 0.587785, 0.425325}, +{0.809017, 0.309017, 0.500000}, +{0.681718, 0.147621, 0.716567}, +{0.587785, 0.425325, 0.688191}, +{0.955423, 0.295242, 0.000000}, +{1.000000, 0.000000, 0.000000}, +{0.951056, 0.162460, 0.262866}, +{0.850651, -0.525731, 0.000000}, +{0.955423, -0.295242, 0.000000}, +{0.864188, -0.442863, 0.238856}, +{0.951056, -0.162460, 0.262866}, +{0.809017, -0.309017, 0.500000}, +{0.681718, -0.147621, 0.716567}, +{0.850651, 0.000000, 0.525731}, +{0.864188, 0.442863, -0.238856}, +{0.809017, 0.309017, -0.500000}, +{0.951056, 0.162460, -0.262866}, +{0.525731, 0.000000, -0.850651}, +{0.681718, 0.147621, -0.716567}, +{0.681718, -0.147621, -0.716567}, +{0.850651, 0.000000, -0.525731}, +{0.809017, -0.309017, -0.500000}, +{0.864188, -0.442863, -0.238856}, +{0.951056, -0.162460, -0.262866}, +{0.147621, 0.716567, -0.681718}, +{0.309017, 0.500000, -0.809017}, +{0.425325, 0.688191, -0.587785}, +{0.442863, 0.238856, -0.864188}, +{0.587785, 0.425325, -0.688191}, +{0.688191, 0.587785, -0.425325}, +{-0.147621, 0.716567, -0.681718}, +{-0.309017, 0.500000, -0.809017}, +{0.000000, 0.525731, -0.850651}, +{-0.525731, 0.000000, -0.850651}, +{-0.442863, 0.238856, -0.864188}, +{-0.295242, 0.000000, -0.955423}, +{-0.162460, 0.262866, -0.951056}, +{0.000000, 0.000000, -1.000000}, +{0.295242, 0.000000, -0.955423}, +{0.162460, 0.262866, -0.951056}, +{-0.442863, -0.238856, -0.864188}, +{-0.309017, -0.500000, -0.809017}, +{-0.162460, -0.262866, -0.951056}, +{0.000000, -0.850651, -0.525731}, +{-0.147621, -0.716567, -0.681718}, +{0.147621, -0.716567, -0.681718}, +{0.000000, -0.525731, -0.850651}, +{0.309017, -0.500000, -0.809017}, +{0.442863, -0.238856, -0.864188}, +{0.162460, -0.262866, -0.951056}, +{0.238856, -0.864188, -0.442863}, +{0.500000, -0.809017, -0.309017}, +{0.425325, -0.688191, -0.587785}, +{0.716567, -0.681718, -0.147621}, +{0.688191, -0.587785, -0.425325}, +{0.587785, -0.425325, -0.688191}, +{0.000000, -0.955423, -0.295242}, +{0.000000, -1.000000, 0.000000}, +{0.262866, -0.951056, -0.162460}, +{0.000000, -0.850651, 0.525731}, +{0.000000, -0.955423, 0.295242}, +{0.238856, -0.864188, 0.442863}, +{0.262866, -0.951056, 0.162460}, +{0.500000, -0.809017, 0.309017}, +{0.716567, -0.681718, 0.147621}, +{0.525731, -0.850651, 0.000000}, +{-0.238856, -0.864188, -0.442863}, +{-0.500000, -0.809017, -0.309017}, +{-0.262866, -0.951056, -0.162460}, +{-0.850651, -0.525731, 0.000000}, +{-0.716567, -0.681718, -0.147621}, +{-0.716567, -0.681718, 0.147621}, +{-0.525731, -0.850651, 0.000000}, +{-0.500000, -0.809017, 0.309017}, +{-0.238856, -0.864188, 0.442863}, +{-0.262866, -0.951056, 0.162460}, +{-0.864188, -0.442863, 0.238856}, +{-0.809017, -0.309017, 0.500000}, +{-0.688191, -0.587785, 0.425325}, +{-0.681718, -0.147621, 0.716567}, +{-0.442863, -0.238856, 0.864188}, +{-0.587785, -0.425325, 0.688191}, +{-0.309017, -0.500000, 0.809017}, +{-0.147621, -0.716567, 0.681718}, +{-0.425325, -0.688191, 0.587785}, +{-0.162460, -0.262866, 0.951056}, +{0.442863, -0.238856, 0.864188}, +{0.162460, -0.262866, 0.951056}, +{0.309017, -0.500000, 0.809017}, +{0.147621, -0.716567, 0.681718}, +{0.000000, -0.525731, 0.850651}, +{0.425325, -0.688191, 0.587785}, +{0.587785, -0.425325, 0.688191}, +{0.688191, -0.587785, 0.425325}, +{-0.955423, 0.295242, 0.000000}, +{-0.951056, 0.162460, 0.262866}, +{-1.000000, 0.000000, 0.000000}, +{-0.850651, 0.000000, 0.525731}, +{-0.955423, -0.295242, 0.000000}, +{-0.951056, -0.162460, 0.262866}, +{-0.864188, 0.442863, -0.238856}, +{-0.951056, 0.162460, -0.262866}, +{-0.809017, 0.309017, -0.500000}, +{-0.864188, -0.442863, -0.238856}, +{-0.951056, -0.162460, -0.262866}, +{-0.809017, -0.309017, -0.500000}, +{-0.681718, 0.147621, -0.716567}, +{-0.681718, -0.147621, -0.716567}, +{-0.850651, 0.000000, -0.525731}, +{-0.688191, 0.587785, -0.425325}, +{-0.587785, 0.425325, -0.688191}, +{-0.425325, 0.688191, -0.587785}, +{-0.425325, -0.688191, -0.587785}, +{-0.587785, -0.425325, -0.688191}, +{-0.688191, -0.587785, -0.425325}, diff --git a/engine/archtypes.h b/engine/archtypes.h index ea143ce..3315135 100644 --- a/engine/archtypes.h +++ b/engine/archtypes.h @@ -1,41 +1,41 @@ -// -// Word size dependent definitions -// DAL 1/03 -// -#ifndef ARCHTYPES_H -#define ARCHTYPES_H - -#ifdef __x86_64__ -#define X64BITS -#endif - -#if defined( _WIN32 ) && (! defined( __MINGW32__ )) - -typedef __int16 int16; -typedef unsigned __int16 uint16; -typedef __int32 int32; -typedef unsigned __int32 uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; -typedef __int32 intp; // intp is an integer that can accomodate a pointer -typedef unsigned __int32 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *) - -#else /* _WIN32 */ - -typedef short int16; -typedef unsigned short uint16; -typedef int int32; -typedef unsigned int uint32; -typedef long long int64; -typedef unsigned long long uint64; -#ifdef X64BITS -typedef long long intp; -typedef unsigned long long uintp; -#else -typedef int intp; -typedef unsigned int uintp; -#endif - -#endif /* else _WIN32 */ - -#endif /* ARCHTYPES_H */ +// +// Word size dependent definitions +// DAL 1/03 +// +#ifndef ARCHTYPES_H +#define ARCHTYPES_H + +#ifdef __x86_64__ +#define X64BITS +#endif + +#if defined( _WIN32 ) && (! defined( __MINGW32__ )) + +typedef __int16 int16; +typedef unsigned __int16 uint16; +typedef __int32 int32; +typedef unsigned __int32 uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; +typedef __int32 intp; // intp is an integer that can accomodate a pointer +typedef unsigned __int32 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *) + +#else /* _WIN32 */ + +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; +typedef long long int64; +typedef unsigned long long uint64; +#ifdef X64BITS +typedef long long intp; +typedef unsigned long long uintp; +#else +typedef int intp; +typedef unsigned int uintp; +#endif + +#endif /* else _WIN32 */ + +#endif /* ARCHTYPES_H */ diff --git a/engine/cdll_int.h b/engine/cdll_int.h index bc73ad3..337d4fe 100644 --- a/engine/cdll_int.h +++ b/engine/cdll_int.h @@ -1,352 +1,352 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// -// cdll_int.h -// -// 4-23-98 -// JOHN: client dll interface declarations -// - -#ifndef CDLL_INT_H -#define CDLL_INT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "const.h" - - -// this file is included by both the engine and the client-dll, -// so make sure engine declarations aren't done twice - -typedef int HSPRITE; // handle to a graphic - -#define SCRINFO_SCREENFLASH 1 -#define SCRINFO_STRETCHED 2 - -typedef struct SCREENINFO_s -{ - int iSize; - int iWidth; - int iHeight; - int iFlags; - int iCharHeight; - short charWidths[256]; -} SCREENINFO; - - -typedef struct client_data_s -{ - // fields that cannot be modified (ie. have no effect if changed) - vec3_t origin; - - // fields that can be changed by the cldll - vec3_t viewangles; - int iWeaponBits; - float fov; // field of view -} client_data_t; - -typedef struct client_sprite_s -{ - char szName[64]; - char szSprite[64]; - int hspr; - int iRes; - wrect_t rc; -} client_sprite_t; - -#ifndef CLIENT_TEXTMESAGE_S -typedef struct client_textmessage_s -{ - int effect; - byte r1, g1, b1, a1; // 2 colors for effects - byte r2, g2, b2, a2; - float x; - float y; - float fadein; - float fadeout; - float holdtime; - float fxtime; - const char *pName; - const char *pMessage; -} client_textmessage_t; -#endif - -typedef struct hud_player_info_s -{ - char *name; - short ping; - byte thisplayer; // TRUE if this is the calling player - - // stuff that's unused at the moment, but should be done - byte spectator; - byte packetloss; - - char *model; - short topcolor; - short bottomcolor; - -} hud_player_info_t; - - -typedef struct cl_enginefuncs_s -{ - // sprite handlers - HSPRITE ( *pfnSPR_Load ) ( const char *szPicName ); - int ( *pfnSPR_Frames ) ( HSPRITE hPic ); - int ( *pfnSPR_Height ) ( HSPRITE hPic, int frame ); - int ( *pfnSPR_Width ) ( HSPRITE hPic, int frame ); - void ( *pfnSPR_Set ) ( HSPRITE hPic, int r, int g, int b ); - void ( *pfnSPR_Draw ) ( int frame, int x, int y, const wrect_t *prc ); - void ( *pfnSPR_DrawHoles ) ( int frame, int x, int y, const wrect_t *prc ); - void ( *pfnSPR_DrawAdditive ) ( int frame, int x, int y, const wrect_t *prc ); - void ( *pfnSPR_EnableScissor ) ( int x, int y, int width, int height ); - void ( *pfnSPR_DisableScissor ) ( void ); - client_sprite_t *( *pfnSPR_GetList ) ( char *psz, int *piCount ); - - // screen handlers - void ( *pfnFillRGBA ) ( int x, int y, int width, int height, int r, int g, int b, int a ); - int ( *pfnGetScreenInfo ) ( SCREENINFO *pscrinfo ); - void ( *pfnSetCrosshair ) ( HSPRITE hspr, wrect_t rc, int r, int g, int b ); - - // cvar handlers - struct cvar_s *( *pfnRegisterVariable ) ( char *szName, char *szValue, int flags ); - float ( *pfnGetCvarFloat ) ( char *szName ); - char* ( *pfnGetCvarString ) ( char *szName ); - - // command handlers - int ( *pfnAddCommand ) ( char *cmd_name, void (*function)(void) ); - int ( *pfnHookUserMsg ) ( char *szMsgName, pfnUserMsgHook pfn ); - int ( *pfnServerCmd ) ( char *szCmdString ); - int ( *pfnClientCmd ) ( char *szCmdString ); - - void ( *pfnGetPlayerInfo ) ( int ent_num, hud_player_info_t *pinfo ); - - // sound handlers - void ( *pfnPlaySoundByName ) ( char *szSound, float volume ); - void ( *pfnPlaySoundByIndex ) ( int iSound, float volume ); - - // vector helpers - void ( *pfnAngleVectors ) ( const float * vecAngles, float * forward, float * right, float * up ); - - // text message system - client_textmessage_t *( *pfnTextMessageGet ) ( const char *pName ); - int ( *pfnDrawCharacter ) ( int x, int y, int number, int r, int g, int b ); - int ( *pfnDrawConsoleString ) ( int x, int y, char *string ); - void ( *pfnDrawSetTextColor ) ( float r, float g, float b ); - void ( *pfnDrawConsoleStringLen )( const char *string, int *length, int *height ); - - void ( *pfnConsolePrint ) ( const char *string ); - void ( *pfnCenterPrint ) ( const char *string ); - - -// Added for user input processing - int ( *GetWindowCenterX ) ( void ); - int ( *GetWindowCenterY ) ( void ); - void ( *GetViewAngles ) ( float * ); - void ( *SetViewAngles ) ( float * ); - int ( *GetMaxClients ) ( void ); - void ( *Cvar_SetValue ) ( char *cvar, float value ); - - int (*Cmd_Argc) (void); - char *( *Cmd_Argv ) ( int arg ); - void ( *Con_Printf ) ( char *fmt, ... ); - void ( *Con_DPrintf ) ( char *fmt, ... ); - void ( *Con_NPrintf ) ( int pos, char *fmt, ... ); - void ( *Con_NXPrintf ) ( struct con_nprint_s *info, char *fmt, ... ); - - const char *( *PhysInfo_ValueForKey ) ( const char *key ); - const char *( *ServerInfo_ValueForKey )( const char *key ); - float ( *GetClientMaxspeed ) ( void ); - int ( *CheckParm ) ( char *parm, char **ppnext ); - void ( *Key_Event ) ( int key, int down ); - void ( *GetMousePosition ) ( int *mx, int *my ); - int ( *IsNoClipping ) ( void ); - - struct cl_entity_s *( *GetLocalPlayer ) ( void ); - struct cl_entity_s *( *GetViewModel ) ( void ); - struct cl_entity_s *( *GetEntityByIndex ) ( int idx ); - - float ( *GetClientTime ) ( void ); - void ( *V_CalcShake ) ( void ); - void ( *V_ApplyShake ) ( float *origin, float *angles, float factor ); - - int ( *PM_PointContents ) ( float *point, int *truecontents ); - int ( *PM_WaterEntity ) ( float *p ); - struct pmtrace_s *( *PM_TraceLine ) ( float *start, float *end, int flags, int usehull, int ignore_pe ); - - struct model_s *( *CL_LoadModel ) ( const char *modelname, int *index ); - int ( *CL_CreateVisibleEntity ) ( int type, struct cl_entity_s *ent ); - - const struct model_s * ( *GetSpritePointer ) ( HSPRITE hSprite ); - void ( *pfnPlaySoundByNameAtLocation ) ( char *szSound, float volume, float *origin ); - - unsigned short ( *pfnPrecacheEvent ) ( int type, const char* psz ); - void ( *pfnPlaybackEvent ) ( 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 ( *pfnWeaponAnim ) ( int iAnim, int body ); - float ( *pfnRandomFloat ) ( float flLow, float flHigh ); - long ( *pfnRandomLong ) ( long lLow, long lHigh ); - void ( *pfnHookEvent ) ( char *name, void ( *pfnEvent )( struct event_args_s *args ) ); - int (*Con_IsVisible) (); - const char *( *pfnGetGameDirectory ) ( void ); - struct cvar_s *( *pfnGetCvarPointer ) ( const char *szName ); - const char *( *Key_LookupBinding ) ( const char *pBinding ); - const char *( *pfnGetLevelName ) ( void ); - void ( *pfnGetScreenFade ) ( struct screenfade_s *fade ); - void ( *pfnSetScreenFade ) ( struct screenfade_s *fade ); - void *( *VGui_GetPanel ) ( ); - void ( *VGui_ViewportPaintBackground ) (int extents[4]); - - byte* (*COM_LoadFile) ( char *path, int usehunk, int *pLength ); - char* (*COM_ParseFile) ( char *data, char *token ); - void (*COM_FreeFile) ( void *buffer ); - - struct triangleapi_s *pTriAPI; - struct efx_api_s *pEfxAPI; - struct event_api_s *pEventAPI; - struct demo_api_s *pDemoAPI; - struct net_api_s *pNetAPI; - struct IVoiceTweak_s *pVoiceTweak; - - // returns 1 if the client is a spectator only (connected to a proxy), 0 otherwise or 2 if in dev_overview mode - int ( *IsSpectateOnly ) ( void ); - struct model_s *( *LoadMapSprite ) ( const char *filename ); - - // file search functions - void ( *COM_AddAppDirectoryToSearchPath ) ( const char *pszBaseDir, const char *appName ); - int ( *COM_ExpandFilename) ( const char *fileName, char *nameOutBuffer, int nameOutBufferSize ); - - // User info - // playerNum is in the range (1, MaxClients) - // returns NULL if player doesn't exit - // returns "" if no value is set - const char *( *PlayerInfo_ValueForKey )( int playerNum, const char *key ); - void ( *PlayerInfo_SetValueForKey )( const char *key, const char *value ); - - // Gets a unique ID for the specified player. This is the same even if you see the player on a different server. - // iPlayer is an entity index, so client 0 would use iPlayer=1. - // Returns false if there is no player on the server in the specified slot. - qboolean (*GetPlayerUniqueID)(int iPlayer, char playerID[16]); - - // TrackerID access - int (*GetTrackerIDForPlayer)(int playerSlot); - int (*GetPlayerForTrackerID)(int trackerID); - - // Same as pfnServerCmd, but the message goes in the unreliable stream so it can't clog the net stream - // (but it might not get there). - int ( *pfnServerCmdUnreliable )( char *szCmdString ); - - void ( *pfnGetMousePos )( struct tagPOINT *ppt ); - void ( *pfnSetMousePos )( int x, int y ); - void ( *pfnSetMouseEnable )( qboolean fEnable ); - - - // undocumented interface starts here - struct cvar_s* (*pfnGetFirstCvarPtr)( void ); - void* (*pfnGetFirstCmdFunctionHandle)( void ); - void* (*pfnGetNextCmdFunctionHandle)( void *cmdhandle ); - const char* (*pfnGetCmdFunctionName)( void *cmdhandle ); - float (*pfnGetClientOldTime)( void ); - float (*pfnGetGravity)( void ); - struct model_s* (*pfnGetModelByIndex)( int index ); - void (*pfnSetFilterMode)( int mode ); // same as gl_texsort in original Quake - void (*pfnSetFilterColor)( float red, float green, float blue ); - void (*pfnSetFilterBrightness)( float brightness ); - void *(*pfnSequenceGet)( const char *fileName, const char *entryName ); - void (*pfnSPR_DrawGeneric)( int frame, int x, int y, const wrect_t *prc, int blendsrc, int blenddst, int width, int height ); - void *(*pfnSequencePickSentence)( const char *groupName, int pickMethod, int *entryPicked ); - int (*pfnDrawString)( int x, int y, const char *str, int r, int g, int b ); - int (*pfnDrawStringReverse)( int x, int y, const char *str, int r, int g, int b ); - const char *(*LocalPlayerInfo_ValueForKey)( const char* key ); - int (*pfnVGUI2DrawCharacter)( int x, int y, int ch, unsigned int font ); - int (*pfnVGUI2DrawCharacterAdditive)( int x, int y, int ch, int r, int g, int b, unsigned int font ); - unsigned int (*pfnGetApproxWavePlayLen)( char *filename ); - void* (*GetCareerGameUI)( void ); // g-cont. !!!! potential crash-point! - void (*Cvar_Set)( char *name, char *value ); - int (*pfnIsPlayingCareerMatch)( void ); - void (*pfnPlaySoundVoiceByName)( char *szSound, float volume, int pitch ); - void (*pfnPrimeMusicStream)( char *filename, int looping ); - double (*pfnSys_FloatTime)( void ); - - // decay funcs - void (*pfnProcessTutorMessageDecayBuffer)( int *buffer, int buflen ); - void (*pfnConstructTutorMessageDecayBuffer)( int *buffer, int buflen ); - void (*pfnResetTutorMessageDecayData)( void ); - - void (*pfnPlaySoundByNameAtPitch)( char *szSound, float volume, int pitch ); - void (*pfnFillRGBABlend)( int x, int y, int width, int height, int r, int g, int b, int a ); - int (*pfnGetAppID)( void ); - void *(*pfnGetAliases)( void ); - void (*pfnVguiWrap2_GetMouseDelta)( int *x, int *y ); -} cl_enginefunc_t; - -#ifndef IN_BUTTONS_H -#include "in_buttons.h" -#endif - -#define CLDLL_INTERFACE_VERSION 7 - -extern void ClientDLL_Init( void ); // from cdll_int.c -extern void ClientDLL_Shutdown( void ); -extern void ClientDLL_HudInit( void ); -extern void ClientDLL_HudVidInit( void ); -extern void ClientDLL_UpdateClientData( void ); -extern void ClientDLL_Frame( double time ); -extern void ClientDLL_HudRedraw( int intermission ); -extern void ClientDLL_MoveClient( struct playermove_s *ppmove ); -extern void ClientDLL_ClientMoveInit( struct playermove_s *ppmove ); -extern char ClientDLL_ClientTextureType( char *name ); - -extern void ClientDLL_CreateMove( float frametime, struct usercmd_s *cmd, int active ); -extern void ClientDLL_ActivateMouse( void ); -extern void ClientDLL_DeactivateMouse( void ); -extern void ClientDLL_MouseEvent( int mstate ); -extern void ClientDLL_ClearStates( void ); -extern int ClientDLL_IsThirdPerson( void ); -extern void ClientDLL_GetCameraOffsets( float *ofs ); -extern int ClientDLL_GraphKeyDown( void ); -extern struct kbutton_s *ClientDLL_FindKey( const char *name ); -extern void ClientDLL_CAM_Think( void ); -extern void ClientDLL_IN_Accumulate( void ); -extern void ClientDLL_CalcRefdef( struct ref_params_s *pparams ); -extern int ClientDLL_AddEntity( int type, struct cl_entity_s *ent ); -extern void ClientDLL_CreateEntities( void ); - -extern void ClientDLL_DrawNormalTriangles( void ); -extern void ClientDLL_DrawTransparentTriangles( void ); -extern void ClientDLL_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity ); -extern void ClientDLL_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed ); -extern void ClientDLL_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client ); -extern void ClientDLL_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src ); -extern void ClientDLL_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 ); -extern void ClientDLL_ReadDemoBuffer( int size, unsigned char *buffer ); -extern int ClientDLL_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size ); -extern int ClientDLL_GetHullBounds( int hullnumber, float *mins, float *maxs ); - -extern void ClientDLL_VGui_ConsolePrint(const char* text); - -extern int ClientDLL_Key_Event( int down, int keynum, const char *pszCurrentBinding ); -extern void ClientDLL_TempEntUpdate( double ft, double ct, double grav, struct tempent_s **ppFreeTE, struct tempent_s **ppActiveTE, int ( *addTEntity )( struct cl_entity_s *pEntity ), void ( *playTESound )( struct tempent_s *pTemp, float damp ) ); -extern struct cl_entity_s *ClientDLL_GetUserEntity( int index ); -extern void ClientDLL_VoiceStatus(int entindex, qboolean bTalking); -extern void ClientDLL_DirectorMessage( int iSize, void *pbuf ); - - -#ifdef __cplusplus -} -#endif - -#endif // CDLL_INT_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// +// cdll_int.h +// +// 4-23-98 +// JOHN: client dll interface declarations +// + +#ifndef CDLL_INT_H +#define CDLL_INT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "const.h" + + +// this file is included by both the engine and the client-dll, +// so make sure engine declarations aren't done twice + +typedef int HSPRITE; // handle to a graphic + +#define SCRINFO_SCREENFLASH 1 +#define SCRINFO_STRETCHED 2 + +typedef struct SCREENINFO_s +{ + int iSize; + int iWidth; + int iHeight; + int iFlags; + int iCharHeight; + short charWidths[256]; +} SCREENINFO; + + +typedef struct client_data_s +{ + // fields that cannot be modified (ie. have no effect if changed) + vec3_t origin; + + // fields that can be changed by the cldll + vec3_t viewangles; + int iWeaponBits; + float fov; // field of view +} client_data_t; + +typedef struct client_sprite_s +{ + char szName[64]; + char szSprite[64]; + int hspr; + int iRes; + wrect_t rc; +} client_sprite_t; + +#ifndef CLIENT_TEXTMESAGE_S +typedef struct client_textmessage_s +{ + int effect; + byte r1, g1, b1, a1; // 2 colors for effects + byte r2, g2, b2, a2; + float x; + float y; + float fadein; + float fadeout; + float holdtime; + float fxtime; + const char *pName; + const char *pMessage; +} client_textmessage_t; +#endif + +typedef struct hud_player_info_s +{ + char *name; + short ping; + byte thisplayer; // TRUE if this is the calling player + + // stuff that's unused at the moment, but should be done + byte spectator; + byte packetloss; + + char *model; + short topcolor; + short bottomcolor; + +} hud_player_info_t; + + +typedef struct cl_enginefuncs_s +{ + // sprite handlers + HSPRITE ( *pfnSPR_Load ) ( const char *szPicName ); + int ( *pfnSPR_Frames ) ( HSPRITE hPic ); + int ( *pfnSPR_Height ) ( HSPRITE hPic, int frame ); + int ( *pfnSPR_Width ) ( HSPRITE hPic, int frame ); + void ( *pfnSPR_Set ) ( HSPRITE hPic, int r, int g, int b ); + void ( *pfnSPR_Draw ) ( int frame, int x, int y, const wrect_t *prc ); + void ( *pfnSPR_DrawHoles ) ( int frame, int x, int y, const wrect_t *prc ); + void ( *pfnSPR_DrawAdditive ) ( int frame, int x, int y, const wrect_t *prc ); + void ( *pfnSPR_EnableScissor ) ( int x, int y, int width, int height ); + void ( *pfnSPR_DisableScissor ) ( void ); + client_sprite_t *( *pfnSPR_GetList ) ( char *psz, int *piCount ); + + // screen handlers + void ( *pfnFillRGBA ) ( int x, int y, int width, int height, int r, int g, int b, int a ); + int ( *pfnGetScreenInfo ) ( SCREENINFO *pscrinfo ); + void ( *pfnSetCrosshair ) ( HSPRITE hspr, wrect_t rc, int r, int g, int b ); + + // cvar handlers + struct cvar_s *( *pfnRegisterVariable ) ( char *szName, char *szValue, int flags ); + float ( *pfnGetCvarFloat ) ( char *szName ); + char* ( *pfnGetCvarString ) ( char *szName ); + + // command handlers + int ( *pfnAddCommand ) ( char *cmd_name, void (*function)(void) ); + int ( *pfnHookUserMsg ) ( char *szMsgName, pfnUserMsgHook pfn ); + int ( *pfnServerCmd ) ( char *szCmdString ); + int ( *pfnClientCmd ) ( char *szCmdString ); + + void ( *pfnGetPlayerInfo ) ( int ent_num, hud_player_info_t *pinfo ); + + // sound handlers + void ( *pfnPlaySoundByName ) ( char *szSound, float volume ); + void ( *pfnPlaySoundByIndex ) ( int iSound, float volume ); + + // vector helpers + void ( *pfnAngleVectors ) ( const float * vecAngles, float * forward, float * right, float * up ); + + // text message system + client_textmessage_t *( *pfnTextMessageGet ) ( const char *pName ); + int ( *pfnDrawCharacter ) ( int x, int y, int number, int r, int g, int b ); + int ( *pfnDrawConsoleString ) ( int x, int y, char *string ); + void ( *pfnDrawSetTextColor ) ( float r, float g, float b ); + void ( *pfnDrawConsoleStringLen )( const char *string, int *length, int *height ); + + void ( *pfnConsolePrint ) ( const char *string ); + void ( *pfnCenterPrint ) ( const char *string ); + + +// Added for user input processing + int ( *GetWindowCenterX ) ( void ); + int ( *GetWindowCenterY ) ( void ); + void ( *GetViewAngles ) ( float * ); + void ( *SetViewAngles ) ( float * ); + int ( *GetMaxClients ) ( void ); + void ( *Cvar_SetValue ) ( char *cvar, float value ); + + int (*Cmd_Argc) (void); + char *( *Cmd_Argv ) ( int arg ); + void ( *Con_Printf ) ( char *fmt, ... ); + void ( *Con_DPrintf ) ( char *fmt, ... ); + void ( *Con_NPrintf ) ( int pos, char *fmt, ... ); + void ( *Con_NXPrintf ) ( struct con_nprint_s *info, char *fmt, ... ); + + const char *( *PhysInfo_ValueForKey ) ( const char *key ); + const char *( *ServerInfo_ValueForKey )( const char *key ); + float ( *GetClientMaxspeed ) ( void ); + int ( *CheckParm ) ( char *parm, char **ppnext ); + void ( *Key_Event ) ( int key, int down ); + void ( *GetMousePosition ) ( int *mx, int *my ); + int ( *IsNoClipping ) ( void ); + + struct cl_entity_s *( *GetLocalPlayer ) ( void ); + struct cl_entity_s *( *GetViewModel ) ( void ); + struct cl_entity_s *( *GetEntityByIndex ) ( int idx ); + + float ( *GetClientTime ) ( void ); + void ( *V_CalcShake ) ( void ); + void ( *V_ApplyShake ) ( float *origin, float *angles, float factor ); + + int ( *PM_PointContents ) ( float *point, int *truecontents ); + int ( *PM_WaterEntity ) ( float *p ); + struct pmtrace_s *( *PM_TraceLine ) ( float *start, float *end, int flags, int usehull, int ignore_pe ); + + struct model_s *( *CL_LoadModel ) ( const char *modelname, int *index ); + int ( *CL_CreateVisibleEntity ) ( int type, struct cl_entity_s *ent ); + + const struct model_s * ( *GetSpritePointer ) ( HSPRITE hSprite ); + void ( *pfnPlaySoundByNameAtLocation ) ( char *szSound, float volume, float *origin ); + + unsigned short ( *pfnPrecacheEvent ) ( int type, const char* psz ); + void ( *pfnPlaybackEvent ) ( 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 ( *pfnWeaponAnim ) ( int iAnim, int body ); + float ( *pfnRandomFloat ) ( float flLow, float flHigh ); + long ( *pfnRandomLong ) ( long lLow, long lHigh ); + void ( *pfnHookEvent ) ( char *name, void ( *pfnEvent )( struct event_args_s *args ) ); + int (*Con_IsVisible) (); + const char *( *pfnGetGameDirectory ) ( void ); + struct cvar_s *( *pfnGetCvarPointer ) ( const char *szName ); + const char *( *Key_LookupBinding ) ( const char *pBinding ); + const char *( *pfnGetLevelName ) ( void ); + void ( *pfnGetScreenFade ) ( struct screenfade_s *fade ); + void ( *pfnSetScreenFade ) ( struct screenfade_s *fade ); + void *( *VGui_GetPanel ) ( ); + void ( *VGui_ViewportPaintBackground ) (int extents[4]); + + byte* (*COM_LoadFile) ( char *path, int usehunk, int *pLength ); + char* (*COM_ParseFile) ( char *data, char *token ); + void (*COM_FreeFile) ( void *buffer ); + + struct triangleapi_s *pTriAPI; + struct efx_api_s *pEfxAPI; + struct event_api_s *pEventAPI; + struct demo_api_s *pDemoAPI; + struct net_api_s *pNetAPI; + struct IVoiceTweak_s *pVoiceTweak; + + // returns 1 if the client is a spectator only (connected to a proxy), 0 otherwise or 2 if in dev_overview mode + int ( *IsSpectateOnly ) ( void ); + struct model_s *( *LoadMapSprite ) ( const char *filename ); + + // file search functions + void ( *COM_AddAppDirectoryToSearchPath ) ( const char *pszBaseDir, const char *appName ); + int ( *COM_ExpandFilename) ( const char *fileName, char *nameOutBuffer, int nameOutBufferSize ); + + // User info + // playerNum is in the range (1, MaxClients) + // returns NULL if player doesn't exit + // returns "" if no value is set + const char *( *PlayerInfo_ValueForKey )( int playerNum, const char *key ); + void ( *PlayerInfo_SetValueForKey )( const char *key, const char *value ); + + // Gets a unique ID for the specified player. This is the same even if you see the player on a different server. + // iPlayer is an entity index, so client 0 would use iPlayer=1. + // Returns false if there is no player on the server in the specified slot. + qboolean (*GetPlayerUniqueID)(int iPlayer, char playerID[16]); + + // TrackerID access + int (*GetTrackerIDForPlayer)(int playerSlot); + int (*GetPlayerForTrackerID)(int trackerID); + + // Same as pfnServerCmd, but the message goes in the unreliable stream so it can't clog the net stream + // (but it might not get there). + int ( *pfnServerCmdUnreliable )( char *szCmdString ); + + void ( *pfnGetMousePos )( struct tagPOINT *ppt ); + void ( *pfnSetMousePos )( int x, int y ); + void ( *pfnSetMouseEnable )( qboolean fEnable ); + + + // undocumented interface starts here + struct cvar_s* (*pfnGetFirstCvarPtr)( void ); + void* (*pfnGetFirstCmdFunctionHandle)( void ); + void* (*pfnGetNextCmdFunctionHandle)( void *cmdhandle ); + const char* (*pfnGetCmdFunctionName)( void *cmdhandle ); + float (*pfnGetClientOldTime)( void ); + float (*pfnGetGravity)( void ); + struct model_s* (*pfnGetModelByIndex)( int index ); + void (*pfnSetFilterMode)( int mode ); // same as gl_texsort in original Quake + void (*pfnSetFilterColor)( float red, float green, float blue ); + void (*pfnSetFilterBrightness)( float brightness ); + void *(*pfnSequenceGet)( const char *fileName, const char *entryName ); + void (*pfnSPR_DrawGeneric)( int frame, int x, int y, const wrect_t *prc, int blendsrc, int blenddst, int width, int height ); + void *(*pfnSequencePickSentence)( const char *groupName, int pickMethod, int *entryPicked ); + int (*pfnDrawString)( int x, int y, const char *str, int r, int g, int b ); + int (*pfnDrawStringReverse)( int x, int y, const char *str, int r, int g, int b ); + const char *(*LocalPlayerInfo_ValueForKey)( const char* key ); + int (*pfnVGUI2DrawCharacter)( int x, int y, int ch, unsigned int font ); + int (*pfnVGUI2DrawCharacterAdditive)( int x, int y, int ch, int r, int g, int b, unsigned int font ); + unsigned int (*pfnGetApproxWavePlayLen)( char *filename ); + void* (*GetCareerGameUI)( void ); // g-cont. !!!! potential crash-point! + void (*Cvar_Set)( char *name, char *value ); + int (*pfnIsPlayingCareerMatch)( void ); + void (*pfnPlaySoundVoiceByName)( char *szSound, float volume, int pitch ); + void (*pfnPrimeMusicStream)( char *filename, int looping ); + double (*pfnSys_FloatTime)( void ); + + // decay funcs + void (*pfnProcessTutorMessageDecayBuffer)( int *buffer, int buflen ); + void (*pfnConstructTutorMessageDecayBuffer)( int *buffer, int buflen ); + void (*pfnResetTutorMessageDecayData)( void ); + + void (*pfnPlaySoundByNameAtPitch)( char *szSound, float volume, int pitch ); + void (*pfnFillRGBABlend)( int x, int y, int width, int height, int r, int g, int b, int a ); + int (*pfnGetAppID)( void ); + void *(*pfnGetAliases)( void ); + void (*pfnVguiWrap2_GetMouseDelta)( int *x, int *y ); +} cl_enginefunc_t; + +#ifndef IN_BUTTONS_H +#include "in_buttons.h" +#endif + +#define CLDLL_INTERFACE_VERSION 7 + +extern void ClientDLL_Init( void ); // from cdll_int.c +extern void ClientDLL_Shutdown( void ); +extern void ClientDLL_HudInit( void ); +extern void ClientDLL_HudVidInit( void ); +extern void ClientDLL_UpdateClientData( void ); +extern void ClientDLL_Frame( double time ); +extern void ClientDLL_HudRedraw( int intermission ); +extern void ClientDLL_MoveClient( struct playermove_s *ppmove ); +extern void ClientDLL_ClientMoveInit( struct playermove_s *ppmove ); +extern char ClientDLL_ClientTextureType( char *name ); + +extern void ClientDLL_CreateMove( float frametime, struct usercmd_s *cmd, int active ); +extern void ClientDLL_ActivateMouse( void ); +extern void ClientDLL_DeactivateMouse( void ); +extern void ClientDLL_MouseEvent( int mstate ); +extern void ClientDLL_ClearStates( void ); +extern int ClientDLL_IsThirdPerson( void ); +extern void ClientDLL_GetCameraOffsets( float *ofs ); +extern int ClientDLL_GraphKeyDown( void ); +extern struct kbutton_s *ClientDLL_FindKey( const char *name ); +extern void ClientDLL_CAM_Think( void ); +extern void ClientDLL_IN_Accumulate( void ); +extern void ClientDLL_CalcRefdef( struct ref_params_s *pparams ); +extern int ClientDLL_AddEntity( int type, struct cl_entity_s *ent ); +extern void ClientDLL_CreateEntities( void ); + +extern void ClientDLL_DrawNormalTriangles( void ); +extern void ClientDLL_DrawTransparentTriangles( void ); +extern void ClientDLL_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity ); +extern void ClientDLL_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed ); +extern void ClientDLL_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client ); +extern void ClientDLL_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src ); +extern void ClientDLL_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 ); +extern void ClientDLL_ReadDemoBuffer( int size, unsigned char *buffer ); +extern int ClientDLL_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size ); +extern int ClientDLL_GetHullBounds( int hullnumber, float *mins, float *maxs ); + +extern void ClientDLL_VGui_ConsolePrint(const char* text); + +extern int ClientDLL_Key_Event( int down, int keynum, const char *pszCurrentBinding ); +extern void ClientDLL_TempEntUpdate( double ft, double ct, double grav, struct tempent_s **ppFreeTE, struct tempent_s **ppActiveTE, int ( *addTEntity )( struct cl_entity_s *pEntity ), void ( *playTESound )( struct tempent_s *pTemp, float damp ) ); +extern struct cl_entity_s *ClientDLL_GetUserEntity( int index ); +extern void ClientDLL_VoiceStatus(int entindex, qboolean bTalking); +extern void ClientDLL_DirectorMessage( int iSize, void *pbuf ); + + +#ifdef __cplusplus +} +#endif + +#endif // CDLL_INT_H diff --git a/engine/custom.h b/engine/custom.h index 077832a..79030ef 100644 --- a/engine/custom.h +++ b/engine/custom.h @@ -1,103 +1,103 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// Customization.h - -#ifndef CUSTOM_H -#define CUSTOM_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -#include "const.h" - -#define MAX_QPATH 64 // Must match value in quakedefs.h - -///////////////// -// Customization -// passed to pfnPlayerCustomization -// For automatic downloading. -typedef enum -{ - t_sound = 0, - t_skin, - t_model, - t_decal, - t_generic, - t_eventscript, - t_world, // Fake type for world, is really t_model -} resourcetype_t; - - -typedef struct -{ - int size; -} _resourceinfo_t; - -typedef struct resourceinfo_s -{ - _resourceinfo_t info[ 8 ]; -} resourceinfo_t; - -#define RES_FATALIFMISSING (1<<0) // Disconnect if we can't get this file. -#define RES_WASMISSING (1<<1) // Do we have the file locally, did we get it ok? -#define RES_CUSTOM (1<<2) // Is this resource one that corresponds to another player's customization - // or is it a server startup resource. -#define RES_REQUESTED (1<<3) // Already requested a download of this one -#define RES_PRECACHED (1<<4) // Already precached - -#include "crc.h" - -typedef struct resource_s -{ - char szFileName[MAX_QPATH]; // File name to download/precache. - resourcetype_t type; // t_sound, t_skin, t_model, t_decal. - int nIndex; // For t_decals - int nDownloadSize; // Size in Bytes if this must be downloaded. - unsigned char ucFlags; - -// For handling client to client resource propagation - unsigned char rgucMD5_hash[16]; // To determine if we already have it. - unsigned char playernum; // Which player index this resource is associated with, if it's a custom resource. - - unsigned char rguc_reserved[ 32 ]; // For future expansion - struct resource_s *pNext; // Next in chain. - struct resource_s *pPrev; -} resource_t; - -typedef struct customization_s -{ - qboolean bInUse; // Is this customization in use; - resource_t resource; // The resource_t for this customization - qboolean bTranslated; // Has the raw data been translated into a useable format? - // (e.g., raw decal .wad make into texture_t *) - int nUserData1; // Customization specific data - int nUserData2; // Customization specific data - void *pInfo; // Buffer that holds the data structure that references the data (e.g., the cachewad_t) - void *pBuffer; // Buffer that holds the data for the customization (the raw .wad data) - struct customization_s *pNext; // Next in chain -} customization_t; - -#define FCUST_FROMHPAK ( 1<<0 ) -#define FCUST_WIPEDATA ( 1<<1 ) -#define FCUST_IGNOREINIT ( 1<<2 ) - -void COM_ClearCustomizationList( struct customization_s *pHead, qboolean bCleanDecals); -qboolean COM_CreateCustomization( struct customization_s *pListHead, struct resource_s *pResource, int playernumber, int flags, - struct customization_s **pCustomization, int *nLumps ); -int COM_SizeofResourceList ( struct resource_s *pList, struct resourceinfo_s *ri ); - -#endif // CUSTOM_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// Customization.h + +#ifndef CUSTOM_H +#define CUSTOM_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +#include "const.h" + +#define MAX_QPATH 64 // Must match value in quakedefs.h + +///////////////// +// Customization +// passed to pfnPlayerCustomization +// For automatic downloading. +typedef enum +{ + t_sound = 0, + t_skin, + t_model, + t_decal, + t_generic, + t_eventscript, + t_world, // Fake type for world, is really t_model +} resourcetype_t; + + +typedef struct +{ + int size; +} _resourceinfo_t; + +typedef struct resourceinfo_s +{ + _resourceinfo_t info[ 8 ]; +} resourceinfo_t; + +#define RES_FATALIFMISSING (1<<0) // Disconnect if we can't get this file. +#define RES_WASMISSING (1<<1) // Do we have the file locally, did we get it ok? +#define RES_CUSTOM (1<<2) // Is this resource one that corresponds to another player's customization + // or is it a server startup resource. +#define RES_REQUESTED (1<<3) // Already requested a download of this one +#define RES_PRECACHED (1<<4) // Already precached + +#include "crc.h" + +typedef struct resource_s +{ + char szFileName[MAX_QPATH]; // File name to download/precache. + resourcetype_t type; // t_sound, t_skin, t_model, t_decal. + int nIndex; // For t_decals + int nDownloadSize; // Size in Bytes if this must be downloaded. + unsigned char ucFlags; + +// For handling client to client resource propagation + unsigned char rgucMD5_hash[16]; // To determine if we already have it. + unsigned char playernum; // Which player index this resource is associated with, if it's a custom resource. + + unsigned char rguc_reserved[ 32 ]; // For future expansion + struct resource_s *pNext; // Next in chain. + struct resource_s *pPrev; +} resource_t; + +typedef struct customization_s +{ + qboolean bInUse; // Is this customization in use; + resource_t resource; // The resource_t for this customization + qboolean bTranslated; // Has the raw data been translated into a useable format? + // (e.g., raw decal .wad make into texture_t *) + int nUserData1; // Customization specific data + int nUserData2; // Customization specific data + void *pInfo; // Buffer that holds the data structure that references the data (e.g., the cachewad_t) + void *pBuffer; // Buffer that holds the data for the customization (the raw .wad data) + struct customization_s *pNext; // Next in chain +} customization_t; + +#define FCUST_FROMHPAK ( 1<<0 ) +#define FCUST_WIPEDATA ( 1<<1 ) +#define FCUST_IGNOREINIT ( 1<<2 ) + +void COM_ClearCustomizationList( struct customization_s *pHead, qboolean bCleanDecals); +qboolean COM_CreateCustomization( struct customization_s *pListHead, struct resource_s *pResource, int playernumber, int flags, + struct customization_s **pCustomization, int *nLumps ); +int COM_SizeofResourceList ( struct resource_s *pList, struct resourceinfo_s *ri ); + +#endif // CUSTOM_H diff --git a/engine/customentity.h b/engine/customentity.h index 2c4eb5e..0895bee 100644 --- a/engine/customentity.h +++ b/engine/customentity.h @@ -1,38 +1,38 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef CUSTOMENTITY_H -#define CUSTOMENTITY_H - -// Custom Entities - -// Start/End Entity is encoded as 12 bits of entity index, and 4 bits of attachment (4:12) -#define BEAMENT_ENTITY(x) ((x)&0xFFF) -#define BEAMENT_ATTACHMENT(x) (((x)>>12)&0xF) - -// Beam types, encoded as a byte -enum -{ - BEAM_POINTS = 0, - BEAM_ENTPOINT, - BEAM_ENTS, - BEAM_HOSE, -}; - -#define BEAM_FSINE 0x10 -#define BEAM_FSOLID 0x20 -#define BEAM_FSHADEIN 0x40 -#define BEAM_FSHADEOUT 0x80 - -#endif //CUSTOMENTITY_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef CUSTOMENTITY_H +#define CUSTOMENTITY_H + +// Custom Entities + +// Start/End Entity is encoded as 12 bits of entity index, and 4 bits of attachment (4:12) +#define BEAMENT_ENTITY(x) ((x)&0xFFF) +#define BEAMENT_ATTACHMENT(x) (((x)>>12)&0xF) + +// Beam types, encoded as a byte +enum +{ + BEAM_POINTS = 0, + BEAM_ENTPOINT, + BEAM_ENTS, + BEAM_HOSE, +}; + +#define BEAM_FSINE 0x10 +#define BEAM_FSOLID 0x20 +#define BEAM_FSHADEIN 0x40 +#define BEAM_FSHADEOUT 0x80 + +#endif //CUSTOMENTITY_H diff --git a/engine/edict.h b/engine/edict.h index ba11fb9..58f2c0c 100644 --- a/engine/edict.h +++ b/engine/edict.h @@ -1,38 +1,38 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#if !defined EDICT_H -#define EDICT_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif -#define MAX_ENT_LEAFS 48 - -#include "progdefs.h" - -struct edict_s -{ - qboolean free; - int serialnumber; - link_t area; // linked to a division node or leaf - - int headnode; // -1 to use normal leaf check - int num_leafs; - short leafnums[MAX_ENT_LEAFS]; - - float freetime; // sv.time when the object was freed - - void* pvPrivateData; // Alloced and freed by engine, used by DLLs - - entvars_t v; // C exported fields from progs - - // other fields from progs come immediately after -}; - -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#if !defined EDICT_H +#define EDICT_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif +#define MAX_ENT_LEAFS 48 + +#include "progdefs.h" + +struct edict_s +{ + qboolean free; + int serialnumber; + link_t area; // linked to a division node or leaf + + int headnode; // -1 to use normal leaf check + int num_leafs; + short leafnums[MAX_ENT_LEAFS]; + + float freetime; // sv.time when the object was freed + + void* pvPrivateData; // Alloced and freed by engine, used by DLLs + + entvars_t v; // C exported fields from progs + + // other fields from progs come immediately after +}; + +#endif diff --git a/engine/eiface.h b/engine/eiface.h index cd6d438..a0bdff0 100644 --- a/engine/eiface.h +++ b/engine/eiface.h @@ -1,531 +1,531 @@ -/*** -* -* 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. -* -****/ -#ifndef EIFACE_H -#define EIFACE_H - -#include "archtypes.h" // DAL - -#ifdef HLDEMO_BUILD -#define INTERFACE_VERSION 001 -#else // !HLDEMO_BUILD, i.e., regular version of HL -#define INTERFACE_VERSION 140 -#endif // !HLDEMO_BUILD - -#include -#include "custom.h" -#include "cvardef.h" -#include "Sequence.h" -// -// Defines entity interface between engine and DLLs. -// This header file included by engine files and DLL files. -// -// Before including this header, DLLs must: -// include progdefs.h -// This is conveniently done for them in extdll.h -// - -#ifdef _WIN32 -#define DLLEXPORT __stdcall -#else -#define DLLEXPORT /* */ -#endif - -typedef enum - { - at_notice, - at_console, // same as at_notice, but forces a ConPrintf, not a message box - at_aiconsole, // same as at_console, but only shown if developer level is 2! - at_warning, - at_error, - at_logged // Server print to console ( only in multiplayer games ). - } ALERT_TYPE; - -// 4-22-98 JOHN: added for use in pfnClientPrintf -typedef enum - { - print_console, - print_center, - print_chat, - } PRINT_TYPE; - -// For integrity checking of content on clients -typedef enum -{ - force_exactfile, // File on client must exactly match server's file - force_model_samebounds, // For model files only, the geometry must fit in the same bbox - force_model_specifybounds, // For model files only, the geometry must fit in the specified bbox - force_model_specifybounds_if_avail, // For Steam model files only, the geometry must fit in the specified bbox (if the file is available) -} FORCE_TYPE; - -// Returned by TraceLine -typedef struct - { - int fAllSolid; // if true, plane is not valid - int fStartSolid; // if true, the initial point was in a solid area - int fInOpen; - int fInWater; - float flFraction; // time completed, 1.0 = didn't hit anything - vec3_t vecEndPos; // final position - float flPlaneDist; - vec3_t vecPlaneNormal; // surface normal at impact - edict_t *pHit; // entity the surface is on - int iHitgroup; // 0 == generic, non zero is specific body part - } TraceResult; - -// CD audio status -typedef struct -{ - int fPlaying;// is sound playing right now? - int fWasPlaying;// if not, CD is paused if WasPlaying is true. - int fInitialized; - int fEnabled; - int fPlayLooping; - float cdvolume; - //BYTE remap[100]; - int fCDRom; - int fPlayTrack; -} CDStatus; - -#include "../common/crc.h" - - -// Engine hands this to DLLs for functionality callbacks -typedef struct enginefuncs_s -{ - int (*pfnPrecacheModel) (char* s); - int (*pfnPrecacheSound) (char* s); - void (*pfnSetModel) (edict_t *e, const char *m); - int (*pfnModelIndex) (const char *m); - int (*pfnModelFrames) (int modelIndex); - void (*pfnSetSize) (edict_t *e, const float *rgflMin, const float *rgflMax); - void (*pfnChangeLevel) (char* s1, char* s2); - void (*pfnGetSpawnParms) (edict_t *ent); - void (*pfnSaveSpawnParms) (edict_t *ent); - float (*pfnVecToYaw) (const float *rgflVector); - void (*pfnVecToAngles) (const float *rgflVectorIn, float *rgflVectorOut); - void (*pfnMoveToOrigin) (edict_t *ent, const float *pflGoal, float dist, int iMoveType); - void (*pfnChangeYaw) (edict_t* ent); - void (*pfnChangePitch) (edict_t* ent); - edict_t* (*pfnFindEntityByString) (edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue); - int (*pfnGetEntityIllum) (edict_t* pEnt); - edict_t* (*pfnFindEntityInSphere) (edict_t *pEdictStartSearchAfter, const float *org, float rad); - edict_t* (*pfnFindClientInPVS) (edict_t *pEdict); - edict_t* (*pfnEntitiesInPVS) (edict_t *pplayer); - void (*pfnMakeVectors) (const float *rgflVector); - void (*pfnAngleVectors) (const float *rgflVector, float *forward, float *right, float *up); - edict_t* (*pfnCreateEntity) (void); - void (*pfnRemoveEntity) (edict_t* e); - edict_t* (*pfnCreateNamedEntity) (int className); - void (*pfnMakeStatic) (edict_t *ent); - int (*pfnEntIsOnFloor) (edict_t *e); - int (*pfnDropToFloor) (edict_t* e); - int (*pfnWalkMove) (edict_t *ent, float yaw, float dist, int iMode); - void (*pfnSetOrigin) (edict_t *e, const float *rgflOrigin); - void (*pfnEmitSound) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch); - void (*pfnEmitAmbientSound) (edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch); - void (*pfnTraceLine) (const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr); - void (*pfnTraceToss) (edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr); - int (*pfnTraceMonsterHull) (edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr); - void (*pfnTraceHull) (const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr); - void (*pfnTraceModel) (const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr); - const char *(*pfnTraceTexture) (edict_t *pTextureEntity, const float *v1, const float *v2 ); - void (*pfnTraceSphere) (const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr); - void (*pfnGetAimVector) (edict_t* ent, float speed, float *rgflReturn); - void (*pfnServerCommand) (char* str); - void (*pfnServerExecute) (void); - void (*pfnClientCommand) (edict_t* pEdict, char* szFmt, ...); - void (*pfnParticleEffect) (const float *org, const float *dir, float color, float count); - void (*pfnLightStyle) (int style, char* val); - int (*pfnDecalIndex) (const char *name); - int (*pfnPointContents) (const float *rgflVector); - void (*pfnMessageBegin) (int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); - void (*pfnMessageEnd) (void); - void (*pfnWriteByte) (int iValue); - void (*pfnWriteChar) (int iValue); - void (*pfnWriteShort) (int iValue); - void (*pfnWriteLong) (int iValue); - void (*pfnWriteAngle) (float flValue); - void (*pfnWriteCoord) (float flValue); - void (*pfnWriteString) (const char *sz); - void (*pfnWriteEntity) (int iValue); - void (*pfnCVarRegister) (cvar_t *pCvar); - float (*pfnCVarGetFloat) (const char *szVarName); - const char* (*pfnCVarGetString) (const char *szVarName); - void (*pfnCVarSetFloat) (const char *szVarName, float flValue); - void (*pfnCVarSetString) (const char *szVarName, const char *szValue); - void (*pfnAlertMessage) (ALERT_TYPE atype, char *szFmt, ...); - void (*pfnEngineFprintf) (void *pfile, char *szFmt, ...); - void* (*pfnPvAllocEntPrivateData) (edict_t *pEdict, int32 cb); - void* (*pfnPvEntPrivateData) (edict_t *pEdict); - void (*pfnFreeEntPrivateData) (edict_t *pEdict); - const char* (*pfnSzFromIndex) (int iString); - int (*pfnAllocString) (const char *szValue); - struct entvars_s* (*pfnGetVarsOfEnt) (edict_t *pEdict); - edict_t* (*pfnPEntityOfEntOffset) (int iEntOffset); - int (*pfnEntOffsetOfPEntity) (const edict_t *pEdict); - int (*pfnIndexOfEdict) (const edict_t *pEdict); - edict_t* (*pfnPEntityOfEntIndex) (int iEntIndex); - edict_t* (*pfnFindEntityByVars) (struct entvars_s* pvars); - void* (*pfnGetModelPtr) (edict_t* pEdict); - int (*pfnRegUserMsg) (const char *pszName, int iSize); - void (*pfnAnimationAutomove) (const edict_t* pEdict, float flTime); - void (*pfnGetBonePosition) (const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles ); - uint32 (*pfnFunctionFromName) ( const char *pName ); - const char *(*pfnNameForFunction) ( uint32 function ); - void (*pfnClientPrintf) ( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg ); // JOHN: engine callbacks so game DLL can print messages to individual clients - void (*pfnServerPrint) ( const char *szMsg ); - const char *(*pfnCmd_Args) ( void ); // these 3 added - const char *(*pfnCmd_Argv) ( int argc ); // so game DLL can easily - int (*pfnCmd_Argc) ( void ); // access client 'cmd' strings - void (*pfnGetAttachment) (const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles ); - void (*pfnCRC32_Init) (CRC32_t *pulCRC); - void (*pfnCRC32_ProcessBuffer) (CRC32_t *pulCRC, void *p, int len); - void (*pfnCRC32_ProcessByte) (CRC32_t *pulCRC, unsigned char ch); - CRC32_t (*pfnCRC32_Final) (CRC32_t pulCRC); - int32 (*pfnRandomLong) (int32 lLow, int32 lHigh); - float (*pfnRandomFloat) (float flLow, float flHigh); - void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent ); - float (*pfnTime) ( void ); - void (*pfnCrosshairAngle) (const edict_t *pClient, float pitch, float yaw); - byte * (*pfnLoadFileForMe) (char *filename, int *pLength); - void (*pfnFreeFile) (void *buffer); - void (*pfnEndSection) (const char *pszSectionName); // trigger_endsection - int (*pfnCompareFileTime) (char *filename1, char *filename2, int *iCompare); - void (*pfnGetGameDir) (char *szGetGameDir); - void (*pfnCvar_RegisterVariable) (cvar_t *variable); - void (*pfnFadeClientVolume) (const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds); - void (*pfnSetClientMaxspeed) (const edict_t *pEdict, float fNewMaxspeed); - edict_t * (*pfnCreateFakeClient) (const char *netname); // returns NULL if fake client can't be created - void (*pfnRunPlayerMove) (edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec ); - int (*pfnNumberOfEntities) (void); - char* (*pfnGetInfoKeyBuffer) (edict_t *e); // passing in NULL gets the serverinfo - char* (*pfnInfoKeyValue) (char *infobuffer, char *key); - void (*pfnSetKeyValue) (char *infobuffer, char *key, char *value); - void (*pfnSetClientKeyValue) (int clientIndex, char *infobuffer, char *key, char *value); - int (*pfnIsMapValid) (char *filename); - void (*pfnStaticDecal) ( const float *origin, int decalIndex, int entityIndex, int modelIndex ); - int (*pfnPrecacheGeneric) (char* s); - int (*pfnGetPlayerUserId) (edict_t *e ); // returns the server assigned userid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients - void (*pfnBuildSoundMsg) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); - int (*pfnIsDedicatedServer) (void);// is this a dedicated server? - cvar_t *(*pfnCVarGetPointer) (const char *szVarName); - unsigned int (*pfnGetPlayerWONId) (edict_t *e); // returns the server assigned WONid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients - - // YWB 8/1/99 TFF Physics additions - void (*pfnInfo_RemoveKey) ( char *s, const char *key ); - const char *(*pfnGetPhysicsKeyValue) ( const edict_t *pClient, const char *key ); - void (*pfnSetPhysicsKeyValue) ( const edict_t *pClient, const char *key, const char *value ); - const char *(*pfnGetPhysicsInfoString) ( const edict_t *pClient ); - unsigned short (*pfnPrecacheEvent) ( int type, const char*psz ); - void (*pfnPlaybackEvent) ( 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 ); - - unsigned char *(*pfnSetFatPVS) ( float *org ); - unsigned char *(*pfnSetFatPAS) ( float *org ); - - int (*pfnCheckVisibility ) ( const edict_t *entity, unsigned char *pset ); - - void (*pfnDeltaSetField) ( struct delta_s *pFields, const char *fieldname ); - void (*pfnDeltaUnsetField) ( struct delta_s *pFields, const char *fieldname ); - void (*pfnDeltaAddEncoder) ( char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) ); - int (*pfnGetCurrentPlayer) ( void ); - int (*pfnCanSkipPlayer) ( const edict_t *player ); - int (*pfnDeltaFindField) ( struct delta_s *pFields, const char *fieldname ); - void (*pfnDeltaSetFieldByIndex) ( struct delta_s *pFields, int fieldNumber ); - void (*pfnDeltaUnsetFieldByIndex)( struct delta_s *pFields, int fieldNumber ); - - void (*pfnSetGroupMask) ( int mask, int op ); - - int (*pfnCreateInstancedBaseline) ( int classname, struct entity_state_s *baseline ); - void (*pfnCvar_DirectSet) ( struct cvar_s *var, char *value ); - - // Forces the client and server to be running with the same version of the specified file - // ( e.g., a player model ). - // Calling this has no effect in single player - void (*pfnForceUnmodified) ( FORCE_TYPE type, float *mins, float *maxs, const char *filename ); - - void (*pfnGetPlayerStats) ( const edict_t *pClient, int *ping, int *packet_loss ); - - void (*pfnAddServerCommand) ( char *cmd_name, void (*function) (void) ); - - // For voice communications, set which clients hear eachother. - // NOTE: these functions take player entity indices (starting at 1). - qboolean (*pfnVoice_GetClientListening)(int iReceiver, int iSender); - qboolean (*pfnVoice_SetClientListening)(int iReceiver, int iSender, qboolean bListen); - - const char *(*pfnGetPlayerAuthId) ( edict_t *e ); - - // PSV: Added for CZ training map -// const char *(*pfnKeyNameForBinding) ( const char* pBinding ); - - sequenceEntry_s* (*pfnSequenceGet) ( const char* fileName, const char* entryName ); - sentenceEntry_s* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked ); - - // LH: Give access to filesize via filesystem - int (*pfnGetFileSize) ( char *filename ); - - unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath); - // MDC: Added for CZ career-mode - int (*pfnIsCareerMatch) ( void ); - - // BGC: return the number of characters of the localized string referenced by using "label" - int (*pfnGetLocalizedStringLength) (const char *label); - - // BGC: added to facilitate persistent storage of tutor message decay values for - // different career game profiles. Also needs to persist regardless of mp.dll being - // destroyed and recreated. - void (*pfnRegisterTutorMessageShown) (int mid); - int (*pfnGetTimesTutorMessageShown) (int mid); - void (*pfnProcessTutorMessageDecayBuffer) (int *buffer, int bufferLength); - void (*pfnConstructTutorMessageDecayBuffer) (int *buffer, int bufferLength); - void (*pfnResetTutorMessageDecayData) ( void ); - void (*pfnQueryClientCvarValue) ( const edict_t *player, const char *cvarName ); - void (*pfnQueryClientCvarValue2) ( const edict_t *player, const char *cvarName, int requestID ); - int (*pfnEngCheckParm) ( const char *pchCmdLineToken, char **pchNextVal ); -} enginefuncs_t; - - -// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138 - -// Passed to pfnKeyValue -typedef struct KeyValueData_s -{ - char *szClassName; // in: entity classname - char *szKeyName; // in: name of key - char *szValue; // in: value of key - int32 fHandled; // out: DLL sets to true if key-value pair was understood -} KeyValueData; - - -typedef struct -{ - char mapName[ 32 ]; - char landmarkName[ 32 ]; - edict_t *pentLandmark; - vec3_t vecLandmarkOrigin; -} LEVELLIST; -#define MAX_LEVEL_CONNECTIONS 16 // These are encoded in the lower 16bits of ENTITYTABLE->flags - -typedef struct -{ - int id; // Ordinal ID of this entity (used for entity <--> pointer conversions) - edict_t *pent; // Pointer to the in-game entity - - int location; // Offset from the base data of this entity - int size; // Byte size of this entity's data - int flags; // This could be a short -- bit mask of transitions that this entity is in the PVS of - string_t classname; // entity class name - -} ENTITYTABLE; - -#define FENTTABLE_PLAYER 0x80000000 -#define FENTTABLE_REMOVED 0x40000000 -#define FENTTABLE_MOVEABLE 0x20000000 -#define FENTTABLE_GLOBAL 0x10000000 - -typedef struct saverestore_s SAVERESTOREDATA; - -#ifdef _WIN32 -typedef -#endif -struct saverestore_s -{ - char *pBaseData; // Start of all entity save data - char *pCurrentData; // Current buffer pointer for sequential access - int size; // Current data size - int bufferSize; // Total space for data - int tokenSize; // Size of the linear list of tokens - int tokenCount; // Number of elements in the pTokens table - char **pTokens; // Hash table of entity strings (sparse) - int currentIndex; // Holds a global entity table ID - int tableCount; // Number of elements in the entity table - int connectionCount;// Number of elements in the levelList[] - ENTITYTABLE *pTable; // Array of ENTITYTABLE elements (1 for each entity) - LEVELLIST levelList[ MAX_LEVEL_CONNECTIONS ]; // List of connections from this level - - // smooth transition - int fUseLandmark; - char szLandmarkName[20];// landmark we'll spawn near in next level - vec3_t vecLandmarkOffset;// for landmark transitions - float time; - char szCurrentMapName[32]; // To check global entities - -} -#ifdef _WIN32 -SAVERESTOREDATA -#endif -; - -typedef enum _fieldtypes -{ - FIELD_FLOAT = 0, // Any floating point value - FIELD_STRING, // A string ID (return from ALLOC_STRING) - FIELD_ENTITY, // An entity offset (EOFFSET) - FIELD_CLASSPTR, // CBaseEntity * - FIELD_EHANDLE, // Entity handle - FIELD_EVARS, // EVARS * - FIELD_EDICT, // edict_t *, or edict_t * (same thing) - FIELD_VECTOR, // Any vector - FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically) - FIELD_POINTER, // Arbitrary data pointer... to be removed, use an array of FIELD_CHARACTER - FIELD_INTEGER, // Any integer or enum - FIELD_FUNCTION, // A class function pointer (Think, Use, etc) - FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression - FIELD_SHORT, // 2 byte integer - FIELD_CHARACTER, // a byte - FIELD_TIME, // a floating point time (these are fixed up automatically too!) - FIELD_MODELNAME, // Engine string that is a model name (needs precache) - FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) - - FIELD_TYPECOUNT, // MUST BE LAST -} FIELDTYPE; - -#ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif - -#define _FIELD(type,name,fieldtype,count,flags) { fieldtype, #name, offsetof(type, name), count, flags } -#define DEFINE_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, 0) -#define DEFINE_ARRAY(type,name,fieldtype,count) _FIELD(type, name, fieldtype, count, 0) -#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(entvars_t, name, fieldtype, 1, 0 ) -#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(entvars_t, name, fieldtype, 1, FTYPEDESC_GLOBAL ) -#define DEFINE_GLOBAL_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, FTYPEDESC_GLOBAL ) - - -#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore - -typedef struct -{ - FIELDTYPE fieldType; - char *fieldName; - int fieldOffset; - short fieldSize; - short flags; -} TYPEDESCRIPTION; - -#ifndef ARRAYSIZE -#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) -#endif - -typedef struct -{ - // Initialize/shutdown the game (one-time call after loading of game .dll ) - void (*pfnGameInit) ( void ); - int (*pfnSpawn) ( edict_t *pent ); - void (*pfnThink) ( edict_t *pent ); - void (*pfnUse) ( edict_t *pentUsed, edict_t *pentOther ); - void (*pfnTouch) ( edict_t *pentTouched, edict_t *pentOther ); - void (*pfnBlocked) ( edict_t *pentBlocked, edict_t *pentOther ); - void (*pfnKeyValue) ( edict_t *pentKeyvalue, KeyValueData *pkvd ); - void (*pfnSave) ( edict_t *pent, SAVERESTOREDATA *pSaveData ); - int (*pfnRestore) ( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity ); - void (*pfnSetAbsBox) ( edict_t *pent ); - - void (*pfnSaveWriteFields) ( SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int ); - void (*pfnSaveReadFields) ( SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int ); - - void (*pfnSaveGlobalState) ( SAVERESTOREDATA * ); - void (*pfnRestoreGlobalState) ( SAVERESTOREDATA * ); - void (*pfnResetGlobalState) ( void ); - - qboolean (*pfnClientConnect) ( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ); - - void (*pfnClientDisconnect) ( edict_t *pEntity ); - void (*pfnClientKill) ( edict_t *pEntity ); - void (*pfnClientPutInServer) ( edict_t *pEntity ); - void (*pfnClientCommand) ( edict_t *pEntity ); - void (*pfnClientUserInfoChanged)( edict_t *pEntity, char *infobuffer ); - - void (*pfnServerActivate) ( edict_t *pEdictList, int edictCount, int clientMax ); - void (*pfnServerDeactivate) ( void ); - - void (*pfnPlayerPreThink) ( edict_t *pEntity ); - void (*pfnPlayerPostThink) ( edict_t *pEntity ); - - void (*pfnStartFrame) ( void ); - void (*pfnParmsNewLevel) ( void ); - void (*pfnParmsChangeLevel) ( void ); - - // Returns string describing current .dll. E.g., TeamFotrress 2, Half-Life - const char *(*pfnGetGameDescription)( void ); - - // Notify dll about a player customization. - void (*pfnPlayerCustomization) ( edict_t *pEntity, customization_t *pCustom ); - - // Spectator funcs - void (*pfnSpectatorConnect) ( edict_t *pEntity ); - void (*pfnSpectatorDisconnect) ( edict_t *pEntity ); - void (*pfnSpectatorThink) ( edict_t *pEntity ); - - // Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. - void (*pfnSys_Error) ( const char *error_string ); - - void (*pfnPM_Move) ( struct playermove_s *ppmove, qboolean server ); - void (*pfnPM_Init) ( struct playermove_s *ppmove ); - char (*pfnPM_FindTextureType)( char *name ); - void (*pfnSetupVisibility)( struct edict_s *pViewEntity, struct edict_s *pClient, unsigned char **pvs, unsigned char **pas ); - void (*pfnUpdateClientData) ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd ); - int (*pfnAddToFullPack)( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet ); - void (*pfnCreateBaseline) ( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs ); - void (*pfnRegisterEncoders) ( void ); - int (*pfnGetWeaponData) ( struct edict_s *player, struct weapon_data_s *info ); - - void (*pfnCmdStart) ( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed ); - void (*pfnCmdEnd) ( const edict_t *player ); - - // 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 (*pfnConnectionlessPacket ) ( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size ); - - // Enumerates player hulls. Returns 0 if the hull number doesn't exist, 1 otherwise - int (*pfnGetHullBounds) ( int hullnumber, float *mins, float *maxs ); - - // Create baselines for certain "unplaced" items. - void (*pfnCreateInstancedBaselines) ( void ); - - // One of the pfnForceUnmodified files failed the consistency check for the specified player - // Return 0 to allow the client to continue, 1 to force immediate disconnection ( with an optional disconnect message of up to 256 characters ) - int (*pfnInconsistentFile)( const struct edict_s *player, const char *filename, char *disconnect_message ); - - // The game .dll should return 1 if lag compensation should be allowed ( could also just set - // the sv_unlag cvar. - // Most games right now should return 0, until client-side weapon prediction code is written - // and tested for them. - int (*pfnAllowLagCompensation)( void ); -} DLL_FUNCTIONS; - -extern DLL_FUNCTIONS gEntityInterface; - -// Current version. -#define NEW_DLL_FUNCTIONS_VERSION 1 - -typedef struct -{ - // Called right before the object's memory is freed. - // Calls its destructor. - void (*pfnOnFreeEntPrivateData)(edict_t *pEnt); - void (*pfnGameShutdown)(void); - int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther ); - void (*pfnCvarValue)( const edict_t *pEnt, const char *value ); - void (*pfnCvarValue2)( const edict_t *pEnt, int requestID, const char *cvarName, const char *value ); -} NEW_DLL_FUNCTIONS; -typedef int (*NEW_DLL_FUNCTIONS_FN)( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); - -// Pointers will be null if the game DLL doesn't support this API. -extern NEW_DLL_FUNCTIONS gNewDLLFunctions; - -typedef int (*APIFUNCTION)( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); -typedef int (*APIFUNCTION2)( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); - -#endif /* EIFACE_H */ +/*** +* +* 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. +* +****/ +#ifndef EIFACE_H +#define EIFACE_H + +#include "archtypes.h" // DAL + +#ifdef HLDEMO_BUILD +#define INTERFACE_VERSION 001 +#else // !HLDEMO_BUILD, i.e., regular version of HL +#define INTERFACE_VERSION 140 +#endif // !HLDEMO_BUILD + +#include +#include "custom.h" +#include "cvardef.h" +#include "Sequence.h" +// +// Defines entity interface between engine and DLLs. +// This header file included by engine files and DLL files. +// +// Before including this header, DLLs must: +// include progdefs.h +// This is conveniently done for them in extdll.h +// + +#ifdef _WIN32 +#define DLLEXPORT __stdcall +#else +#define DLLEXPORT /* */ +#endif + +typedef enum + { + at_notice, + at_console, // same as at_notice, but forces a ConPrintf, not a message box + at_aiconsole, // same as at_console, but only shown if developer level is 2! + at_warning, + at_error, + at_logged // Server print to console ( only in multiplayer games ). + } ALERT_TYPE; + +// 4-22-98 JOHN: added for use in pfnClientPrintf +typedef enum + { + print_console, + print_center, + print_chat, + } PRINT_TYPE; + +// For integrity checking of content on clients +typedef enum +{ + force_exactfile, // File on client must exactly match server's file + force_model_samebounds, // For model files only, the geometry must fit in the same bbox + force_model_specifybounds, // For model files only, the geometry must fit in the specified bbox + force_model_specifybounds_if_avail, // For Steam model files only, the geometry must fit in the specified bbox (if the file is available) +} FORCE_TYPE; + +// Returned by TraceLine +typedef struct + { + int fAllSolid; // if true, plane is not valid + int fStartSolid; // if true, the initial point was in a solid area + int fInOpen; + int fInWater; + float flFraction; // time completed, 1.0 = didn't hit anything + vec3_t vecEndPos; // final position + float flPlaneDist; + vec3_t vecPlaneNormal; // surface normal at impact + edict_t *pHit; // entity the surface is on + int iHitgroup; // 0 == generic, non zero is specific body part + } TraceResult; + +// CD audio status +typedef struct +{ + int fPlaying;// is sound playing right now? + int fWasPlaying;// if not, CD is paused if WasPlaying is true. + int fInitialized; + int fEnabled; + int fPlayLooping; + float cdvolume; + //BYTE remap[100]; + int fCDRom; + int fPlayTrack; +} CDStatus; + +#include "../common/crc.h" + + +// Engine hands this to DLLs for functionality callbacks +typedef struct enginefuncs_s +{ + int (*pfnPrecacheModel) (char* s); + int (*pfnPrecacheSound) (char* s); + void (*pfnSetModel) (edict_t *e, const char *m); + int (*pfnModelIndex) (const char *m); + int (*pfnModelFrames) (int modelIndex); + void (*pfnSetSize) (edict_t *e, const float *rgflMin, const float *rgflMax); + void (*pfnChangeLevel) (char* s1, char* s2); + void (*pfnGetSpawnParms) (edict_t *ent); + void (*pfnSaveSpawnParms) (edict_t *ent); + float (*pfnVecToYaw) (const float *rgflVector); + void (*pfnVecToAngles) (const float *rgflVectorIn, float *rgflVectorOut); + void (*pfnMoveToOrigin) (edict_t *ent, const float *pflGoal, float dist, int iMoveType); + void (*pfnChangeYaw) (edict_t* ent); + void (*pfnChangePitch) (edict_t* ent); + edict_t* (*pfnFindEntityByString) (edict_t *pEdictStartSearchAfter, const char *pszField, const char *pszValue); + int (*pfnGetEntityIllum) (edict_t* pEnt); + edict_t* (*pfnFindEntityInSphere) (edict_t *pEdictStartSearchAfter, const float *org, float rad); + edict_t* (*pfnFindClientInPVS) (edict_t *pEdict); + edict_t* (*pfnEntitiesInPVS) (edict_t *pplayer); + void (*pfnMakeVectors) (const float *rgflVector); + void (*pfnAngleVectors) (const float *rgflVector, float *forward, float *right, float *up); + edict_t* (*pfnCreateEntity) (void); + void (*pfnRemoveEntity) (edict_t* e); + edict_t* (*pfnCreateNamedEntity) (int className); + void (*pfnMakeStatic) (edict_t *ent); + int (*pfnEntIsOnFloor) (edict_t *e); + int (*pfnDropToFloor) (edict_t* e); + int (*pfnWalkMove) (edict_t *ent, float yaw, float dist, int iMode); + void (*pfnSetOrigin) (edict_t *e, const float *rgflOrigin); + void (*pfnEmitSound) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch); + void (*pfnEmitAmbientSound) (edict_t *entity, float *pos, const char *samp, float vol, float attenuation, int fFlags, int pitch); + void (*pfnTraceLine) (const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr); + void (*pfnTraceToss) (edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr); + int (*pfnTraceMonsterHull) (edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr); + void (*pfnTraceHull) (const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr); + void (*pfnTraceModel) (const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr); + const char *(*pfnTraceTexture) (edict_t *pTextureEntity, const float *v1, const float *v2 ); + void (*pfnTraceSphere) (const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr); + void (*pfnGetAimVector) (edict_t* ent, float speed, float *rgflReturn); + void (*pfnServerCommand) (char* str); + void (*pfnServerExecute) (void); + void (*pfnClientCommand) (edict_t* pEdict, char* szFmt, ...); + void (*pfnParticleEffect) (const float *org, const float *dir, float color, float count); + void (*pfnLightStyle) (int style, char* val); + int (*pfnDecalIndex) (const char *name); + int (*pfnPointContents) (const float *rgflVector); + void (*pfnMessageBegin) (int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); + void (*pfnMessageEnd) (void); + void (*pfnWriteByte) (int iValue); + void (*pfnWriteChar) (int iValue); + void (*pfnWriteShort) (int iValue); + void (*pfnWriteLong) (int iValue); + void (*pfnWriteAngle) (float flValue); + void (*pfnWriteCoord) (float flValue); + void (*pfnWriteString) (const char *sz); + void (*pfnWriteEntity) (int iValue); + void (*pfnCVarRegister) (cvar_t *pCvar); + float (*pfnCVarGetFloat) (const char *szVarName); + const char* (*pfnCVarGetString) (const char *szVarName); + void (*pfnCVarSetFloat) (const char *szVarName, float flValue); + void (*pfnCVarSetString) (const char *szVarName, const char *szValue); + void (*pfnAlertMessage) (ALERT_TYPE atype, char *szFmt, ...); + void (*pfnEngineFprintf) (void *pfile, char *szFmt, ...); + void* (*pfnPvAllocEntPrivateData) (edict_t *pEdict, int32 cb); + void* (*pfnPvEntPrivateData) (edict_t *pEdict); + void (*pfnFreeEntPrivateData) (edict_t *pEdict); + const char* (*pfnSzFromIndex) (int iString); + int (*pfnAllocString) (const char *szValue); + struct entvars_s* (*pfnGetVarsOfEnt) (edict_t *pEdict); + edict_t* (*pfnPEntityOfEntOffset) (int iEntOffset); + int (*pfnEntOffsetOfPEntity) (const edict_t *pEdict); + int (*pfnIndexOfEdict) (const edict_t *pEdict); + edict_t* (*pfnPEntityOfEntIndex) (int iEntIndex); + edict_t* (*pfnFindEntityByVars) (struct entvars_s* pvars); + void* (*pfnGetModelPtr) (edict_t* pEdict); + int (*pfnRegUserMsg) (const char *pszName, int iSize); + void (*pfnAnimationAutomove) (const edict_t* pEdict, float flTime); + void (*pfnGetBonePosition) (const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles ); + uint32 (*pfnFunctionFromName) ( const char *pName ); + const char *(*pfnNameForFunction) ( uint32 function ); + void (*pfnClientPrintf) ( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg ); // JOHN: engine callbacks so game DLL can print messages to individual clients + void (*pfnServerPrint) ( const char *szMsg ); + const char *(*pfnCmd_Args) ( void ); // these 3 added + const char *(*pfnCmd_Argv) ( int argc ); // so game DLL can easily + int (*pfnCmd_Argc) ( void ); // access client 'cmd' strings + void (*pfnGetAttachment) (const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles ); + void (*pfnCRC32_Init) (CRC32_t *pulCRC); + void (*pfnCRC32_ProcessBuffer) (CRC32_t *pulCRC, void *p, int len); + void (*pfnCRC32_ProcessByte) (CRC32_t *pulCRC, unsigned char ch); + CRC32_t (*pfnCRC32_Final) (CRC32_t pulCRC); + int32 (*pfnRandomLong) (int32 lLow, int32 lHigh); + float (*pfnRandomFloat) (float flLow, float flHigh); + void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent ); + float (*pfnTime) ( void ); + void (*pfnCrosshairAngle) (const edict_t *pClient, float pitch, float yaw); + byte * (*pfnLoadFileForMe) (char *filename, int *pLength); + void (*pfnFreeFile) (void *buffer); + void (*pfnEndSection) (const char *pszSectionName); // trigger_endsection + int (*pfnCompareFileTime) (char *filename1, char *filename2, int *iCompare); + void (*pfnGetGameDir) (char *szGetGameDir); + void (*pfnCvar_RegisterVariable) (cvar_t *variable); + void (*pfnFadeClientVolume) (const edict_t *pEdict, int fadePercent, int fadeOutSeconds, int holdTime, int fadeInSeconds); + void (*pfnSetClientMaxspeed) (const edict_t *pEdict, float fNewMaxspeed); + edict_t * (*pfnCreateFakeClient) (const char *netname); // returns NULL if fake client can't be created + void (*pfnRunPlayerMove) (edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec ); + int (*pfnNumberOfEntities) (void); + char* (*pfnGetInfoKeyBuffer) (edict_t *e); // passing in NULL gets the serverinfo + char* (*pfnInfoKeyValue) (char *infobuffer, char *key); + void (*pfnSetKeyValue) (char *infobuffer, char *key, char *value); + void (*pfnSetClientKeyValue) (int clientIndex, char *infobuffer, char *key, char *value); + int (*pfnIsMapValid) (char *filename); + void (*pfnStaticDecal) ( const float *origin, int decalIndex, int entityIndex, int modelIndex ); + int (*pfnPrecacheGeneric) (char* s); + int (*pfnGetPlayerUserId) (edict_t *e ); // returns the server assigned userid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients + void (*pfnBuildSoundMsg) (edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); + int (*pfnIsDedicatedServer) (void);// is this a dedicated server? + cvar_t *(*pfnCVarGetPointer) (const char *szVarName); + unsigned int (*pfnGetPlayerWONId) (edict_t *e); // returns the server assigned WONid for this player. useful for logging frags, etc. returns -1 if the edict couldn't be found in the list of clients + + // YWB 8/1/99 TFF Physics additions + void (*pfnInfo_RemoveKey) ( char *s, const char *key ); + const char *(*pfnGetPhysicsKeyValue) ( const edict_t *pClient, const char *key ); + void (*pfnSetPhysicsKeyValue) ( const edict_t *pClient, const char *key, const char *value ); + const char *(*pfnGetPhysicsInfoString) ( const edict_t *pClient ); + unsigned short (*pfnPrecacheEvent) ( int type, const char*psz ); + void (*pfnPlaybackEvent) ( 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 ); + + unsigned char *(*pfnSetFatPVS) ( float *org ); + unsigned char *(*pfnSetFatPAS) ( float *org ); + + int (*pfnCheckVisibility ) ( const edict_t *entity, unsigned char *pset ); + + void (*pfnDeltaSetField) ( struct delta_s *pFields, const char *fieldname ); + void (*pfnDeltaUnsetField) ( struct delta_s *pFields, const char *fieldname ); + void (*pfnDeltaAddEncoder) ( char *name, void (*conditionalencode)( struct delta_s *pFields, const unsigned char *from, const unsigned char *to ) ); + int (*pfnGetCurrentPlayer) ( void ); + int (*pfnCanSkipPlayer) ( const edict_t *player ); + int (*pfnDeltaFindField) ( struct delta_s *pFields, const char *fieldname ); + void (*pfnDeltaSetFieldByIndex) ( struct delta_s *pFields, int fieldNumber ); + void (*pfnDeltaUnsetFieldByIndex)( struct delta_s *pFields, int fieldNumber ); + + void (*pfnSetGroupMask) ( int mask, int op ); + + int (*pfnCreateInstancedBaseline) ( int classname, struct entity_state_s *baseline ); + void (*pfnCvar_DirectSet) ( struct cvar_s *var, char *value ); + + // Forces the client and server to be running with the same version of the specified file + // ( e.g., a player model ). + // Calling this has no effect in single player + void (*pfnForceUnmodified) ( FORCE_TYPE type, float *mins, float *maxs, const char *filename ); + + void (*pfnGetPlayerStats) ( const edict_t *pClient, int *ping, int *packet_loss ); + + void (*pfnAddServerCommand) ( char *cmd_name, void (*function) (void) ); + + // For voice communications, set which clients hear eachother. + // NOTE: these functions take player entity indices (starting at 1). + qboolean (*pfnVoice_GetClientListening)(int iReceiver, int iSender); + qboolean (*pfnVoice_SetClientListening)(int iReceiver, int iSender, qboolean bListen); + + const char *(*pfnGetPlayerAuthId) ( edict_t *e ); + + // PSV: Added for CZ training map +// const char *(*pfnKeyNameForBinding) ( const char* pBinding ); + + sequenceEntry_s* (*pfnSequenceGet) ( const char* fileName, const char* entryName ); + sentenceEntry_s* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked ); + + // LH: Give access to filesize via filesystem + int (*pfnGetFileSize) ( char *filename ); + + unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath); + // MDC: Added for CZ career-mode + int (*pfnIsCareerMatch) ( void ); + + // BGC: return the number of characters of the localized string referenced by using "label" + int (*pfnGetLocalizedStringLength) (const char *label); + + // BGC: added to facilitate persistent storage of tutor message decay values for + // different career game profiles. Also needs to persist regardless of mp.dll being + // destroyed and recreated. + void (*pfnRegisterTutorMessageShown) (int mid); + int (*pfnGetTimesTutorMessageShown) (int mid); + void (*pfnProcessTutorMessageDecayBuffer) (int *buffer, int bufferLength); + void (*pfnConstructTutorMessageDecayBuffer) (int *buffer, int bufferLength); + void (*pfnResetTutorMessageDecayData) ( void ); + void (*pfnQueryClientCvarValue) ( const edict_t *player, const char *cvarName ); + void (*pfnQueryClientCvarValue2) ( const edict_t *player, const char *cvarName, int requestID ); + int (*pfnEngCheckParm) ( const char *pchCmdLineToken, char **pchNextVal ); +} enginefuncs_t; + + +// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138 + +// Passed to pfnKeyValue +typedef struct KeyValueData_s +{ + char *szClassName; // in: entity classname + char *szKeyName; // in: name of key + char *szValue; // in: value of key + int32 fHandled; // out: DLL sets to true if key-value pair was understood +} KeyValueData; + + +typedef struct +{ + char mapName[ 32 ]; + char landmarkName[ 32 ]; + edict_t *pentLandmark; + vec3_t vecLandmarkOrigin; +} LEVELLIST; +#define MAX_LEVEL_CONNECTIONS 16 // These are encoded in the lower 16bits of ENTITYTABLE->flags + +typedef struct +{ + int id; // Ordinal ID of this entity (used for entity <--> pointer conversions) + edict_t *pent; // Pointer to the in-game entity + + int location; // Offset from the base data of this entity + int size; // Byte size of this entity's data + int flags; // This could be a short -- bit mask of transitions that this entity is in the PVS of + string_t classname; // entity class name + +} ENTITYTABLE; + +#define FENTTABLE_PLAYER 0x80000000 +#define FENTTABLE_REMOVED 0x40000000 +#define FENTTABLE_MOVEABLE 0x20000000 +#define FENTTABLE_GLOBAL 0x10000000 + +typedef struct saverestore_s SAVERESTOREDATA; + +#ifdef _WIN32 +typedef +#endif +struct saverestore_s +{ + char *pBaseData; // Start of all entity save data + char *pCurrentData; // Current buffer pointer for sequential access + int size; // Current data size + int bufferSize; // Total space for data + int tokenSize; // Size of the linear list of tokens + int tokenCount; // Number of elements in the pTokens table + char **pTokens; // Hash table of entity strings (sparse) + int currentIndex; // Holds a global entity table ID + int tableCount; // Number of elements in the entity table + int connectionCount;// Number of elements in the levelList[] + ENTITYTABLE *pTable; // Array of ENTITYTABLE elements (1 for each entity) + LEVELLIST levelList[ MAX_LEVEL_CONNECTIONS ]; // List of connections from this level + + // smooth transition + int fUseLandmark; + char szLandmarkName[20];// landmark we'll spawn near in next level + vec3_t vecLandmarkOffset;// for landmark transitions + float time; + char szCurrentMapName[32]; // To check global entities + +} +#ifdef _WIN32 +SAVERESTOREDATA +#endif +; + +typedef enum _fieldtypes +{ + FIELD_FLOAT = 0, // Any floating point value + FIELD_STRING, // A string ID (return from ALLOC_STRING) + FIELD_ENTITY, // An entity offset (EOFFSET) + FIELD_CLASSPTR, // CBaseEntity * + FIELD_EHANDLE, // Entity handle + FIELD_EVARS, // EVARS * + FIELD_EDICT, // edict_t *, or edict_t * (same thing) + FIELD_VECTOR, // Any vector + FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically) + FIELD_POINTER, // Arbitrary data pointer... to be removed, use an array of FIELD_CHARACTER + FIELD_INTEGER, // Any integer or enum + FIELD_FUNCTION, // A class function pointer (Think, Use, etc) + FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression + FIELD_SHORT, // 2 byte integer + FIELD_CHARACTER, // a byte + FIELD_TIME, // a floating point time (these are fixed up automatically too!) + FIELD_MODELNAME, // Engine string that is a model name (needs precache) + FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) + + FIELD_TYPECOUNT, // MUST BE LAST +} FIELDTYPE; + +#ifndef offsetof +#define offsetof(s,m) (size_t)&(((s *)0)->m) +#endif + +#define _FIELD(type,name,fieldtype,count,flags) { fieldtype, #name, offsetof(type, name), count, flags } +#define DEFINE_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, 0) +#define DEFINE_ARRAY(type,name,fieldtype,count) _FIELD(type, name, fieldtype, count, 0) +#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(entvars_t, name, fieldtype, 1, 0 ) +#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(entvars_t, name, fieldtype, 1, FTYPEDESC_GLOBAL ) +#define DEFINE_GLOBAL_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, FTYPEDESC_GLOBAL ) + + +#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore + +typedef struct +{ + FIELDTYPE fieldType; + char *fieldName; + int fieldOffset; + short fieldSize; + short flags; +} TYPEDESCRIPTION; + +#ifndef ARRAYSIZE +#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) +#endif + +typedef struct +{ + // Initialize/shutdown the game (one-time call after loading of game .dll ) + void (*pfnGameInit) ( void ); + int (*pfnSpawn) ( edict_t *pent ); + void (*pfnThink) ( edict_t *pent ); + void (*pfnUse) ( edict_t *pentUsed, edict_t *pentOther ); + void (*pfnTouch) ( edict_t *pentTouched, edict_t *pentOther ); + void (*pfnBlocked) ( edict_t *pentBlocked, edict_t *pentOther ); + void (*pfnKeyValue) ( edict_t *pentKeyvalue, KeyValueData *pkvd ); + void (*pfnSave) ( edict_t *pent, SAVERESTOREDATA *pSaveData ); + int (*pfnRestore) ( edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity ); + void (*pfnSetAbsBox) ( edict_t *pent ); + + void (*pfnSaveWriteFields) ( SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int ); + void (*pfnSaveReadFields) ( SAVERESTOREDATA *, const char *, void *, TYPEDESCRIPTION *, int ); + + void (*pfnSaveGlobalState) ( SAVERESTOREDATA * ); + void (*pfnRestoreGlobalState) ( SAVERESTOREDATA * ); + void (*pfnResetGlobalState) ( void ); + + qboolean (*pfnClientConnect) ( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[ 128 ] ); + + void (*pfnClientDisconnect) ( edict_t *pEntity ); + void (*pfnClientKill) ( edict_t *pEntity ); + void (*pfnClientPutInServer) ( edict_t *pEntity ); + void (*pfnClientCommand) ( edict_t *pEntity ); + void (*pfnClientUserInfoChanged)( edict_t *pEntity, char *infobuffer ); + + void (*pfnServerActivate) ( edict_t *pEdictList, int edictCount, int clientMax ); + void (*pfnServerDeactivate) ( void ); + + void (*pfnPlayerPreThink) ( edict_t *pEntity ); + void (*pfnPlayerPostThink) ( edict_t *pEntity ); + + void (*pfnStartFrame) ( void ); + void (*pfnParmsNewLevel) ( void ); + void (*pfnParmsChangeLevel) ( void ); + + // Returns string describing current .dll. E.g., TeamFotrress 2, Half-Life + const char *(*pfnGetGameDescription)( void ); + + // Notify dll about a player customization. + void (*pfnPlayerCustomization) ( edict_t *pEntity, customization_t *pCustom ); + + // Spectator funcs + void (*pfnSpectatorConnect) ( edict_t *pEntity ); + void (*pfnSpectatorDisconnect) ( edict_t *pEntity ); + void (*pfnSpectatorThink) ( edict_t *pEntity ); + + // Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. + void (*pfnSys_Error) ( const char *error_string ); + + void (*pfnPM_Move) ( struct playermove_s *ppmove, qboolean server ); + void (*pfnPM_Init) ( struct playermove_s *ppmove ); + char (*pfnPM_FindTextureType)( char *name ); + void (*pfnSetupVisibility)( struct edict_s *pViewEntity, struct edict_s *pClient, unsigned char **pvs, unsigned char **pas ); + void (*pfnUpdateClientData) ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd ); + int (*pfnAddToFullPack)( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet ); + void (*pfnCreateBaseline) ( int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs ); + void (*pfnRegisterEncoders) ( void ); + int (*pfnGetWeaponData) ( struct edict_s *player, struct weapon_data_s *info ); + + void (*pfnCmdStart) ( const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed ); + void (*pfnCmdEnd) ( const edict_t *player ); + + // 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 (*pfnConnectionlessPacket ) ( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size ); + + // Enumerates player hulls. Returns 0 if the hull number doesn't exist, 1 otherwise + int (*pfnGetHullBounds) ( int hullnumber, float *mins, float *maxs ); + + // Create baselines for certain "unplaced" items. + void (*pfnCreateInstancedBaselines) ( void ); + + // One of the pfnForceUnmodified files failed the consistency check for the specified player + // Return 0 to allow the client to continue, 1 to force immediate disconnection ( with an optional disconnect message of up to 256 characters ) + int (*pfnInconsistentFile)( const struct edict_s *player, const char *filename, char *disconnect_message ); + + // The game .dll should return 1 if lag compensation should be allowed ( could also just set + // the sv_unlag cvar. + // Most games right now should return 0, until client-side weapon prediction code is written + // and tested for them. + int (*pfnAllowLagCompensation)( void ); +} DLL_FUNCTIONS; + +extern DLL_FUNCTIONS gEntityInterface; + +// Current version. +#define NEW_DLL_FUNCTIONS_VERSION 1 + +typedef struct +{ + // Called right before the object's memory is freed. + // Calls its destructor. + void (*pfnOnFreeEntPrivateData)(edict_t *pEnt); + void (*pfnGameShutdown)(void); + int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther ); + void (*pfnCvarValue)( const edict_t *pEnt, const char *value ); + void (*pfnCvarValue2)( const edict_t *pEnt, int requestID, const char *cvarName, const char *value ); +} NEW_DLL_FUNCTIONS; +typedef int (*NEW_DLL_FUNCTIONS_FN)( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); + +// Pointers will be null if the game DLL doesn't support this API. +extern NEW_DLL_FUNCTIONS gNewDLLFunctions; + +typedef int (*APIFUNCTION)( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); +typedef int (*APIFUNCTION2)( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); + +#endif /* EIFACE_H */ diff --git a/engine/keydefs.h b/engine/keydefs.h index 4adeeab..0d1c02d 100644 --- a/engine/keydefs.h +++ b/engine/keydefs.h @@ -1,131 +1,131 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// keydefs.h -#ifndef KEYDEFS_H -#define KEYDEFS_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -// -// these are the key numbers that should be passed to Key_Event -// -#define K_TAB 9 -#define K_ENTER 13 -#define K_ESCAPE 27 -#define K_SPACE 32 - -// normal keys should be passed as lowercased ascii - -#define K_BACKSPACE 127 -#define K_UPARROW 128 -#define K_DOWNARROW 129 -#define K_LEFTARROW 130 -#define K_RIGHTARROW 131 - -#define K_ALT 132 -#define K_CTRL 133 -#define K_SHIFT 134 -#define K_F1 135 -#define K_F2 136 -#define K_F3 137 -#define K_F4 138 -#define K_F5 139 -#define K_F6 140 -#define K_F7 141 -#define K_F8 142 -#define K_F9 143 -#define K_F10 144 -#define K_F11 145 -#define K_F12 146 -#define K_INS 147 -#define K_DEL 148 -#define K_PGDN 149 -#define K_PGUP 150 -#define K_HOME 151 -#define K_END 152 - -#define K_KP_HOME 160 -#define K_KP_UPARROW 161 -#define K_KP_PGUP 162 -#define K_KP_LEFTARROW 163 -#define K_KP_5 164 -#define K_KP_RIGHTARROW 165 -#define K_KP_END 166 -#define K_KP_DOWNARROW 167 -#define K_KP_PGDN 168 -#define K_KP_ENTER 169 -#define K_KP_INS 170 -#define K_KP_DEL 171 -#define K_KP_SLASH 172 -#define K_KP_MINUS 173 -#define K_KP_PLUS 174 -#define K_CAPSLOCK 175 - - -// -// joystick buttons -// -#define K_JOY1 203 -#define K_JOY2 204 -#define K_JOY3 205 -#define K_JOY4 206 - -// -// aux keys are for multi-buttoned joysticks to generate so they can use -// the normal binding process -// -#define K_AUX1 207 -#define K_AUX2 208 -#define K_AUX3 209 -#define K_AUX4 210 -#define K_AUX5 211 -#define K_AUX6 212 -#define K_AUX7 213 -#define K_AUX8 214 -#define K_AUX9 215 -#define K_AUX10 216 -#define K_AUX11 217 -#define K_AUX12 218 -#define K_AUX13 219 -#define K_AUX14 220 -#define K_AUX15 221 -#define K_AUX16 222 -#define K_AUX17 223 -#define K_AUX18 224 -#define K_AUX19 225 -#define K_AUX20 226 -#define K_AUX21 227 -#define K_AUX22 228 -#define K_AUX23 229 -#define K_AUX24 230 -#define K_AUX25 231 -#define K_AUX26 232 -#define K_AUX27 233 -#define K_AUX28 234 -#define K_AUX29 235 -#define K_AUX30 236 -#define K_AUX31 237 -#define K_AUX32 238 -#define K_MWHEELDOWN 239 -#define K_MWHEELUP 240 - -#define K_PAUSE 255 - -// -// mouse buttons generate virtual keys -// -#define K_MOUSE1 241 -#define K_MOUSE2 242 -#define K_MOUSE3 243 -#define K_MOUSE4 244 -#define K_MOUSE5 245 - -#endif // KEYDEFS_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// keydefs.h +#ifndef KEYDEFS_H +#define KEYDEFS_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +// +// these are the key numbers that should be passed to Key_Event +// +#define K_TAB 9 +#define K_ENTER 13 +#define K_ESCAPE 27 +#define K_SPACE 32 + +// normal keys should be passed as lowercased ascii + +#define K_BACKSPACE 127 +#define K_UPARROW 128 +#define K_DOWNARROW 129 +#define K_LEFTARROW 130 +#define K_RIGHTARROW 131 + +#define K_ALT 132 +#define K_CTRL 133 +#define K_SHIFT 134 +#define K_F1 135 +#define K_F2 136 +#define K_F3 137 +#define K_F4 138 +#define K_F5 139 +#define K_F6 140 +#define K_F7 141 +#define K_F8 142 +#define K_F9 143 +#define K_F10 144 +#define K_F11 145 +#define K_F12 146 +#define K_INS 147 +#define K_DEL 148 +#define K_PGDN 149 +#define K_PGUP 150 +#define K_HOME 151 +#define K_END 152 + +#define K_KP_HOME 160 +#define K_KP_UPARROW 161 +#define K_KP_PGUP 162 +#define K_KP_LEFTARROW 163 +#define K_KP_5 164 +#define K_KP_RIGHTARROW 165 +#define K_KP_END 166 +#define K_KP_DOWNARROW 167 +#define K_KP_PGDN 168 +#define K_KP_ENTER 169 +#define K_KP_INS 170 +#define K_KP_DEL 171 +#define K_KP_SLASH 172 +#define K_KP_MINUS 173 +#define K_KP_PLUS 174 +#define K_CAPSLOCK 175 + + +// +// joystick buttons +// +#define K_JOY1 203 +#define K_JOY2 204 +#define K_JOY3 205 +#define K_JOY4 206 + +// +// aux keys are for multi-buttoned joysticks to generate so they can use +// the normal binding process +// +#define K_AUX1 207 +#define K_AUX2 208 +#define K_AUX3 209 +#define K_AUX4 210 +#define K_AUX5 211 +#define K_AUX6 212 +#define K_AUX7 213 +#define K_AUX8 214 +#define K_AUX9 215 +#define K_AUX10 216 +#define K_AUX11 217 +#define K_AUX12 218 +#define K_AUX13 219 +#define K_AUX14 220 +#define K_AUX15 221 +#define K_AUX16 222 +#define K_AUX17 223 +#define K_AUX18 224 +#define K_AUX19 225 +#define K_AUX20 226 +#define K_AUX21 227 +#define K_AUX22 228 +#define K_AUX23 229 +#define K_AUX24 230 +#define K_AUX25 231 +#define K_AUX26 232 +#define K_AUX27 233 +#define K_AUX28 234 +#define K_AUX29 235 +#define K_AUX30 236 +#define K_AUX31 237 +#define K_AUX32 238 +#define K_MWHEELDOWN 239 +#define K_MWHEELUP 240 + +#define K_PAUSE 255 + +// +// mouse buttons generate virtual keys +// +#define K_MOUSE1 241 +#define K_MOUSE2 242 +#define K_MOUSE3 243 +#define K_MOUSE4 244 +#define K_MOUSE5 245 + +#endif // KEYDEFS_H diff --git a/engine/progdefs.h b/engine/progdefs.h index 083b620..c7b9855 100644 --- a/engine/progdefs.h +++ b/engine/progdefs.h @@ -1,226 +1,226 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef PROGDEFS_H -#define PROGDEFS_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -typedef struct -{ - float time; - float frametime; - float force_retouch; - string_t mapname; - string_t startspot; - float deathmatch; - float coop; - float teamplay; - float serverflags; - float found_secrets; - vec3_t v_forward; - vec3_t v_up; - vec3_t v_right; - float trace_allsolid; - float trace_startsolid; - float trace_fraction; - vec3_t trace_endpos; - vec3_t trace_plane_normal; - float trace_plane_dist; - edict_t *trace_ent; - float trace_inopen; - float trace_inwater; - int trace_hitgroup; - int trace_flags; - int msg_entity; - int cdAudioTrack; - int maxClients; - int maxEntities; - const char *pStringBase; - - void *pSaveData; - vec3_t vecLandmarkOffset; -} globalvars_t; - - -typedef struct entvars_s -{ - string_t classname; - string_t globalname; - - vec3_t origin; - vec3_t oldorigin; - vec3_t velocity; - vec3_t basevelocity; - vec3_t clbasevelocity; // Base velocity that was passed in to server physics so - // client can predict conveyors correctly. Server zeroes it, so we need to store here, too. - vec3_t movedir; - - vec3_t angles; // Model angles - vec3_t avelocity; // angle velocity (degrees per second) - vec3_t punchangle; // auto-decaying view angle adjustment - vec3_t v_angle; // Viewing angle (player only) - - // For parametric entities - vec3_t endpos; - vec3_t startpos; - float impacttime; - float starttime; - - int fixangle; // 0:nothing, 1:force view angles, 2:add avelocity - float idealpitch; - float pitch_speed; - float ideal_yaw; - float yaw_speed; - - int modelindex; - string_t model; - - int viewmodel; // player's viewmodel - int weaponmodel; // what other players see - - vec3_t absmin; // BB max translated to world coord - vec3_t absmax; // BB max translated to world coord - vec3_t mins; // local BB min - vec3_t maxs; // local BB max - vec3_t size; // maxs - mins - - float ltime; - float nextthink; - - int movetype; - int solid; - - int skin; - int body; // sub-model selection for studiomodels - int effects; - - float gravity; // % of "normal" gravity - float friction; // inverse elasticity of MOVETYPE_BOUNCE - - int light_level; - - int sequence; // animation sequence - int gaitsequence; // movement animation sequence for player (0 for none) - float frame; // % playback position in animation sequences (0..255) - float animtime; // world time when frame was set - float framerate; // animation playback rate (-8x to 8x) - byte controller[4]; // bone controller setting (0..255) - byte blending[2]; // blending amount between sub-sequences (0..255) - - float scale; // sprite rendering scale (0..255) - - int rendermode; - float renderamt; - vec3_t rendercolor; - int renderfx; - - float health; - float frags; - int weapons; // bit mask for available weapons - float takedamage; - - int deadflag; - vec3_t view_ofs; // eye position - - int button; - int impulse; - - edict_t *chain; // Entity pointer when linked into a linked list - edict_t *dmg_inflictor; - edict_t *enemy; - edict_t *aiment; // entity pointer when MOVETYPE_FOLLOW - edict_t *owner; - edict_t *groundentity; - - int spawnflags; - int flags; - - int colormap; // lowbyte topcolor, highbyte bottomcolor - int team; - - float max_health; - float teleport_time; - float armortype; - float armorvalue; - int waterlevel; - int watertype; - - string_t target; - string_t targetname; - string_t netname; - string_t message; - - float dmg_take; - float dmg_save; - float dmg; - float dmgtime; - - string_t noise; - string_t noise1; - string_t noise2; - string_t noise3; - - float speed; - float air_finished; - float pain_finished; - float radsuit_finished; - - edict_t *pContainingEntity; - - int playerclass; - float maxspeed; - - float fov; - int weaponanim; - - int pushmsec; - - int bInDuck; - int flTimeStepSound; - int flSwimTime; - int flDuckTime; - int iStepLeft; - float flFallVelocity; - - int gamestate; - - int oldbuttons; - - int groupinfo; - - // 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; - edict_t *euser1; - edict_t *euser2; - edict_t *euser3; - edict_t *euser4; -} entvars_t; - - -#endif // PROGDEFS_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef PROGDEFS_H +#define PROGDEFS_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +typedef struct +{ + float time; + float frametime; + float force_retouch; + string_t mapname; + string_t startspot; + float deathmatch; + float coop; + float teamplay; + float serverflags; + float found_secrets; + vec3_t v_forward; + vec3_t v_up; + vec3_t v_right; + float trace_allsolid; + float trace_startsolid; + float trace_fraction; + vec3_t trace_endpos; + vec3_t trace_plane_normal; + float trace_plane_dist; + edict_t *trace_ent; + float trace_inopen; + float trace_inwater; + int trace_hitgroup; + int trace_flags; + int msg_entity; + int cdAudioTrack; + int maxClients; + int maxEntities; + const char *pStringBase; + + void *pSaveData; + vec3_t vecLandmarkOffset; +} globalvars_t; + + +typedef struct entvars_s +{ + string_t classname; + string_t globalname; + + vec3_t origin; + vec3_t oldorigin; + vec3_t velocity; + vec3_t basevelocity; + vec3_t clbasevelocity; // Base velocity that was passed in to server physics so + // client can predict conveyors correctly. Server zeroes it, so we need to store here, too. + vec3_t movedir; + + vec3_t angles; // Model angles + vec3_t avelocity; // angle velocity (degrees per second) + vec3_t punchangle; // auto-decaying view angle adjustment + vec3_t v_angle; // Viewing angle (player only) + + // For parametric entities + vec3_t endpos; + vec3_t startpos; + float impacttime; + float starttime; + + int fixangle; // 0:nothing, 1:force view angles, 2:add avelocity + float idealpitch; + float pitch_speed; + float ideal_yaw; + float yaw_speed; + + int modelindex; + string_t model; + + int viewmodel; // player's viewmodel + int weaponmodel; // what other players see + + vec3_t absmin; // BB max translated to world coord + vec3_t absmax; // BB max translated to world coord + vec3_t mins; // local BB min + vec3_t maxs; // local BB max + vec3_t size; // maxs - mins + + float ltime; + float nextthink; + + int movetype; + int solid; + + int skin; + int body; // sub-model selection for studiomodels + int effects; + + float gravity; // % of "normal" gravity + float friction; // inverse elasticity of MOVETYPE_BOUNCE + + int light_level; + + int sequence; // animation sequence + int gaitsequence; // movement animation sequence for player (0 for none) + float frame; // % playback position in animation sequences (0..255) + float animtime; // world time when frame was set + float framerate; // animation playback rate (-8x to 8x) + byte controller[4]; // bone controller setting (0..255) + byte blending[2]; // blending amount between sub-sequences (0..255) + + float scale; // sprite rendering scale (0..255) + + int rendermode; + float renderamt; + vec3_t rendercolor; + int renderfx; + + float health; + float frags; + int weapons; // bit mask for available weapons + float takedamage; + + int deadflag; + vec3_t view_ofs; // eye position + + int button; + int impulse; + + edict_t *chain; // Entity pointer when linked into a linked list + edict_t *dmg_inflictor; + edict_t *enemy; + edict_t *aiment; // entity pointer when MOVETYPE_FOLLOW + edict_t *owner; + edict_t *groundentity; + + int spawnflags; + int flags; + + int colormap; // lowbyte topcolor, highbyte bottomcolor + int team; + + float max_health; + float teleport_time; + float armortype; + float armorvalue; + int waterlevel; + int watertype; + + string_t target; + string_t targetname; + string_t netname; + string_t message; + + float dmg_take; + float dmg_save; + float dmg; + float dmgtime; + + string_t noise; + string_t noise1; + string_t noise2; + string_t noise3; + + float speed; + float air_finished; + float pain_finished; + float radsuit_finished; + + edict_t *pContainingEntity; + + int playerclass; + float maxspeed; + + float fov; + int weaponanim; + + int pushmsec; + + int bInDuck; + int flTimeStepSound; + int flSwimTime; + int flDuckTime; + int iStepLeft; + float flFallVelocity; + + int gamestate; + + int oldbuttons; + + int groupinfo; + + // 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; + edict_t *euser1; + edict_t *euser2; + edict_t *euser3; + edict_t *euser4; +} entvars_t; + + +#endif // PROGDEFS_H diff --git a/engine/progs.h b/engine/progs.h index 1d1f885..fe4796e 100644 --- a/engine/progs.h +++ b/engine/progs.h @@ -1,82 +1,82 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef PROGS_H -#define PROGS_H - -#include "progdefs.h" - -// 16 simultaneous events, max -#define MAX_EVENT_QUEUE 64 - -#define DEFAULT_EVENT_RESENDS 1 - -#include "event_flags.h" - -typedef struct event_info_s event_info_t; - -#include "event_args.h" - -struct event_info_s -{ - unsigned short index; // 0 implies not in use - - short packet_index; // Use data from state info for entity in delta_packet . -1 implies separate info based on event - // parameter signature - short entity_index; // The edict this event is associated with - - float fire_time; // if non-zero, the time when the event should be fired ( fixed up on the client ) - - event_args_t args; - -// CLIENT ONLY - int flags; // Reliable or not, etc. - -}; - -typedef struct event_state_s event_state_t; - -struct event_state_s -{ - struct event_info_s ei[ MAX_EVENT_QUEUE ]; -}; - -#if !defined( ENTITY_STATEH ) -#include "entity_state.h" -#endif - -#if !defined( EDICT_H ) -#include "edict.h" -#endif - -#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) -#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) - -//============================================================================ - -extern char *pr_strings; -extern globalvars_t gGlobalVariables; - -//============================================================================ - -edict_t *ED_Alloc (void); -void ED_Free (edict_t *ed); -void ED_LoadFromFile (char *data); - -edict_t *EDICT_NUM(int n); -int NUM_FOR_EDICT(const edict_t *e); - -#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e)) - -#endif // PROGS_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef PROGS_H +#define PROGS_H + +#include "progdefs.h" + +// 16 simultaneous events, max +#define MAX_EVENT_QUEUE 64 + +#define DEFAULT_EVENT_RESENDS 1 + +#include "event_flags.h" + +typedef struct event_info_s event_info_t; + +#include "event_args.h" + +struct event_info_s +{ + unsigned short index; // 0 implies not in use + + short packet_index; // Use data from state info for entity in delta_packet . -1 implies separate info based on event + // parameter signature + short entity_index; // The edict this event is associated with + + float fire_time; // if non-zero, the time when the event should be fired ( fixed up on the client ) + + event_args_t args; + +// CLIENT ONLY + int flags; // Reliable or not, etc. + +}; + +typedef struct event_state_s event_state_t; + +struct event_state_s +{ + struct event_info_s ei[ MAX_EVENT_QUEUE ]; +}; + +#if !defined( ENTITY_STATEH ) +#include "entity_state.h" +#endif + +#if !defined( EDICT_H ) +#include "edict.h" +#endif + +#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m))) +#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area) + +//============================================================================ + +extern char *pr_strings; +extern globalvars_t gGlobalVariables; + +//============================================================================ + +edict_t *ED_Alloc (void); +void ED_Free (edict_t *ed); +void ED_LoadFromFile (char *data); + +edict_t *EDICT_NUM(int n); +int NUM_FOR_EDICT(const edict_t *e); + +#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e)) + +#endif // PROGS_H diff --git a/engine/shake.h b/engine/shake.h index 8e405db..a18ddc2 100644 --- a/engine/shake.h +++ b/engine/shake.h @@ -1,55 +1,55 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef SHAKE_H -#define SHAKE_H - -// Screen / View effects - -// screen shake -extern int gmsgShake; - -// This structure is sent over the net to describe a screen shake event -typedef struct -{ - unsigned short amplitude; // FIXED 4.12 amount of shake - unsigned short duration; // FIXED 4.12 seconds duration - unsigned short frequency; // FIXED 8.8 noise frequency (low frequency is a jerk,high frequency is a rumble) -} ScreenShake; - -extern void V_ApplyShake( float *origin, float *angles, float factor ); -extern void V_CalcShake( void ); -extern int V_ScreenShake( const char *pszName, int iSize, void *pbuf ); -extern int V_ScreenFade( const char *pszName, int iSize, void *pbuf ); - - -// Fade in/out -extern int gmsgFade; - -#define FFADE_IN 0x0000 // Just here so we don't pass 0 into the function -#define FFADE_OUT 0x0001 // Fade out (not in) -#define FFADE_MODULATE 0x0002 // Modulate (don't blend) -#define FFADE_STAYOUT 0x0004 // ignores the duration, stays faded out until new ScreenFade message received - -// This structure is sent over the net to describe a screen fade event -typedef struct -{ - unsigned short duration; // FIXED 4.12 seconds duration - unsigned short holdTime; // FIXED 4.12 seconds duration until reset (fade & hold) - short fadeFlags; // flags - byte r, g, b, a; // fade to color ( max alpha ) -} ScreenFade; - -#endif // SHAKE_H - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef SHAKE_H +#define SHAKE_H + +// Screen / View effects + +// screen shake +extern int gmsgShake; + +// This structure is sent over the net to describe a screen shake event +typedef struct +{ + unsigned short amplitude; // FIXED 4.12 amount of shake + unsigned short duration; // FIXED 4.12 seconds duration + unsigned short frequency; // FIXED 8.8 noise frequency (low frequency is a jerk,high frequency is a rumble) +} ScreenShake; + +extern void V_ApplyShake( float *origin, float *angles, float factor ); +extern void V_CalcShake( void ); +extern int V_ScreenShake( const char *pszName, int iSize, void *pbuf ); +extern int V_ScreenFade( const char *pszName, int iSize, void *pbuf ); + + +// Fade in/out +extern int gmsgFade; + +#define FFADE_IN 0x0000 // Just here so we don't pass 0 into the function +#define FFADE_OUT 0x0001 // Fade out (not in) +#define FFADE_MODULATE 0x0002 // Modulate (don't blend) +#define FFADE_STAYOUT 0x0004 // ignores the duration, stays faded out until new ScreenFade message received + +// This structure is sent over the net to describe a screen fade event +typedef struct +{ + unsigned short duration; // FIXED 4.12 seconds duration + unsigned short holdTime; // FIXED 4.12 seconds duration until reset (fade & hold) + short fadeFlags; // flags + byte r, g, b, a; // fade to color ( max alpha ) +} ScreenFade; + +#endif // SHAKE_H + diff --git a/engine/studio.h b/engine/studio.h index 62d4a98..ec98f2d 100644 --- a/engine/studio.h +++ b/engine/studio.h @@ -1,362 +1,362 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - - - - -#ifndef _STUDIO_H_ -#define _STUDIO_H_ - -/* -============================================================================== - -STUDIO MODELS - -Studio models are position independent, so the cache manager can move them. -============================================================================== -*/ - - -#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this -#define MAXSTUDIOVERTS 2048 // TODO: tune this -#define MAXSTUDIOSEQUENCES 256 // total animation sequences -#define MAXSTUDIOSKINS 100 // total textures -#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement -#define MAXSTUDIOBONES 128 // total bones actually used -#define MAXSTUDIOMODELS 32 // sub-models per model -#define MAXSTUDIOBODYPARTS 32 -#define MAXSTUDIOGROUPS 16 -#define MAXSTUDIOANIMATIONS 512 // per sequence -#define MAXSTUDIOMESHES 256 -#define MAXSTUDIOEVENTS 1024 -#define MAXSTUDIOPIVOTS 256 -#define MAXSTUDIOCONTROLLERS 8 - -typedef struct -{ - int id; - int version; - - char name[64]; - int length; - - vec3_t eyeposition; // ideal eye position - vec3_t min; // ideal movement hull size - vec3_t max; - - vec3_t bbmin; // clipping bounding box - vec3_t bbmax; - - int flags; - - int numbones; // bones - int boneindex; - - int numbonecontrollers; // bone controllers - int bonecontrollerindex; - - int numhitboxes; // complex bounding boxes - int hitboxindex; - - int numseq; // animation sequences - int seqindex; - - int numseqgroups; // demand loaded sequences - int seqgroupindex; - - int numtextures; // raw textures - int textureindex; - int texturedataindex; - - int numskinref; // replaceable textures - int numskinfamilies; - int skinindex; - - int numbodyparts; - int bodypartindex; - - int numattachments; // queryable attachable points - int attachmentindex; - - int soundtable; - int soundindex; - int soundgroups; - int soundgroupindex; - - int numtransitions; // animation node to animation node transition graph - int transitionindex; -} studiohdr_t; - -// header for demand loaded sequence group data -typedef struct -{ - int id; - int version; - - char name[64]; - int length; -} studioseqhdr_t; - -// bones -typedef struct -{ - char name[32]; // bone name for symbolic links - int parent; // parent bone - int flags; // ?? - int bonecontroller[6]; // bone controller index, -1 == none - float value[6]; // default DoF values - float scale[6]; // scale for delta DoF values -} mstudiobone_t; - - -// bone controllers -typedef struct -{ - int bone; // -1 == 0 - int type; // X, Y, Z, XR, YR, ZR, M - float start; - float end; - int rest; // byte index value at rest - int index; // 0-3 user set controller, 4 mouth -} mstudiobonecontroller_t; - -// intersection boxes -typedef struct -{ - int bone; - int group; // intersection group - vec3_t bbmin; // bounding box - vec3_t bbmax; -} mstudiobbox_t; - -#if !defined( CACHE_USER ) && !defined( QUAKEDEF_H ) -#define CACHE_USER -typedef struct cache_user_s -{ - void *data; -} cache_user_t; -#endif - -// demand loaded sequence groups -typedef struct -{ - char label[32]; // textual name - char name[64]; // file name - cache_user_t cache; // cache index pointer - int data; // hack for group 0 -} mstudioseqgroup_t; - -// sequence descriptions -typedef struct -{ - char label[32]; // sequence label - - float fps; // frames per second - int flags; // looping/non-looping flags - - int activity; - int actweight; - - int numevents; - int eventindex; - - int numframes; // number of frames per sequence - - int numpivots; // number of foot pivots - int pivotindex; - - int motiontype; - int motionbone; - vec3_t linearmovement; - int automoveposindex; - int automoveangleindex; - - vec3_t bbmin; // per sequence bounding box - vec3_t bbmax; - - int numblends; - int animindex; // mstudioanim_t pointer relative to start of sequence group data - // [blend][bone][X, Y, Z, XR, YR, ZR] - - int blendtype[2]; // X, Y, Z, XR, YR, ZR - float blendstart[2]; // starting value - float blendend[2]; // ending value - int blendparent; - - int seqgroup; // sequence group for demand loading - - int entrynode; // transition node at entry - int exitnode; // transition node at exit - int nodeflags; // transition rules - - int nextseq; // auto advancing sequences -} mstudioseqdesc_t; - -// events -#include "studio_event.h" -/* -typedef struct -{ - int frame; - int event; - int type; - char options[64]; -} mstudioevent_t; -*/ - -// pivots -typedef struct -{ - vec3_t org; // pivot point - int start; - int end; -} mstudiopivot_t; - -// attachment -typedef struct -{ - char name[32]; - int type; - int bone; - vec3_t org; // attachment point - vec3_t vectors[3]; -} mstudioattachment_t; - -typedef struct -{ - unsigned short offset[6]; -} mstudioanim_t; - -// animation frames -typedef union -{ - struct { - byte valid; - byte total; - } num; - short value; -} mstudioanimvalue_t; - - - -// body part index -typedef struct -{ - char name[64]; - int nummodels; - int base; - int modelindex; // index into models array -} mstudiobodyparts_t; - - - -// skin info -typedef struct -{ - char name[64]; - int flags; - int width; - int height; - int index; -} mstudiotexture_t; - - -// skin families -// short index[skinfamilies][skinref] - -// studio models -typedef struct -{ - char name[64]; - - int type; - - float boundingradius; - - int nummesh; - int meshindex; - - int numverts; // number of unique vertices - int vertinfoindex; // vertex bone info - int vertindex; // vertex vec3_t - int numnorms; // number of unique surface normals - int norminfoindex; // normal bone info - int normindex; // normal vec3_t - - int numgroups; // deformation groups - int groupindex; -} mstudiomodel_t; - - -// vec3_t boundingbox[model][bone][2]; // complex intersection info - - -// meshes -typedef struct -{ - int numtris; - int triindex; - int skinref; - int numnorms; // per mesh normals - int normindex; // normal vec3_t -} mstudiomesh_t; - -// triangles -#if 0 -typedef struct -{ - short vertindex; // index into vertex array - short normindex; // index into normal array - short s,t; // s,t position on skin -} mstudiotrivert_t; -#endif - -// lighting options -#define STUDIO_NF_FLATSHADE 0x0001 -#define STUDIO_NF_CHROME 0x0002 -#define STUDIO_NF_FULLBRIGHT 0x0004 - -// motion flags -#define STUDIO_X 0x0001 -#define STUDIO_Y 0x0002 -#define STUDIO_Z 0x0004 -#define STUDIO_XR 0x0008 -#define STUDIO_YR 0x0010 -#define STUDIO_ZR 0x0020 -#define STUDIO_LX 0x0040 -#define STUDIO_LY 0x0080 -#define STUDIO_LZ 0x0100 -#define STUDIO_AX 0x0200 -#define STUDIO_AY 0x0400 -#define STUDIO_AZ 0x0800 -#define STUDIO_AXR 0x1000 -#define STUDIO_AYR 0x2000 -#define STUDIO_AZR 0x4000 -#define STUDIO_TYPES 0x7FFF -#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance - -// sequence flags -#define STUDIO_LOOPING 0x0001 - -// bone flags -#define STUDIO_HAS_NORMALS 0x0001 -#define STUDIO_HAS_VERTICES 0x0002 -#define STUDIO_HAS_BBOX 0x0004 -#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them - -#define RAD_TO_STUDIO (32768.0/M_PI) -#define STUDIO_TO_RAD (M_PI/32768.0) - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + + + + +#ifndef _STUDIO_H_ +#define _STUDIO_H_ + +/* +============================================================================== + +STUDIO MODELS + +Studio models are position independent, so the cache manager can move them. +============================================================================== +*/ + + +#define MAXSTUDIOTRIANGLES 20000 // TODO: tune this +#define MAXSTUDIOVERTS 2048 // TODO: tune this +#define MAXSTUDIOSEQUENCES 256 // total animation sequences +#define MAXSTUDIOSKINS 100 // total textures +#define MAXSTUDIOSRCBONES 512 // bones allowed at source movement +#define MAXSTUDIOBONES 128 // total bones actually used +#define MAXSTUDIOMODELS 32 // sub-models per model +#define MAXSTUDIOBODYPARTS 32 +#define MAXSTUDIOGROUPS 16 +#define MAXSTUDIOANIMATIONS 512 // per sequence +#define MAXSTUDIOMESHES 256 +#define MAXSTUDIOEVENTS 1024 +#define MAXSTUDIOPIVOTS 256 +#define MAXSTUDIOCONTROLLERS 8 + +typedef struct +{ + int id; + int version; + + char name[64]; + int length; + + vec3_t eyeposition; // ideal eye position + vec3_t min; // ideal movement hull size + vec3_t max; + + vec3_t bbmin; // clipping bounding box + vec3_t bbmax; + + int flags; + + int numbones; // bones + int boneindex; + + int numbonecontrollers; // bone controllers + int bonecontrollerindex; + + int numhitboxes; // complex bounding boxes + int hitboxindex; + + int numseq; // animation sequences + int seqindex; + + int numseqgroups; // demand loaded sequences + int seqgroupindex; + + int numtextures; // raw textures + int textureindex; + int texturedataindex; + + int numskinref; // replaceable textures + int numskinfamilies; + int skinindex; + + int numbodyparts; + int bodypartindex; + + int numattachments; // queryable attachable points + int attachmentindex; + + int soundtable; + int soundindex; + int soundgroups; + int soundgroupindex; + + int numtransitions; // animation node to animation node transition graph + int transitionindex; +} studiohdr_t; + +// header for demand loaded sequence group data +typedef struct +{ + int id; + int version; + + char name[64]; + int length; +} studioseqhdr_t; + +// bones +typedef struct +{ + char name[32]; // bone name for symbolic links + int parent; // parent bone + int flags; // ?? + int bonecontroller[6]; // bone controller index, -1 == none + float value[6]; // default DoF values + float scale[6]; // scale for delta DoF values +} mstudiobone_t; + + +// bone controllers +typedef struct +{ + int bone; // -1 == 0 + int type; // X, Y, Z, XR, YR, ZR, M + float start; + float end; + int rest; // byte index value at rest + int index; // 0-3 user set controller, 4 mouth +} mstudiobonecontroller_t; + +// intersection boxes +typedef struct +{ + int bone; + int group; // intersection group + vec3_t bbmin; // bounding box + vec3_t bbmax; +} mstudiobbox_t; + +#if !defined( CACHE_USER ) && !defined( QUAKEDEF_H ) +#define CACHE_USER +typedef struct cache_user_s +{ + void *data; +} cache_user_t; +#endif + +// demand loaded sequence groups +typedef struct +{ + char label[32]; // textual name + char name[64]; // file name + cache_user_t cache; // cache index pointer + int data; // hack for group 0 +} mstudioseqgroup_t; + +// sequence descriptions +typedef struct +{ + char label[32]; // sequence label + + float fps; // frames per second + int flags; // looping/non-looping flags + + int activity; + int actweight; + + int numevents; + int eventindex; + + int numframes; // number of frames per sequence + + int numpivots; // number of foot pivots + int pivotindex; + + int motiontype; + int motionbone; + vec3_t linearmovement; + int automoveposindex; + int automoveangleindex; + + vec3_t bbmin; // per sequence bounding box + vec3_t bbmax; + + int numblends; + int animindex; // mstudioanim_t pointer relative to start of sequence group data + // [blend][bone][X, Y, Z, XR, YR, ZR] + + int blendtype[2]; // X, Y, Z, XR, YR, ZR + float blendstart[2]; // starting value + float blendend[2]; // ending value + int blendparent; + + int seqgroup; // sequence group for demand loading + + int entrynode; // transition node at entry + int exitnode; // transition node at exit + int nodeflags; // transition rules + + int nextseq; // auto advancing sequences +} mstudioseqdesc_t; + +// events +#include "studio_event.h" +/* +typedef struct +{ + int frame; + int event; + int type; + char options[64]; +} mstudioevent_t; +*/ + +// pivots +typedef struct +{ + vec3_t org; // pivot point + int start; + int end; +} mstudiopivot_t; + +// attachment +typedef struct +{ + char name[32]; + int type; + int bone; + vec3_t org; // attachment point + vec3_t vectors[3]; +} mstudioattachment_t; + +typedef struct +{ + unsigned short offset[6]; +} mstudioanim_t; + +// animation frames +typedef union +{ + struct { + byte valid; + byte total; + } num; + short value; +} mstudioanimvalue_t; + + + +// body part index +typedef struct +{ + char name[64]; + int nummodels; + int base; + int modelindex; // index into models array +} mstudiobodyparts_t; + + + +// skin info +typedef struct +{ + char name[64]; + int flags; + int width; + int height; + int index; +} mstudiotexture_t; + + +// skin families +// short index[skinfamilies][skinref] + +// studio models +typedef struct +{ + char name[64]; + + int type; + + float boundingradius; + + int nummesh; + int meshindex; + + int numverts; // number of unique vertices + int vertinfoindex; // vertex bone info + int vertindex; // vertex vec3_t + int numnorms; // number of unique surface normals + int norminfoindex; // normal bone info + int normindex; // normal vec3_t + + int numgroups; // deformation groups + int groupindex; +} mstudiomodel_t; + + +// vec3_t boundingbox[model][bone][2]; // complex intersection info + + +// meshes +typedef struct +{ + int numtris; + int triindex; + int skinref; + int numnorms; // per mesh normals + int normindex; // normal vec3_t +} mstudiomesh_t; + +// triangles +#if 0 +typedef struct +{ + short vertindex; // index into vertex array + short normindex; // index into normal array + short s,t; // s,t position on skin +} mstudiotrivert_t; +#endif + +// lighting options +#define STUDIO_NF_FLATSHADE 0x0001 +#define STUDIO_NF_CHROME 0x0002 +#define STUDIO_NF_FULLBRIGHT 0x0004 + +// motion flags +#define STUDIO_X 0x0001 +#define STUDIO_Y 0x0002 +#define STUDIO_Z 0x0004 +#define STUDIO_XR 0x0008 +#define STUDIO_YR 0x0010 +#define STUDIO_ZR 0x0020 +#define STUDIO_LX 0x0040 +#define STUDIO_LY 0x0080 +#define STUDIO_LZ 0x0100 +#define STUDIO_AX 0x0200 +#define STUDIO_AY 0x0400 +#define STUDIO_AZ 0x0800 +#define STUDIO_AXR 0x1000 +#define STUDIO_AYR 0x2000 +#define STUDIO_AZR 0x4000 +#define STUDIO_TYPES 0x7FFF +#define STUDIO_RLOOP 0x8000 // controller that wraps shortest distance + +// sequence flags +#define STUDIO_LOOPING 0x0001 + +// bone flags +#define STUDIO_HAS_NORMALS 0x0001 +#define STUDIO_HAS_VERTICES 0x0002 +#define STUDIO_HAS_BBOX 0x0004 +#define STUDIO_HAS_CHROME 0x0008 // if any of the textures have chrome on them + +#define RAD_TO_STUDIO (32768.0/M_PI) +#define STUDIO_TO_RAD (M_PI/32768.0) + +#endif diff --git a/game_shared/bitvec.h b/game_shared/bitvec.h index d77bfee..1881c9c 100644 --- a/game_shared/bitvec.h +++ b/game_shared/bitvec.h @@ -1,181 +1,181 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef BITVEC_H -#define BITVEC_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - - -#include - - -class CBitVecAccessor -{ -public: - CBitVecAccessor(unsigned long *pDWords, int iBit); - - void operator=(int val); - operator unsigned long(); - -private: - unsigned long *m_pDWords; - int m_iBit; -}; - - -// CBitVec allows you to store a list of bits and do operations on them like they were -// an atomic type. -template -class CBitVec -{ -public: - - CBitVec(); - - // Set all values to the specified value (0 or 1..) - void Init(int val = 0); - - // Access the bits like an array. - CBitVecAccessor operator[](int i); - - // Operations on other bit vectors. - CBitVec& operator=(CBitVec const &other); - bool operator==(CBitVec const &other); - bool operator!=(CBitVec const &other); - - // Get underlying dword representations of the bits. - int GetNumDWords(); - unsigned long GetDWord(int i); - void SetDWord(int i, unsigned long val); - - int GetNumBits(); - -private: - - enum {NUM_DWORDS = NUM_BITS/32 + !!(NUM_BITS & 31)}; - unsigned long m_DWords[NUM_DWORDS]; -}; - - - -// ------------------------------------------------------------------------ // -// CBitVecAccessor inlines. -// ------------------------------------------------------------------------ // - -inline CBitVecAccessor::CBitVecAccessor(unsigned long *pDWords, int iBit) -{ - m_pDWords = pDWords; - m_iBit = iBit; -} - - -inline void CBitVecAccessor::operator=(int val) -{ - if(val) - m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31)); - else - m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31)); -} - -inline CBitVecAccessor::operator unsigned long() -{ - return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31)); -} - - - -// ------------------------------------------------------------------------ // -// CBitVec inlines. -// ------------------------------------------------------------------------ // - -template -inline int CBitVec::GetNumBits() -{ - return NUM_BITS; -} - - -template -inline CBitVec::CBitVec() -{ - for(int i=0; i < NUM_DWORDS; i++) - m_DWords[i] = 0; -} - - -template -inline void CBitVec::Init(int val) -{ - for(int i=0; i < GetNumBits(); i++) - { - (*this)[i] = val; - } -} - - -template -inline CBitVec& CBitVec::operator=(CBitVec const &other) -{ - memcpy(m_DWords, other.m_DWords, sizeof(m_DWords)); - return *this; -} - - -template -inline CBitVecAccessor CBitVec::operator[](int i) -{ - assert(i >= 0 && i < GetNumBits()); - return CBitVecAccessor(m_DWords, i); -} - - -template -inline bool CBitVec::operator==(CBitVec const &other) -{ - for(int i=0; i < NUM_DWORDS; i++) - if(m_DWords[i] != other.m_DWords[i]) - return false; - - return true; -} - - -template -inline bool CBitVec::operator!=(CBitVec const &other) -{ - return !(*this == other); -} - - -template -inline int CBitVec::GetNumDWords() -{ - return NUM_DWORDS; -} - -template -inline unsigned long CBitVec::GetDWord(int i) -{ - assert(i >= 0 && i < NUM_DWORDS); - return m_DWords[i]; -} - - -template -inline void CBitVec::SetDWord(int i, unsigned long val) -{ - assert(i >= 0 && i < NUM_DWORDS); - m_DWords[i] = val; -} - - -#endif // BITVEC_H - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef BITVEC_H +#define BITVEC_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + + +#include + + +class CBitVecAccessor +{ +public: + CBitVecAccessor(unsigned long *pDWords, int iBit); + + void operator=(int val); + operator unsigned long(); + +private: + unsigned long *m_pDWords; + int m_iBit; +}; + + +// CBitVec allows you to store a list of bits and do operations on them like they were +// an atomic type. +template +class CBitVec +{ +public: + + CBitVec(); + + // Set all values to the specified value (0 or 1..) + void Init(int val = 0); + + // Access the bits like an array. + CBitVecAccessor operator[](int i); + + // Operations on other bit vectors. + CBitVec& operator=(CBitVec const &other); + bool operator==(CBitVec const &other); + bool operator!=(CBitVec const &other); + + // Get underlying dword representations of the bits. + int GetNumDWords(); + unsigned long GetDWord(int i); + void SetDWord(int i, unsigned long val); + + int GetNumBits(); + +private: + + enum {NUM_DWORDS = NUM_BITS/32 + !!(NUM_BITS & 31)}; + unsigned long m_DWords[NUM_DWORDS]; +}; + + + +// ------------------------------------------------------------------------ // +// CBitVecAccessor inlines. +// ------------------------------------------------------------------------ // + +inline CBitVecAccessor::CBitVecAccessor(unsigned long *pDWords, int iBit) +{ + m_pDWords = pDWords; + m_iBit = iBit; +} + + +inline void CBitVecAccessor::operator=(int val) +{ + if(val) + m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31)); + else + m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31)); +} + +inline CBitVecAccessor::operator unsigned long() +{ + return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31)); +} + + + +// ------------------------------------------------------------------------ // +// CBitVec inlines. +// ------------------------------------------------------------------------ // + +template +inline int CBitVec::GetNumBits() +{ + return NUM_BITS; +} + + +template +inline CBitVec::CBitVec() +{ + for(int i=0; i < NUM_DWORDS; i++) + m_DWords[i] = 0; +} + + +template +inline void CBitVec::Init(int val) +{ + for(int i=0; i < GetNumBits(); i++) + { + (*this)[i] = val; + } +} + + +template +inline CBitVec& CBitVec::operator=(CBitVec const &other) +{ + memcpy(m_DWords, other.m_DWords, sizeof(m_DWords)); + return *this; +} + + +template +inline CBitVecAccessor CBitVec::operator[](int i) +{ + assert(i >= 0 && i < GetNumBits()); + return CBitVecAccessor(m_DWords, i); +} + + +template +inline bool CBitVec::operator==(CBitVec const &other) +{ + for(int i=0; i < NUM_DWORDS; i++) + if(m_DWords[i] != other.m_DWords[i]) + return false; + + return true; +} + + +template +inline bool CBitVec::operator!=(CBitVec const &other) +{ + return !(*this == other); +} + + +template +inline int CBitVec::GetNumDWords() +{ + return NUM_DWORDS; +} + +template +inline unsigned long CBitVec::GetDWord(int i) +{ + assert(i >= 0 && i < NUM_DWORDS); + return m_DWords[i]; +} + + +template +inline void CBitVec::SetDWord(int i, unsigned long val) +{ + assert(i >= 0 && i < NUM_DWORDS); + m_DWords[i] = val; +} + + +#endif // BITVEC_H + diff --git a/game_shared/voice_banmgr.cpp b/game_shared/voice_banmgr.cpp index 470e80e..c9ff3ad 100644 --- a/game_shared/voice_banmgr.cpp +++ b/game_shared/voice_banmgr.cpp @@ -1,197 +1,197 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include -#include -#include "voice_banmgr.h" - - -#define BANMGR_FILEVERSION 1 -char const *g_pBanMgrFilename = "voice_ban.dt"; - - - -// Hash a player ID to a byte. -unsigned char HashPlayerID(char const playerID[16]) -{ - unsigned char curHash = 0; - - for(int i=0; i < 16; i++) - curHash += (unsigned char)playerID[i]; - - return curHash; -} - - - -CVoiceBanMgr::CVoiceBanMgr() -{ - Clear(); -} - - -CVoiceBanMgr::~CVoiceBanMgr() -{ - Term(); -} - - -bool CVoiceBanMgr::Init(char const *pGameDir) -{ - Term(); - - char filename[512]; - _snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename); - - // Load in the squelch file. - FILE *fp = fopen(filename, "rb"); - if(fp) - { - int version; - fread(&version, 1, sizeof(version), fp); - if(version == BANMGR_FILEVERSION) - { - fseek(fp, 0, SEEK_END); - int nIDs = (ftell(fp) - sizeof(version)) / 16; - fseek(fp, sizeof(version), SEEK_SET); - - for(int i=0; i < nIDs; i++) - { - char playerID[16]; - fread(playerID, 1, 16, fp); - AddBannedPlayer(playerID); - } - } - - fclose(fp); - } - - return true; -} - - -void CVoiceBanMgr::Term() -{ - // Free all the player structures. - for(int i=0; i < 256; i++) - { - BannedPlayer *pListHead = &m_PlayerHash[i]; - BannedPlayer *pNext; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pNext) - { - pNext = pCur->m_pNext; - delete pCur; - } - } - - Clear(); -} - - -void CVoiceBanMgr::SaveState(char const *pGameDir) -{ - // Save the file out. - char filename[512]; - _snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename); - - FILE *fp = fopen(filename, "wb"); - if(fp) - { - int version = BANMGR_FILEVERSION; - fwrite(&version, 1, sizeof(version), fp); - - for(int i=0; i < 256; i++) - { - BannedPlayer *pListHead = &m_PlayerHash[i]; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) - { - fwrite(pCur->m_PlayerID, 1, 16, fp); - } - } - - fclose(fp); - } -} - - -bool CVoiceBanMgr::GetPlayerBan(char const playerID[16]) -{ - return !!InternalFindPlayerSquelch(playerID); -} - - -void CVoiceBanMgr::SetPlayerBan(char const playerID[16], bool bSquelch) -{ - if(bSquelch) - { - // Is this guy already squelched? - if(GetPlayerBan(playerID)) - return; - - AddBannedPlayer(playerID); - } - else - { - BannedPlayer *pPlayer = InternalFindPlayerSquelch(playerID); - if(pPlayer) - { - pPlayer->m_pPrev->m_pNext = pPlayer->m_pNext; - pPlayer->m_pNext->m_pPrev = pPlayer->m_pPrev; - delete pPlayer; - } - } -} - - -void CVoiceBanMgr::ForEachBannedPlayer(void (*callback)(char id[16])) -{ - for(int i=0; i < 256; i++) - { - for(BannedPlayer *pCur=m_PlayerHash[i].m_pNext; pCur != &m_PlayerHash[i]; pCur=pCur->m_pNext) - { - callback(pCur->m_PlayerID); - } - } -} - - -void CVoiceBanMgr::Clear() -{ - // Tie off the hash table entries. - for(int i=0; i < 256; i++) - m_PlayerHash[i].m_pNext = m_PlayerHash[i].m_pPrev = &m_PlayerHash[i]; -} - - -CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::InternalFindPlayerSquelch(char const playerID[16]) -{ - int index = HashPlayerID(playerID); - BannedPlayer *pListHead = &m_PlayerHash[index]; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) - { - if(memcmp(playerID, pCur->m_PlayerID, 16) == 0) - return pCur; - } - - return NULL; -} - - -CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::AddBannedPlayer(char const playerID[16]) -{ - BannedPlayer *pNew = new BannedPlayer; - if(!pNew) - return NULL; - - int index = HashPlayerID(playerID); - memcpy(pNew->m_PlayerID, playerID, 16); - pNew->m_pNext = &m_PlayerHash[index]; - pNew->m_pPrev = m_PlayerHash[index].m_pPrev; - pNew->m_pPrev->m_pNext = pNew->m_pNext->m_pPrev = pNew; - return pNew; -} - +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include +#include +#include "voice_banmgr.h" + + +#define BANMGR_FILEVERSION 1 +char const *g_pBanMgrFilename = "voice_ban.dt"; + + + +// Hash a player ID to a byte. +unsigned char HashPlayerID(char const playerID[16]) +{ + unsigned char curHash = 0; + + for(int i=0; i < 16; i++) + curHash += (unsigned char)playerID[i]; + + return curHash; +} + + + +CVoiceBanMgr::CVoiceBanMgr() +{ + Clear(); +} + + +CVoiceBanMgr::~CVoiceBanMgr() +{ + Term(); +} + + +bool CVoiceBanMgr::Init(char const *pGameDir) +{ + Term(); + + char filename[512]; + _snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename); + + // Load in the squelch file. + FILE *fp = fopen(filename, "rb"); + if(fp) + { + int version; + fread(&version, 1, sizeof(version), fp); + if(version == BANMGR_FILEVERSION) + { + fseek(fp, 0, SEEK_END); + int nIDs = (ftell(fp) - sizeof(version)) / 16; + fseek(fp, sizeof(version), SEEK_SET); + + for(int i=0; i < nIDs; i++) + { + char playerID[16]; + fread(playerID, 1, 16, fp); + AddBannedPlayer(playerID); + } + } + + fclose(fp); + } + + return true; +} + + +void CVoiceBanMgr::Term() +{ + // Free all the player structures. + for(int i=0; i < 256; i++) + { + BannedPlayer *pListHead = &m_PlayerHash[i]; + BannedPlayer *pNext; + for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pNext) + { + pNext = pCur->m_pNext; + delete pCur; + } + } + + Clear(); +} + + +void CVoiceBanMgr::SaveState(char const *pGameDir) +{ + // Save the file out. + char filename[512]; + _snprintf(filename, sizeof(filename), "%s/%s", pGameDir, g_pBanMgrFilename); + + FILE *fp = fopen(filename, "wb"); + if(fp) + { + int version = BANMGR_FILEVERSION; + fwrite(&version, 1, sizeof(version), fp); + + for(int i=0; i < 256; i++) + { + BannedPlayer *pListHead = &m_PlayerHash[i]; + for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) + { + fwrite(pCur->m_PlayerID, 1, 16, fp); + } + } + + fclose(fp); + } +} + + +bool CVoiceBanMgr::GetPlayerBan(char const playerID[16]) +{ + return !!InternalFindPlayerSquelch(playerID); +} + + +void CVoiceBanMgr::SetPlayerBan(char const playerID[16], bool bSquelch) +{ + if(bSquelch) + { + // Is this guy already squelched? + if(GetPlayerBan(playerID)) + return; + + AddBannedPlayer(playerID); + } + else + { + BannedPlayer *pPlayer = InternalFindPlayerSquelch(playerID); + if(pPlayer) + { + pPlayer->m_pPrev->m_pNext = pPlayer->m_pNext; + pPlayer->m_pNext->m_pPrev = pPlayer->m_pPrev; + delete pPlayer; + } + } +} + + +void CVoiceBanMgr::ForEachBannedPlayer(void (*callback)(char id[16])) +{ + for(int i=0; i < 256; i++) + { + for(BannedPlayer *pCur=m_PlayerHash[i].m_pNext; pCur != &m_PlayerHash[i]; pCur=pCur->m_pNext) + { + callback(pCur->m_PlayerID); + } + } +} + + +void CVoiceBanMgr::Clear() +{ + // Tie off the hash table entries. + for(int i=0; i < 256; i++) + m_PlayerHash[i].m_pNext = m_PlayerHash[i].m_pPrev = &m_PlayerHash[i]; +} + + +CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::InternalFindPlayerSquelch(char const playerID[16]) +{ + int index = HashPlayerID(playerID); + BannedPlayer *pListHead = &m_PlayerHash[index]; + for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) + { + if(memcmp(playerID, pCur->m_PlayerID, 16) == 0) + return pCur; + } + + return NULL; +} + + +CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::AddBannedPlayer(char const playerID[16]) +{ + BannedPlayer *pNew = new BannedPlayer; + if(!pNew) + return NULL; + + int index = HashPlayerID(playerID); + memcpy(pNew->m_PlayerID, playerID, 16); + pNew->m_pNext = &m_PlayerHash[index]; + pNew->m_pPrev = m_PlayerHash[index].m_pPrev; + pNew->m_pPrev->m_pNext = pNew->m_pNext->m_pPrev = pNew; + return pNew; +} + diff --git a/game_shared/voice_banmgr.h b/game_shared/voice_banmgr.h index 4846167..eefe405 100644 --- a/game_shared/voice_banmgr.h +++ b/game_shared/voice_banmgr.h @@ -1,59 +1,59 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef VOICE_BANMGR_H -#define VOICE_BANMGR_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - - -// This class manages the (persistent) list of squelched players. -class CVoiceBanMgr -{ -public: - - CVoiceBanMgr(); - ~CVoiceBanMgr(); - - // Init loads the list of squelched players from disk. - bool Init(char const *pGameDir); - void Term(); - - // Saves the state into voice_squelch.dt. - void SaveState(char const *pGameDir); - - bool GetPlayerBan(char const playerID[16]); - void SetPlayerBan(char const playerID[16], bool bSquelch); - - // Call your callback for each banned player. - void ForEachBannedPlayer(void (*callback)(char id[16])); - - -protected: - - class BannedPlayer - { - public: - char m_PlayerID[16]; - BannedPlayer *m_pPrev, *m_pNext; - }; - - void Clear(); - BannedPlayer* InternalFindPlayerSquelch(char const playerID[16]); - BannedPlayer* AddBannedPlayer(char const playerID[16]); - - -protected: - - BannedPlayer m_PlayerHash[256]; -}; - - -#endif // VOICE_BANMGR_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VOICE_BANMGR_H +#define VOICE_BANMGR_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + + +// This class manages the (persistent) list of squelched players. +class CVoiceBanMgr +{ +public: + + CVoiceBanMgr(); + ~CVoiceBanMgr(); + + // Init loads the list of squelched players from disk. + bool Init(char const *pGameDir); + void Term(); + + // Saves the state into voice_squelch.dt. + void SaveState(char const *pGameDir); + + bool GetPlayerBan(char const playerID[16]); + void SetPlayerBan(char const playerID[16], bool bSquelch); + + // Call your callback for each banned player. + void ForEachBannedPlayer(void (*callback)(char id[16])); + + +protected: + + class BannedPlayer + { + public: + char m_PlayerID[16]; + BannedPlayer *m_pPrev, *m_pNext; + }; + + void Clear(); + BannedPlayer* InternalFindPlayerSquelch(char const playerID[16]); + BannedPlayer* AddBannedPlayer(char const playerID[16]); + + +protected: + + BannedPlayer m_PlayerHash[256]; +}; + + +#endif // VOICE_BANMGR_H diff --git a/game_shared/voice_common.h b/game_shared/voice_common.h index c83effd..c9eee93 100644 --- a/game_shared/voice_common.h +++ b/game_shared/voice_common.h @@ -1,26 +1,26 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef VOICE_COMMON_H -#define VOICE_COMMON_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - - -#include "bitvec.h" - - -#define VOICE_MAX_PLAYERS 32 // (todo: this should just be set to MAX_CLIENTS). -#define VOICE_MAX_PLAYERS_DW ((VOICE_MAX_PLAYERS / 32) + !!(VOICE_MAX_PLAYERS & 31)) - -typedef CBitVec CPlayerBitVec; - - -#endif // VOICE_COMMON_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VOICE_COMMON_H +#define VOICE_COMMON_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + + +#include "bitvec.h" + + +#define VOICE_MAX_PLAYERS 32 // (todo: this should just be set to MAX_CLIENTS). +#define VOICE_MAX_PLAYERS_DW ((VOICE_MAX_PLAYERS / 32) + !!(VOICE_MAX_PLAYERS & 31)) + +typedef CBitVec CPlayerBitVec; + + +#endif // VOICE_COMMON_H diff --git a/game_shared/voice_gamemgr.cpp b/game_shared/voice_gamemgr.cpp index 5ba2edf..c215cfc 100644 --- a/game_shared/voice_gamemgr.cpp +++ b/game_shared/voice_gamemgr.cpp @@ -1,274 +1,274 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include "voice_gamemgr.h" -#include -#include -#include "extdll.h" -#include "util.h" -#include "cbase.h" -#include "player.h" - - - -#define UPDATE_INTERVAL 0.3 - - -// These are stored off as CVoiceGameMgr is created and deleted. -CPlayerBitVec g_PlayerModEnable; // Set to 1 for each player if the player wants to use voice in this mod. - // (If it's zero, then the server reports that the game rules are saying the - // player can't hear anyone). - -CPlayerBitVec g_BanMasks[VOICE_MAX_PLAYERS]; // Tells which players don't want to hear each other. - // These are indexed as clients and each bit represents a client - // (so player entity is bit+1). - -CPlayerBitVec g_SentGameRulesMasks[VOICE_MAX_PLAYERS]; // These store the masks we last sent to each client so we can determine if -CPlayerBitVec g_SentBanMasks[VOICE_MAX_PLAYERS]; // we need to resend them. -CPlayerBitVec g_bWantModEnable; - -cvar_t voice_serverdebug = {"voice_serverdebug", "0"}; - -// Set game rules to allow all clients to talk to each other. -// Muted players still can't talk to each other. -cvar_t sv_alltalk = {"sv_alltalk", "0"}; - -// ------------------------------------------------------------------------ // -// Static helpers. -// ------------------------------------------------------------------------ // - -// Find a player with a case-insensitive name search. -static CBasePlayer* FindPlayerByName(const char *pTestName) -{ - for(int i=1; i <= gpGlobals->maxClients; i++) - { - edict_t *pEdict = g_engfuncs.pfnPEntityOfEntIndex(i); - if(pEdict) - { - CBaseEntity *pEnt = CBaseEntity::Instance(pEdict); - if(pEnt && pEnt->IsPlayer()) - { - const char *pNetName = STRING(pEnt->pev->netname); - if(stricmp(pNetName, pTestName) == 0) - { - return (CBasePlayer*)pEnt; - } - } - } - } - - return NULL; -} - -static void VoiceServerDebug( char const *pFmt, ... ) -{ - char msg[4096]; - va_list marker; - - if( !voice_serverdebug.value ) - return; - - va_start( marker, pFmt ); - _vsnprintf( msg, sizeof(msg), pFmt, marker ); - va_end( marker ); - - ALERT( at_console, "%s", msg ); -} - - - -// ------------------------------------------------------------------------ // -// CVoiceGameMgr. -// ------------------------------------------------------------------------ // - -CVoiceGameMgr::CVoiceGameMgr() -{ - m_UpdateInterval = 0; - m_nMaxPlayers = 0; -} - - -CVoiceGameMgr::~CVoiceGameMgr() -{ -} - - -bool CVoiceGameMgr::Init( - IVoiceGameMgrHelper *pHelper, - int maxClients) -{ - m_pHelper = pHelper; - m_nMaxPlayers = VOICE_MAX_PLAYERS < maxClients ? VOICE_MAX_PLAYERS : maxClients; - g_engfuncs.pfnPrecacheModel("sprites/voiceicon.spr"); - - m_msgPlayerVoiceMask = REG_USER_MSG( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 ); - m_msgRequestState = REG_USER_MSG( "ReqState", 0 ); - - // register voice_serverdebug if it hasn't been registered already - if ( !CVAR_GET_POINTER( "voice_serverdebug" ) ) - CVAR_REGISTER( &voice_serverdebug ); - - if( !CVAR_GET_POINTER( "sv_alltalk" ) ) - CVAR_REGISTER( &sv_alltalk ); - - return true; -} - - -void CVoiceGameMgr::SetHelper(IVoiceGameMgrHelper *pHelper) -{ - m_pHelper = pHelper; -} - - -void CVoiceGameMgr::Update(double frametime) -{ - // Only update periodically. - m_UpdateInterval += frametime; - if(m_UpdateInterval < UPDATE_INTERVAL) - return; - - UpdateMasks(); -} - - -void CVoiceGameMgr::ClientConnected(edict_t *pEdict) -{ - int index = ENTINDEX(pEdict) - 1; - - // Clear out everything we use for deltas on this guy. - g_bWantModEnable[index] = true; - g_SentGameRulesMasks[index].Init(0); - g_SentBanMasks[index].Init(0); -} - -// Called to determine if the Receiver has muted (blocked) the Sender -// Returns true if the receiver has blocked the sender -bool CVoiceGameMgr::PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender) -{ - int iReceiverIndex, iSenderIndex; - - if ( !pReceiver || !pSender ) - return false; - - iReceiverIndex = pReceiver->entindex() - 1; - iSenderIndex = pSender->entindex() - 1; - - if ( iReceiverIndex < 0 || iReceiverIndex >= m_nMaxPlayers || iSenderIndex < 0 || iSenderIndex >= m_nMaxPlayers ) - return false; - - return ( g_BanMasks[iReceiverIndex][iSenderIndex] ? true : false ); -} - -bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd) -{ - int playerClientIndex = pPlayer->entindex() - 1; - if(playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers) - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: cmd %s from invalid client (%d)\n", cmd, playerClientIndex ); - return true; - } - - bool bBan = stricmp(cmd, "vban") == 0; - if(bBan && CMD_ARGC() >= 2) - { - for(int i=1; i < CMD_ARGC(); i++) - { - unsigned long mask = 0; - sscanf(CMD_ARGV(i), "%x", &mask); - - if(i <= VOICE_MAX_PLAYERS_DW) - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: vban (0x%x) from %d\n", mask, playerClientIndex ); - g_BanMasks[playerClientIndex].SetDWord(i-1, mask); - } - else - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i ); - } - } - - // Force it to update the masks now. - //UpdateMasks(); - return true; - } - else if(stricmp(cmd, "VModEnable") == 0 && CMD_ARGC() >= 2) - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi(CMD_ARGV(1)) ); - g_PlayerModEnable[playerClientIndex] = !!atoi(CMD_ARGV(1)); - g_bWantModEnable[playerClientIndex] = false; - //UpdateMasks(); - return true; - } - else - { - return false; - } -} - - -void CVoiceGameMgr::UpdateMasks() -{ - m_UpdateInterval = 0; - - bool bAllTalk = !!g_engfuncs.pfnCVarGetFloat( "sv_alltalk" ); - - for(int iClient=0; iClient < m_nMaxPlayers; iClient++) - { - CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient+1); - if(!pEnt || !pEnt->IsPlayer()) - continue; - - // Request the state of their "VModEnable" cvar. - if(g_bWantModEnable[iClient]) - { - MESSAGE_BEGIN(MSG_ONE, m_msgRequestState, NULL, pEnt->pev); - MESSAGE_END(); - } - - CBasePlayer *pPlayer = (CBasePlayer*)pEnt; - - CPlayerBitVec gameRulesMask; - if( g_PlayerModEnable[iClient] ) - { - // Build a mask of who they can hear based on the game rules. - for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) - { - CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient+1); - if(pEnt && pEnt->IsPlayer() && - (bAllTalk || m_pHelper->CanPlayerHearPlayer(pPlayer, (CBasePlayer*)pEnt)) ) - { - gameRulesMask[iOtherClient] = true; - } - } - } - - // If this is different from what the client has, send an update. - if(gameRulesMask != g_SentGameRulesMasks[iClient] || - g_BanMasks[iClient] != g_SentBanMasks[iClient]) - { - g_SentGameRulesMasks[iClient] = gameRulesMask; - g_SentBanMasks[iClient] = g_BanMasks[iClient]; - - MESSAGE_BEGIN(MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev); - int dw; - for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - WRITE_LONG(gameRulesMask.GetDWord(dw)); - WRITE_LONG(g_BanMasks[iClient].GetDWord(dw)); - } - MESSAGE_END(); - } - - // Tell the engine. - for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) - { - bool bCanHear = gameRulesMask[iOtherClient] && !g_BanMasks[iClient][iOtherClient]; - g_engfuncs.pfnVoice_SetClientListening(iClient+1, iOtherClient+1, bCanHear); - } - } -} +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "voice_gamemgr.h" +#include +#include +#include "extdll.h" +#include "util.h" +#include "cbase.h" +#include "player.h" + + + +#define UPDATE_INTERVAL 0.3 + + +// These are stored off as CVoiceGameMgr is created and deleted. +CPlayerBitVec g_PlayerModEnable; // Set to 1 for each player if the player wants to use voice in this mod. + // (If it's zero, then the server reports that the game rules are saying the + // player can't hear anyone). + +CPlayerBitVec g_BanMasks[VOICE_MAX_PLAYERS]; // Tells which players don't want to hear each other. + // These are indexed as clients and each bit represents a client + // (so player entity is bit+1). + +CPlayerBitVec g_SentGameRulesMasks[VOICE_MAX_PLAYERS]; // These store the masks we last sent to each client so we can determine if +CPlayerBitVec g_SentBanMasks[VOICE_MAX_PLAYERS]; // we need to resend them. +CPlayerBitVec g_bWantModEnable; + +cvar_t voice_serverdebug = {"voice_serverdebug", "0"}; + +// Set game rules to allow all clients to talk to each other. +// Muted players still can't talk to each other. +cvar_t sv_alltalk = {"sv_alltalk", "0"}; + +// ------------------------------------------------------------------------ // +// Static helpers. +// ------------------------------------------------------------------------ // + +// Find a player with a case-insensitive name search. +static CBasePlayer* FindPlayerByName(const char *pTestName) +{ + for(int i=1; i <= gpGlobals->maxClients; i++) + { + edict_t *pEdict = g_engfuncs.pfnPEntityOfEntIndex(i); + if(pEdict) + { + CBaseEntity *pEnt = CBaseEntity::Instance(pEdict); + if(pEnt && pEnt->IsPlayer()) + { + const char *pNetName = STRING(pEnt->pev->netname); + if(stricmp(pNetName, pTestName) == 0) + { + return (CBasePlayer*)pEnt; + } + } + } + } + + return NULL; +} + +static void VoiceServerDebug( char const *pFmt, ... ) +{ + char msg[4096]; + va_list marker; + + if( !voice_serverdebug.value ) + return; + + va_start( marker, pFmt ); + _vsnprintf( msg, sizeof(msg), pFmt, marker ); + va_end( marker ); + + ALERT( at_console, "%s", msg ); +} + + + +// ------------------------------------------------------------------------ // +// CVoiceGameMgr. +// ------------------------------------------------------------------------ // + +CVoiceGameMgr::CVoiceGameMgr() +{ + m_UpdateInterval = 0; + m_nMaxPlayers = 0; +} + + +CVoiceGameMgr::~CVoiceGameMgr() +{ +} + + +bool CVoiceGameMgr::Init( + IVoiceGameMgrHelper *pHelper, + int maxClients) +{ + m_pHelper = pHelper; + m_nMaxPlayers = VOICE_MAX_PLAYERS < maxClients ? VOICE_MAX_PLAYERS : maxClients; + g_engfuncs.pfnPrecacheModel("sprites/voiceicon.spr"); + + m_msgPlayerVoiceMask = REG_USER_MSG( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 ); + m_msgRequestState = REG_USER_MSG( "ReqState", 0 ); + + // register voice_serverdebug if it hasn't been registered already + if ( !CVAR_GET_POINTER( "voice_serverdebug" ) ) + CVAR_REGISTER( &voice_serverdebug ); + + if( !CVAR_GET_POINTER( "sv_alltalk" ) ) + CVAR_REGISTER( &sv_alltalk ); + + return true; +} + + +void CVoiceGameMgr::SetHelper(IVoiceGameMgrHelper *pHelper) +{ + m_pHelper = pHelper; +} + + +void CVoiceGameMgr::Update(double frametime) +{ + // Only update periodically. + m_UpdateInterval += frametime; + if(m_UpdateInterval < UPDATE_INTERVAL) + return; + + UpdateMasks(); +} + + +void CVoiceGameMgr::ClientConnected(edict_t *pEdict) +{ + int index = ENTINDEX(pEdict) - 1; + + // Clear out everything we use for deltas on this guy. + g_bWantModEnable[index] = true; + g_SentGameRulesMasks[index].Init(0); + g_SentBanMasks[index].Init(0); +} + +// Called to determine if the Receiver has muted (blocked) the Sender +// Returns true if the receiver has blocked the sender +bool CVoiceGameMgr::PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender) +{ + int iReceiverIndex, iSenderIndex; + + if ( !pReceiver || !pSender ) + return false; + + iReceiverIndex = pReceiver->entindex() - 1; + iSenderIndex = pSender->entindex() - 1; + + if ( iReceiverIndex < 0 || iReceiverIndex >= m_nMaxPlayers || iSenderIndex < 0 || iSenderIndex >= m_nMaxPlayers ) + return false; + + return ( g_BanMasks[iReceiverIndex][iSenderIndex] ? true : false ); +} + +bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd) +{ + int playerClientIndex = pPlayer->entindex() - 1; + if(playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers) + { + VoiceServerDebug( "CVoiceGameMgr::ClientCommand: cmd %s from invalid client (%d)\n", cmd, playerClientIndex ); + return true; + } + + bool bBan = stricmp(cmd, "vban") == 0; + if(bBan && CMD_ARGC() >= 2) + { + for(int i=1; i < CMD_ARGC(); i++) + { + unsigned long mask = 0; + sscanf(CMD_ARGV(i), "%x", &mask); + + if(i <= VOICE_MAX_PLAYERS_DW) + { + VoiceServerDebug( "CVoiceGameMgr::ClientCommand: vban (0x%x) from %d\n", mask, playerClientIndex ); + g_BanMasks[playerClientIndex].SetDWord(i-1, mask); + } + else + { + VoiceServerDebug( "CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i ); + } + } + + // Force it to update the masks now. + //UpdateMasks(); + return true; + } + else if(stricmp(cmd, "VModEnable") == 0 && CMD_ARGC() >= 2) + { + VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi(CMD_ARGV(1)) ); + g_PlayerModEnable[playerClientIndex] = !!atoi(CMD_ARGV(1)); + g_bWantModEnable[playerClientIndex] = false; + //UpdateMasks(); + return true; + } + else + { + return false; + } +} + + +void CVoiceGameMgr::UpdateMasks() +{ + m_UpdateInterval = 0; + + bool bAllTalk = !!g_engfuncs.pfnCVarGetFloat( "sv_alltalk" ); + + for(int iClient=0; iClient < m_nMaxPlayers; iClient++) + { + CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient+1); + if(!pEnt || !pEnt->IsPlayer()) + continue; + + // Request the state of their "VModEnable" cvar. + if(g_bWantModEnable[iClient]) + { + MESSAGE_BEGIN(MSG_ONE, m_msgRequestState, NULL, pEnt->pev); + MESSAGE_END(); + } + + CBasePlayer *pPlayer = (CBasePlayer*)pEnt; + + CPlayerBitVec gameRulesMask; + if( g_PlayerModEnable[iClient] ) + { + // Build a mask of who they can hear based on the game rules. + for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) + { + CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient+1); + if(pEnt && pEnt->IsPlayer() && + (bAllTalk || m_pHelper->CanPlayerHearPlayer(pPlayer, (CBasePlayer*)pEnt)) ) + { + gameRulesMask[iOtherClient] = true; + } + } + } + + // If this is different from what the client has, send an update. + if(gameRulesMask != g_SentGameRulesMasks[iClient] || + g_BanMasks[iClient] != g_SentBanMasks[iClient]) + { + g_SentGameRulesMasks[iClient] = gameRulesMask; + g_SentBanMasks[iClient] = g_BanMasks[iClient]; + + MESSAGE_BEGIN(MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev); + int dw; + for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + { + WRITE_LONG(gameRulesMask.GetDWord(dw)); + WRITE_LONG(g_BanMasks[iClient].GetDWord(dw)); + } + MESSAGE_END(); + } + + // Tell the engine. + for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) + { + bool bCanHear = gameRulesMask[iOtherClient] && !g_BanMasks[iClient][iOtherClient]; + g_engfuncs.pfnVoice_SetClientListening(iClient+1, iOtherClient+1, bCanHear); + } + } +} diff --git a/game_shared/voice_gamemgr.h b/game_shared/voice_gamemgr.h index 7a0ee1f..2bf0d5f 100644 --- a/game_shared/voice_gamemgr.h +++ b/game_shared/voice_gamemgr.h @@ -1,83 +1,83 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef VOICE_GAMEMGR_H -#define VOICE_GAMEMGR_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - - -#include "voice_common.h" - - -class CGameRules; -class CBasePlayer; - - -class IVoiceGameMgrHelper -{ -public: - virtual ~IVoiceGameMgrHelper() {} - - // Called each frame to determine which players are allowed to hear each other. This overrides - // whatever squelch settings players have. - virtual bool CanPlayerHearPlayer(CBasePlayer *pListener, CBasePlayer *pTalker) = 0; -}; - - -// CVoiceGameMgr manages which clients can hear which other clients. -class CVoiceGameMgr -{ -public: - CVoiceGameMgr(); - virtual ~CVoiceGameMgr(); - - bool Init( - IVoiceGameMgrHelper *m_pHelper, - int maxClients - ); - - void SetHelper(IVoiceGameMgrHelper *pHelper); - - // Updates which players can hear which other players. - // If gameplay mode is DM, then only players within the PVS can hear each other. - // If gameplay mode is teamplay, then only players on the same team can hear each other. - // Player masks are always applied. - void Update(double frametime); - - // Called when a new client connects (unsquelches its entity for everyone). - void ClientConnected(struct edict_s *pEdict); - - // Called on ClientCommand. Checks for the squelch and unsquelch commands. - // Returns true if it handled the command. - bool ClientCommand(CBasePlayer *pPlayer, const char *cmd); - - // Called to determine if the Receiver has muted (blocked) the Sender - // Returns true if the receiver has blocked the sender - bool PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender); - - -private: - - // Force it to update the client masks. - void UpdateMasks(); - - -private: - int m_msgPlayerVoiceMask; - int m_msgRequestState; - - IVoiceGameMgrHelper *m_pHelper; - int m_nMaxPlayers; - double m_UpdateInterval; // How long since the last update. -}; - - -#endif // VOICE_GAMEMGR_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VOICE_GAMEMGR_H +#define VOICE_GAMEMGR_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + + +#include "voice_common.h" + + +class CGameRules; +class CBasePlayer; + + +class IVoiceGameMgrHelper +{ +public: + virtual ~IVoiceGameMgrHelper() {} + + // Called each frame to determine which players are allowed to hear each other. This overrides + // whatever squelch settings players have. + virtual bool CanPlayerHearPlayer(CBasePlayer *pListener, CBasePlayer *pTalker) = 0; +}; + + +// CVoiceGameMgr manages which clients can hear which other clients. +class CVoiceGameMgr +{ +public: + CVoiceGameMgr(); + virtual ~CVoiceGameMgr(); + + bool Init( + IVoiceGameMgrHelper *m_pHelper, + int maxClients + ); + + void SetHelper(IVoiceGameMgrHelper *pHelper); + + // Updates which players can hear which other players. + // If gameplay mode is DM, then only players within the PVS can hear each other. + // If gameplay mode is teamplay, then only players on the same team can hear each other. + // Player masks are always applied. + void Update(double frametime); + + // Called when a new client connects (unsquelches its entity for everyone). + void ClientConnected(struct edict_s *pEdict); + + // Called on ClientCommand. Checks for the squelch and unsquelch commands. + // Returns true if it handled the command. + bool ClientCommand(CBasePlayer *pPlayer, const char *cmd); + + // Called to determine if the Receiver has muted (blocked) the Sender + // Returns true if the receiver has blocked the sender + bool PlayerHasBlockedPlayer(CBasePlayer *pReceiver, CBasePlayer *pSender); + + +private: + + // Force it to update the client masks. + void UpdateMasks(); + + +private: + int m_msgPlayerVoiceMask; + int m_msgRequestState; + + IVoiceGameMgrHelper *m_pHelper; + int m_nMaxPlayers; + double m_UpdateInterval; // How long since the last update. +}; + + +#endif // VOICE_GAMEMGR_H diff --git a/game_shared/voice_status.cpp b/game_shared/voice_status.cpp index e5378d0..77dd42a 100644 --- a/game_shared/voice_status.cpp +++ b/game_shared/voice_status.cpp @@ -1,874 +1,874 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// There are hud.h's coming out of the woodwork so this ensures that we get the right one. -#if defined( DMC_BUILD ) - #include "../dmc/cl_dll/hud.h" - #include "../dmc/cl_dll/cl_util.h" -#elif defined( RICOCHET_BUILD ) - #include "../ricochet/cl_dll/hud.h" - #include "../ricochet/cl_dll/cl_util.h" -#else - #include "../cl_dll/hud.h" - #include "../cl_dll/cl_util.h" -#endif - -#include -#include -#include - -#if defined( DMC_BUILD ) - #include "../dmc/cl_dll/parsemsg.h" - #include "../dmc/cl_dll/hud_servers.h" - #include "../dmc/cl_dll/demo.h" -#elif defined( RICOCHET_BUILD ) - #include "../ricochet/cl_dll/parsemsg.h" - #include "../ricochet/cl_dll/hud_servers.h" - #include "../ricochet/cl_dll/demo.h" -#else - #include "../cl_dll/parsemsg.h" - #include "../cl_dll/hud_servers.h" - #include "../cl_dll/demo.h" -#endif - -#include "demo_api.h" -#include "voice_status.h" -#include "r_efx.h" -#include "entity_types.h" -#include "VGUI_ActionSignal.h" -#include "VGUI_Scheme.h" -#include "VGUI_TextImage.h" -#include "vgui_loadtga.h" -#include "vgui_helpers.h" -#include "vgui_mousecode.h" - - - -using namespace vgui; - - -extern int cam_thirdperson; - - -#define VOICE_MODEL_INTERVAL 0.3 -#define SCOREBOARD_BLINK_FREQUENCY 0.3 // How often to blink the scoreboard icons. -#define SQUELCHOSCILLATE_PER_SECOND 2.0f - - -extern BitmapTGA *LoadTGA( const char* pImageName ); - - - -// ---------------------------------------------------------------------- // -// The voice manager for the client. -// ---------------------------------------------------------------------- // -CVoiceStatus g_VoiceStatus; - -CVoiceStatus* GetClientVoiceMgr() -{ - return &g_VoiceStatus; -} - - - -// ---------------------------------------------------------------------- // -// CVoiceStatus. -// ---------------------------------------------------------------------- // - -static CVoiceStatus *g_pInternalVoiceStatus = NULL; - -int __MsgFunc_VoiceMask(const char *pszName, int iSize, void *pbuf) -{ - if(g_pInternalVoiceStatus) - g_pInternalVoiceStatus->HandleVoiceMaskMsg(iSize, pbuf); - - return 1; -} - -int __MsgFunc_ReqState(const char *pszName, int iSize, void *pbuf) -{ - if(g_pInternalVoiceStatus) - g_pInternalVoiceStatus->HandleReqStateMsg(iSize, pbuf); - - return 1; -} - - -int g_BannedPlayerPrintCount; -void ForEachBannedPlayer(char id[16]) -{ - char str[256]; - sprintf(str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n", - g_BannedPlayerPrintCount++, - id[0], id[1], id[2], id[3], - id[4], id[5], id[6], id[7], - id[8], id[9], id[10], id[11], - id[12], id[13], id[14], id[15] - ); - strupr(str); - gEngfuncs.pfnConsolePrint(str); -} - - -void ShowBannedCallback() -{ - if(g_pInternalVoiceStatus) - { - g_BannedPlayerPrintCount = 0; - gEngfuncs.pfnConsolePrint("------- BANNED PLAYERS -------\n"); - g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer(ForEachBannedPlayer); - gEngfuncs.pfnConsolePrint("------------------------------\n"); - } -} - - -// ---------------------------------------------------------------------- // -// CVoiceStatus. -// ---------------------------------------------------------------------- // - -CVoiceStatus::CVoiceStatus() -{ - m_bBanMgrInitialized = false; - m_LastUpdateServerState = 0; - - m_pSpeakerLabelIcon = NULL; - m_pScoreboardNeverSpoken = NULL; - m_pScoreboardNotSpeaking = NULL; - m_pScoreboardSpeaking = NULL; - m_pScoreboardSpeaking2 = NULL; - m_pScoreboardSquelch = NULL; - m_pScoreboardBanned = NULL; - - m_pLocalBitmap = NULL; - m_pAckBitmap = NULL; - - m_bTalking = m_bServerAcked = false; - - memset(m_pBanButtons, 0, sizeof(m_pBanButtons)); - - m_bServerModEnable = -1; - - m_pchGameDir = NULL; -} - - -CVoiceStatus::~CVoiceStatus() -{ - g_pInternalVoiceStatus = NULL; - - for(int i=0; i < MAX_VOICE_SPEAKERS; i++) - { - delete m_Labels[i].m_pLabel; - m_Labels[i].m_pLabel = NULL; - - delete m_Labels[i].m_pIcon; - m_Labels[i].m_pIcon = NULL; - - delete m_Labels[i].m_pBackground; - m_Labels[i].m_pBackground = NULL; - } - - delete m_pLocalLabel; - m_pLocalLabel = NULL; - - FreeBitmaps(); - - if(m_pchGameDir) - { - if(m_bBanMgrInitialized) - { - m_BanMgr.SaveState(m_pchGameDir); - } - - free(m_pchGameDir); - } -} - - -int CVoiceStatus::Init( - IVoiceStatusHelper *pHelper, - Panel **pParentPanel) -{ - // Setup the voice_modenable cvar. - gEngfuncs.pfnRegisterVariable("voice_modenable", "1", FCVAR_ARCHIVE); - - gEngfuncs.pfnRegisterVariable("voice_clientdebug", "0", 0); - - gEngfuncs.pfnAddCommand("voice_showbanned", ShowBannedCallback); - - if(gEngfuncs.pfnGetGameDirectory()) - { - m_BanMgr.Init(gEngfuncs.pfnGetGameDirectory()); - m_bBanMgrInitialized = true; - } - - assert(!g_pInternalVoiceStatus); - g_pInternalVoiceStatus = this; - - m_BlinkTimer = 0; - m_VoiceHeadModel = NULL; - memset(m_Labels, 0, sizeof(m_Labels)); - - for(int i=0; i < MAX_VOICE_SPEAKERS; i++) - { - CVoiceLabel *pLabel = &m_Labels[i]; - - pLabel->m_pBackground = new Label(""); - - if(pLabel->m_pLabel = new Label("")) - { - pLabel->m_pLabel->setVisible( true ); - pLabel->m_pLabel->setFont( Scheme::sf_primary2 ); - pLabel->m_pLabel->setTextAlignment( Label::a_east ); - pLabel->m_pLabel->setContentAlignment( Label::a_east ); - pLabel->m_pLabel->setParent( pLabel->m_pBackground ); - } - - if( pLabel->m_pIcon = new ImagePanel( NULL ) ) - { - pLabel->m_pIcon->setVisible( true ); - pLabel->m_pIcon->setParent( pLabel->m_pBackground ); - } - - pLabel->m_clientindex = -1; - } - - m_pLocalLabel = new ImagePanel(NULL); - - m_bInSquelchMode = false; - - m_pHelper = pHelper; - m_pParentPanel = pParentPanel; - gHUD.AddHudElem(this); - m_iFlags = HUD_ACTIVE; - HOOK_MESSAGE(VoiceMask); - HOOK_MESSAGE(ReqState); - - // Cache the game directory for use when we shut down - const char *pchGameDirT = gEngfuncs.pfnGetGameDirectory(); - m_pchGameDir = (char *)malloc(strlen(pchGameDirT) + 1); - strcpy(m_pchGameDir, pchGameDirT); - - return 1; -} - - -int CVoiceStatus::VidInit() -{ - FreeBitmaps(); - - - if( m_pLocalBitmap = vgui_LoadTGA("gfx/vgui/icntlk_pl.tga") ) - { - m_pLocalBitmap->setColor(Color(255,255,255,135)); - } - - if( m_pAckBitmap = vgui_LoadTGA("gfx/vgui/icntlk_sv.tga") ) - { - m_pAckBitmap->setColor(Color(255,255,255,135)); // Give just a tiny bit of translucency so software draws correctly. - } - - m_pLocalLabel->setImage( m_pLocalBitmap ); - m_pLocalLabel->setVisible( false ); - - - if( m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha("gfx/vgui/speaker4.tga" ) ) - m_pSpeakerLabelIcon->setColor( Color(255,255,255,1) ); // Give just a tiny bit of translucency so software draws correctly. - - if (m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker1.tga")) - m_pScoreboardNeverSpoken->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker2.tga")) - m_pScoreboardNotSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker3.tga")) - m_pScoreboardSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker4.tga")) - m_pScoreboardSpeaking2->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardSquelch = vgui_LoadTGA("gfx/vgui/icntlk_squelch.tga")) - m_pScoreboardSquelch->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - if(m_pScoreboardBanned = vgui_LoadTGA("gfx/vgui/640_voiceblocked.tga")) - m_pScoreboardBanned->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. - - // Figure out the voice head model height. - m_VoiceHeadModelHeight = 45; - char *pFile = (char *)gEngfuncs.COM_LoadFile("scripts/voicemodel.txt", 5, NULL); - if(pFile) - { - char token[4096]; - gEngfuncs.COM_ParseFile(pFile, token); - if(token[0] >= '0' && token[0] <= '9') - { - m_VoiceHeadModelHeight = (float)atof(token); - } - - gEngfuncs.COM_FreeFile(pFile); - } - - m_VoiceHeadModel = gEngfuncs.pfnSPR_Load("sprites/voiceicon.spr"); - return TRUE; -} - - -void CVoiceStatus::Frame(double frametime) -{ - // check server banned players once per second - if(gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1) - { - UpdateServerState(false); - } - - m_BlinkTimer += frametime; - - // Update speaker labels. - if( m_pHelper->CanShowSpeakerLabels() ) - { - for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) - m_Labels[i].m_pBackground->setVisible( m_Labels[i].m_clientindex != -1 ); - } - else - { - for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) - m_Labels[i].m_pBackground->setVisible( false ); - } - - for(int i=0; i < VOICE_MAX_PLAYERS; i++) - UpdateBanButton(i); -} - - -void CVoiceStatus::CreateEntities() -{ - if(!m_VoiceHeadModel) - return; - - cl_entity_t *localPlayer = gEngfuncs.GetLocalPlayer(); - - int iOutModel = 0; - for(int i=0; i < VOICE_MAX_PLAYERS; i++) - { - if(!m_VoicePlayers[i]) - continue; - - cl_entity_s *pClient = gEngfuncs.GetEntityByIndex(i+1); - - // Don't show an icon if the player is not in our PVS. - if(!pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum) - continue; - - // Don't show an icon for dead or spectating players (ie: invisible entities). - if(pClient->curstate.effects & EF_NODRAW) - continue; - - // Don't show an icon for the local player unless we're in thirdperson mode. - if(pClient == localPlayer && !cam_thirdperson) - continue; - - cl_entity_s *pEnt = &m_VoiceHeadModels[iOutModel]; - ++iOutModel; - - memset(pEnt, 0, sizeof(*pEnt)); - - pEnt->curstate.rendermode = kRenderTransAdd; - pEnt->curstate.renderamt = 255; - pEnt->baseline.renderamt = 255; - pEnt->curstate.renderfx = kRenderFxNoDissipation; - pEnt->curstate.framerate = 1; - pEnt->curstate.frame = 0; - pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer(m_VoiceHeadModel); - pEnt->angles[0] = pEnt->angles[1] = pEnt->angles[2] = 0; - pEnt->curstate.scale = 0.5f; - - pEnt->origin[0] = pEnt->origin[1] = 0; - pEnt->origin[2] = 45; - - VectorAdd(pEnt->origin, pClient->origin, pEnt->origin); - - // Tell the engine. - gEngfuncs.CL_CreateVisibleEntity(ET_NORMAL, pEnt); - } -} - - -void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking) -{ - if(!*m_pParentPanel) - return; - - if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) - { - char msg[256]; - _snprintf( msg, sizeof(msg), "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking ); - gEngfuncs.pfnConsolePrint( msg ); - } - - // Is it the local player talking? - if( entindex == -1 ) - { - m_bTalking = !!bTalking; - if( bTalking ) - { - // Enable voice for them automatically if they try to talk. - gEngfuncs.pfnClientCmd( "voice_modenable 1" ); - } - } - else if( entindex == -2 ) - { - m_bServerAcked = !!bTalking; - } - else if(entindex >= 0 && entindex <= VOICE_MAX_PLAYERS) - { - int iClient = entindex - 1; - if(iClient < 0) - return; - - CVoiceLabel *pLabel = FindVoiceLabel(iClient); - if(bTalking) - { - m_VoicePlayers[iClient] = true; - m_VoiceEnabledPlayers[iClient] = true; - - // If we don't have a label for this guy yet, then create one. - if(!pLabel) - { - if(pLabel = GetFreeVoiceLabel()) - { - // Get the name from the engine. - hud_player_info_t info; - memset(&info, 0, sizeof(info)); - GetPlayerInfo(entindex, &info); - - char paddedName[512]; - _snprintf(paddedName, sizeof(paddedName), "%s ", info.name); - - int color[3]; - m_pHelper->GetPlayerTextColor( entindex, color ); - - if( pLabel->m_pBackground ) - { - pLabel->m_pBackground->setBgColor( color[0], color[1], color[2], 135 ); - pLabel->m_pBackground->setParent( *m_pParentPanel ); - pLabel->m_pBackground->setVisible( m_pHelper->CanShowSpeakerLabels() ); - } - - if( pLabel->m_pLabel ) - { - pLabel->m_pLabel->setFgColor( 255, 255, 255, 0 ); - pLabel->m_pLabel->setBgColor( 0, 0, 0, 255 ); - pLabel->m_pLabel->setText( paddedName ); - } - - pLabel->m_clientindex = iClient; - } - } - } - else - { - m_VoicePlayers[iClient] = false; - - // If we have a label for this guy, kill it. - if(pLabel) - { - pLabel->m_pBackground->setVisible(false); - pLabel->m_clientindex = -1; - } - } - } - - RepositionLabels(); -} - - -void CVoiceStatus::UpdateServerState(bool bForce) -{ - // Can't do anything when we're not in a level. - char const *pLevelName = gEngfuncs.pfnGetLevelName(); - if( pLevelName[0] == 0 ) - { - if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) - { - gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: pLevelName[0]==0\n" ); - } - - return; - } - - int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat("voice_modenable"); - if(bForce || m_bServerModEnable != bCVarModEnable) - { - m_bServerModEnable = bCVarModEnable; - - char str[256]; - _snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable); - ServerCmd(str); - - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - char msg[256]; - sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); - gEngfuncs.pfnConsolePrint(msg); - } - } - - char str[2048]; - sprintf(str, "vban"); - bool bChange = false; - - for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - unsigned long serverBanMask = 0; - unsigned long banMask = 0; - for(unsigned long i=0; i < 32; i++) - { - char playerID[16]; - if(!gEngfuncs.GetPlayerUniqueID(i+1, playerID)) - continue; - - if(m_BanMgr.GetPlayerBan(playerID)) - banMask |= 1 << i; - - if(m_ServerBannedPlayers[dw*32 + i]) - serverBanMask |= 1 << i; - } - - if(serverBanMask != banMask) - bChange = true; - - // Ok, the server needs to be updated. - char numStr[512]; - sprintf(numStr, " %x", banMask); - strcat(str, numStr); - } - - if(bChange || bForce) - { - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - char msg[256]; - sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); - gEngfuncs.pfnConsolePrint(msg); - } - - gEngfuncs.pfnServerCmdUnreliable(str); // Tell the server.. - } - else - { - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: no change\n" ); - } - } - - m_LastUpdateServerState = gEngfuncs.GetClientTime(); -} - -void CVoiceStatus::UpdateSpeakerImage(Label *pLabel, int iPlayer) -{ - m_pBanButtons[iPlayer-1] = pLabel; - UpdateBanButton(iPlayer-1); -} - -void CVoiceStatus::UpdateBanButton(int iClient) -{ - Label *pPanel = m_pBanButtons[iClient]; - - if (!pPanel) - return; - - char playerID[16]; - extern bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] ); - if(!HACK_GetPlayerUniqueID(iClient+1, playerID)) - return; - - // Figure out if it's blinking or not. - bool bBlink = fmod(m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY*2) < SCOREBOARD_BLINK_FREQUENCY; - bool bTalking = !!m_VoicePlayers[iClient]; - bool bBanned = m_BanMgr.GetPlayerBan(playerID); - bool bNeverSpoken = !m_VoiceEnabledPlayers[iClient]; - - // Get the appropriate image to display on the panel. - if (bBanned) - { - pPanel->setImage(m_pScoreboardBanned); - } - else if (bTalking) - { - if (bBlink) - { - pPanel->setImage(m_pScoreboardSpeaking2); - } - else - { - pPanel->setImage(m_pScoreboardSpeaking); - } - pPanel->setFgColor(255, 170, 0, 1); - } - else if (bNeverSpoken) - { - pPanel->setImage(m_pScoreboardNeverSpoken); - pPanel->setFgColor(100, 100, 100, 1); - } - else - { - pPanel->setImage(m_pScoreboardNotSpeaking); - } -} - - -void CVoiceStatus::HandleVoiceMaskMsg(int iSize, void *pbuf) -{ - BEGIN_READ( pbuf, iSize ); - - unsigned long dw; - for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - m_AudiblePlayers.SetDWord(dw, (unsigned long)READ_LONG()); - m_ServerBannedPlayers.SetDWord(dw, (unsigned long)READ_LONG()); - - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - char str[256]; - gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleVoiceMaskMsg\n"); - - sprintf(str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); - gEngfuncs.pfnConsolePrint(str); - - sprintf(str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); - gEngfuncs.pfnConsolePrint(str); - } - } - - m_bServerModEnable = READ_BYTE(); -} - -void CVoiceStatus::HandleReqStateMsg(int iSize, void *pbuf) -{ - if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleReqStateMsg\n"); - } - - UpdateServerState(true); -} - -void CVoiceStatus::StartSquelchMode() -{ - if(m_bInSquelchMode) - return; - - m_bInSquelchMode = true; - m_pHelper->UpdateCursorState(); -} - -void CVoiceStatus::StopSquelchMode() -{ - m_bInSquelchMode = false; - m_pHelper->UpdateCursorState(); -} - -bool CVoiceStatus::IsInSquelchMode() -{ - return m_bInSquelchMode; -} - -CVoiceLabel* CVoiceStatus::FindVoiceLabel(int clientindex) -{ - for(int i=0; i < MAX_VOICE_SPEAKERS; i++) - { - if(m_Labels[i].m_clientindex == clientindex) - return &m_Labels[i]; - } - - return NULL; -} - - -CVoiceLabel* CVoiceStatus::GetFreeVoiceLabel() -{ - return FindVoiceLabel(-1); -} - - -void CVoiceStatus::RepositionLabels() -{ - // find starting position to draw from, along right-hand side of screen - int y = ScreenHeight / 2; - - int iconWide = 8, iconTall = 8; - if( m_pSpeakerLabelIcon ) - { - m_pSpeakerLabelIcon->getSize( iconWide, iconTall ); - } - - // Reposition active labels. - for(int i = 0; i < MAX_VOICE_SPEAKERS; i++) - { - CVoiceLabel *pLabel = &m_Labels[i]; - - if( pLabel->m_clientindex == -1 || !pLabel->m_pLabel ) - { - if( pLabel->m_pBackground ) - pLabel->m_pBackground->setVisible( false ); - - continue; - } - - int textWide, textTall; - pLabel->m_pLabel->getContentSize( textWide, textTall ); - - // Don't let it stretch too far across their screen. - if( textWide > (ScreenWidth*2)/3 ) - textWide = (ScreenWidth*2)/3; - - // Setup the background label to fit everything in. - int border = 2; - int bgWide = textWide + iconWide + border*3; - int bgTall = max( textTall, iconTall ) + border*2; - pLabel->m_pBackground->setBounds( ScreenWidth - bgWide - 8, y, bgWide, bgTall ); - - // Put the text at the left. - pLabel->m_pLabel->setBounds( border, (bgTall - textTall) / 2, textWide, textTall ); - - // Put the icon at the right. - int iconLeft = border + textWide + border; - int iconTop = (bgTall - iconTall) / 2; - if( pLabel->m_pIcon ) - { - pLabel->m_pIcon->setImage( m_pSpeakerLabelIcon ); - pLabel->m_pIcon->setBounds( iconLeft, iconTop, iconWide, iconTall ); - } - - y += bgTall + 2; - } - - if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && (m_bTalking || m_bServerAcked) ) - { - m_pLocalLabel->setParent(*m_pParentPanel); - m_pLocalLabel->setVisible( true ); - - if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) - m_pLocalLabel->setImage( m_pAckBitmap ); - else - m_pLocalLabel->setImage( m_pLocalBitmap ); - - int sizeX, sizeY; - m_pLocalBitmap->getSize(sizeX, sizeY); - - int local_xPos = ScreenWidth - sizeX - 10; - int local_yPos = m_pHelper->GetAckIconHeight() - sizeY; - - m_pLocalLabel->setPos( local_xPos, local_yPos ); - } - else - { - m_pLocalLabel->setVisible( false ); - } -} - - -void CVoiceStatus::FreeBitmaps() -{ - // Delete all the images we have loaded. - delete m_pLocalBitmap; - m_pLocalBitmap = NULL; - - delete m_pAckBitmap; - m_pAckBitmap = NULL; - - delete m_pSpeakerLabelIcon; - m_pSpeakerLabelIcon = NULL; - - delete m_pScoreboardNeverSpoken; - m_pScoreboardNeverSpoken = NULL; - - delete m_pScoreboardNotSpeaking; - m_pScoreboardNotSpeaking = NULL; - - delete m_pScoreboardSpeaking; - m_pScoreboardSpeaking = NULL; - - delete m_pScoreboardSpeaking2; - m_pScoreboardSpeaking2 = NULL; - - delete m_pScoreboardSquelch; - m_pScoreboardSquelch = NULL; - - delete m_pScoreboardBanned; - m_pScoreboardBanned = NULL; - - // Clear references to the images in panels. - for(int i=0; i < VOICE_MAX_PLAYERS; i++) - { - if (m_pBanButtons[i]) - { - m_pBanButtons[i]->setImage(NULL); - } - } - - if(m_pLocalLabel) - m_pLocalLabel->setImage(NULL); -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the target client has been banned -// Input : playerID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerBlocked(int iPlayer) -{ - char playerID[16]; - if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) - return false; - - return m_BanMgr.GetPlayerBan(playerID); -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the player can't hear the other client due to game rules (eg. the other team) -// Input : playerID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerAudible(int iPlayer) -{ - return !!m_AudiblePlayers[iPlayer-1]; -} - -//----------------------------------------------------------------------------- -// Purpose: blocks/unblocks the target client from being heard -// Input : playerID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CVoiceStatus::SetPlayerBlockedState(int iPlayer, bool blocked) -{ - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 1\n" ); - } - - char playerID[16]; - if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) - return; - - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 2\n" ); - } - - // Squelch or (try to) unsquelch this player. - if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) - { - char str[256]; - sprintf(str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(playerID)); - gEngfuncs.pfnConsolePrint(str); - } - - m_BanMgr.SetPlayerBan( playerID, blocked ); - UpdateServerState(false); -} +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// There are hud.h's coming out of the woodwork so this ensures that we get the right one. +#if defined( DMC_BUILD ) + #include "../dmc/cl_dll/hud.h" + #include "../dmc/cl_dll/cl_util.h" +#elif defined( RICOCHET_BUILD ) + #include "../ricochet/cl_dll/hud.h" + #include "../ricochet/cl_dll/cl_util.h" +#else + #include "../cl_dll/hud.h" + #include "../cl_dll/cl_util.h" +#endif + +#include +#include +#include + +#if defined( DMC_BUILD ) + #include "../dmc/cl_dll/parsemsg.h" + #include "../dmc/cl_dll/hud_servers.h" + #include "../dmc/cl_dll/demo.h" +#elif defined( RICOCHET_BUILD ) + #include "../ricochet/cl_dll/parsemsg.h" + #include "../ricochet/cl_dll/hud_servers.h" + #include "../ricochet/cl_dll/demo.h" +#else + #include "../cl_dll/parsemsg.h" + #include "../cl_dll/hud_servers.h" + #include "../cl_dll/demo.h" +#endif + +#include "demo_api.h" +#include "voice_status.h" +#include "r_efx.h" +#include "entity_types.h" +#include "VGUI_ActionSignal.h" +#include "VGUI_Scheme.h" +#include "VGUI_TextImage.h" +#include "vgui_loadtga.h" +#include "vgui_helpers.h" +#include "vgui_mousecode.h" + + + +using namespace vgui; + + +extern int cam_thirdperson; + + +#define VOICE_MODEL_INTERVAL 0.3 +#define SCOREBOARD_BLINK_FREQUENCY 0.3 // How often to blink the scoreboard icons. +#define SQUELCHOSCILLATE_PER_SECOND 2.0f + + +extern BitmapTGA *LoadTGA( const char* pImageName ); + + + +// ---------------------------------------------------------------------- // +// The voice manager for the client. +// ---------------------------------------------------------------------- // +CVoiceStatus g_VoiceStatus; + +CVoiceStatus* GetClientVoiceMgr() +{ + return &g_VoiceStatus; +} + + + +// ---------------------------------------------------------------------- // +// CVoiceStatus. +// ---------------------------------------------------------------------- // + +static CVoiceStatus *g_pInternalVoiceStatus = NULL; + +int __MsgFunc_VoiceMask(const char *pszName, int iSize, void *pbuf) +{ + if(g_pInternalVoiceStatus) + g_pInternalVoiceStatus->HandleVoiceMaskMsg(iSize, pbuf); + + return 1; +} + +int __MsgFunc_ReqState(const char *pszName, int iSize, void *pbuf) +{ + if(g_pInternalVoiceStatus) + g_pInternalVoiceStatus->HandleReqStateMsg(iSize, pbuf); + + return 1; +} + + +int g_BannedPlayerPrintCount; +void ForEachBannedPlayer(char id[16]) +{ + char str[256]; + sprintf(str, "Ban %d: %2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x\n", + g_BannedPlayerPrintCount++, + id[0], id[1], id[2], id[3], + id[4], id[5], id[6], id[7], + id[8], id[9], id[10], id[11], + id[12], id[13], id[14], id[15] + ); + strupr(str); + gEngfuncs.pfnConsolePrint(str); +} + + +void ShowBannedCallback() +{ + if(g_pInternalVoiceStatus) + { + g_BannedPlayerPrintCount = 0; + gEngfuncs.pfnConsolePrint("------- BANNED PLAYERS -------\n"); + g_pInternalVoiceStatus->m_BanMgr.ForEachBannedPlayer(ForEachBannedPlayer); + gEngfuncs.pfnConsolePrint("------------------------------\n"); + } +} + + +// ---------------------------------------------------------------------- // +// CVoiceStatus. +// ---------------------------------------------------------------------- // + +CVoiceStatus::CVoiceStatus() +{ + m_bBanMgrInitialized = false; + m_LastUpdateServerState = 0; + + m_pSpeakerLabelIcon = NULL; + m_pScoreboardNeverSpoken = NULL; + m_pScoreboardNotSpeaking = NULL; + m_pScoreboardSpeaking = NULL; + m_pScoreboardSpeaking2 = NULL; + m_pScoreboardSquelch = NULL; + m_pScoreboardBanned = NULL; + + m_pLocalBitmap = NULL; + m_pAckBitmap = NULL; + + m_bTalking = m_bServerAcked = false; + + memset(m_pBanButtons, 0, sizeof(m_pBanButtons)); + + m_bServerModEnable = -1; + + m_pchGameDir = NULL; +} + + +CVoiceStatus::~CVoiceStatus() +{ + g_pInternalVoiceStatus = NULL; + + for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + { + delete m_Labels[i].m_pLabel; + m_Labels[i].m_pLabel = NULL; + + delete m_Labels[i].m_pIcon; + m_Labels[i].m_pIcon = NULL; + + delete m_Labels[i].m_pBackground; + m_Labels[i].m_pBackground = NULL; + } + + delete m_pLocalLabel; + m_pLocalLabel = NULL; + + FreeBitmaps(); + + if(m_pchGameDir) + { + if(m_bBanMgrInitialized) + { + m_BanMgr.SaveState(m_pchGameDir); + } + + free(m_pchGameDir); + } +} + + +int CVoiceStatus::Init( + IVoiceStatusHelper *pHelper, + Panel **pParentPanel) +{ + // Setup the voice_modenable cvar. + gEngfuncs.pfnRegisterVariable("voice_modenable", "1", FCVAR_ARCHIVE); + + gEngfuncs.pfnRegisterVariable("voice_clientdebug", "0", 0); + + gEngfuncs.pfnAddCommand("voice_showbanned", ShowBannedCallback); + + if(gEngfuncs.pfnGetGameDirectory()) + { + m_BanMgr.Init(gEngfuncs.pfnGetGameDirectory()); + m_bBanMgrInitialized = true; + } + + assert(!g_pInternalVoiceStatus); + g_pInternalVoiceStatus = this; + + m_BlinkTimer = 0; + m_VoiceHeadModel = NULL; + memset(m_Labels, 0, sizeof(m_Labels)); + + for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + { + CVoiceLabel *pLabel = &m_Labels[i]; + + pLabel->m_pBackground = new Label(""); + + if(pLabel->m_pLabel = new Label("")) + { + pLabel->m_pLabel->setVisible( true ); + pLabel->m_pLabel->setFont( Scheme::sf_primary2 ); + pLabel->m_pLabel->setTextAlignment( Label::a_east ); + pLabel->m_pLabel->setContentAlignment( Label::a_east ); + pLabel->m_pLabel->setParent( pLabel->m_pBackground ); + } + + if( pLabel->m_pIcon = new ImagePanel( NULL ) ) + { + pLabel->m_pIcon->setVisible( true ); + pLabel->m_pIcon->setParent( pLabel->m_pBackground ); + } + + pLabel->m_clientindex = -1; + } + + m_pLocalLabel = new ImagePanel(NULL); + + m_bInSquelchMode = false; + + m_pHelper = pHelper; + m_pParentPanel = pParentPanel; + gHUD.AddHudElem(this); + m_iFlags = HUD_ACTIVE; + HOOK_MESSAGE(VoiceMask); + HOOK_MESSAGE(ReqState); + + // Cache the game directory for use when we shut down + const char *pchGameDirT = gEngfuncs.pfnGetGameDirectory(); + m_pchGameDir = (char *)malloc(strlen(pchGameDirT) + 1); + strcpy(m_pchGameDir, pchGameDirT); + + return 1; +} + + +int CVoiceStatus::VidInit() +{ + FreeBitmaps(); + + + if( m_pLocalBitmap = vgui_LoadTGA("gfx/vgui/icntlk_pl.tga") ) + { + m_pLocalBitmap->setColor(Color(255,255,255,135)); + } + + if( m_pAckBitmap = vgui_LoadTGA("gfx/vgui/icntlk_sv.tga") ) + { + m_pAckBitmap->setColor(Color(255,255,255,135)); // Give just a tiny bit of translucency so software draws correctly. + } + + m_pLocalLabel->setImage( m_pLocalBitmap ); + m_pLocalLabel->setVisible( false ); + + + if( m_pSpeakerLabelIcon = vgui_LoadTGANoInvertAlpha("gfx/vgui/speaker4.tga" ) ) + m_pSpeakerLabelIcon->setColor( Color(255,255,255,1) ); // Give just a tiny bit of translucency so software draws correctly. + + if (m_pScoreboardNeverSpoken = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker1.tga")) + m_pScoreboardNeverSpoken->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if(m_pScoreboardNotSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker2.tga")) + m_pScoreboardNotSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if(m_pScoreboardSpeaking = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker3.tga")) + m_pScoreboardSpeaking->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if(m_pScoreboardSpeaking2 = vgui_LoadTGANoInvertAlpha("gfx/vgui/640_speaker4.tga")) + m_pScoreboardSpeaking2->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if(m_pScoreboardSquelch = vgui_LoadTGA("gfx/vgui/icntlk_squelch.tga")) + m_pScoreboardSquelch->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + if(m_pScoreboardBanned = vgui_LoadTGA("gfx/vgui/640_voiceblocked.tga")) + m_pScoreboardBanned->setColor(Color(255,255,255,1)); // Give just a tiny bit of translucency so software draws correctly. + + // Figure out the voice head model height. + m_VoiceHeadModelHeight = 45; + char *pFile = (char *)gEngfuncs.COM_LoadFile("scripts/voicemodel.txt", 5, NULL); + if(pFile) + { + char token[4096]; + gEngfuncs.COM_ParseFile(pFile, token); + if(token[0] >= '0' && token[0] <= '9') + { + m_VoiceHeadModelHeight = (float)atof(token); + } + + gEngfuncs.COM_FreeFile(pFile); + } + + m_VoiceHeadModel = gEngfuncs.pfnSPR_Load("sprites/voiceicon.spr"); + return TRUE; +} + + +void CVoiceStatus::Frame(double frametime) +{ + // check server banned players once per second + if(gEngfuncs.GetClientTime() - m_LastUpdateServerState > 1) + { + UpdateServerState(false); + } + + m_BlinkTimer += frametime; + + // Update speaker labels. + if( m_pHelper->CanShowSpeakerLabels() ) + { + for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) + m_Labels[i].m_pBackground->setVisible( m_Labels[i].m_clientindex != -1 ); + } + else + { + for( int i=0; i < MAX_VOICE_SPEAKERS; i++ ) + m_Labels[i].m_pBackground->setVisible( false ); + } + + for(int i=0; i < VOICE_MAX_PLAYERS; i++) + UpdateBanButton(i); +} + + +void CVoiceStatus::CreateEntities() +{ + if(!m_VoiceHeadModel) + return; + + cl_entity_t *localPlayer = gEngfuncs.GetLocalPlayer(); + + int iOutModel = 0; + for(int i=0; i < VOICE_MAX_PLAYERS; i++) + { + if(!m_VoicePlayers[i]) + continue; + + cl_entity_s *pClient = gEngfuncs.GetEntityByIndex(i+1); + + // Don't show an icon if the player is not in our PVS. + if(!pClient || pClient->curstate.messagenum < localPlayer->curstate.messagenum) + continue; + + // Don't show an icon for dead or spectating players (ie: invisible entities). + if(pClient->curstate.effects & EF_NODRAW) + continue; + + // Don't show an icon for the local player unless we're in thirdperson mode. + if(pClient == localPlayer && !cam_thirdperson) + continue; + + cl_entity_s *pEnt = &m_VoiceHeadModels[iOutModel]; + ++iOutModel; + + memset(pEnt, 0, sizeof(*pEnt)); + + pEnt->curstate.rendermode = kRenderTransAdd; + pEnt->curstate.renderamt = 255; + pEnt->baseline.renderamt = 255; + pEnt->curstate.renderfx = kRenderFxNoDissipation; + pEnt->curstate.framerate = 1; + pEnt->curstate.frame = 0; + pEnt->model = (struct model_s*)gEngfuncs.GetSpritePointer(m_VoiceHeadModel); + pEnt->angles[0] = pEnt->angles[1] = pEnt->angles[2] = 0; + pEnt->curstate.scale = 0.5f; + + pEnt->origin[0] = pEnt->origin[1] = 0; + pEnt->origin[2] = 45; + + VectorAdd(pEnt->origin, pClient->origin, pEnt->origin); + + // Tell the engine. + gEngfuncs.CL_CreateVisibleEntity(ET_NORMAL, pEnt); + } +} + + +void CVoiceStatus::UpdateSpeakerStatus(int entindex, qboolean bTalking) +{ + if(!*m_pParentPanel) + return; + + if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + { + char msg[256]; + _snprintf( msg, sizeof(msg), "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking ); + gEngfuncs.pfnConsolePrint( msg ); + } + + // Is it the local player talking? + if( entindex == -1 ) + { + m_bTalking = !!bTalking; + if( bTalking ) + { + // Enable voice for them automatically if they try to talk. + gEngfuncs.pfnClientCmd( "voice_modenable 1" ); + } + } + else if( entindex == -2 ) + { + m_bServerAcked = !!bTalking; + } + else if(entindex >= 0 && entindex <= VOICE_MAX_PLAYERS) + { + int iClient = entindex - 1; + if(iClient < 0) + return; + + CVoiceLabel *pLabel = FindVoiceLabel(iClient); + if(bTalking) + { + m_VoicePlayers[iClient] = true; + m_VoiceEnabledPlayers[iClient] = true; + + // If we don't have a label for this guy yet, then create one. + if(!pLabel) + { + if(pLabel = GetFreeVoiceLabel()) + { + // Get the name from the engine. + hud_player_info_t info; + memset(&info, 0, sizeof(info)); + GetPlayerInfo(entindex, &info); + + char paddedName[512]; + _snprintf(paddedName, sizeof(paddedName), "%s ", info.name); + + int color[3]; + m_pHelper->GetPlayerTextColor( entindex, color ); + + if( pLabel->m_pBackground ) + { + pLabel->m_pBackground->setBgColor( color[0], color[1], color[2], 135 ); + pLabel->m_pBackground->setParent( *m_pParentPanel ); + pLabel->m_pBackground->setVisible( m_pHelper->CanShowSpeakerLabels() ); + } + + if( pLabel->m_pLabel ) + { + pLabel->m_pLabel->setFgColor( 255, 255, 255, 0 ); + pLabel->m_pLabel->setBgColor( 0, 0, 0, 255 ); + pLabel->m_pLabel->setText( paddedName ); + } + + pLabel->m_clientindex = iClient; + } + } + } + else + { + m_VoicePlayers[iClient] = false; + + // If we have a label for this guy, kill it. + if(pLabel) + { + pLabel->m_pBackground->setVisible(false); + pLabel->m_clientindex = -1; + } + } + } + + RepositionLabels(); +} + + +void CVoiceStatus::UpdateServerState(bool bForce) +{ + // Can't do anything when we're not in a level. + char const *pLevelName = gEngfuncs.pfnGetLevelName(); + if( pLevelName[0] == 0 ) + { + if( gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: pLevelName[0]==0\n" ); + } + + return; + } + + int bCVarModEnable = !!gEngfuncs.pfnGetCvarFloat("voice_modenable"); + if(bForce || m_bServerModEnable != bCVarModEnable) + { + m_bServerModEnable = bCVarModEnable; + + char str[256]; + _snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable); + ServerCmd(str); + + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char msg[256]; + sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); + gEngfuncs.pfnConsolePrint(msg); + } + } + + char str[2048]; + sprintf(str, "vban"); + bool bChange = false; + + for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + { + unsigned long serverBanMask = 0; + unsigned long banMask = 0; + for(unsigned long i=0; i < 32; i++) + { + char playerID[16]; + if(!gEngfuncs.GetPlayerUniqueID(i+1, playerID)) + continue; + + if(m_BanMgr.GetPlayerBan(playerID)) + banMask |= 1 << i; + + if(m_ServerBannedPlayers[dw*32 + i]) + serverBanMask |= 1 << i; + } + + if(serverBanMask != banMask) + bChange = true; + + // Ok, the server needs to be updated. + char numStr[512]; + sprintf(numStr, " %x", banMask); + strcat(str, numStr); + } + + if(bChange || bForce) + { + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char msg[256]; + sprintf(msg, "CVoiceStatus::UpdateServerState: Sending '%s'\n", str); + gEngfuncs.pfnConsolePrint(msg); + } + + gEngfuncs.pfnServerCmdUnreliable(str); // Tell the server.. + } + else + { + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::UpdateServerState: no change\n" ); + } + } + + m_LastUpdateServerState = gEngfuncs.GetClientTime(); +} + +void CVoiceStatus::UpdateSpeakerImage(Label *pLabel, int iPlayer) +{ + m_pBanButtons[iPlayer-1] = pLabel; + UpdateBanButton(iPlayer-1); +} + +void CVoiceStatus::UpdateBanButton(int iClient) +{ + Label *pPanel = m_pBanButtons[iClient]; + + if (!pPanel) + return; + + char playerID[16]; + extern bool HACK_GetPlayerUniqueID( int iPlayer, char playerID[16] ); + if(!HACK_GetPlayerUniqueID(iClient+1, playerID)) + return; + + // Figure out if it's blinking or not. + bool bBlink = fmod(m_BlinkTimer, SCOREBOARD_BLINK_FREQUENCY*2) < SCOREBOARD_BLINK_FREQUENCY; + bool bTalking = !!m_VoicePlayers[iClient]; + bool bBanned = m_BanMgr.GetPlayerBan(playerID); + bool bNeverSpoken = !m_VoiceEnabledPlayers[iClient]; + + // Get the appropriate image to display on the panel. + if (bBanned) + { + pPanel->setImage(m_pScoreboardBanned); + } + else if (bTalking) + { + if (bBlink) + { + pPanel->setImage(m_pScoreboardSpeaking2); + } + else + { + pPanel->setImage(m_pScoreboardSpeaking); + } + pPanel->setFgColor(255, 170, 0, 1); + } + else if (bNeverSpoken) + { + pPanel->setImage(m_pScoreboardNeverSpoken); + pPanel->setFgColor(100, 100, 100, 1); + } + else + { + pPanel->setImage(m_pScoreboardNotSpeaking); + } +} + + +void CVoiceStatus::HandleVoiceMaskMsg(int iSize, void *pbuf) +{ + BEGIN_READ( pbuf, iSize ); + + unsigned long dw; + for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) + { + m_AudiblePlayers.SetDWord(dw, (unsigned long)READ_LONG()); + m_ServerBannedPlayers.SetDWord(dw, (unsigned long)READ_LONG()); + + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char str[256]; + gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleVoiceMaskMsg\n"); + + sprintf(str, " - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); + gEngfuncs.pfnConsolePrint(str); + + sprintf(str, " - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); + gEngfuncs.pfnConsolePrint(str); + } + } + + m_bServerModEnable = READ_BYTE(); +} + +void CVoiceStatus::HandleReqStateMsg(int iSize, void *pbuf) +{ + if(gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint("CVoiceStatus::HandleReqStateMsg\n"); + } + + UpdateServerState(true); +} + +void CVoiceStatus::StartSquelchMode() +{ + if(m_bInSquelchMode) + return; + + m_bInSquelchMode = true; + m_pHelper->UpdateCursorState(); +} + +void CVoiceStatus::StopSquelchMode() +{ + m_bInSquelchMode = false; + m_pHelper->UpdateCursorState(); +} + +bool CVoiceStatus::IsInSquelchMode() +{ + return m_bInSquelchMode; +} + +CVoiceLabel* CVoiceStatus::FindVoiceLabel(int clientindex) +{ + for(int i=0; i < MAX_VOICE_SPEAKERS; i++) + { + if(m_Labels[i].m_clientindex == clientindex) + return &m_Labels[i]; + } + + return NULL; +} + + +CVoiceLabel* CVoiceStatus::GetFreeVoiceLabel() +{ + return FindVoiceLabel(-1); +} + + +void CVoiceStatus::RepositionLabels() +{ + // find starting position to draw from, along right-hand side of screen + int y = ScreenHeight / 2; + + int iconWide = 8, iconTall = 8; + if( m_pSpeakerLabelIcon ) + { + m_pSpeakerLabelIcon->getSize( iconWide, iconTall ); + } + + // Reposition active labels. + for(int i = 0; i < MAX_VOICE_SPEAKERS; i++) + { + CVoiceLabel *pLabel = &m_Labels[i]; + + if( pLabel->m_clientindex == -1 || !pLabel->m_pLabel ) + { + if( pLabel->m_pBackground ) + pLabel->m_pBackground->setVisible( false ); + + continue; + } + + int textWide, textTall; + pLabel->m_pLabel->getContentSize( textWide, textTall ); + + // Don't let it stretch too far across their screen. + if( textWide > (ScreenWidth*2)/3 ) + textWide = (ScreenWidth*2)/3; + + // Setup the background label to fit everything in. + int border = 2; + int bgWide = textWide + iconWide + border*3; + int bgTall = max( textTall, iconTall ) + border*2; + pLabel->m_pBackground->setBounds( ScreenWidth - bgWide - 8, y, bgWide, bgTall ); + + // Put the text at the left. + pLabel->m_pLabel->setBounds( border, (bgTall - textTall) / 2, textWide, textTall ); + + // Put the icon at the right. + int iconLeft = border + textWide + border; + int iconTop = (bgTall - iconTall) / 2; + if( pLabel->m_pIcon ) + { + pLabel->m_pIcon->setImage( m_pSpeakerLabelIcon ); + pLabel->m_pIcon->setBounds( iconLeft, iconTop, iconWide, iconTall ); + } + + y += bgTall + 2; + } + + if( m_pLocalBitmap && m_pAckBitmap && m_pLocalLabel && (m_bTalking || m_bServerAcked) ) + { + m_pLocalLabel->setParent(*m_pParentPanel); + m_pLocalLabel->setVisible( true ); + + if( m_bServerAcked && !!gEngfuncs.pfnGetCvarFloat("voice_clientdebug") ) + m_pLocalLabel->setImage( m_pAckBitmap ); + else + m_pLocalLabel->setImage( m_pLocalBitmap ); + + int sizeX, sizeY; + m_pLocalBitmap->getSize(sizeX, sizeY); + + int local_xPos = ScreenWidth - sizeX - 10; + int local_yPos = m_pHelper->GetAckIconHeight() - sizeY; + + m_pLocalLabel->setPos( local_xPos, local_yPos ); + } + else + { + m_pLocalLabel->setVisible( false ); + } +} + + +void CVoiceStatus::FreeBitmaps() +{ + // Delete all the images we have loaded. + delete m_pLocalBitmap; + m_pLocalBitmap = NULL; + + delete m_pAckBitmap; + m_pAckBitmap = NULL; + + delete m_pSpeakerLabelIcon; + m_pSpeakerLabelIcon = NULL; + + delete m_pScoreboardNeverSpoken; + m_pScoreboardNeverSpoken = NULL; + + delete m_pScoreboardNotSpeaking; + m_pScoreboardNotSpeaking = NULL; + + delete m_pScoreboardSpeaking; + m_pScoreboardSpeaking = NULL; + + delete m_pScoreboardSpeaking2; + m_pScoreboardSpeaking2 = NULL; + + delete m_pScoreboardSquelch; + m_pScoreboardSquelch = NULL; + + delete m_pScoreboardBanned; + m_pScoreboardBanned = NULL; + + // Clear references to the images in panels. + for(int i=0; i < VOICE_MAX_PLAYERS; i++) + { + if (m_pBanButtons[i]) + { + m_pBanButtons[i]->setImage(NULL); + } + } + + if(m_pLocalLabel) + m_pLocalLabel->setImage(NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the target client has been banned +// Input : playerID - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CVoiceStatus::IsPlayerBlocked(int iPlayer) +{ + char playerID[16]; + if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) + return false; + + return m_BanMgr.GetPlayerBan(playerID); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if the player can't hear the other client due to game rules (eg. the other team) +// Input : playerID - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CVoiceStatus::IsPlayerAudible(int iPlayer) +{ + return !!m_AudiblePlayers[iPlayer-1]; +} + +//----------------------------------------------------------------------------- +// Purpose: blocks/unblocks the target client from being heard +// Input : playerID - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +void CVoiceStatus::SetPlayerBlockedState(int iPlayer, bool blocked) +{ + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 1\n" ); + } + + char playerID[16]; + if (!gEngfuncs.GetPlayerUniqueID(iPlayer, playerID)) + return; + + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + gEngfuncs.pfnConsolePrint( "CVoiceStatus::SetPlayerBlockedState part 2\n" ); + } + + // Squelch or (try to) unsquelch this player. + if (gEngfuncs.pfnGetCvarFloat("voice_clientdebug")) + { + char str[256]; + sprintf(str, "CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(playerID)); + gEngfuncs.pfnConsolePrint(str); + } + + m_BanMgr.SetPlayerBan( playerID, blocked ); + UpdateServerState(false); +} diff --git a/game_shared/voice_status.h b/game_shared/voice_status.h index 113b328..dfd4d9b 100644 --- a/game_shared/voice_status.h +++ b/game_shared/voice_status.h @@ -1,232 +1,232 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef VOICE_STATUS_H -#define VOICE_STATUS_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - - -#include "VGUI_Label.h" -#include "VGUI_LineBorder.h" -#include "VGUI_ImagePanel.h" -#include "VGUI_BitmapTGA.h" -#include "VGUI_InputSignal.h" -#include "VGUI_Button.h" -#include "voice_common.h" -#include "cl_entity.h" -#include "voice_banmgr.h" -#include "vgui_checkbutton2.h" -#include "vgui_defaultinputsignal.h" - - -class CVoiceStatus; - - -class CVoiceLabel -{ -public: - vgui::Label *m_pLabel; - vgui::Label *m_pBackground; - vgui::ImagePanel *m_pIcon; // Voice icon next to player name. - int m_clientindex; // Client index of the speaker. -1 if this label isn't being used. -}; - - -// This is provided by each mod to access data that may not be the same across mods. -class IVoiceStatusHelper -{ -public: - virtual ~IVoiceStatusHelper() {} - - // Get RGB color for voice status text about this player. - virtual void GetPlayerTextColor(int entindex, int color[3]) = 0; - - // Force it to update the cursor state. - virtual void UpdateCursorState() = 0; - - // Return the height above the bottom that the voice ack icons should be drawn at. - virtual int GetAckIconHeight() = 0; - - // Return true if the voice manager is allowed to show speaker labels - // (mods usually return false when the scoreboard is up). - virtual bool CanShowSpeakerLabels() = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Holds a color for the shared image -//----------------------------------------------------------------------------- -class VoiceImagePanel : public vgui::ImagePanel -{ - virtual void paintBackground() - { - if (_image!=null) - { - vgui::Color col; - getFgColor(col); - _image->setColor(col); - _image->doPaint(this); - } - } -}; - - -class CVoiceStatus : public CHudBase, public vgui::CDefaultInputSignal -{ -public: - CVoiceStatus(); - virtual ~CVoiceStatus(); - -// CHudBase overrides. -public: - - // Initialize the cl_dll's voice manager. - virtual int Init( - IVoiceStatusHelper *m_pHelper, - vgui::Panel **pParentPanel); - - // ackPosition is the bottom position of where CVoiceStatus will draw the voice acknowledgement labels. - virtual int VidInit(); - - -public: - - // Call from HUD_Frame each frame. - void Frame(double frametime); - - // Called when a player starts or stops talking. - // entindex is -1 to represent the local client talking (before the data comes back from the server). - // When the server acknowledges that the local client is talking, then entindex will be gEngfuncs.GetLocalPlayer(). - // entindex is -2 to represent the local client's voice being acked by the server. - void UpdateSpeakerStatus(int entindex, qboolean bTalking); - - // sets the correct image in the label for the player - void UpdateSpeakerImage(vgui::Label *pLabel, int iPlayer); - - // Call from the HUD_CreateEntities function so it can add sprites above player heads. - void CreateEntities(); - - // Called when the server registers a change to who this client can hear. - void HandleVoiceMaskMsg(int iSize, void *pbuf); - - // The server sends this message initially to tell the client to send their state. - void HandleReqStateMsg(int iSize, void *pbuf); - - -// Squelch mode functions. -public: - - // When you enter squelch mode, pass in - void StartSquelchMode(); - void StopSquelchMode(); - bool IsInSquelchMode(); - - // returns true if the target client has been banned - // playerIndex is of range 1..maxplayers - bool IsPlayerBlocked(int iPlayerIndex); - - // returns false if the player can't hear the other client due to game rules (eg. the other team) - bool IsPlayerAudible(int iPlayerIndex); - - // blocks the target client from being heard - void SetPlayerBlockedState(int iPlayerIndex, bool blocked); - -public: - - CVoiceLabel* FindVoiceLabel(int clientindex); // Find a CVoiceLabel representing the specified speaker. - // Returns NULL if none. - // entindex can be -1 if you want a currently-unused voice label. - CVoiceLabel* GetFreeVoiceLabel(); // Get an unused voice label. Returns NULL if none. - - void RepositionLabels(); - - void FreeBitmaps(); - - void UpdateServerState(bool bForce); - - // Update the button artwork to reflect the client's current state. - void UpdateBanButton(int iClient); - - -public: - - enum {MAX_VOICE_SPEAKERS=7}; - - float m_LastUpdateServerState; // Last time we called this function. - int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar. - - vgui::Panel **m_pParentPanel; - CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index. - - // This is the gamerules-defined list of players that you can hear. It is based on what teams people are on - // and is totally separate from the ban list. Indexed by client index. - CPlayerBitVec m_AudiblePlayers; - - // Players who have spoken at least once in the game so far - CPlayerBitVec m_VoiceEnabledPlayers; - - // This is who the server THINKS we have banned (it can become incorrect when a new player arrives on the server). - // It is checked periodically, and the server is told to squelch or unsquelch the appropriate players. - CPlayerBitVec m_ServerBannedPlayers; - - cl_entity_s m_VoiceHeadModels[VOICE_MAX_PLAYERS]; // These aren't necessarily in the order of players. They are just - // a place for it to put data in during CreateEntities. - - IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this. - - - // Scoreboard icons. - double m_BlinkTimer; // Blink scoreboard icons.. - vgui::BitmapTGA *m_pScoreboardNeverSpoken; - vgui::BitmapTGA *m_pScoreboardNotSpeaking; - vgui::BitmapTGA *m_pScoreboardSpeaking; - vgui::BitmapTGA *m_pScoreboardSpeaking2; - vgui::BitmapTGA *m_pScoreboardSquelch; - vgui::BitmapTGA *m_pScoreboardBanned; - - vgui::Label *m_pBanButtons[VOICE_MAX_PLAYERS]; // scoreboard buttons. - - // Squelch mode stuff. - bool m_bInSquelchMode; - - HSPRITE m_VoiceHeadModel; // Voice head model (goes above players who are speaking). - float m_VoiceHeadModelHeight; // Height above their head to place the model. - - vgui::Image *m_pSpeakerLabelIcon; // Icon next to speaker labels. - - // Lower-right icons telling when the local player is talking.. - vgui::BitmapTGA *m_pLocalBitmap; // Represents the local client talking. - vgui::BitmapTGA *m_pAckBitmap; // Represents the server ack'ing the client talking. - vgui::ImagePanel *m_pLocalLabel; // Represents the local client talking. - - bool m_bTalking; // Set to true when the client thinks it's talking. - bool m_bServerAcked; // Set to true when the server knows the client is talking. - -public: - - CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear. - -public: - - bool m_bBanMgrInitialized; - - // Labels telling who is speaking. - CVoiceLabel m_Labels[MAX_VOICE_SPEAKERS]; - - // Cache the game directory for use when we shut down - char * m_pchGameDir; -}; - - -// Get the (global) voice manager. -CVoiceStatus* GetClientVoiceMgr(); - - -#endif // VOICE_STATUS_H +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef VOICE_STATUS_H +#define VOICE_STATUS_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + + +#include "VGUI_Label.h" +#include "VGUI_LineBorder.h" +#include "VGUI_ImagePanel.h" +#include "VGUI_BitmapTGA.h" +#include "VGUI_InputSignal.h" +#include "VGUI_Button.h" +#include "voice_common.h" +#include "cl_entity.h" +#include "voice_banmgr.h" +#include "vgui_checkbutton2.h" +#include "vgui_defaultinputsignal.h" + + +class CVoiceStatus; + + +class CVoiceLabel +{ +public: + vgui::Label *m_pLabel; + vgui::Label *m_pBackground; + vgui::ImagePanel *m_pIcon; // Voice icon next to player name. + int m_clientindex; // Client index of the speaker. -1 if this label isn't being used. +}; + + +// This is provided by each mod to access data that may not be the same across mods. +class IVoiceStatusHelper +{ +public: + virtual ~IVoiceStatusHelper() {} + + // Get RGB color for voice status text about this player. + virtual void GetPlayerTextColor(int entindex, int color[3]) = 0; + + // Force it to update the cursor state. + virtual void UpdateCursorState() = 0; + + // Return the height above the bottom that the voice ack icons should be drawn at. + virtual int GetAckIconHeight() = 0; + + // Return true if the voice manager is allowed to show speaker labels + // (mods usually return false when the scoreboard is up). + virtual bool CanShowSpeakerLabels() = 0; +}; + +//----------------------------------------------------------------------------- +// Purpose: Holds a color for the shared image +//----------------------------------------------------------------------------- +class VoiceImagePanel : public vgui::ImagePanel +{ + virtual void paintBackground() + { + if (_image!=null) + { + vgui::Color col; + getFgColor(col); + _image->setColor(col); + _image->doPaint(this); + } + } +}; + + +class CVoiceStatus : public CHudBase, public vgui::CDefaultInputSignal +{ +public: + CVoiceStatus(); + virtual ~CVoiceStatus(); + +// CHudBase overrides. +public: + + // Initialize the cl_dll's voice manager. + virtual int Init( + IVoiceStatusHelper *m_pHelper, + vgui::Panel **pParentPanel); + + // ackPosition is the bottom position of where CVoiceStatus will draw the voice acknowledgement labels. + virtual int VidInit(); + + +public: + + // Call from HUD_Frame each frame. + void Frame(double frametime); + + // Called when a player starts or stops talking. + // entindex is -1 to represent the local client talking (before the data comes back from the server). + // When the server acknowledges that the local client is talking, then entindex will be gEngfuncs.GetLocalPlayer(). + // entindex is -2 to represent the local client's voice being acked by the server. + void UpdateSpeakerStatus(int entindex, qboolean bTalking); + + // sets the correct image in the label for the player + void UpdateSpeakerImage(vgui::Label *pLabel, int iPlayer); + + // Call from the HUD_CreateEntities function so it can add sprites above player heads. + void CreateEntities(); + + // Called when the server registers a change to who this client can hear. + void HandleVoiceMaskMsg(int iSize, void *pbuf); + + // The server sends this message initially to tell the client to send their state. + void HandleReqStateMsg(int iSize, void *pbuf); + + +// Squelch mode functions. +public: + + // When you enter squelch mode, pass in + void StartSquelchMode(); + void StopSquelchMode(); + bool IsInSquelchMode(); + + // returns true if the target client has been banned + // playerIndex is of range 1..maxplayers + bool IsPlayerBlocked(int iPlayerIndex); + + // returns false if the player can't hear the other client due to game rules (eg. the other team) + bool IsPlayerAudible(int iPlayerIndex); + + // blocks the target client from being heard + void SetPlayerBlockedState(int iPlayerIndex, bool blocked); + +public: + + CVoiceLabel* FindVoiceLabel(int clientindex); // Find a CVoiceLabel representing the specified speaker. + // Returns NULL if none. + // entindex can be -1 if you want a currently-unused voice label. + CVoiceLabel* GetFreeVoiceLabel(); // Get an unused voice label. Returns NULL if none. + + void RepositionLabels(); + + void FreeBitmaps(); + + void UpdateServerState(bool bForce); + + // Update the button artwork to reflect the client's current state. + void UpdateBanButton(int iClient); + + +public: + + enum {MAX_VOICE_SPEAKERS=7}; + + float m_LastUpdateServerState; // Last time we called this function. + int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar. + + vgui::Panel **m_pParentPanel; + CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index. + + // This is the gamerules-defined list of players that you can hear. It is based on what teams people are on + // and is totally separate from the ban list. Indexed by client index. + CPlayerBitVec m_AudiblePlayers; + + // Players who have spoken at least once in the game so far + CPlayerBitVec m_VoiceEnabledPlayers; + + // This is who the server THINKS we have banned (it can become incorrect when a new player arrives on the server). + // It is checked periodically, and the server is told to squelch or unsquelch the appropriate players. + CPlayerBitVec m_ServerBannedPlayers; + + cl_entity_s m_VoiceHeadModels[VOICE_MAX_PLAYERS]; // These aren't necessarily in the order of players. They are just + // a place for it to put data in during CreateEntities. + + IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this. + + + // Scoreboard icons. + double m_BlinkTimer; // Blink scoreboard icons.. + vgui::BitmapTGA *m_pScoreboardNeverSpoken; + vgui::BitmapTGA *m_pScoreboardNotSpeaking; + vgui::BitmapTGA *m_pScoreboardSpeaking; + vgui::BitmapTGA *m_pScoreboardSpeaking2; + vgui::BitmapTGA *m_pScoreboardSquelch; + vgui::BitmapTGA *m_pScoreboardBanned; + + vgui::Label *m_pBanButtons[VOICE_MAX_PLAYERS]; // scoreboard buttons. + + // Squelch mode stuff. + bool m_bInSquelchMode; + + HSPRITE m_VoiceHeadModel; // Voice head model (goes above players who are speaking). + float m_VoiceHeadModelHeight; // Height above their head to place the model. + + vgui::Image *m_pSpeakerLabelIcon; // Icon next to speaker labels. + + // Lower-right icons telling when the local player is talking.. + vgui::BitmapTGA *m_pLocalBitmap; // Represents the local client talking. + vgui::BitmapTGA *m_pAckBitmap; // Represents the server ack'ing the client talking. + vgui::ImagePanel *m_pLocalLabel; // Represents the local client talking. + + bool m_bTalking; // Set to true when the client thinks it's talking. + bool m_bServerAcked; // Set to true when the server knows the client is talking. + +public: + + CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear. + +public: + + bool m_bBanMgrInitialized; + + // Labels telling who is speaking. + CVoiceLabel m_Labels[MAX_VOICE_SPEAKERS]; + + // Cache the game directory for use when we shut down + char * m_pchGameDir; +}; + + +// Get the (global) voice manager. +CVoiceStatus* GetClientVoiceMgr(); + + +#endif // VOICE_STATUS_H diff --git a/mainui/basemenu.cpp b/mainui/basemenu.cpp index 6ef9486..a0a80d2 100644 --- a/mainui/basemenu.cpp +++ b/mainui/basemenu.cpp @@ -270,9 +270,9 @@ void UI_DrawString( int x, int y, int w, int h, const char *string, const int co ch &= 255; #if 0 #ifdef _WIN32 - // fix for letter � - if( ch == 0xB8 ) ch = (byte)'�'; - if( ch == 0xA8 ) ch = (byte)'�'; + // fix for letter пїЅ + if( ch == 0xB8 ) ch = (byte)'пїЅ'; + if( ch == 0xA8 ) ch = (byte)'пїЅ'; #endif #endif ch = UtfProcessChar( (unsigned char) ch ); diff --git a/mainui/basemenu.h b/mainui/basemenu.h index 48e6c3b..34caa34 100644 --- a/mainui/basemenu.h +++ b/mainui/basemenu.h @@ -102,7 +102,7 @@ typedef enum QMTYPE_FIELD, QMTYPE_ACTION, QMTYPE_BITMAP, - // CR: ����� ��� ������ + // CR: пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ QMTYPE_BM_BUTTON } menuType_t; diff --git a/mainui/ui_title_anim.h b/mainui/ui_title_anim.h index f2dd6ba..a9293ee 100644 --- a/mainui/ui_title_anim.h +++ b/mainui/ui_title_anim.h @@ -15,5 +15,5 @@ typedef struct void UI_PopPButtonStack( void ); void UI_ClearButtonStack( void ); -// èñïîëüçîâàòü êóñîê èç btns_main.bmp çàìåñòî head_%s.bmp +// иÑпользовать куÑок из btns_main.bmp замеÑто head_%s.bmp //#define TA_ALT_MODE 1 diff --git a/pm_shared/pm_debug.c b/pm_shared/pm_debug.c index b03ed33..9da3eee 100644 --- a/pm_shared/pm_debug.c +++ b/pm_shared/pm_debug.c @@ -1,320 +1,320 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#include "mathlib.h" -#include "const.h" -#include "usercmd.h" -#include "pm_defs.h" -#include "pm_shared.h" -#include "pm_movevars.h" -#include "pm_debug.h" - -#include - -#pragma warning(disable : 4244) -#pragma warning(disable : 4305) - -extern playermove_t *pmove; - -// Expand debugging BBOX particle hulls by this many units. -#define BOX_GAP 0.0f - -static int PM_boxpnt[6][4] = -{ - { 0, 4, 6, 2 }, // +X - { 0, 1, 5, 4 }, // +Y - { 0, 2, 3, 1 }, // +Z - { 7, 5, 1, 3 }, // -X - { 7, 3, 2, 6 }, // -Y - { 7, 6, 4, 5 }, // -Z -}; - -void PM_ShowClipBox(void) -{ -#if defined( _DEBUG ) - vec3_t org; - vec3_t offset = { 0, 0, 0 }; - - if ( !pmove->runfuncs ) - return; - - // More debugging, draw the particle bbox for player and for the entity we are looking directly at. - // aslo prints entity info to the console overlay. - //if ( !pmove->server ) - // return; - - // Draw entity in center of view - // Also draws the normal to the clip plane that intersects our movement ray. Leaves a particle - // trail at the intersection point. - PM_ViewEntity(); - - VectorCopy( pmove->origin, org ); - - if ( pmove->server ) - { - VectorAdd( org, offset, org ); - } - else - { - VectorSubtract( org, offset, org ); - } - - // Show our BBOX in particles. - PM_DrawBBox( pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], org, pmove->server ? 132 : 0, 0.1 ); - - PM_ParticleLine( org, org, pmove->server ? 132 : 0, 0.1, 5.0 ); -/* - { - int i; - for ( i = 0; i < pmove->numphysent; i++ ) - { - if ( pmove->physents[ i ].info >= 1 && pmove->physents[ i ].info <= 4 ) - { - PM_DrawBBox( pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], pmove->physents[i].origin, 132, 0.1 ); - } - } - } -*/ -#endif -} - -/* -=============== -PM_ParticleLine(vec3_t start, vec3_t end, int color, float life) - -================ -*/ -void PM_ParticleLine(vec3_t start, vec3_t end, int pcolor, float life, float vert) -{ - float linestep = 2.0f; - float curdist; - float len; - vec3_t curpos; - vec3_t diff; - int i; - // Determine distance; - - VectorSubtract(end, start, diff); - - len = VectorNormalize(diff); - - curdist = 0; - while (curdist <= len) - { - for (i = 0; i < 3; i++) - curpos[i] = start[i] + curdist * diff[i]; - - pmove->PM_Particle( curpos, pcolor, life, 0, vert); - curdist += linestep; - } - -} - -/* -================ -PM_DrawRectangle(vec3_t tl, vec3_t br) - -================ -*/ -void PM_DrawRectangle(vec3_t tl, vec3_t bl, vec3_t tr, vec3_t br, int pcolor, float life) -{ - PM_ParticleLine(tl, bl, pcolor, life, 0); - PM_ParticleLine(bl, br, pcolor, life, 0); - PM_ParticleLine(br, tr, pcolor, life, 0); - PM_ParticleLine(tr, tl, pcolor, life, 0); -} - -/* -================ -PM_DrawPhysEntBBox(int num) - -================ -*/ -void PM_DrawPhysEntBBox(int num, int pcolor, float life) -{ - physent_t *pe; - vec3_t org; - int j; - vec3_t tmp; - vec3_t p[8]; - float gap = BOX_GAP; - vec3_t modelmins, modelmaxs; - - if (num >= pmove->numphysent || - num <= 0) - return; - - pe = &pmove->physents[num]; - - if (pe->model) - { - VectorCopy(pe->origin, org); - - pmove->PM_GetModelBounds( pe->model, modelmins, modelmaxs ); - for (j = 0; j < 8; j++) - { - tmp[0] = (j & 1) ? modelmins[0] - gap : modelmaxs[0] + gap; - tmp[1] = (j & 2) ? modelmins[1] - gap : modelmaxs[1] + gap; - tmp[2] = (j & 4) ? modelmins[2] - gap : modelmaxs[2] + gap; - - VectorCopy(tmp, p[j]); - } - - // If the bbox should be rotated, do that - if (pe->angles[0] || pe->angles[1] || pe->angles[2]) - { - vec3_t forward, right, up; - - AngleVectorsTranspose(pe->angles, forward, right, up); - for (j = 0; j < 8; j++) - { - VectorCopy(p[j], tmp); - p[j][0] = DotProduct ( tmp, forward ); - p[j][1] = DotProduct ( tmp, right ); - p[j][2] = DotProduct ( tmp, up ); - } - } - - // Offset by entity origin, if any. - for (j = 0; j < 8; j++) - VectorAdd(p[j], org, p[j]); - - for (j = 0; j < 6; j++) - { - PM_DrawRectangle( - p[PM_boxpnt[j][1]], - p[PM_boxpnt[j][0]], - p[PM_boxpnt[j][2]], - p[PM_boxpnt[j][3]], - pcolor, life); - } - } - else - { - for (j = 0; j < 8; j++) - { - tmp[0] = (j & 1) ? pe->mins[0] : pe->maxs[0]; - tmp[1] = (j & 2) ? pe->mins[1] : pe->maxs[1]; - tmp[2] = (j & 4) ? pe->mins[2] : pe->maxs[2]; - - VectorAdd(tmp, pe->origin, tmp); - VectorCopy(tmp, p[j]); - } - - for (j = 0; j < 6; j++) - { - PM_DrawRectangle( - p[PM_boxpnt[j][1]], - p[PM_boxpnt[j][0]], - p[PM_boxpnt[j][2]], - p[PM_boxpnt[j][3]], - pcolor, life); - } - - } -} - -/* -================ -PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life) - -================ -*/ -void PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life) -{ - int j; - - vec3_t tmp; - vec3_t p[8]; - float gap = BOX_GAP; - - for (j = 0; j < 8; j++) - { - tmp[0] = (j & 1) ? mins[0] - gap : maxs[0] + gap; - tmp[1] = (j & 2) ? mins[1] - gap : maxs[1] + gap ; - tmp[2] = (j & 4) ? mins[2] - gap : maxs[2] + gap ; - - VectorAdd(tmp, origin, tmp); - VectorCopy(tmp, p[j]); - } - - for (j = 0; j < 6; j++) - { - PM_DrawRectangle( - p[PM_boxpnt[j][1]], - p[PM_boxpnt[j][0]], - p[PM_boxpnt[j][2]], - p[PM_boxpnt[j][3]], - pcolor, life); - } -} - - -#ifndef DEDICATED - -/* -================ -PM_ViewEntity - -Shows a particle trail from player to entity in crosshair. -Shows particles at that entities bbox - -Tries to shoot a ray out by about 128 units. -================ -*/ -void PM_ViewEntity(void) -{ - vec3_t forward, right, up; - float raydist = 256.0f; - vec3_t origin; - vec3_t end; - int i; - pmtrace_t trace; - int pcolor = 77; - float fup; - -#if 0 - if ( !pm_showclip.value ) - return; -#endif - - AngleVectors (pmove->angles, forward, right, up); // Determine movement angles - - VectorCopy( pmove->origin, origin); - - fup = 0.5*( pmove->player_mins[pmove->usehull][2] + pmove->player_maxs[pmove->usehull][2] ); - fup += pmove->view_ofs[2]; - fup -= 4; - - for (i = 0; i < 3; i++) - { - end[i] = origin[i] + raydist * forward[i]; - } - - trace = pmove->PM_PlayerTrace( origin, end, PM_STUDIO_BOX, -1 ); - - if (trace.ent > 0) // Not the world - { - pcolor = 111; - } - - // Draw the hull or bbox. - if (trace.ent > 0) - { - PM_DrawPhysEntBBox(trace.ent, pcolor, 0.3f); - } -} - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include "mathlib.h" +#include "const.h" +#include "usercmd.h" +#include "pm_defs.h" +#include "pm_shared.h" +#include "pm_movevars.h" +#include "pm_debug.h" + +#include + +#pragma warning(disable : 4244) +#pragma warning(disable : 4305) + +extern playermove_t *pmove; + +// Expand debugging BBOX particle hulls by this many units. +#define BOX_GAP 0.0f + +static int PM_boxpnt[6][4] = +{ + { 0, 4, 6, 2 }, // +X + { 0, 1, 5, 4 }, // +Y + { 0, 2, 3, 1 }, // +Z + { 7, 5, 1, 3 }, // -X + { 7, 3, 2, 6 }, // -Y + { 7, 6, 4, 5 }, // -Z +}; + +void PM_ShowClipBox(void) +{ +#if defined( _DEBUG ) + vec3_t org; + vec3_t offset = { 0, 0, 0 }; + + if ( !pmove->runfuncs ) + return; + + // More debugging, draw the particle bbox for player and for the entity we are looking directly at. + // aslo prints entity info to the console overlay. + //if ( !pmove->server ) + // return; + + // Draw entity in center of view + // Also draws the normal to the clip plane that intersects our movement ray. Leaves a particle + // trail at the intersection point. + PM_ViewEntity(); + + VectorCopy( pmove->origin, org ); + + if ( pmove->server ) + { + VectorAdd( org, offset, org ); + } + else + { + VectorSubtract( org, offset, org ); + } + + // Show our BBOX in particles. + PM_DrawBBox( pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], org, pmove->server ? 132 : 0, 0.1 ); + + PM_ParticleLine( org, org, pmove->server ? 132 : 0, 0.1, 5.0 ); +/* + { + int i; + for ( i = 0; i < pmove->numphysent; i++ ) + { + if ( pmove->physents[ i ].info >= 1 && pmove->physents[ i ].info <= 4 ) + { + PM_DrawBBox( pmove->player_mins[pmove->usehull], pmove->player_maxs[pmove->usehull], pmove->physents[i].origin, 132, 0.1 ); + } + } + } +*/ +#endif +} + +/* +=============== +PM_ParticleLine(vec3_t start, vec3_t end, int color, float life) + +================ +*/ +void PM_ParticleLine(vec3_t start, vec3_t end, int pcolor, float life, float vert) +{ + float linestep = 2.0f; + float curdist; + float len; + vec3_t curpos; + vec3_t diff; + int i; + // Determine distance; + + VectorSubtract(end, start, diff); + + len = VectorNormalize(diff); + + curdist = 0; + while (curdist <= len) + { + for (i = 0; i < 3; i++) + curpos[i] = start[i] + curdist * diff[i]; + + pmove->PM_Particle( curpos, pcolor, life, 0, vert); + curdist += linestep; + } + +} + +/* +================ +PM_DrawRectangle(vec3_t tl, vec3_t br) + +================ +*/ +void PM_DrawRectangle(vec3_t tl, vec3_t bl, vec3_t tr, vec3_t br, int pcolor, float life) +{ + PM_ParticleLine(tl, bl, pcolor, life, 0); + PM_ParticleLine(bl, br, pcolor, life, 0); + PM_ParticleLine(br, tr, pcolor, life, 0); + PM_ParticleLine(tr, tl, pcolor, life, 0); +} + +/* +================ +PM_DrawPhysEntBBox(int num) + +================ +*/ +void PM_DrawPhysEntBBox(int num, int pcolor, float life) +{ + physent_t *pe; + vec3_t org; + int j; + vec3_t tmp; + vec3_t p[8]; + float gap = BOX_GAP; + vec3_t modelmins, modelmaxs; + + if (num >= pmove->numphysent || + num <= 0) + return; + + pe = &pmove->physents[num]; + + if (pe->model) + { + VectorCopy(pe->origin, org); + + pmove->PM_GetModelBounds( pe->model, modelmins, modelmaxs ); + for (j = 0; j < 8; j++) + { + tmp[0] = (j & 1) ? modelmins[0] - gap : modelmaxs[0] + gap; + tmp[1] = (j & 2) ? modelmins[1] - gap : modelmaxs[1] + gap; + tmp[2] = (j & 4) ? modelmins[2] - gap : modelmaxs[2] + gap; + + VectorCopy(tmp, p[j]); + } + + // If the bbox should be rotated, do that + if (pe->angles[0] || pe->angles[1] || pe->angles[2]) + { + vec3_t forward, right, up; + + AngleVectorsTranspose(pe->angles, forward, right, up); + for (j = 0; j < 8; j++) + { + VectorCopy(p[j], tmp); + p[j][0] = DotProduct ( tmp, forward ); + p[j][1] = DotProduct ( tmp, right ); + p[j][2] = DotProduct ( tmp, up ); + } + } + + // Offset by entity origin, if any. + for (j = 0; j < 8; j++) + VectorAdd(p[j], org, p[j]); + + for (j = 0; j < 6; j++) + { + PM_DrawRectangle( + p[PM_boxpnt[j][1]], + p[PM_boxpnt[j][0]], + p[PM_boxpnt[j][2]], + p[PM_boxpnt[j][3]], + pcolor, life); + } + } + else + { + for (j = 0; j < 8; j++) + { + tmp[0] = (j & 1) ? pe->mins[0] : pe->maxs[0]; + tmp[1] = (j & 2) ? pe->mins[1] : pe->maxs[1]; + tmp[2] = (j & 4) ? pe->mins[2] : pe->maxs[2]; + + VectorAdd(tmp, pe->origin, tmp); + VectorCopy(tmp, p[j]); + } + + for (j = 0; j < 6; j++) + { + PM_DrawRectangle( + p[PM_boxpnt[j][1]], + p[PM_boxpnt[j][0]], + p[PM_boxpnt[j][2]], + p[PM_boxpnt[j][3]], + pcolor, life); + } + + } +} + +/* +================ +PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life) + +================ +*/ +void PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life) +{ + int j; + + vec3_t tmp; + vec3_t p[8]; + float gap = BOX_GAP; + + for (j = 0; j < 8; j++) + { + tmp[0] = (j & 1) ? mins[0] - gap : maxs[0] + gap; + tmp[1] = (j & 2) ? mins[1] - gap : maxs[1] + gap ; + tmp[2] = (j & 4) ? mins[2] - gap : maxs[2] + gap ; + + VectorAdd(tmp, origin, tmp); + VectorCopy(tmp, p[j]); + } + + for (j = 0; j < 6; j++) + { + PM_DrawRectangle( + p[PM_boxpnt[j][1]], + p[PM_boxpnt[j][0]], + p[PM_boxpnt[j][2]], + p[PM_boxpnt[j][3]], + pcolor, life); + } +} + + +#ifndef DEDICATED + +/* +================ +PM_ViewEntity + +Shows a particle trail from player to entity in crosshair. +Shows particles at that entities bbox + +Tries to shoot a ray out by about 128 units. +================ +*/ +void PM_ViewEntity(void) +{ + vec3_t forward, right, up; + float raydist = 256.0f; + vec3_t origin; + vec3_t end; + int i; + pmtrace_t trace; + int pcolor = 77; + float fup; + +#if 0 + if ( !pm_showclip.value ) + return; +#endif + + AngleVectors (pmove->angles, forward, right, up); // Determine movement angles + + VectorCopy( pmove->origin, origin); + + fup = 0.5*( pmove->player_mins[pmove->usehull][2] + pmove->player_maxs[pmove->usehull][2] ); + fup += pmove->view_ofs[2]; + fup -= 4; + + for (i = 0; i < 3; i++) + { + end[i] = origin[i] + raydist * forward[i]; + } + + trace = pmove->PM_PlayerTrace( origin, end, PM_STUDIO_BOX, -1 ); + + if (trace.ent > 0) // Not the world + { + pcolor = 111; + } + + // Draw the hull or bbox. + if (trace.ent > 0) + { + PM_DrawPhysEntBBox(trace.ent, pcolor, 0.3f); + } +} + +#endif diff --git a/pm_shared/pm_debug.h b/pm_shared/pm_debug.h index 949971c..6be768a 100644 --- a/pm_shared/pm_debug.h +++ b/pm_shared/pm_debug.h @@ -1,28 +1,28 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#ifndef PM_DEBUG_H -#define PM_DEBUG_H -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -void PM_ViewEntity(void); -void PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life); -void PM_ParticleLine(vec3_t start, vec3_t end, int pcolor, float life, float vert); -void PM_ShowClipBox(void); - -#endif // PMOVEDBG_H +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef PM_DEBUG_H +#define PM_DEBUG_H +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +void PM_ViewEntity(void); +void PM_DrawBBox(vec3_t mins, vec3_t maxs, vec3_t origin, int pcolor, float life); +void PM_ParticleLine(vec3_t start, vec3_t end, int pcolor, float life, float vert); +void PM_ShowClipBox(void); + +#endif // PMOVEDBG_H diff --git a/pm_shared/pm_defs.h b/pm_shared/pm_defs.h index 8a3eff0..309119d 100644 --- a/pm_shared/pm_defs.h +++ b/pm_shared/pm_defs.h @@ -1,226 +1,226 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// pm_defs.h -#if !defined( PM_DEFSH ) -#define PM_DEFSH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -#define MAX_PHYSENTS 600 // Must have room for all entities in the world. -#define MAX_MOVEENTS 64 -#define MAX_CLIP_PLANES 5 - -#define PM_NORMAL 0x00000000 -#define PM_STUDIO_IGNORE 0x00000001 // Skip studio models -#define PM_STUDIO_BOX 0x00000002 // Use boxes for non-complex studio models (even in traceline) -#define PM_GLASS_IGNORE 0x00000004 // Ignore entities with non-normal rendermode -#define PM_WORLD_ONLY 0x00000008 // Only trace against the world - -// Values for flags parameter of PM_TraceLine -#define PM_TRACELINE_PHYSENTSONLY 0 -#define PM_TRACELINE_ANYVISIBLE 1 - - -#include "pm_info.h" - -// PM_PlayerTrace results. -#include "pmtrace.h" - -#if !defined ( USERCMD_H ) -#include "usercmd.h" -#endif - -// physent_t -typedef struct physent_s -{ - char name[32]; // Name of model, or "player" or "world". - int player; - vec3_t origin; // Model's origin in world coordinates. - struct model_s *model; // only for bsp models - struct model_s *studiomodel; // SOLID_BBOX, but studio clip intersections. - vec3_t mins, maxs; // only for non-bsp models - int info; // For client or server to use to identify (index into edicts or cl_entities) - vec3_t angles; // rotated entities need this info for hull testing to work. - - int solid; // Triggers and func_door type WATER brushes are SOLID_NOT - int skin; // BSP Contents for such things like fun_door water brushes. - int rendermode; // So we can ignore glass - - // Complex collision detection. - float frame; - int sequence; - byte controller[4]; - byte blending[2]; - - int movetype; - int takedamage; - int blooddecal; - int team; - int classnumber; - - // 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; -} physent_t; - - -typedef struct playermove_s -{ - int player_index; // So we don't try to run the PM_CheckStuck nudging too quickly. - qboolean server; // For debugging, are we running physics code on server side? - - qboolean multiplayer; // 1 == multiplayer server - float time; // realtime on host, for reckoning duck timing - float frametime; // Duration of this frame - - vec3_t forward, right, up; // Vectors for angles - // player state - vec3_t origin; // Movement origin. - vec3_t angles; // Movement view angles. - vec3_t oldangles; // Angles before movement view angles were looked at. - vec3_t velocity; // Current movement direction. - vec3_t movedir; // For waterjumping, a forced forward velocity so we can fly over lip of ledge. - vec3_t basevelocity; // Velocity of the conveyor we are standing, e.g. - - // For ducking/dead - vec3_t view_ofs; // Our eye position. - float flDuckTime; // Time we started duck - qboolean bInDuck; // In process of ducking or ducked already? - - // For walking/falling - int flTimeStepSound; // Next time we can play a step sound - int iStepLeft; - - float flFallVelocity; - vec3_t punchangle; - - float flSwimTime; - - float flNextPrimaryAttack; - - int effects; // MUZZLE FLASH, e.g. - - int flags; // FL_ONGROUND, FL_DUCKING, etc. - int usehull; // 0 = regular player hull, 1 = ducked player hull, 2 = point hull - float gravity; // Our current gravity and friction. - float friction; - int oldbuttons; // Buttons last usercmd - float waterjumptime; // Amount of time left in jumping out of water cycle. - qboolean dead; // Are we a dead player? - int deadflag; - int spectator; // Should we use spectator physics model? - int movetype; // Our movement type, NOCLIP, WALK, FLY - - int onground; - int waterlevel; - int watertype; - int oldwaterlevel; - - char sztexturename[256]; - char chtexturetype; - - float maxspeed; - float clientmaxspeed; // Player specific maxspeed - - // 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; - // world state - // Number of entities to clip against. - int numphysent; - physent_t physents[MAX_PHYSENTS]; - // Number of momvement entities (ladders) - int nummoveent; - // just a list of ladders - physent_t moveents[MAX_MOVEENTS]; - - // All things being rendered, for tracing against things you don't actually collide with - int numvisent; - physent_t visents[ MAX_PHYSENTS ]; - - // input to run through physics. - usercmd_t cmd; - - // Trace results for objects we collided with. - int numtouch; - pmtrace_t touchindex[MAX_PHYSENTS]; - - char physinfo[ MAX_PHYSINFO_STRING ]; // Physics info string - - struct movevars_s *movevars; - vec3_t player_mins[ 4 ]; - vec3_t player_maxs[ 4 ]; - - // Common functions - const char *(*PM_Info_ValueForKey) ( const char *s, const char *key ); - void (*PM_Particle)( float *origin, int color, float life, int zpos, int zvel); - int (*PM_TestPlayerPosition) (float *pos, pmtrace_t *ptrace ); - void (*Con_NPrintf)( int idx, char *fmt, ... ); - void (*Con_DPrintf)( char *fmt, ... ); - void (*Con_Printf)( char *fmt, ... ); - double (*Sys_FloatTime)(void); - void (*PM_StuckTouch)( int hitent, pmtrace_t *ptraceresult ); - int (*PM_PointContents) (float *p, int *truecontents /*filled in if this is non-null*/ ); - int (*PM_TruePointContents) (float *p); - int (*PM_HullPointContents) ( struct hull_s *hull, int num, float *p); - pmtrace_t (*PM_PlayerTrace) (float *start, float *end, int traceFlags, int ignore_pe ); - struct pmtrace_s *(*PM_TraceLine)( float *start, float *end, int flags, int usehulll, int ignore_pe ); - long (*RandomLong)( long lLow, long lHigh ); - float (*RandomFloat)( float flLow, float flHigh ); - int (*PM_GetModelType)( struct model_s *mod ); - void (*PM_GetModelBounds)( struct model_s *mod, float *mins, float *maxs ); - void *(*PM_HullForBsp)( physent_t *pe, float *offset ); - float (*PM_TraceModel)( physent_t *pEnt, float *start, float *end, trace_t *trace ); - int (*COM_FileSize)(char *filename); - byte *(*COM_LoadFile) (char *path, int usehunk, int *pLength); - void (*COM_FreeFile) ( void *buffer ); - char *(*memfgets)( byte *pMemFile, int fileSize, int *pFilePos, char *pBuffer, int bufferSize ); - - // Functions - // Run functions for this frame? - qboolean runfuncs; - void (*PM_PlaySound) ( int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch ); - const char *(*PM_TraceTexture) ( int ground, float *vstart, float *vend ); - void (*PM_PlaybackEventFull) ( int flags, int clientindex, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ); - - pmtrace_t (*PM_PlayerTraceEx) (float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ) ); - int (*PM_TestPlayerPositionEx) (float *pos, pmtrace_t *ptrace, int (*pfnIgnore)( physent_t *pe ) ); - struct pmtrace_s *(*PM_TraceLineEx)( float *start, float *end, int flags, int usehulll, int (*pfnIgnore)( physent_t *pe ) ); -} playermove_t; - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// pm_defs.h +#if !defined( PM_DEFSH ) +#define PM_DEFSH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +#define MAX_PHYSENTS 600 // Must have room for all entities in the world. +#define MAX_MOVEENTS 64 +#define MAX_CLIP_PLANES 5 + +#define PM_NORMAL 0x00000000 +#define PM_STUDIO_IGNORE 0x00000001 // Skip studio models +#define PM_STUDIO_BOX 0x00000002 // Use boxes for non-complex studio models (even in traceline) +#define PM_GLASS_IGNORE 0x00000004 // Ignore entities with non-normal rendermode +#define PM_WORLD_ONLY 0x00000008 // Only trace against the world + +// Values for flags parameter of PM_TraceLine +#define PM_TRACELINE_PHYSENTSONLY 0 +#define PM_TRACELINE_ANYVISIBLE 1 + + +#include "pm_info.h" + +// PM_PlayerTrace results. +#include "pmtrace.h" + +#if !defined ( USERCMD_H ) +#include "usercmd.h" +#endif + +// physent_t +typedef struct physent_s +{ + char name[32]; // Name of model, or "player" or "world". + int player; + vec3_t origin; // Model's origin in world coordinates. + struct model_s *model; // only for bsp models + struct model_s *studiomodel; // SOLID_BBOX, but studio clip intersections. + vec3_t mins, maxs; // only for non-bsp models + int info; // For client or server to use to identify (index into edicts or cl_entities) + vec3_t angles; // rotated entities need this info for hull testing to work. + + int solid; // Triggers and func_door type WATER brushes are SOLID_NOT + int skin; // BSP Contents for such things like fun_door water brushes. + int rendermode; // So we can ignore glass + + // Complex collision detection. + float frame; + int sequence; + byte controller[4]; + byte blending[2]; + + int movetype; + int takedamage; + int blooddecal; + int team; + int classnumber; + + // 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; +} physent_t; + + +typedef struct playermove_s +{ + int player_index; // So we don't try to run the PM_CheckStuck nudging too quickly. + qboolean server; // For debugging, are we running physics code on server side? + + qboolean multiplayer; // 1 == multiplayer server + float time; // realtime on host, for reckoning duck timing + float frametime; // Duration of this frame + + vec3_t forward, right, up; // Vectors for angles + // player state + vec3_t origin; // Movement origin. + vec3_t angles; // Movement view angles. + vec3_t oldangles; // Angles before movement view angles were looked at. + vec3_t velocity; // Current movement direction. + vec3_t movedir; // For waterjumping, a forced forward velocity so we can fly over lip of ledge. + vec3_t basevelocity; // Velocity of the conveyor we are standing, e.g. + + // For ducking/dead + vec3_t view_ofs; // Our eye position. + float flDuckTime; // Time we started duck + qboolean bInDuck; // In process of ducking or ducked already? + + // For walking/falling + int flTimeStepSound; // Next time we can play a step sound + int iStepLeft; + + float flFallVelocity; + vec3_t punchangle; + + float flSwimTime; + + float flNextPrimaryAttack; + + int effects; // MUZZLE FLASH, e.g. + + int flags; // FL_ONGROUND, FL_DUCKING, etc. + int usehull; // 0 = regular player hull, 1 = ducked player hull, 2 = point hull + float gravity; // Our current gravity and friction. + float friction; + int oldbuttons; // Buttons last usercmd + float waterjumptime; // Amount of time left in jumping out of water cycle. + qboolean dead; // Are we a dead player? + int deadflag; + int spectator; // Should we use spectator physics model? + int movetype; // Our movement type, NOCLIP, WALK, FLY + + int onground; + int waterlevel; + int watertype; + int oldwaterlevel; + + char sztexturename[256]; + char chtexturetype; + + float maxspeed; + float clientmaxspeed; // Player specific maxspeed + + // 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; + // world state + // Number of entities to clip against. + int numphysent; + physent_t physents[MAX_PHYSENTS]; + // Number of momvement entities (ladders) + int nummoveent; + // just a list of ladders + physent_t moveents[MAX_MOVEENTS]; + + // All things being rendered, for tracing against things you don't actually collide with + int numvisent; + physent_t visents[ MAX_PHYSENTS ]; + + // input to run through physics. + usercmd_t cmd; + + // Trace results for objects we collided with. + int numtouch; + pmtrace_t touchindex[MAX_PHYSENTS]; + + char physinfo[ MAX_PHYSINFO_STRING ]; // Physics info string + + struct movevars_s *movevars; + vec3_t player_mins[ 4 ]; + vec3_t player_maxs[ 4 ]; + + // Common functions + const char *(*PM_Info_ValueForKey) ( const char *s, const char *key ); + void (*PM_Particle)( float *origin, int color, float life, int zpos, int zvel); + int (*PM_TestPlayerPosition) (float *pos, pmtrace_t *ptrace ); + void (*Con_NPrintf)( int idx, char *fmt, ... ); + void (*Con_DPrintf)( char *fmt, ... ); + void (*Con_Printf)( char *fmt, ... ); + double (*Sys_FloatTime)(void); + void (*PM_StuckTouch)( int hitent, pmtrace_t *ptraceresult ); + int (*PM_PointContents) (float *p, int *truecontents /*filled in if this is non-null*/ ); + int (*PM_TruePointContents) (float *p); + int (*PM_HullPointContents) ( struct hull_s *hull, int num, float *p); + pmtrace_t (*PM_PlayerTrace) (float *start, float *end, int traceFlags, int ignore_pe ); + struct pmtrace_s *(*PM_TraceLine)( float *start, float *end, int flags, int usehulll, int ignore_pe ); + long (*RandomLong)( long lLow, long lHigh ); + float (*RandomFloat)( float flLow, float flHigh ); + int (*PM_GetModelType)( struct model_s *mod ); + void (*PM_GetModelBounds)( struct model_s *mod, float *mins, float *maxs ); + void *(*PM_HullForBsp)( physent_t *pe, float *offset ); + float (*PM_TraceModel)( physent_t *pEnt, float *start, float *end, trace_t *trace ); + int (*COM_FileSize)(char *filename); + byte *(*COM_LoadFile) (char *path, int usehunk, int *pLength); + void (*COM_FreeFile) ( void *buffer ); + char *(*memfgets)( byte *pMemFile, int fileSize, int *pFilePos, char *pBuffer, int bufferSize ); + + // Functions + // Run functions for this frame? + qboolean runfuncs; + void (*PM_PlaySound) ( int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch ); + const char *(*PM_TraceTexture) ( int ground, float *vstart, float *vend ); + void (*PM_PlaybackEventFull) ( int flags, int clientindex, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ); + + pmtrace_t (*PM_PlayerTraceEx) (float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ) ); + int (*PM_TestPlayerPositionEx) (float *pos, pmtrace_t *ptrace, int (*pfnIgnore)( physent_t *pe ) ); + struct pmtrace_s *(*PM_TraceLineEx)( float *start, float *end, int flags, int usehulll, int (*pfnIgnore)( physent_t *pe ) ); +} playermove_t; + +#endif diff --git a/pm_shared/pm_info.h b/pm_shared/pm_info.h index 5a9ff00..fa3cc19 100644 --- a/pm_shared/pm_info.h +++ b/pm_shared/pm_info.h @@ -1,26 +1,26 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// Physics info string definition -#if !defined( PM_INFOH ) -#define PM_INFOH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -#define MAX_PHYSINFO_STRING 256 - -#endif // PM_INFOH +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// Physics info string definition +#if !defined( PM_INFOH ) +#define PM_INFOH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +#define MAX_PHYSINFO_STRING 256 + +#endif // PM_INFOH diff --git a/pm_shared/pm_materials.h b/pm_shared/pm_materials.h index 0c76bd8..ad5556a 100644 --- a/pm_shared/pm_materials.h +++ b/pm_shared/pm_materials.h @@ -1,38 +1,38 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -#if !defined(PM_MATERIALSH) -#define PM_MATERIALSH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif -#endif - -#define CBTEXTURENAMEMAX 17 - -#define CHAR_TEX_CONCRETE 'C' -#define CHAR_TEX_METAL 'M' -#define CHAR_TEX_DIRT 'D' -#define CHAR_TEX_VENT 'V' -#define CHAR_TEX_GRATE 'G' -#define CHAR_TEX_TILE 'T' -#define CHAR_TEX_SLOSH 'S' -#define CHAR_TEX_WOOD 'W' -#define CHAR_TEX_COMPUTER 'P' -#define CHAR_TEX_GLASS 'Y' -#define CHAR_TEX_FLESH 'F' -#define CHAR_TEX_SNOW 'N' - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#if !defined(PM_MATERIALSH) +#define PM_MATERIALSH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif +#endif + +#define CBTEXTURENAMEMAX 17 + +#define CHAR_TEX_CONCRETE 'C' +#define CHAR_TEX_METAL 'M' +#define CHAR_TEX_DIRT 'D' +#define CHAR_TEX_VENT 'V' +#define CHAR_TEX_GRATE 'G' +#define CHAR_TEX_TILE 'T' +#define CHAR_TEX_SLOSH 'S' +#define CHAR_TEX_WOOD 'W' +#define CHAR_TEX_COMPUTER 'P' +#define CHAR_TEX_GLASS 'Y' +#define CHAR_TEX_FLESH 'F' +#define CHAR_TEX_SNOW 'N' + #endif \ No newline at end of file diff --git a/pm_shared/pm_math.c b/pm_shared/pm_math.c index a5d78dc..8edaa3a 100644 --- a/pm_shared/pm_math.c +++ b/pm_shared/pm_math.c @@ -1,422 +1,422 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ -// pm_math.c -- math primitives - -#include "mathlib.h" -#include "const.h" -#include - -// up / down -#define PITCH 0 -// left / right -#define YAW 1 -// fall over -#define ROLL 2 - -#pragma warning(disable : 4244) - -vec3_t vec3_origin = {0,0,0}; -int nanmask = 255<<23; - -float anglemod(float a) -{ - a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); - return a; -} - -void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - if (forward) - { - forward[0] = cp*cy; - forward[1] = cp*sy; - forward[2] = -sp; - } - if (right) - { - right[0] = (-1*sr*sp*cy+-1*cr*-sy); - right[1] = (-1*sr*sp*sy+-1*cr*cy); - right[2] = -1*sr*cp; - } - if (up) - { - up[0] = (cr*sp*cy+-sr*-sy); - up[1] = (cr*sp*sy+-sr*cy); - up[2] = cr*cp; - } -} - -void AngleVectorsTranspose (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - if (forward) - { - forward[0] = cp*cy; - forward[1] = (sr*sp*cy+cr*-sy); - forward[2] = (cr*sp*cy+-sr*-sy); - } - if (right) - { - right[0] = cp*sy; - right[1] = (sr*sp*sy+cr*cy); - right[2] = (cr*sp*sy+-sr*cy); - } - if (up) - { - up[0] = -sp; - up[1] = sr*cp; - up[2] = cr*cp; - } -} - - -void AngleMatrix (const vec3_t angles, float (*matrix)[4] ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - // matrix = (YAW * PITCH) * ROLL - matrix[0][0] = cp*cy; - matrix[1][0] = cp*sy; - matrix[2][0] = -sp; - matrix[0][1] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[2][1] = sr*cp; - matrix[0][2] = (cr*sp*cy+-sr*-sy); - matrix[1][2] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; - matrix[0][3] = 0.0; - matrix[1][3] = 0.0; - matrix[2][3] = 0.0; -} - -void AngleIMatrix (const vec3_t angles, float matrix[3][4] ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[YAW] * (M_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[PITCH] * (M_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[ROLL] * (M_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - // matrix = (YAW * PITCH) * ROLL - matrix[0][0] = cp*cy; - matrix[0][1] = cp*sy; - matrix[0][2] = -sp; - matrix[1][0] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[1][2] = sr*cp; - matrix[2][0] = (cr*sp*cy+-sr*-sy); - matrix[2][1] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; - matrix[0][3] = 0.0; - matrix[1][3] = 0.0; - matrix[2][3] = 0.0; -} - -void NormalizeAngles( float *angles ) -{ - int i; - // Normalize angles - for ( i = 0; i < 3; i++ ) - { - if ( angles[i] > 180.0 ) - { - angles[i] -= 360.0; - } - else if ( angles[i] < -180.0 ) - { - angles[i] += 360.0; - } - } -} - -/* -=================== -InterpolateAngles - -Interpolate Euler angles. -FIXME: Use Quaternions to avoid discontinuities -Frac is 0.0 to 1.0 ( i.e., should probably be clamped, but doesn't have to be ) -=================== -*/ -void InterpolateAngles( float *start, float *end, float *output, float frac ) -{ - int i; - float ang1, ang2; - float d; - - NormalizeAngles( start ); - NormalizeAngles( end ); - - for ( i = 0 ; i < 3 ; i++ ) - { - ang1 = start[i]; - ang2 = end[i]; - - d = ang2 - ang1; - if ( d > 180 ) - { - d -= 360; - } - else if ( d < -180 ) - { - d += 360; - } - - output[i] = ang1 + d * frac; - } - - NormalizeAngles( output ); -} - - -/* -=================== -AngleBetweenVectors - -=================== -*/ -float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 ) -{ - float angle; - float l1 = Length( v1 ); - float l2 = Length( v2 ); - - if ( !l1 || !l2 ) - return 0.0f; - - angle = acos( DotProduct( v1, v2 ) ) / (l1*l2); - angle = ( angle * 180.0f ) / M_PI; - - return angle; -} - - -void VectorTransform (const vec3_t in1, float in2[3][4], vec3_t out) -{ - out[0] = DotProduct(in1, in2[0]) + in2[0][3]; - out[1] = DotProduct(in1, in2[1]) + in2[1][3]; - out[2] = DotProduct(in1, in2[2]) + in2[2][3]; -} - - -int VectorCompare (const vec3_t v1, const vec3_t v2) -{ - int i; - - for (i=0 ; i<3 ; i++) - if (v1[i] != v2[i]) - return 0; - - return 1; -} - -void VectorMA (const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) -{ - vecc[0] = veca[0] + scale*vecb[0]; - vecc[1] = veca[1] + scale*vecb[1]; - vecc[2] = veca[2] + scale*vecb[2]; -} - - -vec_t _DotProduct (vec3_t v1, vec3_t v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out) -{ - out[0] = veca[0]-vecb[0]; - out[1] = veca[1]-vecb[1]; - out[2] = veca[2]-vecb[2]; -} - -void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out) -{ - out[0] = veca[0]+vecb[0]; - out[1] = veca[1]+vecb[1]; - out[2] = veca[2]+vecb[2]; -} - -void _VectorCopy (vec3_t in, vec3_t out) -{ - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; -} - -void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross) -{ - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -double sqrt(double x); - -float Length(const vec3_t v) -{ - int i; - float length = 0.0f; - - for (i=0 ; i< 3 ; i++) - length += v[i]*v[i]; - length = sqrt (length); // FIXME - - return length; -} - -float Distance(const vec3_t v1, const vec3_t v2) -{ - vec3_t d; - VectorSubtract(v2,v1,d); - return Length(d); -} - -float VectorNormalize (vec3_t 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 (vec3_t v) -{ - v[0] = -v[0]; - v[1] = -v[1]; - v[2] = -v[2]; -} - -void VectorScale (const vec3_t in, vec_t scale, vec3_t out) -{ - out[0] = in[0]*scale; - out[1] = in[1]*scale; - out[2] = in[2]*scale; -} - - -int Q_log2(int val) -{ - int answer=0; - while (val>>=1) - answer++; - return answer; -} - -void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up) -{ - vec3_t tmp; - - if (forward[0] == 0 && forward[1] == 0) - { - right[0] = 1; - right[1] = 0; - right[2] = 0; - up[0] = -forward[2]; - up[1] = 0; - up[2] = 0; - return; - } - - tmp[0] = 0; tmp[1] = 0; tmp[2] = 1.0; - CrossProduct( forward, tmp, right ); - VectorNormalize( right ); - CrossProduct( right, forward, up ); - VectorNormalize( up ); -} - - -void VectorAngles( const vec3_t forward, vec3_t 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; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +// pm_math.c -- math primitives + +#include "mathlib.h" +#include "const.h" +#include + +// up / down +#define PITCH 0 +// left / right +#define YAW 1 +// fall over +#define ROLL 2 + +#pragma warning(disable : 4244) + +vec3_t vec3_origin = {0,0,0}; +int nanmask = 255<<23; + +float anglemod(float a) +{ + a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); + return a; +} + +void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + if (forward) + { + forward[0] = cp*cy; + forward[1] = cp*sy; + forward[2] = -sp; + } + if (right) + { + right[0] = (-1*sr*sp*cy+-1*cr*-sy); + right[1] = (-1*sr*sp*sy+-1*cr*cy); + right[2] = -1*sr*cp; + } + if (up) + { + up[0] = (cr*sp*cy+-sr*-sy); + up[1] = (cr*sp*sy+-sr*cy); + up[2] = cr*cp; + } +} + +void AngleVectorsTranspose (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + if (forward) + { + forward[0] = cp*cy; + forward[1] = (sr*sp*cy+cr*-sy); + forward[2] = (cr*sp*cy+-sr*-sy); + } + if (right) + { + right[0] = cp*sy; + right[1] = (sr*sp*sy+cr*cy); + right[2] = (cr*sp*sy+-sr*cy); + } + if (up) + { + up[0] = -sp; + up[1] = sr*cp; + up[2] = cr*cp; + } +} + + +void AngleMatrix (const vec3_t angles, float (*matrix)[4] ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + // matrix = (YAW * PITCH) * ROLL + matrix[0][0] = cp*cy; + matrix[1][0] = cp*sy; + matrix[2][0] = -sp; + matrix[0][1] = sr*sp*cy+cr*-sy; + matrix[1][1] = sr*sp*sy+cr*cy; + matrix[2][1] = sr*cp; + matrix[0][2] = (cr*sp*cy+-sr*-sy); + matrix[1][2] = (cr*sp*sy+-sr*cy); + matrix[2][2] = cr*cp; + matrix[0][3] = 0.0; + matrix[1][3] = 0.0; + matrix[2][3] = 0.0; +} + +void AngleIMatrix (const vec3_t angles, float matrix[3][4] ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[YAW] * (M_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[PITCH] * (M_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[ROLL] * (M_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + // matrix = (YAW * PITCH) * ROLL + matrix[0][0] = cp*cy; + matrix[0][1] = cp*sy; + matrix[0][2] = -sp; + matrix[1][0] = sr*sp*cy+cr*-sy; + matrix[1][1] = sr*sp*sy+cr*cy; + matrix[1][2] = sr*cp; + matrix[2][0] = (cr*sp*cy+-sr*-sy); + matrix[2][1] = (cr*sp*sy+-sr*cy); + matrix[2][2] = cr*cp; + matrix[0][3] = 0.0; + matrix[1][3] = 0.0; + matrix[2][3] = 0.0; +} + +void NormalizeAngles( float *angles ) +{ + int i; + // Normalize angles + for ( i = 0; i < 3; i++ ) + { + if ( angles[i] > 180.0 ) + { + angles[i] -= 360.0; + } + else if ( angles[i] < -180.0 ) + { + angles[i] += 360.0; + } + } +} + +/* +=================== +InterpolateAngles + +Interpolate Euler angles. +FIXME: Use Quaternions to avoid discontinuities +Frac is 0.0 to 1.0 ( i.e., should probably be clamped, but doesn't have to be ) +=================== +*/ +void InterpolateAngles( float *start, float *end, float *output, float frac ) +{ + int i; + float ang1, ang2; + float d; + + NormalizeAngles( start ); + NormalizeAngles( end ); + + for ( i = 0 ; i < 3 ; i++ ) + { + ang1 = start[i]; + ang2 = end[i]; + + d = ang2 - ang1; + if ( d > 180 ) + { + d -= 360; + } + else if ( d < -180 ) + { + d += 360; + } + + output[i] = ang1 + d * frac; + } + + NormalizeAngles( output ); +} + + +/* +=================== +AngleBetweenVectors + +=================== +*/ +float AngleBetweenVectors( const vec3_t v1, const vec3_t v2 ) +{ + float angle; + float l1 = Length( v1 ); + float l2 = Length( v2 ); + + if ( !l1 || !l2 ) + return 0.0f; + + angle = acos( DotProduct( v1, v2 ) ) / (l1*l2); + angle = ( angle * 180.0f ) / M_PI; + + return angle; +} + + +void VectorTransform (const vec3_t in1, float in2[3][4], vec3_t out) +{ + out[0] = DotProduct(in1, in2[0]) + in2[0][3]; + out[1] = DotProduct(in1, in2[1]) + in2[1][3]; + out[2] = DotProduct(in1, in2[2]) + in2[2][3]; +} + + +int VectorCompare (const vec3_t v1, const vec3_t v2) +{ + int i; + + for (i=0 ; i<3 ; i++) + if (v1[i] != v2[i]) + return 0; + + return 1; +} + +void VectorMA (const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) +{ + vecc[0] = veca[0] + scale*vecb[0]; + vecc[1] = veca[1] + scale*vecb[1]; + vecc[2] = veca[2] + scale*vecb[2]; +} + + +vec_t _DotProduct (vec3_t v1, vec3_t v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out) +{ + out[0] = veca[0]-vecb[0]; + out[1] = veca[1]-vecb[1]; + out[2] = veca[2]-vecb[2]; +} + +void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out) +{ + out[0] = veca[0]+vecb[0]; + out[1] = veca[1]+vecb[1]; + out[2] = veca[2]+vecb[2]; +} + +void _VectorCopy (vec3_t in, vec3_t out) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +void CrossProduct (const vec3_t v1, const vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +double sqrt(double x); + +float Length(const vec3_t v) +{ + int i; + float length = 0.0f; + + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = sqrt (length); // FIXME + + return length; +} + +float Distance(const vec3_t v1, const vec3_t v2) +{ + vec3_t d; + VectorSubtract(v2,v1,d); + return Length(d); +} + +float VectorNormalize (vec3_t 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 (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +void VectorScale (const vec3_t in, vec_t scale, vec3_t out) +{ + out[0] = in[0]*scale; + out[1] = in[1]*scale; + out[2] = in[2]*scale; +} + + +int Q_log2(int val) +{ + int answer=0; + while (val>>=1) + answer++; + return answer; +} + +void VectorMatrix( vec3_t forward, vec3_t right, vec3_t up) +{ + vec3_t tmp; + + if (forward[0] == 0 && forward[1] == 0) + { + right[0] = 1; + right[1] = 0; + right[2] = 0; + up[0] = -forward[2]; + up[1] = 0; + up[2] = 0; + return; + } + + tmp[0] = 0; tmp[1] = 0; tmp[2] = 1.0; + CrossProduct( forward, tmp, right ); + VectorNormalize( right ); + CrossProduct( right, forward, up ); + VectorNormalize( up ); +} + + +void VectorAngles( const vec3_t forward, vec3_t 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; +} diff --git a/pm_shared/pm_movevars.h b/pm_shared/pm_movevars.h index 3bea8b3..b145004 100644 --- a/pm_shared/pm_movevars.h +++ b/pm_shared/pm_movevars.h @@ -1,47 +1,47 @@ -//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -// pm_movevars.h -#if !defined( PM_MOVEVARSH ) -#define PM_MOVEVARSH - -// movevars_t // Physics variables. -typedef struct movevars_s movevars_t; - -struct movevars_s -{ - float gravity; // Gravity for map - float stopspeed; // Deceleration when not moving - float maxspeed; // Max allowed speed - float spectatormaxspeed; - float accelerate; // Acceleration factor - float airaccelerate; // Same for when in open air - float wateraccelerate; // Same for when in water - float friction; - float edgefriction; // Extra friction near dropofs - float waterfriction; // Less in water - float entgravity; // 1.0 - float bounce; // Wall bounce value. 1.0 - float stepsize; // sv_stepsize; - float maxvelocity; // maximum server velocity. - float zmax; // Max z-buffer range (for GL) - float waveHeight; // Water wave height (for GL) - qboolean footsteps; // Play footstep sounds - char skyName[32]; // Name of the sky map - float rollangle; - float rollspeed; - float skycolor_r; // Sky color - float skycolor_g; // - float skycolor_b; // - float skyvec_x; // Sky vector - float skyvec_y; // - float skyvec_z; // -}; - -extern movevars_t movevars; - -#endif +//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============ +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +// pm_movevars.h +#if !defined( PM_MOVEVARSH ) +#define PM_MOVEVARSH + +// movevars_t // Physics variables. +typedef struct movevars_s movevars_t; + +struct movevars_s +{ + float gravity; // Gravity for map + float stopspeed; // Deceleration when not moving + float maxspeed; // Max allowed speed + float spectatormaxspeed; + float accelerate; // Acceleration factor + float airaccelerate; // Same for when in open air + float wateraccelerate; // Same for when in water + float friction; + float edgefriction; // Extra friction near dropofs + float waterfriction; // Less in water + float entgravity; // 1.0 + float bounce; // Wall bounce value. 1.0 + float stepsize; // sv_stepsize; + float maxvelocity; // maximum server velocity. + float zmax; // Max z-buffer range (for GL) + float waveHeight; // Water wave height (for GL) + qboolean footsteps; // Play footstep sounds + char skyName[32]; // Name of the sky map + float rollangle; + float rollspeed; + float skycolor_r; // Sky color + float skycolor_g; // + float skycolor_b; // + float skyvec_x; // Sky vector + float skyvec_y; // + float skyvec_z; // +}; + +extern movevars_t movevars; + +#endif diff --git a/pm_shared/pm_shared.c b/pm_shared/pm_shared.c index 8b28473..3fb44bc 100644 --- a/pm_shared/pm_shared.c +++ b/pm_shared/pm_shared.c @@ -1,2802 +1,2802 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -#include -#include "mathlib.h" -#include "const.h" -#include "usercmd.h" -#include "pm_defs.h" -#include "pm_shared.h" -#include "pm_movevars.h" -#include "pm_debug.h" -#include -#include -#include -#include -#include - -#ifdef CLIENT_DLL - int iJumpSpectator; - float vJumpOrigin[3]; - float vJumpAngles[3]; -#endif - -static int pm_shared_initialized = 0; - -#ifdef _MSC_VER -#pragma warning(disable:4101) -#pragma warning(disable:4305) -#endif - -typedef enum -{ - mod_brush, - mod_sprite, - mod_alias, - mod_studio -} -modtype_t; - -playermove_t *pmove = NULL; - -typedef struct -{ - int planenum; - short children[2]; -} -dclipnode_t; - -typedef struct mplane_s -{ - vec3_t normal; - float dist; - byte type; - byte signbits; - byte pad[2]; -} -mplane_t; - -typedef struct hull_s -{ - dclipnode_t *clipnodes; - mplane_t *planes; - int firstclipnode; - int lastclipnode; - vec3_t clip_mins; - vec3_t clip_maxs; -} -hull_t; - -#define TIME_TO_DUCK 0.4 -#define VEC_DUCK_HULL_MIN -18 -#define VEC_DUCK_HULL_MAX 32 -#define VEC_DUCK_VIEW 12 -#define PM_DEAD_VIEWHEIGHT -8 -#define MAX_CLIMB_SPEED 200 -#define STUCK_MOVEUP 1 -#define STUCK_MOVEDOWN -1 -#define VEC_HULL_MIN -36 -#define VEC_HULL_MAX 36 - -#define VEC_VIEW 17 -#define STOP_EPSILON 0.1 - -#define CTEXTURESMAX 1024 - -#define CBTEXTURENAMEMAX 17 - -#define CHAR_TEX_CONCRETE 'C' -#define CHAR_TEX_METAL 'M' -#define CHAR_TEX_DIRT 'D' -#define CHAR_TEX_VENT 'V' -#define CHAR_TEX_GRATE 'G' -#define CHAR_TEX_TILE 'T' -#define CHAR_TEX_SLOSH 'S' -#define CHAR_TEX_WOOD 'W' -#define CHAR_TEX_COMPUTER 'P' -#define CHAR_TEX_GLASS 'Y' -#define CHAR_TEX_FLESH 'F' -#define CHAR_TEX_SNOW 'N' - -#define STEP_CONCRETE 0 -#define STEP_METAL 1 -#define STEP_DIRT 2 -#define STEP_VENT 3 -#define STEP_GRATE 4 -#define STEP_TILE 5 -#define STEP_SLOSH 6 -#define STEP_WADE 7 -#define STEP_LADDER 8 -#define STEP_SNOW 9 - -#define PLAYER_FATAL_FALL_SPEED 1024 -#define PLAYER_MAX_SAFE_FALL_SPEED 580 -#define DAMAGE_FOR_FALL_SPEED (float)100 / (PLAYER_FATAL_FALL_SPEED - PLAYER_MAX_SAFE_FALL_SPEED) - -#define PLAYER_MIN_BOUNCE_SPEED 350 - -#define PLAYER_FALL_PUNCH_THRESHHOLD (float)250 - -#define PLAYER_LONGJUMP_SPEED 350 - -#pragma warning(disable : 4244) - -#define max(a, b) (((a) > (b)) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) - -#define PITCH 0 -#define YAW 1 -#define ROLL 2 - -#define MAX_CLIENTS 32 - -#define CONTENTS_CURRENT_0 -9 -#define CONTENTS_CURRENT_90 -10 -#define CONTENTS_CURRENT_180 -11 -#define CONTENTS_CURRENT_270 -12 -#define CONTENTS_CURRENT_UP -13 -#define CONTENTS_CURRENT_DOWN -14 - -#define CONTENTS_TRANSLUCENT -15 - -static vec3_t rgv3tStuckTable[54]; -static int rgStuckLast[MAX_CLIENTS][2]; - -static int gcTextures = 0; -static char grgszTextureName[CTEXTURESMAX][CBTEXTURENAMEMAX]; -static char grgchTextureType[CTEXTURESMAX]; - -int g_onladder = 0; - -void PM_SwapTextures(int i, int j) -{ - char chTemp; - char szTemp[CBTEXTURENAMEMAX]; - - strcpy(szTemp, grgszTextureName[i]); - chTemp = grgchTextureType[i]; - - strcpy(grgszTextureName[i], grgszTextureName[j]); - grgchTextureType[i] = grgchTextureType[j]; - - strcpy(grgszTextureName[j], szTemp); - grgchTextureType[j] = chTemp; -} - -void PM_SortTextures(void) -{ - int i, j; - - for (i = 0 ; i < gcTextures; i++) - { - for (j = i + 1; j < gcTextures; j++) - { - if (stricmp(grgszTextureName[i], grgszTextureName[j]) > 0) - PM_SwapTextures(i, j); - } - } -} - -void PM_InitTextureTypes(void) -{ - char buffer[512]; - int i, j; - byte *pMemFile; - int fileSize, filePos = 0; - static qboolean bTextureTypeInit = false; - - if (bTextureTypeInit) - return; - - memset(&(grgszTextureName[0][0]), 0, CTEXTURESMAX * CBTEXTURENAMEMAX); - memset(grgchTextureType, 0, CTEXTURESMAX); - - gcTextures = 0; - memset(buffer, 0, 512); - - fileSize = pmove->COM_FileSize("sound/materials.txt"); - pMemFile = pmove->COM_LoadFile("sound/materials.txt", 5, NULL); - - if (!pMemFile) - return; - - filePos = 0; - - while (pmove->memfgets(pMemFile, fileSize, &filePos, buffer, 511) != NULL && (gcTextures < CTEXTURESMAX)) - { - i = 0; - - while (buffer[i] && isspace(buffer[i])) - i++; - - if (!buffer[i]) - continue; - - if (buffer[i] == '/' || !isalpha(buffer[i])) - continue; - - grgchTextureType[gcTextures] = toupper(buffer[i++]); - - while (buffer[i] && isspace(buffer[i])) - i++; - - if (!buffer[i]) - continue; - - j = i; - - while (buffer[j] && !isspace(buffer[j])) - j++; - - if (!buffer[j]) - continue; - - j = min (j, CBTEXTURENAMEMAX - 1 + i); - buffer[j] = 0; - strcpy(&(grgszTextureName[gcTextures++][0]), &(buffer[i])); - } - - pmove->COM_FreeFile(pMemFile); - - PM_SortTextures(); - - bTextureTypeInit = true; -} - -char PM_FindTextureType(char *name) -{ - int left, right, pivot; - int val; - - assert(pm_shared_initialized); - - left = 0; - right = gcTextures - 1; - - while (left <= right) - { - pivot = (left + right) / 2; - - val = strnicmp(name, grgszTextureName[pivot], CBTEXTURENAMEMAX - 1); - - if (val == 0) - { - return grgchTextureType[pivot]; - } - else if (val > 0) - { - left = pivot + 1; - } - else if (val < 0) - { - right = pivot - 1; - } - } - - return CHAR_TEX_CONCRETE; -} - -void PM_PlayStepSound(int step, float fvol) -{ - static int iSkipStep = 0; - int irand; - - pmove->iStepLeft = !pmove->iStepLeft; - - if (!pmove->runfuncs) - return; - - irand = pmove->RandomLong(0, 1) + (pmove->iStepLeft * 2); - - if (pmove->multiplayer && !pmove->movevars->footsteps) - return; - - switch (step) - { - default: - case STEP_CONCRETE: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_METAL: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_DIRT: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_VENT: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_GRATE: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_TILE: - { - if (!pmove->RandomLong(0, 4)) - irand = 4; - - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 4: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile5.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_SLOSH: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_WADE: - { - if (iSkipStep == 0) - { - iSkipStep++; - break; - } - - if (iSkipStep++ == 3) - iSkipStep = 0; - - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_LADDER: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - - case STEP_SNOW: - { - switch (irand) - { - case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; - } - - break; - } - } -} - -int PM_MapTextureTypeStepType( char chTextureType) -{ - switch (chTextureType) - { - default: - case CHAR_TEX_CONCRETE: return STEP_CONCRETE; - case CHAR_TEX_METAL: return STEP_METAL; - case CHAR_TEX_DIRT: return STEP_DIRT; - case CHAR_TEX_VENT: return STEP_VENT; - case CHAR_TEX_GRATE: return STEP_GRATE; - case CHAR_TEX_TILE: return STEP_TILE; - case CHAR_TEX_SLOSH: return STEP_SLOSH; - case CHAR_TEX_SNOW: return STEP_SNOW; - } -} - -void PM_CatagorizeTextureType(void) -{ - vec3_t start, end; - const char *pTextureName; - - VectorCopy(pmove->origin, start); - VectorCopy(pmove->origin, end); - - end[2] -= 64; - - pmove->sztexturename[0] = '\0'; - pmove->chtexturetype = CHAR_TEX_CONCRETE; - - pTextureName = pmove->PM_TraceTexture(pmove->onground, start, end); - - if (!pTextureName) - return; - - if (*pTextureName == '-' || *pTextureName == '+') - pTextureName += 2; - - if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') - pTextureName++; - - strcpy(pmove->sztexturename, pTextureName); - pmove->sztexturename[CBTEXTURENAMEMAX - 1] = 0; - - pmove->chtexturetype = PM_FindTextureType(pmove->sztexturename); -} - -void PM_UpdateStepSound(void) -{ - float fvol; - vec3_t knee; - vec3_t feet; - vec3_t center; - float height; - float speed; - int fLadder; - int step; - - if (pmove->flTimeStepSound > 0) - return; - - if (pmove->flags & FL_FROZEN) - return; - - speed = Length(pmove->velocity); - - if (speed < 150) - { - pmove->flTimeStepSound = 400; - return; - } - - fLadder = (pmove->movetype == MOVETYPE_FLY); - - if (fLadder || (pmove->onground != -1)) - { - PM_CatagorizeTextureType(); - - VectorCopy(pmove->origin, center); - VectorCopy(pmove->origin, knee); - VectorCopy(pmove->origin, feet); - - height = pmove->player_maxs[pmove->usehull][2] - pmove->player_mins[pmove->usehull][2]; - - knee[2] = pmove->origin[2] - 0.3 * height; - feet[2] = pmove->origin[2] - 0.5 * height; - - if (fLadder) - { - step = STEP_LADDER; - fvol = 0.35; - pmove->flTimeStepSound = 350; - } - else if (pmove->PM_PointContents(knee, NULL) == CONTENTS_WATER) - { - step = STEP_WADE; - fvol = 0.65; - pmove->flTimeStepSound = 600; - } - else if (pmove->PM_PointContents(feet, NULL) == CONTENTS_WATER) - { - step = STEP_SLOSH; - fvol = 0.5; - pmove->flTimeStepSound = 300; - } - else - { - step = PM_MapTextureTypeStepType(pmove->chtexturetype); - - switch (pmove->chtexturetype) - { - case CHAR_TEX_CONCRETE: - { - fvol = 0.5; - pmove->flTimeStepSound = 300; - break; - } - - case CHAR_TEX_METAL: - { - fvol = 0.5; - pmove->flTimeStepSound = 300; - break; - } - - case CHAR_TEX_DIRT: - { - fvol = 0.55; - pmove->flTimeStepSound = 300; - break; - } - - case CHAR_TEX_VENT: - { - fvol = 0.7; - pmove->flTimeStepSound = 300; - break; - } - - default: - { - fvol = 0.5; - break; - } - - case CHAR_TEX_GRATE: - { - fvol = 0.5; - pmove->flTimeStepSound = 300; - break; - } - - case CHAR_TEX_TILE: - { - fvol = 0.5; - pmove->flTimeStepSound = 300; - break; - } - - case CHAR_TEX_SLOSH: - { - fvol = 0.5; - pmove->flTimeStepSound = 300; - break; - } - - case CHAR_TEX_SNOW: - { - fvol = 0.5; - pmove->flTimeStepSound = 300; - break; - } - - pmove->flTimeStepSound = 300; - } - } - - if (pmove->flags & FL_DUCKING || fLadder) - { - pmove->flTimeStepSound += 100; - - if (pmove->flags & FL_DUCKING && pmove->flDuckTime < 950.0) - fvol *= 0.35; - } - - PM_PlayStepSound(step, fvol); - } -} - -qboolean PM_AddToTouched(pmtrace_t tr, vec3_t impactvelocity) -{ - int i; - - for (i = 0; i < pmove->numtouch; i++) - { - if (pmove->touchindex[i].ent == tr.ent) - break; - } - - if (i != pmove->numtouch) - return false; - - VectorCopy(impactvelocity, tr.deltavelocity); - - if (pmove->numtouch >= MAX_PHYSENTS) - pmove->Con_DPrintf("Too many entities were touched!\n"); - - pmove->touchindex[pmove->numtouch++] = tr; - return true; -} - -void PM_CheckVelocity(void) -{ - int i; - - for (i = 0; i < 3; i++) - { - if (IS_NAN(pmove->velocity[i])) - { - pmove->Con_Printf("PM Got a NaN velocity %i\n", i); - pmove->velocity[i] = 0; - } - if (IS_NAN(pmove->origin[i])) - { - pmove->Con_Printf("PM Got a NaN origin on %i\n", i); - pmove->origin[i] = 0; - } - - if (pmove->velocity[i] > pmove->movevars->maxvelocity) - { - pmove->Con_DPrintf("PM Got a velocity too high on %i\n", i); - pmove->velocity[i] = pmove->movevars->maxvelocity; - } - else if (pmove->velocity[i] < -pmove->movevars->maxvelocity) - { - pmove->Con_DPrintf("PM Got a velocity too low on %i\n", i); - pmove->velocity[i] = -pmove->movevars->maxvelocity; - } - } -} - -int PM_ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce) -{ - float backoff; - float change; - float angle; - int i, blocked; - - angle = normal[2]; - - blocked = 0x00; - - if (angle > 0) - blocked |= 0x01; - - if (!angle) - blocked |= 0x02; - - backoff = DotProduct(in, normal) * overbounce; - - for (i = 0; i < 3; i++) - { - change = normal[i] * backoff; - out[i] = in[i] - change; - - if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) - out[i] = 0; - } - - return blocked; -} - -void PM_AddCorrectGravity(void) -{ - float ent_gravity; - - if (pmove->waterjumptime) - return; - - if (pmove->gravity) - ent_gravity = pmove->gravity; - else - ent_gravity = 1.0; - - pmove->velocity[2] -= (ent_gravity * pmove->movevars->gravity * 0.5 * pmove->frametime); - pmove->velocity[2] += pmove->basevelocity[2] * pmove->frametime; - pmove->basevelocity[2] = 0; - - PM_CheckVelocity(); -} - -void PM_FixupGravityVelocity(void) -{ - float ent_gravity; - - if (pmove->waterjumptime) - return; - - if (pmove->gravity) - ent_gravity = pmove->gravity; - else - ent_gravity = 1.0; - - pmove->velocity[2] -= (ent_gravity * pmove->movevars->gravity * pmove->frametime * 0.5); - - PM_CheckVelocity(); -} - -int PM_FlyMove(void) -{ - int bumpcount, numbumps; - vec3_t dir; - float d; - int numplanes; - vec3_t planes[MAX_CLIP_PLANES]; - vec3_t primal_velocity, original_velocity; - vec3_t new_velocity; - int i, j; - pmtrace_t trace; - vec3_t end; - float time_left, allFraction; - int blocked; - - numbumps = 4; - - blocked = 0; - numplanes = 0; - - VectorCopy(pmove->velocity, original_velocity); - VectorCopy(pmove->velocity, primal_velocity); - - allFraction = 0; - time_left = pmove->frametime; - - for (bumpcount = 0; bumpcount < numbumps; bumpcount++) - { - if (!pmove->velocity[0] && !pmove->velocity[1] && !pmove->velocity[2]) - break; - - for (i = 0; i < 3; i++) - end[i] = pmove->origin[i] + time_left * pmove->velocity[i]; - - trace = pmove->PM_PlayerTrace(pmove->origin, end, PM_NORMAL, -1); - - allFraction += trace.fraction; - - if (trace.allsolid) - { - VectorCopy(vec3_origin, pmove->velocity); - return 4; - } - - if (trace.fraction > 0) - { - VectorCopy(trace.endpos, pmove->origin); - VectorCopy(pmove->velocity, original_velocity); - numplanes = 0; - } - - if (trace.fraction == 1) - break; - - PM_AddToTouched(trace, pmove->velocity); - - if (trace.plane.normal[2] > 0.7) - blocked |= 1; - - if (!trace.plane.normal[2]) - blocked |= 2; - - time_left -= time_left * trace.fraction; - - if (numplanes >= MAX_CLIP_PLANES) - { - VectorCopy(vec3_origin, pmove->velocity); - break; - } - - VectorCopy(trace.plane.normal, planes[numplanes]); - numplanes++; - - if (pmove->movetype == MOVETYPE_WALK && ((pmove->onground == -1) || (pmove->friction != 1))) - { - for (i = 0; i < numplanes; i++) - { - if (planes[i][2] > 0.7) - { - PM_ClipVelocity(original_velocity, planes[i], new_velocity, 1); - VectorCopy(new_velocity, original_velocity); - } - else - PM_ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + pmove->movevars->bounce * (1 - pmove->friction)); - } - - VectorCopy(new_velocity, pmove->velocity); - VectorCopy(new_velocity, original_velocity); - } - else - { - for (i = 0; i < numplanes; i++) - { - PM_ClipVelocity(original_velocity, planes[i], pmove->velocity, 1); - - for (j = 0; j velocity, planes[j]) < 0) - break; - } - } - - if (j == numplanes) - break; - } - - if (i != numplanes) - { - } - else - { - if (numplanes != 2) - { - VectorCopy(vec3_origin, pmove->velocity); - break; - } - - CrossProduct(planes[0], planes[1], dir); - d = DotProduct(dir, pmove->velocity); - VectorScale(dir, d, pmove->velocity); - } - - if (DotProduct(pmove->velocity, primal_velocity) <= 0) - { - VectorCopy(vec3_origin, pmove->velocity); - break; - } - } - } - - if (allFraction == 0) - VectorCopy(vec3_origin, pmove->velocity); - - return blocked; -} - -void PM_Accelerate(vec3_t wishdir, float wishspeed, float accel) -{ - int i; - float addspeed, accelspeed, currentspeed; - - if (pmove->dead) - return; - - if (pmove->waterjumptime) - return; - - currentspeed = DotProduct(pmove->velocity, wishdir); - - addspeed = wishspeed - currentspeed; - - if (addspeed <= 0) - return; - - accelspeed = accel * pmove->frametime * wishspeed * pmove->friction; - - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i = 0; i < 3; i++) - pmove->velocity[i] += accelspeed * wishdir[i]; -} - -void PM_WalkMove(void) -{ - int clip; - int oldonground; - int i; - - vec3_t wishvel; - float spd; - float fmove, smove; - vec3_t wishdir; - float wishspeed; - - vec3_t dest, start; - vec3_t original, originalvel; - vec3_t down, downvel; - float downdist, updist; - - pmtrace_t trace; - - if (pmove->fuser2 > 0.0) - { - float factor; - factor = (100.0 - pmove->fuser2 * 0.001 * 19.0) * 0.01; - pmove->velocity[0] *= factor; - pmove->velocity[1] *= factor; - } - - fmove = pmove->cmd.forwardmove; - smove = pmove->cmd.sidemove; - - pmove->forward[2] = 0; - pmove->right[2] = 0; - - VectorNormalize(pmove->forward); - VectorNormalize(pmove->right); - - for (i = 0; i < 2; i++) - wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; - - wishvel[2] = 0; - - VectorCopy(wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); - - if (wishspeed > pmove->maxspeed) - { - VectorScale(wishvel, pmove->maxspeed/wishspeed, wishvel); - wishspeed = pmove->maxspeed; - } - - pmove->velocity[2] = 0; - - PM_Accelerate(wishdir, wishspeed, pmove->movevars->accelerate); - pmove->velocity[2] = 0; - - VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); - - spd = Length(pmove->velocity); - - if (spd < 1.0f) - { - VectorClear(pmove->velocity); - return; - } - - oldonground = pmove->onground; - - dest[0] = pmove->origin[0] + pmove->velocity[0]*pmove->frametime; - dest[1] = pmove->origin[1] + pmove->velocity[1]*pmove->frametime; - dest[2] = pmove->origin[2]; - - VectorCopy(dest, start); - trace = pmove->PM_PlayerTrace(pmove->origin, dest, PM_NORMAL, -1); - - if (trace.fraction == 1) - { - VectorCopy(trace.endpos, pmove->origin); - return; - } - - if (oldonground == -1 && pmove->waterlevel == 0) - return; - - if (pmove->waterjumptime) - return; - - VectorCopy(pmove->origin, original); - VectorCopy(pmove->velocity, originalvel); - - clip = PM_FlyMove(); - - VectorCopy(pmove->origin, down); - VectorCopy(pmove->velocity, downvel); - - VectorCopy(original, pmove->origin); - VectorCopy(originalvel, pmove->velocity); - - VectorCopy(pmove->origin, dest); - dest[2] += pmove->movevars->stepsize; - - trace = pmove->PM_PlayerTrace(pmove->origin, dest, PM_NORMAL, -1); - - if (!trace.startsolid && !trace.allsolid) - VectorCopy(trace.endpos, pmove->origin); - - clip = PM_FlyMove(); - - VectorCopy(pmove->origin, dest); - dest[2] -= pmove->movevars->stepsize; - - trace = pmove->PM_PlayerTrace(pmove->origin, dest, PM_NORMAL, -1); - - if (trace.plane.normal[2] < 0.7) - goto usedown; - - if (!trace.startsolid && !trace.allsolid) - VectorCopy(trace.endpos, pmove->origin); - - VectorCopy(pmove->origin, pmove->up); - - downdist = (down[0] - original[0])*(down[0] - original[0]) + (down[1] - original[1])*(down[1] - original[1]); - updist = (pmove->up[0] - original[0])*(pmove->up[0] - original[0]) + (pmove->up[1] - original[1])*(pmove->up[1] - original[1]); - - if (downdist > updist) - { -usedown: - VectorCopy(down, pmove->origin); - VectorCopy(downvel, pmove->velocity); - } - else - pmove->velocity[2] = downvel[2]; -} - -void PM_Friction(void) -{ - float *vel; - float speed, newspeed, control; - float friction; - float drop; - vec3_t newvel; - - if (pmove->waterjumptime) - return; - - vel = pmove->velocity; - - speed = sqrt(vel[0] * vel[0] +vel[1] * vel[1] + vel[2] * vel[2]); - - if (speed < 0.1f) - return; - - drop = 0; - - if (pmove->onground != -1) - { - vec3_t start, stop; - pmtrace_t trace; - - start[0] = stop[0] = pmove->origin[0] + vel[0] / speed * 16; - start[1] = stop[1] = pmove->origin[1] + vel[1] / speed * 16; - start[2] = pmove->origin[2] + pmove->player_mins[pmove->usehull][2]; - stop[2] = start[2] - 34; - - trace = pmove->PM_PlayerTrace(start, stop, PM_NORMAL, -1); - - if (trace.fraction == 1.0) - friction = pmove->movevars->friction * pmove->movevars->edgefriction; - else - friction = pmove->movevars->friction; - - friction *= pmove->friction; - - control = (speed < pmove->movevars->stopspeed) ? pmove->movevars->stopspeed : speed; - drop += control*friction*pmove->frametime; - } - - newspeed = speed - drop; - - if (newspeed < 0) - newspeed = 0; - - newspeed /= speed; - - newvel[0] = vel[0] * newspeed; - newvel[1] = vel[1] * newspeed; - newvel[2] = vel[2] * newspeed; - - VectorCopy(newvel, pmove->velocity); -} - -void PM_AirAccelerate(vec3_t wishdir, float wishspeed, float accel) -{ - int i; - float addspeed, accelspeed, currentspeed, wishspd = wishspeed; - - if (pmove->dead) - return; - - if (pmove->waterjumptime) - return; - - if (wishspd > 30) - wishspd = 30; - - currentspeed = DotProduct(pmove->velocity, wishdir); - addspeed = wishspd - currentspeed; - - if (addspeed <= 0) - return; - - accelspeed = accel * wishspeed * pmove->frametime * pmove->friction; - - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i = 0; i < 3; i++) - pmove->velocity[i] += accelspeed * wishdir[i]; -} - -void PM_WaterMove(void) -{ - int i; - vec3_t wishvel; - float wishspeed; - vec3_t wishdir; - vec3_t start, dest; - vec3_t temp; - pmtrace_t trace; - - float speed, newspeed, addspeed, accelspeed; - - for (i = 0; i < 3; i++) - wishvel[i] = pmove->forward[i] * pmove->cmd.forwardmove + pmove->right[i] * pmove->cmd.sidemove; - - if (!pmove->cmd.forwardmove && !pmove->cmd.sidemove && !pmove->cmd.upmove) - wishvel[2] -= 60; - else - wishvel[2] += pmove->cmd.upmove; - - VectorCopy(wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); - - if (wishspeed > pmove->maxspeed) - { - VectorScale(wishvel, pmove->maxspeed / wishspeed, wishvel); - wishspeed = pmove->maxspeed; - } - - wishspeed *= 0.8; - - VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); - VectorCopy(pmove->velocity, temp); - speed = VectorNormalize(temp); - - if (speed) - { - newspeed = speed - pmove->frametime * speed * pmove->movevars->friction * pmove->friction; - - if (newspeed < 0) - newspeed = 0; - - VectorScale(pmove->velocity, newspeed / speed, pmove->velocity); - } - else - newspeed = 0; - - if (wishspeed < 0.1f) - return; - - addspeed = wishspeed - newspeed; - - if (addspeed > 0) - { - VectorNormalize(wishvel); - accelspeed = pmove->movevars->accelerate * wishspeed * pmove->frametime * pmove->friction; - - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i = 0; i < 3; i++) - pmove->velocity[i] += accelspeed * wishvel[i]; - } - - VectorMA(pmove->origin, pmove->frametime, pmove->velocity, dest); - VectorCopy(dest, start); - start[2] += pmove->movevars->stepsize + 1; - trace = pmove->PM_PlayerTrace(start, dest, PM_NORMAL, -1); - - if (!trace.startsolid && !trace.allsolid) - { - VectorCopy(trace.endpos, pmove->origin); - return; - } - - PM_FlyMove(); -} - -void PM_AirMove(void) -{ - int i; - vec3_t wishvel; - float fmove, smove; - vec3_t wishdir; - float wishspeed; - - fmove = pmove->cmd.forwardmove; - smove = pmove->cmd.sidemove; - - pmove->forward[2] = 0; - pmove->right[2] = 0; - - VectorNormalize(pmove->forward); - VectorNormalize(pmove->right); - - for (i = 0; i < 2; i++) - { - wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; - } - - wishvel[2] = 0; - - VectorCopy(wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); - - if (wishspeed > pmove->maxspeed) - { - VectorScale(wishvel, pmove->maxspeed / wishspeed, wishvel); - wishspeed = pmove->maxspeed; - } - - PM_AirAccelerate(wishdir, wishspeed, pmove->movevars->airaccelerate); - - VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); - - PM_FlyMove(); -} - -qboolean PM_InWater(void) -{ - return (pmove->waterlevel > 1); -} - -qboolean PM_CheckWater(void) -{ - vec3_t point; - int cont; - int truecont; - float height; - float heightover2; - - point[0] = pmove->origin[0] + (pmove->player_mins[pmove->usehull][0] + pmove->player_maxs[pmove->usehull][0]) * 0.5; - point[1] = pmove->origin[1] + (pmove->player_mins[pmove->usehull][1] + pmove->player_maxs[pmove->usehull][1]) * 0.5; - point[2] = pmove->origin[2] + pmove->player_mins[pmove->usehull][2] + 1; - - pmove->waterlevel = 0; - pmove->watertype = CONTENTS_EMPTY; - - cont = pmove->PM_PointContents(point, &truecont); - - if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT) - { - pmove->watertype = cont; - pmove->waterlevel = 1; - - height = (pmove->player_mins[pmove->usehull][2] + pmove->player_maxs[pmove->usehull][2]); - heightover2 = height * 0.5; - - point[2] = pmove->origin[2] + heightover2; - cont = pmove->PM_PointContents(point, NULL); - - if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT) - { - pmove->waterlevel = 2; - - point[2] = pmove->origin[2] + pmove->view_ofs[2]; - - cont = pmove->PM_PointContents(point, NULL); - - if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT) - pmove->waterlevel = 3; - } - - if ((truecont <= CONTENTS_CURRENT_0) && (truecont >= CONTENTS_CURRENT_DOWN)) - { - static vec3_t current_table[] = - { - { 1, 0, 0 }, { 0, 1, 0 }, { -1, 0, 0 }, - { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 } - }; - - VectorMA(pmove->basevelocity, 50.0 * pmove->waterlevel, current_table[CONTENTS_CURRENT_0 - truecont], pmove->basevelocity); - } - } - - return pmove->waterlevel > 1; -} - -void PM_CatagorizePosition(void) -{ - vec3_t point; - pmtrace_t tr; - - PM_CheckWater(); - - point[0] = pmove->origin[0]; - point[1] = pmove->origin[1]; - point[2] = pmove->origin[2] - 2; - - if (pmove->velocity[2] > 180) - { - pmove->onground = -1; - } - else - { - tr = pmove->PM_PlayerTrace(pmove->origin, point, PM_NORMAL, -1); - - if (tr.plane.normal[2] < 0.7) - pmove->onground = -1; - else - pmove->onground = tr.ent; - - if (pmove->onground != -1) - { - pmove->waterjumptime = 0; - - if (pmove->waterlevel < 2 && !tr.startsolid && !tr.allsolid) - VectorCopy(tr.endpos, pmove->origin); - } - - if (tr.ent > 0) - { - PM_AddToTouched(tr, pmove->velocity); - } - } -} - -int PM_GetRandomStuckOffsets(int nIndex, int server, vec3_t offset) -{ - int idx; - idx = rgStuckLast[nIndex][server]++; - - VectorCopy(rgv3tStuckTable[idx % 54], offset); - - return (idx % 54); -} - -void PM_ResetStuckOffsets(int nIndex, int server) -{ - rgStuckLast[nIndex][server] = 0; -} - -#define PM_CHECKSTUCK_MINTIME 0.05 - -int PM_CheckStuck(void) -{ - vec3_t base; - vec3_t offset; - vec3_t test; - int hitent; - int idx; - float fTime; - int i; - pmtrace_t traceresult; - - static float rgStuckCheckTime[MAX_CLIENTS][2]; - - hitent = pmove->PM_TestPlayerPosition(pmove->origin, &traceresult); - - if (hitent == -1) - { - PM_ResetStuckOffsets(pmove->player_index, pmove->server); - return 0; - } - - VectorCopy(pmove->origin, base); - - if (!pmove->server) - { - if ((hitent == 0) || (pmove->physents[hitent].model != NULL)) - { - int nReps = 0; - - PM_ResetStuckOffsets(pmove->player_index, pmove->server); - - do - { - i = PM_GetRandomStuckOffsets(pmove->player_index, pmove->server, offset); - - VectorAdd(base, offset, test); - - if (pmove->PM_TestPlayerPosition(test, &traceresult) == -1) - { - PM_ResetStuckOffsets(pmove->player_index, pmove->server); - - VectorCopy(test, pmove->origin); - return 0; - } - - nReps++; - } - while (nReps < 54); - } - } - - if (pmove->server) - idx = 0; - else - idx = 1; - - fTime = pmove->Sys_FloatTime(); - - if (rgStuckCheckTime[pmove->player_index][idx] >= (fTime - PM_CHECKSTUCK_MINTIME)) - return 1; - - rgStuckCheckTime[pmove->player_index][idx] = fTime; - - pmove->PM_StuckTouch(hitent, &traceresult); - - i = PM_GetRandomStuckOffsets(pmove->player_index, pmove->server, offset); - - VectorAdd(base, offset, test); - - if ((hitent = pmove->PM_TestPlayerPosition(test, NULL)) == -1) - { - PM_ResetStuckOffsets(pmove->player_index, pmove->server); - - if (i >= 27) - VectorCopy(test, pmove->origin); - - return 0; - } - - if (pmove->cmd.buttons & (IN_JUMP | IN_DUCK | IN_ATTACK) && ( pmove->physents[hitent].player != 0)) - { - float x, y, z; - float xystep = 8.0; - float zstep = 18.0; - float xyminmax = xystep; - float zminmax = 4 * zstep; - - for (z = 0; z <= zminmax; z += zstep) - { - for (x = -xyminmax; x <= xyminmax; x += xystep) - { - for (y = -xyminmax; y <= xyminmax; y += xystep) - { - VectorCopy(base, test); - test[0] += x; - test[1] += y; - test[2] += z; - - if (pmove->PM_TestPlayerPosition(test, NULL) == -1) - { - VectorCopy(test, pmove->origin); - return 0; - } - } - } - } - } - - return 1; -} - -void PM_SpectatorMove(void) -{ - float speed, drop, friction, control, newspeed; - float accel; - float currentspeed, addspeed, accelspeed; - int i; - vec3_t wishvel; - float fmove, smove; - vec3_t wishdir; - float wishspeed; - - if (pmove->iuser1 == OBS_ROAMING) - { -#ifdef CLIENT_DLL - if (iJumpSpectator) - { - VectorCopy(vJumpOrigin, pmove->origin); - VectorCopy(vJumpAngles, pmove->angles); - VectorCopy(vec3_origin, pmove->velocity); - iJumpSpectator = 0; - return; - } -#endif - speed = Length(pmove->velocity); - - if (speed < 1) - { - VectorCopy(vec3_origin, pmove->velocity) - } - else - { - drop = 0; - - friction = pmove->movevars->friction * 1.5; - control = speed < pmove->movevars->stopspeed ? pmove->movevars->stopspeed : speed; - drop += control*friction*pmove->frametime; - - newspeed = speed - drop; - - if (newspeed < 0) - newspeed = 0; - - newspeed /= speed; - - VectorScale(pmove->velocity, newspeed, pmove->velocity); - } - - fmove = pmove->cmd.forwardmove; - smove = pmove->cmd.sidemove; - - VectorNormalize(pmove->forward); - VectorNormalize(pmove->right); - - for (i = 0; i < 3; i++) - wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; - - wishvel[2] += pmove->cmd.upmove; - - VectorCopy(wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); - - if (wishspeed > pmove->movevars->spectatormaxspeed) - { - VectorScale(wishvel, pmove->movevars->spectatormaxspeed / wishspeed, wishvel); - wishspeed = pmove->movevars->spectatormaxspeed; - } - - currentspeed = DotProduct(pmove->velocity, wishdir); - addspeed = wishspeed - currentspeed; - - if (addspeed <= 0) - return; - - accelspeed = pmove->movevars->accelerate * pmove->frametime * wishspeed; - - if (accelspeed > addspeed) - accelspeed = addspeed; - - for (i = 0; i < 3; i++) - pmove->velocity[i] += accelspeed * wishdir[i]; - - VectorMA(pmove->origin, pmove->frametime, pmove->velocity, pmove->origin); - } - else - { - int target; - - if (pmove->iuser2 <= 0) - return; - - for (target = 0; target < pmove->numphysent; target++) - { - if (pmove->physents[target].info == pmove->iuser2) - break; - } - - if (target == pmove->numphysent) - return; - - VectorCopy(pmove->physents[target].angles, pmove->angles); - VectorCopy(pmove->physents[target].origin, pmove->origin); - - VectorCopy(vec3_origin, pmove->velocity); - } -} - -float PM_SplineFraction(float value, float scale) -{ - float valueSquared; - - value = scale * value; - valueSquared = value * value; - - return 3 * valueSquared - 2 * valueSquared * value; -} - -void PM_FixPlayerCrouchStuck(int direction) -{ - int hitent; - int i; - vec3_t test; - - hitent = pmove->PM_TestPlayerPosition(pmove->origin, NULL); - - if (hitent == -1) - return; - - VectorCopy(pmove->origin, test); - - for (i = 0; i < 36; i++) - { - pmove->origin[2] += direction; - hitent = pmove->PM_TestPlayerPosition(pmove->origin, NULL); - - if (hitent == -1) - return; - } - - VectorCopy(test, pmove->origin); -} - -void PM_UnDuck(void) -{ - int i; - pmtrace_t trace; - vec3_t newOrigin; - - VectorCopy(pmove->origin, newOrigin); - - if (pmove->onground != -1) - { - newOrigin[2] += 18.0; - } - - trace = pmove->PM_PlayerTrace(newOrigin, newOrigin, PM_NORMAL, -1); - - if (!trace.startsolid) - { - pmove->usehull = 0; - - trace = pmove->PM_PlayerTrace(newOrigin, newOrigin, PM_NORMAL, -1); - - if (trace.startsolid) - { - pmove->usehull = 1; - return; - } - - pmove->flags &= ~FL_DUCKING; - pmove->bInDuck = false; - pmove->view_ofs[2] = VEC_VIEW; - pmove->flDuckTime = 0; - - pmove->flTimeStepSound -= 100; - - if (pmove->flTimeStepSound < 0) - { - pmove->flTimeStepSound = 0; - } - - VectorCopy(newOrigin, pmove->origin); - - PM_CatagorizePosition(); - } -} - -void PM_Duck(void) -{ - int i; - float time; - float duckFraction; - - int buttonsChanged = (pmove->oldbuttons ^ pmove->cmd.buttons); - int nButtonPressed = buttonsChanged & pmove->cmd.buttons; - - int duckchange = buttonsChanged & IN_DUCK ? 1 : 0; - int duckpressed = nButtonPressed & IN_DUCK ? 1 : 0; - - if (pmove->cmd.buttons & IN_DUCK) - { - pmove->oldbuttons |= IN_DUCK; - } - else - { - pmove->oldbuttons &= ~IN_DUCK; - } - - if (pmove->dead) - return; - - if ((pmove->cmd.buttons & IN_DUCK) || (pmove->bInDuck) || (pmove->flags & FL_DUCKING)) - { - pmove->cmd.forwardmove *= 0.333; - pmove->cmd.sidemove *= 0.333; - pmove->cmd.upmove *= 0.333; - - if (pmove->cmd.buttons & IN_DUCK) - { - if ((nButtonPressed & IN_DUCK) && !(pmove->flags & FL_DUCKING)) - { - pmove->flDuckTime = 1000; - pmove->bInDuck = true; - } - - time = max(0.0, ( 1.0 - (float)pmove->flDuckTime / 1000.0)); - - if (pmove->bInDuck) - { - if (((float)pmove->flDuckTime / 1000.0 <= (1.0 - TIME_TO_DUCK)) || (pmove->onground == -1)) - { - pmove->usehull = 1; - pmove->view_ofs[2] = VEC_DUCK_VIEW; - - pmove->flags |= FL_DUCKING; - pmove->bInDuck = false; - - if (pmove->onground != -1) - { - pmove->origin[2] = pmove->origin[2] - 18.0; - - PM_FixPlayerCrouchStuck(STUCK_MOVEUP); - - PM_CatagorizePosition(); - } - } - else - { - float fMore = (VEC_DUCK_HULL_MIN - VEC_HULL_MIN); - - duckFraction = PM_SplineFraction(time, (1.0 / TIME_TO_DUCK)); - pmove->view_ofs[2] = ((VEC_DUCK_VIEW - fMore) * duckFraction) + (VEC_VIEW * (1 - duckFraction)); - } - } - } - else - { - PM_UnDuck(); - } - } -} - -void PM_LadderMove(physent_t *pLadder) -{ - vec3_t ladderCenter; - trace_t trace; - qboolean onFloor; - vec3_t floor; - vec3_t modelmins, modelmaxs; - - if (pmove->movetype == MOVETYPE_NOCLIP) - return; - - pmove->PM_GetModelBounds(pLadder->model, modelmins, modelmaxs); - - VectorAdd(modelmins, modelmaxs, ladderCenter); - VectorScale(ladderCenter, 0.5, ladderCenter); - - pmove->movetype = MOVETYPE_FLY; - - VectorCopy(pmove->origin, floor); - floor[2] += pmove->player_mins[pmove->usehull][2] - 1; - - if (pmove->PM_PointContents(floor, NULL) == CONTENTS_SOLID) - onFloor = true; - else - onFloor = false; - - pmove->gravity = 0; - pmove->PM_TraceModel(pLadder, pmove->origin, ladderCenter, &trace); - - if (trace.fraction != 1.0) - { - float forward = 0, right = 0; - vec3_t vpn, v_right; - - float flSpeed = MAX_CLIMB_SPEED; - - if (pmove->maxspeed < MAX_CLIMB_SPEED) - flSpeed = pmove->maxspeed; - - AngleVectors(pmove->angles, vpn, v_right, NULL); - - if (pmove->flags & FL_DUCKING) - { - flSpeed *= 0.333; - } - - if (pmove->cmd.buttons & IN_BACK) - forward -= flSpeed; - - if (pmove->cmd.buttons & IN_FORWARD) - forward += flSpeed; - - if (pmove->cmd.buttons & IN_MOVELEFT) - right -= flSpeed; - - if (pmove->cmd.buttons & IN_MOVERIGHT) - right += flSpeed; - - if (pmove->cmd.buttons & IN_JUMP) - { - pmove->movetype = MOVETYPE_WALK; - VectorScale(trace.plane.normal, 270, pmove->velocity); - } - else - { - if (forward != 0 || right != 0) - { - vec3_t velocity, perp, cross, lateral, tmp; - float normal; - - VectorScale(vpn, forward, velocity); - VectorMA(velocity, right, v_right, velocity); - - VectorClear(tmp); - tmp[2] = 1; - CrossProduct(tmp, trace.plane.normal, perp); - VectorNormalize(perp); - - normal = DotProduct(velocity, trace.plane.normal); - VectorScale(trace.plane.normal, normal, cross); - - VectorSubtract(velocity, cross, lateral); - - CrossProduct(trace.plane.normal, perp, tmp); - VectorMA(lateral, -normal, tmp, pmove->velocity); - - if (onFloor && normal > 0) - { - VectorMA(pmove->velocity, MAX_CLIMB_SPEED, trace.plane.normal, pmove->velocity); - } - } - else - { - VectorClear(pmove->velocity); - } - } - } -} - -physent_t *PM_Ladder(void) -{ - int i; - physent_t *pe; - hull_t *hull; - int num; - vec3_t test; - - for (i = 0; i < pmove->nummoveent; i++) - { - pe = &pmove->moveents[i]; - - if (pe->model && (modtype_t)pmove->PM_GetModelType(pe->model) == mod_brush && pe->skin == CONTENTS_LADDER) - { - hull = (hull_t *)pmove->PM_HullForBsp(pe, test); - num = hull->firstclipnode; - - VectorSubtract(pmove->origin, test, test); - - if (pmove->PM_HullPointContents (hull, num, test) == CONTENTS_EMPTY) - continue; - - return pe; - } - } - - return NULL; -} - -void PM_WaterJump(void) -{ - if (pmove->waterjumptime > 10000) - pmove->waterjumptime = 10000; - - if (!pmove->waterjumptime) - return; - - pmove->waterjumptime -= pmove->cmd.msec; - - if (pmove->waterjumptime < 0 || !pmove->waterlevel) - { - pmove->waterjumptime = 0; - pmove->flags &= ~FL_WATERJUMP; - } - - pmove->velocity[0] = pmove->movedir[0]; - pmove->velocity[1] = pmove->movedir[1]; -} - -void PM_AddGravity(void) -{ - float ent_gravity; - - if (pmove->gravity) - ent_gravity = pmove->gravity; - else - ent_gravity = 1.0; - - pmove->velocity[2] -= (ent_gravity * pmove->movevars->gravity * pmove->frametime); - pmove->velocity[2] += pmove->basevelocity[2] * pmove->frametime; - pmove->basevelocity[2] = 0; - PM_CheckVelocity(); -} - -pmtrace_t PM_PushEntity(vec3_t push) -{ - pmtrace_t trace; - vec3_t end; - - VectorAdd(pmove->origin, push, end); - - trace = pmove->PM_PlayerTrace(pmove->origin, end, PM_NORMAL, -1); - - VectorCopy(trace.endpos, pmove->origin); - - if (trace.fraction < 1.0 && !trace.allsolid) - { - PM_AddToTouched(trace, pmove->velocity); - } - - return trace; -} - -void PM_Physics_Toss(void) -{ - pmtrace_t trace; - vec3_t move; - float backoff; - - PM_CheckWater(); - - if (pmove->velocity[2] > 0) - pmove->onground = -1; - - if (pmove->onground != -1) - { - if (VectorCompare(pmove->basevelocity, vec3_origin) && VectorCompare(pmove->velocity, vec3_origin)) - return; - } - - PM_CheckVelocity(); - - if (pmove->movetype != MOVETYPE_FLY && pmove->movetype != MOVETYPE_BOUNCEMISSILE && pmove->movetype != MOVETYPE_FLYMISSILE) - PM_AddGravity(); - - VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); - - PM_CheckVelocity(); - VectorScale(pmove->velocity, pmove->frametime, move); - VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); - - trace = PM_PushEntity(move); - - PM_CheckVelocity(); - - if (trace.allsolid) - { - pmove->onground = trace.ent; - VectorCopy(vec3_origin, pmove->velocity); - return; - } - - if (trace.fraction == 1) - { - PM_CheckWater(); - return; - } - - if (pmove->movetype == MOVETYPE_BOUNCE) - backoff = 2.0 - pmove->friction; - else if (pmove->movetype == MOVETYPE_BOUNCEMISSILE) - backoff = 2.0; - else - backoff = 1; - - PM_ClipVelocity(pmove->velocity, trace.plane.normal, pmove->velocity, backoff); - - if (trace.plane.normal[2] > 0.7) - { - float vel; - vec3_t base; - - VectorClear(base); - - if (pmove->velocity[2] < pmove->movevars->gravity * pmove->frametime) - { - pmove->onground = trace.ent; - pmove->velocity[2] = 0; - } - - vel = DotProduct(pmove->velocity, pmove->velocity); - - if (vel < (30 * 30) || (pmove->movetype != MOVETYPE_BOUNCE && pmove->movetype != MOVETYPE_BOUNCEMISSILE)) - { - pmove->onground = trace.ent; - VectorCopy(vec3_origin, pmove->velocity); - } - else - { - VectorScale(pmove->velocity, (1.0 - trace.fraction) * pmove->frametime * 0.9, move); - - trace = PM_PushEntity(move); - } - - VectorSubtract(pmove->velocity, base, pmove->velocity) - } - - PM_CheckWater(); -} - -void PM_NoClip(void) -{ - int i; - vec3_t wishvel; - float fmove, smove; - float currentspeed, addspeed, accelspeed; - - fmove = pmove->cmd.forwardmove; - smove = pmove->cmd.sidemove; - - VectorNormalize(pmove->forward); - VectorNormalize(pmove->right); - - for (i = 0; i < 3; i++) - { - wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; - } - - wishvel[2] += pmove->cmd.upmove; - - VectorMA(pmove->origin, pmove->frametime, wishvel, pmove->origin); - - VectorClear(pmove->velocity); -} - -#define BUNNYJUMP_MAX_SPEED_FACTOR 1.2f - -void PM_PreventMegaBunnyJumping(void) -{ - float spd; - float fraction; - float maxscaledspeed; - - maxscaledspeed = BUNNYJUMP_MAX_SPEED_FACTOR * pmove->maxspeed; - - if (maxscaledspeed <= 0.0f) - return; - - spd = Length(pmove->velocity); - - if (spd <= maxscaledspeed) - return; - - fraction = (maxscaledspeed / spd) * 0.8; - - VectorScale(pmove->velocity, fraction, pmove->velocity); -} - -void PM_Jump(void) -{ - int i; - qboolean tfc = false; - - qboolean cansuperjump = false; - - if (pmove->dead) - { - pmove->oldbuttons |= IN_JUMP; - return; - } - - if (pmove->waterjumptime) - { - pmove->waterjumptime -= pmove->cmd.msec; - - if (pmove->waterjumptime < 0) - { - pmove->waterjumptime = 0; - } - - return; - } - - if (pmove->waterlevel >= 2) - { - pmove->onground = -1; - - if (pmove->watertype == CONTENTS_WATER) - pmove->velocity[2] = 100; - else if (pmove->watertype == CONTENTS_SLIME) - pmove->velocity[2] = 80; - else - pmove->velocity[2] = 50; - - if (pmove->flSwimTime <= 0) - { - pmove->flSwimTime = 1000; - - switch (pmove->RandomLong(0, 3)) - { - case 0: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - - case 1: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade2.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - - case 2: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade3.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - - case 3: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade4.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - } - } - - return; - } - - if (pmove->onground == -1) - { - pmove->oldbuttons |= IN_JUMP; - return; - } - - if (~pmove->oldbuttons & IN_JUMP && (!pmove->bInDuck || ~pmove->flags & FL_DUCKING)) - { - pmove->onground = -1; - - PM_CatagorizeTextureType(); - PM_PreventMegaBunnyJumping(); - - if (Length(pmove->velocity) >= 150.0) - { - PM_PlayStepSound(PM_MapTextureTypeStepType(pmove->chtexturetype), 1.0); - } - - pmove->velocity[2] = sqrt(2 * 800 * 45.0); - - if (pmove->fuser2 > 0.0) - pmove->velocity[2] *= (100.0 - pmove->fuser2 * 0.001 * 19.0) * 0.01; - - pmove->fuser2 = 1315.7894; - - PM_FixupGravityVelocity(); - - pmove->oldbuttons |= IN_JUMP; - } -} - -#define WJ_HEIGHT 8 - -void PM_CheckWaterJump(void) -{ - vec3_t vecStart, vecEnd; - vec3_t flatforward; - vec3_t flatvelocity; - float curspeed; - pmtrace_t tr; - int savehull; - - if (pmove->waterjumptime) - return; - - if (pmove->velocity[2] < -180) - return; - - flatvelocity[0] = pmove->velocity[0]; - flatvelocity[1] = pmove->velocity[1]; - flatvelocity[2] = 0; - - curspeed = VectorNormalize(flatvelocity); - - flatforward[0] = pmove->forward[0]; - flatforward[1] = pmove->forward[1]; - flatforward[2] = 0; - VectorNormalize (flatforward); - - if (curspeed != 0.0 && (DotProduct(flatvelocity, flatforward) < 0.0)) - return; - - VectorCopy(pmove->origin, vecStart); - vecStart[2] += WJ_HEIGHT; - - VectorMA(vecStart, 24, flatforward, vecEnd); - - savehull = pmove->usehull; - pmove->usehull = 2; - tr = pmove->PM_PlayerTrace(vecStart, vecEnd, PM_NORMAL, -1); - - if (tr.fraction < 1.0 && fabs(tr.plane.normal[2]) < 0.1f) - { - vecStart[2] += pmove->player_maxs[savehull][2] - WJ_HEIGHT; - VectorMA(vecStart, 24, flatforward, vecEnd); - VectorMA(vec3_origin, -50, tr.plane.normal, pmove->movedir); - - tr = pmove->PM_PlayerTrace(vecStart, vecEnd, PM_NORMAL, -1); - - if (tr.fraction == 1.0) - { - pmove->waterjumptime = 2000; - pmove->velocity[2] = 225; - pmove->oldbuttons |= IN_JUMP; - pmove->flags |= FL_WATERJUMP; - } - } - - pmove->usehull = savehull; -} - -void PM_CheckFalling(void) -{ - if (pmove->onground != -1 && !pmove->dead && pmove->flFallVelocity >= PLAYER_FALL_PUNCH_THRESHHOLD) - { - float fvol = 0.5; - - if (pmove->waterlevel > 0) - { - } - else if (pmove->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED) - { - fvol = 1.0; - } - else if (pmove->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED / 2) - { - fvol = 0.85; - } - else if (pmove->flFallVelocity < PLAYER_MIN_BOUNCE_SPEED) - { - fvol = 0; - } - - if (fvol > 0.0) - { - PM_CatagorizeTextureType(); - PM_PlayStepSound(PM_MapTextureTypeStepType(pmove->chtexturetype), fvol); - - pmove->flTimeStepSound = 300; - - pmove->punchangle[2] = pmove->flFallVelocity * 0.013; - - if (pmove->punchangle[0] > 8) - pmove->punchangle[0] = 8; - } - } - - if (pmove->onground != -1) - { - pmove->flFallVelocity = 0; - } -} - -void PM_PlayWaterSounds(void) -{ - if ((pmove->oldwaterlevel == 0 && pmove->waterlevel != 0) || (pmove->oldwaterlevel != 0 && pmove->waterlevel == 0)) - { - switch (pmove->RandomLong(0, 3)) - { - case 0: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - - case 1: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade2.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - - case 2: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade3.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - - case 3: - { - pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade4.wav", 1, ATTN_NORM, 0, PITCH_NORM); - break; - } - } - } -} - -float PM_CalcRoll(vec3_t angles, vec3_t velocity, float rollangle, float rollspeed) -{ - float sign; - float side; - float value; - vec3_t forward, right, up; - - AngleVectors(angles, forward, right, up); - - side = DotProduct(velocity, right); - - sign = side < 0 ? -1 : 1; - - side = fabs(side); - - value = rollangle; - - if (side < rollspeed) - { - side = side * value / rollspeed; - } - else - { - side = value; - } - - return side * sign; -} - -void PM_DropPunchAngle(vec3_t punchangle) -{ - float len; - - len = VectorNormalize (punchangle); - len -= (10.0 + len * 0.5) * pmove->frametime; - len = max(len, 0.0); - VectorScale(punchangle, len, punchangle); -} - -void PM_CheckParamters(void) -{ - float spd; - float maxspeed; - vec3_t v_angle; - - spd = (pmove->cmd.forwardmove * pmove->cmd.forwardmove) + (pmove->cmd.sidemove * pmove->cmd.sidemove) + (pmove->cmd.upmove * pmove->cmd.upmove); - spd = sqrt(spd); - - maxspeed = pmove->clientmaxspeed; - - if (maxspeed != 0.0) - pmove->maxspeed = min(maxspeed, pmove->maxspeed); - - if ((spd != 0.0) && (spd > pmove->maxspeed)) - { - float fRatio = pmove->maxspeed / spd; - pmove->cmd.forwardmove *= fRatio; - pmove->cmd.sidemove *= fRatio; - pmove->cmd.upmove *= fRatio; - } - - if (pmove->flags & FL_FROZEN || pmove->flags & FL_ONTRAIN || pmove->dead) - { - pmove->cmd.forwardmove = 0; - pmove->cmd.sidemove = 0; - pmove->cmd.upmove = 0; - } - - PM_DropPunchAngle(pmove->punchangle); - - if (!pmove->dead) - { - VectorCopy(pmove->cmd.viewangles, v_angle); - VectorAdd(v_angle, pmove->punchangle, v_angle); - - pmove->angles[ROLL] = PM_CalcRoll(v_angle, pmove->velocity, pmove->movevars->rollangle, pmove->movevars->rollspeed) * 4; - pmove->angles[PITCH] = v_angle[PITCH]; - pmove->angles[YAW] = v_angle[YAW]; - } - else - { - VectorCopy(pmove->oldangles, pmove->angles); - } - - if (pmove->dead) - { - pmove->view_ofs[2] = PM_DEAD_VIEWHEIGHT; - } - - if (pmove->angles[YAW] > 180.0f) - { - pmove->angles[YAW] -= 360.0f; - } -} - -void PM_ReduceTimers(void) -{ - if (pmove->flTimeStepSound > 0) - { - pmove->flTimeStepSound -= pmove->cmd.msec; - - if (pmove->flTimeStepSound < 0) - { - pmove->flTimeStepSound = 0; - } - } - - if (pmove->flDuckTime > 0) - { - pmove->flDuckTime -= pmove->cmd.msec; - - if (pmove->flDuckTime < 0) - { - pmove->flDuckTime = 0; - } - } - - if (pmove->flSwimTime > 0) - { - pmove->flSwimTime -= pmove->cmd.msec; - - if (pmove->flSwimTime < 0) - { - pmove->flSwimTime = 0; - } - } - - if (pmove->fuser2 > 0.0) - { - pmove->fuser2 -= pmove->cmd.msec; - - if (pmove->fuser2 < 0) - pmove->fuser2 = 0; - } -} - -void PM_PlayerMove(qboolean server) -{ - physent_t *pLadder = NULL; - - pmove->server = server; - - PM_CheckParamters(); - - pmove->numtouch = 0; - pmove->frametime = pmove->cmd.msec * 0.001; - - PM_ReduceTimers(); - - AngleVectors(pmove->angles, pmove->forward, pmove->right, pmove->up); - - if ((pmove->spectator || pmove->iuser1 > 0) && (pmove->iuser3 <= 0 || pmove->deadflag == DEAD_DEAD)) - { - PM_SpectatorMove(); - PM_CatagorizePosition(); - return; - } - - if (pmove->movetype != MOVETYPE_NOCLIP && pmove->movetype != MOVETYPE_NONE) - { - if (PM_CheckStuck()) - { - return; - } - } - - PM_CatagorizePosition(); - - pmove->oldwaterlevel = pmove->waterlevel; - - if (pmove->onground == -1) - { - pmove->flFallVelocity = -pmove->velocity[2]; - } - - g_onladder = 0; - - if (!pmove->dead && !(pmove->flags & FL_ONTRAIN)) - { - pLadder = PM_Ladder(); - - if (pLadder) - { - g_onladder = 1; - } - } - - PM_Duck(); - PM_UpdateStepSound(); - - if (!pmove->dead && !(pmove->flags & FL_ONTRAIN)) - { - if (pLadder) - { - PM_LadderMove(pLadder); - } - else if (pmove->movetype != MOVETYPE_WALK && pmove->movetype != MOVETYPE_NOCLIP) - { - pmove->movetype = MOVETYPE_WALK; - } - } - - switch (pmove->movetype) - { - default: - { - pmove->Con_DPrintf("Bogus pmove player movetype %i on (%i) 0=cl 1=sv\n", pmove->movetype, pmove->server); - break; - } - - case MOVETYPE_NONE: - { - break; - } - - case MOVETYPE_NOCLIP: - { - PM_NoClip(); - break; - } - - case MOVETYPE_TOSS: - case MOVETYPE_BOUNCE: - { - PM_Physics_Toss(); - break; - } - - case MOVETYPE_FLY: - { - PM_CheckWater(); - - if (pmove->cmd.buttons & IN_JUMP) - { - if (!pLadder) - { - PM_Jump(); - } - } - else - { - pmove->oldbuttons &= ~IN_JUMP; - } - - VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); - PM_FlyMove(); - VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); - break; - } - - case MOVETYPE_WALK: - { - if (!PM_InWater()) - { - PM_AddCorrectGravity(); - } - - if (pmove->waterjumptime) - { - PM_WaterJump(); - PM_FlyMove(); - - PM_CheckWater(); - return; - } - - if (pmove->waterlevel >= 2) - { - if (pmove->waterlevel == 2) - { - PM_CheckWaterJump(); - } - - if (pmove->velocity[2] < 0 && pmove->waterjumptime) - { - pmove->waterjumptime = 0; - } - - if (pmove->cmd.buttons & IN_JUMP) - { - PM_Jump(); - } - else - { - pmove->oldbuttons &= ~IN_JUMP; - } - - PM_WaterMove(); - - VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); - - PM_CatagorizePosition(); - } - else - { - if (pmove->cmd.buttons & IN_JUMP) - { - if (!pLadder) - { - PM_Jump(); - } - } - else - { - pmove->oldbuttons &= ~IN_JUMP; - } - - if (pmove->onground != -1) - { - pmove->velocity[2] = 0.0; - PM_Friction(); - } - - PM_CheckVelocity(); - - if (pmove->onground != -1) - { - PM_WalkMove(); - } - else - { - PM_AirMove(); - } - - PM_CatagorizePosition(); - - VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); - - PM_CheckVelocity(); - - if (!PM_InWater()) - { - PM_FixupGravityVelocity(); - } - - if (pmove->onground != -1) - { - pmove->velocity[2] = 0; - } - - PM_CheckFalling(); - } - - PM_PlayWaterSounds(); - break; - } - } -} - -void PM_CreateStuckTable(void) -{ - float x, y, z; - int idx; - int i; - float zi[3]; - - memset(rgv3tStuckTable, 0, sizeof(rgv3tStuckTable)); - - idx = 0; - x = y = 0; - - for (z = -0.125; z <= 0.125; z += 0.125, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - - x = z = 0; - - for (y = -0.125; y <= 0.125; y += 0.125, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - - y = z = 0; - - for (x = -0.125; x <= 0.125; x += 0.125, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - - for (x = -0.125; x <= 0.125; x += 0.250) - { - for (y = -0.125; y <= 0.125; y += 0.250) - { - for (z = -0.125; z <= 0.125; z += 0.250, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - } - } - - x = y = 0; - zi[0] = 0; - zi[1] = 1; - zi[2] = 6; - - for (i = 0; i < 3; i++, idx++) - { - z = zi[i]; - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - - x = z = 0; - - for (y = -2; y <= 2; y += 2, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - - y = z = 0; - - for (x = -2; x <= 2; x += 2, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - - for (i = 0; i < 3; i++) - { - z = zi[i]; - - for (y = -2; y <= 2; y += 2) - { - for (z = -2; z <= 2; z += 2, idx++) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - } - } - } -} - -void PM_Move (struct playermove_s *ppmove, int server) -{ - assert(pm_shared_initialized); - - pmove = ppmove; - - PM_PlayerMove((server != 0) ? true : false); - - if (pmove->onground != -1) - { - pmove->flags |= FL_ONGROUND; - } - else - { - pmove->flags &= ~FL_ONGROUND; - } - - if (!pmove->multiplayer && (pmove->movetype == MOVETYPE_WALK)) - { - pmove->friction = 1.0f; - } -} - -int PM_GetVisEntInfo(int ent) -{ - if (ent >= 0 && ent <= pmove->numvisent) - { - return pmove->visents[ent].info; - } - - return -1; -} - -int PM_GetPhysEntInfo(int ent) -{ - if (ent >= 0 && ent <= pmove->numphysent) - return pmove->physents[ent].info; - - return -1; -} - -void PM_Init(struct playermove_s *ppmove) -{ - assert(!pm_shared_initialized); - - pmove = ppmove; - - PM_CreateStuckTable(); - PM_InitTextureTypes(); - - pm_shared_initialized = 1; -} +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +#include +#include "mathlib.h" +#include "const.h" +#include "usercmd.h" +#include "pm_defs.h" +#include "pm_shared.h" +#include "pm_movevars.h" +#include "pm_debug.h" +#include +#include +#include +#include +#include + +#ifdef CLIENT_DLL + int iJumpSpectator; + float vJumpOrigin[3]; + float vJumpAngles[3]; +#endif + +static int pm_shared_initialized = 0; + +#ifdef _MSC_VER +#pragma warning(disable:4101) +#pragma warning(disable:4305) +#endif + +typedef enum +{ + mod_brush, + mod_sprite, + mod_alias, + mod_studio +} +modtype_t; + +playermove_t *pmove = NULL; + +typedef struct +{ + int planenum; + short children[2]; +} +dclipnode_t; + +typedef struct mplane_s +{ + vec3_t normal; + float dist; + byte type; + byte signbits; + byte pad[2]; +} +mplane_t; + +typedef struct hull_s +{ + dclipnode_t *clipnodes; + mplane_t *planes; + int firstclipnode; + int lastclipnode; + vec3_t clip_mins; + vec3_t clip_maxs; +} +hull_t; + +#define TIME_TO_DUCK 0.4 +#define VEC_DUCK_HULL_MIN -18 +#define VEC_DUCK_HULL_MAX 32 +#define VEC_DUCK_VIEW 12 +#define PM_DEAD_VIEWHEIGHT -8 +#define MAX_CLIMB_SPEED 200 +#define STUCK_MOVEUP 1 +#define STUCK_MOVEDOWN -1 +#define VEC_HULL_MIN -36 +#define VEC_HULL_MAX 36 + +#define VEC_VIEW 17 +#define STOP_EPSILON 0.1 + +#define CTEXTURESMAX 1024 + +#define CBTEXTURENAMEMAX 17 + +#define CHAR_TEX_CONCRETE 'C' +#define CHAR_TEX_METAL 'M' +#define CHAR_TEX_DIRT 'D' +#define CHAR_TEX_VENT 'V' +#define CHAR_TEX_GRATE 'G' +#define CHAR_TEX_TILE 'T' +#define CHAR_TEX_SLOSH 'S' +#define CHAR_TEX_WOOD 'W' +#define CHAR_TEX_COMPUTER 'P' +#define CHAR_TEX_GLASS 'Y' +#define CHAR_TEX_FLESH 'F' +#define CHAR_TEX_SNOW 'N' + +#define STEP_CONCRETE 0 +#define STEP_METAL 1 +#define STEP_DIRT 2 +#define STEP_VENT 3 +#define STEP_GRATE 4 +#define STEP_TILE 5 +#define STEP_SLOSH 6 +#define STEP_WADE 7 +#define STEP_LADDER 8 +#define STEP_SNOW 9 + +#define PLAYER_FATAL_FALL_SPEED 1024 +#define PLAYER_MAX_SAFE_FALL_SPEED 580 +#define DAMAGE_FOR_FALL_SPEED (float)100 / (PLAYER_FATAL_FALL_SPEED - PLAYER_MAX_SAFE_FALL_SPEED) + +#define PLAYER_MIN_BOUNCE_SPEED 350 + +#define PLAYER_FALL_PUNCH_THRESHHOLD (float)250 + +#define PLAYER_LONGJUMP_SPEED 350 + +#pragma warning(disable : 4244) + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +#define PITCH 0 +#define YAW 1 +#define ROLL 2 + +#define MAX_CLIENTS 32 + +#define CONTENTS_CURRENT_0 -9 +#define CONTENTS_CURRENT_90 -10 +#define CONTENTS_CURRENT_180 -11 +#define CONTENTS_CURRENT_270 -12 +#define CONTENTS_CURRENT_UP -13 +#define CONTENTS_CURRENT_DOWN -14 + +#define CONTENTS_TRANSLUCENT -15 + +static vec3_t rgv3tStuckTable[54]; +static int rgStuckLast[MAX_CLIENTS][2]; + +static int gcTextures = 0; +static char grgszTextureName[CTEXTURESMAX][CBTEXTURENAMEMAX]; +static char grgchTextureType[CTEXTURESMAX]; + +int g_onladder = 0; + +void PM_SwapTextures(int i, int j) +{ + char chTemp; + char szTemp[CBTEXTURENAMEMAX]; + + strcpy(szTemp, grgszTextureName[i]); + chTemp = grgchTextureType[i]; + + strcpy(grgszTextureName[i], grgszTextureName[j]); + grgchTextureType[i] = grgchTextureType[j]; + + strcpy(grgszTextureName[j], szTemp); + grgchTextureType[j] = chTemp; +} + +void PM_SortTextures(void) +{ + int i, j; + + for (i = 0 ; i < gcTextures; i++) + { + for (j = i + 1; j < gcTextures; j++) + { + if (stricmp(grgszTextureName[i], grgszTextureName[j]) > 0) + PM_SwapTextures(i, j); + } + } +} + +void PM_InitTextureTypes(void) +{ + char buffer[512]; + int i, j; + byte *pMemFile; + int fileSize, filePos = 0; + static qboolean bTextureTypeInit = false; + + if (bTextureTypeInit) + return; + + memset(&(grgszTextureName[0][0]), 0, CTEXTURESMAX * CBTEXTURENAMEMAX); + memset(grgchTextureType, 0, CTEXTURESMAX); + + gcTextures = 0; + memset(buffer, 0, 512); + + fileSize = pmove->COM_FileSize("sound/materials.txt"); + pMemFile = pmove->COM_LoadFile("sound/materials.txt", 5, NULL); + + if (!pMemFile) + return; + + filePos = 0; + + while (pmove->memfgets(pMemFile, fileSize, &filePos, buffer, 511) != NULL && (gcTextures < CTEXTURESMAX)) + { + i = 0; + + while (buffer[i] && isspace(buffer[i])) + i++; + + if (!buffer[i]) + continue; + + if (buffer[i] == '/' || !isalpha(buffer[i])) + continue; + + grgchTextureType[gcTextures] = toupper(buffer[i++]); + + while (buffer[i] && isspace(buffer[i])) + i++; + + if (!buffer[i]) + continue; + + j = i; + + while (buffer[j] && !isspace(buffer[j])) + j++; + + if (!buffer[j]) + continue; + + j = min (j, CBTEXTURENAMEMAX - 1 + i); + buffer[j] = 0; + strcpy(&(grgszTextureName[gcTextures++][0]), &(buffer[i])); + } + + pmove->COM_FreeFile(pMemFile); + + PM_SortTextures(); + + bTextureTypeInit = true; +} + +char PM_FindTextureType(char *name) +{ + int left, right, pivot; + int val; + + assert(pm_shared_initialized); + + left = 0; + right = gcTextures - 1; + + while (left <= right) + { + pivot = (left + right) / 2; + + val = strnicmp(name, grgszTextureName[pivot], CBTEXTURENAMEMAX - 1); + + if (val == 0) + { + return grgchTextureType[pivot]; + } + else if (val > 0) + { + left = pivot + 1; + } + else if (val < 0) + { + right = pivot - 1; + } + } + + return CHAR_TEX_CONCRETE; +} + +void PM_PlayStepSound(int step, float fvol) +{ + static int iSkipStep = 0; + int irand; + + pmove->iStepLeft = !pmove->iStepLeft; + + if (!pmove->runfuncs) + return; + + irand = pmove->RandomLong(0, 1) + (pmove->iStepLeft * 2); + + if (pmove->multiplayer && !pmove->movevars->footsteps) + return; + + switch (step) + { + default: + case STEP_CONCRETE: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_step4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_METAL: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_metal4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_DIRT: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_dirt4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_VENT: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_duct4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_GRATE: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_grate4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_TILE: + { + if (!pmove->RandomLong(0, 4)) + irand = 4; + + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 4: pmove->PM_PlaySound(CHAN_BODY, "player/pl_tile5.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_SLOSH: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_slosh4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_WADE: + { + if (iSkipStep == 0) + { + iSkipStep++; + break; + } + + if (iSkipStep++ == 3) + iSkipStep = 0; + + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_LADDER: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_ladder4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + + case STEP_SNOW: + { + switch (irand) + { + case 0: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow1.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 1: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow3.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 2: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow2.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + case 3: pmove->PM_PlaySound(CHAN_BODY, "player/pl_snow4.wav", fvol, ATTN_NORM, 0, PITCH_NORM); break; + } + + break; + } + } +} + +int PM_MapTextureTypeStepType( char chTextureType) +{ + switch (chTextureType) + { + default: + case CHAR_TEX_CONCRETE: return STEP_CONCRETE; + case CHAR_TEX_METAL: return STEP_METAL; + case CHAR_TEX_DIRT: return STEP_DIRT; + case CHAR_TEX_VENT: return STEP_VENT; + case CHAR_TEX_GRATE: return STEP_GRATE; + case CHAR_TEX_TILE: return STEP_TILE; + case CHAR_TEX_SLOSH: return STEP_SLOSH; + case CHAR_TEX_SNOW: return STEP_SNOW; + } +} + +void PM_CatagorizeTextureType(void) +{ + vec3_t start, end; + const char *pTextureName; + + VectorCopy(pmove->origin, start); + VectorCopy(pmove->origin, end); + + end[2] -= 64; + + pmove->sztexturename[0] = '\0'; + pmove->chtexturetype = CHAR_TEX_CONCRETE; + + pTextureName = pmove->PM_TraceTexture(pmove->onground, start, end); + + if (!pTextureName) + return; + + if (*pTextureName == '-' || *pTextureName == '+') + pTextureName += 2; + + if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ') + pTextureName++; + + strcpy(pmove->sztexturename, pTextureName); + pmove->sztexturename[CBTEXTURENAMEMAX - 1] = 0; + + pmove->chtexturetype = PM_FindTextureType(pmove->sztexturename); +} + +void PM_UpdateStepSound(void) +{ + float fvol; + vec3_t knee; + vec3_t feet; + vec3_t center; + float height; + float speed; + int fLadder; + int step; + + if (pmove->flTimeStepSound > 0) + return; + + if (pmove->flags & FL_FROZEN) + return; + + speed = Length(pmove->velocity); + + if (speed < 150) + { + pmove->flTimeStepSound = 400; + return; + } + + fLadder = (pmove->movetype == MOVETYPE_FLY); + + if (fLadder || (pmove->onground != -1)) + { + PM_CatagorizeTextureType(); + + VectorCopy(pmove->origin, center); + VectorCopy(pmove->origin, knee); + VectorCopy(pmove->origin, feet); + + height = pmove->player_maxs[pmove->usehull][2] - pmove->player_mins[pmove->usehull][2]; + + knee[2] = pmove->origin[2] - 0.3 * height; + feet[2] = pmove->origin[2] - 0.5 * height; + + if (fLadder) + { + step = STEP_LADDER; + fvol = 0.35; + pmove->flTimeStepSound = 350; + } + else if (pmove->PM_PointContents(knee, NULL) == CONTENTS_WATER) + { + step = STEP_WADE; + fvol = 0.65; + pmove->flTimeStepSound = 600; + } + else if (pmove->PM_PointContents(feet, NULL) == CONTENTS_WATER) + { + step = STEP_SLOSH; + fvol = 0.5; + pmove->flTimeStepSound = 300; + } + else + { + step = PM_MapTextureTypeStepType(pmove->chtexturetype); + + switch (pmove->chtexturetype) + { + case CHAR_TEX_CONCRETE: + { + fvol = 0.5; + pmove->flTimeStepSound = 300; + break; + } + + case CHAR_TEX_METAL: + { + fvol = 0.5; + pmove->flTimeStepSound = 300; + break; + } + + case CHAR_TEX_DIRT: + { + fvol = 0.55; + pmove->flTimeStepSound = 300; + break; + } + + case CHAR_TEX_VENT: + { + fvol = 0.7; + pmove->flTimeStepSound = 300; + break; + } + + default: + { + fvol = 0.5; + break; + } + + case CHAR_TEX_GRATE: + { + fvol = 0.5; + pmove->flTimeStepSound = 300; + break; + } + + case CHAR_TEX_TILE: + { + fvol = 0.5; + pmove->flTimeStepSound = 300; + break; + } + + case CHAR_TEX_SLOSH: + { + fvol = 0.5; + pmove->flTimeStepSound = 300; + break; + } + + case CHAR_TEX_SNOW: + { + fvol = 0.5; + pmove->flTimeStepSound = 300; + break; + } + + pmove->flTimeStepSound = 300; + } + } + + if (pmove->flags & FL_DUCKING || fLadder) + { + pmove->flTimeStepSound += 100; + + if (pmove->flags & FL_DUCKING && pmove->flDuckTime < 950.0) + fvol *= 0.35; + } + + PM_PlayStepSound(step, fvol); + } +} + +qboolean PM_AddToTouched(pmtrace_t tr, vec3_t impactvelocity) +{ + int i; + + for (i = 0; i < pmove->numtouch; i++) + { + if (pmove->touchindex[i].ent == tr.ent) + break; + } + + if (i != pmove->numtouch) + return false; + + VectorCopy(impactvelocity, tr.deltavelocity); + + if (pmove->numtouch >= MAX_PHYSENTS) + pmove->Con_DPrintf("Too many entities were touched!\n"); + + pmove->touchindex[pmove->numtouch++] = tr; + return true; +} + +void PM_CheckVelocity(void) +{ + int i; + + for (i = 0; i < 3; i++) + { + if (IS_NAN(pmove->velocity[i])) + { + pmove->Con_Printf("PM Got a NaN velocity %i\n", i); + pmove->velocity[i] = 0; + } + if (IS_NAN(pmove->origin[i])) + { + pmove->Con_Printf("PM Got a NaN origin on %i\n", i); + pmove->origin[i] = 0; + } + + if (pmove->velocity[i] > pmove->movevars->maxvelocity) + { + pmove->Con_DPrintf("PM Got a velocity too high on %i\n", i); + pmove->velocity[i] = pmove->movevars->maxvelocity; + } + else if (pmove->velocity[i] < -pmove->movevars->maxvelocity) + { + pmove->Con_DPrintf("PM Got a velocity too low on %i\n", i); + pmove->velocity[i] = -pmove->movevars->maxvelocity; + } + } +} + +int PM_ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce) +{ + float backoff; + float change; + float angle; + int i, blocked; + + angle = normal[2]; + + blocked = 0x00; + + if (angle > 0) + blocked |= 0x01; + + if (!angle) + blocked |= 0x02; + + backoff = DotProduct(in, normal) * overbounce; + + for (i = 0; i < 3; i++) + { + change = normal[i] * backoff; + out[i] = in[i] - change; + + if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) + out[i] = 0; + } + + return blocked; +} + +void PM_AddCorrectGravity(void) +{ + float ent_gravity; + + if (pmove->waterjumptime) + return; + + if (pmove->gravity) + ent_gravity = pmove->gravity; + else + ent_gravity = 1.0; + + pmove->velocity[2] -= (ent_gravity * pmove->movevars->gravity * 0.5 * pmove->frametime); + pmove->velocity[2] += pmove->basevelocity[2] * pmove->frametime; + pmove->basevelocity[2] = 0; + + PM_CheckVelocity(); +} + +void PM_FixupGravityVelocity(void) +{ + float ent_gravity; + + if (pmove->waterjumptime) + return; + + if (pmove->gravity) + ent_gravity = pmove->gravity; + else + ent_gravity = 1.0; + + pmove->velocity[2] -= (ent_gravity * pmove->movevars->gravity * pmove->frametime * 0.5); + + PM_CheckVelocity(); +} + +int PM_FlyMove(void) +{ + int bumpcount, numbumps; + vec3_t dir; + float d; + int numplanes; + vec3_t planes[MAX_CLIP_PLANES]; + vec3_t primal_velocity, original_velocity; + vec3_t new_velocity; + int i, j; + pmtrace_t trace; + vec3_t end; + float time_left, allFraction; + int blocked; + + numbumps = 4; + + blocked = 0; + numplanes = 0; + + VectorCopy(pmove->velocity, original_velocity); + VectorCopy(pmove->velocity, primal_velocity); + + allFraction = 0; + time_left = pmove->frametime; + + for (bumpcount = 0; bumpcount < numbumps; bumpcount++) + { + if (!pmove->velocity[0] && !pmove->velocity[1] && !pmove->velocity[2]) + break; + + for (i = 0; i < 3; i++) + end[i] = pmove->origin[i] + time_left * pmove->velocity[i]; + + trace = pmove->PM_PlayerTrace(pmove->origin, end, PM_NORMAL, -1); + + allFraction += trace.fraction; + + if (trace.allsolid) + { + VectorCopy(vec3_origin, pmove->velocity); + return 4; + } + + if (trace.fraction > 0) + { + VectorCopy(trace.endpos, pmove->origin); + VectorCopy(pmove->velocity, original_velocity); + numplanes = 0; + } + + if (trace.fraction == 1) + break; + + PM_AddToTouched(trace, pmove->velocity); + + if (trace.plane.normal[2] > 0.7) + blocked |= 1; + + if (!trace.plane.normal[2]) + blocked |= 2; + + time_left -= time_left * trace.fraction; + + if (numplanes >= MAX_CLIP_PLANES) + { + VectorCopy(vec3_origin, pmove->velocity); + break; + } + + VectorCopy(trace.plane.normal, planes[numplanes]); + numplanes++; + + if (pmove->movetype == MOVETYPE_WALK && ((pmove->onground == -1) || (pmove->friction != 1))) + { + for (i = 0; i < numplanes; i++) + { + if (planes[i][2] > 0.7) + { + PM_ClipVelocity(original_velocity, planes[i], new_velocity, 1); + VectorCopy(new_velocity, original_velocity); + } + else + PM_ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + pmove->movevars->bounce * (1 - pmove->friction)); + } + + VectorCopy(new_velocity, pmove->velocity); + VectorCopy(new_velocity, original_velocity); + } + else + { + for (i = 0; i < numplanes; i++) + { + PM_ClipVelocity(original_velocity, planes[i], pmove->velocity, 1); + + for (j = 0; j velocity, planes[j]) < 0) + break; + } + } + + if (j == numplanes) + break; + } + + if (i != numplanes) + { + } + else + { + if (numplanes != 2) + { + VectorCopy(vec3_origin, pmove->velocity); + break; + } + + CrossProduct(planes[0], planes[1], dir); + d = DotProduct(dir, pmove->velocity); + VectorScale(dir, d, pmove->velocity); + } + + if (DotProduct(pmove->velocity, primal_velocity) <= 0) + { + VectorCopy(vec3_origin, pmove->velocity); + break; + } + } + } + + if (allFraction == 0) + VectorCopy(vec3_origin, pmove->velocity); + + return blocked; +} + +void PM_Accelerate(vec3_t wishdir, float wishspeed, float accel) +{ + int i; + float addspeed, accelspeed, currentspeed; + + if (pmove->dead) + return; + + if (pmove->waterjumptime) + return; + + currentspeed = DotProduct(pmove->velocity, wishdir); + + addspeed = wishspeed - currentspeed; + + if (addspeed <= 0) + return; + + accelspeed = accel * pmove->frametime * wishspeed * pmove->friction; + + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i = 0; i < 3; i++) + pmove->velocity[i] += accelspeed * wishdir[i]; +} + +void PM_WalkMove(void) +{ + int clip; + int oldonground; + int i; + + vec3_t wishvel; + float spd; + float fmove, smove; + vec3_t wishdir; + float wishspeed; + + vec3_t dest, start; + vec3_t original, originalvel; + vec3_t down, downvel; + float downdist, updist; + + pmtrace_t trace; + + if (pmove->fuser2 > 0.0) + { + float factor; + factor = (100.0 - pmove->fuser2 * 0.001 * 19.0) * 0.01; + pmove->velocity[0] *= factor; + pmove->velocity[1] *= factor; + } + + fmove = pmove->cmd.forwardmove; + smove = pmove->cmd.sidemove; + + pmove->forward[2] = 0; + pmove->right[2] = 0; + + VectorNormalize(pmove->forward); + VectorNormalize(pmove->right); + + for (i = 0; i < 2; i++) + wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; + + wishvel[2] = 0; + + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + + if (wishspeed > pmove->maxspeed) + { + VectorScale(wishvel, pmove->maxspeed/wishspeed, wishvel); + wishspeed = pmove->maxspeed; + } + + pmove->velocity[2] = 0; + + PM_Accelerate(wishdir, wishspeed, pmove->movevars->accelerate); + pmove->velocity[2] = 0; + + VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); + + spd = Length(pmove->velocity); + + if (spd < 1.0f) + { + VectorClear(pmove->velocity); + return; + } + + oldonground = pmove->onground; + + dest[0] = pmove->origin[0] + pmove->velocity[0]*pmove->frametime; + dest[1] = pmove->origin[1] + pmove->velocity[1]*pmove->frametime; + dest[2] = pmove->origin[2]; + + VectorCopy(dest, start); + trace = pmove->PM_PlayerTrace(pmove->origin, dest, PM_NORMAL, -1); + + if (trace.fraction == 1) + { + VectorCopy(trace.endpos, pmove->origin); + return; + } + + if (oldonground == -1 && pmove->waterlevel == 0) + return; + + if (pmove->waterjumptime) + return; + + VectorCopy(pmove->origin, original); + VectorCopy(pmove->velocity, originalvel); + + clip = PM_FlyMove(); + + VectorCopy(pmove->origin, down); + VectorCopy(pmove->velocity, downvel); + + VectorCopy(original, pmove->origin); + VectorCopy(originalvel, pmove->velocity); + + VectorCopy(pmove->origin, dest); + dest[2] += pmove->movevars->stepsize; + + trace = pmove->PM_PlayerTrace(pmove->origin, dest, PM_NORMAL, -1); + + if (!trace.startsolid && !trace.allsolid) + VectorCopy(trace.endpos, pmove->origin); + + clip = PM_FlyMove(); + + VectorCopy(pmove->origin, dest); + dest[2] -= pmove->movevars->stepsize; + + trace = pmove->PM_PlayerTrace(pmove->origin, dest, PM_NORMAL, -1); + + if (trace.plane.normal[2] < 0.7) + goto usedown; + + if (!trace.startsolid && !trace.allsolid) + VectorCopy(trace.endpos, pmove->origin); + + VectorCopy(pmove->origin, pmove->up); + + downdist = (down[0] - original[0])*(down[0] - original[0]) + (down[1] - original[1])*(down[1] - original[1]); + updist = (pmove->up[0] - original[0])*(pmove->up[0] - original[0]) + (pmove->up[1] - original[1])*(pmove->up[1] - original[1]); + + if (downdist > updist) + { +usedown: + VectorCopy(down, pmove->origin); + VectorCopy(downvel, pmove->velocity); + } + else + pmove->velocity[2] = downvel[2]; +} + +void PM_Friction(void) +{ + float *vel; + float speed, newspeed, control; + float friction; + float drop; + vec3_t newvel; + + if (pmove->waterjumptime) + return; + + vel = pmove->velocity; + + speed = sqrt(vel[0] * vel[0] +vel[1] * vel[1] + vel[2] * vel[2]); + + if (speed < 0.1f) + return; + + drop = 0; + + if (pmove->onground != -1) + { + vec3_t start, stop; + pmtrace_t trace; + + start[0] = stop[0] = pmove->origin[0] + vel[0] / speed * 16; + start[1] = stop[1] = pmove->origin[1] + vel[1] / speed * 16; + start[2] = pmove->origin[2] + pmove->player_mins[pmove->usehull][2]; + stop[2] = start[2] - 34; + + trace = pmove->PM_PlayerTrace(start, stop, PM_NORMAL, -1); + + if (trace.fraction == 1.0) + friction = pmove->movevars->friction * pmove->movevars->edgefriction; + else + friction = pmove->movevars->friction; + + friction *= pmove->friction; + + control = (speed < pmove->movevars->stopspeed) ? pmove->movevars->stopspeed : speed; + drop += control*friction*pmove->frametime; + } + + newspeed = speed - drop; + + if (newspeed < 0) + newspeed = 0; + + newspeed /= speed; + + newvel[0] = vel[0] * newspeed; + newvel[1] = vel[1] * newspeed; + newvel[2] = vel[2] * newspeed; + + VectorCopy(newvel, pmove->velocity); +} + +void PM_AirAccelerate(vec3_t wishdir, float wishspeed, float accel) +{ + int i; + float addspeed, accelspeed, currentspeed, wishspd = wishspeed; + + if (pmove->dead) + return; + + if (pmove->waterjumptime) + return; + + if (wishspd > 30) + wishspd = 30; + + currentspeed = DotProduct(pmove->velocity, wishdir); + addspeed = wishspd - currentspeed; + + if (addspeed <= 0) + return; + + accelspeed = accel * wishspeed * pmove->frametime * pmove->friction; + + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i = 0; i < 3; i++) + pmove->velocity[i] += accelspeed * wishdir[i]; +} + +void PM_WaterMove(void) +{ + int i; + vec3_t wishvel; + float wishspeed; + vec3_t wishdir; + vec3_t start, dest; + vec3_t temp; + pmtrace_t trace; + + float speed, newspeed, addspeed, accelspeed; + + for (i = 0; i < 3; i++) + wishvel[i] = pmove->forward[i] * pmove->cmd.forwardmove + pmove->right[i] * pmove->cmd.sidemove; + + if (!pmove->cmd.forwardmove && !pmove->cmd.sidemove && !pmove->cmd.upmove) + wishvel[2] -= 60; + else + wishvel[2] += pmove->cmd.upmove; + + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + + if (wishspeed > pmove->maxspeed) + { + VectorScale(wishvel, pmove->maxspeed / wishspeed, wishvel); + wishspeed = pmove->maxspeed; + } + + wishspeed *= 0.8; + + VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); + VectorCopy(pmove->velocity, temp); + speed = VectorNormalize(temp); + + if (speed) + { + newspeed = speed - pmove->frametime * speed * pmove->movevars->friction * pmove->friction; + + if (newspeed < 0) + newspeed = 0; + + VectorScale(pmove->velocity, newspeed / speed, pmove->velocity); + } + else + newspeed = 0; + + if (wishspeed < 0.1f) + return; + + addspeed = wishspeed - newspeed; + + if (addspeed > 0) + { + VectorNormalize(wishvel); + accelspeed = pmove->movevars->accelerate * wishspeed * pmove->frametime * pmove->friction; + + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i = 0; i < 3; i++) + pmove->velocity[i] += accelspeed * wishvel[i]; + } + + VectorMA(pmove->origin, pmove->frametime, pmove->velocity, dest); + VectorCopy(dest, start); + start[2] += pmove->movevars->stepsize + 1; + trace = pmove->PM_PlayerTrace(start, dest, PM_NORMAL, -1); + + if (!trace.startsolid && !trace.allsolid) + { + VectorCopy(trace.endpos, pmove->origin); + return; + } + + PM_FlyMove(); +} + +void PM_AirMove(void) +{ + int i; + vec3_t wishvel; + float fmove, smove; + vec3_t wishdir; + float wishspeed; + + fmove = pmove->cmd.forwardmove; + smove = pmove->cmd.sidemove; + + pmove->forward[2] = 0; + pmove->right[2] = 0; + + VectorNormalize(pmove->forward); + VectorNormalize(pmove->right); + + for (i = 0; i < 2; i++) + { + wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; + } + + wishvel[2] = 0; + + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + + if (wishspeed > pmove->maxspeed) + { + VectorScale(wishvel, pmove->maxspeed / wishspeed, wishvel); + wishspeed = pmove->maxspeed; + } + + PM_AirAccelerate(wishdir, wishspeed, pmove->movevars->airaccelerate); + + VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); + + PM_FlyMove(); +} + +qboolean PM_InWater(void) +{ + return (pmove->waterlevel > 1); +} + +qboolean PM_CheckWater(void) +{ + vec3_t point; + int cont; + int truecont; + float height; + float heightover2; + + point[0] = pmove->origin[0] + (pmove->player_mins[pmove->usehull][0] + pmove->player_maxs[pmove->usehull][0]) * 0.5; + point[1] = pmove->origin[1] + (pmove->player_mins[pmove->usehull][1] + pmove->player_maxs[pmove->usehull][1]) * 0.5; + point[2] = pmove->origin[2] + pmove->player_mins[pmove->usehull][2] + 1; + + pmove->waterlevel = 0; + pmove->watertype = CONTENTS_EMPTY; + + cont = pmove->PM_PointContents(point, &truecont); + + if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT) + { + pmove->watertype = cont; + pmove->waterlevel = 1; + + height = (pmove->player_mins[pmove->usehull][2] + pmove->player_maxs[pmove->usehull][2]); + heightover2 = height * 0.5; + + point[2] = pmove->origin[2] + heightover2; + cont = pmove->PM_PointContents(point, NULL); + + if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT) + { + pmove->waterlevel = 2; + + point[2] = pmove->origin[2] + pmove->view_ofs[2]; + + cont = pmove->PM_PointContents(point, NULL); + + if (cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT) + pmove->waterlevel = 3; + } + + if ((truecont <= CONTENTS_CURRENT_0) && (truecont >= CONTENTS_CURRENT_DOWN)) + { + static vec3_t current_table[] = + { + { 1, 0, 0 }, { 0, 1, 0 }, { -1, 0, 0 }, + { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 } + }; + + VectorMA(pmove->basevelocity, 50.0 * pmove->waterlevel, current_table[CONTENTS_CURRENT_0 - truecont], pmove->basevelocity); + } + } + + return pmove->waterlevel > 1; +} + +void PM_CatagorizePosition(void) +{ + vec3_t point; + pmtrace_t tr; + + PM_CheckWater(); + + point[0] = pmove->origin[0]; + point[1] = pmove->origin[1]; + point[2] = pmove->origin[2] - 2; + + if (pmove->velocity[2] > 180) + { + pmove->onground = -1; + } + else + { + tr = pmove->PM_PlayerTrace(pmove->origin, point, PM_NORMAL, -1); + + if (tr.plane.normal[2] < 0.7) + pmove->onground = -1; + else + pmove->onground = tr.ent; + + if (pmove->onground != -1) + { + pmove->waterjumptime = 0; + + if (pmove->waterlevel < 2 && !tr.startsolid && !tr.allsolid) + VectorCopy(tr.endpos, pmove->origin); + } + + if (tr.ent > 0) + { + PM_AddToTouched(tr, pmove->velocity); + } + } +} + +int PM_GetRandomStuckOffsets(int nIndex, int server, vec3_t offset) +{ + int idx; + idx = rgStuckLast[nIndex][server]++; + + VectorCopy(rgv3tStuckTable[idx % 54], offset); + + return (idx % 54); +} + +void PM_ResetStuckOffsets(int nIndex, int server) +{ + rgStuckLast[nIndex][server] = 0; +} + +#define PM_CHECKSTUCK_MINTIME 0.05 + +int PM_CheckStuck(void) +{ + vec3_t base; + vec3_t offset; + vec3_t test; + int hitent; + int idx; + float fTime; + int i; + pmtrace_t traceresult; + + static float rgStuckCheckTime[MAX_CLIENTS][2]; + + hitent = pmove->PM_TestPlayerPosition(pmove->origin, &traceresult); + + if (hitent == -1) + { + PM_ResetStuckOffsets(pmove->player_index, pmove->server); + return 0; + } + + VectorCopy(pmove->origin, base); + + if (!pmove->server) + { + if ((hitent == 0) || (pmove->physents[hitent].model != NULL)) + { + int nReps = 0; + + PM_ResetStuckOffsets(pmove->player_index, pmove->server); + + do + { + i = PM_GetRandomStuckOffsets(pmove->player_index, pmove->server, offset); + + VectorAdd(base, offset, test); + + if (pmove->PM_TestPlayerPosition(test, &traceresult) == -1) + { + PM_ResetStuckOffsets(pmove->player_index, pmove->server); + + VectorCopy(test, pmove->origin); + return 0; + } + + nReps++; + } + while (nReps < 54); + } + } + + if (pmove->server) + idx = 0; + else + idx = 1; + + fTime = pmove->Sys_FloatTime(); + + if (rgStuckCheckTime[pmove->player_index][idx] >= (fTime - PM_CHECKSTUCK_MINTIME)) + return 1; + + rgStuckCheckTime[pmove->player_index][idx] = fTime; + + pmove->PM_StuckTouch(hitent, &traceresult); + + i = PM_GetRandomStuckOffsets(pmove->player_index, pmove->server, offset); + + VectorAdd(base, offset, test); + + if ((hitent = pmove->PM_TestPlayerPosition(test, NULL)) == -1) + { + PM_ResetStuckOffsets(pmove->player_index, pmove->server); + + if (i >= 27) + VectorCopy(test, pmove->origin); + + return 0; + } + + if (pmove->cmd.buttons & (IN_JUMP | IN_DUCK | IN_ATTACK) && ( pmove->physents[hitent].player != 0)) + { + float x, y, z; + float xystep = 8.0; + float zstep = 18.0; + float xyminmax = xystep; + float zminmax = 4 * zstep; + + for (z = 0; z <= zminmax; z += zstep) + { + for (x = -xyminmax; x <= xyminmax; x += xystep) + { + for (y = -xyminmax; y <= xyminmax; y += xystep) + { + VectorCopy(base, test); + test[0] += x; + test[1] += y; + test[2] += z; + + if (pmove->PM_TestPlayerPosition(test, NULL) == -1) + { + VectorCopy(test, pmove->origin); + return 0; + } + } + } + } + } + + return 1; +} + +void PM_SpectatorMove(void) +{ + float speed, drop, friction, control, newspeed; + float accel; + float currentspeed, addspeed, accelspeed; + int i; + vec3_t wishvel; + float fmove, smove; + vec3_t wishdir; + float wishspeed; + + if (pmove->iuser1 == OBS_ROAMING) + { +#ifdef CLIENT_DLL + if (iJumpSpectator) + { + VectorCopy(vJumpOrigin, pmove->origin); + VectorCopy(vJumpAngles, pmove->angles); + VectorCopy(vec3_origin, pmove->velocity); + iJumpSpectator = 0; + return; + } +#endif + speed = Length(pmove->velocity); + + if (speed < 1) + { + VectorCopy(vec3_origin, pmove->velocity) + } + else + { + drop = 0; + + friction = pmove->movevars->friction * 1.5; + control = speed < pmove->movevars->stopspeed ? pmove->movevars->stopspeed : speed; + drop += control*friction*pmove->frametime; + + newspeed = speed - drop; + + if (newspeed < 0) + newspeed = 0; + + newspeed /= speed; + + VectorScale(pmove->velocity, newspeed, pmove->velocity); + } + + fmove = pmove->cmd.forwardmove; + smove = pmove->cmd.sidemove; + + VectorNormalize(pmove->forward); + VectorNormalize(pmove->right); + + for (i = 0; i < 3; i++) + wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; + + wishvel[2] += pmove->cmd.upmove; + + VectorCopy(wishvel, wishdir); + wishspeed = VectorNormalize(wishdir); + + if (wishspeed > pmove->movevars->spectatormaxspeed) + { + VectorScale(wishvel, pmove->movevars->spectatormaxspeed / wishspeed, wishvel); + wishspeed = pmove->movevars->spectatormaxspeed; + } + + currentspeed = DotProduct(pmove->velocity, wishdir); + addspeed = wishspeed - currentspeed; + + if (addspeed <= 0) + return; + + accelspeed = pmove->movevars->accelerate * pmove->frametime * wishspeed; + + if (accelspeed > addspeed) + accelspeed = addspeed; + + for (i = 0; i < 3; i++) + pmove->velocity[i] += accelspeed * wishdir[i]; + + VectorMA(pmove->origin, pmove->frametime, pmove->velocity, pmove->origin); + } + else + { + int target; + + if (pmove->iuser2 <= 0) + return; + + for (target = 0; target < pmove->numphysent; target++) + { + if (pmove->physents[target].info == pmove->iuser2) + break; + } + + if (target == pmove->numphysent) + return; + + VectorCopy(pmove->physents[target].angles, pmove->angles); + VectorCopy(pmove->physents[target].origin, pmove->origin); + + VectorCopy(vec3_origin, pmove->velocity); + } +} + +float PM_SplineFraction(float value, float scale) +{ + float valueSquared; + + value = scale * value; + valueSquared = value * value; + + return 3 * valueSquared - 2 * valueSquared * value; +} + +void PM_FixPlayerCrouchStuck(int direction) +{ + int hitent; + int i; + vec3_t test; + + hitent = pmove->PM_TestPlayerPosition(pmove->origin, NULL); + + if (hitent == -1) + return; + + VectorCopy(pmove->origin, test); + + for (i = 0; i < 36; i++) + { + pmove->origin[2] += direction; + hitent = pmove->PM_TestPlayerPosition(pmove->origin, NULL); + + if (hitent == -1) + return; + } + + VectorCopy(test, pmove->origin); +} + +void PM_UnDuck(void) +{ + int i; + pmtrace_t trace; + vec3_t newOrigin; + + VectorCopy(pmove->origin, newOrigin); + + if (pmove->onground != -1) + { + newOrigin[2] += 18.0; + } + + trace = pmove->PM_PlayerTrace(newOrigin, newOrigin, PM_NORMAL, -1); + + if (!trace.startsolid) + { + pmove->usehull = 0; + + trace = pmove->PM_PlayerTrace(newOrigin, newOrigin, PM_NORMAL, -1); + + if (trace.startsolid) + { + pmove->usehull = 1; + return; + } + + pmove->flags &= ~FL_DUCKING; + pmove->bInDuck = false; + pmove->view_ofs[2] = VEC_VIEW; + pmove->flDuckTime = 0; + + pmove->flTimeStepSound -= 100; + + if (pmove->flTimeStepSound < 0) + { + pmove->flTimeStepSound = 0; + } + + VectorCopy(newOrigin, pmove->origin); + + PM_CatagorizePosition(); + } +} + +void PM_Duck(void) +{ + int i; + float time; + float duckFraction; + + int buttonsChanged = (pmove->oldbuttons ^ pmove->cmd.buttons); + int nButtonPressed = buttonsChanged & pmove->cmd.buttons; + + int duckchange = buttonsChanged & IN_DUCK ? 1 : 0; + int duckpressed = nButtonPressed & IN_DUCK ? 1 : 0; + + if (pmove->cmd.buttons & IN_DUCK) + { + pmove->oldbuttons |= IN_DUCK; + } + else + { + pmove->oldbuttons &= ~IN_DUCK; + } + + if (pmove->dead) + return; + + if ((pmove->cmd.buttons & IN_DUCK) || (pmove->bInDuck) || (pmove->flags & FL_DUCKING)) + { + pmove->cmd.forwardmove *= 0.333; + pmove->cmd.sidemove *= 0.333; + pmove->cmd.upmove *= 0.333; + + if (pmove->cmd.buttons & IN_DUCK) + { + if ((nButtonPressed & IN_DUCK) && !(pmove->flags & FL_DUCKING)) + { + pmove->flDuckTime = 1000; + pmove->bInDuck = true; + } + + time = max(0.0, ( 1.0 - (float)pmove->flDuckTime / 1000.0)); + + if (pmove->bInDuck) + { + if (((float)pmove->flDuckTime / 1000.0 <= (1.0 - TIME_TO_DUCK)) || (pmove->onground == -1)) + { + pmove->usehull = 1; + pmove->view_ofs[2] = VEC_DUCK_VIEW; + + pmove->flags |= FL_DUCKING; + pmove->bInDuck = false; + + if (pmove->onground != -1) + { + pmove->origin[2] = pmove->origin[2] - 18.0; + + PM_FixPlayerCrouchStuck(STUCK_MOVEUP); + + PM_CatagorizePosition(); + } + } + else + { + float fMore = (VEC_DUCK_HULL_MIN - VEC_HULL_MIN); + + duckFraction = PM_SplineFraction(time, (1.0 / TIME_TO_DUCK)); + pmove->view_ofs[2] = ((VEC_DUCK_VIEW - fMore) * duckFraction) + (VEC_VIEW * (1 - duckFraction)); + } + } + } + else + { + PM_UnDuck(); + } + } +} + +void PM_LadderMove(physent_t *pLadder) +{ + vec3_t ladderCenter; + trace_t trace; + qboolean onFloor; + vec3_t floor; + vec3_t modelmins, modelmaxs; + + if (pmove->movetype == MOVETYPE_NOCLIP) + return; + + pmove->PM_GetModelBounds(pLadder->model, modelmins, modelmaxs); + + VectorAdd(modelmins, modelmaxs, ladderCenter); + VectorScale(ladderCenter, 0.5, ladderCenter); + + pmove->movetype = MOVETYPE_FLY; + + VectorCopy(pmove->origin, floor); + floor[2] += pmove->player_mins[pmove->usehull][2] - 1; + + if (pmove->PM_PointContents(floor, NULL) == CONTENTS_SOLID) + onFloor = true; + else + onFloor = false; + + pmove->gravity = 0; + pmove->PM_TraceModel(pLadder, pmove->origin, ladderCenter, &trace); + + if (trace.fraction != 1.0) + { + float forward = 0, right = 0; + vec3_t vpn, v_right; + + float flSpeed = MAX_CLIMB_SPEED; + + if (pmove->maxspeed < MAX_CLIMB_SPEED) + flSpeed = pmove->maxspeed; + + AngleVectors(pmove->angles, vpn, v_right, NULL); + + if (pmove->flags & FL_DUCKING) + { + flSpeed *= 0.333; + } + + if (pmove->cmd.buttons & IN_BACK) + forward -= flSpeed; + + if (pmove->cmd.buttons & IN_FORWARD) + forward += flSpeed; + + if (pmove->cmd.buttons & IN_MOVELEFT) + right -= flSpeed; + + if (pmove->cmd.buttons & IN_MOVERIGHT) + right += flSpeed; + + if (pmove->cmd.buttons & IN_JUMP) + { + pmove->movetype = MOVETYPE_WALK; + VectorScale(trace.plane.normal, 270, pmove->velocity); + } + else + { + if (forward != 0 || right != 0) + { + vec3_t velocity, perp, cross, lateral, tmp; + float normal; + + VectorScale(vpn, forward, velocity); + VectorMA(velocity, right, v_right, velocity); + + VectorClear(tmp); + tmp[2] = 1; + CrossProduct(tmp, trace.plane.normal, perp); + VectorNormalize(perp); + + normal = DotProduct(velocity, trace.plane.normal); + VectorScale(trace.plane.normal, normal, cross); + + VectorSubtract(velocity, cross, lateral); + + CrossProduct(trace.plane.normal, perp, tmp); + VectorMA(lateral, -normal, tmp, pmove->velocity); + + if (onFloor && normal > 0) + { + VectorMA(pmove->velocity, MAX_CLIMB_SPEED, trace.plane.normal, pmove->velocity); + } + } + else + { + VectorClear(pmove->velocity); + } + } + } +} + +physent_t *PM_Ladder(void) +{ + int i; + physent_t *pe; + hull_t *hull; + int num; + vec3_t test; + + for (i = 0; i < pmove->nummoveent; i++) + { + pe = &pmove->moveents[i]; + + if (pe->model && (modtype_t)pmove->PM_GetModelType(pe->model) == mod_brush && pe->skin == CONTENTS_LADDER) + { + hull = (hull_t *)pmove->PM_HullForBsp(pe, test); + num = hull->firstclipnode; + + VectorSubtract(pmove->origin, test, test); + + if (pmove->PM_HullPointContents (hull, num, test) == CONTENTS_EMPTY) + continue; + + return pe; + } + } + + return NULL; +} + +void PM_WaterJump(void) +{ + if (pmove->waterjumptime > 10000) + pmove->waterjumptime = 10000; + + if (!pmove->waterjumptime) + return; + + pmove->waterjumptime -= pmove->cmd.msec; + + if (pmove->waterjumptime < 0 || !pmove->waterlevel) + { + pmove->waterjumptime = 0; + pmove->flags &= ~FL_WATERJUMP; + } + + pmove->velocity[0] = pmove->movedir[0]; + pmove->velocity[1] = pmove->movedir[1]; +} + +void PM_AddGravity(void) +{ + float ent_gravity; + + if (pmove->gravity) + ent_gravity = pmove->gravity; + else + ent_gravity = 1.0; + + pmove->velocity[2] -= (ent_gravity * pmove->movevars->gravity * pmove->frametime); + pmove->velocity[2] += pmove->basevelocity[2] * pmove->frametime; + pmove->basevelocity[2] = 0; + PM_CheckVelocity(); +} + +pmtrace_t PM_PushEntity(vec3_t push) +{ + pmtrace_t trace; + vec3_t end; + + VectorAdd(pmove->origin, push, end); + + trace = pmove->PM_PlayerTrace(pmove->origin, end, PM_NORMAL, -1); + + VectorCopy(trace.endpos, pmove->origin); + + if (trace.fraction < 1.0 && !trace.allsolid) + { + PM_AddToTouched(trace, pmove->velocity); + } + + return trace; +} + +void PM_Physics_Toss(void) +{ + pmtrace_t trace; + vec3_t move; + float backoff; + + PM_CheckWater(); + + if (pmove->velocity[2] > 0) + pmove->onground = -1; + + if (pmove->onground != -1) + { + if (VectorCompare(pmove->basevelocity, vec3_origin) && VectorCompare(pmove->velocity, vec3_origin)) + return; + } + + PM_CheckVelocity(); + + if (pmove->movetype != MOVETYPE_FLY && pmove->movetype != MOVETYPE_BOUNCEMISSILE && pmove->movetype != MOVETYPE_FLYMISSILE) + PM_AddGravity(); + + VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); + + PM_CheckVelocity(); + VectorScale(pmove->velocity, pmove->frametime, move); + VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); + + trace = PM_PushEntity(move); + + PM_CheckVelocity(); + + if (trace.allsolid) + { + pmove->onground = trace.ent; + VectorCopy(vec3_origin, pmove->velocity); + return; + } + + if (trace.fraction == 1) + { + PM_CheckWater(); + return; + } + + if (pmove->movetype == MOVETYPE_BOUNCE) + backoff = 2.0 - pmove->friction; + else if (pmove->movetype == MOVETYPE_BOUNCEMISSILE) + backoff = 2.0; + else + backoff = 1; + + PM_ClipVelocity(pmove->velocity, trace.plane.normal, pmove->velocity, backoff); + + if (trace.plane.normal[2] > 0.7) + { + float vel; + vec3_t base; + + VectorClear(base); + + if (pmove->velocity[2] < pmove->movevars->gravity * pmove->frametime) + { + pmove->onground = trace.ent; + pmove->velocity[2] = 0; + } + + vel = DotProduct(pmove->velocity, pmove->velocity); + + if (vel < (30 * 30) || (pmove->movetype != MOVETYPE_BOUNCE && pmove->movetype != MOVETYPE_BOUNCEMISSILE)) + { + pmove->onground = trace.ent; + VectorCopy(vec3_origin, pmove->velocity); + } + else + { + VectorScale(pmove->velocity, (1.0 - trace.fraction) * pmove->frametime * 0.9, move); + + trace = PM_PushEntity(move); + } + + VectorSubtract(pmove->velocity, base, pmove->velocity) + } + + PM_CheckWater(); +} + +void PM_NoClip(void) +{ + int i; + vec3_t wishvel; + float fmove, smove; + float currentspeed, addspeed, accelspeed; + + fmove = pmove->cmd.forwardmove; + smove = pmove->cmd.sidemove; + + VectorNormalize(pmove->forward); + VectorNormalize(pmove->right); + + for (i = 0; i < 3; i++) + { + wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove; + } + + wishvel[2] += pmove->cmd.upmove; + + VectorMA(pmove->origin, pmove->frametime, wishvel, pmove->origin); + + VectorClear(pmove->velocity); +} + +#define BUNNYJUMP_MAX_SPEED_FACTOR 1.2f + +void PM_PreventMegaBunnyJumping(void) +{ + float spd; + float fraction; + float maxscaledspeed; + + maxscaledspeed = BUNNYJUMP_MAX_SPEED_FACTOR * pmove->maxspeed; + + if (maxscaledspeed <= 0.0f) + return; + + spd = Length(pmove->velocity); + + if (spd <= maxscaledspeed) + return; + + fraction = (maxscaledspeed / spd) * 0.8; + + VectorScale(pmove->velocity, fraction, pmove->velocity); +} + +void PM_Jump(void) +{ + int i; + qboolean tfc = false; + + qboolean cansuperjump = false; + + if (pmove->dead) + { + pmove->oldbuttons |= IN_JUMP; + return; + } + + if (pmove->waterjumptime) + { + pmove->waterjumptime -= pmove->cmd.msec; + + if (pmove->waterjumptime < 0) + { + pmove->waterjumptime = 0; + } + + return; + } + + if (pmove->waterlevel >= 2) + { + pmove->onground = -1; + + if (pmove->watertype == CONTENTS_WATER) + pmove->velocity[2] = 100; + else if (pmove->watertype == CONTENTS_SLIME) + pmove->velocity[2] = 80; + else + pmove->velocity[2] = 50; + + if (pmove->flSwimTime <= 0) + { + pmove->flSwimTime = 1000; + + switch (pmove->RandomLong(0, 3)) + { + case 0: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + + case 1: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade2.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + + case 2: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade3.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + + case 3: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade4.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + } + } + + return; + } + + if (pmove->onground == -1) + { + pmove->oldbuttons |= IN_JUMP; + return; + } + + if (~pmove->oldbuttons & IN_JUMP && (!pmove->bInDuck || ~pmove->flags & FL_DUCKING)) + { + pmove->onground = -1; + + PM_CatagorizeTextureType(); + PM_PreventMegaBunnyJumping(); + + if (Length(pmove->velocity) >= 150.0) + { + PM_PlayStepSound(PM_MapTextureTypeStepType(pmove->chtexturetype), 1.0); + } + + pmove->velocity[2] = sqrt(2 * 800 * 45.0); + + if (pmove->fuser2 > 0.0) + pmove->velocity[2] *= (100.0 - pmove->fuser2 * 0.001 * 19.0) * 0.01; + + pmove->fuser2 = 1315.7894; + + PM_FixupGravityVelocity(); + + pmove->oldbuttons |= IN_JUMP; + } +} + +#define WJ_HEIGHT 8 + +void PM_CheckWaterJump(void) +{ + vec3_t vecStart, vecEnd; + vec3_t flatforward; + vec3_t flatvelocity; + float curspeed; + pmtrace_t tr; + int savehull; + + if (pmove->waterjumptime) + return; + + if (pmove->velocity[2] < -180) + return; + + flatvelocity[0] = pmove->velocity[0]; + flatvelocity[1] = pmove->velocity[1]; + flatvelocity[2] = 0; + + curspeed = VectorNormalize(flatvelocity); + + flatforward[0] = pmove->forward[0]; + flatforward[1] = pmove->forward[1]; + flatforward[2] = 0; + VectorNormalize (flatforward); + + if (curspeed != 0.0 && (DotProduct(flatvelocity, flatforward) < 0.0)) + return; + + VectorCopy(pmove->origin, vecStart); + vecStart[2] += WJ_HEIGHT; + + VectorMA(vecStart, 24, flatforward, vecEnd); + + savehull = pmove->usehull; + pmove->usehull = 2; + tr = pmove->PM_PlayerTrace(vecStart, vecEnd, PM_NORMAL, -1); + + if (tr.fraction < 1.0 && fabs(tr.plane.normal[2]) < 0.1f) + { + vecStart[2] += pmove->player_maxs[savehull][2] - WJ_HEIGHT; + VectorMA(vecStart, 24, flatforward, vecEnd); + VectorMA(vec3_origin, -50, tr.plane.normal, pmove->movedir); + + tr = pmove->PM_PlayerTrace(vecStart, vecEnd, PM_NORMAL, -1); + + if (tr.fraction == 1.0) + { + pmove->waterjumptime = 2000; + pmove->velocity[2] = 225; + pmove->oldbuttons |= IN_JUMP; + pmove->flags |= FL_WATERJUMP; + } + } + + pmove->usehull = savehull; +} + +void PM_CheckFalling(void) +{ + if (pmove->onground != -1 && !pmove->dead && pmove->flFallVelocity >= PLAYER_FALL_PUNCH_THRESHHOLD) + { + float fvol = 0.5; + + if (pmove->waterlevel > 0) + { + } + else if (pmove->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED) + { + fvol = 1.0; + } + else if (pmove->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED / 2) + { + fvol = 0.85; + } + else if (pmove->flFallVelocity < PLAYER_MIN_BOUNCE_SPEED) + { + fvol = 0; + } + + if (fvol > 0.0) + { + PM_CatagorizeTextureType(); + PM_PlayStepSound(PM_MapTextureTypeStepType(pmove->chtexturetype), fvol); + + pmove->flTimeStepSound = 300; + + pmove->punchangle[2] = pmove->flFallVelocity * 0.013; + + if (pmove->punchangle[0] > 8) + pmove->punchangle[0] = 8; + } + } + + if (pmove->onground != -1) + { + pmove->flFallVelocity = 0; + } +} + +void PM_PlayWaterSounds(void) +{ + if ((pmove->oldwaterlevel == 0 && pmove->waterlevel != 0) || (pmove->oldwaterlevel != 0 && pmove->waterlevel == 0)) + { + switch (pmove->RandomLong(0, 3)) + { + case 0: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + + case 1: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade2.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + + case 2: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade3.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + + case 3: + { + pmove->PM_PlaySound(CHAN_BODY, "player/pl_wade4.wav", 1, ATTN_NORM, 0, PITCH_NORM); + break; + } + } + } +} + +float PM_CalcRoll(vec3_t angles, vec3_t velocity, float rollangle, float rollspeed) +{ + float sign; + float side; + float value; + vec3_t forward, right, up; + + AngleVectors(angles, forward, right, up); + + side = DotProduct(velocity, right); + + sign = side < 0 ? -1 : 1; + + side = fabs(side); + + value = rollangle; + + if (side < rollspeed) + { + side = side * value / rollspeed; + } + else + { + side = value; + } + + return side * sign; +} + +void PM_DropPunchAngle(vec3_t punchangle) +{ + float len; + + len = VectorNormalize (punchangle); + len -= (10.0 + len * 0.5) * pmove->frametime; + len = max(len, 0.0); + VectorScale(punchangle, len, punchangle); +} + +void PM_CheckParamters(void) +{ + float spd; + float maxspeed; + vec3_t v_angle; + + spd = (pmove->cmd.forwardmove * pmove->cmd.forwardmove) + (pmove->cmd.sidemove * pmove->cmd.sidemove) + (pmove->cmd.upmove * pmove->cmd.upmove); + spd = sqrt(spd); + + maxspeed = pmove->clientmaxspeed; + + if (maxspeed != 0.0) + pmove->maxspeed = min(maxspeed, pmove->maxspeed); + + if ((spd != 0.0) && (spd > pmove->maxspeed)) + { + float fRatio = pmove->maxspeed / spd; + pmove->cmd.forwardmove *= fRatio; + pmove->cmd.sidemove *= fRatio; + pmove->cmd.upmove *= fRatio; + } + + if (pmove->flags & FL_FROZEN || pmove->flags & FL_ONTRAIN || pmove->dead) + { + pmove->cmd.forwardmove = 0; + pmove->cmd.sidemove = 0; + pmove->cmd.upmove = 0; + } + + PM_DropPunchAngle(pmove->punchangle); + + if (!pmove->dead) + { + VectorCopy(pmove->cmd.viewangles, v_angle); + VectorAdd(v_angle, pmove->punchangle, v_angle); + + pmove->angles[ROLL] = PM_CalcRoll(v_angle, pmove->velocity, pmove->movevars->rollangle, pmove->movevars->rollspeed) * 4; + pmove->angles[PITCH] = v_angle[PITCH]; + pmove->angles[YAW] = v_angle[YAW]; + } + else + { + VectorCopy(pmove->oldangles, pmove->angles); + } + + if (pmove->dead) + { + pmove->view_ofs[2] = PM_DEAD_VIEWHEIGHT; + } + + if (pmove->angles[YAW] > 180.0f) + { + pmove->angles[YAW] -= 360.0f; + } +} + +void PM_ReduceTimers(void) +{ + if (pmove->flTimeStepSound > 0) + { + pmove->flTimeStepSound -= pmove->cmd.msec; + + if (pmove->flTimeStepSound < 0) + { + pmove->flTimeStepSound = 0; + } + } + + if (pmove->flDuckTime > 0) + { + pmove->flDuckTime -= pmove->cmd.msec; + + if (pmove->flDuckTime < 0) + { + pmove->flDuckTime = 0; + } + } + + if (pmove->flSwimTime > 0) + { + pmove->flSwimTime -= pmove->cmd.msec; + + if (pmove->flSwimTime < 0) + { + pmove->flSwimTime = 0; + } + } + + if (pmove->fuser2 > 0.0) + { + pmove->fuser2 -= pmove->cmd.msec; + + if (pmove->fuser2 < 0) + pmove->fuser2 = 0; + } +} + +void PM_PlayerMove(qboolean server) +{ + physent_t *pLadder = NULL; + + pmove->server = server; + + PM_CheckParamters(); + + pmove->numtouch = 0; + pmove->frametime = pmove->cmd.msec * 0.001; + + PM_ReduceTimers(); + + AngleVectors(pmove->angles, pmove->forward, pmove->right, pmove->up); + + if ((pmove->spectator || pmove->iuser1 > 0) && (pmove->iuser3 <= 0 || pmove->deadflag == DEAD_DEAD)) + { + PM_SpectatorMove(); + PM_CatagorizePosition(); + return; + } + + if (pmove->movetype != MOVETYPE_NOCLIP && pmove->movetype != MOVETYPE_NONE) + { + if (PM_CheckStuck()) + { + return; + } + } + + PM_CatagorizePosition(); + + pmove->oldwaterlevel = pmove->waterlevel; + + if (pmove->onground == -1) + { + pmove->flFallVelocity = -pmove->velocity[2]; + } + + g_onladder = 0; + + if (!pmove->dead && !(pmove->flags & FL_ONTRAIN)) + { + pLadder = PM_Ladder(); + + if (pLadder) + { + g_onladder = 1; + } + } + + PM_Duck(); + PM_UpdateStepSound(); + + if (!pmove->dead && !(pmove->flags & FL_ONTRAIN)) + { + if (pLadder) + { + PM_LadderMove(pLadder); + } + else if (pmove->movetype != MOVETYPE_WALK && pmove->movetype != MOVETYPE_NOCLIP) + { + pmove->movetype = MOVETYPE_WALK; + } + } + + switch (pmove->movetype) + { + default: + { + pmove->Con_DPrintf("Bogus pmove player movetype %i on (%i) 0=cl 1=sv\n", pmove->movetype, pmove->server); + break; + } + + case MOVETYPE_NONE: + { + break; + } + + case MOVETYPE_NOCLIP: + { + PM_NoClip(); + break; + } + + case MOVETYPE_TOSS: + case MOVETYPE_BOUNCE: + { + PM_Physics_Toss(); + break; + } + + case MOVETYPE_FLY: + { + PM_CheckWater(); + + if (pmove->cmd.buttons & IN_JUMP) + { + if (!pLadder) + { + PM_Jump(); + } + } + else + { + pmove->oldbuttons &= ~IN_JUMP; + } + + VectorAdd(pmove->velocity, pmove->basevelocity, pmove->velocity); + PM_FlyMove(); + VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); + break; + } + + case MOVETYPE_WALK: + { + if (!PM_InWater()) + { + PM_AddCorrectGravity(); + } + + if (pmove->waterjumptime) + { + PM_WaterJump(); + PM_FlyMove(); + + PM_CheckWater(); + return; + } + + if (pmove->waterlevel >= 2) + { + if (pmove->waterlevel == 2) + { + PM_CheckWaterJump(); + } + + if (pmove->velocity[2] < 0 && pmove->waterjumptime) + { + pmove->waterjumptime = 0; + } + + if (pmove->cmd.buttons & IN_JUMP) + { + PM_Jump(); + } + else + { + pmove->oldbuttons &= ~IN_JUMP; + } + + PM_WaterMove(); + + VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); + + PM_CatagorizePosition(); + } + else + { + if (pmove->cmd.buttons & IN_JUMP) + { + if (!pLadder) + { + PM_Jump(); + } + } + else + { + pmove->oldbuttons &= ~IN_JUMP; + } + + if (pmove->onground != -1) + { + pmove->velocity[2] = 0.0; + PM_Friction(); + } + + PM_CheckVelocity(); + + if (pmove->onground != -1) + { + PM_WalkMove(); + } + else + { + PM_AirMove(); + } + + PM_CatagorizePosition(); + + VectorSubtract(pmove->velocity, pmove->basevelocity, pmove->velocity); + + PM_CheckVelocity(); + + if (!PM_InWater()) + { + PM_FixupGravityVelocity(); + } + + if (pmove->onground != -1) + { + pmove->velocity[2] = 0; + } + + PM_CheckFalling(); + } + + PM_PlayWaterSounds(); + break; + } + } +} + +void PM_CreateStuckTable(void) +{ + float x, y, z; + int idx; + int i; + float zi[3]; + + memset(rgv3tStuckTable, 0, sizeof(rgv3tStuckTable)); + + idx = 0; + x = y = 0; + + for (z = -0.125; z <= 0.125; z += 0.125, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + + x = z = 0; + + for (y = -0.125; y <= 0.125; y += 0.125, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + + y = z = 0; + + for (x = -0.125; x <= 0.125; x += 0.125, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + + for (x = -0.125; x <= 0.125; x += 0.250) + { + for (y = -0.125; y <= 0.125; y += 0.250) + { + for (z = -0.125; z <= 0.125; z += 0.250, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + } + } + + x = y = 0; + zi[0] = 0; + zi[1] = 1; + zi[2] = 6; + + for (i = 0; i < 3; i++, idx++) + { + z = zi[i]; + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + + x = z = 0; + + for (y = -2; y <= 2; y += 2, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + + y = z = 0; + + for (x = -2; x <= 2; x += 2, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + + for (i = 0; i < 3; i++) + { + z = zi[i]; + + for (y = -2; y <= 2; y += 2) + { + for (z = -2; z <= 2; z += 2, idx++) + { + rgv3tStuckTable[idx][0] = x; + rgv3tStuckTable[idx][1] = y; + rgv3tStuckTable[idx][2] = z; + } + } + } +} + +void PM_Move (struct playermove_s *ppmove, int server) +{ + assert(pm_shared_initialized); + + pmove = ppmove; + + PM_PlayerMove((server != 0) ? true : false); + + if (pmove->onground != -1) + { + pmove->flags |= FL_ONGROUND; + } + else + { + pmove->flags &= ~FL_ONGROUND; + } + + if (!pmove->multiplayer && (pmove->movetype == MOVETYPE_WALK)) + { + pmove->friction = 1.0f; + } +} + +int PM_GetVisEntInfo(int ent) +{ + if (ent >= 0 && ent <= pmove->numvisent) + { + return pmove->visents[ent].info; + } + + return -1; +} + +int PM_GetPhysEntInfo(int ent) +{ + if (ent >= 0 && ent <= pmove->numphysent) + return pmove->physents[ent].info; + + return -1; +} + +void PM_Init(struct playermove_s *ppmove) +{ + assert(!pm_shared_initialized); + + pmove = ppmove; + + PM_CreateStuckTable(); + PM_InitTextureTypes(); + + pm_shared_initialized = 1; +} diff --git a/pm_shared/pm_shared.h b/pm_shared/pm_shared.h index 191e1fc..153c539 100644 --- a/pm_shared/pm_shared.h +++ b/pm_shared/pm_shared.h @@ -1,40 +1,40 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -* Use, distribution, and modification of this source code and/or resulting -* object code is restricted to non-commercial enhancements to products from -* Valve LLC. All other use, distribution, or modification is prohibited -* without written permission from Valve LLC. -* -****/ - -// -// pm_shared.h -// -#if !defined( PM_SHAREDH ) -#define PM_SHAREDH -#ifdef _WIN32 -#ifndef __MINGW32__ -#pragma once -#endif /* not __MINGW32__ */ -#endif - -void PM_Init( struct playermove_s *ppmove ); -void PM_Move ( struct playermove_s *ppmove, int server ); -char PM_FindTextureType( char *name ); - -// Spectator Movement modes (stored in pev->iuser1, so the physics code can get at them) -#define OBS_NONE 0 -#define OBS_CHASE_LOCKED 1 -#define OBS_CHASE_FREE 2 -#define OBS_ROAMING 3 -#define OBS_IN_EYE 4 -#define OBS_MAP_FREE 5 -#define OBS_MAP_CHASE 6 - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ + +// +// pm_shared.h +// +#if !defined( PM_SHAREDH ) +#define PM_SHAREDH +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma once +#endif /* not __MINGW32__ */ +#endif + +void PM_Init( struct playermove_s *ppmove ); +void PM_Move ( struct playermove_s *ppmove, int server ); +char PM_FindTextureType( char *name ); + +// Spectator Movement modes (stored in pev->iuser1, so the physics code can get at them) +#define OBS_NONE 0 +#define OBS_CHASE_LOCKED 1 +#define OBS_CHASE_FREE 2 +#define OBS_ROAMING 3 +#define OBS_IN_EYE 4 +#define OBS_MAP_FREE 5 +#define OBS_MAP_CHASE 6 + +#endif diff --git a/public/tier1/UtlMemory.h b/public/tier1/UtlMemory.h index dde74bf..123ce2a 100644 --- a/public/tier1/UtlMemory.h +++ b/public/tier1/UtlMemory.h @@ -1,388 +1,388 @@ -//=========== (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. -// -// $Header: $ -// $NoKeywords: $ -// -// A growable memory class. -//============================================================================= - -#ifndef UTLMEMORY_H -#define UTLMEMORY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include - -#pragma warning (disable:4100) -#pragma warning (disable:4514) - -//----------------------------------------------------------------------------- -// Methods to invoke the constructor, copy constructor, and destructor -//----------------------------------------------------------------------------- - -template -inline void Construct( T* pMemory ) -{ - ::new( pMemory ) T; -} - -template -inline void CopyConstruct( T* pMemory, T const& src ) -{ - ::new( pMemory ) T(src); -} - -template -inline void Destruct( T* pMemory ) -{ - pMemory->~T(); - -#ifdef _DEBUG - memset( pMemory, 0xDD, sizeof(T) ); -#endif -} - - - - - - - - - - - - - - - - - - -//----------------------------------------------------------------------------- -// The CUtlMemory class: -// A growable memory class which doubles in size by default. -//----------------------------------------------------------------------------- -template< class T > -class CUtlMemory -{ -public: - // constructor, destructor - CUtlMemory( int nGrowSize = 0, int nInitSize = 0 ); - CUtlMemory( T* pMemory, int numElements ); - CUtlMemory( const T* pMemory, int numElements ); - ~CUtlMemory(); - - // element access - T& operator[]( int i ); - T const& operator[]( int i ) const; - T& Element( int i ); - T const& Element( int i ) const; - - // Can we use this index? - bool IsIdxValid( int i ) const; - - // Gets the base address (can change when adding elements!) - T* Base(); - T const* Base() const; - - // Attaches the buffer to external memory.... - void SetExternalBuffer( T* pMemory, int numElements ); - - // Size - int NumAllocated() const; - int Count() const; - - // Grows the memory, so that at least allocated + num elements are allocated - void Grow( int num = 1 ); - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ); - - // Memory deallocation - void Purge(); - - // is the memory externally allocated? - bool IsExternallyAllocated() const; - - // is the memory read only? - bool IsReadOnly() const; - - // Set the size by which the memory grows - void SetGrowSize( int size ); - -private: - enum - { - EXTERNAL_BUFFER_MARKER = -1, - EXTERNAL_CONST_BUFFER_MARKER = 2, - }; - - T* m_pMemory; - int m_nAllocationCount; - int m_nGrowSize; -}; - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -template< class T > -CUtlMemory::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0), - m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize ) -{ - assert( (nGrowSize >= 0) && (nGrowSize != EXTERNAL_BUFFER_MARKER) ); - if (m_nAllocationCount) - { - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - } -} - -template< class T > -CUtlMemory::CUtlMemory( T* pMemory, int numElements ) : m_pMemory(pMemory), - m_nAllocationCount( numElements ) -{ - // Special marker indicating externally supplied memory - m_nGrowSize = EXTERNAL_BUFFER_MARKER; -} - -template< class T > -CUtlMemory::CUtlMemory( const T* pMemory, int numElements ) : m_pMemory( (T*)pMemory ), - m_nAllocationCount( numElements ) -{ - // Special marker indicating externally supplied modifyable memory - m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER; -} - -template< class T > -CUtlMemory::~CUtlMemory() -{ - Purge(); -} - - -//----------------------------------------------------------------------------- -// Attaches the buffer to external memory.... -//----------------------------------------------------------------------------- -template< class T > -void CUtlMemory::SetExternalBuffer( T* pMemory, int numElements ) -{ - // Blow away any existing allocated memory - Purge(); - - m_pMemory = pMemory; - m_nAllocationCount = numElements; - - // Indicate that we don't own the memory - m_nGrowSize = EXTERNAL_BUFFER_MARKER; -} - - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- -template< class T > -inline T& CUtlMemory::operator[]( int i ) -{ - assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - -template< class T > -inline T const& CUtlMemory::operator[]( int i ) const -{ - assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - -template< class T > -inline T& CUtlMemory::Element( int i ) -{ - assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - -template< class T > -inline T const& CUtlMemory::Element( int i ) const -{ - assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - - -//----------------------------------------------------------------------------- -// is the memory externally allocated? -//----------------------------------------------------------------------------- -template< class T > -bool CUtlMemory::IsExternallyAllocated() const -{ - return m_nGrowSize == EXTERNAL_BUFFER_MARKER; -} - -//----------------------------------------------------------------------------- -// is the memory read only? -//----------------------------------------------------------------------------- -template< class T > -bool CUtlMemory::IsReadOnly() const -{ - return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER); -} - -template< class T > -void CUtlMemory::SetGrowSize( int nSize ) -{ - assert( (nSize >= 0) && (nSize != EXTERNAL_BUFFER_MARKER) ); - m_nGrowSize = nSize; -} - - -//----------------------------------------------------------------------------- -// Gets the base address (can change when adding elements!) -//----------------------------------------------------------------------------- -template< class T > -inline T* CUtlMemory::Base() -{ - return m_pMemory; -} - -template< class T > -inline T const* CUtlMemory::Base() const -{ - return m_pMemory; -} - - -//----------------------------------------------------------------------------- -// Size -//----------------------------------------------------------------------------- -template< class T > -inline int CUtlMemory::NumAllocated() const -{ - return m_nAllocationCount; -} - -template< class T > -inline int CUtlMemory::Count() const -{ - return m_nAllocationCount; -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- -template< class T > -inline bool CUtlMemory::IsIdxValid( int i ) const -{ - return (i >= 0) && (i < m_nAllocationCount); -} - - -//----------------------------------------------------------------------------- -// Grows the memory -//----------------------------------------------------------------------------- -template< class T > -void CUtlMemory::Grow( int num ) -{ - assert( num > 0 ); - - if (IsExternallyAllocated()) - { - // Can't grow a buffer whose memory was externally allocated - assert(0); - return; - } - - // Make sure we have at least numallocated + num allocations. - // Use the grow rules specified for this memory (in m_nGrowSize) - int nAllocationRequested = m_nAllocationCount + num; - while (m_nAllocationCount < nAllocationRequested) - { - if ( m_nAllocationCount != 0 ) - { - if (m_nGrowSize) - { - m_nAllocationCount += m_nGrowSize; - } - else - { - m_nAllocationCount += m_nAllocationCount; - } - } - else - { - // Compute an allocation which is at least as big as a cache line... - m_nAllocationCount = (31 + sizeof(T)) / sizeof(T); - assert(m_nAllocationCount != 0); - } - } - - if (m_pMemory) - { - m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); - } - else - { - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - } -} - - -//----------------------------------------------------------------------------- -// Makes sure we've got at least this much memory -//----------------------------------------------------------------------------- -template< class T > -inline void CUtlMemory::EnsureCapacity( int num ) -{ - if (m_nAllocationCount >= num) - return; - - if (IsExternallyAllocated()) - { - // Can't grow a buffer whose memory was externally allocated - assert(0); - return; - } - - m_nAllocationCount = num; - if (m_pMemory) - { - m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); - } - else - { - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - } -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- -template< class T > -void CUtlMemory::Purge() -{ - if (!IsExternallyAllocated()) - { - if (m_pMemory) - { - free( (void*)m_pMemory ); - m_pMemory = 0; - } - m_nAllocationCount = 0; - } -} - - -#endif // UTLSTORAGE_H +//=========== (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. +// +// $Header: $ +// $NoKeywords: $ +// +// A growable memory class. +//============================================================================= + +#ifndef UTLMEMORY_H +#define UTLMEMORY_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include +#include + +#pragma warning (disable:4100) +#pragma warning (disable:4514) + +//----------------------------------------------------------------------------- +// Methods to invoke the constructor, copy constructor, and destructor +//----------------------------------------------------------------------------- + +template +inline void Construct( T* pMemory ) +{ + ::new( pMemory ) T; +} + +template +inline void CopyConstruct( T* pMemory, T const& src ) +{ + ::new( pMemory ) T(src); +} + +template +inline void Destruct( T* pMemory ) +{ + pMemory->~T(); + +#ifdef _DEBUG + memset( pMemory, 0xDD, sizeof(T) ); +#endif +} + + + + + + + + + + + + + + + + + + +//----------------------------------------------------------------------------- +// The CUtlMemory class: +// A growable memory class which doubles in size by default. +//----------------------------------------------------------------------------- +template< class T > +class CUtlMemory +{ +public: + // constructor, destructor + CUtlMemory( int nGrowSize = 0, int nInitSize = 0 ); + CUtlMemory( T* pMemory, int numElements ); + CUtlMemory( const T* pMemory, int numElements ); + ~CUtlMemory(); + + // element access + T& operator[]( int i ); + T const& operator[]( int i ) const; + T& Element( int i ); + T const& Element( int i ) const; + + // Can we use this index? + bool IsIdxValid( int i ) const; + + // Gets the base address (can change when adding elements!) + T* Base(); + T const* Base() const; + + // Attaches the buffer to external memory.... + void SetExternalBuffer( T* pMemory, int numElements ); + + // Size + int NumAllocated() const; + int Count() const; + + // Grows the memory, so that at least allocated + num elements are allocated + void Grow( int num = 1 ); + + // Makes sure we've got at least this much memory + void EnsureCapacity( int num ); + + // Memory deallocation + void Purge(); + + // is the memory externally allocated? + bool IsExternallyAllocated() const; + + // is the memory read only? + bool IsReadOnly() const; + + // Set the size by which the memory grows + void SetGrowSize( int size ); + +private: + enum + { + EXTERNAL_BUFFER_MARKER = -1, + EXTERNAL_CONST_BUFFER_MARKER = 2, + }; + + T* m_pMemory; + int m_nAllocationCount; + int m_nGrowSize; +}; + + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- +template< class T > +CUtlMemory::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0), + m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize ) +{ + assert( (nGrowSize >= 0) && (nGrowSize != EXTERNAL_BUFFER_MARKER) ); + if (m_nAllocationCount) + { + m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); + } +} + +template< class T > +CUtlMemory::CUtlMemory( T* pMemory, int numElements ) : m_pMemory(pMemory), + m_nAllocationCount( numElements ) +{ + // Special marker indicating externally supplied memory + m_nGrowSize = EXTERNAL_BUFFER_MARKER; +} + +template< class T > +CUtlMemory::CUtlMemory( const T* pMemory, int numElements ) : m_pMemory( (T*)pMemory ), + m_nAllocationCount( numElements ) +{ + // Special marker indicating externally supplied modifyable memory + m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER; +} + +template< class T > +CUtlMemory::~CUtlMemory() +{ + Purge(); +} + + +//----------------------------------------------------------------------------- +// Attaches the buffer to external memory.... +//----------------------------------------------------------------------------- +template< class T > +void CUtlMemory::SetExternalBuffer( T* pMemory, int numElements ) +{ + // Blow away any existing allocated memory + Purge(); + + m_pMemory = pMemory; + m_nAllocationCount = numElements; + + // Indicate that we don't own the memory + m_nGrowSize = EXTERNAL_BUFFER_MARKER; +} + + +//----------------------------------------------------------------------------- +// element access +//----------------------------------------------------------------------------- +template< class T > +inline T& CUtlMemory::operator[]( int i ) +{ + assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + +template< class T > +inline T const& CUtlMemory::operator[]( int i ) const +{ + assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + +template< class T > +inline T& CUtlMemory::Element( int i ) +{ + assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + +template< class T > +inline T const& CUtlMemory::Element( int i ) const +{ + assert( IsIdxValid(i) ); + return m_pMemory[i]; +} + + +//----------------------------------------------------------------------------- +// is the memory externally allocated? +//----------------------------------------------------------------------------- +template< class T > +bool CUtlMemory::IsExternallyAllocated() const +{ + return m_nGrowSize == EXTERNAL_BUFFER_MARKER; +} + +//----------------------------------------------------------------------------- +// is the memory read only? +//----------------------------------------------------------------------------- +template< class T > +bool CUtlMemory::IsReadOnly() const +{ + return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER); +} + +template< class T > +void CUtlMemory::SetGrowSize( int nSize ) +{ + assert( (nSize >= 0) && (nSize != EXTERNAL_BUFFER_MARKER) ); + m_nGrowSize = nSize; +} + + +//----------------------------------------------------------------------------- +// Gets the base address (can change when adding elements!) +//----------------------------------------------------------------------------- +template< class T > +inline T* CUtlMemory::Base() +{ + return m_pMemory; +} + +template< class T > +inline T const* CUtlMemory::Base() const +{ + return m_pMemory; +} + + +//----------------------------------------------------------------------------- +// Size +//----------------------------------------------------------------------------- +template< class T > +inline int CUtlMemory::NumAllocated() const +{ + return m_nAllocationCount; +} + +template< class T > +inline int CUtlMemory::Count() const +{ + return m_nAllocationCount; +} + + +//----------------------------------------------------------------------------- +// Is element index valid? +//----------------------------------------------------------------------------- +template< class T > +inline bool CUtlMemory::IsIdxValid( int i ) const +{ + return (i >= 0) && (i < m_nAllocationCount); +} + + +//----------------------------------------------------------------------------- +// Grows the memory +//----------------------------------------------------------------------------- +template< class T > +void CUtlMemory::Grow( int num ) +{ + assert( num > 0 ); + + if (IsExternallyAllocated()) + { + // Can't grow a buffer whose memory was externally allocated + assert(0); + return; + } + + // Make sure we have at least numallocated + num allocations. + // Use the grow rules specified for this memory (in m_nGrowSize) + int nAllocationRequested = m_nAllocationCount + num; + while (m_nAllocationCount < nAllocationRequested) + { + if ( m_nAllocationCount != 0 ) + { + if (m_nGrowSize) + { + m_nAllocationCount += m_nGrowSize; + } + else + { + m_nAllocationCount += m_nAllocationCount; + } + } + else + { + // Compute an allocation which is at least as big as a cache line... + m_nAllocationCount = (31 + sizeof(T)) / sizeof(T); + assert(m_nAllocationCount != 0); + } + } + + if (m_pMemory) + { + m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); + } + else + { + m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); + } +} + + +//----------------------------------------------------------------------------- +// Makes sure we've got at least this much memory +//----------------------------------------------------------------------------- +template< class T > +inline void CUtlMemory::EnsureCapacity( int num ) +{ + if (m_nAllocationCount >= num) + return; + + if (IsExternallyAllocated()) + { + // Can't grow a buffer whose memory was externally allocated + assert(0); + return; + } + + m_nAllocationCount = num; + if (m_pMemory) + { + m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); + } + else + { + m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); + } +} + + +//----------------------------------------------------------------------------- +// Memory deallocation +//----------------------------------------------------------------------------- +template< class T > +void CUtlMemory::Purge() +{ + if (!IsExternallyAllocated()) + { + if (m_pMemory) + { + free( (void*)m_pMemory ); + m_pMemory = 0; + } + m_nAllocationCount = 0; + } +} + + +#endif // UTLSTORAGE_H diff --git a/public/tier1/UtlVector.h b/public/tier1/UtlVector.h index 8febe34..24569db 100644 --- a/public/tier1/UtlVector.h +++ b/public/tier1/UtlVector.h @@ -1,603 +1,603 @@ -//=========== (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. -// -// $Header: $ -// $NoKeywords: $ -// -// A growable array class that maintains a free list and keeps elements -// in the same location -//============================================================================= - -#ifndef UTLVECTOR_H -#define UTLVECTOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "UtlMemory.h" - -//----------------------------------------------------------------------------- -// The CUtlVector class: -// A growable array class which doubles in size by default. -// It will always keep all elements consecutive in memory, and may move the -// elements around in memory (via a realloc) when elements are inserted or -// removed. Clients should therefore refer to the elements of the vector -// by index (they should *never* maintain pointers to elements in the vector). -//----------------------------------------------------------------------------- - -template< class T > -class CUtlVector -{ -public: - typedef T ElemType_t; - - // constructor, destructor - CUtlVector( int growSize = 0, int initSize = 0 ); - CUtlVector( T* pMemory, int numElements ); - ~CUtlVector(); - - // Copy the array. - CUtlVector& operator=( const CUtlVector &other ); - - // element access - T& operator[]( int i ); - T const& operator[]( int i ) const; - T& Element( int i ); - T const& Element( int i ) const; - - // Gets the base address (can change when adding elements!) - T* Base(); - T const* Base() const; - - // Returns the number of elements in the vector - // SIZE IS DEPRECATED! - int Count() const; - int Size() const; // don't use me! - - // Is element index valid? - bool IsValidIndex( int i ) const; - static int InvalidIndex( void ); - - // Adds an element, uses default constructor - int AddToHead(); - int AddToTail(); - int InsertBefore( int elem ); - int InsertAfter( int elem ); - - // Adds an element, uses copy constructor - int AddToHead( T const& src ); - int AddToTail( T const& src ); - int InsertBefore( int elem, T const& src ); - int InsertAfter( int elem, T const& src ); - - // Adds multiple elements, uses default constructor - int AddMultipleToHead( int num ); - int AddMultipleToTail( int num, const T *pToCopy=NULL ); - int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and - int InsertMultipleAfter( int elem, int num ); - - // Calls RemoveAll() then AddMultipleToTail. - void SetSize( int size ); - void SetCount( int count ); - - // Calls SetSize and copies each element. - void CopyArray( T const *pArray, int size ); - - // Add the specified array to the tail. - int AddVectorToTail( CUtlVector const &src ); - - // Finds an element (element needs operator== defined) - int Find( T const& src ) const; - - bool HasElement( T const& src ); - - // Makes sure we have enough memory allocated to store a requested # of elements - void EnsureCapacity( int num ); - - // Makes sure we have at least this many elements - void EnsureCount( int num ); - - // Element removal - void FastRemove( int elem ); // doesn't preserve order - void Remove( int elem ); // preserves order, shifts elements - void FindAndRemove( T const& src ); // removes first occurrence of src, preserves order, shifts elements - void RemoveMultiple( int elem, int num ); // preserves order, shifts elements - void RemoveAll(); // doesn't deallocate memory - - // Memory deallocation - void Purge(); - - // Purges the list and calls delete on each element in it. - void PurgeAndDeleteElements(); - - // Set the size by which it grows when it needs to allocate more memory. - void SetGrowSize( int size ); - -protected: - // Can't copy this unless we explicitly do it! - CUtlVector( CUtlVector const& vec ) { assert(0); - } - - // Grows the vector - void GrowVector( int num = 1 ); - - // Shifts elements.... - void ShiftElementsRight( int elem, int num = 1 ); - void ShiftElementsLeft( int elem, int num = 1 ); - - // For easier access to the elements through the debugger - void ResetDbgInfo(); - - CUtlMemory m_Memory; - int m_Size; - - // For easier access to the elements through the debugger - // it's in release builds so this can be used in libraries correctly - T *m_pElements; -}; - - -//----------------------------------------------------------------------------- -// For easier access to the elements through the debugger -//----------------------------------------------------------------------------- - -template< class T > -inline void CUtlVector::ResetDbgInfo() -{ - m_pElements = m_Memory.Base(); -} - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template< class T > -inline CUtlVector::CUtlVector( int growSize, int initSize ) : - m_Memory(growSize, initSize), m_Size(0) -{ - ResetDbgInfo(); -} - -template< class T > -inline CUtlVector::CUtlVector( T* pMemory, int numElements ) : - m_Memory(pMemory, numElements), m_Size(0) -{ - ResetDbgInfo(); -} - -template< class T > -inline CUtlVector::~CUtlVector() -{ - Purge(); -} - -template -inline CUtlVector& CUtlVector::operator=( const CUtlVector &other ) -{ - CopyArray( other.Base(), other.Count() ); - return *this; -} - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- - -template< class T > -inline T& CUtlVector::operator[]( int i ) -{ - assert( IsValidIndex(i) ); - return m_Memory[i]; -} - -template< class T > -inline T const& CUtlVector::operator[]( int i ) const -{ - assert( IsValidIndex(i) ); - return m_Memory[i]; -} - -template< class T > -inline T& CUtlVector::Element( int i ) -{ - assert( IsValidIndex(i) ); - return m_Memory[i]; -} - -template< class T > -inline T const& CUtlVector::Element( int i ) const -{ - assert( IsValidIndex(i) ); - return m_Memory[i]; -} - - -//----------------------------------------------------------------------------- -// Gets the base address (can change when adding elements!) -//----------------------------------------------------------------------------- - -template< class T > -inline T* CUtlVector::Base() -{ - return m_Memory.Base(); -} - -template< class T > -inline T const* CUtlVector::Base() const -{ - return m_Memory.Base(); -} - -//----------------------------------------------------------------------------- -// Count -//----------------------------------------------------------------------------- - -template< class T > -inline int CUtlVector::Size() const -{ - return m_Size; -} - -template< class T > -inline int CUtlVector::Count() const -{ - return m_Size; -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- - -template< class T > -inline bool CUtlVector::IsValidIndex( int i ) const -{ - return (i >= 0) && (i < m_Size); -} - - -//----------------------------------------------------------------------------- -// Returns in invalid index -//----------------------------------------------------------------------------- -template< class T > -inline int CUtlVector::InvalidIndex( void ) -{ - return -1; -} - - -//----------------------------------------------------------------------------- -// Grows the vector -//----------------------------------------------------------------------------- -template< class T > -void CUtlVector::GrowVector( int num ) -{ - if (m_Size + num - 1 >= m_Memory.NumAllocated()) - { - m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() ); - } - - m_Size += num; - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Makes sure we have enough memory allocated to store a requested # of elements -//----------------------------------------------------------------------------- -template< class T > -void CUtlVector::EnsureCapacity( int num ) -{ - m_Memory.EnsureCapacity(num); - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Makes sure we have at least this many elements -//----------------------------------------------------------------------------- -template< class T > -void CUtlVector::EnsureCount( int num ) -{ - if (Count() < num) - AddMultipleToTail( num - Count() ); -} - - -//----------------------------------------------------------------------------- -// Shifts elements -//----------------------------------------------------------------------------- -template< class T > -void CUtlVector::ShiftElementsRight( int elem, int num ) -{ - assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); - int numToMove = m_Size - elem - num; - if ((numToMove > 0) && (num > 0)) - memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) ); -} - -template< class T > -void CUtlVector::ShiftElementsLeft( int elem, int num ) -{ - assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); - int numToMove = m_Size - elem - num; - if ((numToMove > 0) && (num > 0)) - { - memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) ); - -#ifdef _DEBUG - memset( &Element(m_Size-num), 0xDD, num * sizeof(T) ); -#endif - } -} - -//----------------------------------------------------------------------------- -// Adds an element, uses default constructor -//----------------------------------------------------------------------------- - -template< class T > -inline int CUtlVector::AddToHead() -{ - return InsertBefore(0); -} - -template< class T > -inline int CUtlVector::AddToTail() -{ - return InsertBefore( m_Size ); -} - -template< class T > -inline int CUtlVector::InsertAfter( int elem ) -{ - return InsertBefore( elem + 1 ); -} - -template< class T > -int CUtlVector::InsertBefore( int elem ) -{ - // Can insert at the end - assert( (elem == Count()) || IsValidIndex(elem) ); - - GrowVector(); - ShiftElementsRight(elem); - Construct( &Element(elem) ); - return elem; -} - - -//----------------------------------------------------------------------------- -// Adds an element, uses copy constructor -//----------------------------------------------------------------------------- - -template< class T > -inline int CUtlVector::AddToHead( T const& src ) -{ - return InsertBefore( 0, src ); -} - -template< class T > -inline int CUtlVector::AddToTail( T const& src ) -{ - return InsertBefore( m_Size, src ); -} - -template< class T > -inline int CUtlVector::InsertAfter( int elem, T const& src ) -{ - return InsertBefore( elem + 1, src ); -} - -template< class T > -int CUtlVector::InsertBefore( int elem, T const& src ) -{ - // Can insert at the end - assert( (elem == Count()) || IsValidIndex(elem) ); - - GrowVector(); - ShiftElementsRight(elem); - CopyConstruct( &Element(elem), src ); - return elem; -} - - -//----------------------------------------------------------------------------- -// Adds multiple elements, uses default constructor -//----------------------------------------------------------------------------- - -template< class T > -inline int CUtlVector::AddMultipleToHead( int num ) -{ - return InsertMultipleBefore( 0, num ); -} - -template< class T > -inline int CUtlVector::AddMultipleToTail( int num, const T *pToCopy ) -{ - return InsertMultipleBefore( m_Size, num, pToCopy ); -} - -template< class T > -int CUtlVector::InsertMultipleAfter( int elem, int num ) -{ - return InsertMultipleBefore( elem + 1, num ); -} - - -template< class T > -void CUtlVector::SetCount( int count ) -{ - RemoveAll(); - AddMultipleToTail( count ); -} - -template< class T > -inline void CUtlVector::SetSize( int size ) -{ - SetCount( size ); -} - -template< class T > -void CUtlVector::CopyArray( T const *pArray, int size ) -{ - SetSize( size ); - for( int i=0; i < size; i++ ) - (*this)[i] = pArray[i]; -} - -template< class T > -int CUtlVector::AddVectorToTail( CUtlVector const &src ) -{ - int base = Count(); - - // Make space. - AddMultipleToTail( src.Count() ); - - // Copy the elements. - for ( int i=0; i < src.Count(); i++ ) - (*this)[base + i] = src[i]; - - return base; -} - -template< class T > -inline int CUtlVector::InsertMultipleBefore( int elem, int num, const T *pToInsert ) -{ - if( num == 0 ) - return elem; - - // Can insert at the end - assert( (elem == Count()) || IsValidIndex(elem) ); - - GrowVector(num); - ShiftElementsRight(elem, num); - - // Invoke default constructors - for (int i = 0; i < num; ++i) - Construct( &Element(elem+i) ); - - // Copy stuff in? - if ( pToInsert ) - { - for ( int i=0; i < num; i++ ) - { - Element( elem+i ) = pToInsert[i]; - } - } - - return elem; -} - -//----------------------------------------------------------------------------- -// Finds an element (element needs operator== defined) -//----------------------------------------------------------------------------- -template< class T > -int CUtlVector::Find( T const& src ) const -{ - for ( int i = 0; i < Count(); ++i ) - { - if (Element(i) == src) - return i; - } - return -1; -} - -template< class T > -bool CUtlVector::HasElement( T const& src ) -{ - return ( Find(src) >= 0 ); -} - -//----------------------------------------------------------------------------- -// Element removal -//----------------------------------------------------------------------------- - -template< class T > -void CUtlVector::FastRemove( int elem ) -{ - assert( IsValidIndex(elem) ); - - Destruct( &Element(elem) ); - if (m_Size > 0) - { - memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) ); - --m_Size; - } -} - -template< class T > -void CUtlVector::Remove( int elem ) -{ - Destruct( &Element(elem) ); - ShiftElementsLeft(elem); - --m_Size; -} - -template< class T > -void CUtlVector::FindAndRemove( T const& src ) -{ - int elem = Find( src ); - if ( elem != -1 ) - { - Remove( elem ); - } -} - -template< class T > -void CUtlVector::RemoveMultiple( int elem, int num ) -{ - assert( IsValidIndex(elem) ); - assert( elem + num <= Count() ); - - for (int i = elem + num; --i >= elem; ) - Destruct(&Element(i)); - - ShiftElementsLeft(elem, num); - m_Size -= num; -} - -template< class T > -void CUtlVector::RemoveAll() -{ - for (int i = m_Size; --i >= 0; ) - Destruct(&Element(i)); - - m_Size = 0; -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- - -template< class T > -void CUtlVector::Purge() -{ - RemoveAll(); - m_Memory.Purge( ); - ResetDbgInfo(); -} - - -template -inline void CUtlVector::PurgeAndDeleteElements() -{ - for( int i=0; i < m_Size; i++ ) - delete Element(i); - - Purge(); -} - - -template< class T > -void CUtlVector::SetGrowSize( int size ) -{ - m_Memory.SetGrowSize( size ); -} - - -#endif // CCVECTOR_H +//=========== (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. +// +// $Header: $ +// $NoKeywords: $ +// +// A growable array class that maintains a free list and keeps elements +// in the same location +//============================================================================= + +#ifndef UTLVECTOR_H +#define UTLVECTOR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "UtlMemory.h" + +//----------------------------------------------------------------------------- +// The CUtlVector class: +// A growable array class which doubles in size by default. +// It will always keep all elements consecutive in memory, and may move the +// elements around in memory (via a realloc) when elements are inserted or +// removed. Clients should therefore refer to the elements of the vector +// by index (they should *never* maintain pointers to elements in the vector). +//----------------------------------------------------------------------------- + +template< class T > +class CUtlVector +{ +public: + typedef T ElemType_t; + + // constructor, destructor + CUtlVector( int growSize = 0, int initSize = 0 ); + CUtlVector( T* pMemory, int numElements ); + ~CUtlVector(); + + // Copy the array. + CUtlVector& operator=( const CUtlVector &other ); + + // element access + T& operator[]( int i ); + T const& operator[]( int i ) const; + T& Element( int i ); + T const& Element( int i ) const; + + // Gets the base address (can change when adding elements!) + T* Base(); + T const* Base() const; + + // Returns the number of elements in the vector + // SIZE IS DEPRECATED! + int Count() const; + int Size() const; // don't use me! + + // Is element index valid? + bool IsValidIndex( int i ) const; + static int InvalidIndex( void ); + + // Adds an element, uses default constructor + int AddToHead(); + int AddToTail(); + int InsertBefore( int elem ); + int InsertAfter( int elem ); + + // Adds an element, uses copy constructor + int AddToHead( T const& src ); + int AddToTail( T const& src ); + int InsertBefore( int elem, T const& src ); + int InsertAfter( int elem, T const& src ); + + // Adds multiple elements, uses default constructor + int AddMultipleToHead( int num ); + int AddMultipleToTail( int num, const T *pToCopy=NULL ); + int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and + int InsertMultipleAfter( int elem, int num ); + + // Calls RemoveAll() then AddMultipleToTail. + void SetSize( int size ); + void SetCount( int count ); + + // Calls SetSize and copies each element. + void CopyArray( T const *pArray, int size ); + + // Add the specified array to the tail. + int AddVectorToTail( CUtlVector const &src ); + + // Finds an element (element needs operator== defined) + int Find( T const& src ) const; + + bool HasElement( T const& src ); + + // Makes sure we have enough memory allocated to store a requested # of elements + void EnsureCapacity( int num ); + + // Makes sure we have at least this many elements + void EnsureCount( int num ); + + // Element removal + void FastRemove( int elem ); // doesn't preserve order + void Remove( int elem ); // preserves order, shifts elements + void FindAndRemove( T const& src ); // removes first occurrence of src, preserves order, shifts elements + void RemoveMultiple( int elem, int num ); // preserves order, shifts elements + void RemoveAll(); // doesn't deallocate memory + + // Memory deallocation + void Purge(); + + // Purges the list and calls delete on each element in it. + void PurgeAndDeleteElements(); + + // Set the size by which it grows when it needs to allocate more memory. + void SetGrowSize( int size ); + +protected: + // Can't copy this unless we explicitly do it! + CUtlVector( CUtlVector const& vec ) { assert(0); + } + + // Grows the vector + void GrowVector( int num = 1 ); + + // Shifts elements.... + void ShiftElementsRight( int elem, int num = 1 ); + void ShiftElementsLeft( int elem, int num = 1 ); + + // For easier access to the elements through the debugger + void ResetDbgInfo(); + + CUtlMemory m_Memory; + int m_Size; + + // For easier access to the elements through the debugger + // it's in release builds so this can be used in libraries correctly + T *m_pElements; +}; + + +//----------------------------------------------------------------------------- +// For easier access to the elements through the debugger +//----------------------------------------------------------------------------- + +template< class T > +inline void CUtlVector::ResetDbgInfo() +{ + m_pElements = m_Memory.Base(); +} + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- + +template< class T > +inline CUtlVector::CUtlVector( int growSize, int initSize ) : + m_Memory(growSize, initSize), m_Size(0) +{ + ResetDbgInfo(); +} + +template< class T > +inline CUtlVector::CUtlVector( T* pMemory, int numElements ) : + m_Memory(pMemory, numElements), m_Size(0) +{ + ResetDbgInfo(); +} + +template< class T > +inline CUtlVector::~CUtlVector() +{ + Purge(); +} + +template +inline CUtlVector& CUtlVector::operator=( const CUtlVector &other ) +{ + CopyArray( other.Base(), other.Count() ); + return *this; +} + +//----------------------------------------------------------------------------- +// element access +//----------------------------------------------------------------------------- + +template< class T > +inline T& CUtlVector::operator[]( int i ) +{ + assert( IsValidIndex(i) ); + return m_Memory[i]; +} + +template< class T > +inline T const& CUtlVector::operator[]( int i ) const +{ + assert( IsValidIndex(i) ); + return m_Memory[i]; +} + +template< class T > +inline T& CUtlVector::Element( int i ) +{ + assert( IsValidIndex(i) ); + return m_Memory[i]; +} + +template< class T > +inline T const& CUtlVector::Element( int i ) const +{ + assert( IsValidIndex(i) ); + return m_Memory[i]; +} + + +//----------------------------------------------------------------------------- +// Gets the base address (can change when adding elements!) +//----------------------------------------------------------------------------- + +template< class T > +inline T* CUtlVector::Base() +{ + return m_Memory.Base(); +} + +template< class T > +inline T const* CUtlVector::Base() const +{ + return m_Memory.Base(); +} + +//----------------------------------------------------------------------------- +// Count +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::Size() const +{ + return m_Size; +} + +template< class T > +inline int CUtlVector::Count() const +{ + return m_Size; +} + + +//----------------------------------------------------------------------------- +// Is element index valid? +//----------------------------------------------------------------------------- + +template< class T > +inline bool CUtlVector::IsValidIndex( int i ) const +{ + return (i >= 0) && (i < m_Size); +} + + +//----------------------------------------------------------------------------- +// Returns in invalid index +//----------------------------------------------------------------------------- +template< class T > +inline int CUtlVector::InvalidIndex( void ) +{ + return -1; +} + + +//----------------------------------------------------------------------------- +// Grows the vector +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::GrowVector( int num ) +{ + if (m_Size + num - 1 >= m_Memory.NumAllocated()) + { + m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() ); + } + + m_Size += num; + ResetDbgInfo(); +} + + +//----------------------------------------------------------------------------- +// Makes sure we have enough memory allocated to store a requested # of elements +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::EnsureCapacity( int num ) +{ + m_Memory.EnsureCapacity(num); + ResetDbgInfo(); +} + + +//----------------------------------------------------------------------------- +// Makes sure we have at least this many elements +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::EnsureCount( int num ) +{ + if (Count() < num) + AddMultipleToTail( num - Count() ); +} + + +//----------------------------------------------------------------------------- +// Shifts elements +//----------------------------------------------------------------------------- +template< class T > +void CUtlVector::ShiftElementsRight( int elem, int num ) +{ + assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); + int numToMove = m_Size - elem - num; + if ((numToMove > 0) && (num > 0)) + memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) ); +} + +template< class T > +void CUtlVector::ShiftElementsLeft( int elem, int num ) +{ + assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); + int numToMove = m_Size - elem - num; + if ((numToMove > 0) && (num > 0)) + { + memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) ); + +#ifdef _DEBUG + memset( &Element(m_Size-num), 0xDD, num * sizeof(T) ); +#endif + } +} + +//----------------------------------------------------------------------------- +// Adds an element, uses default constructor +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::AddToHead() +{ + return InsertBefore(0); +} + +template< class T > +inline int CUtlVector::AddToTail() +{ + return InsertBefore( m_Size ); +} + +template< class T > +inline int CUtlVector::InsertAfter( int elem ) +{ + return InsertBefore( elem + 1 ); +} + +template< class T > +int CUtlVector::InsertBefore( int elem ) +{ + // Can insert at the end + assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(); + ShiftElementsRight(elem); + Construct( &Element(elem) ); + return elem; +} + + +//----------------------------------------------------------------------------- +// Adds an element, uses copy constructor +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::AddToHead( T const& src ) +{ + return InsertBefore( 0, src ); +} + +template< class T > +inline int CUtlVector::AddToTail( T const& src ) +{ + return InsertBefore( m_Size, src ); +} + +template< class T > +inline int CUtlVector::InsertAfter( int elem, T const& src ) +{ + return InsertBefore( elem + 1, src ); +} + +template< class T > +int CUtlVector::InsertBefore( int elem, T const& src ) +{ + // Can insert at the end + assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(); + ShiftElementsRight(elem); + CopyConstruct( &Element(elem), src ); + return elem; +} + + +//----------------------------------------------------------------------------- +// Adds multiple elements, uses default constructor +//----------------------------------------------------------------------------- + +template< class T > +inline int CUtlVector::AddMultipleToHead( int num ) +{ + return InsertMultipleBefore( 0, num ); +} + +template< class T > +inline int CUtlVector::AddMultipleToTail( int num, const T *pToCopy ) +{ + return InsertMultipleBefore( m_Size, num, pToCopy ); +} + +template< class T > +int CUtlVector::InsertMultipleAfter( int elem, int num ) +{ + return InsertMultipleBefore( elem + 1, num ); +} + + +template< class T > +void CUtlVector::SetCount( int count ) +{ + RemoveAll(); + AddMultipleToTail( count ); +} + +template< class T > +inline void CUtlVector::SetSize( int size ) +{ + SetCount( size ); +} + +template< class T > +void CUtlVector::CopyArray( T const *pArray, int size ) +{ + SetSize( size ); + for( int i=0; i < size; i++ ) + (*this)[i] = pArray[i]; +} + +template< class T > +int CUtlVector::AddVectorToTail( CUtlVector const &src ) +{ + int base = Count(); + + // Make space. + AddMultipleToTail( src.Count() ); + + // Copy the elements. + for ( int i=0; i < src.Count(); i++ ) + (*this)[base + i] = src[i]; + + return base; +} + +template< class T > +inline int CUtlVector::InsertMultipleBefore( int elem, int num, const T *pToInsert ) +{ + if( num == 0 ) + return elem; + + // Can insert at the end + assert( (elem == Count()) || IsValidIndex(elem) ); + + GrowVector(num); + ShiftElementsRight(elem, num); + + // Invoke default constructors + for (int i = 0; i < num; ++i) + Construct( &Element(elem+i) ); + + // Copy stuff in? + if ( pToInsert ) + { + for ( int i=0; i < num; i++ ) + { + Element( elem+i ) = pToInsert[i]; + } + } + + return elem; +} + +//----------------------------------------------------------------------------- +// Finds an element (element needs operator== defined) +//----------------------------------------------------------------------------- +template< class T > +int CUtlVector::Find( T const& src ) const +{ + for ( int i = 0; i < Count(); ++i ) + { + if (Element(i) == src) + return i; + } + return -1; +} + +template< class T > +bool CUtlVector::HasElement( T const& src ) +{ + return ( Find(src) >= 0 ); +} + +//----------------------------------------------------------------------------- +// Element removal +//----------------------------------------------------------------------------- + +template< class T > +void CUtlVector::FastRemove( int elem ) +{ + assert( IsValidIndex(elem) ); + + Destruct( &Element(elem) ); + if (m_Size > 0) + { + memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) ); + --m_Size; + } +} + +template< class T > +void CUtlVector::Remove( int elem ) +{ + Destruct( &Element(elem) ); + ShiftElementsLeft(elem); + --m_Size; +} + +template< class T > +void CUtlVector::FindAndRemove( T const& src ) +{ + int elem = Find( src ); + if ( elem != -1 ) + { + Remove( elem ); + } +} + +template< class T > +void CUtlVector::RemoveMultiple( int elem, int num ) +{ + assert( IsValidIndex(elem) ); + assert( elem + num <= Count() ); + + for (int i = elem + num; --i >= elem; ) + Destruct(&Element(i)); + + ShiftElementsLeft(elem, num); + m_Size -= num; +} + +template< class T > +void CUtlVector::RemoveAll() +{ + for (int i = m_Size; --i >= 0; ) + Destruct(&Element(i)); + + m_Size = 0; +} + + +//----------------------------------------------------------------------------- +// Memory deallocation +//----------------------------------------------------------------------------- + +template< class T > +void CUtlVector::Purge() +{ + RemoveAll(); + m_Memory.Purge( ); + ResetDbgInfo(); +} + + +template +inline void CUtlVector::PurgeAndDeleteElements() +{ + for( int i=0; i < m_Size; i++ ) + delete Element(i); + + Purge(); +} + + +template< class T > +void CUtlVector::SetGrowSize( int size ) +{ + m_Memory.SetGrowSize( size ); +} + + +#endif // CCVECTOR_H diff --git a/utils/common/bspfile.c b/utils/common/bspfile.c index c118701..688f10d 100644 --- a/utils/common/bspfile.c +++ b/utils/common/bspfile.c @@ -1,709 +1,709 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "scriplib.h" - -//============================================================================= - -int nummodels; -dmodel_t dmodels[MAX_MAP_MODELS]; -int dmodels_checksum; - -int visdatasize; -byte dvisdata[MAX_MAP_VISIBILITY]; -int dvisdata_checksum; - -int lightdatasize; -byte dlightdata[MAX_MAP_LIGHTING]; -int dlightdata_checksum; - -int texdatasize; -byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) -int dtexdata_checksum; - -int entdatasize; -char dentdata[MAX_MAP_ENTSTRING]; -int dentdata_checksum; - -int numleafs; -dleaf_t dleafs[MAX_MAP_LEAFS]; -int dleafs_checksum; - -int numplanes; -dplane_t dplanes[MAX_MAP_PLANES]; -int dplanes_checksum; - -int numvertexes; -dvertex_t dvertexes[MAX_MAP_VERTS]; -int dvertexes_checksum; - -int numnodes; -dnode_t dnodes[MAX_MAP_NODES]; -int dnodes_checksum; - -int numtexinfo; -texinfo_t texinfo[MAX_MAP_TEXINFO]; -int texinfo_checksum; - -int numfaces; -dface_t dfaces[MAX_MAP_FACES]; -int dfaces_checksum; - -int numclipnodes; -dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; -int dclipnodes_checksum; - -int numedges; -dedge_t dedges[MAX_MAP_EDGES]; -int dedges_checksum; - -int nummarksurfaces; -unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; -int dmarksurfaces_checksum; - -int numsurfedges; -int dsurfedges[MAX_MAP_SURFEDGES]; -int dsurfedges_checksum; - -int num_entities; -entity_t entities[MAX_MAP_ENTITIES]; - -/* -=============== -FastChecksum -=============== -*/ - -int FastChecksum(void *buffer, int bytes) -{ - int checksum = 0; - - while( bytes-- ) - checksum = _rotl(checksum, 4) ^ *((char *)buffer)++; - - return checksum; -} - -/* -=============== -CompressVis -=============== -*/ -int CompressVis (byte *vis, byte *dest) -{ - int j; - int rep; - int visrow; - byte *dest_p; - - dest_p = dest; - visrow = (numleafs + 7)>>3; - - for (j=0 ; j>3; - out = decompressed; - - do - { - if (*in) - { - *out++ = *in++; - continue; - } - - c = in[1]; - in += 2; - while (c) - { - *out++ = 0; - c--; - } - } while (out - decompressed < row); -} - -//============================================================================= - -/* -============= -SwapBSPFile - -Byte swaps all data in a bsp file. -============= -*/ -void SwapBSPFile (qboolean todisk) -{ - int i, j, c; - dmodel_t *d; - dmiptexlump_t *mtl; - - -// models - for (i=0 ; iheadnode[j] = LittleLong (d->headnode[j]); - - d->visleafs = LittleLong (d->visleafs); - d->firstface = LittleLong (d->firstface); - d->numfaces = LittleLong (d->numfaces); - - for (j=0 ; j<3 ; j++) - { - d->mins[j] = LittleFloat(d->mins[j]); - d->maxs[j] = LittleFloat(d->maxs[j]); - d->origin[j] = LittleFloat(d->origin[j]); - } - } - -// -// vertexes -// - for (i=0 ; inummiptex; - else - c = LittleLong(mtl->nummiptex); - mtl->nummiptex = LittleLong (mtl->nummiptex); - for (i=0 ; idataofs[i] = LittleLong(mtl->dataofs[i]); - } - -// -// marksurfaces -// - for (i=0 ; ilumps[lump].filelen; - ofs = header->lumps[lump].fileofs; - - if (length % size) - Error ("LoadBSPFile: odd lump size"); - - memcpy (dest, (byte *)header + ofs, length); - - return length / size; -} - -/* -============= -LoadBSPFile -============= -*/ -void LoadBSPFile (char *filename) -{ - int i; - -// -// load the file header -// - LoadFile (filename, (void **)&header); - -// swap the header - for (i=0 ; i< sizeof(dheader_t)/4 ; i++) - ((int *)header)[i] = LittleLong ( ((int *)header)[i]); - - if (header->version != BSPVERSION) - Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); - - nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t)); - numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t)); - numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t)); - numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t)); - numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t)); - numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t)); - numclipnodes = CopyLump (LUMP_CLIPNODES, dclipnodes, sizeof(dclipnode_t)); - numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t)); - nummarksurfaces = CopyLump (LUMP_MARKSURFACES, dmarksurfaces, sizeof(dmarksurfaces[0])); - numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0])); - numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t)); - - texdatasize = CopyLump (LUMP_TEXTURES, dtexdata, 1); - visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1); - lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1); - entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1); - - free (header); // everything has been copied out - -// -// swap everything -// - SwapBSPFile (false); - - dmodels_checksum = FastChecksum( dmodels, nummodels*sizeof(dmodels[0]) ); - dvertexes_checksum = FastChecksum( dvertexes, numvertexes*sizeof(dvertexes[0]) ); - dplanes_checksum = FastChecksum( dplanes, numplanes*sizeof(dplanes[0]) ); - dleafs_checksum = FastChecksum( dleafs, numleafs*sizeof(dleafs[0]) ); - dnodes_checksum = FastChecksum( dnodes, numnodes*sizeof(dnodes[0]) ); - texinfo_checksum = FastChecksum( texinfo, numtexinfo*sizeof(texinfo[0]) ); - dclipnodes_checksum = FastChecksum( dclipnodes, numclipnodes*sizeof(dclipnodes[0]) ); - dfaces_checksum = FastChecksum( dfaces, numfaces*sizeof(dfaces[0]) ); - dmarksurfaces_checksum = FastChecksum( dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0]) ); - dsurfedges_checksum = FastChecksum( dsurfedges, numsurfedges*sizeof(dsurfedges[0]) ); - dedges_checksum = FastChecksum( dedges, numedges*sizeof(dedges[0]) ); - dtexdata_checksum = FastChecksum( dtexdata, numedges*sizeof(dtexdata[0]) ); - dvisdata_checksum = FastChecksum( dvisdata, visdatasize*sizeof(dvisdata[0]) ); - dlightdata_checksum = FastChecksum( dlightdata, lightdatasize*sizeof(dlightdata[0]) ); - dentdata_checksum = FastChecksum( dentdata, entdatasize*sizeof(dentdata[0]) ); - -} - -//============================================================================ - -FILE *wadfile; -dheader_t outheader; - -void AddLump (int lumpnum, void *data, int len) -{ - lump_t *lump; - - lump = &header->lumps[lumpnum]; - - lump->fileofs = LittleLong( ftell(wadfile) ); - lump->filelen = LittleLong(len); - SafeWrite (wadfile, data, (len+3)&~3); -} - -/* -============= -WriteBSPFile - -Swaps the bsp file in place, so it should not be referenced again -============= -*/ -void WriteBSPFile (char *filename) -{ - header = &outheader; - memset (header, 0, sizeof(dheader_t)); - - SwapBSPFile (true); - - header->version = LittleLong (BSPVERSION); - - wadfile = SafeOpenWrite (filename); - SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later - - AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t)); - AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t)); - AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t)); - AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t)); - AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t)); - AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t)); - AddLump (LUMP_CLIPNODES, dclipnodes, numclipnodes*sizeof(dclipnode_t)); - AddLump (LUMP_MARKSURFACES, dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0])); - AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0])); - AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t)); - AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t)); - - AddLump (LUMP_LIGHTING, dlightdata, lightdatasize); - AddLump (LUMP_VISIBILITY, dvisdata, visdatasize); - AddLump (LUMP_ENTITIES, dentdata, entdatasize); - AddLump (LUMP_TEXTURES, dtexdata, texdatasize); - - fseek (wadfile, 0, SEEK_SET); - SafeWrite (wadfile, header, sizeof(dheader_t)); - fclose (wadfile); -} - -//============================================================================ - -#define ENTRIES(a) (sizeof(a)/sizeof(*(a))) -#define ENTRYSIZE(a) (sizeof(*(a))) - -ArrayUsage( char *szItem, int items, int maxitems, int itemsize ) -{ - float percentage = maxitems ? items * 100.0 / maxitems : 0.0; - - printf("%-12s %7i/%-7i %7i/%-7i (%4.1f%%)", - szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage ); - if ( percentage > 80.0 ) - printf( "VERY FULL!\n" ); - else if ( percentage > 95.0 ) - printf( "SIZE DANGER!\n" ); - else if ( percentage > 99.9 ) - printf( "SIZE OVERFLOW!!!\n" ); - else - printf( "\n" ); - return items * itemsize; -} - -GlobUsage( char *szItem, int itemstorage, int maxstorage ) -{ - float percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0; - printf("%-12s [variable] %7i/%-7i (%4.1f%%)", - szItem, itemstorage, maxstorage, percentage ); - if ( percentage > 80.0 ) - printf( "VERY FULL!\n" ); - else if ( percentage > 95.0 ) - printf( "SIZE DANGER!\n" ); - else if ( percentage > 99.9 ) - printf( "SIZE OVERFLOW!!!\n" ); - else - printf( "\n" ); - return itemstorage; -} - -/* -============= -PrintBSPFileSizes - -Dumps info about current file -============= -*/ -void PrintBSPFileSizes (void) -{ - int numtextures = texdatasize ? ((dmiptexlump_t*)dtexdata)->nummiptex : 0; - int totalmemory = 0; - - printf("\n"); - printf("Object names Objects/Maxobjs Memory / Maxmem Fullness\n" ); - printf("------------ --------------- --------------- --------\n" ); - - totalmemory += ArrayUsage( "models", nummodels, ENTRIES(dmodels), ENTRYSIZE(dmodels) ); - totalmemory += ArrayUsage( "planes", numplanes, ENTRIES(dplanes), ENTRYSIZE(dplanes) ); - totalmemory += ArrayUsage( "vertexes", numvertexes, ENTRIES(dvertexes), ENTRYSIZE(dvertexes) ); - totalmemory += ArrayUsage( "nodes", numnodes, ENTRIES(dnodes), ENTRYSIZE(dnodes) ); - totalmemory += ArrayUsage( "texinfos", numtexinfo, ENTRIES(texinfo), ENTRYSIZE(texinfo) ); - totalmemory += ArrayUsage( "faces", numfaces, ENTRIES(dfaces), ENTRYSIZE(dfaces) ); - totalmemory += ArrayUsage( "clipnodes", numclipnodes, ENTRIES(dclipnodes), ENTRYSIZE(dclipnodes) ); - totalmemory += ArrayUsage( "leaves", numleafs, ENTRIES(dleafs), ENTRYSIZE(dleafs) ); - totalmemory += ArrayUsage( "marksurfaces", nummarksurfaces,ENTRIES(dmarksurfaces), ENTRYSIZE(dmarksurfaces) ); - totalmemory += ArrayUsage( "surfedges", numsurfedges, ENTRIES(dsurfedges), ENTRYSIZE(dsurfedges) ); - totalmemory += ArrayUsage( "edges", numedges, ENTRIES(dedges), ENTRYSIZE(dedges) ); - - totalmemory += GlobUsage( "texdata", texdatasize, sizeof(dtexdata) ); - totalmemory += GlobUsage( "lightdata", lightdatasize, sizeof(dlightdata) ); - totalmemory += GlobUsage( "visdata", visdatasize, sizeof(dvisdata) ); - totalmemory += GlobUsage( "entdata", entdatasize, sizeof(dentdata) ); - - printf( "=== Total BSP file data space used: %d bytes ===\n", totalmemory ); -} - - -/* -================= -ParseEpair -================= -*/ -epair_t *ParseEpair (void) -{ - epair_t *e; - - e = malloc (sizeof(epair_t)); - memset (e, 0, sizeof(epair_t)); - - if (strlen(token) >= MAX_KEY-1) - Error ("ParseEpar: token too long"); - e->key = copystring(token); - GetToken (false); - if (strlen(token) >= MAX_VALUE-1) - Error ("ParseEpar: token too long"); - e->value = copystring(token); - - return e; -} - - -/* -================ -ParseEntity -================ -*/ -qboolean ParseEntity (void) -{ - epair_t *e; - entity_t *mapent; - - if (!GetToken (true)) - return false; - - if (strcmp (token, "{") ) - Error ("ParseEntity: { not found"); - - if (num_entities == MAX_MAP_ENTITIES) - Error ("num_entities == MAX_MAP_ENTITIES"); - - mapent = &entities[num_entities]; - num_entities++; - - do - { - if (!GetToken (true)) - Error ("ParseEntity: EOF without closing brace"); - if (!strcmp (token, "}") ) - break; - e = ParseEpair (); - e->next = mapent->epairs; - mapent->epairs = e; - } while (1); - - return true; -} - -/* -================ -ParseEntities - -Parses the dentdata string into entities -================ -*/ -void ParseEntities (void) -{ - num_entities = 0; - ParseFromMemory (dentdata, entdatasize); - - while (ParseEntity ()) - { - } -} - - -/* -================ -UnparseEntities - -Generates the dentdata string from all the entities -================ -*/ -void UnparseEntities (void) -{ - char *buf, *end; - epair_t *ep; - char line[2048]; - int i; - - buf = dentdata; - end = buf; - *end = 0; - - for (i=0 ; inext) - { - sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value); - strcat (end, line); - end += strlen(line); - } - strcat (end,"}\n"); - end += 2; - - if (end > buf + MAX_MAP_ENTSTRING) - Error ("Entity text too long"); - } - entdatasize = end - buf + 1; -} - - - -void SetKeyValue (entity_t *ent, char *key, char *value) -{ - epair_t *ep; - - for (ep=ent->epairs ; ep ; ep=ep->next) - if (!strcmp (ep->key, key) ) - { - free (ep->value); - ep->value = copystring(value); - return; - } - ep = malloc (sizeof(*ep)); - ep->next = ent->epairs; - ent->epairs = ep; - ep->key = copystring(key); - ep->value = copystring(value); -} - -char *ValueForKey (entity_t *ent, char *key) -{ - epair_t *ep; - - for (ep=ent->epairs ; ep ; ep=ep->next) - if (!strcmp (ep->key, key) ) - return ep->value; - return ""; -} - -vec_t FloatForKey (entity_t *ent, char *key) -{ - char *k; - - k = ValueForKey (ent, key); - return atof(k); -} - -void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) -{ - char *k; - double v1, v2, v3; - - k = ValueForKey (ent, key); -// scanf into doubles, then assign, so it is vec_t size independent - v1 = v2 = v3 = 0; - sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); - vec[0] = v1; - vec[1] = v2; - vec[2] = v3; -} - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +#include "cmdlib.h" +#include "mathlib.h" +#include "bspfile.h" +#include "scriplib.h" + +//============================================================================= + +int nummodels; +dmodel_t dmodels[MAX_MAP_MODELS]; +int dmodels_checksum; + +int visdatasize; +byte dvisdata[MAX_MAP_VISIBILITY]; +int dvisdata_checksum; + +int lightdatasize; +byte dlightdata[MAX_MAP_LIGHTING]; +int dlightdata_checksum; + +int texdatasize; +byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) +int dtexdata_checksum; + +int entdatasize; +char dentdata[MAX_MAP_ENTSTRING]; +int dentdata_checksum; + +int numleafs; +dleaf_t dleafs[MAX_MAP_LEAFS]; +int dleafs_checksum; + +int numplanes; +dplane_t dplanes[MAX_MAP_PLANES]; +int dplanes_checksum; + +int numvertexes; +dvertex_t dvertexes[MAX_MAP_VERTS]; +int dvertexes_checksum; + +int numnodes; +dnode_t dnodes[MAX_MAP_NODES]; +int dnodes_checksum; + +int numtexinfo; +texinfo_t texinfo[MAX_MAP_TEXINFO]; +int texinfo_checksum; + +int numfaces; +dface_t dfaces[MAX_MAP_FACES]; +int dfaces_checksum; + +int numclipnodes; +dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; +int dclipnodes_checksum; + +int numedges; +dedge_t dedges[MAX_MAP_EDGES]; +int dedges_checksum; + +int nummarksurfaces; +unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; +int dmarksurfaces_checksum; + +int numsurfedges; +int dsurfedges[MAX_MAP_SURFEDGES]; +int dsurfedges_checksum; + +int num_entities; +entity_t entities[MAX_MAP_ENTITIES]; + +/* +=============== +FastChecksum +=============== +*/ + +int FastChecksum(void *buffer, int bytes) +{ + int checksum = 0; + + while( bytes-- ) + checksum = _rotl(checksum, 4) ^ *((char *)buffer)++; + + return checksum; +} + +/* +=============== +CompressVis +=============== +*/ +int CompressVis (byte *vis, byte *dest) +{ + int j; + int rep; + int visrow; + byte *dest_p; + + dest_p = dest; + visrow = (numleafs + 7)>>3; + + for (j=0 ; j>3; + out = decompressed; + + do + { + if (*in) + { + *out++ = *in++; + continue; + } + + c = in[1]; + in += 2; + while (c) + { + *out++ = 0; + c--; + } + } while (out - decompressed < row); +} + +//============================================================================= + +/* +============= +SwapBSPFile + +Byte swaps all data in a bsp file. +============= +*/ +void SwapBSPFile (qboolean todisk) +{ + int i, j, c; + dmodel_t *d; + dmiptexlump_t *mtl; + + +// models + for (i=0 ; iheadnode[j] = LittleLong (d->headnode[j]); + + d->visleafs = LittleLong (d->visleafs); + d->firstface = LittleLong (d->firstface); + d->numfaces = LittleLong (d->numfaces); + + for (j=0 ; j<3 ; j++) + { + d->mins[j] = LittleFloat(d->mins[j]); + d->maxs[j] = LittleFloat(d->maxs[j]); + d->origin[j] = LittleFloat(d->origin[j]); + } + } + +// +// vertexes +// + for (i=0 ; inummiptex; + else + c = LittleLong(mtl->nummiptex); + mtl->nummiptex = LittleLong (mtl->nummiptex); + for (i=0 ; idataofs[i] = LittleLong(mtl->dataofs[i]); + } + +// +// marksurfaces +// + for (i=0 ; ilumps[lump].filelen; + ofs = header->lumps[lump].fileofs; + + if (length % size) + Error ("LoadBSPFile: odd lump size"); + + memcpy (dest, (byte *)header + ofs, length); + + return length / size; +} + +/* +============= +LoadBSPFile +============= +*/ +void LoadBSPFile (char *filename) +{ + int i; + +// +// load the file header +// + LoadFile (filename, (void **)&header); + +// swap the header + for (i=0 ; i< sizeof(dheader_t)/4 ; i++) + ((int *)header)[i] = LittleLong ( ((int *)header)[i]); + + if (header->version != BSPVERSION) + Error ("%s is version %i, not %i", filename, header->version, BSPVERSION); + + nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t)); + numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t)); + numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t)); + numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t)); + numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t)); + numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t)); + numclipnodes = CopyLump (LUMP_CLIPNODES, dclipnodes, sizeof(dclipnode_t)); + numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t)); + nummarksurfaces = CopyLump (LUMP_MARKSURFACES, dmarksurfaces, sizeof(dmarksurfaces[0])); + numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0])); + numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t)); + + texdatasize = CopyLump (LUMP_TEXTURES, dtexdata, 1); + visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1); + lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1); + entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1); + + free (header); // everything has been copied out + +// +// swap everything +// + SwapBSPFile (false); + + dmodels_checksum = FastChecksum( dmodels, nummodels*sizeof(dmodels[0]) ); + dvertexes_checksum = FastChecksum( dvertexes, numvertexes*sizeof(dvertexes[0]) ); + dplanes_checksum = FastChecksum( dplanes, numplanes*sizeof(dplanes[0]) ); + dleafs_checksum = FastChecksum( dleafs, numleafs*sizeof(dleafs[0]) ); + dnodes_checksum = FastChecksum( dnodes, numnodes*sizeof(dnodes[0]) ); + texinfo_checksum = FastChecksum( texinfo, numtexinfo*sizeof(texinfo[0]) ); + dclipnodes_checksum = FastChecksum( dclipnodes, numclipnodes*sizeof(dclipnodes[0]) ); + dfaces_checksum = FastChecksum( dfaces, numfaces*sizeof(dfaces[0]) ); + dmarksurfaces_checksum = FastChecksum( dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0]) ); + dsurfedges_checksum = FastChecksum( dsurfedges, numsurfedges*sizeof(dsurfedges[0]) ); + dedges_checksum = FastChecksum( dedges, numedges*sizeof(dedges[0]) ); + dtexdata_checksum = FastChecksum( dtexdata, numedges*sizeof(dtexdata[0]) ); + dvisdata_checksum = FastChecksum( dvisdata, visdatasize*sizeof(dvisdata[0]) ); + dlightdata_checksum = FastChecksum( dlightdata, lightdatasize*sizeof(dlightdata[0]) ); + dentdata_checksum = FastChecksum( dentdata, entdatasize*sizeof(dentdata[0]) ); + +} + +//============================================================================ + +FILE *wadfile; +dheader_t outheader; + +void AddLump (int lumpnum, void *data, int len) +{ + lump_t *lump; + + lump = &header->lumps[lumpnum]; + + lump->fileofs = LittleLong( ftell(wadfile) ); + lump->filelen = LittleLong(len); + SafeWrite (wadfile, data, (len+3)&~3); +} + +/* +============= +WriteBSPFile + +Swaps the bsp file in place, so it should not be referenced again +============= +*/ +void WriteBSPFile (char *filename) +{ + header = &outheader; + memset (header, 0, sizeof(dheader_t)); + + SwapBSPFile (true); + + header->version = LittleLong (BSPVERSION); + + wadfile = SafeOpenWrite (filename); + SafeWrite (wadfile, header, sizeof(dheader_t)); // overwritten later + + AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t)); + AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t)); + AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t)); + AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t)); + AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t)); + AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t)); + AddLump (LUMP_CLIPNODES, dclipnodes, numclipnodes*sizeof(dclipnode_t)); + AddLump (LUMP_MARKSURFACES, dmarksurfaces, nummarksurfaces*sizeof(dmarksurfaces[0])); + AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0])); + AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t)); + AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t)); + + AddLump (LUMP_LIGHTING, dlightdata, lightdatasize); + AddLump (LUMP_VISIBILITY, dvisdata, visdatasize); + AddLump (LUMP_ENTITIES, dentdata, entdatasize); + AddLump (LUMP_TEXTURES, dtexdata, texdatasize); + + fseek (wadfile, 0, SEEK_SET); + SafeWrite (wadfile, header, sizeof(dheader_t)); + fclose (wadfile); +} + +//============================================================================ + +#define ENTRIES(a) (sizeof(a)/sizeof(*(a))) +#define ENTRYSIZE(a) (sizeof(*(a))) + +ArrayUsage( char *szItem, int items, int maxitems, int itemsize ) +{ + float percentage = maxitems ? items * 100.0 / maxitems : 0.0; + + printf("%-12s %7i/%-7i %7i/%-7i (%4.1f%%)", + szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage ); + if ( percentage > 80.0 ) + printf( "VERY FULL!\n" ); + else if ( percentage > 95.0 ) + printf( "SIZE DANGER!\n" ); + else if ( percentage > 99.9 ) + printf( "SIZE OVERFLOW!!!\n" ); + else + printf( "\n" ); + return items * itemsize; +} + +GlobUsage( char *szItem, int itemstorage, int maxstorage ) +{ + float percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0; + printf("%-12s [variable] %7i/%-7i (%4.1f%%)", + szItem, itemstorage, maxstorage, percentage ); + if ( percentage > 80.0 ) + printf( "VERY FULL!\n" ); + else if ( percentage > 95.0 ) + printf( "SIZE DANGER!\n" ); + else if ( percentage > 99.9 ) + printf( "SIZE OVERFLOW!!!\n" ); + else + printf( "\n" ); + return itemstorage; +} + +/* +============= +PrintBSPFileSizes + +Dumps info about current file +============= +*/ +void PrintBSPFileSizes (void) +{ + int numtextures = texdatasize ? ((dmiptexlump_t*)dtexdata)->nummiptex : 0; + int totalmemory = 0; + + printf("\n"); + printf("Object names Objects/Maxobjs Memory / Maxmem Fullness\n" ); + printf("------------ --------------- --------------- --------\n" ); + + totalmemory += ArrayUsage( "models", nummodels, ENTRIES(dmodels), ENTRYSIZE(dmodels) ); + totalmemory += ArrayUsage( "planes", numplanes, ENTRIES(dplanes), ENTRYSIZE(dplanes) ); + totalmemory += ArrayUsage( "vertexes", numvertexes, ENTRIES(dvertexes), ENTRYSIZE(dvertexes) ); + totalmemory += ArrayUsage( "nodes", numnodes, ENTRIES(dnodes), ENTRYSIZE(dnodes) ); + totalmemory += ArrayUsage( "texinfos", numtexinfo, ENTRIES(texinfo), ENTRYSIZE(texinfo) ); + totalmemory += ArrayUsage( "faces", numfaces, ENTRIES(dfaces), ENTRYSIZE(dfaces) ); + totalmemory += ArrayUsage( "clipnodes", numclipnodes, ENTRIES(dclipnodes), ENTRYSIZE(dclipnodes) ); + totalmemory += ArrayUsage( "leaves", numleafs, ENTRIES(dleafs), ENTRYSIZE(dleafs) ); + totalmemory += ArrayUsage( "marksurfaces", nummarksurfaces,ENTRIES(dmarksurfaces), ENTRYSIZE(dmarksurfaces) ); + totalmemory += ArrayUsage( "surfedges", numsurfedges, ENTRIES(dsurfedges), ENTRYSIZE(dsurfedges) ); + totalmemory += ArrayUsage( "edges", numedges, ENTRIES(dedges), ENTRYSIZE(dedges) ); + + totalmemory += GlobUsage( "texdata", texdatasize, sizeof(dtexdata) ); + totalmemory += GlobUsage( "lightdata", lightdatasize, sizeof(dlightdata) ); + totalmemory += GlobUsage( "visdata", visdatasize, sizeof(dvisdata) ); + totalmemory += GlobUsage( "entdata", entdatasize, sizeof(dentdata) ); + + printf( "=== Total BSP file data space used: %d bytes ===\n", totalmemory ); +} + + +/* +================= +ParseEpair +================= +*/ +epair_t *ParseEpair (void) +{ + epair_t *e; + + e = malloc (sizeof(epair_t)); + memset (e, 0, sizeof(epair_t)); + + if (strlen(token) >= MAX_KEY-1) + Error ("ParseEpar: token too long"); + e->key = copystring(token); + GetToken (false); + if (strlen(token) >= MAX_VALUE-1) + Error ("ParseEpar: token too long"); + e->value = copystring(token); + + return e; +} + + +/* +================ +ParseEntity +================ +*/ +qboolean ParseEntity (void) +{ + epair_t *e; + entity_t *mapent; + + if (!GetToken (true)) + return false; + + if (strcmp (token, "{") ) + Error ("ParseEntity: { not found"); + + if (num_entities == MAX_MAP_ENTITIES) + Error ("num_entities == MAX_MAP_ENTITIES"); + + mapent = &entities[num_entities]; + num_entities++; + + do + { + if (!GetToken (true)) + Error ("ParseEntity: EOF without closing brace"); + if (!strcmp (token, "}") ) + break; + e = ParseEpair (); + e->next = mapent->epairs; + mapent->epairs = e; + } while (1); + + return true; +} + +/* +================ +ParseEntities + +Parses the dentdata string into entities +================ +*/ +void ParseEntities (void) +{ + num_entities = 0; + ParseFromMemory (dentdata, entdatasize); + + while (ParseEntity ()) + { + } +} + + +/* +================ +UnparseEntities + +Generates the dentdata string from all the entities +================ +*/ +void UnparseEntities (void) +{ + char *buf, *end; + epair_t *ep; + char line[2048]; + int i; + + buf = dentdata; + end = buf; + *end = 0; + + for (i=0 ; inext) + { + sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value); + strcat (end, line); + end += strlen(line); + } + strcat (end,"}\n"); + end += 2; + + if (end > buf + MAX_MAP_ENTSTRING) + Error ("Entity text too long"); + } + entdatasize = end - buf + 1; +} + + + +void SetKeyValue (entity_t *ent, char *key, char *value) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + { + free (ep->value); + ep->value = copystring(value); + return; + } + ep = malloc (sizeof(*ep)); + ep->next = ent->epairs; + ent->epairs = ep; + ep->key = copystring(key); + ep->value = copystring(value); +} + +char *ValueForKey (entity_t *ent, char *key) +{ + epair_t *ep; + + for (ep=ent->epairs ; ep ; ep=ep->next) + if (!strcmp (ep->key, key) ) + return ep->value; + return ""; +} + +vec_t FloatForKey (entity_t *ent, char *key) +{ + char *k; + + k = ValueForKey (ent, key); + return atof(k); +} + +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec) +{ + char *k; + double v1, v2, v3; + + k = ValueForKey (ent, key); +// scanf into doubles, then assign, so it is vec_t size independent + v1 = v2 = v3 = 0; + sscanf (k, "%lf %lf %lf", &v1, &v2, &v3); + vec[0] = v1; + vec[1] = v2; + vec[2] = v3; +} + diff --git a/utils/common/bspfile.h b/utils/common/bspfile.h index 96dd94b..1804d77 100644 --- a/utils/common/bspfile.h +++ b/utils/common/bspfile.h @@ -1,332 +1,332 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - - -// upper design bounds - -#define MAX_MAP_HULLS 4 - -#define MAX_MAP_MODELS 400 -#define MAX_MAP_BRUSHES 4096 -#define MAX_MAP_ENTITIES 1024 -#define MAX_MAP_ENTSTRING (128*1024) - -#define MAX_MAP_PLANES 32767 -#define MAX_MAP_NODES 32767 // because negative shorts are contents -#define MAX_MAP_CLIPNODES 32767 // -#define MAX_MAP_LEAFS 8192 -#define MAX_MAP_VERTS 65535 -#define MAX_MAP_FACES 65535 -#define MAX_MAP_MARKSURFACES 65535 -#define MAX_MAP_TEXINFO 8192 -#define MAX_MAP_EDGES 256000 -#define MAX_MAP_SURFEDGES 512000 -#define MAX_MAP_TEXTURES 512 -#define MAX_MAP_MIPTEX 0x200000 -#define MAX_MAP_LIGHTING 0x200000 -#define MAX_MAP_VISIBILITY 0x200000 - -#define MAX_MAP_PORTALS 65536 - -// key / value pair sizes - -#define MAX_KEY 32 -#define MAX_VALUE 1024 - -//============================================================================= - - -#define BSPVERSION 30 -#define TOOLVERSION 2 - - -typedef struct -{ - int fileofs, filelen; -} lump_t; - -#define LUMP_ENTITIES 0 -#define LUMP_PLANES 1 -#define LUMP_TEXTURES 2 -#define LUMP_VERTEXES 3 -#define LUMP_VISIBILITY 4 -#define LUMP_NODES 5 -#define LUMP_TEXINFO 6 -#define LUMP_FACES 7 -#define LUMP_LIGHTING 8 -#define LUMP_CLIPNODES 9 -#define LUMP_LEAFS 10 -#define LUMP_MARKSURFACES 11 -#define LUMP_EDGES 12 -#define LUMP_SURFEDGES 13 -#define LUMP_MODELS 14 - -#define HEADER_LUMPS 15 - -typedef struct -{ - float mins[3], maxs[3]; - float origin[3]; - int headnode[MAX_MAP_HULLS]; - int visleafs; // not including the solid leaf 0 - int firstface, numfaces; -} dmodel_t; - -typedef struct -{ - int version; - lump_t lumps[HEADER_LUMPS]; -} dheader_t; - -typedef struct -{ - int nummiptex; - int dataofs[4]; // [nummiptex] -} dmiptexlump_t; - -#define MIPLEVELS 4 -typedef struct miptex_s -{ - char name[16]; - unsigned width, height; - unsigned offsets[MIPLEVELS]; // four mip maps stored -} miptex_t; - - -typedef struct -{ - float point[3]; -} dvertex_t; - - -// 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 - -// 3-5 are non-axial planes snapped to the nearest -#define PLANE_ANYX 3 -#define PLANE_ANYY 4 -#define PLANE_ANYZ 5 - -typedef struct -{ - float normal[3]; - float dist; - int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate -} dplane_t; - - - -#define CONTENTS_EMPTY -1 -#define CONTENTS_SOLID -2 -#define CONTENTS_WATER -3 -#define CONTENTS_SLIME -4 -#define CONTENTS_LAVA -5 -#define CONTENTS_SKY -6 -#define CONTENTS_ORIGIN -7 // removed at csg time -#define CONTENTS_CLIP -8 // changed to contents_solid - -#define CONTENTS_CURRENT_0 -9 -#define CONTENTS_CURRENT_90 -10 -#define CONTENTS_CURRENT_180 -11 -#define CONTENTS_CURRENT_270 -12 -#define CONTENTS_CURRENT_UP -13 -#define CONTENTS_CURRENT_DOWN -14 - -#define CONTENTS_TRANSLUCENT -15 - -// !!! if this is changed, it must be changed in asm_i386.h too !!! -typedef struct -{ - int planenum; - short children[2]; // negative numbers are -(leafs+1), not nodes - short mins[3]; // for sphere culling - short maxs[3]; - unsigned short firstface; - unsigned short numfaces; // counting both sides -} dnode_t; - -typedef struct -{ - int planenum; - short children[2]; // negative numbers are contents -} dclipnode_t; - - -typedef struct texinfo_s -{ - float vecs[2][4]; // [s/t][xyz offset] - int miptex; - int flags; -} texinfo_t; -#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision - -// note that edge 0 is never used, because negative edge nums are used for -// counterclockwise use of the edge in a face -typedef struct -{ - unsigned short v[2]; // vertex numbers -} dedge_t; - -#define MAXLIGHTMAPS 4 -typedef struct -{ - short planenum; - short side; - - int firstedge; // we must support > 64k edges - short numedges; - short texinfo; - -// lighting info - byte styles[MAXLIGHTMAPS]; - int lightofs; // start of [numstyles*surfsize] samples -} dface_t; - - - -#define AMBIENT_WATER 0 -#define AMBIENT_SKY 1 -#define AMBIENT_SLIME 2 -#define AMBIENT_LAVA 3 - -#define NUM_AMBIENTS 4 // automatic ambient sounds - -// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas -// all other leafs need visibility info -typedef struct -{ - int contents; - int visofs; // -1 = no visibility info - - short mins[3]; // for frustum culling - short maxs[3]; - - unsigned short firstmarksurface; - unsigned short nummarksurfaces; - - byte ambient_level[NUM_AMBIENTS]; -} dleaf_t; - - -//============================================================================ - -#ifndef QUAKE_GAME - -#define ANGLE_UP -1 -#define ANGLE_DOWN -2 - - -// the utilities get to be lazy and just use large static arrays - -extern int nummodels; -extern dmodel_t dmodels[MAX_MAP_MODELS]; -extern int dmodels_checksum; - -extern int visdatasize; -extern byte dvisdata[MAX_MAP_VISIBILITY]; -extern int dvisdata_checksum; - -extern int lightdatasize; -extern byte dlightdata[MAX_MAP_LIGHTING]; -extern int dlightdata_checksum; - -extern int texdatasize; -extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) -extern int dtexdata_checksum; - -extern int entdatasize; -extern char dentdata[MAX_MAP_ENTSTRING]; -extern int dentdata_checksum; - -extern int numleafs; -extern dleaf_t dleafs[MAX_MAP_LEAFS]; -extern int dleafs_checksum; - -extern int numplanes; -extern dplane_t dplanes[MAX_MAP_PLANES]; -extern int dplanes_checksum; - -extern int numvertexes; -extern dvertex_t dvertexes[MAX_MAP_VERTS]; -extern int dvertexes_checksum; - -extern int numnodes; -extern dnode_t dnodes[MAX_MAP_NODES]; -extern int dnodes_checksum; - -extern int numtexinfo; -extern texinfo_t texinfo[MAX_MAP_TEXINFO]; -extern int texinfo_checksum; - -extern int numfaces; -extern dface_t dfaces[MAX_MAP_FACES]; -extern int dfaces_checksum; - -extern int numclipnodes; -extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; -extern int dclipnodes_checksum; - -extern int numedges; -extern dedge_t dedges[MAX_MAP_EDGES]; -extern int dedges_checksum; - -extern int nummarksurfaces; -extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; -extern int dmarksurfaces_checksum; - -extern int numsurfedges; -extern int dsurfedges[MAX_MAP_SURFEDGES]; -extern int dsurfedges_checksum; - -int FastChecksum(void *buffer, int bytes); - -void DecompressVis (byte *in, byte *decompressed); -int CompressVis (byte *vis, byte *dest); - -void LoadBSPFile (char *filename); -void WriteBSPFile (char *filename); -void PrintBSPFileSizes (void); - -//=============== - - -typedef struct epair_s -{ - struct epair_s *next; - char *key; - char *value; -} epair_t; - -typedef struct -{ - vec3_t origin; - int firstbrush; - int numbrushes; - epair_t *epairs; -} entity_t; - -extern int num_entities; -extern entity_t entities[MAX_MAP_ENTITIES]; - -void ParseEntities (void); -void UnparseEntities (void); - -void SetKeyValue (entity_t *ent, char *key, char *value); -char *ValueForKey (entity_t *ent, char *key); -// will return "" if not present - -vec_t FloatForKey (entity_t *ent, char *key); -void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); - -epair_t *ParseEpair (void); - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + + +// upper design bounds + +#define MAX_MAP_HULLS 4 + +#define MAX_MAP_MODELS 400 +#define MAX_MAP_BRUSHES 4096 +#define MAX_MAP_ENTITIES 1024 +#define MAX_MAP_ENTSTRING (128*1024) + +#define MAX_MAP_PLANES 32767 +#define MAX_MAP_NODES 32767 // because negative shorts are contents +#define MAX_MAP_CLIPNODES 32767 // +#define MAX_MAP_LEAFS 8192 +#define MAX_MAP_VERTS 65535 +#define MAX_MAP_FACES 65535 +#define MAX_MAP_MARKSURFACES 65535 +#define MAX_MAP_TEXINFO 8192 +#define MAX_MAP_EDGES 256000 +#define MAX_MAP_SURFEDGES 512000 +#define MAX_MAP_TEXTURES 512 +#define MAX_MAP_MIPTEX 0x200000 +#define MAX_MAP_LIGHTING 0x200000 +#define MAX_MAP_VISIBILITY 0x200000 + +#define MAX_MAP_PORTALS 65536 + +// key / value pair sizes + +#define MAX_KEY 32 +#define MAX_VALUE 1024 + +//============================================================================= + + +#define BSPVERSION 30 +#define TOOLVERSION 2 + + +typedef struct +{ + int fileofs, filelen; +} lump_t; + +#define LUMP_ENTITIES 0 +#define LUMP_PLANES 1 +#define LUMP_TEXTURES 2 +#define LUMP_VERTEXES 3 +#define LUMP_VISIBILITY 4 +#define LUMP_NODES 5 +#define LUMP_TEXINFO 6 +#define LUMP_FACES 7 +#define LUMP_LIGHTING 8 +#define LUMP_CLIPNODES 9 +#define LUMP_LEAFS 10 +#define LUMP_MARKSURFACES 11 +#define LUMP_EDGES 12 +#define LUMP_SURFEDGES 13 +#define LUMP_MODELS 14 + +#define HEADER_LUMPS 15 + +typedef struct +{ + float mins[3], maxs[3]; + float origin[3]; + int headnode[MAX_MAP_HULLS]; + int visleafs; // not including the solid leaf 0 + int firstface, numfaces; +} dmodel_t; + +typedef struct +{ + int version; + lump_t lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct +{ + int nummiptex; + int dataofs[4]; // [nummiptex] +} dmiptexlump_t; + +#define MIPLEVELS 4 +typedef struct miptex_s +{ + char name[16]; + unsigned width, height; + unsigned offsets[MIPLEVELS]; // four mip maps stored +} miptex_t; + + +typedef struct +{ + float point[3]; +} dvertex_t; + + +// 0-2 are axial planes +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 + +// 3-5 are non-axial planes snapped to the nearest +#define PLANE_ANYX 3 +#define PLANE_ANYY 4 +#define PLANE_ANYZ 5 + +typedef struct +{ + float normal[3]; + float dist; + int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate +} dplane_t; + + + +#define CONTENTS_EMPTY -1 +#define CONTENTS_SOLID -2 +#define CONTENTS_WATER -3 +#define CONTENTS_SLIME -4 +#define CONTENTS_LAVA -5 +#define CONTENTS_SKY -6 +#define CONTENTS_ORIGIN -7 // removed at csg time +#define CONTENTS_CLIP -8 // changed to contents_solid + +#define CONTENTS_CURRENT_0 -9 +#define CONTENTS_CURRENT_90 -10 +#define CONTENTS_CURRENT_180 -11 +#define CONTENTS_CURRENT_270 -12 +#define CONTENTS_CURRENT_UP -13 +#define CONTENTS_CURRENT_DOWN -14 + +#define CONTENTS_TRANSLUCENT -15 + +// !!! if this is changed, it must be changed in asm_i386.h too !!! +typedef struct +{ + int planenum; + short children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for sphere culling + short maxs[3]; + unsigned short firstface; + unsigned short numfaces; // counting both sides +} dnode_t; + +typedef struct +{ + int planenum; + short children[2]; // negative numbers are contents +} dclipnode_t; + + +typedef struct texinfo_s +{ + float vecs[2][4]; // [s/t][xyz offset] + int miptex; + int flags; +} texinfo_t; +#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision + +// note that edge 0 is never used, because negative edge nums are used for +// counterclockwise use of the edge in a face +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dedge_t; + +#define MAXLIGHTMAPS 4 +typedef struct +{ + short planenum; + short side; + + int firstedge; // we must support > 64k edges + short numedges; + short texinfo; + +// lighting info + byte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dface_t; + + + +#define AMBIENT_WATER 0 +#define AMBIENT_SKY 1 +#define AMBIENT_SLIME 2 +#define AMBIENT_LAVA 3 + +#define NUM_AMBIENTS 4 // automatic ambient sounds + +// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas +// all other leafs need visibility info +typedef struct +{ + int contents; + int visofs; // -1 = no visibility info + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned short firstmarksurface; + unsigned short nummarksurfaces; + + byte ambient_level[NUM_AMBIENTS]; +} dleaf_t; + + +//============================================================================ + +#ifndef QUAKE_GAME + +#define ANGLE_UP -1 +#define ANGLE_DOWN -2 + + +// the utilities get to be lazy and just use large static arrays + +extern int nummodels; +extern dmodel_t dmodels[MAX_MAP_MODELS]; +extern int dmodels_checksum; + +extern int visdatasize; +extern byte dvisdata[MAX_MAP_VISIBILITY]; +extern int dvisdata_checksum; + +extern int lightdatasize; +extern byte dlightdata[MAX_MAP_LIGHTING]; +extern int dlightdata_checksum; + +extern int texdatasize; +extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t) +extern int dtexdata_checksum; + +extern int entdatasize; +extern char dentdata[MAX_MAP_ENTSTRING]; +extern int dentdata_checksum; + +extern int numleafs; +extern dleaf_t dleafs[MAX_MAP_LEAFS]; +extern int dleafs_checksum; + +extern int numplanes; +extern dplane_t dplanes[MAX_MAP_PLANES]; +extern int dplanes_checksum; + +extern int numvertexes; +extern dvertex_t dvertexes[MAX_MAP_VERTS]; +extern int dvertexes_checksum; + +extern int numnodes; +extern dnode_t dnodes[MAX_MAP_NODES]; +extern int dnodes_checksum; + +extern int numtexinfo; +extern texinfo_t texinfo[MAX_MAP_TEXINFO]; +extern int texinfo_checksum; + +extern int numfaces; +extern dface_t dfaces[MAX_MAP_FACES]; +extern int dfaces_checksum; + +extern int numclipnodes; +extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES]; +extern int dclipnodes_checksum; + +extern int numedges; +extern dedge_t dedges[MAX_MAP_EDGES]; +extern int dedges_checksum; + +extern int nummarksurfaces; +extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES]; +extern int dmarksurfaces_checksum; + +extern int numsurfedges; +extern int dsurfedges[MAX_MAP_SURFEDGES]; +extern int dsurfedges_checksum; + +int FastChecksum(void *buffer, int bytes); + +void DecompressVis (byte *in, byte *decompressed); +int CompressVis (byte *vis, byte *dest); + +void LoadBSPFile (char *filename); +void WriteBSPFile (char *filename); +void PrintBSPFileSizes (void); + +//=============== + + +typedef struct epair_s +{ + struct epair_s *next; + char *key; + char *value; +} epair_t; + +typedef struct +{ + vec3_t origin; + int firstbrush; + int numbrushes; + epair_t *epairs; +} entity_t; + +extern int num_entities; +extern entity_t entities[MAX_MAP_ENTITIES]; + +void ParseEntities (void); +void UnparseEntities (void); + +void SetKeyValue (entity_t *ent, char *key, char *value); +char *ValueForKey (entity_t *ent, char *key); +// will return "" if not present + +vec_t FloatForKey (entity_t *ent, char *key); +void GetVectorForKey (entity_t *ent, char *key, vec3_t vec); + +epair_t *ParseEpair (void); + +#endif diff --git a/utils/common/cmdlib.c b/utils/common/cmdlib.c index 535aced..6e91fd9 100644 --- a/utils/common/cmdlib.c +++ b/utils/common/cmdlib.c @@ -1,1040 +1,1040 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// cmdlib.c - -#include "cmdlib.h" -#include -#include - -#ifdef WIN32 -#include -#endif - -#ifdef NeXT -#include -#endif - -#ifdef WIN32 -#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') -#else //WIN32 -#define PATHSEPARATOR(c) ((c) == '/') -#endif //WIN32 - -// set these before calling CheckParm -int myargc; -char **myargv; - -char com_token[1024]; -qboolean com_eof; - -qboolean archive; -char archivedir[1024]; - - -void COM_FixSlashes( char *pname ) -{ -#if 0 - while ( *pname ) { - if ( *pname == '/' ) - *pname = '\\'; - pname++; - } -#else - while ( *pname ) { - if ( *pname == '\\' ) - *pname = '/'; - pname++; - } -#endif -} - - -/* -================= -Error - -For abnormal program terminations -================= -*/ -void Error (char *error, ...) -{ - va_list argptr; - - printf ("\n************ ERROR ************\n"); - - va_start (argptr,error); - vprintf (error,argptr); - va_end (argptr); - printf ("\n"); - - exit (1); -} - -// only printf if in verbose mode -qboolean verbose = false; -void qprintf (char *format, ...) -{ - va_list argptr; - - if (!verbose) - return; - va_start (argptr,format); - vprintf (format,argptr); - va_end (argptr); -} - - -/* - -qdir will hold the path up to the quake directory, including the slash - - f:\quake\ - /raid/quake/ - -gamedir will hold qdir + the game directory (id1, id2, etc) - - */ - -char qproject[ 1024 ]={'\0'}; -char qdir[1024]={'\0'}; -char gamedir[1024]={'\0'}; - -void SetQdirFromPath (char *path) -{ -#ifndef OLD_BOGUS_PATH_CODE - - if ( qproject[0]=='\0' ) - { - if ( getenv("QPROJECT") ) - { - char c = qproject[ strlen(qproject)-1 ]; - strcpy( qproject, getenv("QPROJECT") ); - if ( !PATHSEPARATOR( c ) ) - strcat( qproject, "\\" ); - } - else - strcpy( qproject, "quiver\\" ); - } - if ( qproject[0] != '\\' && qproject[0] != '/' && qproject[1] != ':' ) - { - strcpy( qdir, "\\" ); - } - - strcat( qdir, qproject ); - strcpy( gamedir, qdir ); - strcat( gamedir, "\\valve\\" ); - -#else - char temp[1024]; - char *c; - - if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':')) - { // path is partial - Q_getwd (temp); - strcat (temp, path); - path = temp; - } - -// search for "quake" or quiver in path - if( !qproject[0] ) { - char *pszProj; - - pszProj = getenv("QPROJECT"); - - if (pszProj != NULL) - strcpy(qproject, pszProj); - else - strcpy(qproject, "quiver"); - } - -try_again: - - for (c=path ; *c ; c++) - { - int iSize = 0; - - if (!Q_strncasecmp( c, qproject, strlen( qproject ) ) ) - iSize = strlen( qproject ) + 1; - - if (iSize > 0) - { - strncpy (qdir, path, c + iSize - path); - printf ("qdir: %s\n", qdir); - c += iSize; - while (*c) - { - if (*c == '/' || *c == '\\') - { - strncpy (gamedir, path, c+1-path); - printf ("gamedir: %s\n", gamedir); - return; - } - c++; - } - Error ("No gamedir in %s", path); - return; - } - } - - if (!strcmp(qproject, "quiver")) - { - strcpy(qproject, "prospero"); - goto try_again; - } - - Error ("SetQdirFromPath: no '%s' in %s", qproject, path); -#endif -} - - -char *ExpandArg (char *path) -{ - static char full[1024]; - - if (path[0] != '/' && path[0] != '\\' && path[1] != ':') - { - Q_getwd (full); - strcat (full, path); - } - else - strcpy (full, path); - return full; -} - -char *ExpandPath (char *path) -{ - char *psz; - static char full[1024]; - if (!qdir) - Error ("ExpandPath called without qdir set"); - if (path[0] == '/' || path[0] == '\\' || path[1] == ':') - return path; - psz = strstr(path, qdir); - if (psz) - strcpy(full, path); - else - sprintf (full, "%s%s", qdir, path); - - return full; -} - -char *ExpandPathAndArchive (char *path) -{ - char *expanded; - char archivename[1024]; - - expanded = ExpandPath (path); - - if (archive) - { - sprintf (archivename, "%s/%s", archivedir, path); - QCopyFile (expanded, archivename); - } - return expanded; -} - - -char *copystring(char *s) -{ - char *b; - b = malloc(strlen(s)+1); - strcpy (b, s); - return b; -} - - - -/* -================ -I_FloatTime -================ -*/ -double I_FloatTime (void) -{ - time_t t; - - time (&t); - - return t; -#if 0 -// more precise, less portable - struct timeval tp; - struct timezone tzp; - static int secbase; - - gettimeofday(&tp, &tzp); - - if (!secbase) - { - secbase = tp.tv_sec; - return tp.tv_usec/1000000.0; - } - - return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; -#endif -} - -void Q_getwd (char *out) -{ -#ifdef WIN32 - _getcwd (out, 256); - strcat (out, "\\"); -#else - getwd (out); -#endif -} - - -void Q_mkdir (char *path) -{ -#ifdef WIN32 - if (_mkdir (path) != -1) - return; -#else - if (mkdir (path, 0777) != -1) - return; -#endif - if (errno != EEXIST) - Error ("mkdir %s: %s",path, strerror(errno)); -} - -/* -============ -FileTime - -returns -1 if not present -============ -*/ -int FileTime (char *path) -{ - struct stat buf; - - if (stat (path,&buf) == -1) - return -1; - - return buf.st_mtime; -} - - - -/* -============== -COM_Parse - - Parse a token out of a string (into global: char com_token[1024]) -============== -*/ -char *COM_Parse (char *data) -{ - int c; - int len; - - len = 0; - com_token[0] = 0; - - if (!data) - return NULL; - -// skip whitespace -skipwhite: - while ( (c = *data) <= ' ') - { - if (c == 0) - { - com_eof = true; - return NULL; // end of file; - } - data++; - } - -// skip // comments - if (c=='/' && data[1] == '/') - { - while (*data && *data != '\n') - data++; - goto skipwhite; - } - - -// handle quoted strings specially - if (c == '\"') - { - data++; - do - { - c = *data++; - if (c=='\"') - { - com_token[len] = 0; - return data; - } - com_token[len] = c; - len++; - } while (1); - } - -// parse single characters - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - { - com_token[len] = c; - len++; - com_token[len] = 0; - return data+1; - } - -// parse a regular word - do - { - com_token[len] = c; - data++; - len++; - c = *data; - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') - break; - } while (c>32); - - com_token[len] = 0; - return data; -} - - -int Q_strncasecmp (char *s1, char *s2, int n) -{ - int c1, c2; - - while (1) - { - c1 = *s1++; - c2 = *s2++; - - if (!n--) - return 0; // strings are equal until end point - - if (c1 != c2) - { - if (c1 >= 'a' && c1 <= 'z') - c1 -= ('a' - 'A'); - if (c2 >= 'a' && c2 <= 'z') - c2 -= ('a' - 'A'); - if (c1 != c2) - return -1; // strings not equal - } - if (!c1) - return 0; // strings are equal - } - - return -1; -} - -int Q_strcasecmp (char *s1, char *s2) -{ - return Q_strncasecmp (s1, s2, 99999); -} - - -char *strupr (char *start) -{ - char *in; - in = start; - while (*in) - { - *in = toupper(*in); - in++; - } - return start; -} - -char *strlower (char *start) -{ - char *in; - in = start; - while (*in) - { - *in = tolower(*in); - in++; - } - return start; -} - - -/* -============================================================================= - - MISC FUNCTIONS - -============================================================================= -*/ - - -/* -================= -CheckParm - -Checks for the given parameter in the program's command line arguments -Returns the argument number (1 to argc-1) or 0 if not present -================= -*/ -int CheckParm (char *check) -{ - int i; - - for (i = 1;i 0 && !PATHSEPARATOR(path[length])) - length--; - path[length] = 0; -} - -void StripExtension (char *path) -{ - int length; - - length = strlen(path)-1; - while (length > 0 && path[length] != '.') - { - length--; - if (path[length] == '/') - return; // no extension - } - if (length) - path[length] = 0; -} - - -/* -==================== -Extract file parts -==================== -*/ -void ExtractFilePath (char *path, char *dest) -{ - char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && !PATHSEPARATOR(*(src-1))) - src--; - - memcpy (dest, path, src-path); - dest[src-path] = 0; -} - -void ExtractFileBase (char *path, char *dest) -{ - char *src; - - src = path + strlen(path) - 1; - -// -// back up until a \ or the start -// - while (src != path && !PATHSEPARATOR(*(src-1))) - src--; - - while (*src && *src != '.') - { - *dest++ = *src++; - } - *dest = 0; -} - -void ExtractFileExtension (char *path, char *dest) -{ - char *src; - - src = path + strlen(path) - 1; - -// -// back up until a . or the start -// - while (src != path && *(src-1) != '.') - src--; - if (src == path) - { - *dest = 0; // no extension - return; - } - - strcpy (dest,src); -} - - -/* -============== -ParseNum / ParseHex -============== -*/ -int ParseHex (char *hex) -{ - char *str; - int num; - - num = 0; - str = hex; - - while (*str) - { - num <<= 4; - if (*str >= '0' && *str <= '9') - num += *str-'0'; - else if (*str >= 'a' && *str <= 'f') - num += 10 + *str-'a'; - else if (*str >= 'A' && *str <= 'F') - num += 10 + *str-'A'; - else - Error ("Bad hex number: %s",hex); - str++; - } - - return num; -} - - -int ParseNum (char *str) -{ - if (str[0] == '$') - return ParseHex (str+1); - if (str[0] == '0' && str[1] == 'x') - return ParseHex (str+2); - return atol (str); -} - - - -/* -============================================================================ - - BYTE ORDER FUNCTIONS - -============================================================================ -*/ - -#ifdef _SGI_SOURCE -#define __BIG_ENDIAN__ -#endif - -#ifdef __BIG_ENDIAN__ - -short LittleShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short BigShort (short l) -{ - return l; -} - - -int LittleLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int BigLong (int l) -{ - return l; -} - - -float LittleFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float BigFloat (float l) -{ - return l; -} - - -#else - - -short BigShort (short l) -{ - byte b1,b2; - - b1 = l&255; - b2 = (l>>8)&255; - - return (b1<<8) + b2; -} - -short LittleShort (short l) -{ - return l; -} - - -int BigLong (int l) -{ - byte b1,b2,b3,b4; - - b1 = l&255; - b2 = (l>>8)&255; - b3 = (l>>16)&255; - b4 = (l>>24)&255; - - return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; -} - -int LittleLong (int l) -{ - return l; -} - -float BigFloat (float l) -{ - union {byte b[4]; float f;} in, out; - - in.f = l; - out.b[0] = in.b[3]; - out.b[1] = in.b[2]; - out.b[2] = in.b[1]; - out.b[3] = in.b[0]; - - return out.f; -} - -float LittleFloat (float l) -{ - return l; -} - - -#endif - - -//======================================================= - - -// FIXME: byte swap? - -// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 -// and the initial and final xor values shown below... in other words, the -// CCITT standard CRC used by XMODEM - -#define CRC_INIT_VALUE 0xffff -#define CRC_XOR_VALUE 0x0000 - -static unsigned short crctable[256] = -{ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - -void CRC_Init(unsigned short *crcvalue) -{ - *crcvalue = CRC_INIT_VALUE; -} - -void CRC_ProcessByte(unsigned short *crcvalue, byte data) -{ - *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; -} - -unsigned short CRC_Value(unsigned short crcvalue) -{ - return crcvalue ^ CRC_XOR_VALUE; -} -//============================================================================= - -/* -============ -CreatePath -============ -*/ -void CreatePath (char *path) -{ - char *ofs, c; - - for (ofs = path+1 ; *ofs ; ofs++) - { - c = *ofs; - if (c == '/' || c == '\\') - { // create the directory - *ofs = 0; - Q_mkdir (path); - *ofs = c; - } - } -} - - -/* -============ -QCopyFile - - Used to archive source files -============ -*/ -void QCopyFile (char *from, char *to) -{ - void *buffer; - int length; - - length = LoadFile (from, &buffer); - CreatePath (to); - SaveFile (to, buffer, length); - free (buffer); -} - - -/* -============ -ListPak - - Prints the contents of the specified pak file to stdout -============ -*/ - -void ListPak(char* pakname) -{ - FILE* f = SafeOpenRead(pakname); - packheader_t head; - packfile_t* pdir; - long i=0,imax=0; - long totlen=0; - - SafeRead(f,&head,sizeof(packheader_t)); - pdir=malloc(head.dirlen); - - fseek(f,head.dirofs,SEEK_SET); - SafeRead(f,pdir,head.dirlen); - - fseek(f,0,SEEK_END); - totlen=ftell(f); - - fclose(f); - - imax=head.dirlen/sizeof(packfile_t); - - for(i;i +#include + +#ifdef WIN32 +#include +#endif + +#ifdef NeXT +#include +#endif + +#ifdef WIN32 +#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') +#else //WIN32 +#define PATHSEPARATOR(c) ((c) == '/') +#endif //WIN32 + +// set these before calling CheckParm +int myargc; +char **myargv; + +char com_token[1024]; +qboolean com_eof; + +qboolean archive; +char archivedir[1024]; + + +void COM_FixSlashes( char *pname ) +{ +#if 0 + while ( *pname ) { + if ( *pname == '/' ) + *pname = '\\'; + pname++; + } +#else + while ( *pname ) { + if ( *pname == '\\' ) + *pname = '/'; + pname++; + } +#endif +} + + +/* +================= +Error + +For abnormal program terminations +================= +*/ +void Error (char *error, ...) +{ + va_list argptr; + + printf ("\n************ ERROR ************\n"); + + va_start (argptr,error); + vprintf (error,argptr); + va_end (argptr); + printf ("\n"); + + exit (1); +} + +// only printf if in verbose mode +qboolean verbose = false; +void qprintf (char *format, ...) +{ + va_list argptr; + + if (!verbose) + return; + va_start (argptr,format); + vprintf (format,argptr); + va_end (argptr); +} + + +/* + +qdir will hold the path up to the quake directory, including the slash + + f:\quake\ + /raid/quake/ + +gamedir will hold qdir + the game directory (id1, id2, etc) + + */ + +char qproject[ 1024 ]={'\0'}; +char qdir[1024]={'\0'}; +char gamedir[1024]={'\0'}; + +void SetQdirFromPath (char *path) +{ +#ifndef OLD_BOGUS_PATH_CODE + + if ( qproject[0]=='\0' ) + { + if ( getenv("QPROJECT") ) + { + char c = qproject[ strlen(qproject)-1 ]; + strcpy( qproject, getenv("QPROJECT") ); + if ( !PATHSEPARATOR( c ) ) + strcat( qproject, "\\" ); + } + else + strcpy( qproject, "quiver\\" ); + } + if ( qproject[0] != '\\' && qproject[0] != '/' && qproject[1] != ':' ) + { + strcpy( qdir, "\\" ); + } + + strcat( qdir, qproject ); + strcpy( gamedir, qdir ); + strcat( gamedir, "\\valve\\" ); + +#else + char temp[1024]; + char *c; + + if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':')) + { // path is partial + Q_getwd (temp); + strcat (temp, path); + path = temp; + } + +// search for "quake" or quiver in path + if( !qproject[0] ) { + char *pszProj; + + pszProj = getenv("QPROJECT"); + + if (pszProj != NULL) + strcpy(qproject, pszProj); + else + strcpy(qproject, "quiver"); + } + +try_again: + + for (c=path ; *c ; c++) + { + int iSize = 0; + + if (!Q_strncasecmp( c, qproject, strlen( qproject ) ) ) + iSize = strlen( qproject ) + 1; + + if (iSize > 0) + { + strncpy (qdir, path, c + iSize - path); + printf ("qdir: %s\n", qdir); + c += iSize; + while (*c) + { + if (*c == '/' || *c == '\\') + { + strncpy (gamedir, path, c+1-path); + printf ("gamedir: %s\n", gamedir); + return; + } + c++; + } + Error ("No gamedir in %s", path); + return; + } + } + + if (!strcmp(qproject, "quiver")) + { + strcpy(qproject, "prospero"); + goto try_again; + } + + Error ("SetQdirFromPath: no '%s' in %s", qproject, path); +#endif +} + + +char *ExpandArg (char *path) +{ + static char full[1024]; + + if (path[0] != '/' && path[0] != '\\' && path[1] != ':') + { + Q_getwd (full); + strcat (full, path); + } + else + strcpy (full, path); + return full; +} + +char *ExpandPath (char *path) +{ + char *psz; + static char full[1024]; + if (!qdir) + Error ("ExpandPath called without qdir set"); + if (path[0] == '/' || path[0] == '\\' || path[1] == ':') + return path; + psz = strstr(path, qdir); + if (psz) + strcpy(full, path); + else + sprintf (full, "%s%s", qdir, path); + + return full; +} + +char *ExpandPathAndArchive (char *path) +{ + char *expanded; + char archivename[1024]; + + expanded = ExpandPath (path); + + if (archive) + { + sprintf (archivename, "%s/%s", archivedir, path); + QCopyFile (expanded, archivename); + } + return expanded; +} + + +char *copystring(char *s) +{ + char *b; + b = malloc(strlen(s)+1); + strcpy (b, s); + return b; +} + + + +/* +================ +I_FloatTime +================ +*/ +double I_FloatTime (void) +{ + time_t t; + + time (&t); + + return t; +#if 0 +// more precise, less portable + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000000.0; + } + + return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; +#endif +} + +void Q_getwd (char *out) +{ +#ifdef WIN32 + _getcwd (out, 256); + strcat (out, "\\"); +#else + getwd (out); +#endif +} + + +void Q_mkdir (char *path) +{ +#ifdef WIN32 + if (_mkdir (path) != -1) + return; +#else + if (mkdir (path, 0777) != -1) + return; +#endif + if (errno != EEXIST) + Error ("mkdir %s: %s",path, strerror(errno)); +} + +/* +============ +FileTime + +returns -1 if not present +============ +*/ +int FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + + + +/* +============== +COM_Parse + + Parse a token out of a string (into global: char com_token[1024]) +============== +*/ +char *COM_Parse (char *data) +{ + int c; + int len; + + len = 0; + com_token[0] = 0; + + if (!data) + return NULL; + +// skip whitespace +skipwhite: + while ( (c = *data) <= ' ') + { + if (c == 0) + { + com_eof = true; + return NULL; // end of file; + } + data++; + } + +// skip // comments + if (c=='/' && data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + + +// handle quoted strings specially + if (c == '\"') + { + data++; + do + { + c = *data++; + if (c=='\"') + { + com_token[len] = 0; + return data; + } + com_token[len] = c; + len++; + } while (1); + } + +// parse single characters + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + { + com_token[len] = c; + len++; + com_token[len] = 0; + return data+1; + } + +// parse a regular word + do + { + com_token[len] = c; + data++; + len++; + c = *data; + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':') + break; + } while (c>32); + + com_token[len] = 0; + return data; +} + + +int Q_strncasecmp (char *s1, char *s2, int n) +{ + int c1, c2; + + while (1) + { + c1 = *s1++; + c2 = *s2++; + + if (!n--) + return 0; // strings are equal until end point + + if (c1 != c2) + { + if (c1 >= 'a' && c1 <= 'z') + c1 -= ('a' - 'A'); + if (c2 >= 'a' && c2 <= 'z') + c2 -= ('a' - 'A'); + if (c1 != c2) + return -1; // strings not equal + } + if (!c1) + return 0; // strings are equal + } + + return -1; +} + +int Q_strcasecmp (char *s1, char *s2) +{ + return Q_strncasecmp (s1, s2, 99999); +} + + +char *strupr (char *start) +{ + char *in; + in = start; + while (*in) + { + *in = toupper(*in); + in++; + } + return start; +} + +char *strlower (char *start) +{ + char *in; + in = start; + while (*in) + { + *in = tolower(*in); + in++; + } + return start; +} + + +/* +============================================================================= + + MISC FUNCTIONS + +============================================================================= +*/ + + +/* +================= +CheckParm + +Checks for the given parameter in the program's command line arguments +Returns the argument number (1 to argc-1) or 0 if not present +================= +*/ +int CheckParm (char *check) +{ + int i; + + for (i = 1;i 0 && !PATHSEPARATOR(path[length])) + length--; + path[length] = 0; +} + +void StripExtension (char *path) +{ + int length; + + length = strlen(path)-1; + while (length > 0 && path[length] != '.') + { + length--; + if (path[length] == '/') + return; // no extension + } + if (length) + path[length] = 0; +} + + +/* +==================== +Extract file parts +==================== +*/ +void ExtractFilePath (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && !PATHSEPARATOR(*(src-1))) + src--; + + memcpy (dest, path, src-path); + dest[src-path] = 0; +} + +void ExtractFileBase (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a \ or the start +// + while (src != path && !PATHSEPARATOR(*(src-1))) + src--; + + while (*src && *src != '.') + { + *dest++ = *src++; + } + *dest = 0; +} + +void ExtractFileExtension (char *path, char *dest) +{ + char *src; + + src = path + strlen(path) - 1; + +// +// back up until a . or the start +// + while (src != path && *(src-1) != '.') + src--; + if (src == path) + { + *dest = 0; // no extension + return; + } + + strcpy (dest,src); +} + + +/* +============== +ParseNum / ParseHex +============== +*/ +int ParseHex (char *hex) +{ + char *str; + int num; + + num = 0; + str = hex; + + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str-'0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str-'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str-'A'; + else + Error ("Bad hex number: %s",hex); + str++; + } + + return num; +} + + +int ParseNum (char *str) +{ + if (str[0] == '$') + return ParseHex (str+1); + if (str[0] == '0' && str[1] == 'x') + return ParseHex (str+2); + return atol (str); +} + + + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +#ifdef _SGI_SOURCE +#define __BIG_ENDIAN__ +#endif + +#ifdef __BIG_ENDIAN__ + +short LittleShort (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short BigShort (short l) +{ + return l; +} + + +int LittleLong (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int BigLong (int l) +{ + return l; +} + + +float LittleFloat (float l) +{ + union {byte b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float BigFloat (float l) +{ + return l; +} + + +#else + + +short BigShort (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short LittleShort (short l) +{ + return l; +} + + +int BigLong (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int LittleLong (int l) +{ + return l; +} + +float BigFloat (float l) +{ + union {byte b[4]; float f;} in, out; + + in.f = l; + out.b[0] = in.b[3]; + out.b[1] = in.b[2]; + out.b[2] = in.b[1]; + out.b[3] = in.b[0]; + + return out.f; +} + +float LittleFloat (float l) +{ + return l; +} + + +#endif + + +//======================================================= + + +// FIXME: byte swap? + +// this is a 16 bit, non-reflected CRC using the polynomial 0x1021 +// and the initial and final xor values shown below... in other words, the +// CCITT standard CRC used by XMODEM + +#define CRC_INIT_VALUE 0xffff +#define CRC_XOR_VALUE 0x0000 + +static unsigned short crctable[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 +}; + +void CRC_Init(unsigned short *crcvalue) +{ + *crcvalue = CRC_INIT_VALUE; +} + +void CRC_ProcessByte(unsigned short *crcvalue, byte data) +{ + *crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data]; +} + +unsigned short CRC_Value(unsigned short crcvalue) +{ + return crcvalue ^ CRC_XOR_VALUE; +} +//============================================================================= + +/* +============ +CreatePath +============ +*/ +void CreatePath (char *path) +{ + char *ofs, c; + + for (ofs = path+1 ; *ofs ; ofs++) + { + c = *ofs; + if (c == '/' || c == '\\') + { // create the directory + *ofs = 0; + Q_mkdir (path); + *ofs = c; + } + } +} + + +/* +============ +QCopyFile + + Used to archive source files +============ +*/ +void QCopyFile (char *from, char *to) +{ + void *buffer; + int length; + + length = LoadFile (from, &buffer); + CreatePath (to); + SaveFile (to, buffer, length); + free (buffer); +} + + +/* +============ +ListPak + + Prints the contents of the specified pak file to stdout +============ +*/ + +void ListPak(char* pakname) +{ + FILE* f = SafeOpenRead(pakname); + packheader_t head; + packfile_t* pdir; + long i=0,imax=0; + long totlen=0; + + SafeRead(f,&head,sizeof(packheader_t)); + pdir=malloc(head.dirlen); + + fseek(f,head.dirofs,SEEK_SET); + SafeRead(f,pdir,head.dirlen); + + fseek(f,0,SEEK_END); + totlen=ftell(f); + + fclose(f); + + imax=head.dirlen/sizeof(packfile_t); + + for(i;i -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#ifndef __CMDUTIL__ -#define __CMDUTIL__ -#ifndef _NOENUMQBOOL -typedef enum {false, true} qboolean; -#else -typedef int qboolean; -#undef true -#undef false -#define true 1 -#define false 0 -#endif - -typedef unsigned char byte; -#endif - -// the dec offsetof macro doesn't work very well... -#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) - - -// set these before calling CheckParm -extern int myargc; -extern char **myargv; - -void COM_FixSlashes( char *pname ); -char *strupr (char *in); -char *strlower (char *in); -int Q_strncasecmp (char *s1, char *s2, int n); -int Q_strcasecmp (char *s1, char *s2); -void Q_getwd (char *out); - -int filelength (FILE *f); -int FileTime (char *path); - -void Q_mkdir (char *path); - -extern char qdir[1024]; -extern char gamedir[1024]; -void SetQdirFromPath (char *path); -char *ExpandArg (char *path); // from cmd line -char *ExpandPath (char *path); // from scripts -char *ExpandPathAndArchive (char *path); - - -double I_FloatTime (void); - -void Error (char *error, ...); -int CheckParm (char *check); - -FILE *SafeOpenWrite (char *filename); -FILE *SafeOpenRead (char *filename); -void SafeRead (FILE *f, void *buffer, int count); -void SafeWrite (FILE *f, void *buffer, int count); - -int LoadFile (char *filename, void **bufferptr); -void SaveFile (char *filename, void *buffer, int count); - -void DefaultExtension (char *path, char *extension); -void DefaultPath (char *path, char *basepath); -void StripFilename (char *path); -void StripExtension (char *path); - -void ExtractFilePath (char *path, char *dest); -void ExtractFileBase (char *path, char *dest); -void ExtractFileExtension (char *path, char *dest); - -int ParseNum (char *str); - -short BigShort (short l); -short LittleShort (short l); -int BigLong (int l); -int LittleLong (int l); -float BigFloat (float l); -float LittleFloat (float l); - -long flen(FILE* f); - - - -char *COM_Parse (char *data); - -extern char com_token[1024]; -extern qboolean com_eof; - -char *copystring(char *s); - - -void CRC_Init(unsigned short *crcvalue); -void CRC_ProcessByte(unsigned short *crcvalue, byte data); -unsigned short CRC_Value(unsigned short crcvalue); - -void CreatePath (char *path); -void QCopyFile (char *from, char *to); - -extern qboolean archive; -extern char archivedir[1024]; - - -extern qboolean verbose; -void qprintf (char *format, ...); - - -typedef struct -{ - char name[56]; - int filepos, filelen; -} packfile_t; - -typedef struct -{ - char id[4]; - int dirofs; - int dirlen; -} packheader_t; - - -void ListPak(char* pakname); - -#endif -#ifdef __cplusplus -} -#endif - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// cmdlib.h + +#ifndef __CMDLIB__ +#define __CMDLIB__ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef __CMDUTIL__ +#define __CMDUTIL__ +#ifndef _NOENUMQBOOL +typedef enum {false, true} qboolean; +#else +typedef int qboolean; +#undef true +#undef false +#define true 1 +#define false 0 +#endif + +typedef unsigned char byte; +#endif + +// the dec offsetof macro doesn't work very well... +#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) + + +// set these before calling CheckParm +extern int myargc; +extern char **myargv; + +void COM_FixSlashes( char *pname ); +char *strupr (char *in); +char *strlower (char *in); +int Q_strncasecmp (char *s1, char *s2, int n); +int Q_strcasecmp (char *s1, char *s2); +void Q_getwd (char *out); + +int filelength (FILE *f); +int FileTime (char *path); + +void Q_mkdir (char *path); + +extern char qdir[1024]; +extern char gamedir[1024]; +void SetQdirFromPath (char *path); +char *ExpandArg (char *path); // from cmd line +char *ExpandPath (char *path); // from scripts +char *ExpandPathAndArchive (char *path); + + +double I_FloatTime (void); + +void Error (char *error, ...); +int CheckParm (char *check); + +FILE *SafeOpenWrite (char *filename); +FILE *SafeOpenRead (char *filename); +void SafeRead (FILE *f, void *buffer, int count); +void SafeWrite (FILE *f, void *buffer, int count); + +int LoadFile (char *filename, void **bufferptr); +void SaveFile (char *filename, void *buffer, int count); + +void DefaultExtension (char *path, char *extension); +void DefaultPath (char *path, char *basepath); +void StripFilename (char *path); +void StripExtension (char *path); + +void ExtractFilePath (char *path, char *dest); +void ExtractFileBase (char *path, char *dest); +void ExtractFileExtension (char *path, char *dest); + +int ParseNum (char *str); + +short BigShort (short l); +short LittleShort (short l); +int BigLong (int l); +int LittleLong (int l); +float BigFloat (float l); +float LittleFloat (float l); + +long flen(FILE* f); + + + +char *COM_Parse (char *data); + +extern char com_token[1024]; +extern qboolean com_eof; + +char *copystring(char *s); + + +void CRC_Init(unsigned short *crcvalue); +void CRC_ProcessByte(unsigned short *crcvalue, byte data); +unsigned short CRC_Value(unsigned short crcvalue); + +void CreatePath (char *path); +void QCopyFile (char *from, char *to); + +extern qboolean archive; +extern char archivedir[1024]; + + +extern qboolean verbose; +void qprintf (char *format, ...); + + +typedef struct +{ + char name[56]; + int filepos, filelen; +} packfile_t; + +typedef struct +{ + char id[4]; + int dirofs; + int dirlen; +} packheader_t; + + +void ListPak(char* pakname); + +#endif +#ifdef __cplusplus +} +#endif + diff --git a/utils/common/lbmlib.c b/utils/common/lbmlib.c index 578707a..045dbdf 100644 --- a/utils/common/lbmlib.c +++ b/utils/common/lbmlib.c @@ -1,744 +1,744 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// lbmlib.c - -#include -#include - -#include "cmdlib.h" -#include "lbmlib.h" - - - -/* -============================================================================ - - LBM STUFF - -============================================================================ -*/ - - -#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24)) -#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24)) -#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24)) -#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24)) -#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24)) -#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24)) - - -bmhd_t bmhd; - -int Align (int l) -{ - if (l&1) - return l+1; - return l; -} - - - -/* -================ -= -= LBMRLEdecompress -= -= Source must be evenly aligned! -= -================ -*/ - -byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth) -{ - int count; - byte b,rept; - - count = 0; - - do - { - rept = *source++; - - if (rept > 0x80) - { - rept = (rept^0xff)+2; - b = *source++; - memset(unpacked,b,rept); - unpacked += rept; - } - else if (rept < 0x80) - { - rept++; - memcpy(unpacked,source,rept); - unpacked += rept; - source += rept; - } - else - rept = 0; // rept of 0x80 is NOP - - count += rept; - - } while (countbpwidth) - Error ("Decompression exceeded width!\n"); - - - return source; -} - - -#define BPLANESIZE 128 -byte bitplanes[9][BPLANESIZE]; // max size 1024 by 9 bit planes - - -/* -================= -= -= MungeBitPlanes8 -= -= This destroys the bit plane data! -= -================= -*/ - -void MungeBitPlanes8 (int width, byte *dest) -{ - *dest=width; // shut up the compiler warning - Error ("MungeBitPlanes8 not rewritten!"); -#if 0 -asm les di,[dest] -asm mov si,-1 -asm mov cx,[width] -mungebyte: -asm inc si -asm mov dx,8 -mungebit: -asm shl [BYTE PTR bitplanes + BPLANESIZE*7 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*6 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*5 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*4 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 -asm rcl al,1 -asm stosb -asm dec cx -asm jz done -asm dec dx -asm jnz mungebit -asm jmp mungebyte - -done: -#endif -} - - -void MungeBitPlanes4 (int width, byte *dest) -{ - *dest=width; // shut up the compiler warning - Error ("MungeBitPlanes4 not rewritten!"); -#if 0 - -asm les di,[dest] -asm mov si,-1 -asm mov cx,[width] -mungebyte: -asm inc si -asm mov dx,8 -mungebit: -asm xor al,al -asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 -asm rcl al,1 -asm stosb -asm dec cx -asm jz done -asm dec dx -asm jnz mungebit -asm jmp mungebyte - -done: -#endif -} - - -void MungeBitPlanes2 (int width, byte *dest) -{ - *dest=width; // shut up the compiler warning - Error ("MungeBitPlanes2 not rewritten!"); -#if 0 -asm les di,[dest] -asm mov si,-1 -asm mov cx,[width] -mungebyte: -asm inc si -asm mov dx,8 -mungebit: -asm xor al,al -asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 -asm rcl al,1 -asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 -asm rcl al,1 -asm stosb -asm dec cx -asm jz done -asm dec dx -asm jnz mungebit -asm jmp mungebyte - -done: -#endif -} - - -void MungeBitPlanes1 (int width, byte *dest) -{ - *dest=width; // shut up the compiler warning - Error ("MungeBitPlanes1 not rewritten!"); -#if 0 -asm les di,[dest] -asm mov si,-1 -asm mov cx,[width] -mungebyte: -asm inc si -asm mov dx,8 -mungebit: -asm xor al,al -asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 -asm rcl al,1 -asm stosb -asm dec cx -asm jz done -asm dec dx -asm jnz mungebit -asm jmp mungebyte - -done: -#endif -} - -int LoadBMP (const char* szFile, BYTE** ppbBits, BYTE** ppbPalette) -{ - int i, rc = 0; - FILE *pfile = NULL; - BITMAPFILEHEADER bmfh; - BITMAPINFOHEADER bmih; - RGBQUAD rgrgbPalette[256]; - ULONG cbBmpBits; - BYTE* pbBmpBits; - byte *pb, *pbPal = NULL; - ULONG cbPalBytes; - ULONG biTrueWidth; - - // Bogus parameter check - if (!(ppbPalette != NULL && ppbBits != NULL)) - { fprintf(stderr, "invalid BMP file\n"); rc = -1000; goto GetOut; } - - // File exists? - if ((pfile = fopen(szFile, "rb")) == NULL) - { fprintf(stderr, "unable to open BMP file\n"); rc = -1; goto GetOut; } - - // Read file header - if (fread(&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1) - { rc = -2; goto GetOut; } - - // Bogus file header check - if (!(bmfh.bfReserved1 == 0 && bmfh.bfReserved2 == 0)) - { rc = -2000; goto GetOut; } - - // Read info header - if (fread(&bmih, sizeof bmih, 1/*count*/, pfile) != 1) - { rc = -3; goto GetOut; } - - // Bogus info header check - if (!(bmih.biSize == sizeof bmih && bmih.biPlanes == 1)) - { fprintf(stderr, "invalid BMP file header\n"); rc = -3000; goto GetOut; } - - // Bogus bit depth? Only 8-bit supported. - if (bmih.biBitCount != 8) - { fprintf(stderr, "BMP file not 8 bit\n"); rc = -4; goto GetOut; } - - // Bogus compression? Only non-compressed supported. - if (bmih.biCompression != BI_RGB) - { fprintf(stderr, "invalid BMP compression type\n"); rc = -5; goto GetOut; } - - // Figure out how many entires are actually in the table - if (bmih.biClrUsed == 0) - { - bmih.biClrUsed = 256; - cbPalBytes = (1 << bmih.biBitCount) * sizeof( RGBQUAD ); - } - else - { - cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); - } - - // Read palette (bmih.biClrUsed entries) - if (fread(rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1) - { rc = -6; goto GetOut; } - - // convert to a packed 768 byte palette - pbPal = malloc(768); - if (pbPal == NULL) - { rc = -7; goto GetOut; } - - pb = pbPal; - - // Copy over used entries - for (i = 0; i < (int)bmih.biClrUsed; i++) - { - *pb++ = rgrgbPalette[i].rgbRed; - *pb++ = rgrgbPalette[i].rgbGreen; - *pb++ = rgrgbPalette[i].rgbBlue; - } - - // Fill in unused entires will 0,0,0 - for (i = bmih.biClrUsed; i < 256; i++) - { - *pb++ = 0; - *pb++ = 0; - *pb++ = 0; - } - - // Read bitmap bits (remainder of file) - cbBmpBits = bmfh.bfSize - ftell(pfile); - pb = malloc(cbBmpBits); - if (fread(pb, cbBmpBits, 1/*count*/, pfile) != 1) - { rc = -7; goto GetOut; } - - pbBmpBits = malloc(cbBmpBits); - - // data is actually stored with the width being rounded up to a multiple of 4 - biTrueWidth = (bmih.biWidth + 3) & ~3; - - // reverse the order of the data. - pb += (bmih.biHeight - 1) * biTrueWidth; - for(i = 0; i < bmih.biHeight; i++) - { - memmove(&pbBmpBits[biTrueWidth * i], pb, biTrueWidth); - pb -= biTrueWidth; - } - - pb += biTrueWidth; - free(pb); - - bmhd.w = (WORD)bmih.biWidth; - bmhd.h = (WORD)bmih.biHeight; - // Set output parameters - *ppbPalette = pbPal; - *ppbBits = pbBmpBits; - -GetOut: - if (pfile) - fclose(pfile); - - return rc; -} - - -int WriteBMPfile (char *szFile, byte *pbBits, int width, int height, byte *pbPalette) -{ - int i, rc = 0; - FILE *pfile = NULL; - BITMAPFILEHEADER bmfh; - BITMAPINFOHEADER bmih; - RGBQUAD rgrgbPalette[256]; - ULONG cbBmpBits; - BYTE* pbBmpBits; - byte *pb, *pbPal = NULL; - ULONG cbPalBytes; - ULONG biTrueWidth; - - // Bogus parameter check - if (!(pbPalette != NULL && pbBits != NULL)) - { rc = -1000; goto GetOut; } - - // File exists? - if ((pfile = fopen(szFile, "wb")) == NULL) - { rc = -1; goto GetOut; } - - biTrueWidth = ((width + 3) & ~3); - cbBmpBits = biTrueWidth * height; - cbPalBytes = 256 * sizeof( RGBQUAD ); - - // Bogus file header check - bmfh.bfType = MAKEWORD( 'B', 'M' ); - bmfh.bfSize = sizeof bmfh + sizeof bmih + cbBmpBits + cbPalBytes; - bmfh.bfReserved1 = 0; - bmfh.bfReserved2 = 0; - bmfh.bfOffBits = sizeof bmfh + sizeof bmih + cbPalBytes; - - // Write file header - if (fwrite(&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1) - { rc = -2; goto GetOut; } - - // Size of structure - bmih.biSize = sizeof bmih; - // Width - bmih.biWidth = biTrueWidth; - // Height - bmih.biHeight = height; - // Only 1 plane - bmih.biPlanes = 1; - // Only 8-bit supported. - bmih.biBitCount = 8; - // Only non-compressed supported. - bmih.biCompression = BI_RGB; - bmih.biSizeImage = 0; - - // huh? - bmih.biXPelsPerMeter = 0; - bmih.biYPelsPerMeter = 0; - - // Always full palette - bmih.biClrUsed = 256; - bmih.biClrImportant = 0; - - // Write info header - if (fwrite(&bmih, sizeof bmih, 1/*count*/, pfile) != 1) - { rc = -3; goto GetOut; } - - - // convert to expanded palette - pb = pbPalette; - - // Copy over used entries - for (i = 0; i < (int)bmih.biClrUsed; i++) - { - rgrgbPalette[i].rgbRed = *pb++; - rgrgbPalette[i].rgbGreen = *pb++; - rgrgbPalette[i].rgbBlue = *pb++; - rgrgbPalette[i].rgbReserved = 0; - } - - // Write palette (bmih.biClrUsed entries) - cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); - if (fwrite(rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1) - { rc = -6; goto GetOut; } - - - pbBmpBits = malloc(cbBmpBits); - - pb = pbBits; - // reverse the order of the data. - pb += (height - 1) * width; - for(i = 0; i < bmih.biHeight; i++) - { - memmove(&pbBmpBits[biTrueWidth * i], pb, width); - pb -= width; - } - - // Write bitmap bits (remainder of file) - if (fwrite(pbBmpBits, cbBmpBits, 1/*count*/, pfile) != 1) - { rc = -7; goto GetOut; } - - free(pbBmpBits); - -GetOut: - if (pfile) - fclose(pfile); - - return rc; -} - -/* -================= -= -= LoadLBM -= -================= -*/ - -void LoadLBM (char *filename, byte **picture, byte **palette) -{ - byte *LBMbuffer, *picbuffer, *cmapbuffer; - int y,p,planes; - byte *LBM_P, *LBMEND_P; - byte *pic_p; - byte *body_p; - unsigned rowsize; - - int formtype,formlength; - int chunktype,chunklength; - void (*mungecall) (int, byte *); - -// qiet compiler warnings - picbuffer = NULL; - cmapbuffer = NULL; - mungecall = NULL; - -// -// load the LBM -// - LoadFile (filename, (void **)&LBMbuffer); - -// -// parse the LBM header -// - LBM_P = LBMbuffer; - if ( *(int *)LBMbuffer != LittleLong(FORMID) ) - Error ("No FORM ID at start of file!\n"); - - LBM_P += 4; - formlength = BigLong( *(int *)LBM_P ); - LBM_P += 4; - LBMEND_P = LBM_P + Align(formlength); - - formtype = LittleLong(*(int *)LBM_P); - - if (formtype != ILBMID && formtype != PBMID) - Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff - ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); - - LBM_P += 4; - -// -// parse chunks -// - - while (LBM_P < LBMEND_P) - { - chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); - LBM_P += 4; - chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); - LBM_P += 4; - - switch ( chunktype ) - { - case BMHDID: - memcpy (&bmhd,LBM_P,sizeof(bmhd)); - bmhd.w = BigShort(bmhd.w); - bmhd.h = BigShort(bmhd.h); - bmhd.x = BigShort(bmhd.x); - bmhd.y = BigShort(bmhd.y); - bmhd.pageWidth = BigShort(bmhd.pageWidth); - bmhd.pageHeight = BigShort(bmhd.pageHeight); - break; - - case CMAPID: - cmapbuffer = malloc (768); - memset (cmapbuffer, 0, 768); - memcpy (cmapbuffer, LBM_P, chunklength); - break; - - case BODYID: - body_p = LBM_P; - - pic_p = picbuffer = malloc (bmhd.w*bmhd.h); - if (formtype == PBMID) - { - // - // unpack PBM - // - for (y=0 ; y +#include + +#include "cmdlib.h" +#include "lbmlib.h" + + + +/* +============================================================================ + + LBM STUFF + +============================================================================ +*/ + + +#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24)) +#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24)) +#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24)) +#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24)) +#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24)) +#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24)) + + +bmhd_t bmhd; + +int Align (int l) +{ + if (l&1) + return l+1; + return l; +} + + + +/* +================ += += LBMRLEdecompress += += Source must be evenly aligned! += +================ +*/ + +byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth) +{ + int count; + byte b,rept; + + count = 0; + + do + { + rept = *source++; + + if (rept > 0x80) + { + rept = (rept^0xff)+2; + b = *source++; + memset(unpacked,b,rept); + unpacked += rept; + } + else if (rept < 0x80) + { + rept++; + memcpy(unpacked,source,rept); + unpacked += rept; + source += rept; + } + else + rept = 0; // rept of 0x80 is NOP + + count += rept; + + } while (countbpwidth) + Error ("Decompression exceeded width!\n"); + + + return source; +} + + +#define BPLANESIZE 128 +byte bitplanes[9][BPLANESIZE]; // max size 1024 by 9 bit planes + + +/* +================= += += MungeBitPlanes8 += += This destroys the bit plane data! += +================= +*/ + +void MungeBitPlanes8 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes8 not rewritten!"); +#if 0 +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm shl [BYTE PTR bitplanes + BPLANESIZE*7 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*6 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*5 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*4 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + + +void MungeBitPlanes4 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes4 not rewritten!"); +#if 0 + +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*3 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*2 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + + +void MungeBitPlanes2 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes2 not rewritten!"); +#if 0 +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*1 +si],1 +asm rcl al,1 +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + + +void MungeBitPlanes1 (int width, byte *dest) +{ + *dest=width; // shut up the compiler warning + Error ("MungeBitPlanes1 not rewritten!"); +#if 0 +asm les di,[dest] +asm mov si,-1 +asm mov cx,[width] +mungebyte: +asm inc si +asm mov dx,8 +mungebit: +asm xor al,al +asm shl [BYTE PTR bitplanes + BPLANESIZE*0 +si],1 +asm rcl al,1 +asm stosb +asm dec cx +asm jz done +asm dec dx +asm jnz mungebit +asm jmp mungebyte + +done: +#endif +} + +int LoadBMP (const char* szFile, BYTE** ppbBits, BYTE** ppbPalette) +{ + int i, rc = 0; + FILE *pfile = NULL; + BITMAPFILEHEADER bmfh; + BITMAPINFOHEADER bmih; + RGBQUAD rgrgbPalette[256]; + ULONG cbBmpBits; + BYTE* pbBmpBits; + byte *pb, *pbPal = NULL; + ULONG cbPalBytes; + ULONG biTrueWidth; + + // Bogus parameter check + if (!(ppbPalette != NULL && ppbBits != NULL)) + { fprintf(stderr, "invalid BMP file\n"); rc = -1000; goto GetOut; } + + // File exists? + if ((pfile = fopen(szFile, "rb")) == NULL) + { fprintf(stderr, "unable to open BMP file\n"); rc = -1; goto GetOut; } + + // Read file header + if (fread(&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1) + { rc = -2; goto GetOut; } + + // Bogus file header check + if (!(bmfh.bfReserved1 == 0 && bmfh.bfReserved2 == 0)) + { rc = -2000; goto GetOut; } + + // Read info header + if (fread(&bmih, sizeof bmih, 1/*count*/, pfile) != 1) + { rc = -3; goto GetOut; } + + // Bogus info header check + if (!(bmih.biSize == sizeof bmih && bmih.biPlanes == 1)) + { fprintf(stderr, "invalid BMP file header\n"); rc = -3000; goto GetOut; } + + // Bogus bit depth? Only 8-bit supported. + if (bmih.biBitCount != 8) + { fprintf(stderr, "BMP file not 8 bit\n"); rc = -4; goto GetOut; } + + // Bogus compression? Only non-compressed supported. + if (bmih.biCompression != BI_RGB) + { fprintf(stderr, "invalid BMP compression type\n"); rc = -5; goto GetOut; } + + // Figure out how many entires are actually in the table + if (bmih.biClrUsed == 0) + { + bmih.biClrUsed = 256; + cbPalBytes = (1 << bmih.biBitCount) * sizeof( RGBQUAD ); + } + else + { + cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); + } + + // Read palette (bmih.biClrUsed entries) + if (fread(rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1) + { rc = -6; goto GetOut; } + + // convert to a packed 768 byte palette + pbPal = malloc(768); + if (pbPal == NULL) + { rc = -7; goto GetOut; } + + pb = pbPal; + + // Copy over used entries + for (i = 0; i < (int)bmih.biClrUsed; i++) + { + *pb++ = rgrgbPalette[i].rgbRed; + *pb++ = rgrgbPalette[i].rgbGreen; + *pb++ = rgrgbPalette[i].rgbBlue; + } + + // Fill in unused entires will 0,0,0 + for (i = bmih.biClrUsed; i < 256; i++) + { + *pb++ = 0; + *pb++ = 0; + *pb++ = 0; + } + + // Read bitmap bits (remainder of file) + cbBmpBits = bmfh.bfSize - ftell(pfile); + pb = malloc(cbBmpBits); + if (fread(pb, cbBmpBits, 1/*count*/, pfile) != 1) + { rc = -7; goto GetOut; } + + pbBmpBits = malloc(cbBmpBits); + + // data is actually stored with the width being rounded up to a multiple of 4 + biTrueWidth = (bmih.biWidth + 3) & ~3; + + // reverse the order of the data. + pb += (bmih.biHeight - 1) * biTrueWidth; + for(i = 0; i < bmih.biHeight; i++) + { + memmove(&pbBmpBits[biTrueWidth * i], pb, biTrueWidth); + pb -= biTrueWidth; + } + + pb += biTrueWidth; + free(pb); + + bmhd.w = (WORD)bmih.biWidth; + bmhd.h = (WORD)bmih.biHeight; + // Set output parameters + *ppbPalette = pbPal; + *ppbBits = pbBmpBits; + +GetOut: + if (pfile) + fclose(pfile); + + return rc; +} + + +int WriteBMPfile (char *szFile, byte *pbBits, int width, int height, byte *pbPalette) +{ + int i, rc = 0; + FILE *pfile = NULL; + BITMAPFILEHEADER bmfh; + BITMAPINFOHEADER bmih; + RGBQUAD rgrgbPalette[256]; + ULONG cbBmpBits; + BYTE* pbBmpBits; + byte *pb, *pbPal = NULL; + ULONG cbPalBytes; + ULONG biTrueWidth; + + // Bogus parameter check + if (!(pbPalette != NULL && pbBits != NULL)) + { rc = -1000; goto GetOut; } + + // File exists? + if ((pfile = fopen(szFile, "wb")) == NULL) + { rc = -1; goto GetOut; } + + biTrueWidth = ((width + 3) & ~3); + cbBmpBits = biTrueWidth * height; + cbPalBytes = 256 * sizeof( RGBQUAD ); + + // Bogus file header check + bmfh.bfType = MAKEWORD( 'B', 'M' ); + bmfh.bfSize = sizeof bmfh + sizeof bmih + cbBmpBits + cbPalBytes; + bmfh.bfReserved1 = 0; + bmfh.bfReserved2 = 0; + bmfh.bfOffBits = sizeof bmfh + sizeof bmih + cbPalBytes; + + // Write file header + if (fwrite(&bmfh, sizeof bmfh, 1/*count*/, pfile) != 1) + { rc = -2; goto GetOut; } + + // Size of structure + bmih.biSize = sizeof bmih; + // Width + bmih.biWidth = biTrueWidth; + // Height + bmih.biHeight = height; + // Only 1 plane + bmih.biPlanes = 1; + // Only 8-bit supported. + bmih.biBitCount = 8; + // Only non-compressed supported. + bmih.biCompression = BI_RGB; + bmih.biSizeImage = 0; + + // huh? + bmih.biXPelsPerMeter = 0; + bmih.biYPelsPerMeter = 0; + + // Always full palette + bmih.biClrUsed = 256; + bmih.biClrImportant = 0; + + // Write info header + if (fwrite(&bmih, sizeof bmih, 1/*count*/, pfile) != 1) + { rc = -3; goto GetOut; } + + + // convert to expanded palette + pb = pbPalette; + + // Copy over used entries + for (i = 0; i < (int)bmih.biClrUsed; i++) + { + rgrgbPalette[i].rgbRed = *pb++; + rgrgbPalette[i].rgbGreen = *pb++; + rgrgbPalette[i].rgbBlue = *pb++; + rgrgbPalette[i].rgbReserved = 0; + } + + // Write palette (bmih.biClrUsed entries) + cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); + if (fwrite(rgrgbPalette, cbPalBytes, 1/*count*/, pfile) != 1) + { rc = -6; goto GetOut; } + + + pbBmpBits = malloc(cbBmpBits); + + pb = pbBits; + // reverse the order of the data. + pb += (height - 1) * width; + for(i = 0; i < bmih.biHeight; i++) + { + memmove(&pbBmpBits[biTrueWidth * i], pb, width); + pb -= width; + } + + // Write bitmap bits (remainder of file) + if (fwrite(pbBmpBits, cbBmpBits, 1/*count*/, pfile) != 1) + { rc = -7; goto GetOut; } + + free(pbBmpBits); + +GetOut: + if (pfile) + fclose(pfile); + + return rc; +} + +/* +================= += += LoadLBM += +================= +*/ + +void LoadLBM (char *filename, byte **picture, byte **palette) +{ + byte *LBMbuffer, *picbuffer, *cmapbuffer; + int y,p,planes; + byte *LBM_P, *LBMEND_P; + byte *pic_p; + byte *body_p; + unsigned rowsize; + + int formtype,formlength; + int chunktype,chunklength; + void (*mungecall) (int, byte *); + +// qiet compiler warnings + picbuffer = NULL; + cmapbuffer = NULL; + mungecall = NULL; + +// +// load the LBM +// + LoadFile (filename, (void **)&LBMbuffer); + +// +// parse the LBM header +// + LBM_P = LBMbuffer; + if ( *(int *)LBMbuffer != LittleLong(FORMID) ) + Error ("No FORM ID at start of file!\n"); + + LBM_P += 4; + formlength = BigLong( *(int *)LBM_P ); + LBM_P += 4; + LBMEND_P = LBM_P + Align(formlength); + + formtype = LittleLong(*(int *)LBM_P); + + if (formtype != ILBMID && formtype != PBMID) + Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff + ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff); + + LBM_P += 4; + +// +// parse chunks +// + + while (LBM_P < LBMEND_P) + { + chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24); + LBM_P += 4; + chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24); + LBM_P += 4; + + switch ( chunktype ) + { + case BMHDID: + memcpy (&bmhd,LBM_P,sizeof(bmhd)); + bmhd.w = BigShort(bmhd.w); + bmhd.h = BigShort(bmhd.h); + bmhd.x = BigShort(bmhd.x); + bmhd.y = BigShort(bmhd.y); + bmhd.pageWidth = BigShort(bmhd.pageWidth); + bmhd.pageHeight = BigShort(bmhd.pageHeight); + break; + + case CMAPID: + cmapbuffer = malloc (768); + memset (cmapbuffer, 0, 768); + memcpy (cmapbuffer, LBM_P, chunklength); + break; + + case BODYID: + body_p = LBM_P; + + pic_p = picbuffer = malloc (bmhd.w*bmhd.h); + if (formtype == PBMID) + { + // + // unpack PBM + // + for (y=0 ; y EQUAL_EPSILON) - return false; - - return true; -} - -vec_t Q_rint (vec_t in) -{ - return floor (in + 0.5); -} - -void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc) -{ - vc[0] = va[0] + scale*vb[0]; - vc[1] = va[1] + scale*vb[1]; - vc[2] = va[2] + scale*vb[2]; -} - -void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) -{ - cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; - cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; - cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -vec_t _DotProduct (vec3_t v1, vec3_t v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) -{ - out[0] = va[0]-vb[0]; - out[1] = va[1]-vb[1]; - out[2] = va[2]-vb[2]; -} - -void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) -{ - out[0] = va[0]+vb[0]; - out[1] = va[1]+vb[1]; - out[2] = va[2]+vb[2]; -} - -void _VectorCopy (vec3_t in, vec3_t out) -{ - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; -} - -void _VectorScale (vec3_t v, vec_t scale, vec3_t out) -{ - out[0] = v[0] * scale; - out[1] = v[1] * scale; - out[2] = v[2] * scale; -} - -vec_t VectorNormalize (vec3_t v) -{ - int i; - double length; - -if ( fabs(v[1] - 0.000215956) < 0.0001) -i=1; - - length = 0; - for (i=0 ; i< 3 ; i++) - length += v[i]*v[i]; - length = sqrt (length); - if (length == 0) - return 0; - - for (i=0 ; i< 3 ; i++) - v[i] /= length; - - return length; -} - -void VectorInverse (vec3_t v) -{ - v[0] = -v[0]; - v[1] = -v[1]; - v[2] = -v[2]; -} - -void ClearBounds (vec3_t mins, vec3_t maxs) -{ - mins[0] = mins[1] = mins[2] = 99999; - maxs[0] = maxs[1] = maxs[2] = -99999; -} - -void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs) -{ - int i; - vec_t val; - - for (i=0 ; i<3 ; i++) - { - val = v[i]; - if (val < mins[i]) - mins[i] = val; - if (val > maxs[i]) - maxs[i] = val; - } -} - -void AngleMatrix (const vec3_t angles, float (*matrix)[4] ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[2] * (Q_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[1] * (Q_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[0] * (Q_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - // matrix = (Z * Y) * X - matrix[0][0] = cp*cy; - matrix[1][0] = cp*sy; - matrix[2][0] = -sp; - matrix[0][1] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[2][1] = sr*cp; - matrix[0][2] = (cr*sp*cy+-sr*-sy); - matrix[1][2] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; - matrix[0][3] = 0.0; - matrix[1][3] = 0.0; - matrix[2][3] = 0.0; -} - -void AngleIMatrix (const vec3_t angles, float matrix[3][4] ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - angle = angles[2] * (Q_PI*2 / 360); - sy = sin(angle); - cy = cos(angle); - angle = angles[1] * (Q_PI*2 / 360); - sp = sin(angle); - cp = cos(angle); - angle = angles[0] * (Q_PI*2 / 360); - sr = sin(angle); - cr = cos(angle); - - // matrix = (Z * Y) * X - matrix[0][0] = cp*cy; - matrix[0][1] = cp*sy; - matrix[0][2] = -sp; - matrix[1][0] = sr*sp*cy+cr*-sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[1][2] = sr*cp; - matrix[2][0] = (cr*sp*cy+-sr*-sy); - matrix[2][1] = (cr*sp*sy+-sr*cy); - matrix[2][2] = cr*cp; - matrix[0][3] = 0.0; - matrix[1][3] = 0.0; - matrix[2][3] = 0.0; -} - -void R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4]) -{ - out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + - in1[0][2] * in2[2][0]; - out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + - in1[0][2] * in2[2][1]; - out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + - in1[0][2] * in2[2][2]; - out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + - in1[0][2] * in2[2][3] + in1[0][3]; - out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + - in1[1][2] * in2[2][0]; - out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + - in1[1][2] * in2[2][1]; - out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + - in1[1][2] * in2[2][2]; - out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + - in1[1][2] * in2[2][3] + in1[1][3]; - out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + - in1[2][2] * in2[2][0]; - out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + - in1[2][2] * in2[2][1]; - out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + - in1[2][2] * in2[2][2]; - out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + - in1[2][2] * in2[2][3] + in1[2][3]; -} - - - -void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t out) -{ - out[0] = DotProduct(in1, in2[0]); - out[1] = DotProduct(in1, in2[1]); - out[2] = DotProduct(in1, in2[2]); -} - - -// rotate by the inverse of the matrix -void VectorIRotate (const vec3_t in1, const float in2[3][4], vec3_t out) -{ - out[0] = in1[0]*in2[0][0] + in1[1]*in2[1][0] + in1[2]*in2[2][0]; - out[1] = in1[0]*in2[0][1] + in1[1]*in2[1][1] + in1[2]*in2[2][1]; - out[2] = in1[0]*in2[0][2] + in1[1]*in2[1][2] + in1[2]*in2[2][2]; -} - - -void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out) -{ - out[0] = DotProduct(in1, in2[0]) + in2[0][3]; - out[1] = DotProduct(in1, in2[1]) + in2[1][3]; - out[2] = DotProduct(in1, in2[2]) + in2[2][3]; -} - - - -void AngleQuaternion( const vec3_t angles, vec4_t quaternion ) -{ - float angle; - float sr, sp, sy, cr, cp, cy; - - // FIXME: rescale the inputs to 1/2 angle - angle = angles[2] * 0.5; - sy = sin(angle); - cy = cos(angle); - angle = angles[1] * 0.5; - sp = sin(angle); - cp = cos(angle); - angle = angles[0] * 0.5; - sr = sin(angle); - cr = cos(angle); - - quaternion[0] = sr*cp*cy-cr*sp*sy; // X - quaternion[1] = cr*sp*cy+sr*cp*sy; // Y - quaternion[2] = cr*cp*sy-sr*sp*cy; // Z - quaternion[3] = cr*cp*cy+sr*sp*sy; // W -} - -void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ) -{ - - matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2]; - matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2]; - matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1]; - - matrix[0][1] = 2.0 * quaternion[0] * quaternion[1] - 2.0 * quaternion[3] * quaternion[2]; - matrix[1][1] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[2] * quaternion[2]; - matrix[2][1] = 2.0 * quaternion[1] * quaternion[2] + 2.0 * quaternion[3] * quaternion[0]; - - matrix[0][2] = 2.0 * quaternion[0] * quaternion[2] + 2.0 * quaternion[3] * quaternion[1]; - matrix[1][2] = 2.0 * quaternion[1] * quaternion[2] - 2.0 * quaternion[3] * quaternion[0]; - matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1]; -} - -void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) -{ - int i; - float omega, cosom, sinom, sclp, sclq; - - // decide if one of the quaternions is backwards - float a = 0; - float b = 0; - for (i = 0; i < 4; i++) { - a += (p[i]-q[i])*(p[i]-q[i]); - b += (p[i]+q[i])*(p[i]+q[i]); - } - if (a > b) { - for (i = 0; i < 4; i++) { - q[i] = -q[i]; - } - } - - cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; - - if ((1.0 + cosom) > 0.00000001) { - if ((1.0 - cosom) > 0.00000001) { - omega = acos( cosom ); - sinom = sin( omega ); - sclp = sin( (1.0 - t)*omega) / sinom; - sclq = sin( t*omega ) / sinom; - } - else { - sclp = 1.0 - t; - sclq = t; - } - for (i = 0; i < 4; i++) { - qt[i] = sclp * p[i] + sclq * q[i]; - } - } - else { - qt[0] = -p[1]; - qt[1] = p[0]; - qt[2] = -p[3]; - qt[3] = p[2]; - sclp = sin( (1.0 - t) * 0.5 * Q_PI); - sclq = sin( t * 0.5 * Q_PI); - for (i = 0; i < 3; i++) { - qt[i] = sclp * p[i] + sclq * qt[i]; - } - } -} - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// mathlib.c -- math primitives + +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4237 ) +#pragma warning( disable : 4305 ) + +#include "cmdlib.h" +#include "mathlib.h" + +vec3_t vec3_origin = {0,0,0}; + + +double VectorLength(vec3_t v) +{ + int i; + double length; + + length = 0; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = sqrt (length); // FIXME + + return length; +} + + +int VectorCompare (vec3_t v1, vec3_t v2) +{ + int i; + + for (i=0 ; i<3 ; i++) + if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON) + return false; + + return true; +} + +vec_t Q_rint (vec_t in) +{ + return floor (in + 0.5); +} + +void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc) +{ + vc[0] = va[0] + scale*vb[0]; + vc[1] = va[1] + scale*vb[1]; + vc[2] = va[2] + scale*vb[2]; +} + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +vec_t _DotProduct (vec3_t v1, vec3_t v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out) +{ + out[0] = va[0]-vb[0]; + out[1] = va[1]-vb[1]; + out[2] = va[2]-vb[2]; +} + +void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out) +{ + out[0] = va[0]+vb[0]; + out[1] = va[1]+vb[1]; + out[2] = va[2]+vb[2]; +} + +void _VectorCopy (vec3_t in, vec3_t out) +{ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; +} + +void _VectorScale (vec3_t v, vec_t scale, vec3_t out) +{ + out[0] = v[0] * scale; + out[1] = v[1] * scale; + out[2] = v[2] * scale; +} + +vec_t VectorNormalize (vec3_t v) +{ + int i; + double length; + +if ( fabs(v[1] - 0.000215956) < 0.0001) +i=1; + + length = 0; + for (i=0 ; i< 3 ; i++) + length += v[i]*v[i]; + length = sqrt (length); + if (length == 0) + return 0; + + for (i=0 ; i< 3 ; i++) + v[i] /= length; + + return length; +} + +void VectorInverse (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +void ClearBounds (vec3_t mins, vec3_t maxs) +{ + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; +} + +void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs) +{ + int i; + vec_t val; + + for (i=0 ; i<3 ; i++) + { + val = v[i]; + if (val < mins[i]) + mins[i] = val; + if (val > maxs[i]) + maxs[i] = val; + } +} + +void AngleMatrix (const vec3_t angles, float (*matrix)[4] ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[2] * (Q_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[1] * (Q_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[0] * (Q_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + // matrix = (Z * Y) * X + matrix[0][0] = cp*cy; + matrix[1][0] = cp*sy; + matrix[2][0] = -sp; + matrix[0][1] = sr*sp*cy+cr*-sy; + matrix[1][1] = sr*sp*sy+cr*cy; + matrix[2][1] = sr*cp; + matrix[0][2] = (cr*sp*cy+-sr*-sy); + matrix[1][2] = (cr*sp*sy+-sr*cy); + matrix[2][2] = cr*cp; + matrix[0][3] = 0.0; + matrix[1][3] = 0.0; + matrix[2][3] = 0.0; +} + +void AngleIMatrix (const vec3_t angles, float matrix[3][4] ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + angle = angles[2] * (Q_PI*2 / 360); + sy = sin(angle); + cy = cos(angle); + angle = angles[1] * (Q_PI*2 / 360); + sp = sin(angle); + cp = cos(angle); + angle = angles[0] * (Q_PI*2 / 360); + sr = sin(angle); + cr = cos(angle); + + // matrix = (Z * Y) * X + matrix[0][0] = cp*cy; + matrix[0][1] = cp*sy; + matrix[0][2] = -sp; + matrix[1][0] = sr*sp*cy+cr*-sy; + matrix[1][1] = sr*sp*sy+cr*cy; + matrix[1][2] = sr*cp; + matrix[2][0] = (cr*sp*cy+-sr*-sy); + matrix[2][1] = (cr*sp*sy+-sr*cy); + matrix[2][2] = cr*cp; + matrix[0][3] = 0.0; + matrix[1][3] = 0.0; + matrix[2][3] = 0.0; +} + +void R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + + in1[0][2] * in2[2][3] + in1[0][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + + in1[1][2] * in2[2][3] + in1[1][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + + in1[2][2] * in2[2][3] + in1[2][3]; +} + + + +void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t out) +{ + out[0] = DotProduct(in1, in2[0]); + out[1] = DotProduct(in1, in2[1]); + out[2] = DotProduct(in1, in2[2]); +} + + +// rotate by the inverse of the matrix +void VectorIRotate (const vec3_t in1, const float in2[3][4], vec3_t out) +{ + out[0] = in1[0]*in2[0][0] + in1[1]*in2[1][0] + in1[2]*in2[2][0]; + out[1] = in1[0]*in2[0][1] + in1[1]*in2[1][1] + in1[2]*in2[2][1]; + out[2] = in1[0]*in2[0][2] + in1[1]*in2[1][2] + in1[2]*in2[2][2]; +} + + +void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out) +{ + out[0] = DotProduct(in1, in2[0]) + in2[0][3]; + out[1] = DotProduct(in1, in2[1]) + in2[1][3]; + out[2] = DotProduct(in1, in2[2]) + in2[2][3]; +} + + + +void AngleQuaternion( const vec3_t angles, vec4_t quaternion ) +{ + float angle; + float sr, sp, sy, cr, cp, cy; + + // FIXME: rescale the inputs to 1/2 angle + angle = angles[2] * 0.5; + sy = sin(angle); + cy = cos(angle); + angle = angles[1] * 0.5; + sp = sin(angle); + cp = cos(angle); + angle = angles[0] * 0.5; + sr = sin(angle); + cr = cos(angle); + + quaternion[0] = sr*cp*cy-cr*sp*sy; // X + quaternion[1] = cr*sp*cy+sr*cp*sy; // Y + quaternion[2] = cr*cp*sy-sr*sp*cy; // Z + quaternion[3] = cr*cp*cy+sr*sp*sy; // W +} + +void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ) +{ + + matrix[0][0] = 1.0 - 2.0 * quaternion[1] * quaternion[1] - 2.0 * quaternion[2] * quaternion[2]; + matrix[1][0] = 2.0 * quaternion[0] * quaternion[1] + 2.0 * quaternion[3] * quaternion[2]; + matrix[2][0] = 2.0 * quaternion[0] * quaternion[2] - 2.0 * quaternion[3] * quaternion[1]; + + matrix[0][1] = 2.0 * quaternion[0] * quaternion[1] - 2.0 * quaternion[3] * quaternion[2]; + matrix[1][1] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[2] * quaternion[2]; + matrix[2][1] = 2.0 * quaternion[1] * quaternion[2] + 2.0 * quaternion[3] * quaternion[0]; + + matrix[0][2] = 2.0 * quaternion[0] * quaternion[2] + 2.0 * quaternion[3] * quaternion[1]; + matrix[1][2] = 2.0 * quaternion[1] * quaternion[2] - 2.0 * quaternion[3] * quaternion[0]; + matrix[2][2] = 1.0 - 2.0 * quaternion[0] * quaternion[0] - 2.0 * quaternion[1] * quaternion[1]; +} + +void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ) +{ + int i; + float omega, cosom, sinom, sclp, sclq; + + // decide if one of the quaternions is backwards + float a = 0; + float b = 0; + for (i = 0; i < 4; i++) { + a += (p[i]-q[i])*(p[i]-q[i]); + b += (p[i]+q[i])*(p[i]+q[i]); + } + if (a > b) { + for (i = 0; i < 4; i++) { + q[i] = -q[i]; + } + } + + cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3]; + + if ((1.0 + cosom) > 0.00000001) { + if ((1.0 - cosom) > 0.00000001) { + omega = acos( cosom ); + sinom = sin( omega ); + sclp = sin( (1.0 - t)*omega) / sinom; + sclq = sin( t*omega ) / sinom; + } + else { + sclp = 1.0 - t; + sclq = t; + } + for (i = 0; i < 4; i++) { + qt[i] = sclp * p[i] + sclq * q[i]; + } + } + else { + qt[0] = -p[1]; + qt[1] = p[0]; + qt[2] = -p[3]; + qt[3] = p[2]; + sclp = sin( (1.0 - t) * 0.5 * Q_PI); + sclq = sin( t * 0.5 * Q_PI); + for (i = 0; i < 3; i++) { + qt[i] = sclp * p[i] + sclq * qt[i]; + } + } +} + + diff --git a/utils/common/mathlib.h b/utils/common/mathlib.h index 9a8155c..bb6b667 100644 --- a/utils/common/mathlib.h +++ b/utils/common/mathlib.h @@ -1,91 +1,91 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#ifndef __MATHLIB__ -#define __MATHLIB__ - -// mathlib.h - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef DOUBLEVEC_T -typedef double vec_t; -#else -typedef float vec_t; -#endif -#ifndef vec3_t -typedef vec_t vec3_t[3]; // x,y,z -#endif -typedef vec_t vec4_t[4]; // x,y,z,w - -#define SIDE_FRONT 0 -#define SIDE_ON 2 -#define SIDE_BACK 1 -#define SIDE_CROSS -2 - -#define Q_PI 3.14159265358979323846 - -extern vec3_t vec3_origin; - -// Use this definition globally -#define ON_EPSILON 0.01 -#define EQUAL_EPSILON 0.001 - -int VectorCompare (vec3_t v1, vec3_t v2); - -#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) -#define VectorFill(a,b) { (a)[0]=(b); (a)[1]=(b); (a)[2]=(b);} -#define VectorAvg(a) ( ( (a)[0] + (a)[1] + (a)[2] ) / 3 ) -#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 VectorScale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];(c)[2]=(b)*(a)[2];} - -vec_t Q_rint (vec_t in); -vec_t _DotProduct (vec3_t v1, vec3_t v2); -void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); -void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); -void _VectorCopy (vec3_t in, vec3_t out); -void _VectorScale (vec3_t v, vec_t scale, vec3_t out); - -double VectorLength(vec3_t v); - -void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc); - -void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); -vec_t VectorNormalize (vec3_t v); -void VectorInverse (vec3_t v); - -void ClearBounds (vec3_t mins, vec3_t maxs); -void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); - -void AngleMatrix (const vec3_t angles, float matrix[3][4] ); -void AngleIMatrix (const vec3_t angles, float matrix[3][4] ); -void R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4]); - -void VectorIRotate (const vec3_t in1, const float in2[3][4], vec3_t out); -void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t out); - -void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out); - -void AngleQuaternion( const vec3_t angles, vec4_t quaternion ); -void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ); -void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ); - - -#ifdef __cplusplus -} -#endif - -#endif +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +#ifndef __MATHLIB__ +#define __MATHLIB__ + +// mathlib.h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef DOUBLEVEC_T +typedef double vec_t; +#else +typedef float vec_t; +#endif +#ifndef vec3_t +typedef vec_t vec3_t[3]; // x,y,z +#endif +typedef vec_t vec4_t[4]; // x,y,z,w + +#define SIDE_FRONT 0 +#define SIDE_ON 2 +#define SIDE_BACK 1 +#define SIDE_CROSS -2 + +#define Q_PI 3.14159265358979323846 + +extern vec3_t vec3_origin; + +// Use this definition globally +#define ON_EPSILON 0.01 +#define EQUAL_EPSILON 0.001 + +int VectorCompare (vec3_t v1, vec3_t v2); + +#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) +#define VectorFill(a,b) { (a)[0]=(b); (a)[1]=(b); (a)[2]=(b);} +#define VectorAvg(a) ( ( (a)[0] + (a)[1] + (a)[2] ) / 3 ) +#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 VectorScale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];(c)[2]=(b)*(a)[2];} + +vec_t Q_rint (vec_t in); +vec_t _DotProduct (vec3_t v1, vec3_t v2); +void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out); +void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out); +void _VectorCopy (vec3_t in, vec3_t out); +void _VectorScale (vec3_t v, vec_t scale, vec3_t out); + +double VectorLength(vec3_t v); + +void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc); + +void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross); +vec_t VectorNormalize (vec3_t v); +void VectorInverse (vec3_t v); + +void ClearBounds (vec3_t mins, vec3_t maxs); +void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs); + +void AngleMatrix (const vec3_t angles, float matrix[3][4] ); +void AngleIMatrix (const vec3_t angles, float matrix[3][4] ); +void R_ConcatTransforms (const float in1[3][4], const float in2[3][4], float out[3][4]); + +void VectorIRotate (const vec3_t in1, const float in2[3][4], vec3_t out); +void VectorRotate (const vec3_t in1, const float in2[3][4], vec3_t out); + +void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out); + +void AngleQuaternion( const vec3_t angles, vec4_t quaternion ); +void QuaternionMatrix( const vec4_t quaternion, float (*matrix)[4] ); +void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/utils/common/movie.h b/utils/common/movie.h index a68b807..ac4bef7 100644 --- a/utils/common/movie.h +++ b/utils/common/movie.h @@ -1,36 +1,36 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#ifndef _MOVIE_H_ -#define _MOVIE_H_ - -/* - movie.h - - definitions and such for dumping screen shots to make a movie -*/ - -typedef struct -{ - unsigned long tag; - unsigned long size; -} movieblockheader_t; - - -typedef struct -{ - short width; - short height; - short depth; -} movieframe_t; - - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +#ifndef _MOVIE_H_ +#define _MOVIE_H_ + +/* + movie.h + + definitions and such for dumping screen shots to make a movie +*/ + +typedef struct +{ + unsigned long tag; + unsigned long size; +} movieblockheader_t; + + +typedef struct +{ + short width; + short height; + short depth; +} movieframe_t; + + + #endif _MOVIE_H_ \ No newline at end of file diff --git a/utils/common/polylib.c b/utils/common/polylib.c index 844bfea..6420f5b 100644 --- a/utils/common/polylib.c +++ b/utils/common/polylib.c @@ -1,708 +1,708 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - - -#include "cmdlib.h" -#include "mathlib.h" -#include "polylib.h" - -int c_active_windings; -int c_peak_windings; -int c_winding_allocs; -int c_winding_points; - -#define BOGUS_RANGE 8192 - -void pw(winding_t *w) -{ - int i; - for (i=0 ; inumpoints ; i++) - printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]); -} - - -/* -============= -AllocWinding -============= -*/ -winding_t *AllocWinding (int points) -{ - winding_t *w; - int s; - - c_winding_allocs++; - c_winding_points += points; - c_active_windings++; - if (c_active_windings > c_peak_windings) - c_peak_windings = c_active_windings; - s = sizeof(vec_t)*3*points + sizeof(int); - s += sizeof(vec_t) - sizeof(w->numpoints); // padding - - w = malloc (s); - memset (w, 0, s); - - return w; -} - -void FreeWinding (winding_t *w) -{ - c_active_windings--; - free (w); -} - -/* -============ -RemoveColinearPoints -============ -*/ -int c_removed; - -void RemoveColinearPoints (winding_t *w) -{ - int i, j, k; - vec3_t v1, v2; - int nump; - vec3_t p[MAX_POINTS_ON_WINDING]; - - nump = 0; - for (i=0 ; inumpoints ; i++) - { - j = (i+1)%w->numpoints; - k = (i+w->numpoints-1)%w->numpoints; - VectorSubtract (w->p[j], w->p[i], v1); - VectorSubtract (w->p[i], w->p[k], v2); - VectorNormalize(v1); - VectorNormalize(v2); - if (DotProduct(v1, v2) < 1.0-ON_EPSILON) - { - VectorCopy (w->p[i], p[nump]); - nump++; - } - } - - if (nump == w->numpoints) - return; - - c_removed += w->numpoints - nump; - w->numpoints = nump; - memcpy (w->p, p, nump*sizeof(p[0])); -} - -/* -============ -WindingPlane -============ -*/ -void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist) -{ - vec3_t v1, v2; - - VectorSubtract (w->p[1], w->p[0], v1); - VectorSubtract (w->p[2], w->p[0], v2); - CrossProduct (v2, v1, normal); - VectorNormalize (normal); - *dist = DotProduct (w->p[0], normal); - -} - -/* -============= -WindingArea -============= -*/ -vec_t WindingArea (winding_t *w) -{ - int i; - vec3_t d1, d2, cross; - vec_t total; - - total = 0; - for (i=2 ; inumpoints ; i++) - { - VectorSubtract (w->p[i-1], w->p[0], d1); - VectorSubtract (w->p[i], w->p[0], d2); - CrossProduct (d1, d2, cross); - total += 0.5 * VectorLength ( cross ); - } - return total; -} - -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs) -{ - vec_t v; - int i,j; - - mins[0] = mins[1] = mins[2] = 99999; - maxs[0] = maxs[1] = maxs[2] = -99999; - - for (i=0 ; inumpoints ; i++) - { - for (j=0 ; j<3 ; j++) - { - v = w->p[i][j]; - if (v < mins[j]) - mins[j] = v; - if (v > maxs[j]) - maxs[j] = v; - } - } -} - -/* -============= -WindingCenter -============= -*/ -void WindingCenter (winding_t *w, vec3_t center) -{ - int i; - vec3_t d1, d2, cross; - float scale; - - VectorCopy (vec3_origin, center); - for (i=0 ; inumpoints ; i++) - VectorAdd (w->p[i], center, center); - - scale = 1.0/w->numpoints; - VectorScale (center, scale, center); -} - -/* -================= -BaseWindingForPlane -================= -*/ -winding_t *BaseWindingForPlane (vec3_t normal, float dist) -{ - int i, x; - vec_t max, v; - vec3_t org, vright, vup; - winding_t *w; - -// find the major axis - - max = -BOGUS_RANGE; - x = -1; - for (i=0 ; i<3; i++) - { - v = fabs(normal[i]); - if (v > max) - { - x = i; - max = v; - } - } - if (x==-1) - Error ("BaseWindingForPlane: no axis found"); - - VectorCopy (vec3_origin, vup); - switch (x) - { - case 0: - case 1: - vup[2] = 1; - break; - case 2: - vup[0] = 1; - break; - } - - v = DotProduct (vup, normal); - VectorMA (vup, -v, normal, vup); - VectorNormalize (vup); - - VectorScale (normal, dist, org); - - CrossProduct (vup, normal, vright); - - VectorScale (vup, 9000, vup); - VectorScale (vright, 9000, vright); - -// project a really big axis aligned box onto the plane - w = AllocWinding (4); - - VectorSubtract (org, vright, w->p[0]); - VectorAdd (w->p[0], vup, w->p[0]); - - VectorAdd (org, vright, w->p[1]); - VectorAdd (w->p[1], vup, w->p[1]); - - VectorAdd (org, vright, w->p[2]); - VectorSubtract (w->p[2], vup, w->p[2]); - - VectorSubtract (org, vright, w->p[3]); - VectorSubtract (w->p[3], vup, w->p[3]); - - w->numpoints = 4; - - return w; -} - -/* -================== -CopyWinding -================== -*/ -winding_t *CopyWinding (winding_t *w) -{ - int size; - winding_t *c; - - size = (int)((winding_t *)0)->p[w->numpoints]; - c = malloc (size); - memcpy (c, w, size); - return c; -} - - -/* -============= -ClipWinding -============= -*/ -void ClipWinding (winding_t *in, vec3_t normal, vec_t dist, - winding_t **front, winding_t **back) -{ - vec_t dists[MAX_POINTS_ON_WINDING+4]; - int sides[MAX_POINTS_ON_WINDING+4]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *f, *b; - int maxpts; - - counts[0] = counts[1] = counts[2] = 0; - -// determine sides for each point - for (i=0 ; inumpoints ; i++) - { - dot = DotProduct (in->p[i], normal); - dot -= dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - *front = *back = NULL; - - if (!counts[0]) - { - *back = CopyWinding (in); - return; - } - if (!counts[1]) - { - *front = CopyWinding (in); - return; - } - - maxpts = in->numpoints+4; // can't use counts[0]+2 because - // of fp grouping errors - - *front = f = AllocWinding (maxpts); - *back = b = AllocWinding (maxpts); - - for (i=0 ; inumpoints ; i++) - { - p1 = in->p[i]; - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - VectorCopy (p1, b->p[b->numpoints]); - b->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b->p[b->numpoints]); - b->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - // generate a split point - p2 = in->p[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (normal[j] == 1) - mid[j] = dist; - else if (normal[j] == -1) - mid[j] = -dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f->p[f->numpoints]); - f->numpoints++; - VectorCopy (mid, b->p[b->numpoints]); - b->numpoints++; - } - - if (f->numpoints > maxpts || b->numpoints > maxpts) - Error ("ClipWinding: points exceeded estimate"); - if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) - Error ("ClipWinding: MAX_POINTS_ON_WINDING"); -} - - - -/* -============= -ClipWindingNoCopy -============= -*/ -void ClipWindingNoCopy (winding_t *in, vec3_t normal, vec_t dist, - winding_t **front, winding_t **back) -{ - vec_t dists[MAX_POINTS_ON_WINDING+4]; - int sides[MAX_POINTS_ON_WINDING+4]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *f, *b; - int maxpts; - - counts[0] = counts[1] = counts[2] = 0; - -// determine sides for each point - for (i=0 ; inumpoints ; i++) - { - dot = DotProduct (in->p[i], normal); - dot -= dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - *front = *back = NULL; - - if (!counts[0]) - { - *back = in; - return; - } - if (!counts[1]) - { - *front = in; - return; - } - - maxpts = in->numpoints+4; // can't use counts[0]+2 because - // of fp grouping errors - - *front = f = AllocWinding (maxpts); - *back = b = AllocWinding (maxpts); - - for (i=0 ; inumpoints ; i++) - { - p1 = in->p[i]; - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - VectorCopy (p1, b->p[b->numpoints]); - b->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b->p[b->numpoints]); - b->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - // generate a split point - p2 = in->p[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (normal[j] == 1) - mid[j] = dist; - else if (normal[j] == -1) - mid[j] = -dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f->p[f->numpoints]); - f->numpoints++; - VectorCopy (mid, b->p[b->numpoints]); - b->numpoints++; - } - - if (f->numpoints > maxpts || b->numpoints > maxpts) - Error ("ClipWinding: points exceeded estimate"); - if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) - Error ("ClipWinding: MAX_POINTS_ON_WINDING"); -} - - -/* -============= -ChopWindingNoFree -============= -*/ -winding_t *ChopWindingNoFree (winding_t *in, vec3_t normal, vec_t dist) -{ - vec_t dists[MAX_POINTS_ON_WINDING+4]; - int sides[MAX_POINTS_ON_WINDING+4]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *f; - int maxpts; - - counts[0] = counts[1] = counts[2] = 0; - -// determine sides for each point - for (i=0 ; inumpoints ; i++) - { - dot = DotProduct (in->p[i], normal); - dot -= dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - sides[i] = sides[0]; - dists[i] = dists[0]; - - if (!counts[0]) - return NULL; - if (!counts[1]) - return in; - - maxpts = in->numpoints+4; // can't use counts[0]+2 because - // of fp grouping errors - - f = AllocWinding (maxpts); - - for (i=0 ; inumpoints ; i++) - { - p1 = in->p[i]; - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f->p[f->numpoints]); - f->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - // generate a split point - p2 = in->p[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (normal[j] == 1) - mid[j] = dist; - else if (normal[j] == -1) - mid[j] = -dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f->p[f->numpoints]); - f->numpoints++; - } - - if (f->numpoints > maxpts) - Error ("ClipWinding: points exceeded estimate"); - if (f->numpoints > MAX_POINTS_ON_WINDING) - Error ("ClipWinding: MAX_POINTS_ON_WINDING"); - - return f; -} - - -/* -================= -ChopWinding - -Returns the fragment of in that is on the front side -of the cliping plane. The original is freed. -================= -*/ -winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist) -{ - winding_t *f, *b; - - ClipWinding (in, normal, dist, &f, &b); - FreeWinding (in); - if (b) - FreeWinding (b); - return f; -} - - -/* -================= -CheckWinding - -================= -*/ -void CheckWinding (winding_t *w) -{ - int i, j; - vec_t *p1, *p2; - vec_t d, edgedist; - vec3_t dir, edgenormal, facenormal; - vec_t area; - vec_t facedist; - - if (w->numpoints < 3) - Error ("CheckWinding: %i points",w->numpoints); - - area = WindingArea(w); - if (area < 1) - Error ("CheckWinding: %f area", area); - - WindingPlane (w, facenormal, &facedist); - - for (i=0 ; inumpoints ; i++) - { - p1 = w->p[i]; - - for (j=0 ; j<3 ; j++) - if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) - Error ("CheckFace: BUGUS_RANGE: %f",p1[j]); - - j = i+1 == w->numpoints ? 0 : i+1; - - // check the point is on the face plane - d = DotProduct (p1, facenormal) - facedist; - if (d < -ON_EPSILON || d > ON_EPSILON) - Error ("CheckWinding: point off plane"); - - // check the edge isn't degenerate - p2 = w->p[j]; - VectorSubtract (p2, p1, dir); - - if (VectorLength (dir) < ON_EPSILON) - Error ("CheckWinding: degenerate edge"); - - CrossProduct (facenormal, dir, edgenormal); - VectorNormalize (edgenormal); - edgedist = DotProduct (p1, edgenormal); - edgedist += ON_EPSILON; - - // all other points must be on front side - for (j=0 ; jnumpoints ; j++) - { - if (j == i) - continue; - d = DotProduct (w->p[j], edgenormal); - if (d > edgedist) - Error ("CheckWinding: non-convex"); - } - } -} - - -/* -============ -WindingOnPlaneSide -============ -*/ -int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist) -{ - qboolean front, back; - int i; - vec_t d; - - front = false; - back = false; - for (i=0 ; inumpoints ; i++) - { - d = DotProduct (w->p[i], normal) - dist; - if (d < -ON_EPSILON) - { - if (front) - return SIDE_CROSS; - back = true; - continue; - } - if (d > ON_EPSILON) - { - if (back) - return SIDE_CROSS; - front = true; - continue; - } - } - - if (back) - return SIDE_BACK; - if (front) - return SIDE_FRONT; - return SIDE_ON; -} - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + + +#include "cmdlib.h" +#include "mathlib.h" +#include "polylib.h" + +int c_active_windings; +int c_peak_windings; +int c_winding_allocs; +int c_winding_points; + +#define BOGUS_RANGE 8192 + +void pw(winding_t *w) +{ + int i; + for (i=0 ; inumpoints ; i++) + printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]); +} + + +/* +============= +AllocWinding +============= +*/ +winding_t *AllocWinding (int points) +{ + winding_t *w; + int s; + + c_winding_allocs++; + c_winding_points += points; + c_active_windings++; + if (c_active_windings > c_peak_windings) + c_peak_windings = c_active_windings; + s = sizeof(vec_t)*3*points + sizeof(int); + s += sizeof(vec_t) - sizeof(w->numpoints); // padding + + w = malloc (s); + memset (w, 0, s); + + return w; +} + +void FreeWinding (winding_t *w) +{ + c_active_windings--; + free (w); +} + +/* +============ +RemoveColinearPoints +============ +*/ +int c_removed; + +void RemoveColinearPoints (winding_t *w) +{ + int i, j, k; + vec3_t v1, v2; + int nump; + vec3_t p[MAX_POINTS_ON_WINDING]; + + nump = 0; + for (i=0 ; inumpoints ; i++) + { + j = (i+1)%w->numpoints; + k = (i+w->numpoints-1)%w->numpoints; + VectorSubtract (w->p[j], w->p[i], v1); + VectorSubtract (w->p[i], w->p[k], v2); + VectorNormalize(v1); + VectorNormalize(v2); + if (DotProduct(v1, v2) < 1.0-ON_EPSILON) + { + VectorCopy (w->p[i], p[nump]); + nump++; + } + } + + if (nump == w->numpoints) + return; + + c_removed += w->numpoints - nump; + w->numpoints = nump; + memcpy (w->p, p, nump*sizeof(p[0])); +} + +/* +============ +WindingPlane +============ +*/ +void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist) +{ + vec3_t v1, v2; + + VectorSubtract (w->p[1], w->p[0], v1); + VectorSubtract (w->p[2], w->p[0], v2); + CrossProduct (v2, v1, normal); + VectorNormalize (normal); + *dist = DotProduct (w->p[0], normal); + +} + +/* +============= +WindingArea +============= +*/ +vec_t WindingArea (winding_t *w) +{ + int i; + vec3_t d1, d2, cross; + vec_t total; + + total = 0; + for (i=2 ; inumpoints ; i++) + { + VectorSubtract (w->p[i-1], w->p[0], d1); + VectorSubtract (w->p[i], w->p[0], d2); + CrossProduct (d1, d2, cross); + total += 0.5 * VectorLength ( cross ); + } + return total; +} + +void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs) +{ + vec_t v; + int i,j; + + mins[0] = mins[1] = mins[2] = 99999; + maxs[0] = maxs[1] = maxs[2] = -99999; + + for (i=0 ; inumpoints ; i++) + { + for (j=0 ; j<3 ; j++) + { + v = w->p[i][j]; + if (v < mins[j]) + mins[j] = v; + if (v > maxs[j]) + maxs[j] = v; + } + } +} + +/* +============= +WindingCenter +============= +*/ +void WindingCenter (winding_t *w, vec3_t center) +{ + int i; + vec3_t d1, d2, cross; + float scale; + + VectorCopy (vec3_origin, center); + for (i=0 ; inumpoints ; i++) + VectorAdd (w->p[i], center, center); + + scale = 1.0/w->numpoints; + VectorScale (center, scale, center); +} + +/* +================= +BaseWindingForPlane +================= +*/ +winding_t *BaseWindingForPlane (vec3_t normal, float dist) +{ + int i, x; + vec_t max, v; + vec3_t org, vright, vup; + winding_t *w; + +// find the major axis + + max = -BOGUS_RANGE; + x = -1; + for (i=0 ; i<3; i++) + { + v = fabs(normal[i]); + if (v > max) + { + x = i; + max = v; + } + } + if (x==-1) + Error ("BaseWindingForPlane: no axis found"); + + VectorCopy (vec3_origin, vup); + switch (x) + { + case 0: + case 1: + vup[2] = 1; + break; + case 2: + vup[0] = 1; + break; + } + + v = DotProduct (vup, normal); + VectorMA (vup, -v, normal, vup); + VectorNormalize (vup); + + VectorScale (normal, dist, org); + + CrossProduct (vup, normal, vright); + + VectorScale (vup, 9000, vup); + VectorScale (vright, 9000, vright); + +// project a really big axis aligned box onto the plane + w = AllocWinding (4); + + VectorSubtract (org, vright, w->p[0]); + VectorAdd (w->p[0], vup, w->p[0]); + + VectorAdd (org, vright, w->p[1]); + VectorAdd (w->p[1], vup, w->p[1]); + + VectorAdd (org, vright, w->p[2]); + VectorSubtract (w->p[2], vup, w->p[2]); + + VectorSubtract (org, vright, w->p[3]); + VectorSubtract (w->p[3], vup, w->p[3]); + + w->numpoints = 4; + + return w; +} + +/* +================== +CopyWinding +================== +*/ +winding_t *CopyWinding (winding_t *w) +{ + int size; + winding_t *c; + + size = (int)((winding_t *)0)->p[w->numpoints]; + c = malloc (size); + memcpy (c, w, size); + return c; +} + + +/* +============= +ClipWinding +============= +*/ +void ClipWinding (winding_t *in, vec3_t normal, vec_t dist, + winding_t **front, winding_t **back) +{ + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *f, *b; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > ON_EPSILON) + sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = NULL; + + if (!counts[0]) + { + *back = CopyWinding (in); + return; + } + if (!counts[1]) + { + *front = CopyWinding (in); + return; + } + + maxpts = in->numpoints+4; // can't use counts[0]+2 because + // of fp grouping errors + + *front = f = AllocWinding (maxpts); + *back = b = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + if (sides[i] == SIDE_BACK) + { + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (mid, b->p[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); +} + + + +/* +============= +ClipWindingNoCopy +============= +*/ +void ClipWindingNoCopy (winding_t *in, vec3_t normal, vec_t dist, + winding_t **front, winding_t **back) +{ + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *f, *b; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > ON_EPSILON) + sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + *front = *back = NULL; + + if (!counts[0]) + { + *back = in; + return; + } + if (!counts[1]) + { + *front = in; + return; + } + + maxpts = in->numpoints+4; // can't use counts[0]+2 because + // of fp grouping errors + + *front = f = AllocWinding (maxpts); + *back = b = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + if (sides[i] == SIDE_BACK) + { + VectorCopy (p1, b->p[b->numpoints]); + b->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + VectorCopy (mid, b->p[b->numpoints]); + b->numpoints++; + } + + if (f->numpoints > maxpts || b->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); +} + + +/* +============= +ChopWindingNoFree +============= +*/ +winding_t *ChopWindingNoFree (winding_t *in, vec3_t normal, vec_t dist) +{ + vec_t dists[MAX_POINTS_ON_WINDING+4]; + int sides[MAX_POINTS_ON_WINDING+4]; + int counts[3]; + vec_t dot; + int i, j; + vec_t *p1, *p2; + vec3_t mid; + winding_t *f; + int maxpts; + + counts[0] = counts[1] = counts[2] = 0; + +// determine sides for each point + for (i=0 ; inumpoints ; i++) + { + dot = DotProduct (in->p[i], normal); + dot -= dist; + dists[i] = dot; + if (dot > ON_EPSILON) + sides[i] = SIDE_FRONT; + else if (dot < -ON_EPSILON) + sides[i] = SIDE_BACK; + else + { + sides[i] = SIDE_ON; + } + counts[sides[i]]++; + } + sides[i] = sides[0]; + dists[i] = dists[0]; + + if (!counts[0]) + return NULL; + if (!counts[1]) + return in; + + maxpts = in->numpoints+4; // can't use counts[0]+2 because + // of fp grouping errors + + f = AllocWinding (maxpts); + + for (i=0 ; inumpoints ; i++) + { + p1 = in->p[i]; + + if (sides[i] == SIDE_ON) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + continue; + } + + if (sides[i] == SIDE_FRONT) + { + VectorCopy (p1, f->p[f->numpoints]); + f->numpoints++; + } + + if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) + continue; + + // generate a split point + p2 = in->p[(i+1)%in->numpoints]; + + dot = dists[i] / (dists[i]-dists[i+1]); + for (j=0 ; j<3 ; j++) + { // avoid round off error when possible + if (normal[j] == 1) + mid[j] = dist; + else if (normal[j] == -1) + mid[j] = -dist; + else + mid[j] = p1[j] + dot*(p2[j]-p1[j]); + } + + VectorCopy (mid, f->p[f->numpoints]); + f->numpoints++; + } + + if (f->numpoints > maxpts) + Error ("ClipWinding: points exceeded estimate"); + if (f->numpoints > MAX_POINTS_ON_WINDING) + Error ("ClipWinding: MAX_POINTS_ON_WINDING"); + + return f; +} + + +/* +================= +ChopWinding + +Returns the fragment of in that is on the front side +of the cliping plane. The original is freed. +================= +*/ +winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist) +{ + winding_t *f, *b; + + ClipWinding (in, normal, dist, &f, &b); + FreeWinding (in); + if (b) + FreeWinding (b); + return f; +} + + +/* +================= +CheckWinding + +================= +*/ +void CheckWinding (winding_t *w) +{ + int i, j; + vec_t *p1, *p2; + vec_t d, edgedist; + vec3_t dir, edgenormal, facenormal; + vec_t area; + vec_t facedist; + + if (w->numpoints < 3) + Error ("CheckWinding: %i points",w->numpoints); + + area = WindingArea(w); + if (area < 1) + Error ("CheckWinding: %f area", area); + + WindingPlane (w, facenormal, &facedist); + + for (i=0 ; inumpoints ; i++) + { + p1 = w->p[i]; + + for (j=0 ; j<3 ; j++) + if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE) + Error ("CheckFace: BUGUS_RANGE: %f",p1[j]); + + j = i+1 == w->numpoints ? 0 : i+1; + + // check the point is on the face plane + d = DotProduct (p1, facenormal) - facedist; + if (d < -ON_EPSILON || d > ON_EPSILON) + Error ("CheckWinding: point off plane"); + + // check the edge isn't degenerate + p2 = w->p[j]; + VectorSubtract (p2, p1, dir); + + if (VectorLength (dir) < ON_EPSILON) + Error ("CheckWinding: degenerate edge"); + + CrossProduct (facenormal, dir, edgenormal); + VectorNormalize (edgenormal); + edgedist = DotProduct (p1, edgenormal); + edgedist += ON_EPSILON; + + // all other points must be on front side + for (j=0 ; jnumpoints ; j++) + { + if (j == i) + continue; + d = DotProduct (w->p[j], edgenormal); + if (d > edgedist) + Error ("CheckWinding: non-convex"); + } + } +} + + +/* +============ +WindingOnPlaneSide +============ +*/ +int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist) +{ + qboolean front, back; + int i; + vec_t d; + + front = false; + back = false; + for (i=0 ; inumpoints ; i++) + { + d = DotProduct (w->p[i], normal) - dist; + if (d < -ON_EPSILON) + { + if (front) + return SIDE_CROSS; + back = true; + continue; + } + if (d > ON_EPSILON) + { + if (back) + return SIDE_CROSS; + front = true; + continue; + } + } + + if (back) + return SIDE_BACK; + if (front) + return SIDE_FRONT; + return SIDE_ON; +} + diff --git a/utils/common/polylib.h b/utils/common/polylib.h index ed69f0b..b8ccff8 100644 --- a/utils/common/polylib.h +++ b/utils/common/polylib.h @@ -1,36 +1,36 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - - -typedef struct -{ - int numpoints; - vec3_t p[8]; // variable sized -} winding_t; - -#define MAX_POINTS_ON_WINDING 128 - -winding_t *AllocWinding (int points); -vec_t WindingArea (winding_t *w); -void WindingCenter (winding_t *w, vec3_t center); -void ClipWinding (winding_t *in, vec3_t normal, vec_t dist, - winding_t **front, winding_t **back); -void ClipWindingNoCopy (winding_t *in, vec3_t normal, vec_t dist, - winding_t **front, winding_t **back); -winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist); -winding_t *ChopWindingNoFree (winding_t *in, vec3_t normal, vec_t dist); -winding_t *CopyWinding (winding_t *w); -winding_t *BaseWindingForPlane (vec3_t normal, float dist); -void CheckWinding (winding_t *w); -void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist); -void RemoveColinearPoints (winding_t *w); -int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist); -void FreeWinding (winding_t *w); +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + + +typedef struct +{ + int numpoints; + vec3_t p[8]; // variable sized +} winding_t; + +#define MAX_POINTS_ON_WINDING 128 + +winding_t *AllocWinding (int points); +vec_t WindingArea (winding_t *w); +void WindingCenter (winding_t *w, vec3_t center); +void ClipWinding (winding_t *in, vec3_t normal, vec_t dist, + winding_t **front, winding_t **back); +void ClipWindingNoCopy (winding_t *in, vec3_t normal, vec_t dist, + winding_t **front, winding_t **back); +winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist); +winding_t *ChopWindingNoFree (winding_t *in, vec3_t normal, vec_t dist); +winding_t *CopyWinding (winding_t *w); +winding_t *BaseWindingForPlane (vec3_t normal, float dist); +void CheckWinding (winding_t *w); +void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist); +void RemoveColinearPoints (winding_t *w); +int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist); +void FreeWinding (winding_t *w); void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); \ No newline at end of file diff --git a/utils/common/scriplib.c b/utils/common/scriplib.c index c22476c..71bc0bd 100644 --- a/utils/common/scriplib.c +++ b/utils/common/scriplib.c @@ -1,268 +1,268 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// scriplib.c - -#include "cmdlib.h" -#include "scriplib.h" - -/* -============================================================================= - - PARSING STUFF - -============================================================================= -*/ - -typedef struct -{ - char filename[1024]; - char *buffer,*script_p,*end_p; - int line; -} script_t; - -#define MAX_INCLUDES 8 -script_t scriptstack[MAX_INCLUDES]; -script_t *script; -int scriptline; - -char token[MAXTOKEN]; -qboolean endofscript; -qboolean tokenready; // only true if UnGetToken was just called - -/* -============== -AddScriptToStack -============== -*/ -void AddScriptToStack (char *filename) -{ - int size; - - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - strcpy (script->filename, ExpandPath (filename) ); - - size = LoadFile (script->filename, (void **)&script->buffer); - - printf ("entering %s\n", script->filename); - - script->line = 1; - - script->script_p = script->buffer; - script->end_p = script->buffer + size; -} - - -/* -============== -LoadScriptFile -============== -*/ -void LoadScriptFile (char *filename) -{ - script = scriptstack; - AddScriptToStack (filename); - - endofscript = false; - tokenready = false; -} - - -/* -============== -ParseFromMemory -============== -*/ -void ParseFromMemory (char *buffer, int size) -{ - script = scriptstack; - script++; - if (script == &scriptstack[MAX_INCLUDES]) - Error ("script file exceeded MAX_INCLUDES"); - strcpy (script->filename, "memory buffer" ); - - script->buffer = buffer; - script->line = 1; - script->script_p = script->buffer; - script->end_p = script->buffer + size; - - endofscript = false; - tokenready = false; -} - - -/* -============== -UnGetToken - -Signals that the current token was not used, and should be reported -for the next GetToken. Note that - -GetToken (true); -UnGetToken (); -GetToken (false); - -could cross a line boundary. -============== -*/ -void UnGetToken (void) -{ - tokenready = true; -} - - -qboolean EndOfScript (qboolean crossline) -{ - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - - if (!strcmp (script->filename, "memory buffer")) - { - endofscript = true; - return false; - } - - free (script->buffer); - if (script == scriptstack+1) - { - endofscript = true; - return false; - } - script--; - scriptline = script->line; - printf ("returning to %s\n", script->filename); - return GetToken (crossline); -} - -/* -============== -GetToken -============== -*/ -qboolean GetToken (qboolean crossline) -{ - char *token_p; - - if (tokenready) // is a token allready waiting? - { - tokenready = false; - return true; - } - - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - -// -// skip space -// -skipspace: - while (*script->script_p <= 32) - { - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - if (*script->script_p++ == '\n') - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - scriptline = script->line++; - } - } - - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - - if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field - (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field - { - if (!crossline) - Error ("Line %i is incomplete\n",scriptline); - while (*script->script_p++ != '\n') - if (script->script_p >= script->end_p) - return EndOfScript (crossline); - goto skipspace; - } - -// -// copy token -// - token_p = token; - - if (*script->script_p == '"') - { - // quoted token - script->script_p++; - while (*script->script_p != '"') - { - *token_p++ = *script->script_p++; - if (script->script_p == script->end_p) - break; - if (token_p == &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - } - script->script_p++; - } - else // regular token - while ( *script->script_p > 32 && *script->script_p != ';') - { - *token_p++ = *script->script_p++; - if (script->script_p == script->end_p) - break; - if (token_p == &token[MAXTOKEN]) - Error ("Token too large on line %i\n",scriptline); - } - - *token_p = 0; - - if (!strcmp (token, "$include")) - { - GetToken (false); - AddScriptToStack (token); - return GetToken (crossline); - } - - return true; -} - - -/* -============== -TokenAvailable - -Returns true if there is another token on the line -============== -*/ -qboolean TokenAvailable (void) -{ - char *search_p; - - search_p = script->script_p; - - if (search_p >= script->end_p) - return false; - - while ( *search_p <= 32) - { - if (*search_p == '\n') - return false; - search_p++; - if (search_p == script->end_p) - return false; - - } - - if (*search_p == ';') - return false; - - return true; -} - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// scriplib.c + +#include "cmdlib.h" +#include "scriplib.h" + +/* +============================================================================= + + PARSING STUFF + +============================================================================= +*/ + +typedef struct +{ + char filename[1024]; + char *buffer,*script_p,*end_p; + int line; +} script_t; + +#define MAX_INCLUDES 8 +script_t scriptstack[MAX_INCLUDES]; +script_t *script; +int scriptline; + +char token[MAXTOKEN]; +qboolean endofscript; +qboolean tokenready; // only true if UnGetToken was just called + +/* +============== +AddScriptToStack +============== +*/ +void AddScriptToStack (char *filename) +{ + int size; + + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + strcpy (script->filename, ExpandPath (filename) ); + + size = LoadFile (script->filename, (void **)&script->buffer); + + printf ("entering %s\n", script->filename); + + script->line = 1; + + script->script_p = script->buffer; + script->end_p = script->buffer + size; +} + + +/* +============== +LoadScriptFile +============== +*/ +void LoadScriptFile (char *filename) +{ + script = scriptstack; + AddScriptToStack (filename); + + endofscript = false; + tokenready = false; +} + + +/* +============== +ParseFromMemory +============== +*/ +void ParseFromMemory (char *buffer, int size) +{ + script = scriptstack; + script++; + if (script == &scriptstack[MAX_INCLUDES]) + Error ("script file exceeded MAX_INCLUDES"); + strcpy (script->filename, "memory buffer" ); + + script->buffer = buffer; + script->line = 1; + script->script_p = script->buffer; + script->end_p = script->buffer + size; + + endofscript = false; + tokenready = false; +} + + +/* +============== +UnGetToken + +Signals that the current token was not used, and should be reported +for the next GetToken. Note that + +GetToken (true); +UnGetToken (); +GetToken (false); + +could cross a line boundary. +============== +*/ +void UnGetToken (void) +{ + tokenready = true; +} + + +qboolean EndOfScript (qboolean crossline) +{ + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + + if (!strcmp (script->filename, "memory buffer")) + { + endofscript = true; + return false; + } + + free (script->buffer); + if (script == scriptstack+1) + { + endofscript = true; + return false; + } + script--; + scriptline = script->line; + printf ("returning to %s\n", script->filename); + return GetToken (crossline); +} + +/* +============== +GetToken +============== +*/ +qboolean GetToken (qboolean crossline) +{ + char *token_p; + + if (tokenready) // is a token allready waiting? + { + tokenready = false; + return true; + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + +// +// skip space +// +skipspace: + while (*script->script_p <= 32) + { + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + if (*script->script_p++ == '\n') + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + scriptline = script->line++; + } + } + + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + + if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field + (*script->script_p == '/' && *((script->script_p)+1) == '/')) // also make // a comment field + { + if (!crossline) + Error ("Line %i is incomplete\n",scriptline); + while (*script->script_p++ != '\n') + if (script->script_p >= script->end_p) + return EndOfScript (crossline); + goto skipspace; + } + +// +// copy token +// + token_p = token; + + if (*script->script_p == '"') + { + // quoted token + script->script_p++; + while (*script->script_p != '"') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + script->script_p++; + } + else // regular token + while ( *script->script_p > 32 && *script->script_p != ';') + { + *token_p++ = *script->script_p++; + if (script->script_p == script->end_p) + break; + if (token_p == &token[MAXTOKEN]) + Error ("Token too large on line %i\n",scriptline); + } + + *token_p = 0; + + if (!strcmp (token, "$include")) + { + GetToken (false); + AddScriptToStack (token); + return GetToken (crossline); + } + + return true; +} + + +/* +============== +TokenAvailable + +Returns true if there is another token on the line +============== +*/ +qboolean TokenAvailable (void) +{ + char *search_p; + + search_p = script->script_p; + + if (search_p >= script->end_p) + return false; + + while ( *search_p <= 32) + { + if (*search_p == '\n') + return false; + search_p++; + if (search_p == script->end_p) + return false; + + } + + if (*search_p == ';') + return false; + + return true; +} + + diff --git a/utils/common/scriplib.h b/utils/common/scriplib.h index 0a6f56d..d228d01 100644 --- a/utils/common/scriplib.h +++ b/utils/common/scriplib.h @@ -1,33 +1,33 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// scriplib.h - -#ifndef __CMDLIB__ -#include "cmdlib.h" -#endif - -#define MAXTOKEN 512 - -extern char token[MAXTOKEN]; -extern char *scriptbuffer,*script_p,*scriptend_p; -extern int grabbed; -extern int scriptline; -extern qboolean endofscript; - - -void LoadScriptFile (char *filename); -void ParseFromMemory (char *buffer, int size); - -qboolean GetToken (qboolean crossline); -void UnGetToken (void); -qboolean TokenAvailable (void); - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// scriplib.h + +#ifndef __CMDLIB__ +#include "cmdlib.h" +#endif + +#define MAXTOKEN 512 + +extern char token[MAXTOKEN]; +extern char *scriptbuffer,*script_p,*scriptend_p; +extern int grabbed; +extern int scriptline; +extern qboolean endofscript; + + +void LoadScriptFile (char *filename); +void ParseFromMemory (char *buffer, int size); + +qboolean GetToken (qboolean crossline); +void UnGetToken (void); +qboolean TokenAvailable (void); + + diff --git a/utils/common/threads.c b/utils/common/threads.c index acda957..51d657a 100644 --- a/utils/common/threads.c +++ b/utils/common/threads.c @@ -1,330 +1,330 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -#include "cmdlib.h" -#define NO_THREAD_NAMES -#include "threads.h" - -#define MAX_THREADS 64 - -int dispatch; -int workcount; -int oldf; -qboolean pacifier; - -qboolean threaded; - -/* -============= -GetThreadWork - -============= -*/ -int GetThreadWork (void) -{ - int r; - int f; - - ThreadLock (); - - if (dispatch == workcount) - { - ThreadUnlock (); - return -1; - } - - f = 10*dispatch / workcount; - if (f != oldf) - { - oldf = f; - if (pacifier) - printf ("%i...", f); - } - - r = dispatch; - dispatch++; - ThreadUnlock (); - - return r; -} - - -void (*workfunction) (int); - -void ThreadWorkerFunction (int threadnum) -{ - int work; - - while (1) - { - work = GetThreadWork (); - if (work == -1) - break; - workfunction(work); - } -} - -void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - workfunction = func; - RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); -} - - -/* -=================================================================== - -WIN32 - -=================================================================== -*/ -#ifdef WIN32 - -#define USED - -#include - -int numthreads = -1; -CRITICAL_SECTION crit; -static int enter; - -void ThreadSetDefault (void) -{ - SYSTEM_INFO info; - - if (numthreads == -1) // not set manually - { - GetSystemInfo (&info); - numthreads = info.dwNumberOfProcessors; - if (numthreads < 1 || numthreads > 32) - numthreads = 1; - } - - qprintf ("%i threads\n", numthreads); -} - - -void ThreadLock (void) -{ - if (!threaded) - return; - EnterCriticalSection (&crit); - if (enter) - Error ("Recursive ThreadLock\n"); - enter = 1; -} - -void ThreadUnlock (void) -{ - if (!threaded) - return; - if (!enter) - Error ("ThreadUnlock without lock\n"); - enter = 0; - LeaveCriticalSection (&crit); -} - -/* -============= -RunThreadsOn -============= -*/ -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int threadid[MAX_THREADS]; - HANDLE threadhandle[MAX_THREADS]; - int i; - int start, end; - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = true; - // - // run threads in parallel - // - InitializeCriticalSection (&crit); - for (i=0 ; i - -pthread_mutex_t *my_mutex; - -void ThreadLock (void) -{ - if (my_mutex) - pthread_mutex_lock (my_mutex); -} - -void ThreadUnlock (void) -{ - if (my_mutex) - pthread_mutex_unlock (my_mutex); -} - - -/* -============= -RunThreadsOn -============= -*/ -void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) -{ - int i; - pthread_t work_threads[MAX_THREADS]; - pthread_addr_t status; - pthread_attr_t attrib; - pthread_mutexattr_t mattrib; - int start, end; - - start = I_FloatTime (); - dispatch = 0; - workcount = workcnt; - oldf = -1; - pacifier = showpacifier; - threaded = true; - - if (pacifier) - setbuf (stdout, NULL); - - if (!my_mutex) - { - my_mutex = malloc (sizeof(*my_mutex)); - if (pthread_mutexattr_create (&mattrib) == -1) - Error ("pthread_mutex_attr_create failed"); - if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) - Error ("pthread_mutexattr_setkind_np failed"); - if (pthread_mutex_init (my_mutex, mattrib) == -1) - Error ("pthread_mutex_init failed"); - } - - if (pthread_attr_create (&attrib) == -1) - Error ("pthread_attr_create failed"); - if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) - Error ("pthread_attr_setstacksize failed"); - - for (i=0 ; i + +int numthreads = -1; +CRITICAL_SECTION crit; +static int enter; + +void ThreadSetDefault (void) +{ + SYSTEM_INFO info; + + if (numthreads == -1) // not set manually + { + GetSystemInfo (&info); + numthreads = info.dwNumberOfProcessors; + if (numthreads < 1 || numthreads > 32) + numthreads = 1; + } + + qprintf ("%i threads\n", numthreads); +} + + +void ThreadLock (void) +{ + if (!threaded) + return; + EnterCriticalSection (&crit); + if (enter) + Error ("Recursive ThreadLock\n"); + enter = 1; +} + +void ThreadUnlock (void) +{ + if (!threaded) + return; + if (!enter) + Error ("ThreadUnlock without lock\n"); + enter = 0; + LeaveCriticalSection (&crit); +} + +/* +============= +RunThreadsOn +============= +*/ +void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int threadid[MAX_THREADS]; + HANDLE threadhandle[MAX_THREADS]; + int i; + int start, end; + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + // + // run threads in parallel + // + InitializeCriticalSection (&crit); + for (i=0 ; i + +pthread_mutex_t *my_mutex; + +void ThreadLock (void) +{ + if (my_mutex) + pthread_mutex_lock (my_mutex); +} + +void ThreadUnlock (void) +{ + if (my_mutex) + pthread_mutex_unlock (my_mutex); +} + + +/* +============= +RunThreadsOn +============= +*/ +void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int)) +{ + int i; + pthread_t work_threads[MAX_THREADS]; + pthread_addr_t status; + pthread_attr_t attrib; + pthread_mutexattr_t mattrib; + int start, end; + + start = I_FloatTime (); + dispatch = 0; + workcount = workcnt; + oldf = -1; + pacifier = showpacifier; + threaded = true; + + if (pacifier) + setbuf (stdout, NULL); + + if (!my_mutex) + { + my_mutex = malloc (sizeof(*my_mutex)); + if (pthread_mutexattr_create (&mattrib) == -1) + Error ("pthread_mutex_attr_create failed"); + if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1) + Error ("pthread_mutexattr_setkind_np failed"); + if (pthread_mutex_init (my_mutex, mattrib) == -1) + Error ("pthread_mutex_init failed"); + } + + if (pthread_attr_create (&attrib) == -1) + Error ("pthread_attr_create failed"); + if (pthread_attr_setstacksize (&attrib, 0x100000) == -1) + Error ("pthread_attr_setstacksize failed"); + + for (i=0 ; i -#include "cmdlib.h" -#include "mathlib.h" -#include "trilib.h" - -// on disk representation of a face - - -#define FLOAT_START 99999.0 -#define FLOAT_END -FLOAT_START -#define MAGIC 123322 - -//#define NOISY 1 - -typedef struct { - float v[3]; -} vector; - -typedef struct -{ - vector n; /* normal */ - vector p; /* point */ - vector c; /* color */ - float u; /* u */ - float v; /* v */ -} aliaspoint_t; - -typedef struct { - aliaspoint_t pt[3]; -} tf_triangle; - - -void ByteSwapTri (tf_triangle *tri) -{ - int i; - - for (i=0 ; iverts[j][k] = tri.pt[j].p.v[k]; - } - } - - ptri++; - - if ((ptri - *pptri) >= MAXTRIANGLES) - Error ("Error: too many triangles; increase MAXTRIANGLES\n"); - } - } - - *numtriangles = ptri - *pptri; - - fclose (input); -} - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// +// trilib.c: library for loading triangles from an Alias triangle file +// + +#include +#include "cmdlib.h" +#include "mathlib.h" +#include "trilib.h" + +// on disk representation of a face + + +#define FLOAT_START 99999.0 +#define FLOAT_END -FLOAT_START +#define MAGIC 123322 + +//#define NOISY 1 + +typedef struct { + float v[3]; +} vector; + +typedef struct +{ + vector n; /* normal */ + vector p; /* point */ + vector c; /* color */ + float u; /* u */ + float v; /* v */ +} aliaspoint_t; + +typedef struct { + aliaspoint_t pt[3]; +} tf_triangle; + + +void ByteSwapTri (tf_triangle *tri) +{ + int i; + + for (i=0 ; iverts[j][k] = tri.pt[j].p.v[k]; + } + } + + ptri++; + + if ((ptri - *pptri) >= MAXTRIANGLES) + Error ("Error: too many triangles; increase MAXTRIANGLES\n"); + } + } + + *numtriangles = ptri - *pptri; + + fclose (input); +} + diff --git a/utils/common/trilib.h b/utils/common/trilib.h index 0927166..2840c68 100644 --- a/utils/common/trilib.h +++ b/utils/common/trilib.h @@ -1,21 +1,21 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// -// trilib.h: header file for loading triangles from an Alias triangle file -// -#define MAXTRIANGLES 2048 - -typedef struct { - vec3_t verts[3]; -} triangle_t; - -void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles); - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// +// trilib.h: header file for loading triangles from an Alias triangle file +// +#define MAXTRIANGLES 2048 + +typedef struct { + vec3_t verts[3]; +} triangle_t; + +void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles); + diff --git a/utils/common/wadlib.c b/utils/common/wadlib.c index 19faf60..88b71fb 100644 --- a/utils/common/wadlib.c +++ b/utils/common/wadlib.c @@ -1,339 +1,339 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// wad2lib.c - -#include -#include -#include -#include -#include -#include -#include -//#include -#include - -#ifdef NeXT -#include -#endif -#include "cmdlib.h" -#include "wadlib.h" - -/* -============================================================================ - - WAD READING - -============================================================================ -*/ - - -lumpinfo_t *lumpinfo; // location of each lump on disk -int numlumps; - -wadinfo_t header; -FILE *wadhandle; - - -/* -==================== -W_OpenWad -==================== -*/ -void W_OpenWad (char *filename) -{ - lumpinfo_t *lump_p; - unsigned i; - int length; - -// -// open the file and add to directory -// - wadhandle = SafeOpenRead (filename); - SafeRead (wadhandle, &header, sizeof(header)); - - if (strncmp(header.identification,"WAD2",4) && - strncmp(header.identification, "WAD3", 4)) - Error ("Wad file %s doesn't have WAD2/WAD3 id\n",filename); - - header.numlumps = LittleLong(header.numlumps); - header.infotableofs = LittleLong(header.infotableofs); - - numlumps = header.numlumps; - - length = numlumps*sizeof(lumpinfo_t); - lumpinfo = malloc (length); - lump_p = lumpinfo; - - fseek (wadhandle, header.infotableofs, SEEK_SET); - SafeRead (wadhandle, lumpinfo, length); - -// -// Fill in lumpinfo -// - - for (i=0 ; ifilepos = LittleLong(lump_p->filepos); - lump_p->size = LittleLong(lump_p->size); - } -} - - - -void CleanupName (char *in, char *out) -{ - int i; - - for (i=0 ; iname ) ; i++ ) - { - if (!in[i]) - break; - - out[i] = toupper(in[i]); - } - - for ( ; iname ); i++ ) - out[i] = 0; -} - - -/* -==================== -W_CheckNumForName - -Returns -1 if name not found -==================== -*/ -int W_CheckNumForName (char *name) -{ - char cleanname[16]; - int v1,v2, v3, v4; - int i; - lumpinfo_t *lump_p; - - CleanupName (name, cleanname); - -// make the name into four integers for easy compares - - v1 = *(int *)cleanname; - v2 = *(int *)&cleanname[4]; - v3 = *(int *)&cleanname[8]; - v4 = *(int *)&cleanname[12]; - -// find it - - lump_p = lumpinfo; - for (i=0 ; iname == v1 - && *(int *)&lump_p->name[4] == v2 - && *(int *)&lump_p->name[8] == v3 - && *(int *)&lump_p->name[12] == v4) - return i; - } - - return -1; -} - - -/* -==================== -W_GetNumForName - -Calls W_CheckNumForName, but bombs out if not found -==================== -*/ -int W_GetNumForName (char *name) -{ - int i; - - i = W_CheckNumForName (name); - if (i != -1) - return i; - - Error ("W_GetNumForName: %s not found!",name); - return -1; -} - - -/* -==================== -W_LumpLength - -Returns the buffer size needed to load the given lump -==================== -*/ -int W_LumpLength (int lump) -{ - if (lump >= numlumps) - Error ("W_LumpLength: %i >= numlumps",lump); - return lumpinfo[lump].size; -} - - -/* -==================== -W_ReadLumpNum - -Loads the lump into the given buffer, which must be >= W_LumpLength() -==================== -*/ -void W_ReadLumpNum (int lump, void *dest) -{ - lumpinfo_t *l; - - if (lump >= numlumps) - Error ("W_ReadLump: %i >= numlumps",lump); - l = lumpinfo+lump; - - fseek (wadhandle, l->filepos, SEEK_SET); - SafeRead (wadhandle, dest, l->size); -} - - - -/* -==================== -W_LoadLumpNum -==================== -*/ -void *W_LoadLumpNum (int lump) -{ - void *buf; - - if ((unsigned)lump >= numlumps) - Error ("W_CacheLumpNum: %i >= numlumps",lump); - - buf = malloc (W_LumpLength (lump)); - W_ReadLumpNum (lump, buf); - - return buf; -} - - -/* -==================== -W_LoadLumpName -==================== -*/ -void *W_LoadLumpName (char *name) -{ - return W_LoadLumpNum (W_GetNumForName(name)); -} - - -/* -=============================================================================== - - WAD CREATION - -=============================================================================== -*/ - -FILE *outwad; - -lumpinfo_t outinfo[4096]; -int outlumps; - -short (*wadshort) (short l); -int (*wadlong) (int l); - -/* -=============== -NewWad -=============== -*/ - -void NewWad (char *pathname, qboolean bigendien) -{ - outwad = SafeOpenWrite (pathname); - fseek (outwad, sizeof(wadinfo_t), SEEK_SET); - memset (outinfo, 0, sizeof(outinfo)); - - if (bigendien) - { - wadshort = BigShort; - wadlong = BigLong; - } - else - { - wadshort = LittleShort; - wadlong = LittleLong; - } - - outlumps = 0; -} - - -/* -=============== -AddLump -=============== -*/ - -void AddLump (char *name, void *buffer, int length, int type, int compress) -{ - lumpinfo_t *info; - int ofs; - - info = &outinfo[outlumps]; - outlumps++; - - memset (info,0,sizeof(info)); - - strcpy (info->name, name); - strupr (info->name); - - ofs = ftell(outwad); - info->filepos = wadlong(ofs); - info->size = info->disksize = wadlong(length); - info->type = type; - info->compression = compress; - -// FIXME: do compression - - SafeWrite (outwad, buffer, length); -} - - -/* -=============== -WriteWad -=============== -*/ - -void WriteWad (int wad3) -{ - wadinfo_t header; - int ofs; - -// write the lumpingo - ofs = ftell(outwad); - - SafeWrite (outwad, outinfo, outlumps*sizeof(lumpinfo_t) ); - -// write the header - -// a program will be able to tell the ednieness of a wad by the id - header.identification[0] = 'W'; - header.identification[1] = 'A'; - header.identification[2] = 'D'; - header.identification[3] = wad3 ? '3' : '2'; - - header.numlumps = wadlong(outlumps); - header.infotableofs = wadlong(ofs); - - fseek (outwad, 0, SEEK_SET); - SafeWrite (outwad, &header, sizeof(header)); - fclose (outwad); -} - - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// wad2lib.c + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#ifdef NeXT +#include +#endif +#include "cmdlib.h" +#include "wadlib.h" + +/* +============================================================================ + + WAD READING + +============================================================================ +*/ + + +lumpinfo_t *lumpinfo; // location of each lump on disk +int numlumps; + +wadinfo_t header; +FILE *wadhandle; + + +/* +==================== +W_OpenWad +==================== +*/ +void W_OpenWad (char *filename) +{ + lumpinfo_t *lump_p; + unsigned i; + int length; + +// +// open the file and add to directory +// + wadhandle = SafeOpenRead (filename); + SafeRead (wadhandle, &header, sizeof(header)); + + if (strncmp(header.identification,"WAD2",4) && + strncmp(header.identification, "WAD3", 4)) + Error ("Wad file %s doesn't have WAD2/WAD3 id\n",filename); + + header.numlumps = LittleLong(header.numlumps); + header.infotableofs = LittleLong(header.infotableofs); + + numlumps = header.numlumps; + + length = numlumps*sizeof(lumpinfo_t); + lumpinfo = malloc (length); + lump_p = lumpinfo; + + fseek (wadhandle, header.infotableofs, SEEK_SET); + SafeRead (wadhandle, lumpinfo, length); + +// +// Fill in lumpinfo +// + + for (i=0 ; ifilepos = LittleLong(lump_p->filepos); + lump_p->size = LittleLong(lump_p->size); + } +} + + + +void CleanupName (char *in, char *out) +{ + int i; + + for (i=0 ; iname ) ; i++ ) + { + if (!in[i]) + break; + + out[i] = toupper(in[i]); + } + + for ( ; iname ); i++ ) + out[i] = 0; +} + + +/* +==================== +W_CheckNumForName + +Returns -1 if name not found +==================== +*/ +int W_CheckNumForName (char *name) +{ + char cleanname[16]; + int v1,v2, v3, v4; + int i; + lumpinfo_t *lump_p; + + CleanupName (name, cleanname); + +// make the name into four integers for easy compares + + v1 = *(int *)cleanname; + v2 = *(int *)&cleanname[4]; + v3 = *(int *)&cleanname[8]; + v4 = *(int *)&cleanname[12]; + +// find it + + lump_p = lumpinfo; + for (i=0 ; iname == v1 + && *(int *)&lump_p->name[4] == v2 + && *(int *)&lump_p->name[8] == v3 + && *(int *)&lump_p->name[12] == v4) + return i; + } + + return -1; +} + + +/* +==================== +W_GetNumForName + +Calls W_CheckNumForName, but bombs out if not found +==================== +*/ +int W_GetNumForName (char *name) +{ + int i; + + i = W_CheckNumForName (name); + if (i != -1) + return i; + + Error ("W_GetNumForName: %s not found!",name); + return -1; +} + + +/* +==================== +W_LumpLength + +Returns the buffer size needed to load the given lump +==================== +*/ +int W_LumpLength (int lump) +{ + if (lump >= numlumps) + Error ("W_LumpLength: %i >= numlumps",lump); + return lumpinfo[lump].size; +} + + +/* +==================== +W_ReadLumpNum + +Loads the lump into the given buffer, which must be >= W_LumpLength() +==================== +*/ +void W_ReadLumpNum (int lump, void *dest) +{ + lumpinfo_t *l; + + if (lump >= numlumps) + Error ("W_ReadLump: %i >= numlumps",lump); + l = lumpinfo+lump; + + fseek (wadhandle, l->filepos, SEEK_SET); + SafeRead (wadhandle, dest, l->size); +} + + + +/* +==================== +W_LoadLumpNum +==================== +*/ +void *W_LoadLumpNum (int lump) +{ + void *buf; + + if ((unsigned)lump >= numlumps) + Error ("W_CacheLumpNum: %i >= numlumps",lump); + + buf = malloc (W_LumpLength (lump)); + W_ReadLumpNum (lump, buf); + + return buf; +} + + +/* +==================== +W_LoadLumpName +==================== +*/ +void *W_LoadLumpName (char *name) +{ + return W_LoadLumpNum (W_GetNumForName(name)); +} + + +/* +=============================================================================== + + WAD CREATION + +=============================================================================== +*/ + +FILE *outwad; + +lumpinfo_t outinfo[4096]; +int outlumps; + +short (*wadshort) (short l); +int (*wadlong) (int l); + +/* +=============== +NewWad +=============== +*/ + +void NewWad (char *pathname, qboolean bigendien) +{ + outwad = SafeOpenWrite (pathname); + fseek (outwad, sizeof(wadinfo_t), SEEK_SET); + memset (outinfo, 0, sizeof(outinfo)); + + if (bigendien) + { + wadshort = BigShort; + wadlong = BigLong; + } + else + { + wadshort = LittleShort; + wadlong = LittleLong; + } + + outlumps = 0; +} + + +/* +=============== +AddLump +=============== +*/ + +void AddLump (char *name, void *buffer, int length, int type, int compress) +{ + lumpinfo_t *info; + int ofs; + + info = &outinfo[outlumps]; + outlumps++; + + memset (info,0,sizeof(info)); + + strcpy (info->name, name); + strupr (info->name); + + ofs = ftell(outwad); + info->filepos = wadlong(ofs); + info->size = info->disksize = wadlong(length); + info->type = type; + info->compression = compress; + +// FIXME: do compression + + SafeWrite (outwad, buffer, length); +} + + +/* +=============== +WriteWad +=============== +*/ + +void WriteWad (int wad3) +{ + wadinfo_t header; + int ofs; + +// write the lumpingo + ofs = ftell(outwad); + + SafeWrite (outwad, outinfo, outlumps*sizeof(lumpinfo_t) ); + +// write the header + +// a program will be able to tell the ednieness of a wad by the id + header.identification[0] = 'W'; + header.identification[1] = 'A'; + header.identification[2] = 'D'; + header.identification[3] = wad3 ? '3' : '2'; + + header.numlumps = wadlong(outlumps); + header.infotableofs = wadlong(ofs); + + fseek (outwad, 0, SEEK_SET); + SafeWrite (outwad, &header, sizeof(header)); + fclose (outwad); +} + + diff --git a/utils/common/wadlib.h b/utils/common/wadlib.h index 5b83618..64b6a7d 100644 --- a/utils/common/wadlib.h +++ b/utils/common/wadlib.h @@ -1,63 +1,63 @@ -/*** -* -* Copyright (c) 1996-2002, Valve LLC. All rights reserved. -* -* This product contains software technology licensed from Id -* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. -* All Rights Reserved. -* -****/ - -// wadlib.h - -// -// wad reading -// - -#define CMP_NONE 0 -#define CMP_LZSS 1 - -#define TYP_NONE 0 -#define TYP_LABEL 1 -#define TYP_LUMPY 64 // 64 + grab command number - -typedef struct -{ - char identification[4]; // should be WAD2 or 2DAW - int numlumps; - int infotableofs; -} wadinfo_t; - - -typedef struct -{ - int filepos; - int disksize; - int size; // uncompressed - char type; - char compression; - char pad1, pad2; - char name[16]; // must be null terminated -} lumpinfo_t; - -extern lumpinfo_t *lumpinfo; // location of each lump on disk -extern int numlumps; -extern wadinfo_t header; - -void W_OpenWad (char *filename); -int W_CheckNumForName (char *name); -int W_GetNumForName (char *name); -int W_LumpLength (int lump); -void W_ReadLumpNum (int lump, void *dest); -void *W_LoadLumpNum (int lump); -void *W_LoadLumpName (char *name); - -void CleanupName (char *in, char *out); - -// -// wad creation -// -void NewWad (char *pathname, qboolean bigendien); -void AddLump (char *name, void *buffer, int length, int type, int compress); -void WriteWad (int wad3); - +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +****/ + +// wadlib.h + +// +// wad reading +// + +#define CMP_NONE 0 +#define CMP_LZSS 1 + +#define TYP_NONE 0 +#define TYP_LABEL 1 +#define TYP_LUMPY 64 // 64 + grab command number + +typedef struct +{ + char identification[4]; // should be WAD2 or 2DAW + int numlumps; + int infotableofs; +} wadinfo_t; + + +typedef struct +{ + int filepos; + int disksize; + int size; // uncompressed + char type; + char compression; + char pad1, pad2; + char name[16]; // must be null terminated +} lumpinfo_t; + +extern lumpinfo_t *lumpinfo; // location of each lump on disk +extern int numlumps; +extern wadinfo_t header; + +void W_OpenWad (char *filename); +int W_CheckNumForName (char *name); +int W_GetNumForName (char *name); +int W_LumpLength (int lump); +void W_ReadLumpNum (int lump, void *dest); +void *W_LoadLumpNum (int lump); +void *W_LoadLumpName (char *name); + +void CleanupName (char *in, char *out); + +// +// wad creation +// +void NewWad (char *pathname, qboolean bigendien); +void AddLump (char *name, void *buffer, int length, int type, int compress); +void WriteWad (int wad3); +