Browse Source

initial seed of Half-Life 1 SDK

master
Alfred Reynolds 8 years ago
parent
commit
de70fada50
100 changed files with 37536 additions and 0 deletions
  1. +117
    -0
      cl_dll/Exports.h
  2. +121
    -0
      cl_dll/GameStudioModelRenderer.cpp
  3. +26
    -0
      cl_dll/GameStudioModelRenderer.h
  4. +992
    -0
      cl_dll/GameStudioModelRenderer_Sample.cpp
  5. +55
    -0
      cl_dll/GameStudioModelRenderer_Sample.h
  6. +155
    -0
      cl_dll/MOTD.cpp
  7. +2114
    -0
      cl_dll/StudioModelRenderer.cpp
  8. +189
    -0
      cl_dll/StudioModelRenderer.h
  9. +1200
    -0
      cl_dll/ammo.cpp
  10. +62
    -0
      cl_dll/ammo.h
  11. +159
    -0
      cl_dll/ammo_secondary.cpp
  12. +190
    -0
      cl_dll/ammohistory.cpp
  13. +143
    -0
      cl_dll/ammohistory.h
  14. +158
    -0
      cl_dll/battery.cpp
  15. +26
    -0
      cl_dll/bench.h
  16. +24
    -0
      cl_dll/camera.h
  17. +445
    -0
      cl_dll/cdll_int.cpp
  18. +648
    -0
      cl_dll/cl_dll.dsp
  19. +43
    -0
      cl_dll/cl_dll.h
  20. +196
    -0
      cl_dll/cl_util.h
  21. +277
    -0
      cl_dll/com_weapons.cpp
  22. +44
    -0
      cl_dll/com_weapons.h
  23. +304
    -0
      cl_dll/death.cpp
  24. +99
    -0
      cl_dll/demo.cpp
  25. +27
    -0
      cl_dll/demo.h
  26. +785
    -0
      cl_dll/entity.cpp
  27. +205
    -0
      cl_dll/ev_common.cpp
  28. +1704
    -0
      cl_dll/ev_hldm.cpp
  29. +95
    -0
      cl_dll/ev_hldm.h
  30. +23
    -0
      cl_dll/events.cpp
  31. +73
    -0
      cl_dll/eventscripts.h
  32. +149
    -0
      cl_dll/flashlight.cpp
  33. +184
    -0
      cl_dll/geiger.cpp
  34. +30
    -0
      cl_dll/global_consts.h
  35. +473
    -0
      cl_dll/health.cpp
  36. +127
    -0
      cl_dll/health.h
  37. +348
    -0
      cl_dll/hl/hl_baseentity.cpp
  38. +80
    -0
      cl_dll/hl/hl_events.cpp
  39. +90
    -0
      cl_dll/hl/hl_objects.cpp
  40. +1081
    -0
      cl_dll/hl/hl_weapons.cpp
  41. +698
    -0
      cl_dll/hud.cpp
  42. +658
    -0
      cl_dll/hud.h
  43. +1129
    -0
      cl_dll/hud_bench.cpp
  44. +234
    -0
      cl_dll/hud_benchtrace.cpp
  45. +8
    -0
      cl_dll/hud_benchtrace.h
  46. +17
    -0
      cl_dll/hud_iface.h
  47. +141
    -0
      cl_dll/hud_msg.cpp
  48. +346
    -0
      cl_dll/hud_redraw.cpp
  49. +1234
    -0
      cl_dll/hud_servers.cpp
  50. +41
    -0
      cl_dll/hud_servers.h
  51. +98
    -0
      cl_dll/hud_servers_priv.h
  52. +1981
    -0
      cl_dll/hud_spectator.cpp
  53. +156
    -0
      cl_dll/hud_spectator.h
  54. +54
    -0
      cl_dll/hud_update.cpp
  55. +631
    -0
      cl_dll/in_camera.cpp
  56. +20
    -0
      cl_dll/in_defs.h
  57. +1041
    -0
      cl_dll/input.cpp
  58. +1114
    -0
      cl_dll/inputw32.cpp
  59. +222
    -0
      cl_dll/interpolation.cpp
  60. +56
    -0
      cl_dll/interpolation.h
  61. +18
    -0
      cl_dll/kbutton.h
  62. +283
    -0
      cl_dll/menu.cpp
  63. +536
    -0
      cl_dll/message.cpp
  64. +160
    -0
      cl_dll/overview.cpp
  65. +31
    -0
      cl_dll/overview.h
  66. +20
    -0
      cl_dll/player_info.h
  67. +107
    -0
      cl_dll/readme.txt
  68. +326
    -0
      cl_dll/saytext.cpp
  69. +586
    -0
      cl_dll/scoreboard.cpp
  70. +162
    -0
      cl_dll/soundsystem.cpp
  71. +163
    -0
      cl_dll/status_icons.cpp
  72. +265
    -0
      cl_dll/statusbar.cpp
  73. +251
    -0
      cl_dll/studio_util.cpp
  74. +40
    -0
      cl_dll/studio_util.h
  75. +214
    -0
      cl_dll/text_message.cpp
  76. +1389
    -0
      cl_dll/tf_defs.h
  77. +85
    -0
      cl_dll/train.cpp
  78. +60
    -0
      cl_dll/tri.cpp
  79. +13
    -0
      cl_dll/tri.h
  80. +133
    -0
      cl_dll/util.cpp
  81. +125
    -0
      cl_dll/util_vector.h
  82. +437
    -0
      cl_dll/vgui_ClassMenu.cpp
  83. +101
    -0
      cl_dll/vgui_ConsolePanel.cpp
  84. +38
    -0
      cl_dll/vgui_ConsolePanel.h
  85. +212
    -0
      cl_dll/vgui_ControlConfigPanel.cpp
  86. +47
    -0
      cl_dll/vgui_ControlConfigPanel.h
  87. +547
    -0
      cl_dll/vgui_CustomObjects.cpp
  88. +154
    -0
      cl_dll/vgui_MOTDWindow.cpp
  89. +556
    -0
      cl_dll/vgui_SchemeManager.cpp
  90. +54
    -0
      cl_dll/vgui_SchemeManager.h
  91. +1151
    -0
      cl_dll/vgui_ScorePanel.cpp
  92. +310
    -0
      cl_dll/vgui_ScorePanel.h
  93. +623
    -0
      cl_dll/vgui_ServerBrowser.cpp
  94. +50
    -0
      cl_dll/vgui_ServerBrowser.h
  95. +426
    -0
      cl_dll/vgui_SpectatorPanel.cpp
  96. +112
    -0
      cl_dll/vgui_SpectatorPanel.h
  97. +2644
    -0
      cl_dll/vgui_TeamFortressViewport.cpp
  98. +1818
    -0
      cl_dll/vgui_TeamFortressViewport.h
  99. +128
    -0
      cl_dll/vgui_int.cpp
  100. +21
    -0
      cl_dll/vgui_int.h

+ 117
- 0
cl_dll/Exports.h View File

@@ -0,0 +1,117 @@
// CL_DLLEXPORT is the client version of dllexport. It's turned off for secure clients.
#ifdef _WIN32
#define CL_DLLEXPORT __declspec(dllexport)
#else
#define CL_DLLEXPORT __attribute__ ((visibility("default")))
#endif

extern "C"
{
// From hl_weapons
void CL_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 );

// From cdll_int
int CL_DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion );
int CL_DLLEXPORT HUD_VidInit( void );
void CL_DLLEXPORT HUD_Init( void );
int CL_DLLEXPORT HUD_Redraw( float flTime, int intermission );
int CL_DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime );
void CL_DLLEXPORT HUD_Reset ( void );
void CL_DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server );
void CL_DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove );
char CL_DLLEXPORT HUD_PlayerMoveTexture( char *name );
int CL_DLLEXPORT HUD_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
int CL_DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs );
void CL_DLLEXPORT HUD_Frame( double time );
void CL_DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking);
void CL_DLLEXPORT HUD_DirectorMessage( int iSize, void *pbuf );
void CL_DLLEXPORT HUD_ChatInputPosition( int *x, int *y );

// From demo
void CL_DLLEXPORT Demo_ReadBuffer( int size, unsigned char *buffer );

// From entity
int CL_DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname );
void CL_DLLEXPORT HUD_CreateEntities( void );
void CL_DLLEXPORT HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
void CL_DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client );
void CL_DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src );
void CL_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 CL_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 CL_DLLEXPORT *HUD_GetUserEntity( int index );

// From in_camera
void CL_DLLEXPORT CAM_Think( void );
int CL_DLLEXPORT CL_IsThirdPerson( void );
void CL_DLLEXPORT CL_CameraOffset( float *ofs );

// From input
struct kbutton_s CL_DLLEXPORT *KB_Find( const char *name );
void CL_DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int active );
void CL_DLLEXPORT HUD_Shutdown( void );
int CL_DLLEXPORT HUD_Key_Event( int eventcode, int keynum, const char *pszCurrentBinding );

// From inputw32
void CL_DLLEXPORT IN_ActivateMouse( void );
void CL_DLLEXPORT IN_DeactivateMouse( void );
void CL_DLLEXPORT IN_MouseEvent (int mstate);
void CL_DLLEXPORT IN_Accumulate (void);
void CL_DLLEXPORT IN_ClearStates (void);

// From tri
void CL_DLLEXPORT HUD_DrawNormalTriangles( void );
void CL_DLLEXPORT HUD_DrawTransparentTriangles( void );

// From view
void CL_DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams );

// From GameStudioModelRenderer
int CL_DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio );
}

/*
extern cldll_func_dst_t *g_pcldstAddrs;

// Macros for the client receiving calls from the engine
#define RecClInitialize(a, b) (g_pcldstAddrs->pInitFunc(&a, &b))
#define RecClHudInit() (g_pcldstAddrs->pHudInitFunc())
#define RecClHudVidInit() (g_pcldstAddrs->pHudVidInitFunc())
#define RecClHudRedraw(a, b) (g_pcldstAddrs->pHudRedrawFunc(&a, &b))
#define RecClHudUpdateClientData(a, b) (g_pcldstAddrs->pHudUpdateClientDataFunc(&a, &b))
#define RecClHudReset() (g_pcldstAddrs->pHudResetFunc())
#define RecClClientMove(a, b) (g_pcldstAddrs->pClientMove(&a, &b))
#define RecClClientMoveInit(a) (g_pcldstAddrs->pClientMoveInit(&a))
#define RecClClientTextureType(a) (g_pcldstAddrs->pClientTextureType(&a))
#define RecClIN_ActivateMouse() (g_pcldstAddrs->pIN_ActivateMouse())
#define RecClIN_DeactivateMouse() (g_pcldstAddrs->pIN_DeactivateMouse())
#define RecClIN_MouseEvent(a) (g_pcldstAddrs->pIN_MouseEvent(&a))
#define RecClIN_ClearStates() (g_pcldstAddrs->pIN_ClearStates())
#define RecClIN_Accumulate() (g_pcldstAddrs->pIN_Accumulate())
#define RecClCL_CreateMove(a, b, c) (g_pcldstAddrs->pCL_CreateMove(&a, &b, &c))
#define RecClCL_IsThirdPerson() (g_pcldstAddrs->pCL_IsThirdPerson())
#define RecClCL_GetCameraOffsets(a) (g_pcldstAddrs->pCL_GetCameraOffsets(&a))
#define RecClFindKey(a) (g_pcldstAddrs->pFindKey(&a))
#define RecClCamThink() (g_pcldstAddrs->pCamThink())
#define RecClCalcRefdef(a) (g_pcldstAddrs->pCalcRefdef(&a))
#define RecClAddEntity(a, b, c) (g_pcldstAddrs->pAddEntity(&a, &b, &c))
#define RecClCreateEntities() (g_pcldstAddrs->pCreateEntities())
#define RecClDrawNormalTriangles() (g_pcldstAddrs->pDrawNormalTriangles())
#define RecClDrawTransparentTriangles() (g_pcldstAddrs->pDrawTransparentTriangles())
#define RecClStudioEvent(a, b) (g_pcldstAddrs->pStudioEvent(&a, &b))
#define RecClPostRunCmd(a, b, c, d, e, f) (g_pcldstAddrs->pPostRunCmd(&a, &b, &c, &d, &e, &f))
#define RecClShutdown() (g_pcldstAddrs->pShutdown())
#define RecClTxferLocalOverrides(a, b) (g_pcldstAddrs->pTxferLocalOverrides(&a, &b))
#define RecClProcessPlayerState(a, b) (g_pcldstAddrs->pProcessPlayerState(&a, &b))
#define RecClTxferPredictionData(a, b, c, d, e, f) (g_pcldstAddrs->pTxferPredictionData(&a, &b, &c, &d, &e, &f))
#define RecClReadDemoBuffer(a, b) (g_pcldstAddrs->pReadDemoBuffer(&a, &b))
#define RecClConnectionlessPacket(a, b, c, d) (g_pcldstAddrs->pConnectionlessPacket(&a, &b, &c, &d))
#define RecClGetHullBounds(a, b, c) (g_pcldstAddrs->pGetHullBounds(&a, &b, &c))
#define RecClHudFrame(a) (g_pcldstAddrs->pHudFrame(&a))
#define RecClKeyEvent(a, b, c) (g_pcldstAddrs->pKeyEvent(&a, &b, &c))
#define RecClTempEntUpdate(a, b, c, d, e, f, g) (g_pcldstAddrs->pTempEntUpdate(&a, &b, &c, &d, &e, &f, &g))
#define RecClGetUserEntity(a) (g_pcldstAddrs->pGetUserEntity(&a))
#define RecClVoiceStatus(a, b) (g_pcldstAddrs->pVoiceStatus(&a, &b))
#define RecClDirectorMessage(a, b) (g_pcldstAddrs->pDirectorMessage(&a, &b))
#define RecClStudioInterface(a, b, c) (g_pcldstAddrs->pStudioInterface(&a, &b, &c))
#define RecClChatInputPosition(a, b) (g_pcldstAddrs->pChatInputPosition(&a, &b))
*/

+ 121
- 0
cl_dll/GameStudioModelRenderer.cpp View File

@@ -0,0 +1,121 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#include <assert.h>
#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 <stdio.h>
#include <string.h>
#include <memory.h>
#include <math.h>

#include "studio_util.h"
#include "r_studioint.h"

#include "StudioModelRenderer.h"
#include "GameStudioModelRenderer.h"
#include "Exports.h"

//
// Override the StudioModelRender virtual member functions here to implement custom bone
// setup, blending, etc.
//

// Global engine <-> studio model rendering code interface
extern engine_studio_api_t IEngineStudio;

// The renderer object, created on the stack.
CGameStudioModelRenderer g_StudioRenderer;
/*
====================
CGameStudioModelRenderer

====================
*/
CGameStudioModelRenderer::CGameStudioModelRenderer( void )
{
}

////////////////////////////////////
// Hooks to class implementation
////////////////////////////////////

/*
====================
R_StudioDrawPlayer

====================
*/
int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
{
return g_StudioRenderer.StudioDrawPlayer( flags, pplayer );
}

/*
====================
R_StudioDrawModel

====================
*/
int R_StudioDrawModel( int flags )
{
return g_StudioRenderer.StudioDrawModel( flags );
}

/*
====================
R_StudioInit

====================
*/
void R_StudioInit( void )
{
g_StudioRenderer.Init();
}

// The simple drawing interface we'll pass back to the engine
r_studio_interface_t studio =
{
STUDIO_INTERFACE_VERSION,
R_StudioDrawModel,
R_StudioDrawPlayer,
};

/*
====================
HUD_GetStudioModelInterface

Export this function for the engine to use the studio renderer class to render objects.
====================
*/
int CL_DLLEXPORT HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )
{
// RecClStudioInterface(version, ppinterface, 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;
}

+ 26
- 0
cl_dll/GameStudioModelRenderer.h View File

@@ -0,0 +1,26 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#if !defined( GAMESTUDIOMODELRENDERER_H )
#define GAMESTUDIOMODELRENDERER_H
#if defined( _WIN32 )
#pragma once
#endif

/*
====================
CGameStudioModelRenderer

====================
*/
class CGameStudioModelRenderer : public CStudioModelRenderer
{
public:
CGameStudioModelRenderer( void );
};

#endif // GAMESTUDIOMODELRENDERER_H

+ 992
- 0
cl_dll/GameStudioModelRenderer_Sample.cpp View File

@@ -0,0 +1,992 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#include <assert.h>
#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 <stdio.h>
#include <string.h>
#include <memory.h>
#include <math.h>

#include "studio_util.h"
#include "r_studioint.h"

#include "StudioModelRenderer.h"
#include "GameStudioModelRenderer.h"

// Predicted values saved off in hl_weapons.cpp
void Game_GetSequence( int *seq, int *gaitseq );
void Game_GetOrientation( float *o, float *a );

float g_flStartScaleTime;
int iPrevRenderState;
int iRenderStateChanged;

// Global engine <-> studio model rendering code interface
extern engine_studio_api_t IEngineStudio;

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;

static client_anim_state_t g_state;
static client_anim_state_t g_clientstate;

// The renderer object, created on the stack.
CGameStudioModelRenderer g_StudioRenderer;
/*
====================
CGameStudioModelRenderer

====================
*/
CGameStudioModelRenderer::CGameStudioModelRenderer( void )
{
// If you want to predict animations locally, set this to TRUE
// NOTE: The animation code is somewhat broken, but gives you a sense for how
// to do client side animation of the predicted player in a third person game.
m_bLocal = false;
}

/*
====================
StudioSetupBones

====================
*/
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];

// Use default bone setup for nonplayers
if ( !m_pCurrentEntity->player )
{
CStudioModelRenderer::StudioSetupBones();
return;
}

// Bound sequence number.
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;

if ( m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0 )
{
f = m_pPlayerInfo->gaitframe;
}
else
{
f = StudioEstimateFrame( pseqdesc );
}

// This game knows how to do three way blending
if ( pseqdesc->numblends == 3 )
{
float s;

// Get left anim
panim = StudioGetAnim( m_pRenderModel, pseqdesc );

// Blending is 0-127 == Left to Middle, 128 to 255 == Middle to right
if ( m_pCurrentEntity->curstate.blending[0] <= 127 )
{
StudioCalcRotations( pos, q, pseqdesc, panim, f );
// Scale 0-127 blending up to 0-255
s = m_pCurrentEntity->curstate.blending[0];
s = ( s * 2.0 );
}
else
{
// Skip ahead to middle
panim += m_pStudioHeader->numbones;

StudioCalcRotations( pos, q, pseqdesc, panim, f );

// Scale 127-255 blending up to 0-255
s = m_pCurrentEntity->curstate.blending[0];
s = 2.0 * ( s - 127.0 );
}

// Normalize interpolant
s /= 255.0;

// Go to middle or right
panim += m_pStudioHeader->numbones;

StudioCalcRotations( pos2, q2, pseqdesc, panim, f );

// Spherically interpolate the bones
StudioSlerpBones( q, pos, q2, pos2, s );
}
else
{
panim = StudioGetAnim( m_pRenderModel, pseqdesc );
StudioCalcRotations( pos, q, pseqdesc, panim, f );
}

// Are we in the process of transitioning from one sequence to another.
if ( m_fDoInterp &&
m_pCurrentEntity->latched.sequencetime &&
( m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime ) &&
( m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq ))
{
// blend from last sequence
static float pos1b[MAXSTUDIOBONES][3];
static vec4_t q1b[MAXSTUDIOBONES];
float s;

// Blending value into last sequence
unsigned char prevseqblending = m_pCurrentEntity->latched.prevseqblending[ 0 ];

// Point at previous sequenece
pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence;
// Know how to do three way blends
if ( pseqdesc->numblends == 3 )
{
float s;

// Get left animation
panim = StudioGetAnim( m_pRenderModel, pseqdesc );

if ( prevseqblending <= 127 )
{
// Set up bones based on final frame of previous sequence
StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
s = prevseqblending;
s = ( s * 2.0 );
}
else
{
// Skip to middle blend
panim += m_pStudioHeader->numbones;

StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );

s = prevseqblending;
s = 2.0 * ( s - 127.0 );
}

// Normalize
s /= 255.0;

panim += m_pStudioHeader->numbones;
StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );

// Interpolate bones
StudioSlerpBones( q1b, pos1b, q2, pos2, s );
}
else
{
panim = StudioGetAnim( m_pRenderModel, pseqdesc );
// clip prevframe
StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe );
}

// Now blend last frame of previous sequence with current sequence.
s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2;
StudioSlerpBones( q, pos, q1b, pos1b, s );
}
else
{
m_pCurrentEntity->latched.prevframe = f;
}

// Now convert quaternions and bone positions into matrices
pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);

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]);
ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
}
else
{
ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]);
ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
}

// Apply client-side effects to the transformation matrix
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]);
}
}
}

/*
====================
StudioEstimateGait

====================
*/
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;
}

// VectorAdd( pplayer->velocity, pplayer->prediction_error, est_velocity );
if ( m_fGaitEstimation )
{
VectorSubtract( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity );
VectorCopy( m_pCurrentEntity->origin, m_pPlayerInfo->prevgaitorigin );
m_flGaitMovement = Length( est_velocity );
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 = Length( est_velocity ) * 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;
}

}

/*
====================
StudioProcessGait

====================
*/
void CGameStudioModelRenderer::StudioProcessGait( entity_state_t *pplayer )
{
mstudioseqdesc_t *pseqdesc;
float dt;
float flYaw; // view direction relative to movement

pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;

m_pCurrentEntity->angles[PITCH] = 0;
m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];

dt = (m_clTime - m_clOldTime);
dt = max( 0.0, dt );
dt = min( 1.0, dt );

StudioEstimateGait( pplayer );

// calc side to side turning
flYaw = m_pCurrentEntity->angles[YAW] - m_pPlayerInfo->gaityaw;

flYaw = fmod( flYaw, 360.0 );

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];

pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence;
// Calc gait frame
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;
}

// Do modulo
m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes;
if (m_pPlayerInfo->gaitframe < 0)
{
m_pPlayerInfo->gaitframe += pseqdesc->numframes;
}
}

/*
==============================
SavePlayerState

For local player, in third person, we need to store real render data and then
setup for with fake/client side animation data
==============================
*/
void CGameStudioModelRenderer::SavePlayerState( entity_state_t *pplayer )
{
client_anim_state_t *st;
cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
assert( ent );
if ( !ent )
return;

st = &g_state;

st->angles = ent->curstate.angles;
st->origin = ent->curstate.origin;

st->realangles = ent->angles;

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; // just in case it wasn't caught in GetEvents
}

return flInterval;
}

/*
==============================
SetupClientAnimation

Called to set up local player's animation values
==============================
*/
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();
assert( ent );
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;
Game_GetSequence( &st->sequence, &st->gaitsequence ); //CVAR_GET_FLOAT( "sequence" );
Game_GetOrientation( (float *)&st->origin, (float *)&st->angles );
st->realangles = st->angles;

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 );
// gEngfuncs.Con_Printf( "gs %i frame %f\n", st->gaitsequence, st->frame );

ent->angles = st->realangles;
ent->curstate.angles = st->angles;
ent->curstate.origin = st->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;
}

/*
==============================
RestorePlayerState

Called to restore original player state information
==============================
*/
void CGameStudioModelRenderer::RestorePlayerState( entity_state_t *pplayer )
{
client_anim_state_t *st;
cl_entity_t *ent = IEngineStudio.GetCurrentEntity();
assert( ent );
if ( !ent )
return;

st = &g_clientstate;

st->angles = ent->curstate.angles;
st->origin = ent->curstate.origin;
st->realangles = ent->angles;

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;

ent->curstate.angles = st->angles;
ent->curstate.origin = st->origin;
ent->angles = st->realangles;

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;
}

/*
==============================
StudioDrawPlayer

==============================
*/
int CGameStudioModelRenderer::StudioDrawPlayer( int flags, entity_state_t *pplayer )
{
int iret = 0;

bool isLocalPlayer = false;
// Set up for client?
if ( m_bLocal && IEngineStudio.GetCurrentEntity() == gEngfuncs.GetLocalPlayer() )
{
isLocalPlayer = true;
}

if ( isLocalPlayer )
{
// Store original data
SavePlayerState( pplayer );

// Copy in client side animation data
SetupClientAnimation( pplayer );
}

// Call real draw function
iret = _StudioDrawPlayer( flags, pplayer );

// Restore for client?
if ( isLocalPlayer )
{
// Restore the original data for the player
RestorePlayerState( pplayer );
}

return iret;
}

/*
====================
_StudioDrawPlayer

====================
*/
int CGameStudioModelRenderer::_StudioDrawPlayer( int flags, entity_state_t *pplayer )
{
alight_t lighting;
vec3_t dir;

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)
{
// see if the bounding box lets us trivially reject, also sets
if (!IEngineStudio.StudioCheckBBox ())
return 0;

(*m_pModelsDrawn)++;
(*m_pStudioModelCount)++; // render data cache cookie

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( );
// copy attachments into global entity array
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 )
{
// show highest resolution multiplayer model
m_pCurrentEntity->curstate.body = 255;
}

if (!(m_pCvarDeveloper->value == 0 && gEngfuncs.GetMaxClients() == 1 ) && ( m_pRenderModel == m_pCurrentEntity->model ) )
{
m_pCurrentEntity->curstate.body = 1; // force helmet
}
*/

lighting.plightvec = dir;
IEngineStudio.StudioDynamicLight(m_pCurrentEntity, &lighting );

IEngineStudio.StudioEntityLight( &lighting );

// model and frame independant
IEngineStudio.StudioSetupLighting (&lighting);

m_pPlayerInfo = IEngineStudio.PlayerInfo( m_nPlayerIndex );

// get remap colors
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( );
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( );

StudioCalcAttachments( );

*m_pCurrentEntity = saveent;
}
}

return 1;
}

/*
====================
Studio_FxTransform

====================
*/
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 ) // Choose between x & z
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 ) // Choose between x & z
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;
}

// Make the Model continue to shrink
float flTimeDelta = m_clTime - g_flStartScaleTime;
if ( flTimeDelta > 0 )
{
float flScale = 0.001;
// Goes almost all away
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;
}
}

////////////////////////////////////
// Hooks to class implementation
////////////////////////////////////

/*
====================
R_StudioDrawPlayer

====================
*/
int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
{
return g_StudioRenderer.StudioDrawPlayer( flags, pplayer );
}

/*
====================
R_StudioDrawModel

====================
*/
int R_StudioDrawModel( int flags )
{
return g_StudioRenderer.StudioDrawModel( flags );
}

/*
====================
R_StudioInit

====================
*/
void R_StudioInit( void )
{
g_StudioRenderer.Init();
}

// The simple drawing interface we'll pass back to the engine
r_studio_interface_t studio =
{
STUDIO_INTERFACE_VERSION,
R_StudioDrawModel,
R_StudioDrawPlayer,
};

/*
====================
HUD_GetStudioModelInterface

Export this function for the engine to use the studio renderer class to render objects.
====================
*/
#define DLLEXPORT __declspec( dllexport )
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;
}

+ 55
- 0
cl_dll/GameStudioModelRenderer_Sample.h View File

@@ -0,0 +1,55 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#if !defined( GAMESTUDIOMODELRENDERER_H )
#define GAMESTUDIOMODELRENDERER_H
#if defined( _WIN32 )
#pragma once
#endif

/*
====================
CGameStudioModelRenderer

====================
*/
class CGameStudioModelRenderer : public CStudioModelRenderer
{
public:
CGameStudioModelRenderer( void );

// Set up model bone positions
virtual void StudioSetupBones ( void );

// Estimate gait frame for player
virtual void StudioEstimateGait ( entity_state_t *pplayer );

// Process movement of player
virtual void StudioProcessGait ( entity_state_t *pplayer );

// Player drawing code
virtual int StudioDrawPlayer( int flags, entity_state_t *pplayer );
virtual int _StudioDrawPlayer( int flags, entity_state_t *pplayer );

// Apply special effects to transform matrix
virtual void StudioFxTransform( cl_entity_t *ent, float transform[3][4] );

private:
// For local player, in third person, we need to store real render data and then
// setup for with fake/client side animation data
void SavePlayerState( entity_state_t *pplayer );
// Called to set up local player's animation values
void SetupClientAnimation( entity_state_t *pplayer );
// Called to restore original player state information
void RestorePlayerState( entity_state_t *pplayer );

private:
// Private data
bool m_bLocal;
};

#endif // GAMESTUDIOMODELRENDERER_H

+ 155
- 0
cl_dll/MOTD.cpp View File

@@ -0,0 +1,155 @@
/***
*
* Copyright (c) 1999, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//
// MOTD.cpp
//
// for displaying a server-sent message of the day
//

#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"

#include <string.h>
#include <stdio.h>

//DECLARE_MESSAGE( m_MOTD, MOTD );

int CHudMOTD::MOTD_DISPLAY_TIME;

int CHudMOTD :: Init( void )
{
gHUD.AddHudElem( this );

// HOOK_MESSAGE( MOTD );

CVAR_CREATE( "motd_display_time", "15", 0 );

m_iFlags &= ~HUD_ACTIVE; // start out inactive
m_szMOTD[0] = 0;

return 1;
}

int CHudMOTD :: VidInit( void )
{
// Load sprites here

return 1;
}

void CHudMOTD :: Reset( void )
{
m_iFlags &= ~HUD_ACTIVE; // start out inactive
m_szMOTD[0] = 0;
m_iLines = 0;
m_flActiveRemaining = 0;
}

#define LINE_HEIGHT 13

int CHudMOTD :: Draw( float fTime )
{
static float sfLastTime;
float fElapsed;

// Draw MOTD line-by-line
if ( m_flActiveRemaining <= 0.0 )
{
// finished with MOTD, disable it
m_szMOTD[0] = 0;
m_iLines = 0;
m_iFlags &= ~HUD_ACTIVE;
m_flActiveRemaining = 0.0;
return 1;
}

fElapsed = gHUD.m_flTime - sfLastTime;

// Don't let time go negative ( level transition? )
fElapsed = max( 0.0, fElapsed );
// Don't let time go hugely positive ( first connection to active server ? )
fElapsed = min( 1.0, fElapsed );

// Remember last timestamp
sfLastTime = gHUD.m_flTime;

// Remove a bit of time
m_flActiveRemaining -= fElapsed;

// find the top of where the MOTD should be drawn, so the whole thing is centered in the screen
int ypos = max(((ScreenHeight - (m_iLines * LINE_HEIGHT)) / 2) - 40, 30 ); // shift it up slightly
char *ch = m_szMOTD;
while ( *ch )
{
int line_length = 0; // count the length of the current line
for ( char *next_line = ch; *next_line != '\n' && *next_line != 0; next_line++ )
line_length += gHUD.m_scrinfo.charWidths[ *next_line ];
char *top = next_line;
if ( *top == '\n' )
*top = 0;
else
top = NULL;

// find where to start drawing the line
int xpos = (ScreenWidth - line_length) / 2;

gHUD.DrawHudString( xpos, ypos, ScreenWidth, ch, 255, 180, 0 );

ypos += LINE_HEIGHT;

if ( top ) // restore
*top = '\n';
ch = next_line;
if ( *ch == '\n' )
ch++;

if ( ypos > (ScreenHeight - 20) )
break; // don't let it draw too low
}
return 1;
}

int CHudMOTD :: MsgFunc_MOTD( const char *pszName, int iSize, void *pbuf )
{
if ( m_iFlags & HUD_ACTIVE )
{
Reset(); // clear the current MOTD in prep for this one
}

BEGIN_READ( pbuf, iSize );

int is_finished = READ_BYTE();
strcat( m_szMOTD, READ_STRING() );

if ( is_finished )
{
m_iFlags |= HUD_ACTIVE;

MOTD_DISPLAY_TIME = max( 10, CVAR_GET_FLOAT( "motd_display_time" ) );

m_flActiveRemaining = MOTD_DISPLAY_TIME;

for ( char *sz = m_szMOTD; *sz != 0; sz++ ) // count the number of lines in the MOTD
{
if ( *sz == '\n' )
m_iLines++;
}
}

return 1;
}


+ 2114
- 0
cl_dll/StudioModelRenderer.cpp
File diff suppressed because it is too large
View File


+ 189
- 0
cl_dll/StudioModelRenderer.h View File

@@ -0,0 +1,189 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================

#if !defined ( STUDIOMODELRENDERER_H )
#define STUDIOMODELRENDERER_H
#if defined( _WIN32 )
#pragma once
#endif

/*
====================
CStudioModelRenderer

====================
*/
class CStudioModelRenderer
{
public:
// Construction/Destruction
CStudioModelRenderer( void );
virtual ~CStudioModelRenderer( void );

// Initialization
virtual void Init( void );

public:
// Public Interfaces
virtual int StudioDrawModel ( int flags );
virtual int StudioDrawPlayer ( int flags, struct entity_state_s *pplayer );

public:
// Local interfaces
//

// Look up animation data for sequence
virtual mstudioanim_t *StudioGetAnim ( model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc );

// Interpolate model position and angles and set up matrices
virtual void StudioSetUpTransform (int trivial_accept);

// Set up model bone positions
virtual void StudioSetupBones ( void );

// Find final attachment points
virtual void StudioCalcAttachments ( void );
// Save bone matrices and names
virtual void StudioSaveBones( void );

// Merge cached bones with current bones for model
virtual void StudioMergeBones ( model_t *m_pSubModel );

// Determine interpolation fraction
virtual float StudioEstimateInterpolant( void );

// Determine current frame for rendering
virtual float StudioEstimateFrame ( mstudioseqdesc_t *pseqdesc );

// Apply special effects to transform matrix
virtual void StudioFxTransform( cl_entity_t *ent, float transform[3][4] );

// Spherical interpolation of bones
virtual void StudioSlerpBones ( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s );

// Compute bone adjustments ( bone controllers )
virtual void StudioCalcBoneAdj ( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen );

// Get bone quaternions
virtual void StudioCalcBoneQuaterion ( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q );

// Get bone positions
virtual void StudioCalcBonePosition ( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos );

// Compute rotations
virtual void StudioCalcRotations ( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f );

// Send bones and verts to renderer
virtual void StudioRenderModel ( void );

// Finalize rendering
virtual void StudioRenderFinal (void);
// GL&D3D vs. Software renderer finishing functions
virtual void StudioRenderFinal_Software ( void );
virtual void StudioRenderFinal_Hardware ( void );

// Player specific data
// Determine pitch and blending amounts for players
virtual void StudioPlayerBlend ( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch );

// Estimate gait frame for player
virtual void StudioEstimateGait ( entity_state_t *pplayer );

// Process movement of player
virtual void StudioProcessGait ( entity_state_t *pplayer );

public:

// Client clock
double m_clTime;
// Old Client clock
double m_clOldTime;

// Do interpolation?
int m_fDoInterp;
// Do gait estimation?
int m_fGaitEstimation;

// Current render frame #
int m_nFrameCount;

// Cvars that studio model code needs to reference
//
// Use high quality models?
cvar_t *m_pCvarHiModels;
// Developer debug output desired?
cvar_t *m_pCvarDeveloper;
// Draw entities bone hit boxes, etc?
cvar_t *m_pCvarDrawEntities;

// The entity which we are currently rendering.
cl_entity_t *m_pCurrentEntity;

// The model for the entity being rendered
model_t *m_pRenderModel;

// Player info for current player, if drawing a player
player_info_t *m_pPlayerInfo;

// The index of the player being drawn
int m_nPlayerIndex;

// The player's gait movement
float m_flGaitMovement;

// Pointer to header block for studio model data
studiohdr_t *m_pStudioHeader;
// Pointers to current body part and submodel
mstudiobodyparts_t *m_pBodyPart;
mstudiomodel_t *m_pSubModel;

// Palette substition for top and bottom of model
int m_nTopColor;
int m_nBottomColor;

//
// Sprite model used for drawing studio model chrome
model_t *m_pChromeSprite;

// Caching
// Number of bones in bone cache
int m_nCachedBones;
// Names of cached bones
char m_nCachedBoneNames[ MAXSTUDIOBONES ][ 32 ];
// Cached bone & light transformation matrices
float m_rgCachedBoneTransform [ MAXSTUDIOBONES ][ 3 ][ 4 ];
float m_rgCachedLightTransform[ MAXSTUDIOBONES ][ 3 ][ 4 ];

// Software renderer scale factors
float m_fSoftwareXScale, m_fSoftwareYScale;

// Current view vectors and render origin
float m_vUp[ 3 ];
float m_vRight[ 3 ];
float m_vNormal[ 3 ];

float m_vRenderOrigin[ 3 ];
// Model render counters ( from engine )
int *m_pStudioModelCount;
int *m_pModelsDrawn;

// Matrices
// Model to world transformation
float (*m_protationmatrix)[ 3 ][ 4 ];
// Model to view transformation
float (*m_paliastransform)[ 3 ][ 4 ];

// Concatenated bone and light transforms
float (*m_pbonetransform) [ MAXSTUDIOBONES ][ 3 ][ 4 ];
float (*m_plighttransform)[ MAXSTUDIOBONES ][ 3 ][ 4 ];
};

#endif // STUDIOMODELRENDERER_H

+ 1200
- 0
cl_dll/ammo.cpp
File diff suppressed because it is too large
View File


+ 62
- 0
cl_dll/ammo.h View File

@@ -0,0 +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.
*
****/

#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

+ 159
- 0
cl_dll/ammo_secondary.cpp View File

@@ -0,0 +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 <string.h>
#include <stdio.h>
#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;
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
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 -= (gHUD.GetNumWidth( m_iAmmoAmounts[i], DHN_DRAWZERO ) * AmmoWidth);
gHUD.DrawHudNumber( x, y, DHN_DRAWZERO, m_iAmmoAmounts[i], r, g, b );

if ( i != 0 )
{
// draw the divider bar
x -= (AmmoWidth / 2);
FillRGBA(x, y, (AmmoWidth/10), gHUD.m_iFontHeight, r, g, b, a);
}
}

return 1;
}

// Message handler for Secondary Ammo Value
// accepts one value:
// string: sprite name
int CHudAmmoSecondary :: MsgFunc_SecAmmoIcon( const char *pszName, int iSize, void *pbuf )
{
BEGIN_READ( 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;
}



+ 190
- 0
cl_dll/ammohistory.cpp View File

@@ -0,0 +1,190 @@
/***
*
* 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 <string.h>
#include <stdio.h>

#include "ammohistory.h"

HistoryResource gHR;

#define AMMO_PICKUP_GAP (gHR.iHistoryGap+5)
#define AMMO_PICKUP_PICK_HEIGHT (32 + (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 = CVAR_GET_FLOAT( "hud_drawhistory_time" );

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

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 = CVAR_GET_FLOAT( "hud_drawhistory_time" );
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;
UnpackRGB(r,g,b, RGB_YELLOWISH);
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
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
gHUD.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;
UnpackRGB(r,g,b, RGB_YELLOWISH);

if ( !gWR.HasAmmo( weap ) )
UnpackRGB(r,g,b, RGB_REDISH); // if the weapon doesn't have ammo, display it as red

float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
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 );

UnpackRGB(r,g,b, RGB_YELLOWISH);
float scale = (rgAmmoHistory[i].DisplayTime - flTime) * 80;
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;
}



+ 143
- 0
cl_dll/ammohistory.h View File

@@ -0,0 +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.