1
0
Fork 0
forked from valve/halflife-sdk

as released 2001-08-29

This commit is contained in:
archive 2001-08-29 00:00:00 +00:00
parent e84d04174b
commit d4fc7e405f
295 changed files with 74734 additions and 4076 deletions

View file

@ -42,13 +42,35 @@ clientdata_t none
DEFINE_DELTA( bInDuck, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( flSwimTime, DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( waterjumptime, DT_INTEGER, 15, 1.0 ),
DEFINE_DELTA( waterlevel, DT_INTEGER, 2, 1.0 )
DEFINE_DELTA( waterlevel, DT_INTEGER, 2, 1.0 ),
DEFINE_DELTA( vuser1[0], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser1[1], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser1[2], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser2[0], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser2[1], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser2[2], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser3[0], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser3[1], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser3[2], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser4[0], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser4[1], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( vuser4[2], DT_SIGNED | DT_FLOAT, 10, 1.0 ),
DEFINE_DELTA( fuser1, DT_SIGNED | DT_FLOAT, 22, 128.0 ),
DEFINE_DELTA( fuser2, DT_SIGNED | DT_FLOAT, 2, 128.0 ),
DEFINE_DELTA( fuser3, DT_SIGNED | DT_FLOAT, 2, 128.0 ),
DEFINE_DELTA( fuser4, DT_SIGNED | DT_FLOAT, 2, 128.0 )
}
entity_state_t gamedll Entity_Encode
{
DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
// DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
DEFINE_DELTA( animtime, DT_TIMEWINDOW_BIG, 8, 100.0 ),
DEFINE_DELTA( frame, DT_FLOAT, 10, 4.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 16, 8.0 ),
DEFINE_DELTA( angles[0], DT_ANGLE, 16, 1.0 ),
DEFINE_DELTA( angles[1], DT_ANGLE, 16, 1.0 ),
@ -108,7 +130,8 @@ entity_state_t gamedll Entity_Encode
entity_state_player_t gamedll Player_Encode
{
DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
// DEFINE_DELTA( animtime, DT_TIMEWINDOW_8, 8, 1.0 ),
DEFINE_DELTA( animtime, DT_TIMEWINDOW_BIG, 8, 100.0 ),
DEFINE_DELTA( frame, DT_FLOAT, 8, 1.0 ),
DEFINE_DELTA( origin[0], DT_SIGNED | DT_FLOAT, 18, 32.0 ),
DEFINE_DELTA( angles[0], DT_ANGLE, 16, 1.0 ),
@ -216,7 +239,13 @@ weapon_data_t none
DEFINE_DELTA( m_fAimedDamage, DT_FLOAT, 6, 0.1 ),
DEFINE_DELTA( m_fInZoom, DT_INTEGER, 1, 1.0 ),
DEFINE_DELTA( m_iWeaponState, DT_INTEGER, 2, 1.0 ),
DEFINE_DELTA( m_iId, DT_INTEGER, 5, 1.0 )
DEFINE_DELTA( m_iId, DT_INTEGER, 5, 1.0 ),
DEFINE_DELTA( iuser1, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( iuser2, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( iuser3, DT_SIGNED | DT_INTEGER, 10, 1.0 ),
DEFINE_DELTA( fuser1, DT_SIGNED | DT_FLOAT, 22, 1000.0 ),
DEFINE_DELTA( fuser2, DT_SIGNED | DT_FLOAT, 22, 128.0 ),
DEFINE_DELTA( fuser3, DT_SIGNED | DT_FLOAT, 22, 128.0 )
}
event_t none

View file

@ -30,7 +30,6 @@ extern engine_studio_api_t IEngineStudio;
// The renderer object, created on the stack.
CGameStudioModelRenderer g_StudioRenderer;
/*
====================
CGameStudioModelRenderer

View file

@ -31,13 +31,19 @@ extern "C"
#include <string.h>
#include "hud_servers.h"
#include "vgui_int.h"
#include "interface.h"
#include "ITrackerUser.h"
#define DLLEXPORT __declspec( dllexport )
cl_enginefunc_t gEngfuncs;
CHud gHUD;
TeamFortressViewport *gViewPort = NULL;
HINTERFACEMODULE g_hTrackerModule = NULL;
ITrackerUser *g_pTrackerUser = NULL;
void InitInput (void);
void EV_HookEvents( void );
void IN_Commands( void );
@ -51,18 +57,20 @@ Called when the DLL is first loaded.
*/
extern "C"
{
int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion );
int DLLEXPORT HUD_VidInit( void );
int DLLEXPORT HUD_Init( void );
int DLLEXPORT HUD_Redraw( float flTime, int intermission );
int DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime );
int DLLEXPORT HUD_Reset ( void );
void DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server );
void DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove );
char DLLEXPORT HUD_PlayerMoveTexture( char *name );
int DLLEXPORT HUD_ConnectionlessPacket( struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs );
void DLLEXPORT HUD_Frame( double time );
int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion );
int DLLEXPORT HUD_VidInit( void );
int DLLEXPORT HUD_Init( void );
int DLLEXPORT HUD_Redraw( float flTime, int intermission );
int DLLEXPORT HUD_UpdateClientData( client_data_t *cdata, float flTime );
int DLLEXPORT HUD_Reset ( void );
void DLLEXPORT HUD_PlayerMove( struct playermove_s *ppmove, int server );
void DLLEXPORT HUD_PlayerMoveInit( struct playermove_s *ppmove );
char DLLEXPORT HUD_PlayerMoveTexture( char *name );
int DLLEXPORT HUD_ConnectionlessPacket( struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs );
void DLLEXPORT HUD_Frame( double time );
void DLLEXPORT HUD_VoiceStatus(int entindex, qboolean bTalking);
void DLLEXPORT HUD_DirectorEvent(unsigned char command, unsigned int firstObject, unsigned int secondObject, unsigned int flags);
}
/*
@ -139,17 +147,31 @@ int DLLEXPORT Initialize( cl_enginefunc_t *pEnginefuncs, int iVersion )
{
gEngfuncs = *pEnginefuncs;
//!!! mwh UNDONE We need to think about our versioning strategy. Do we want to try to be compatible
// with previous versions, especially when we're only 'bonus' functionality? Should it be the engine
// that decides if the DLL is compliant?
if (iVersion != CLDLL_INTERFACE_VERSION)
return 0;
memcpy(&gEngfuncs, pEnginefuncs, sizeof(cl_enginefunc_t));
EV_HookEvents();
// get tracker interface, if any
char szDir[512];
if (!gEngfuncs.COM_ExpandFilename("Bin/TrackerUI.dll", szDir, sizeof(szDir)))
{
g_pTrackerUser = NULL;
g_hTrackerModule = NULL;
return 1;
}
g_hTrackerModule = Sys_LoadModule(szDir);
CreateInterfaceFn trackerFactory = Sys_GetFactory(g_hTrackerModule);
if (!trackerFactory)
{
g_pTrackerUser = NULL;
g_hTrackerModule = NULL;
return 1;
}
g_pTrackerUser = (ITrackerUser *)trackerFactory(TRACKERUSER_INTERFACE_VERSION, NULL);
return 1;
}
@ -188,7 +210,6 @@ int DLLEXPORT HUD_Init( void )
InitInput();
gHUD.Init();
Scheme_Init();
return 1;
}
@ -255,4 +276,35 @@ 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_DirectorEvent(unsigned char command, unsigned int firstObject, unsigned int secondObject, unsigned int flags)
{
gHUD.m_Spectator.DirectorEvent(command, firstObject, secondObject, flags);
}

View file

@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\utils\vgui\include" /I "..\dlls" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /Zi /O2 /I "..\utils\vgui\include" /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\dlls" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "CLIENT_DLL" /D "CLIENT_WEAPONS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -54,15 +54,6 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:".\Release\client.dll"
# Begin Custom Build - Copying to \quiver\valve\cl_dlls
TargetDir=.\Release
InputPath=.\Release\client.dll
SOURCE="$(InputPath)"
"\quiver\valve\cl_dlls\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\client.dll \quiver\valve\cl_dlls
# End Custom Build
!ELSEIF "$(CFG)" == "cl_dll - Win32 Debug"
@ -78,7 +69,7 @@ SOURCE="$(InputPath)"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GX /ZI /Od /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\utils\vgui\include" /I "..\dlls" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /c
# ADD CPP /nologo /G5 /MTd /W3 /Gm /GR /GX /ZI /Od /I "..\dlls" /I "..\common" /I "..\pm_shared" /I "..\engine" /I "..\utils\vgui\include" /I "..\game_shared" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "CLIENT_DLL" /D "CLIENT_WEAPONS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
@ -89,15 +80,6 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib winmm.lib ../utils/vgui/lib/win32_vc6/vgui.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:".\Debug\client.dll"
# Begin Custom Build - Copying to \half-life\mp\cl_dlls
TargetDir=.\Debug
InputPath=.\Debug\client.dll
SOURCE="$(InputPath)"
"\half-life\mp\cl_dlls\client.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\client.dll \half-life\mp\cl_dlls
# End Custom Build
!ENDIF
@ -110,13 +92,33 @@ SOURCE="$(InputPath)"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
# Begin Group "hl"
# PROP Default_Filter "*.cpp"
# PROP Default_Filter "*.CPP"
# Begin Source File
SOURCE=..\dlls\crossbow.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\crowbar.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\egon.cpp
# End Source File
# Begin Source File
SOURCE=.\ev_hldm.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\gauss.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\handgrenade.cpp
# End Source File
# Begin Source File
SOURCE=.\hl\hl_baseentity.cpp
# End Source File
# Begin Source File
@ -135,6 +137,62 @@ SOURCE=.\hl\hl_weapons.cpp
SOURCE=..\dlls\wpn_shared\hl_wpn_glock.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\hornetgun.cpp
# End Source File
# Begin Source File
SOURCE=..\common\interface.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\mp5.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\python.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\rpg.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\satchel.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\shotgun.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\squeakgrenade.cpp
# End Source File
# Begin Source File
SOURCE=..\dlls\tripmine.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_scrollbar2.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_slider2.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_banmgr.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_status.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_vgui_tweakdlg.cpp
# End Source File
# End Group
# Begin Source File
@ -214,6 +272,10 @@ SOURCE=.\hud_servers.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_spectator.cpp
# End Source File
# Begin Source File
SOURCE=.\hud_update.cpp
# End Source File
# Begin Source File
@ -238,6 +300,11 @@ SOURCE=.\message.cpp
# End Source File
# Begin Source File
SOURCE=.\overview.cpp
# PROP Exclude_From_Build 1
# End Source File
# Begin Source File
SOURCE=.\parsemsg.cpp
# End Source File
# Begin Source File
@ -294,6 +361,10 @@ SOURCE=.\util.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_checkbutton2.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_ClassMenu.cpp
# End Source File
# Begin Source File
@ -310,10 +381,26 @@ SOURCE=.\vgui_CustomObjects.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_grid.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_helpers.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_int.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_listbox.cpp
# End Source File
# Begin Source File
SOURCE=..\game_shared\vgui_loadtga.cpp
# End Source File
# Begin Source File
SOURCE=.\vgui_MOTDWindow.cpp
# End Source File
# Begin Source File
@ -402,14 +489,26 @@ SOURCE=.\hud_servers_priv.h
# End Source File
# Begin Source File
SOURCE=.\hud_spectator.h
# End Source File
# Begin Source File
SOURCE=.\in_defs.h
# End Source File
# Begin Source File
SOURCE=..\common\itrackeruser.h
# End Source File
# Begin Source File
SOURCE=.\kbutton.h
# End Source File
# Begin Source File
SOURCE=.\overview.h
# End Source File
# Begin Source File
SOURCE=..\pm_shared\pm_debug.h
# End Source File
# Begin Source File
@ -482,6 +581,18 @@ SOURCE=.\view.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_banmgr.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_status.h
# End Source File
# Begin Source File
SOURCE=..\game_shared\voice_vgui_tweakdlg.h
# End Source File
# Begin Source File
SOURCE=.\wrect.h
# End Source File
# End Group

View file

@ -1,37 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "cl_dll"=.\cl_dll.dsp - Package Owner=<4>
Package=<5>
{{{
begin source code control
"$/GoldSrc/cl_dll", HGEBAAAA
.
end source code control
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
begin source code control
"$/Sdk/Standard/cl_dll", UBZBAAAA
.
end source code control
}}}
Package=<3>
{{{
}}}
###############################################################################

View file

@ -67,6 +67,14 @@ inline struct cvar_s *CVAR_CREATE( const char *cv, const char *val, const int fl
// ScreenWidth returns the width of the screen, in pixels
#define ScreenWidth (gHUD.m_scrinfo.iWidth)
// Use this to set any co-ords in 640x480 space
#define XRES(x) ((x) * ((float)ScreenWidth / 640))
#define YRES(y) ((y) * ((float)ScreenHeight / 480))
// 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)
@ -128,7 +136,7 @@ void ScaleColors( int &r, int &g, int &b, int a );
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
#define VectorClear(a) { a[0]=0.0;a[1]=0.0;a[2]=0.0;}
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);

View file

@ -168,6 +168,8 @@ int CHudDeathNotice :: MsgFunc_DeathMsg( const char *pszName, int iSize, void *p
if (gViewPort)
gViewPort->DeathMsg( killer, victim );
gHUD.m_Spectator.DeathMessage(victim);
for ( int i = 0; i < MAX_DEATHNOTICES; i++ )
{
if ( rgDeathNoticeList[i].iId == 0 )

View file

@ -12,6 +12,7 @@
#include "pm_defs.h"
#include "pmtrace.h"
#define DLLEXPORT __declspec( dllexport )
void Game_AddObjects( void );
@ -50,6 +51,17 @@ int DLLEXPORT HUD_AddEntity( int type, struct cl_entity_s *ent, const char *mode
default:
break;
}
// each frame every entity passes this function, so the overview hooks it to filter the overview entities
if (gEngfuncs.IsSpectateOnly())
{
gHUD.m_Spectator.AddOverviewEntity( type, ent, modelname );
if ( ( gHUD.m_Spectator.m_iMainMode == MAIN_IN_EYE ||
gHUD.m_Spectator.m_iInsetMode == INSET_IN_EYE ) &&
ent->index == gHUD.m_Spectator.m_iObserverTarget )
return 0; // don't draw the player we are following in eye
}
return 1;
}
@ -71,6 +83,9 @@ void DLLEXPORT HUD_TxferLocalOverrides( struct entity_state_s *state, const stru
state->iuser1 = client->iuser1;
state->iuser2 = client->iuser2;
// Duck prevention
state->iuser3 = client->iuser3;
// Fire prevention
state->iuser4 = client->iuser4;
}
@ -132,8 +147,11 @@ void DLLEXPORT HUD_ProcessPlayerState( struct entity_state_s *dst, const struct
{
g_iPlayerClass = dst->playerclass;
g_iTeamNumber = dst->team;
g_iUser1 = src->iuser1;
g_iUser2 = src->iuser2;
g_iUser3 = src->iuser3;
}
}
@ -175,9 +193,30 @@ void DLLEXPORT HUD_TxferPredictionData ( struct entity_state_s *ps, const struct
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 ) );
}
@ -488,8 +527,11 @@ void DLLEXPORT HUD_CreateEntities( void )
Beams();
#endif
// Add in any game specific objects
Game_AddObjects();
GetClientVoiceMgr()->CreateEntities();
}
/*
@ -680,6 +722,7 @@ void DLLEXPORT HUD_TempEntUpdate (
pTemp->entity.origin[1] += pTemp->entity.baseline.origin[1] * frametime + 4 * sin( client_time * 30 + (int)pTemp );
pTemp->entity.origin[2] += pTemp->entity.baseline.origin[2] * frametime;
}
else
{
for ( i = 0; i < 3; i++ )
@ -922,4 +965,5 @@ cl_entity_t DLLEXPORT *HUD_GetUserEntity( int index )
#else
return NULL;
#endif
}
}

File diff suppressed because it is too large Load diff

View file

@ -83,6 +83,6 @@ enum gauss_e {
void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName );
void EV_HLDM_DecalGunshot( pmtrace_t *pTrace, int iBulletType );
int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount );
void EV_HLDM_FireBullets( int idx, float *forward, float *right, float *up, int cShots, float *vecSrc, float *vecDirShooting, float *vecSpread, float flDistance, int iBulletType, int iTracerFreq, int *tracerCount );
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 );
#endif // EV_HLDMH

View file

@ -173,10 +173,7 @@ int CHudHealth::Draw(float flTime)
int a = 0, x, y;
int HealthWidth;
// if (m_iHealth <= 0)
// return 1;
if ( gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH )
if ( (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || gEngfuncs.IsSpectateOnly() )
return 1;
if ( !m_hSprite )

View file

@ -27,6 +27,8 @@ This file contains "stubs" of class member implementations so that we can predic
#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 );
@ -91,24 +93,95 @@ void CGrenade::Explode( Vector, Vector ) { }
void CGrenade::Explode( TraceResult *, int ) { }
void CGrenade::Killed( entvars_t *, int ) { }
void CGrenade::Spawn( void ) { }
CGrenade * CGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity, float time ){ return 0; }
CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ){ return 0; }
void CGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ){ }
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 :: Eat ( float flFullDuration ) { }
BOOL CBaseMonster :: FShouldEat ( void ) { return TRUE; }
void CBaseMonster :: BarnacleVictimBitten ( entvars_t *pevBarnacle ) { }
void CBaseMonster :: BarnacleVictimReleased ( void ) { }
void CBaseMonster :: Listen ( void ) { }
float CBaseMonster :: FLSoundVolume ( CSound *pSound ) { return 0.0; }
BOOL CBaseMonster :: FValidateHintType ( short sHint ) { return FALSE; }
void CBaseMonster :: Look ( int iDistance ) { }
int CBaseMonster :: ISoundMask ( void ) { return 0; }
CSound* CBaseMonster :: PBestSound ( void ) { return NULL; }
CSound* CBaseMonster :: PBestScent ( void ) { return NULL; }
float CBaseAnimating :: StudioFrameAdvance ( float flInterval ) { return 0.0; }
void CBaseMonster :: MonsterThink ( void ) { }
void CBaseMonster :: MonsterUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { }
int CBaseMonster :: IgnoreConditions ( void ) { return 0; }
void CBaseMonster :: RouteClear ( void ) { }
void CBaseMonster :: RouteNew ( void ) { }
BOOL CBaseMonster :: FRouteClear ( void ) { return FALSE; }
BOOL CBaseMonster :: FRefreshRoute ( void ) { return 0; }
BOOL CBaseMonster::MoveToEnemy( Activity movementAct, float waitTime ) { return FALSE; }
BOOL CBaseMonster::MoveToLocation( Activity movementAct, float waitTime, const Vector &goal ) { return FALSE; }
BOOL CBaseMonster::MoveToTarget( Activity movementAct, float waitTime ) { return FALSE; }
BOOL CBaseMonster::MoveToNode( Activity movementAct, float waitTime, const Vector &goal ) { return FALSE; }
int ShouldSimplify( int routeType ) { return TRUE; }
void CBaseMonster :: RouteSimplify( CBaseEntity *pTargetEnt ) { }
BOOL CBaseMonster :: FBecomeProne ( void ) { return TRUE; }
BOOL CBaseMonster :: CheckRangeAttack1 ( float flDot, float flDist ) { return FALSE; }
BOOL CBaseMonster :: CheckRangeAttack2 ( float flDot, float flDist ) { return FALSE; }
BOOL CBaseMonster :: CheckMeleeAttack1 ( float flDot, float flDist ) { return FALSE; }
BOOL CBaseMonster :: CheckMeleeAttack2 ( float flDot, float flDist ) { return FALSE; }
void CBaseMonster :: CheckAttacks ( CBaseEntity *pTarget, float flDist ) { }
BOOL CBaseMonster :: FCanCheckAttacks ( void ) { return FALSE; }
int CBaseMonster :: CheckEnemy ( CBaseEntity *pEnemy ) { return 0; }
void CBaseMonster :: PushEnemy( CBaseEntity *pEnemy, Vector &vecLastKnownPos ) { }
BOOL CBaseMonster :: PopEnemy( ) { return FALSE; }
void CBaseMonster :: SetActivity ( Activity NewActivity ) { }
void CBaseMonster :: SetSequenceByName ( char *szSequence ) { }
int CBaseMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist ) { return 0; }
float CBaseMonster :: OpenDoorAndWait( entvars_t *pevDoor ) { return 0.0; }
void CBaseMonster :: AdvanceRoute ( float distance ) { }
int CBaseMonster :: RouteClassify( int iMoveFlag ) { return 0; }
BOOL CBaseMonster :: BuildRoute ( const Vector &vecGoal, int iMoveFlag, CBaseEntity *pTarget ) { return FALSE; }
void CBaseMonster :: InsertWaypoint ( Vector vecLocation, int afMoveFlags ) { }
BOOL CBaseMonster :: FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex ) { return FALSE; }
void CBaseMonster :: Move ( float flInterval ) { }
BOOL CBaseMonster:: ShouldAdvanceRoute( float flWaypointDist ) { return FALSE; }
void CBaseMonster::MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval ) { }
void CBaseMonster :: MonsterInit ( void ) { }
void CBaseMonster :: MonsterInitThink ( void ) { }
void CBaseMonster :: StartMonster ( void ) { }
void CBaseMonster :: MovementComplete( void ) { }
int CBaseMonster::TaskIsRunning( void ) { return 0; }
int CBaseMonster::IRelationship ( CBaseEntity *pTarget ) { return 0; }
BOOL CBaseMonster :: FindCover ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist ) { return FALSE; }
BOOL CBaseMonster :: BuildNearestRoute ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist ) { return FALSE; }
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::FlYawDiff ( void ) { return 0.0; }
float CBaseMonster::ChangeYaw ( int yawSpeed ) { return 0; }
float CBaseMonster::VecToYaw ( Vector vecDir ) { return 0.0; }
int CBaseAnimating :: LookupActivity ( int activity ) { return 0; }
int CBaseAnimating :: LookupActivityHeaviest ( int activity ) { return 0; }
void CBaseMonster :: SetEyePosition ( void ) { }
int CBaseAnimating :: LookupSequence ( const char *label ) { return 0; }
void CBaseAnimating :: ResetSequenceInfo ( ) { }
BOOL CBaseAnimating :: GetSequenceFlags( ) { return FALSE; }
void CBaseAnimating :: DispatchAnimEvents ( float flInterval ) { }
void CBaseMonster :: HandleAnimEvent( MonsterEvent_t *pEvent ) { }
float CBaseAnimating :: SetBoneController ( int iController, float flValue ) { return 0.0; }
void CBaseAnimating :: InitBoneControllers ( void ) { }
float CBaseAnimating :: SetBlending ( int iBlender, float flValue ) { return 0; }
@ -118,16 +191,30 @@ int CBaseAnimating :: FindTransition( int iEndingSequence, int iGoalSequence, in
void CBaseAnimating :: GetAutomovement( Vector &origin, Vector &angles, float flInterval ) { }
void CBaseAnimating :: SetBodygroup( int iGroup, int iValue ) { }
int CBaseAnimating :: GetBodygroup( int iGroup ) { return 0; }
Vector CBaseMonster :: GetGunPosition( void ) { return g_vecZero; }
void CBaseEntity::TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
void CBaseEntity::FireBullets(ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker ) { }
void CBaseEntity :: TraceBleed( float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType ) { }
void CBaseMonster :: MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir ) { }
BOOL CBaseMonster :: FGetNodeRoute ( Vector vecDest ) { return TRUE; }
int CBaseMonster :: FindHintNode ( void ) { return NO_NODE; }
void CBaseMonster::ReportAIState( void ) { }
void CBaseMonster :: KeyValue( KeyValueData *pkvd ) { }
BOOL CBaseMonster :: FCheckAITrigger ( void ) { return FALSE; }
int CBaseMonster :: CanPlaySequence( BOOL fDisregardMonsterState, int interruptLevel ) { return FALSE; }
BOOL CBaseMonster :: FindLateralCover ( const Vector &vecThreat, const Vector &vecViewOffset ) { return FALSE; }
Vector CBaseMonster :: ShootAtEnemy( const Vector &shootOrigin ) { return g_vecZero; }
BOOL CBaseMonster :: FacingIdeal( void ) { return FALSE; }
BOOL CBaseMonster :: FCanActiveIdle ( void ) { return FALSE; }
void CBaseMonster::PlaySentence( const char *pszSentence, float duration, float volume, float attenuation ) { }
void CBaseMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener ) { }
void CBaseMonster::SentenceStop( void ) { }
void CBaseMonster::CorpseFallThink( void ) { }
void CBaseMonster :: MonsterInitDead( void ) { }
BOOL CBaseMonster :: BBoxFlat ( void ) { return TRUE; }
BOOL CBaseMonster :: GetEnemy ( void ) { return FALSE; }
void CBaseMonster :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
CBaseEntity* CBaseMonster :: DropItem ( char *pszItemName, const Vector &vecPos, const Vector &vecAng ) { return NULL; }
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 ) { }
@ -136,16 +223,26 @@ void CBaseMonster :: GibMonster( void ) { }
BOOL CBaseMonster :: HasHumanGibs( void ) { return FALSE; }
BOOL CBaseMonster :: HasAlienGibs( void ) { return FALSE; }
Activity CBaseMonster :: GetDeathActivity ( void ) { return ACT_DIE_HEADSHOT; }
MONSTERSTATE CBaseMonster :: GetIdealState ( void ) { return MONSTERSTATE_ALERT; }
Schedule_t* CBaseMonster :: GetScheduleOfType ( int Type ) { return NULL; }
Schedule_t *CBaseMonster :: GetSchedule ( void ) { return NULL; }
void CBaseMonster :: RunTask ( Task_t *pTask ) { }
void CBaseMonster :: StartTask ( Task_t *pTask ) { }
Schedule_t *CBaseMonster::ScheduleFromName( const char *pName ) { return NULL;}
void CBaseMonster::BecomeDead( void ) {}
void CBaseMonster :: RunAI ( 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 CBaseMonster::Restore( class CRestore & ) { return 1; }
int CBaseMonster::Save( class CSave & ) { return 1; }
int TrainSpeed(int iSpeed, int iMax) { return 0; }
void CBasePlayer :: DeathSound( void ) { }
int CBasePlayer :: TakeHealth( float flHealth, int bitsDamageType ) { return 0; }
void CBasePlayer :: TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType) { }
int CBasePlayer :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType ) { return 0; }
void CBasePlayer::PackDeadPlayerItems( void ) { }
void CBasePlayer::RemoveAllItems( BOOL removeSuit ) { }
void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) { }
void CBasePlayer::WaterMove() { }
@ -157,8 +254,6 @@ void CBasePlayer::PlayerUse ( void ) { }
void CBasePlayer::Jump() { }
void CBasePlayer::Duck( ) { }
int CBasePlayer::Classify ( void ) { return 0; }
void CBasePlayer :: PlayStepSound(int step, float fvol) { }
void CBasePlayer :: UpdateStepSound( void ) { }
void CBasePlayer::PreThink(void) { }
void CBasePlayer::CheckTimeBasedDamage() { }
void CBasePlayer :: UpdateGeigerCounter( void ) { }
@ -247,4 +342,6 @@ 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 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 ){}

View file

@ -24,9 +24,22 @@ 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_TrainPitchAdjust( struct event_args_s *args );
}
@ -50,8 +63,18 @@ void Game_HookEvents( void )
gEngfuncs.pfnHookEvent( "events/shotgun1.sc", EV_FireShotGunSingle );
gEngfuncs.pfnHookEvent( "events/shotgun2.sc", EV_FireShotGunDouble );
gEngfuncs.pfnHookEvent( "events/mp5.sc", EV_FireMP5 );
gEngfuncs.pfnHookEvent( "events/mp52.sc", EV_FireMP52 );
gEngfuncs.pfnHookEvent( "events/python.sc", EV_FirePython );
gEngfuncs.pfnHookEvent( "events/gauss.sc", EV_FireGauss );
gEngfuncs.pfnHookEvent( "events/gaussspin.sc", EV_SpinGauss );
gEngfuncs.pfnHookEvent( "events/train.sc", EV_TrainPitchAdjust );
}
gEngfuncs.pfnHookEvent( "events/crowbar.sc", EV_Crowbar );
gEngfuncs.pfnHookEvent( "events/crossbow1.sc", EV_FireCrossbow );
gEngfuncs.pfnHookEvent( "events/crossbow2.sc", EV_FireCrossbow2 );
gEngfuncs.pfnHookEvent( "events/rpg.sc", EV_FireRpg );
gEngfuncs.pfnHookEvent( "events/egon_fire.sc", EV_EgonFire );
gEngfuncs.pfnHookEvent( "events/egon_stop.sc", EV_EgonStop );
gEngfuncs.pfnHookEvent( "events/firehornet.sc", EV_HornetGunFire );
gEngfuncs.pfnHookEvent( "events/tripfire.sc", EV_TripmineFire );
gEngfuncs.pfnHookEvent( "events/snarkfire.sc", EV_SnarkFire );
}

View file

@ -16,6 +16,59 @@
#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"
extern BEAM *pBeam;
extern BEAM *pBeam2;
void HUD_GetLastOrg( float *org );
void UpdateBeams ( void )
{
vec3_t forward, vecSrc, vecEnd, origin, angles, right, up;
vec3_t view_ofs;
pmtrace_t tr;
cl_entity_t *pthisplayer = gEngfuncs.GetLocalPlayer();
int idx = pthisplayer->index;
// Get our exact viewangles from engine
gEngfuncs.GetViewAngles( (float *)angles );
// Determine our last predicted origin
HUD_GetLastOrg( (float *)&origin );
AngleVectors( angles, forward, right, up );
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();
if ( pBeam )
pBeam->target = tr.endpos;
if ( pBeam2 )
pBeam2->target = tr.endpos;
}
/*
=====================
Game_AddObjects
@ -25,4 +78,6 @@ Add game specific, client-side objects here
*/
void Game_AddObjects( void )
{
}
if ( pBeam && pBeam2 )
UpdateBeams();
}

View file

@ -45,8 +45,24 @@ static globalvars_t Globals;
static CBasePlayerWeapon *g_pWpns[ 32 ];
vec3_t previousorigin;
// HLDM Weapon placeholder entities.
CGlock g_Glock;
CCrowbar g_Crowbar;
CPython g_Python;
CMP5 g_Mp5;
CCrossbow g_Crossbow;
CShotgun g_Shotgun;
CRpg g_Rpg;
CGauss g_Gauss;
CEgon g_Egon;
CHgun g_HGun;
CHandGrenade g_HandGren;
CSatchel g_Satchel;
CTripmine g_Tripmine;
CSqueak g_Snark;
/*
======================
@ -68,6 +84,18 @@ void AlertMessage( ALERT_TYPE atype, char *szFmt, ... )
gEngfuncs.Con_Printf( string );
}
//Returns if it's multiplayer.
//Mostly used by the client side weapons.
bool bIsMultiplayer ( void )
{
return gEngfuncs.GetMaxClients() == 1 ? 0 : 1;
}
//Just loads a v_ model.
void LoadVModel ( char *szViewModel, CBasePlayer *m_pPlayer )
{
gEngfuncs.CL_LoadModel( szViewModel, &m_pPlayer->pev->viewmodel );
}
/*
=====================
HUD_PrepEntity
@ -96,133 +124,6 @@ void HUD_PrepEntity( CBaseEntity *pEntity, CBasePlayer *pWeaponOwner )
}
}
/*
// FIXME: In order to predict animations client side, you'll need to work with the following code.
// It's not quite working, but it should be of use if you want
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pmodel -
// *label -
// Output : int
//-----------------------------------------------------------------------------
int LookupSequence( void *pmodel, const char *label )
{
studiohdr_t *pstudiohdr;
pstudiohdr = (studiohdr_t *)pmodel;
if (! pstudiohdr)
return 0;
mstudioseqdesc_t *pseqdesc;
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
for (int i = 0; i < pstudiohdr->numseq; i++)
{
if (stricmp( pseqdesc[i].label, label ) == 0)
return i;
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *label -
// Output : int CBaseAnimating :: LookupSequence
//-----------------------------------------------------------------------------
int CBaseAnimating :: LookupSequence ( const char *label )
{
cl_entity_t *current;
current = gEngfuncs.GetLocalPlayer();
if ( !current || !current->model )
return 0;
return ::LookupSequence( (studiohdr_t *)IEngineStudio.Mod_Extradata( current->model ), label );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pmodel -
// *pev -
// *pflFrameRate -
// *pflGroundSpeed -
//-----------------------------------------------------------------------------
void GetSequenceInfo( void *pmodel, entvars_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;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pmodel -
// *pev -
// Output : int
//-----------------------------------------------------------------------------
int GetSequenceFlags( void *pmodel, entvars_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;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
//-----------------------------------------------------------------------------
void CBaseAnimating :: ResetSequenceInfo ( )
{
cl_entity_t *current;
current = gEngfuncs.GetLocalPlayer();
if ( !current || !current->model )
return;
void *pmodel = (studiohdr_t *)IEngineStudio.Mod_Extradata( current->model );
GetSequenceInfo( pmodel, pev, &m_flFrameRate, &m_flGroundSpeed );
m_fSequenceLoops = ((GetSequenceFlags() & STUDIO_LOOPING) != 0);
pev->animtime = gpGlobals->time;
pev->framerate = 1.0;
m_fSequenceFinished = FALSE;
m_flLastEventCheck = gpGlobals->time;
}
*/
/*
=====================
CBaseEntity :: Killed
@ -242,7 +143,7 @@ CBasePlayerWeapon :: DefaultReload
*/
BOOL CBasePlayerWeapon :: DefaultReload( int iClipSize, int iAnim, float fDelay )
{
#if 0 // FIXME, need to know primary ammo to get this right
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
return FALSE;
@ -250,7 +151,6 @@ BOOL CBasePlayerWeapon :: DefaultReload( int iClipSize, int iAnim, float fDelay
if (j == 0)
return FALSE;
#endif
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + fDelay;
@ -366,15 +266,49 @@ CBasePlayerWeapon::SendWeaponAnim
Animate weapon model
=====================
*/
void CBasePlayerWeapon::SendWeaponAnim( int iAnim, int skiplocal )
void CBasePlayerWeapon::SendWeaponAnim( int iAnim, int skiplocal, int body )
{
m_pPlayer->pev->weaponanim = iAnim;
int body = 0;
HUD_SendWeaponAnim( iAnim, body, 0 );
}
/*
=====================
CBaseEntity::FireBulletsPlayer
Only produces random numbers to match the server ones.
=====================
*/
Vector CBaseEntity::FireBulletsPlayer ( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq, int iDamage, entvars_t *pevAttacker, int shared_rand )
{
float x, y, z;
for ( ULONG iShot = 1; iShot <= cShots; iShot++ )
{
if ( pevAttacker == NULL )
{
// get circular gaussian spread
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);
}
else
{
//Use player's random seed.
// get circular gaussian spread
x = UTIL_SharedRandomFloat( shared_rand + iShot, -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 1 + iShot ) , -0.5, 0.5 );
y = UTIL_SharedRandomFloat( shared_rand + ( 2 + iShot ), -0.5, 0.5 ) + UTIL_SharedRandomFloat( shared_rand + ( 3 + iShot ), -0.5, 0.5 );
z = x * x + y * y;
}
}
return Vector ( x * vecSpread.x, y * vecSpread.y, 0.0 );
}
/*
=====================
CBasePlayerWeapon::ItemPostFrame
@ -516,8 +450,8 @@ CBasePlayer::Killed
void CBasePlayer::Killed( entvars_t *pevAttacker, int iGib )
{
// Holster weapon immediately, to allow it to cleanup
if (m_pActiveItem)
m_pActiveItem->Holster( );
if ( m_pActiveItem )
m_pActiveItem->Holster( );
}
/*
@ -678,6 +612,55 @@ void HUD_InitClientWeapons( void )
// Allocate slot(s) for each weapon that we are going to be predicting
HUD_PrepEntity( &g_Glock , &player );
HUD_PrepEntity( &g_Crowbar , &player );
HUD_PrepEntity( &g_Python , &player );
HUD_PrepEntity( &g_Mp5 , &player );
HUD_PrepEntity( &g_Crossbow , &player );
HUD_PrepEntity( &g_Shotgun , &player );
HUD_PrepEntity( &g_Rpg , &player );
HUD_PrepEntity( &g_Gauss , &player );
HUD_PrepEntity( &g_Egon , &player );
HUD_PrepEntity( &g_HGun , &player );
HUD_PrepEntity( &g_HandGren , &player );
HUD_PrepEntity( &g_Satchel , &player );
HUD_PrepEntity( &g_Tripmine , &player );
HUD_PrepEntity( &g_Snark , &player );
}
/*
=====================
HUD_GetLastOrg
Retruns the last position that we stored for egon beam endpoint.
=====================
*/
void HUD_GetLastOrg( float *org )
{
int i;
// Return last origin
for ( i = 0; i < 3; i++ )
{
org[i] = previousorigin[i];
}
}
/*
=====================
HUD_SetLastOrg
Remember our exact predicted origin so we can draw the egon to the right position.
=====================
*/
void HUD_SetLastOrg( void )
{
int i;
// Offset final origin by view_offset
for ( i = 0; i < 3; i++ )
{
previousorigin[i] = g_finalstate->playerstate.origin[i] + g_finalstate->client.view_ofs[ i ];
}
}
/*
@ -707,9 +690,83 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
// FIXME, make this a method in each weapon? where you pass in an entity_state_t *?
switch ( from->client.m_iId )
{
case WEAPON_GLOCK:
pWeapon = &g_Glock;
break;
case WEAPON_CROWBAR:
pWeapon = &g_Crowbar;
break;
case WEAPON_GLOCK:
pWeapon = &g_Glock;
break;
case WEAPON_PYTHON:
pWeapon = &g_Python;
break;
case WEAPON_MP5:
pWeapon = &g_Mp5;
break;
case WEAPON_CROSSBOW:
pWeapon = &g_Crossbow;
break;
case WEAPON_SHOTGUN:
pWeapon = &g_Shotgun;
break;
case WEAPON_RPG:
pWeapon = &g_Rpg;
break;
case WEAPON_GAUSS:
pWeapon = &g_Gauss;
break;
case WEAPON_EGON:
pWeapon = &g_Egon;
break;
case WEAPON_HORNETGUN:
pWeapon = &g_HGun;
break;
case WEAPON_HANDGRENADE:
pWeapon = &g_HandGren;
break;
case WEAPON_SATCHEL:
pWeapon = &g_Satchel;
break;
case WEAPON_TRIPMINE:
pWeapon = &g_Tripmine;
break;
case WEAPON_SNARK:
pWeapon = &g_Snark;
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.
@ -727,10 +784,23 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
pfrom = &from->weapondata[ i ];
pCurrent->m_fInReload = pfrom->m_fInReload;
pCurrent->m_fInSpecialReload = pfrom->m_fInSpecialReload;
// pCurrent->m_flPumpTime = pfrom->m_flPumpTime;
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->pev->fuser1 = pfrom->fuser1;
pCurrent->m_flStartThrow = pfrom->fuser2;
pCurrent->m_flReleaseThrow = pfrom->fuser3;
pCurrent->m_chargeReady = pfrom->iuser1;
pCurrent->m_fInAttack = pfrom->iuser2;
pCurrent->m_fireState = pfrom->iuser3;
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];
player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ] = (int)from->client.vuser4[2];
}
// For random weapon events, use this seed to seed random # generator
@ -761,16 +831,31 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
player.pev->weaponanim = from->client.weaponanim;
player.pev->viewmodel = from->client.viewmodel;
player.m_flNextAttack = from->client.m_flNextAttack;
player.m_flNextAmmoBurn = from->client.fuser2;
player.m_flAmmoStartCharge = from->client.fuser3;
//Stores all our ammo info, so the client side weapons can use them.
player.ammo_9mm = (int)from->client.vuser1[0];
player.ammo_357 = (int)from->client.vuser1[1];
player.ammo_argrens = (int)from->client.vuser1[2];
player.ammo_bolts = (int)from->client.ammo_nails; //is an int anyways...
player.ammo_buckshot = (int)from->client.ammo_shells;
player.ammo_uranium = (int)from->client.ammo_cells;
player.ammo_hornets = (int)from->client.vuser2[0];
player.ammo_rockets = (int)from->client.ammo_rockets;
// Point to current weapon object
if ( from->client.m_iId )
{
player.m_pActiveItem = g_pWpns[ from->client.m_iId ];
}
// Store pointer to our destination entity_state_t so we can get our origin, etc. from it
// for setting up events on the client
g_finalstate = to;
if ( player.m_pActiveItem->m_iId == WEAPON_RPG )
{
( ( CRpg * )player.m_pActiveItem)->m_fSpotActive = (int)from->client.vuser2[ 1 ];
( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets = (int)from->client.vuser2[ 2 ];
}
// Don't go firing anything if we have died.
// Or if we don't have a weapon model deployed
@ -782,23 +867,6 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
}
}
// If we are running events/etc. go ahead and see if we
// managed to die between last frame and this one
// If so, run the appropriate player killed or spawn function
if ( g_runfuncs )
{
if ( to->client.health <= 0 && lasthealth > 0 )
{
player.Killed( NULL, 0 );
}
else if ( to->client.health > 0 && lasthealth <= 0 )
{
player.Spawn();
}
lasthealth = to->client.health;
}
// Assume that we are not going to switch weapons
to->client.m_iId = from->client.m_iId;
@ -830,18 +898,42 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
}
}
// Copy in results of predcition code
// 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.fuser2 = player.m_flNextAmmoBurn;
to->client.fuser3 = player.m_flAmmoStartCharge;
to->client.maxspeed = player.pev->maxspeed;
//HL Weapons
to->client.vuser1[0] = player.ammo_9mm;
to->client.vuser1[1] = player.ammo_357;
to->client.vuser1[2] = player.ammo_argrens;
to->client.ammo_nails = player.ammo_bolts;
to->client.ammo_shells = player.ammo_buckshot;
to->client.ammo_cells = player.ammo_uranium;
to->client.vuser2[0] = player.ammo_hornets;
to->client.ammo_rockets = player.ammo_rockets;
if ( player.m_pActiveItem->m_iId == WEAPON_RPG )
{
from->client.vuser2[ 1 ] = ( ( CRpg * )player.m_pActiveItem)->m_fSpotActive;
from->client.vuser2[ 2 ] = ( ( CRpg * )player.m_pActiveItem)->m_cActiveRockets;
}
// Make sure that weapon animation matches what the game .dll is telling us
// over the wire ( fixes some animation glitches )
if ( g_runfuncs && ( HUD_GetWeaponAnim() != to->client.weaponanim ) )
{
int body = 2;
//Pop the model to body 0.
if ( pWeapon == &g_Tripmine )
body = 0;
// Force a fixed anim down to viewmodel
HUD_SendWeaponAnim( to->client.weaponanim, body, 1 );
}
@ -859,10 +951,18 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
}
pto->m_fInReload = pCurrent->m_fInReload;
pto->m_fInSpecialReload = pCurrent->m_fInSpecialReload;
// pto->m_flPumpTime = pCurrent->m_flPumpTime;
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->fuser1 = pCurrent->pev->fuser1;
pto->fuser2 = pCurrent->m_flStartThrow;
pto->fuser3 = pCurrent->m_flReleaseThrow;
pto->iuser1 = pCurrent->m_chargeReady;
pto->iuser2 = pCurrent->m_fInAttack;
pto->iuser3 = pCurrent->m_fireState;
// Decrement weapon counters, server does this at same time ( during post think, after doing everything else )
pto->m_flNextReload -= cmd->msec / 1000.0;
@ -870,13 +970,19 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
pto->m_flNextPrimaryAttack -= cmd->msec / 1000.0;
pto->m_flNextSecondaryAttack -= cmd->msec / 1000.0;
pto->m_flTimeWeaponIdle -= cmd->msec / 1000.0;
pto->fuser1 -= cmd->msec / 1000.0;
if ( pto->m_flPumpTime != -9999 )
to->client.vuser3[2] = pCurrent->m_iSecondaryAmmoType;
to->client.vuser4[0] = pCurrent->m_iPrimaryAmmoType;
to->client.vuser4[1] = player.m_rgAmmo[ pCurrent->m_iPrimaryAmmoType ];
to->client.vuser4[2] = player.m_rgAmmo[ pCurrent->m_iSecondaryAmmoType ];
/* if ( pto->m_flPumpTime != -9999 )
{
pto->m_flPumpTime -= cmd->msec / 1000.0;
if ( pto->m_flPumpTime < -0.001 )
pto->m_flPumpTime = -0.001;
}
}*/
if ( pto->m_fNextAimBonus < -1.0 )
{
@ -902,6 +1008,11 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
{
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
@ -911,62 +1022,25 @@ void HUD_WeaponsPostThink( local_state_s *from, local_state_s *to, usercmd_t *cm
to->client.m_flNextAttack = -0.001;
}
to->client.fuser2 -= cmd->msec / 1000.0;
if ( to->client.fuser2 < -0.001 )
{
to->client.fuser2 = -0.001;
}
to->client.fuser3 -= cmd->msec / 1000.0;
if ( to->client.fuser3 < -0.001 )
{
to->client.fuser3 = -0.001;
}
// Store off the last position from the predicted state.
HUD_SetLastOrg();
// Wipe it so we can't use it after this frame
g_finalstate = NULL;
}
// For storing predicted sequence and gaitsequence and origin/angles data
static int g_rseq = 0, g_gaitseq = 0;
static vec3_t g_clorg, g_clang;
//-----------------------------------------------------------------------------
// Purpose:
// Input : *seq -
// *gaitseq -
//-----------------------------------------------------------------------------
void Game_GetSequence( int *seq, int *gaitseq )
{
*seq = g_rseq;
*gaitseq = g_gaitseq;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : seq -
// gaitseq -
//-----------------------------------------------------------------------------
void Game_SetSequence( int seq, int gaitseq )
{
g_rseq = seq;
g_gaitseq = gaitseq;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : o -
// a -
//-----------------------------------------------------------------------------
void Game_SetOrientation( vec3_t o, vec3_t a )
{
g_clorg = o;
g_clang = a;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *o -
// *a -
//-----------------------------------------------------------------------------
void Game_GetOrientation( float *o, float *a )
{
int i;
for ( i = 0; i < 3; i++ )
{
o[ i ] = g_clorg[ i ];
a[ i ] = g_clang[ i ];
}
}
/*
=====================
@ -983,11 +1057,8 @@ void _DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s
{
g_runfuncs = runfuncs;
// Only run post think stuff for glock for the sample
// implementation
#if defined( CLIENT_WEAPONS )
if ( cl_lw && cl_lw->value &&
from->client.m_iId == WEAPON_GLOCK )
if ( cl_lw && cl_lw->value )
{
HUD_WeaponsPostThink( from, to, cmd, time, random_seed );
}
@ -997,13 +1068,6 @@ void _DLLEXPORT HUD_PostRunCmd( struct local_state_s *from, struct local_state_s
to->client.fov = g_lastFOV;
}
// Store of final sequence, etc. for client side animation
if ( g_runfuncs )
{
Game_SetSequence( to->playerstate.sequence, to->playerstate.gaitsequence );
Game_SetOrientation( to->playerstate.origin, cmd->viewangles );
}
// All games can use FOV state
g_lastFOV = to->client.fov;
}

View file

@ -24,10 +24,59 @@
#include <stdio.h>
#include "parsemsg.h"
#include "hud_servers.h"
#include "vgui_int.h"
#include "vgui_TeamFortressViewport.h"
#include "demo.h"
#include "demo_api.h"
#include "vgui_scorepanel.h"
class CHLVoiceStatusHelper : public IVoiceStatusHelper
{
public:
virtual void GetPlayerTextColor(int entindex, int color[3])
{
color[0] = color[1] = color[2] = 255;
if( entindex >= 0 && entindex < sizeof(g_PlayerExtraInfo)/sizeof(g_PlayerExtraInfo[0]) )
{
int iTeam = g_PlayerExtraInfo[entindex].teamnumber;
if ( iTeam < 0 )
{
iTeam = 0;
}
iTeam = iTeam % iNumberOfTeamColors;
color[0] = iTeamColors[iTeam][0];
color[1] = iTeamColors[iTeam][1];
color[2] = iTeamColors[iTeam][2];
}
}
virtual void UpdateCursorState()
{
gViewPort->UpdateCursorState();
}
virtual int GetAckIconHeight()
{
return ScreenHeight - gHUD.m_iFontHeight*3 - 6;
}
virtual bool CanShowSpeakerLabels()
{
if( gViewPort && gViewPort->m_pScoreBoard )
return !gViewPort->m_pScoreBoard->isVisible();
else
return false;
}
};
static CHLVoiceStatusHelper g_VoiceStatusHelper;
extern client_sprite_t *GetSpriteList(client_sprite_t *pList, const char *psz, int iRes, int iCount);
@ -245,6 +294,10 @@ void CHud :: Init( void )
// VGUI Menus
HOOK_MESSAGE( VGUIMenu );
CVAR_CREATE( "hud_classautokill", "1", FCVAR_ARCHIVE | FCVAR_USERINFO ); // controls whether or not to suicide immediately on TF class switch
CVAR_CREATE( "hud_takesshots", "0", FCVAR_ARCHIVE ); // controls whether or not to automatically take screenshots at the end of a round
m_iLogo = 0;
m_iFOV = 0;
@ -284,6 +337,8 @@ void CHud :: Init( void )
m_AmmoSecondary.Init();
m_TextMessage.Init();
m_StatusIcons.Init();
GetClientVoiceMgr()->Init(&g_VoiceStatusHelper, (vgui::Panel**)&gViewPort);
m_Spectator.Init();
m_SayText.Init();
m_Menu.Init();
@ -431,6 +486,8 @@ void CHud :: VidInit( void )
m_AmmoSecondary.VidInit();
m_TextMessage.VidInit();
m_StatusIcons.VidInit();
GetClientVoiceMgr()->VidInit();
m_Spectator.VidInit();
}
int CHud::MsgFunc_Logo(const char *pszName, int iSize, void *pbuf)
@ -544,10 +601,8 @@ int CHud::MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf)
int newfov = READ_BYTE();
int def_fov = CVAR_GET_FLOAT( "default_fov" );
int tfc = 0;
tfc = HUD_IsGame( "tfc" );
if ( tfc && cl_lw && cl_lw->value )
//Weapon prediction already takes care of changing the fog. ( g_lastFOV ).
if ( cl_lw && cl_lw->value )
return 1;
g_lastFOV = newfov;

View file

@ -40,17 +40,26 @@ typedef struct {
int x, y;
} POSITION;
enum
{
MAX_PLAYERS = 64,
MAX_TEAMS = 64,
MAX_TEAM_NAME = 16,
};
typedef struct {
unsigned char r,g,b,a;
} RGBA;
typedef struct cvar_s cvar_t;
#define HUD_ACTIVE 1
#define HUD_INTERMISSION 2
#define MAX_PLAYER_NAME_LENGTH 32
#define MAX_MOTD_LENGTH 1024
#define MAX_MOTD_LENGTH 1536
//
//-----------------------------------------------------
@ -61,6 +70,7 @@ 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;}
@ -76,6 +86,14 @@ struct HUDLIST {
};
//
//-----------------------------------------------------
//
#include "..\game_shared\voice_status.h"
#include "hud_spectator.h"
//
//-----------------------------------------------------
//
@ -236,6 +254,9 @@ protected:
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];
};
//
@ -273,13 +294,6 @@ private:
};
*/
enum
{
MAX_PLAYERS = 64,
MAX_TEAMS = 64,
MAX_TEAM_NAME = 16,
};
struct extra_player_info_t
{
short frags;
@ -522,7 +536,7 @@ private:
//-----------------------------------------------------
//
typedef struct cvar_s cvar_t;
class CHud
{
@ -580,20 +594,21 @@ public:
int GetSpriteIndex( const char *SpriteName ); // gets a sprite index, for use in the m_rghSprites[] array
CHudAmmo m_Ammo;
CHudHealth m_Health;
CHudGeiger m_Geiger;
CHudBattery m_Battery;
CHudTrain m_Train;
CHudFlashlight m_Flash;
CHudMessage m_Message;
CHudStatusBar m_StatusBar;
CHudAmmo m_Ammo;
CHudHealth m_Health;
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;
CHudSayText m_SayText;
CHudMenu m_Menu;
CHudAmmoSecondary m_AmmoSecondary;
CHudTextMessage m_TextMessage;
CHudStatusIcons m_StatusIcons;
CHudSpectator m_Spectator;
void Init( void );
void VidInit( void );
@ -612,6 +627,7 @@ public:
void _cdecl MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf );
int _cdecl MsgFunc_SetFOV(const char *pszName, int iSize, void *pbuf);
int _cdecl MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf );
// Screen information
SCREENINFO m_scrinfo;
@ -638,4 +654,5 @@ extern int g_iPlayerClass;
extern int g_iTeamNumber;
extern int g_iUser1;
extern int g_iUser2;
extern int g_iUser3;

View file

@ -19,7 +19,14 @@
#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
#include "r_efx.h"
#define MAX_CLIENTS 32
#if !defined( _TFC )
extern BEAM *pBeam;
extern BEAM *pBeam2;
#endif
/// USER-DEFINED SERVER MESSAGE HANDLERS
int CHud :: MsgFunc_ResetHUD(const char *pszName, int iSize, void *pbuf )
@ -56,6 +63,10 @@ void CHud :: MsgFunc_InitHUD( const char *pszName, int iSize, void *pbuf )
pList->p->InitHUDData();
pList = pList->pNext;
}
#if !defined( _TFC )
//Probably not a good place to put this.
pBeam = pBeam2 = NULL;
#endif
}
@ -102,4 +113,3 @@ int CHud :: MsgFunc_Concuss( const char *pszName, int iSize, void *pbuf )
this->m_StatusIcons.DisableIcon("dmg_concuss");
return 1;
}

View file

@ -108,6 +108,7 @@ int CHud :: Redraw( float flTime, int intermission )
else if ( !m_iIntermission && intermission )
{
gViewPort->HideCommandMenu();
gViewPort->HideVGUIMenu();
gViewPort->ShowScoreBoard();
// Take a screenshot if the client's got the cvar set

1179
cl_dll/hud_spectator.cpp Normal file

File diff suppressed because it is too large Load diff

113
cl_dll/hud_spectator.h Normal file
View file

@ -0,0 +1,113 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef SPECTATOR_H
#define SPECTATOR_H
#pragma once
#include "cl_entity.h"
#define MAIN_CHASE_LOCKED 1
#define MAIN_CHASE_FREE 2
#define MAIN_ROAMING 3
#define MAIN_IN_EYE 4
#define MAIN_MAP_FREE 5
#define INSET_OFF 0
#define INSET_CHASE_FREE 1
#define INSET_IN_EYE 2
#define INSET_MAP_FREE 3
#define OVERVIEW_TILE_SIZE 128 // 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 {
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:
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 DirectorEvent(unsigned char command, unsigned int firstObject, unsigned int secondObject, unsigned int flags);
void SetSpectatorStartPosition();
int Init();
int VidInit();
int Draw(float flTime);
int m_iMainMode;
int m_iInsetMode;
int m_iDrawCycle;
overviewInfo_t m_OverviewData;
overviewEntity_t m_OverviewEntities[MAX_OVERVIEW_ENTITIES];
int m_iObserverTarget;
float m_mapZoom; // zoom the user currently uses
vec3_t m_mapOrigin; // origin where user rotates around
vec3_t m_mapAngles; // cuurent map view angles
private:
cvar_t * m_drawnames;
vec3_t m_vPlayerPos[MAX_PLAYERS];
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;
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

View file

@ -22,6 +22,7 @@ extern "C"
#include "vgui_TeamFortressViewport.h"
extern "C"
{
struct kbutton_s DLLEXPORT *KB_Find( const char *name );
@ -391,18 +392,57 @@ void IN_LeftDown(void) {KeyDown(&in_left);}
void IN_LeftUp(void) {KeyUp(&in_left);}
void IN_RightDown(void) {KeyDown(&in_right);}
void IN_RightUp(void) {KeyUp(&in_right);}
void IN_ForwardDown(void) {KeyDown(&in_forward);}
void IN_ForwardUp(void) {KeyUp(&in_forward);}
void IN_BackDown(void) {KeyDown(&in_back);}
void IN_BackUp(void) {KeyUp(&in_back);}
void IN_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);}
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
void IN_MoverightDown(void) {KeyDown(&in_moveright);}
void IN_MoverightUp(void) {KeyUp(&in_moveright);}
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);}
@ -410,18 +450,30 @@ void IN_StrafeUp(void) {KeyUp(&in_strafe);}
// needs capture by hud/vgui also
extern void __CmdFunc_InputPlayerSpecial(void);
void IN_Attack2Down(void)
{
KeyDown(&in_attack2);
__CmdFunc_InputPlayerSpecial();
gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK2 );
}
void IN_Attack2Up(void) {KeyUp(&in_attack2);}
void IN_UseDown (void) {KeyDown(&in_use);}
void IN_UseUp (void) {KeyUp(&in_use);}
void IN_JumpDown (void) {KeyDown(&in_jump);}
void IN_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);}
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);}
@ -433,6 +485,7 @@ void IN_GraphUp(void) {KeyUp(&in_graph);}
void IN_AttackDown(void)
{
KeyDown( &in_attack );
gHUD.m_Spectator.HandleButtonsDown( IN_ATTACK );
}
void IN_AttackUp(void)
@ -672,6 +725,10 @@ void DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int activ
//
cmd->buttons = CL_ButtonBits( 1 );
// If they're in a modal dialog, ignore the attack button.
if(GetClientVoiceMgr()->IsInSquelchMode())
cmd->buttons &= ~IN_ATTACK;
// Using joystick?
if ( in_joystick->value )
{
@ -697,6 +754,7 @@ void DLLEXPORT CL_CreateMove ( float frametime, struct usercmd_s *cmd, int activ
{
VectorCopy( oldangles, cmd->viewangles );
}
}
/*
@ -956,4 +1014,4 @@ void ShutdownInput (void)
void DLLEXPORT HUD_Shutdown( void )
{
ShutdownInput();
}
}

View file

@ -462,10 +462,11 @@ void CHudMessage::MessageAdd( const char *pName, float time )
{
return;
}
// get rid of any other messages in same location (only one displays at a time)
else if ( abs( tempMessage->y - m_pMessages[j]->y ) < 1 )
if ( fabs( tempMessage->y - m_pMessages[j]->y ) < 0.0001 )
{
if ( abs( tempMessage->x - m_pMessages[j]->x ) < 1 )
if ( fabs( tempMessage->x - m_pMessages[j]->x ) < 0.0001 )
{
m_pMessages[j] = NULL;
}

View file

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

160
cl_dll/overview.cpp Normal file
View file

@ -0,0 +1,160 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "hud.h"
#include "cl_util.h"
#include "cl_entity.h"
#include "triangleapi.h"
#include "vgui_TeamFortressViewport.h"
// these are included for the math functions
#include "com_model.h"
#include "studio_util.h"
#pragma warning(disable: 4244)
//-----------------------------------------------------------------------------
// 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
gViewPort->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 );
}

31
cl_dll/overview.h Normal file
View file

@ -0,0 +1,31 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef OVERVIEW_H
#define OVERVIEW_H
#pragma once
//-----------------------------------------------------------------------------
// 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

View file

@ -57,6 +57,8 @@ int CHudSayText :: Init( void )
CVAR_CREATE( "hud_saytext_time", "5", 0 );
m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission
return 1;
}
@ -164,7 +166,11 @@ int CHudSayText :: MsgFunc_SayText( const char *pszName, int iSize, void *pbuf )
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
for ( int i = 0; i < MAX_LINES; i++ )

162
cl_dll/soundsystem.cpp Normal file
View file

@ -0,0 +1,162 @@
//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include <windows.h>
#include <dsound.h>
#include <mmsystem.h>
#include "r_studioint.h"
extern engine_studio_api_t IEngineStudio;
#define RENDERTYPE_UNDEFINED 0
#define RENDERTYPE_SOFTWARE 1
#define RENDERTYPE_HARDWARE 2
#define ENGINE_LAUNCHER_API_VERSION 1
LPDIRECTSOUND lpDS = NULL;
LPDIRECTSOUNDBUFFER lpDSBuf = NULL;
LPHWAVEOUT lpHW = NULL;
static HMODULE hEngine = 0;
typedef struct engine_api_s
{
int version;
int rendertype;
int size;
// Functions
void ( *unused1 ) ( void );
void ( *unused2 ) ( void );
void ( *unused3 ) ( void );
void ( *unused4 ) ( 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 ( *unused16 ) ( void );
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 );
void ( *unused28 ) ( void );
void ( *unused29 ) ( void );
void ( *unused30 ) ( void );
void ( *unused31 ) ( void );
void ( *unused32 ) ( void );
void ( *unused33 ) ( void );
void ( *unused34 ) ( void );
void ( *S_GetDSPointer ) ( struct IDirectSound **lpDS, struct IDirectSoundBuffer **lpDSBuf );
void *( *S_GetWAVPointer ) ( void );
void ( *unused35 ) ( void );
void ( *unused36 ) ( void );
void ( *unused37 ) ( void );
void ( *unused38 ) ( void );
void ( *unused39 ) ( void );
void ( *unused40 ) ( void );
void ( *unused41 ) ( void );
void ( *unused42 ) ( void );
void ( *unused43 ) ( void );
void ( *unused44 ) ( void );
void ( *unused45 ) ( void );
void ( *unused46 ) ( void );
void ( *unused47 ) ( void );
void ( *unused48 ) ( void );
void ( *unused49 ) ( void );
void ( *unused50 ) ( void );
void ( *unused51 ) ( void );
void ( *unused52 ) ( void );
void ( *unused53 ) ( void );
void ( *unused54 ) ( void );
void ( *unused55 ) ( void );
} engine_api_t;
static engine_api_t engineapi;
typedef int (*engine_api_func)( int version, int size, struct engine_api_s *api );
//-----------------------------------------------------------------------------
// Purpose: Get launcher/engine interface from engine module
// Input : hMod -
// Output : int
//-----------------------------------------------------------------------------
int Eng_LoadFunctions( HMODULE hMod )
{
engine_api_func pfnEngineAPI;
pfnEngineAPI = ( engine_api_func )GetProcAddress( hMod, "Sys_EngineAPI" );
if ( !pfnEngineAPI )
return 0;
if ( !(*pfnEngineAPI)( ENGINE_LAUNCHER_API_VERSION, sizeof( engine_api_t ), &engineapi ) )
return 0;
// All is okay
return 1;
}
//-----------------------------------------------------------------------------
// Purpose: Load proper engine .dll and get pointer to either DSound and primary buffer or HWAVEOUT ( NT 4.0, e.g. )
//-----------------------------------------------------------------------------
void LoadSoundAPIs( void )
{
hEngine = ::LoadLibrary( IEngineStudio.IsHardware() ? "hw.dll" : "sw.dll" );
if ( hEngine )
{
if ( Eng_LoadFunctions( hEngine ) )
{
if ( engineapi.S_GetDSPointer && engineapi.S_GetWAVPointer )
{
engineapi.S_GetDSPointer(&lpDS, &lpDSBuf);
lpHW = (HWAVEOUT FAR *)engineapi.S_GetWAVPointer();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Close engine library, release sound pointers
//-----------------------------------------------------------------------------
void ShutdownSoundAPIs( void )
{
if( hEngine )
{
FreeLibrary( hEngine );
hEngine = 0;
}
lpDS = 0;
lpDSBuf = 0;
lpHW = 0;
}

View file

@ -31,6 +31,9 @@ DECLARE_MESSAGE( m_StatusBar, StatusValue );
#define STATUSBAR_ID_LINE 1
float *GetClientColor( int clientIndex );
extern float g_ColorYellow[3];
int CHudStatusBar :: Init( void )
{
gHUD.AddHudElem( this );
@ -54,12 +57,18 @@ int CHudStatusBar :: VidInit( void )
void CHudStatusBar :: Reset( void )
{
int i = 0;
m_iFlags &= ~HUD_ACTIVE; // start out inactive
for ( int i = 0; i < MAX_STATUSBAR_LINES; i++ )
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 )
@ -133,11 +142,13 @@ void CHudStatusBar :: ParseStatusString( int line_num )
if ( g_PlayerInfoList[indexval].name != NULL )
{
strncpy( szRepString, g_PlayerInfoList[indexval].name, MAX_PLAYER_NAME_LENGTH );
m_pflNameColors[line_num] = GetClientColor( indexval );
}
else
{
strcpy( szRepString, "******" );
}
break;
case 'i': // number
sprintf( szRepString, "%d", indexval );
@ -166,7 +177,10 @@ 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;
}
@ -192,6 +206,9 @@ int CHudStatusBar :: Draw( float fTime )
y = (ScreenHeight / 2) + (TextHeight*CVAR_GET_FLOAT("hud_centerid"));
}
if ( m_pflNameColors[i] )
gEngfuncs.pfnDrawSetTextColor( m_pflNameColors[i][0], m_pflNameColors[i][1], m_pflNameColors[i][2] );
DrawConsoleString( x, y, m_szStatusBar[i] );
}

View file

@ -1129,6 +1129,8 @@ float already_chosen_map;
#define MENU_REFRESH_RATE 25
#define MENU_VOICETWEAK 50
//============================
// Timer Types
#define TF_TIMER_ANY 0

View file

@ -94,6 +94,8 @@ Non-transparent triangles-- add them here
void DLLEXPORT HUD_DrawNormalTriangles( void )
{
gHUD.m_Spectator.DrawOverview();
#if defined( TEST_IT )
// Draw_Triangles();
#endif

View file

@ -198,9 +198,11 @@ CClassMenuPanel::CClassMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide
// Open up the Class Briefing File
sprintf(sz, "classes/short_%s.txt", sTFClassSelection[i]);
char *cText = "Class Description not available.";
char *pfile = (char*)gEngfuncs.COM_LoadFile( sz, 5, NULL );
char *pfile = (char *)gEngfuncs.COM_LoadFile( sz, 5, NULL );
if (pfile)
{
cText = pfile;
}
// Create the Text info window
TextPanel *pTextWindow = new TextPanel(cText, textOffs, CLASSMENU_WINDOW_TEXT_Y, (CLASSMENU_WINDOW_SIZE_X - textOffs)-5, CLASSMENU_WINDOW_SIZE_Y - CLASSMENU_WINDOW_TEXT_Y);
@ -215,7 +217,7 @@ CClassMenuPanel::CClassMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide
int wide,tall;
pTextWindow->getTextImage()->getTextSizeWrapped( wide,tall);
pTextWindow->setSize(wide,tall);
//pTextWindow->setBorder(new LineBorder());
int xx,yy;
pTextWindow->getPos(xx,yy);
int maxX=xx+wide;
@ -318,7 +320,10 @@ void CClassMenuPanel::Update()
m_pPlayers[i]->setText( sz );
// Set the text color to the teamcolor
m_pPlayers[i]->setFgColor( iTeamColors[g_iTeamNumber][0], iTeamColors[g_iTeamNumber][1], iTeamColors[g_iTeamNumber][2], 0 );
m_pPlayers[i]->setFgColor( iTeamColors[g_iTeamNumber % iNumberOfTeamColors][0],
iTeamColors[g_iTeamNumber % iNumberOfTeamColors][1],
iTeamColors[g_iTeamNumber % iNumberOfTeamColors][2],
0 );
// set the graphic to be the team pick
for ( int team = 0; team < MAX_TEAMS; team++ )

View file

@ -32,6 +32,7 @@
#include "vgui_int.h"
#include "vgui_TeamFortressViewport.h"
#include "vgui_ServerBrowser.h"
#include "..\game_shared\vgui_LoadTGA.h"
// Arrow filenames
char *sArrowFilenames[] =
@ -42,20 +43,31 @@ char *sArrowFilenames[] =
"arrowrt",
};
// Get the name of TGA file, without a gamedir
char *GetTGANameForRes(const char *pszName)
{
int i;
char sz[256];
static char gd[256];
if (ScreenWidth < 640)
i = 320;
else
i = 640;
sprintf(sz, pszName, i);
sprintf(gd, "gfx/vgui/%s.tga", sz);
return gd;
}
//-----------------------------------------------------------------------------
// Purpose: Loads a .tga file and returns a pointer to the VGUI tga object
//-----------------------------------------------------------------------------
BitmapTGA *LoadTGA( const char* pImageName )
BitmapTGA *LoadTGAForRes( const char* pImageName )
{
BitmapTGA *pTGA;
char sz[256];
sprintf(sz, "%%d_%s", pImageName);
// Load the Image
FileInputStream* fis = new FileInputStream( GetVGUITGAName(sz), false );
pTGA = new BitmapTGA(fis,true);
fis->close();
pTGA = vgui_LoadTGA(GetTGANameForRes(sz));
return pTGA;
}
@ -283,14 +295,14 @@ int ClassButton::IsNotValid()
CImageLabel::CImageLabel( const char* pImageName,int x,int y ) : Label( "", x,y )
{
setContentFitted(true);
m_pTGA = LoadTGA(pImageName);
m_pTGA = LoadTGAForRes(pImageName);
setImage( m_pTGA );
}
CImageLabel::CImageLabel( const char* pImageName,int x,int y,int wide,int tall ) : Label( "", x,y,wide,tall )
{
setContentFitted(true);
m_pTGA = LoadTGA(pImageName);
m_pTGA = LoadTGAForRes(pImageName);
setImage( m_pTGA );
}
@ -328,7 +340,7 @@ CTFScrollButton::CTFScrollButton(int iArrow, const char* text,int x,int y,int wi
setFgColor(Scheme::sc_primary1);
// Load in the arrow
m_pTGA = LoadTGA( sArrowFilenames[iArrow] );
m_pTGA = LoadTGAForRes( sArrowFilenames[iArrow] );
setImage( m_pTGA );
// Highlight signal
@ -338,6 +350,9 @@ CTFScrollButton::CTFScrollButton(int iArrow, const char* text,int x,int y,int wi
void CTFScrollButton::paint( void )
{
if (!m_pTGA)
return;
// draw armed button text in white
if ( isArmed() )
{

View file

@ -104,6 +104,7 @@ CMessageWindowPanel::CMessageWindowPanel( const char *szMOTD, const char *szTitl
// Create the Scroll panel
ScrollPanel *pScrollPanel = new CTFScrollPanel( iXPos + XRES(16), iYPos + MOTD_TITLE_Y*2 + YRES(16), iXSize - XRES(32), iYSize - (YRES(48) + BUTTON_SIZE_Y*2) );
pScrollPanel->setParent(this);
//force the scrollbars on so clientClip will take them in account after the validate
pScrollPanel->setScrollBarAutoVisible(false, false);
pScrollPanel->setScrollBarVisible(true, true);
@ -120,13 +121,19 @@ CMessageWindowPanel::CMessageWindowPanel( const char *szMOTD, const char *szTitl
pSchemes->getBgColor( hMOTDText, r, g, b, a );
pText->setBgColor( r, g, b, a );
pText->setText(szMOTD);
pText->setSize(pScrollPanel->getClientClip()->getWide()-2, 5000);
// Get the total size of the MOTD text and resize the text panel
int iScrollSizeX, iScrollSizeY;
// First, set the size so that the client's wdith is correct at least because the
// width is critical for getting the "wrapped" size right.
// You'll see a horizontal scroll bar if there is a single word that won't wrap in the
// specified width.
pText->getTextImage()->setSize(pScrollPanel->getClientClip()->getWide(), pScrollPanel->getClientClip()->getTall());
pText->getTextImage()->getTextSizeWrapped( iScrollSizeX, iScrollSizeY );
// Now resize the textpanel to fit the scrolled size
pText->setSize( iScrollSizeX , iScrollSizeY );
//pText->setBorder(new LineBorder());
//turn the scrollbars back into automode
pScrollPanel->setScrollBarAutoVisible(true, true);

View file

@ -397,8 +397,6 @@ buildDefaultFont:
{
sprintf(fontFilename, "gfx\\vgui\\fonts\\%d_%s.tga", m_xRes, m_pSchemeList[i].schemeName);
pFontData = gEngfuncs.COM_LoadFile( fontFilename, 5, &fontFileLength );
if(!pFontData)
gEngfuncs.Con_Printf("Missing bitmap font: %s\n", fontFilename);
}
m_pSchemeList[i].font = new vgui::Font(

File diff suppressed because it is too large Load diff

View file

@ -7,116 +7,301 @@
#include<VGUI_HeaderPanel.h>
#include<VGUI_TextGrid.h>
#include<VGUI_Label.h>
#include<VGUI_TextImage.h>
#include "..\game_shared\vgui_listbox.h"
#define MAX_SCORES 10
#include <ctype.h>
#define MAX_SCORES 10
#define MAX_SCOREBOARD_TEAMS 5
// Scoreboard cells
#define NUM_COLUMNS 5
#define NUM_ROWS (MAX_PLAYERS + MAX_TEAMS)
// Scoreboard positions
#define SBOARD_INDENT_X XRES(104)
#define SBOARD_INDENT_Y YRES(40)
#define COLUMN_TRACKER 0
#define COLUMN_NAME 1
#define COLUMN_CLASS 2
#define COLUMN_KILLS 3
#define COLUMN_DEATHS 4
#define COLUMN_LATENCY 5
#define COLUMN_VOICE 6
#define COLUMN_BLANK 7
#define NUM_COLUMNS 8
#define NUM_ROWS (MAX_PLAYERS + (MAX_SCOREBOARD_TEAMS * 2))
using namespace vgui;
class CTextImage2 : public Image
{
public:
CTextImage2()
{
_image[0] = new TextImage("");
_image[1] = new TextImage("");
}
~CTextImage2()
{
delete _image[0];
delete _image[1];
}
TextImage *GetImage(int image)
{
return _image[image];
}
void getSize(int &wide, int &tall)
{
int w1, w2, t1, t2;
_image[0]->getTextSize(w1, t1);
_image[1]->getTextSize(w2, t2);
wide = w1 + w2;
tall = max(t1, t2);
setSize(wide, tall);
}
void doPaint(Panel *panel)
{
_image[0]->doPaint(panel);
_image[1]->doPaint(panel);
}
void setPos(int x, int y)
{
_image[0]->setPos(x, y);
int swide, stall;
_image[0]->getSize(swide, stall);
int wide, tall;
_image[1]->getSize(wide, tall);
_image[1]->setPos(x + wide, y + (stall * 0.9) - tall);
}
void setColor(Color color)
{
_image[0]->setColor(color);
}
void setColor2(Color color)
{
_image[1]->setColor(color);
}
private:
TextImage *_image[2];
};
//-----------------------------------------------------------------------------
// Purpose: Custom label for cells in the Scoreboard's Table Header
//-----------------------------------------------------------------------------
class CLabelHeader : public Label
{
private:
void Init( void )
{
setFont( Scheme::sf_primary1 );
setFgColor( Scheme::sc_primary1 );
setBgColor( 0,0,0, 255 );
}
public:
CLabelHeader(const char* text,int x,int y,int wide,int tall) : Label(text,x,y,wide,tall)
CLabelHeader() : Label("")
{
Init();
_dualImage = new CTextImage2();
_dualImage->setColor2(Color(255, 170, 0, 0));
_row = -2;
_useFgColorAsImageColor = true;
_offset[0] = 0;
_offset[1] = 0;
}
CLabelHeader(const char* text, bool bAlignLeft = false) : Label(text)
~CLabelHeader()
{
Init();
if (bAlignLeft)
setContentAlignment(Label::a_west);
delete _dualImage;
}
void setRow(int row)
{
_row = row;
}
void setFgColorAsImageColor(bool state)
{
_useFgColorAsImageColor = state;
}
virtual void setText(int textBufferLen, const char* text)
{
_dualImage->GetImage(0)->setText(text);
// calculate the text size
Font *font = _dualImage->GetImage(0)->getFont();
_gap = 0;
for (const char *ch = text; *ch != 0; ch++)
{
int a, b, c;
font->getCharABCwide(*ch, a, b, c);
_gap += (a + b + c);
}
_gap += XRES(5);
}
virtual void setText(const char* text)
{
// strip any non-alnum characters from the end
char buf[512];
strcpy(buf, text);
int len = strlen(buf);
while (len && isspace(buf[--len]))
{
buf[len] = 0;
}
CLabelHeader::setText(0, buf);
}
void setText2(const char *text)
{
_dualImage->GetImage(1)->setText(text);
}
void getTextSize(int &wide, int &tall)
{
_dualImage->getSize(wide, tall);
}
void setFgColor(int r,int g,int b,int a)
{
Label::setFgColor(r,g,b,a);
Color color(r,g,b,a);
_dualImage->setColor(color);
_dualImage->setColor2(color);
if (_image && _useFgColorAsImageColor)
{
_image->setColor(color);
}
repaint();
}
void setFgColor(Scheme::SchemeColor sc)
{
Label::setFgColor(sc);
_dualImage->setColor(sc);
}
void setFont(Font *font)
{
_dualImage->GetImage(0)->setFont(font);
}
void setFont2(Font *font)
{
_dualImage->GetImage(1)->setFont(font);
}
// this adjust the absolute position of the text after alignment is calculated
void setTextOffset(int x, int y)
{
_offset[0] = x;
_offset[1] = y;
}
void paint();
void paintBackground();
void calcAlignment(int iwide, int itall, int &x, int &y);
private:
CTextImage2 *_dualImage;
int _row;
int _gap;
int _offset[2];
bool _useFgColorAsImageColor;
};
//-----------------------------------------------------------------------------
// Purpose: Custom Table for the scoreboard
//-----------------------------------------------------------------------------
class ScoreTablePanel : public TablePanel
{
private:
TextGrid *_textGrid;
Label *m_pLabel;
class ScoreTablePanel;
public:
int m_iRows;
int m_iSortedRows[NUM_ROWS];
int m_iIsATeam[NUM_ROWS];
bool m_bHasBeenSorted[MAX_PLAYERS];
int m_iLastKilledBy;
int m_fLastKillTime;
public:
ScoreTablePanel(int x,int y,int wide,int tall,int columnCount) : TablePanel(x,y,wide,tall,columnCount)
{
setCellEditingEnabled(false);
m_pLabel = new Label( "", 0, 0, wide, tall );
m_pLabel->setFont( Scheme::sf_primary2 );
}
virtual int getRowCount()
{
return m_iRows;
}
virtual Panel* startCellEditing(int column,int row)
{
return null;
}
virtual Panel* getCellRenderer(int column,int row,bool columnSelected,bool rowSelected,bool cellSelected);
virtual int getCellTall(int row);
};
#include "..\game_shared\vgui_grid.h"
#include "..\game_shared\vgui_defaultinputsignal.h"
//-----------------------------------------------------------------------------
// Purpose: Scoreboard back panel
//-----------------------------------------------------------------------------
class ScorePanel : public Panel
class ScorePanel : public Panel, public vgui::CDefaultInputSignal
{
private:
HeaderPanel *_headerPanel;
ScoreTablePanel *_tablePanel;
Label *m_pTitleLabel;
// Default panel implementation doesn't forward mouse messages when there is no cursor and we need them.
class HitTestPanel : public Panel
{
public:
virtual void internalMousePressed(MouseCode code);
};
private:
Label m_TitleLabel;
// Here is how these controls are arranged hierarchically.
// m_HeaderGrid
// m_HeaderLabels
// m_PlayerGridScroll
// m_PlayerGrid
// m_PlayerEntries
CGrid m_HeaderGrid;
CLabelHeader m_HeaderLabels[NUM_COLUMNS]; // Labels above the
CLabelHeader *m_pCurrentHighlightLabel;
int m_iHighlightRow;
vgui::CListBox m_PlayerList;
CGrid m_PlayerGrids[NUM_ROWS]; // The grid with player and team info.
CLabelHeader m_PlayerEntries[NUM_COLUMNS][NUM_ROWS]; // Labels for the grid entries.
ScorePanel::HitTestPanel m_HitTestPanel;
CLabelHeader* GetPlayerEntry(int x, int y) {return &m_PlayerEntries[x][y];}
vgui::BitmapTGA *m_pTrackerIcon;
public:
int m_iNumTeams;
int m_iPlayerNum;
int m_iShowscoresHeld;
int m_iNumTeams;
int m_iPlayerNum;
int m_iShowscoresHeld;
int m_iRows;
int m_iSortedRows[NUM_ROWS];
int m_iIsATeam[NUM_ROWS];
bool m_bHasBeenSorted[MAX_PLAYERS];
int m_iLastKilledBy;
int m_fLastKillTime;
public:
ScorePanel(int x,int y,int wide,int tall);
virtual void setSize(int wide,int tall);
void Update( void );
void SortTeams( void );
void SortPlayers( int iTeam, char *team );
void RebuildTeams( void );
void FillGrid();
void DeathMsg( int killer, int victim );
void Initialize( void );
void Open( void )
{
RebuildTeams();
setVisible(true);
}
void Open( void );
void MouseOverCell(int row, int col);
// InputSignal overrides.
public:
virtual void mousePressed(MouseCode code, Panel* panel);
virtual void cursorMoved(int x, int y, Panel *panel);
friend CLabelHeader;
};
#endif
#endif

View file

@ -44,6 +44,7 @@
#include "camera.h"
#include "in_defs.h"
#include "parsemsg.h"
#include "pm_shared.h"
#include "../engine/keydefs.h"
#include "demo.h"
#include "demo_api.h"
@ -59,6 +60,19 @@ int g_iPlayerClass;
int g_iTeamNumber;
int g_iUser1;
int g_iUser2;
int g_iUser3;
// Scoreboard positions
#define SBOARD_INDENT_X XRES(104)
#define SBOARD_INDENT_Y YRES(40)
// low-res scoreboard indents
#define SBOARD_INDENT_X_512 30
#define SBOARD_INDENT_Y_512 30
#define SBOARD_INDENT_X_400 0
#define SBOARD_INDENT_Y_400 20
void IN_ResetMouse( void );
extern CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *szTitle, int iShadeFullscreen, int iRemoveMe, int x, int y, int wide, int tall );
@ -66,15 +80,17 @@ extern CMenuPanel *CMessageWindowPanel_Create( const char *szMOTD, const char *s
using namespace vgui;
// Team Colors
int iNumberOfTeamColors = 5;
int iTeamColors[5][3] =
{
{ 255, 255, 255 },
{ 66, 115, 247 },
{ 220, 51, 38 },
{ 240, 135, 0 },
{ 115, 240, 115 },
{ 255, 170, 0 }, // HL orange (default)
{ 125, 165, 210 }, // Blue
{ 200, 90, 70 }, // Red
{ 225, 205, 45 }, // Yellow
{ 145, 215, 140 }, // Green
};
// Used for Class specific buttons
char *sTFClasses[] =
{
@ -470,9 +486,6 @@ TeamFortressViewport::TeamFortressViewport(int x,int y,int wide,int tall) : Pane
m_pCurrentMenu = NULL;
m_pCurrentCommandMenu = NULL;
CVAR_CREATE( "hud_classautokill", "1", FCVAR_ARCHIVE ); // controls whether or not to suicide immediately on TF class switch
CVAR_CREATE( "hud_takesshots", "0", FCVAR_ARCHIVE ); // controls whether or not to automatically take screenshots at the end of a round
Initialize();
addInputSignal( new CViewPortInputHandler );
@ -595,7 +608,7 @@ void TeamFortressViewport::CreateCommandMenu( void )
m_pCommandMenus[0]->setParent(this);
m_pCommandMenus[0]->setVisible(false);
m_iNumMenus = 1;
m_iCurrentTeamNumber = m_iUser1 = m_iUser2 = 0;
m_iCurrentTeamNumber = m_iUser1 = m_iUser2 = m_iUser3 = 0;
// Read Command Menu from the txt file
char token[1024];
@ -1227,6 +1240,9 @@ void TeamFortressViewport::HideScoreBoard( void )
if (m_pScoreBoard)
{
m_pScoreBoard->setVisible(false);
GetClientVoiceMgr()->StopSquelchMode();
UpdateCursorState();
}
}
@ -1276,26 +1292,61 @@ void TeamFortressViewport::UpdateCommandMenu()
void TeamFortressViewport::UpdateSpectatorMenu()
{
char sz[64];
char helpString1[128];
char helpString2[128];
int mode;
m_iUser1 = g_iUser1;
m_iUser2 = g_iUser2;
m_iUser3 = g_iUser3;
if (!m_pSpectatorMenu)
return;
if (m_iUser1)
if ( gEngfuncs.IsSpectateOnly() )
{
mode = gHUD.m_Spectator.m_iMainMode; // spec mode is set client side
sprintf(helpString2, "#Spec_Only_Help");
}
else
{
// spec mode is given by server
mode = m_iUser1;
// set normal help text
sprintf(helpString2, "#Spec_Help" );
}
if ( mode && ( gEngfuncs.IsSpectateOnly() != 2) ) // don't draw in dev_overview mode
{
m_pSpectatorMenu->setVisible( true );
if (m_iUser2 > 0)
// check if we're locked onto a target, show the player's name
if ( (m_iUser2 > 0) && (m_iUser2 <= gEngfuncs.GetMaxClients()) )
{
// Locked onto a target, show the player's name
sprintf(sz, "#Spec_Mode%d : %s", m_iUser1, g_PlayerInfoList[ m_iUser2 ].name);
m_pSpectatorLabel->setText( CHudTextMessage::BufferedLocaliseTextString( sz ) );
// Locked onto a target, show the player's name
if ( g_PlayerInfoList[ m_iUser2 ].name != NULL )
sprintf(helpString1, "#Spec_Mode%d : %s", mode, g_PlayerInfoList[ m_iUser2 ].name );
else
sprintf(helpString1, "#Spec_Mode%d", mode );
}
else
{
sprintf(sz, "#Spec_Mode%d", m_iUser1);
m_pSpectatorLabel->setText( CHudTextMessage::BufferedLocaliseTextString( sz ) );
sprintf(helpString1, "#Spec_Mode%d", mode);
}
if ( m_iUser1 == OBS_DIRECTED )
{
char tempString[128];
sprintf(tempString, "#Directed %s", helpString1);
strcpy( helpString1, tempString );
}
m_pSpectatorLabel->setText( CHudTextMessage::BufferedLocaliseTextString( helpString1 ) );
m_pSpectatorHelpLabel->setText( CHudTextMessage::BufferedLocaliseTextString( helpString2 ) );
}
else
{
@ -1306,7 +1357,19 @@ void TeamFortressViewport::UpdateSpectatorMenu()
//======================================================================
void TeamFortressViewport::CreateScoreBoard( void )
{
m_pScoreBoard = new ScorePanel(SBOARD_INDENT_X,SBOARD_INDENT_Y, ScreenWidth - (SBOARD_INDENT_X * 2), ScreenHeight - (SBOARD_INDENT_Y * 2));
int xdent = SBOARD_INDENT_X, ydent = SBOARD_INDENT_Y;
if (ScreenWidth == 512)
{
xdent = SBOARD_INDENT_X_512;
ydent = SBOARD_INDENT_Y_512;
}
else if (ScreenWidth == 400)
{
xdent = SBOARD_INDENT_X_400;
ydent = SBOARD_INDENT_Y_400;
}
m_pScoreBoard = new ScorePanel(xdent, ydent, ScreenWidth - (xdent * 2), ScreenHeight - (ydent * 2));
m_pScoreBoard->setParent(this);
m_pScoreBoard->setVisible(false);
}
@ -1462,6 +1525,12 @@ void TeamFortressViewport::ShowVGUIMenu( int iMenu )
if ( gEngfuncs.pDemoAPI->IsPlayingback() )
return;
// Don't open any menus except the MOTD during intermission
// MOTD needs to be accepted because it's sent down to the client
// after map change, before intermission's turned off
if ( gHUD.m_iIntermission && iMenu != MENU_INTRO )
return;
// Don't create one if it's already in the list
if (m_pCurrentMenu)
{
@ -1509,6 +1578,7 @@ void TeamFortressViewport::ShowVGUIMenu( int iMenu )
pNewMenu->SetMenuID( iMenu );
pNewMenu->SetActive( true );
pNewMenu->setParent(this);
// See if another menu is visible, and if so, cache this one for display once the other one's finished
if (m_pCurrentMenu)
@ -1649,16 +1719,16 @@ void TeamFortressViewport::CreateSpectatorMenu()
m_pSpectatorLabel->setContentAlignment( vgui::Label::a_north );
// Create the Help
Label *pLabel = new Label( CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help" ), 0, YRES(25), ScreenWidth, YRES(15) );
pLabel->setParent( m_pSpectatorMenu );
pLabel->setFont( pSchemes->getFont(hHelpText) );
m_pSpectatorHelpLabel = new Label( CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help" ), 0, YRES(25), ScreenWidth, YRES(15) );
m_pSpectatorHelpLabel->setParent( m_pSpectatorMenu );
m_pSpectatorHelpLabel->setFont( pSchemes->getFont(hHelpText) );
pSchemes->getFgColor( hHelpText, r, g, b, a );
pLabel->setFgColor( r, g, b, a );
m_pSpectatorHelpLabel->setFgColor( r, g, b, a );
pSchemes->getBgColor( hHelpText, r, g, b, a );
pLabel->setBgColor( r, g, b, 255 );
pLabel->setContentAlignment( vgui::Label::a_north );
m_pSpectatorHelpLabel->setBgColor( r, g, b, 255 );
m_pSpectatorHelpLabel->setContentAlignment( vgui::Label::a_north );
pLabel = new Label( CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help2" ), 0, YRES(40), ScreenWidth, YRES(20) );
Label *pLabel = new Label( CHudTextMessage::BufferedLocaliseTextString( "#Spec_Help2" ), 0, YRES(40), ScreenWidth, YRES(20) );
pLabel->setParent( m_pSpectatorMenu );
pLabel->setFont( pSchemes->getFont(hHelpText) );
pSchemes->getFgColor( hHelpText, r, g, b, a );
@ -1666,6 +1736,7 @@ void TeamFortressViewport::CreateSpectatorMenu()
pSchemes->getBgColor( hHelpText, r, g, b, a );
pLabel->setBgColor( r, g, b, 255 );
pLabel->setContentAlignment( vgui::Label::a_center );
}
//======================================================================================
@ -1686,7 +1757,7 @@ void TeamFortressViewport::UpdateOnPlayerInfo()
void TeamFortressViewport::UpdateCursorState()
{
// Need cursor if any VGUI window is up
if ( m_pCurrentMenu || m_pTeamMenu->isVisible() || m_pServerBrowser->isVisible() )
if ( m_pCurrentMenu || m_pTeamMenu->isVisible() || m_pServerBrowser->isVisible() || GetClientVoiceMgr()->IsInSquelchMode() )
{
g_iVisibleMouse = true;
App::getInstance()->setCursorOveride( App::getInstance()->getScheme()->getCursor(Scheme::SchemeCursor::scu_arrow) );
@ -1727,6 +1798,13 @@ void TeamFortressViewport::GetAllPlayersInfo( void )
void TeamFortressViewport::paintBackground()
{
if (m_pScoreBoard)
{
int x, y;
getApp()->getCursorPos(x, y);
m_pScoreBoard->cursorMoved(x, y, m_pScoreBoard);
}
// See if the command menu is visible and needs recalculating due to some external change
if ( g_iTeamNumber != m_iCurrentTeamNumber )
{
@ -1748,10 +1826,9 @@ void TeamFortressViewport::paintBackground()
}
// See if the Spectator Menu needs to be update
// no update if only second target (m_iUser3) changes
if ( g_iUser1 != m_iUser1 || g_iUser2 != m_iUser2 )
{
m_iUser1 = g_iUser1;
m_iUser2 = g_iUser2;
UpdateSpectatorMenu();
}
@ -1932,9 +2009,13 @@ int TeamFortressViewport::MsgFunc_TeamNames(const char *pszName, int iSize, void
if (m_pTeamButtons[i])
m_pTeamButtons[i]->setText( m_sTeamNames[teamNum] );
// Set the disguise buttons
if (m_pDisguiseButtons[i])
m_pDisguiseButtons[i]->setText( m_sTeamNames[teamNum] );
// range check this value...m_pDisguiseButtons[5];
if ( teamNum < 5 )
{
// Set the disguise buttons
if ( m_pDisguiseButtons[teamNum] )
m_pDisguiseButtons[teamNum]->setText( m_sTeamNames[teamNum] );
}
}
// Update the Team Menu
@ -1995,7 +2076,10 @@ int TeamFortressViewport::MsgFunc_MOTD( const char *pszName, int iSize, void *pb
BEGIN_READ( pbuf, iSize );
m_iGotAllMOTD = READ_BYTE();
strncat( m_szMOTD, READ_STRING(), sizeof(m_szMOTD) - strlen(m_szMOTD) );
int roomInArray = sizeof(m_szMOTD) - strlen(m_szMOTD) - 1;
strncat( m_szMOTD, READ_STRING(), roomInArray >= 0 ? roomInArray : 0 );
m_szMOTD[ sizeof(m_szMOTD)-1 ] = '\0';
if ( m_iGotAllMOTD )
@ -2052,6 +2136,10 @@ int TeamFortressViewport::MsgFunc_ScoreInfo( const char *pszName, int iSize, voi
g_PlayerExtraInfo[cl].playerclass = playerclass;
g_PlayerExtraInfo[cl].teamnumber = teamnumber;
//Dont go bellow 0!
if ( g_PlayerExtraInfo[cl].teamnumber < 0 )
g_PlayerExtraInfo[cl].teamnumber = 0;
UpdateOnPlayerInfo();
}

View file

@ -45,21 +45,18 @@ class CClassMenuPanel;
class CTeamMenuPanel;
char* GetVGUITGAName(const char *pszName);
BitmapTGA *LoadTGA( const char* pImageName );
BitmapTGA *LoadTGAForRes(const char* pImageName);
void ScaleColors( int &r, int &g, int &b, int a );
extern char *sTFClassSelection[];
extern int sTFValidClassInts[];
extern char *sLocalisedClasses[];
extern int iTeamColors[5][3];
extern int iNumberOfTeamColors;
#define MAX_SERVERNAME_LENGTH 32
// Use this to set any co-ords in 640x480 space
#define XRES(x) (x * ((float)ScreenWidth / 640))
#define YRES(y) (y * ((float)ScreenHeight / 480))
// Command Menu positions
#define MAX_MENUS 40
#define MAX_MENUS 80
#define MAX_BUTTONS 100
#define BUTTON_SIZE_Y YRES(30)
@ -268,6 +265,7 @@ private:
int m_iCurrentPlayerClass;
int m_iUser1;
int m_iUser2;
int m_iUser3;
// VGUI Menus
void CreateTeamMenu( void );
@ -295,6 +293,7 @@ private:
// Spectator "menu"
CTransparentPanel *m_pSpectatorMenu;
Label *m_pSpectatorLabel;
Label *m_pSpectatorHelpLabel;
int m_iAllowSpectators;
// Data for specific sections of the Command Menu
@ -385,6 +384,7 @@ public:
virtual void paintBackground();
CSchemeManager *GetSchemeManager( void ) { return &m_SchemeManager; }
ScorePanel *GetScoreBoard( void ) { return m_pScoreBoard; }
void *operator new( size_t stAllocateBlock );
@ -1252,4 +1252,4 @@ public:
}
};
#endif
#endif

View file

@ -100,7 +100,7 @@ CTeamMenuPanel::CTeamMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide,i
pSchemes->getBgColor( hTeamWindowText, r, g, b, a );
m_pBriefing->setBgColor( r, g, b, a );
m_pBriefing->setText("Map Description not available.");
m_pBriefing->setText( gHUD.m_TextMessage.BufferedLocaliseTextString("#Map_Description_not_available") );
// Team Menu buttons
for (int i = 1; i <= 5; i++)
@ -132,7 +132,10 @@ CTeamMenuPanel::CTeamMenuPanel(int iTrans, int iRemoveMe, int x,int y,int wide,i
m_pTeamInfoPanel[i] = new TextPanel("", TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_INFO_Y, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_X, TEAMMENU_WINDOW_SIZE_X - TEAMMENU_WINDOW_INFO_Y );
m_pTeamInfoPanel[i]->setParent( m_pTeamWindow );
m_pTeamInfoPanel[i]->setFont( pSchemes->getFont(hTeamInfoText) );
m_pTeamInfoPanel[i]->setFgColor( iTeamColors[i][0], iTeamColors[i][1], iTeamColors[i][2], 0 );
m_pTeamInfoPanel[i]->setFgColor( iTeamColors[i % iNumberOfTeamColors][0],
iTeamColors[i % iNumberOfTeamColors][1],
iTeamColors[i % iNumberOfTeamColors][2],
0 );
m_pTeamInfoPanel[i]->setBgColor( 0,0,0, 255 );
}

View file

@ -16,6 +16,7 @@
#include "screenfade.h"
#include "shake.h"
// Spectator Mode
extern "C"
{
@ -39,6 +40,8 @@ extern "C"
void PM_ParticleLine( float *start, float *end, int pcolor, float life, float vert);
int PM_GetInfo( int ent );
void InterpolateAngles( float *start, float *end, float *output, float frac );
float AngleBetweenVectors( float * v1, float * v2 );
}
@ -84,6 +87,7 @@ 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 )
{
@ -110,7 +114,7 @@ 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;
@ -139,7 +143,7 @@ void V_InterpolateAngles( float *start, float *end, float *output, float 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 )
@ -563,13 +567,14 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams )
frac = min( 1.0, frac );
// interpolate angles
V_InterpolateAngles( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], pparams->cl_viewangles, frac );
InterpolateAngles( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], pparams->cl_viewangles, frac );
VectorCopy( pparams->cl_viewangles, vecNewViewAngles );
}
}
}
VectorCopy ( pparams->cl_viewangles, pparams->viewangles );
gEngfuncs.V_CalcShake();
@ -871,6 +876,284 @@ void V_CalcNormalRefdef ( struct ref_params_s *pparams )
lasttime = pparams->time;
v_origin = pparams->vieworg;
}
void V_GetInEyePos(int entity, float *origin, float * angles )
{
cl_entity_t * ent = gEngfuncs.GetEntityByIndex( entity );
if ( !ent )
return;
if ( !ent->player || g_PlayerInfoList[entity].name == NULL )
return;
VectorCopy ( ent->origin, origin );
VectorCopy ( ent->angles, angles );
angles[0]*=-M_PI;
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
}
/*
==================
V_CalcSpectatorRefdef
==================
*/
void V_CalcSpectatorRefdef ( struct ref_params_s *pparams )
{
cl_entity_t *ent, *view;
vec3_t angles;
static viewinterp_t ViewInterp;
static float lasttime;
static float lastang[3];
static float lastorg[3];
vec3_t delta;
// 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();
// refresh position
VectorCopy ( pparams->simorg, pparams->vieworg );
// done all the spectator smoothing only once in the first frame
// Observer angle capturing and smoothing
if ( iHasNewViewOrigin )
{
// Get the angles from the physics code
VectorCopy( vecNewViewOrigin, pparams->vieworg );
}
else
{
// otherwise copy normal vieworigin into vecNewViewOrigin
VectorCopy( pparams->vieworg, vecNewViewOrigin );
}
VectorCopy ( pparams->cl_viewangles, pparams->viewangles );
// Observer angle capturing and smoothing
if ( iHasNewViewAngles )
{
// Get the angles from the physics code
VectorCopy( vecNewViewAngles, pparams->viewangles );
}
else
{
// otherwise copy normal viewangle into vewNewViewAngles
VectorCopy( pparams->viewangles, vecNewViewAngles);
}
// do the smoothing only once per frame
if (pparams->nextView == 0)
{
// smooth angles
VectorSubtract( pparams->viewangles, lastang, delta );
if ( Length( delta ) != 0.0f )
{
VectorCopy( pparams->viewangles, ViewInterp.Angles[ ViewInterp.CurrentAngle & ORIGIN_MASK ] );
ViewInterp.AngleTime[ ViewInterp.CurrentAngle & ORIGIN_MASK ] = pparams->time;
ViewInterp.CurrentAngle++;
VectorCopy( pparams->viewangles, lastang );
}
if ( cl_vsmoothing && cl_vsmoothing->value && ( iIsSpectator & SPEC_SMOOTH_ANGLES ) )
{
int foundidx;
int i;
float t;
t = pparams->time - cl_vsmoothing->value;
for ( i = 1; i < ORIGIN_MASK; i++ )
{
foundidx = ViewInterp.CurrentAngle - 1 - i;
if ( ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ] <= t )
break;
}
if ( i < ORIGIN_MASK && ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ] != 0.0 )
{
// Interpolate
double dt;
float da;
vec3_t v1,v2;
AngleVectors( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], v1, NULL, NULL );
AngleVectors( ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], v2, NULL, NULL );
da = AngleBetweenVectors( v1, v2 );
dt = ViewInterp.AngleTime[ (foundidx + 1) & ORIGIN_MASK ] - ViewInterp.AngleTime[ foundidx & ORIGIN_MASK ];
if ( dt > 0.0 && ( da < 22.5f) )
{
double frac;
frac = ( t - ViewInterp.AngleTime[ foundidx & ORIGIN_MASK] ) / dt;
frac = min( 1.0, frac );
// interpolate angles
InterpolateAngles( ViewInterp.Angles[ foundidx & ORIGIN_MASK ], ViewInterp.Angles[ (foundidx + 1) & ORIGIN_MASK ], vecNewViewAngles, frac );
VectorCopy( vecNewViewAngles, pparams->viewangles );
}
}
}
// smooth origin
VectorSubtract( pparams->vieworg, lastorg, delta );
if ( Length( delta ) != 0.0 )
{
VectorCopy( pparams->vieworg, ViewInterp.Origins[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] );
ViewInterp.OriginTime[ ViewInterp.CurrentOrigin & ORIGIN_MASK ] = pparams->time;
ViewInterp.CurrentOrigin++;
VectorCopy( pparams->vieworg, lastorg );
}
if ( cl_vsmoothing && cl_vsmoothing->value && ( iIsSpectator & SPEC_SMOOTH_ORIGIN ) )
{
int foundidx;
int i;
float t;
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->vieworg, delta, pparams->vieworg );
VectorCopy( pparams->vieworg, vecNewViewOrigin );
}
}
}
}
}
lasttime = pparams->time;
view->model = NULL;
if ( pparams->nextView == 0 )
{
// first renderer cycle
switch (gHUD.m_Spectator.m_iMainMode)
{
case MAIN_MAP_FREE : pparams->onlyClientDraw = true;
angles = pparams->cl_viewangles;
angles[0] = 51.25f + 38.75f*(angles[0]/90.0f);
VectorCopy ( angles, gHUD.m_Spectator.m_mapAngles );
gHUD.m_Spectator.GetMapPosition( pparams->vieworg );
VectorCopy ( angles, pparams->viewangles );
break;
case MAIN_IN_EYE : V_GetInEyePos( gHUD.m_Spectator.m_iObserverTarget,
pparams->vieworg, pparams->viewangles );
break;
default : pparams->onlyClientDraw = false;
break;
}
if ( gHUD.m_Spectator.m_iInsetMode != INSET_OFF )
pparams->nextView = 1; // force a second renderer view
gHUD.m_Spectator.m_iDrawCycle = 0;
}
else
{
// second renderer cycle
// 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
pparams->onlyClientDraw = false;
// override some settings in certain modes
switch (gHUD.m_Spectator.m_iInsetMode)
{
case INSET_MAP_FREE : pparams->onlyClientDraw = true;
angles = pparams->cl_viewangles;
angles[0] = 51.25f + 38.75f*(angles[0]/90.0f);
VectorCopy ( angles, gHUD.m_Spectator.m_mapAngles );
gHUD.m_Spectator.GetMapPosition( pparams->vieworg );
VectorCopy ( angles, pparams->viewangles );
break;
case INSET_IN_EYE : V_GetInEyePos( gHUD.m_Spectator.m_iObserverTarget,
pparams->vieworg, pparams->viewangles );
break;
}
gHUD.m_Spectator.m_iDrawCycle = 1;
}
v_angles = pparams->viewangles;
v_origin = pparams->vieworg;
}
void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams )
@ -880,6 +1163,10 @@ void DLLEXPORT V_CalcRefdef( struct ref_params_s *pparams )
{
V_CalcIntermissionRefdef ( pparams );
}
else if ( pparams->spectator )
{
V_CalcSpectatorRefdef ( pparams );
}
else if ( !pparams->paused )
{
V_CalcNormalRefdef ( pparams );
@ -1036,4 +1323,4 @@ void V_Move( int mx, int my )
}
}
#endif
#endif

View file

@ -59,4 +59,4 @@ struct beam_s
struct particle_s *particles;
};
#endif
#endif

View file

@ -112,4 +112,4 @@ struct cl_entity_s
colorVec cvFloorColor;
};
#endif // !CL_ENTITYH
#endif // !CL_ENTITYH

View file

@ -28,4 +28,4 @@ typedef struct con_nprint_s
void Con_NPrintf( int idx, char *fmt, ... );
void Con_NXPrintf( struct con_nprint_s *info, char *fmt, ... );
#endif
#endif

View file

@ -43,7 +43,7 @@
#define FL_IMMUNE_SLIME (1<<18)
#define FL_IMMUNE_LAVA (1<<19)
//#define FL_ARCHIVE_OVERRIDE (1<<20) // NOT USED
#define FL_PROXY (1<<20) // This is a spectator proxy
#define FL_ALWAYSTHINK (1<<21) // Brush model flag -- call think every frame regardless of nextthink - ltime (for constantly changing velocity/path)
#define FL_BASEVELOCITY (1<<22) // Base velocity has been applied this frame (used to convert base velocity into momentum)
#define FL_MONSTERCLIP (1<<23) // Only collide in with monsters who have FL_MONSTERCLIP set
@ -347,7 +347,17 @@
// ushort 8.8 hold time
// optional ushort 8.8 fxtime (time the highlight lags behing the leading text in effect 2)
// string text message (512 chars max sz string)
#define TE_LINE 30
// coord, coord, coord startpos
// coord, coord, coord endpos
// short life in 0.1 s
// 3 bytes r, g, b
#define TE_BOX 31
// coord, coord, coord boxmins
// coord, coord, coord boxmaxs
// short life in 0.1 s
// 3 bytes r, g, b
#define TE_KILLBEAM 99 // kill all beams attached to entity
// short (entity)
@ -550,6 +560,8 @@
// byte ( color ) this is an index into an array of color vectors in the engine. (0 - )
// byte ( length * 10 )
#define MSG_BROADCAST 0 // unreliable to all
#define MSG_ONE 1 // reliable to one (msg_entity)
#define MSG_ALL 2 // reliable to all
@ -559,6 +571,7 @@
#define MSG_PVS_R 6 // Reliable to PVS
#define MSG_PAS_R 7 // Reliable to PAS
#define MSG_ONE_UNRELIABLE 8 // Send to one client, but don't put in reliable stream, put in unreliable datagram ( could be dropped )
#define MSG_SPEC 9 // Sends to all spectator proxies
// contents of a spot in the world
#define CONTENTS_EMPTY -1
@ -594,9 +607,10 @@
#define CHAN_VOICE 2
#define CHAN_ITEM 3
#define CHAN_BODY 4
#define CHAN_STREAM 5 // allocate stream channel from the static or dynamic area
#define CHAN_STATIC 6 // allocate channel from the static area
#define CHAN_STREAM 5 // allocate stream channel from the static or dynamic area
#define CHAN_STATIC 6 // allocate channel from the static area
#define CHAN_NETWORKVOICE_BASE 7 // voice data coming across the network
#define CHAN_NETWORKVOICE_END 500 // network voice data reserves slots (CHAN_NETWORKVOICE_BASE through CHAN_NETWORKVOICE_END).
// attenuation values
#define ATTN_NONE 0

View file

@ -34,7 +34,8 @@ 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);
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,

View file

@ -33,4 +33,4 @@ typedef struct cvar_s
float value;
struct cvar_s *next;
} cvar_t;
#endif
#endif

View file

@ -28,4 +28,4 @@ typedef struct demo_api_s
extern demo_api_t demoapi;
#endif
#endif

31
common/director_cmds.h Normal file
View file

@ -0,0 +1,31 @@
// 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

View file

@ -30,4 +30,4 @@ typedef struct
qboolean dark; // subtracts light instead of adding
} dlight_t;
#endif
#endif

View file

@ -86,6 +86,7 @@ typedef struct engine_api_s
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 );
@ -93,9 +94,10 @@ typedef struct engine_api_s
void ( *GL_Shutdown ) ( void );
void ( *QGL_D3DShared ) ( void );
void ( *glSwapBuffers ) ( void );
void ( *DirectorProc ) ( void );
// LINUX
#endif
} engine_api_t;
#endif // ENGINE_LAUNCHER_APIH
#endif // ENGINE_LAUNCHER_APIH

View file

@ -49,9 +49,9 @@ struct entity_state_s
short solid;
int effects;
float scale;
byte eflags;
byte eflags;
// Render information
int rendermode;
int renderamt;
@ -190,4 +190,4 @@ typedef struct local_state_s
weapon_data_t weapondata[ 32 ];
} local_state_t;
#endif // !ENTITY_STATEH
#endif // !ENTITY_STATEH

View file

@ -23,4 +23,4 @@
// BMODEL or SPRITE that was split across BSP nodes
#define ET_FRAGMENTED 4
#endif // !ENTITY_TYPESH
#endif // !ENTITY_TYPESH

View file

@ -48,4 +48,3 @@ typedef struct event_args_s
} event_args_t;
#endif

View file

@ -44,4 +44,4 @@
// Only issue event client side ( from shared code )
#define FEV_CLIENT (1<<6)
#endif
#endif

View file

@ -38,4 +38,4 @@ typedef struct exefuncs_s
void (*unused25)(void);
} exefuncs_t;
#endif
#endif

37
common/hltv.h Normal file
View file

@ -0,0 +1,37 @@
// hltv.h
// all shared consts between server, clients and proxy
#define TYPE_CLIENT 0 // client is a normal HL client (default)
#define TYPE_PROXY 1 // client is another proxy
#define TYPE_DIRECTOR 2 // client is a director
#define TYPE_COMMENTATOR 3 // client is a commentator
#define HLTV_ACTIVE 0 // tells client that he's an spectator and will get director command
#define HLTV_STATUS 1 // send status infos about proxy
#define HLTV_CAMERA 2 // set the actual director camera position
#define HLTV_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_DIRTIME 5 // set director time
#define DRCAPI_DIRSCALE 6 // set time scale
#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

View file

@ -35,4 +35,4 @@
#define IN_ALT1 (1 << 14)
#define IN_SCORE (1 << 15) // Used by client.dll for when scoreboard is held down
#endif // IN_BUTTONS_H
#endif // IN_BUTTONS_H

142
common/interface.cpp Normal file
View file

@ -0,0 +1,142 @@
#include <string.h>
#include <stdlib.h>
#include "interface.h"
#ifndef _WIN32 // LINUX
#include <dlfcn.h>
#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 dlsym( (void *)hModule, CREATEINTERFACE_PROCNAME );
}
#endif

123
common/interface.h Normal file
View file

@ -0,0 +1,123 @@
// 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

46
common/itrackeruser.h Normal file
View file

@ -0,0 +1,46 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef ITRACKERUSER_H
#define ITRACKERUSER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
//-----------------------------------------------------------------------------
// Purpose: Interface to accessing information about tracker users
//-----------------------------------------------------------------------------
class ITrackerUser : public IBaseInterface
{
public:
// returns true if the interface is ready for use
virtual bool IsValid() = 0;
// returns the tracker ID of the current user
virtual int GetTrackerID() = 0;
// returns information about a user
// information may not be known about some users, "" will be returned
virtual const char *GetUserName(int trackerID) = 0;
virtual const char *GetFirstName(int trackerID) = 0;
virtual const char *GetLastName(int trackerID) = 0;
virtual const char *GetEmail(int trackerID) = 0;
// returns true if friendID is a friend of the current user
// ie. the current is authorized to see when the friend is online
virtual bool IsFriend(int friendID) = 0;
// requests authorization from a user
virtual void RequestAuthorizationFromUser(int potentialFriendID) = 0;
};
#define TRACKERUSER_INTERFACE_VERSION "TrackerUser001"
#endif // ITRACKERUSER_H

35
common/ivoicetweak.h Normal file
View file

@ -0,0 +1,35 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef IVOICETWEAK_H
#define IVOICETWEAK_H
#ifdef _WIN32
#pragma once
#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

View file

@ -26,7 +26,7 @@ typedef enum
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX
NA_BROADCAST_IPX,
} netadrtype_t;
typedef struct netadr_s
@ -37,4 +37,4 @@ typedef struct netadr_s
unsigned short port;
} netadr_t;
#endif // NETADR_H
#endif // NETADR_H

9
common/nowin.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef INC_NOWIN_H
#define INC_NOWIN_H
#ifndef _WIN32
#include <unistd.h>
#endif //!_WIN32
#endif //INC_NOWIN_H

View file

@ -47,11 +47,11 @@ typedef struct particle_s
ptype_t type;
void (*deathfunc)( struct particle_s *particle );
// For pt_clientcusttom, we'll call this function each frame
// for pt_clientcusttom, we'll call this function each frame
void (*callback)( struct particle_s *particle, float frametime );
// for deathfunc, etc.
// For deathfunc, etc.
unsigned char context;
} particle_t;
#endif
#endif

View file

@ -40,4 +40,4 @@ struct pmtrace_s
int hitgroup;
};
#endif
#endif

View file

@ -37,4 +37,4 @@ typedef struct qfont_s
byte data[4];
} qfont_t;
#endif // qfont.h
#endif // qfont.h

View file

@ -14,7 +14,9 @@
****/
#if !defined ( R_EFXH )
#define R_EFXH
#ifdef _WIN32
#pragma once
#endif
// particle_t
#if !defined( PARTICLEDEFH )
@ -187,8 +189,9 @@ struct efx_api_s
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
#endif

View file

@ -64,6 +64,12 @@ typedef struct ref_params_s
// Movevars
struct movevars_s *movevars;
int viewport[4]; // the viewport coordinates x ,y , width, height
int nextView; // the renderer calls ClientDLL_CalcRefdef() and Renderview
// so long in cycles until this value is 0 (multiple views)
int onlyClientDraw; // if !=0 nothing is drawn by the engine except clientDraw functions
} ref_params_t;
#endif // !REF_PARAMSH
#endif // !REF_PARAMSH

View file

@ -8,9 +8,10 @@ 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
#endif // !SCREENFADEH

View file

@ -26,4 +26,4 @@ typedef struct mstudioevent_s
char options[64];
} mstudioevent_t;
#endif // STUDIO_EVENTH
#endif // STUDIO_EVENTH

View file

@ -49,6 +49,7 @@ typedef struct triangleapi_s
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.
} triangleapi_t;
#endif // !TRIANGLEAPIH
#endif // !TRIANGLEAPIH

View file

@ -38,4 +38,4 @@ typedef struct usercmd_s
vec3_t impact_position;
} usercmd_t;
#endif // USERCMD_H
#endif // USERCMD_H

View file

@ -49,4 +49,4 @@ typedef struct weapon_data_s
float fuser4;
} weapon_data_t;
#endif
#endif

1514
dlls/AI_BaseNPC_Schedule.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
#
# Half-Life StandardSDK 2.0 mp_i386.so Makefile for i386 Linux
# Half-Life Full SDK 2.2 hl_i386.so Makefile for x86 Linux
#
# April 2000 by Leon Hartwig (jehannum@planethalflife.com)
# August 2001 by Leon Hartwig (hartwig@valvesoftware.com)
#
DLLNAME=mp
DLLNAME=hl
ARCH=i386
@ -12,27 +12,32 @@ ARCH=i386
CC=gcc
DLL_SRCDIR=.
ENGINE_SRCDIR=../engine
COMMON_SRCDIR=../common
WPN_SHARED_SRCDIR=./wpn_shared
PM_SHARED_SRCDIR=../pm_shared
GAME_SHARED_SRCDIR=../game_shared
DLL_OBJDIR=$(DLL_SRCDIR)/obj
WPN_SHARED_OBJDIR=$(WPN_SHARED_SRCDIR)/obj
PM_SHARED_OBJDIR=$(PM_SHARED_SRCDIR)/obj
GAME_SHARED_OBJDIR=$(GAME_SHARED_SRCDIR)/obj
BASE_CFLAGS=-Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp
BASE_CFLAGS= -Dstricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-DCLIENT_WEAPONS
#safe optimization
CFLAGS=$(BASE_CFLAGS) -w -m486 -O1
#full optimization
#CFLAGS=$(BASE_CFLAGS) -w -m486 -O2 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
-malign-jumps=2 -malign-functions=2
#CFLAGS=$(BASE_CFLAGS) -w -O1 -m486 -ffast-math -funroll-loops \
-fomit-frame-pointer -fexpensive-optimizations \
-malign-loops=2 -malign-jumps=2 -malign-functions=2
#use these when debugging
#CFLAGS=$(BASE_CFLAGS) -g
INCLUDEDIRS=-I. -I../engine -I../common -I../pm_shared
INCLUDEDIRS=-I. -I$(ENGINE_SRCDIR) -I$(COMMON_SRCDIR) -I$(PM_SHARED_SRCDIR) -I$(GAME_SHARED_SRCDIR)
LDFLAGS=
@ -53,69 +58,111 @@ $(DLL_OBJDIR)/%.o: $(DLL_SRCDIR)/%.cpp
$(WPN_SHARED_OBJDIR)/%.o: $(WPN_SHARED_SRCDIR)/%.cpp
$(DO_CC)
$(GAME_SHARED_OBJDIR)/%.o: $(GAME_SHARED_SRCDIR)/%.cpp
$(DO_CC)
$(PM_SHARED_OBJDIR)/%.o: $(PM_SHARED_SRCDIR)/%.c
$(DO_CC)
OBJ = \
$(DLL_OBJDIR)/aflock.o \
$(DLL_OBJDIR)/agrunt.o \
$(DLL_OBJDIR)/airtank.o \
$(DLL_OBJDIR)/animating.o \
$(DLL_OBJDIR)/animation.o \
$(DLL_OBJDIR)/apache.o \
$(DLL_OBJDIR)/barnacle.o \
$(DLL_OBJDIR)/barney.o \
$(DLL_OBJDIR)/bigmomma.o \
$(DLL_OBJDIR)/bloater.o \
$(DLL_OBJDIR)/bmodels.o \
$(DLL_OBJDIR)/bullsquid.o \
$(DLL_OBJDIR)/buttons.o \
$(DLL_OBJDIR)/cbase.o \
$(DLL_OBJDIR)/client.o \
$(DLL_OBJDIR)/combat.o \
$(DLL_OBJDIR)/controller.o \
$(DLL_OBJDIR)/crossbow.o \
$(DLL_OBJDIR)/crowbar.o \
$(DLL_OBJDIR)/defaultai.o \
$(DLL_OBJDIR)/doors.o \
$(DLL_OBJDIR)/effects.o \
$(DLL_OBJDIR)/egon.o \
$(DLL_OBJDIR)/explode.o \
$(DLL_OBJDIR)/flyingmonster.o \
$(DLL_OBJDIR)/func_break.o \
$(DLL_OBJDIR)/func_tank.o \
$(DLL_OBJDIR)/game.o \
$(DLL_OBJDIR)/gamerules.o \
$(DLL_OBJDIR)/gargantua.o \
$(DLL_OBJDIR)/gauss.o \
$(DLL_OBJDIR)/genericmonster.o \
$(DLL_OBJDIR)/ggrenade.o \
$(DLL_OBJDIR)/globals.o \
$(DLL_OBJDIR)/gman.o \
$(DLL_OBJDIR)/h_ai.o \
$(DLL_OBJDIR)/h_battery.o \
$(DLL_OBJDIR)/h_cine.o \
$(DLL_OBJDIR)/h_cycler.o \
$(DLL_OBJDIR)/h_export.o \
$(DLL_OBJDIR)/handgrenade.o \
$(DLL_OBJDIR)/hassassin.o \
$(DLL_OBJDIR)/headcrab.o \
$(DLL_OBJDIR)/healthkit.o \
$(DLL_OBJDIR)/hgrunt.o \
$(DLL_OBJDIR)/hornet.o \
$(DLL_OBJDIR)/hornetgun.o \
$(DLL_OBJDIR)/houndeye.o \
$(DLL_OBJDIR)/ichthyosaur.o \
$(DLL_OBJDIR)/islave.o \
$(DLL_OBJDIR)/items.o \
$(DLL_OBJDIR)/leech.o \
$(DLL_OBJDIR)/lights.o \
$(DLL_OBJDIR)/maprules.o \
$(DLL_OBJDIR)/monstermaker.o \
$(DLL_OBJDIR)/monsters.o \
$(DLL_OBJDIR)/monsterstate.o \
$(DLL_OBJDIR)/mortar.o \
$(DLL_OBJDIR)/mp5.o \
$(DLL_OBJDIR)/mpstubb.o \
$(DLL_OBJDIR)/multiplay_gamerules.o \
$(DLL_OBJDIR)/nihilanth.o \
$(DLL_OBJDIR)/nodes.o \
$(DLL_OBJDIR)/osprey.o \
$(DLL_OBJDIR)/pathcorner.o \
$(DLL_OBJDIR)/plane.o \
$(DLL_OBJDIR)/plats.o \
$(DLL_OBJDIR)/player.o \
$(DLL_OBJDIR)/python.o \
$(DLL_OBJDIR)/rat.o \
$(DLL_OBJDIR)/roach.o \
$(DLL_OBJDIR)/rpg.o \
$(DLL_OBJDIR)/satchel.o \
$(DLL_OBJDIR)/schedule.o \
$(DLL_OBJDIR)/scientist.o \
$(DLL_OBJDIR)/scripted.o \
$(DLL_OBJDIR)/shotgun.o \
$(DLL_OBJDIR)/singleplay_gamerules.o \
$(DLL_OBJDIR)/skill.o \
$(DLL_OBJDIR)/sound.o \
$(DLL_OBJDIR)/soundent.o \
$(DLL_OBJDIR)/spectator.o \
$(DLL_OBJDIR)/squadmonster.o \
$(DLL_OBJDIR)/squeakgrenade.o \
$(DLL_OBJDIR)/subs.o \
$(DLL_OBJDIR)/talkmonster.o \
$(DLL_OBJDIR)/teamplay_gamerules.o \
$(DLL_OBJDIR)/tempmonster.o \
$(DLL_OBJDIR)/tentacle.o \
$(DLL_OBJDIR)/triggers.o \
$(DLL_OBJDIR)/tripmine.o \
$(DLL_OBJDIR)/turret.o \
$(DLL_OBJDIR)/util.o \
$(DLL_OBJDIR)/weapons.o \
$(DLL_OBJDIR)/world.o \
$(DLL_OBJDIR)/xen.o \
$(DLL_OBJDIR)/zombie.o \
$(WPN_SHARED_OBJDIR)/hl_wpn_glock.o \
$(GAME_SHARED_OBJDIR)/voice_gamemgr.o \
$(PM_SHARED_OBJDIR)/pm_debug.o \
$(PM_SHARED_OBJDIR)/pm_math.o \
$(PM_SHARED_OBJDIR)/pm_shared.o
@ -126,6 +173,7 @@ $(DLLNAME)_$(ARCH).$(SHLIBEXT) : neat $(OBJ)
neat:
-mkdir $(DLL_OBJDIR)
-mkdir $(WPN_SHARED_OBJDIR)
-mkdir $(GAME_SHARED_OBJDIR)
-mkdir $(PM_SHARED_OBJDIR)
clean:
-rm -f $(OBJ)
@ -133,5 +181,6 @@ clean:
spotless: clean
-rm -r $(DLL_OBJDIR)
-rm -r $(WPN_SHARED_OBJDIR)
-rm -r $(GAME_SHARED_OBJDIR)
-rm -r $(PM_SHARED_OBJDIR)

395
dlls/WXDEBUG.CPP Normal file
View file

@ -0,0 +1,395 @@
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// For every module and executable we store a debugging level and flags
// for the types of output that are desired. Constants for the types are
// defined in WXDEBUG.H and more can be added.
// The keys are stored in the registry under the
// HKEY_LOCAL_MACHINE\SOFTWARE\Debug\<Module Name>\Type and
// HKEY_LOCAL_MACHINE\SOFTWARE\Debug\<Module Name>\Level key values
//
// There are also global values under SOFTWARE\Debug\Global which are loaded
// after the module-specific values. The Types specified there are OR'ed with
// the module specific types and m_dwLevel is set to the greater of the global
// and the module specific settings.
#include <stdarg.h>
#include <stdio.h>
#include "extdll.h"
#include "util.h"
#include "wxdebug.h"
#include <tchar.h>
#ifdef _DEBUG
void WINAPI DbgInitModuleName(void);
void WINAPI DbgInitModuleSettings(void);
void WINAPI DbgInitGlobalSettings(void);
void WINAPI DbgInitLogTo(HKEY hKey);
void WINAPI DbgInitKeyLevels(HKEY hKey, DWORD *pdwTypes, DWORD *pdwLevel);
const INT iDEBUGINFO = 512; // Used to format strings
HINSTANCE m_hInst; // Module instance handle
TCHAR m_ModuleName[iDEBUGINFO]; // Cut down module name
//CRITICAL_SECTION m_CSDebug; // Controls access to list
BOOL m_bInit = FALSE; // Have we been initialised
HANDLE m_hOutput = INVALID_HANDLE_VALUE; // Optional output written here
DWORD m_dwTypes = 0;
DWORD m_dwLevel = 0;
const TCHAR *m_pBaseKey = TEXT("SOFTWARE\\Debug");
const TCHAR *m_pGlobalKey = TEXT("GLOBAL");
TCHAR *pKeyNames[] =
{
TEXT("Types"),
TEXT("Level")
};
// DbgInitialize
// This sets the instance handle that the debug library uses to find
// the module's file name from the Win32 GetModuleFileName function
void WINAPI DbgInitialise(HINSTANCE hInst)
{
if (!m_bInit)
{
//InitializeCriticalSection(&m_CSDebug);
m_bInit = TRUE;
m_hInst = hInst;
DbgInitModuleName();
DbgInitModuleSettings();
DbgInitGlobalSettings();
}
}
// DbgTerminate
// This is called to clear up any resources the debug library uses - at the
// moment we delete our critical section and the handle of the output file.
void WINAPI DbgTerminate()
{
if (m_bInit)
{
if (m_hOutput != INVALID_HANDLE_VALUE)
{
DBGASSERTEXECUTE(CloseHandle(m_hOutput));
m_hOutput = INVALID_HANDLE_VALUE;
}
//DeleteCriticalSection(&m_CSDebug);
m_bInit = FALSE;
}
}
// DbgInitModuleName
// Initialise the module file name
void WINAPI DbgInitModuleName()
{
TCHAR FullName[iDEBUGINFO]; // Load the full path and module name
TCHAR *pName; // Searches from the end for a backslash
GetModuleFileName(m_hInst,FullName,iDEBUGINFO);
pName = _tcsrchr(FullName,'\\');
if (pName == NULL)
{
pName = FullName;
}
else
{
pName++;
}
lstrcpy(m_ModuleName,pName);
}
// DbgInitModuleSettings
// Retrieve the module-specific settings
void WINAPI DbgInitModuleSettings()
{
LONG lReturn; // Create key return value
TCHAR szInfo[iDEBUGINFO]; // Constructs key names
HKEY hModuleKey; // Module key handle
// Construct the base key name
wsprintf(szInfo,TEXT("%s\\%s"),m_pBaseKey,m_ModuleName);
// Create or open the key for this module
lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key
szInfo, // Address of subkey name
(DWORD)0, // Reserved value
NULL, // Address of class name
(DWORD)0, // Special options flags
KEY_ALL_ACCESS, // Desired security access
NULL, // Key security descriptor
&hModuleKey, // Opened handle buffer
NULL); // What really happened
if (lReturn != ERROR_SUCCESS)
{
DbgLogInfo(LOG_ERROR, 0, TEXT("Could not access module key"));
return;
}
DbgInitLogTo(hModuleKey);
DbgInitKeyLevels(hModuleKey, &m_dwTypes, &m_dwLevel);
RegCloseKey(hModuleKey);
}
// DbgInitGlobalSettings
// This is called by DbgInitialize to read the global debug settings for
// Level and Type from the registry. The Types are OR'ed together and m_dwLevel
// is set to the greater of the global and module-specific values.
void WINAPI DbgInitGlobalSettings()
{
LONG lReturn; // Create key return value
TCHAR szInfo[iDEBUGINFO]; // Constructs key names
HKEY hGlobalKey; // Global override key
DWORD dwTypes = 0;
DWORD dwLevel = 0;
// Construct the global base key name
wsprintf(szInfo,TEXT("%s\\%s"),m_pBaseKey,m_pGlobalKey);
// Create or open the key for this module
lReturn = RegCreateKeyEx(HKEY_LOCAL_MACHINE, // Handle of an open key
szInfo, // Address of subkey name
(DWORD)0, // Reserved value
NULL, // Address of class name
(DWORD)0, // Special options flags
KEY_ALL_ACCESS, // Desired security access
NULL, // Key security descriptor
&hGlobalKey, // Opened handle buffer
NULL); // What really happened
if (lReturn != ERROR_SUCCESS)
{
DbgLogInfo(LOG_ERROR, 0, TEXT("Could not access GLOBAL module key"));
return;
}
DbgInitKeyLevels(hGlobalKey, &dwTypes, &dwLevel);
RegCloseKey(hGlobalKey);
m_dwTypes |= dwTypes;
if (dwLevel > m_dwLevel)
m_dwLevel = dwLevel;
}
// DbgInitLogTo
// Called by DbgInitModuleSettings to setup alternate logging destinations
void WINAPI DbgInitLogTo(HKEY hKey)
{
LONG lReturn;
DWORD dwKeyType;
DWORD dwKeySize;
TCHAR szFile[MAX_PATH] = {0};
static const TCHAR cszKey[] = TEXT("LogToFile");
dwKeySize = MAX_PATH;
lReturn = RegQueryValueEx(
hKey, // Handle to an open key
cszKey, // Subkey name derivation
NULL, // Reserved field
&dwKeyType, // Returns the field type
(LPBYTE) szFile, // Returns the field's value
&dwKeySize); // Number of bytes transferred
// create an empty key if it does not already exist
if (lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ)
{
dwKeySize = 1;
lReturn = RegSetValueEx(
hKey, // Handle of an open key
cszKey, // Address of subkey name
(DWORD) 0, // Reserved field
REG_SZ, // Type of the key field
(PBYTE)szFile, // Value for the field
dwKeySize); // Size of the field buffer
}
// if an output-to was specified. try to open it.
if (m_hOutput != INVALID_HANDLE_VALUE)
{
DBGASSERTEXECUTE(CloseHandle(m_hOutput));
m_hOutput = INVALID_HANDLE_VALUE;
}
if (szFile[0] != 0)
{
if (!lstrcmpi(szFile, TEXT("Console")))
{
m_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
if (m_hOutput == INVALID_HANDLE_VALUE)
{
AllocConsole();
m_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
}
SetConsoleTitle (TEXT("Valve Debug Output"));
} else if (szFile[0] &&
lstrcmpi(szFile, TEXT("Debug")) &&
lstrcmpi(szFile, TEXT("Debugger")) &&
lstrcmpi(szFile, TEXT("Deb")))
{
m_hOutput = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != m_hOutput)
{
static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n");
SetFilePointer (m_hOutput, 0, NULL, FILE_END);
DbgOutString (cszBar);
}
}
}
}
// DbgInitKeyLevels
// This is called by DbgInitModuleSettings and DbgInitGlobalSettings to read
// settings for Types and Level from the registry
void WINAPI DbgInitKeyLevels(HKEY hKey, DWORD *pdwTypes, DWORD *pdwLevel)
{
LONG lReturn; // Create key return value
DWORD dwKeySize; // Size of the key value
DWORD dwKeyType; // Receives it's type
// Get the Types value
dwKeySize = sizeof(DWORD);
lReturn = RegQueryValueEx(
hKey, // Handle to an open key
pKeyNames[0], // Subkey name derivation
NULL, // Reserved field
&dwKeyType, // Returns the field type
(LPBYTE)pdwTypes, // Returns the field's value
&dwKeySize ); // Number of bytes transferred
// If either the key was not available or it was not a DWORD value
// then we ensure only the high priority debug logging is output
// but we try and update the field to a zero filled DWORD value
if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD)
{
*pdwTypes = 0;
lReturn = RegSetValueEx(
hKey, // Handle of an open key
pKeyNames[0], // Address of subkey name
(DWORD)0, // Reserved field
REG_DWORD, // Type of the key field
(PBYTE)pdwTypes, // Value for the field
sizeof(DWORD)); // Size of the field buffer
if (lReturn != ERROR_SUCCESS)
{
DbgLogInfo(LOG_ERROR, 0, TEXT("Could not create subkey %s"),pKeyNames[0]);
*pdwTypes = 0;
}
}
// Get the Level value
dwKeySize = sizeof(DWORD);
lReturn = RegQueryValueEx(
hKey, // Handle to an open key
pKeyNames[1], // Subkey name derivation
NULL, // Reserved field
&dwKeyType, // Returns the field type
(LPBYTE)pdwLevel, // Returns the field's value
&dwKeySize ); // Number of bytes transferred
// If either the key was not available or it was not a DWORD value
// then we ensure only the high priority debug logging is output
// but we try and update the field to a zero filled DWORD value
if (lReturn != ERROR_SUCCESS || dwKeyType != REG_DWORD)
{
*pdwLevel = 0;
lReturn = RegSetValueEx(
hKey, // Handle of an open key
pKeyNames[1], // Address of subkey name
(DWORD)0, // Reserved field
REG_DWORD, // Type of the key field
(PBYTE)pdwLevel, // Value for the field
sizeof(DWORD)); // Size of the field buffer
if (lReturn != ERROR_SUCCESS)
{
DbgLogInfo(LOG_ERROR, 0, TEXT("Could not create subkey %s"),pKeyNames[1]);
*pdwLevel = 0;
}
}
}
// DbgOutString
void WINAPI DbgOutString(LPCTSTR psz)
{
if (!m_bInit)
return;
if (m_hOutput != INVALID_HANDLE_VALUE) {
UINT cb = lstrlen(psz);
DWORD dw;
WriteFile (m_hOutput, psz, cb, &dw, NULL);
} else {
OutputDebugString (psz);
}
}
// DbgLogInfo
// Print a formatted string to the debugger prefixed with this module's name
// Because the debug code is linked statically every module loaded will
// have its own copy of this code. It therefore helps if the module name is
// included on the output so that the offending code can be easily found
void WINAPI DbgLogInfo(DWORD Type, DWORD Level, const TCHAR *pFormat,...)
{
if (!m_bInit)
return;
// Check the current level for this type combination */
if (((Type & m_dwTypes) == 0) || (m_dwLevel < Level))
return;
TCHAR szInfo[2000];
// Format the variable length parameter list
va_list va;
va_start(va, pFormat);
//lstrcpy(szInfo, m_ModuleName);
//lstrcat(szInfo, TEXT(": "));
wvsprintf(szInfo /* + lstrlen(szInfo) */, pFormat, va);
//lstrcat(szInfo, TEXT("\r\n"));
DbgOutString(szInfo);
va_end(va);
}
// DbgKernelAssert
// If we are executing as a pure kernel filter we cannot display message
// boxes to the user, this provides an alternative which puts the error
// condition on the debugger output with a suitable eye catching message
void WINAPI DbgKernelAssert(const TCHAR *pCondition, const TCHAR *pFileName, INT iLine)
{
if (!m_bInit)
return;
DbgLogInfo(LOG_ERROR, 0, TEXT(m_ModuleName));
DbgLogInfo(LOG_ERROR, 0, TEXT(": Assertion FAILED (%s) at line %d in file %s\r\n"), pCondition, iLine, pFileName);
DebugBreak();
}
#endif // _DEBUG

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

910
dlls/aflock.cpp Normal file
View file

@ -0,0 +1,910 @@
/***
*
* 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.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "squadmonster.h"
#define AFLOCK_MAX_RECRUIT_RADIUS 1024
#define AFLOCK_FLY_SPEED 125
#define AFLOCK_TURN_RATE 75
#define AFLOCK_ACCELERATE 10
#define AFLOCK_CHECK_DIST 192
#define AFLOCK_TOO_CLOSE 100
#define AFLOCK_TOO_FAR 256
//=========================================================
//=========================================================
class CFlockingFlyerFlock : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void KeyValue( KeyValueData *pkvd );
void SpawnFlock( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
// Sounds are shared by the flock
static void PrecacheFlockSounds( void );
int m_cFlockSize;
float m_flFlockRadius;
};
TYPEDESCRIPTION CFlockingFlyerFlock::m_SaveData[] =
{
DEFINE_FIELD( CFlockingFlyerFlock, m_cFlockSize, FIELD_INTEGER ),
DEFINE_FIELD( CFlockingFlyerFlock, m_flFlockRadius, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CFlockingFlyerFlock, CBaseMonster );
//=========================================================
//=========================================================
class CFlockingFlyer : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void SpawnCommonCode( void );
void EXPORT IdleThink( void );
void BoidAdvanceFrame( void );
void EXPORT FormFlock( void );
void EXPORT Start( void );
void EXPORT FlockLeaderThink( void );
void EXPORT FlockFollowerThink( void );
void EXPORT FallHack( void );
void MakeSound( void );
void AlertFlock( void );
void SpreadFlock( void );
void SpreadFlock2( void );
void Killed( entvars_t *pevAttacker, int iGib );
void Poop ( void );
BOOL FPathBlocked( void );
//void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int IsLeader( void ) { return m_pSquadLeader == this; }
int InSquad( void ) { return m_pSquadLeader != NULL; }
int SquadCount( void );
void SquadRemove( CFlockingFlyer *pRemove );
void SquadUnlink( void );
void SquadAdd( CFlockingFlyer *pAdd );
void SquadDisband( void );
CFlockingFlyer *m_pSquadLeader;
CFlockingFlyer *m_pSquadNext;
BOOL m_fTurning;// is this boid turning?
BOOL m_fCourseAdjust;// followers set this flag TRUE to override flocking while they avoid something
BOOL m_fPathBlocked;// TRUE if there is an obstacle ahead
Vector m_vecReferencePoint;// last place we saw leader
Vector m_vecAdjustedVelocity;// adjusted velocity (used when fCourseAdjust is TRUE)
float m_flGoalSpeed;
float m_flLastBlockedTime;
float m_flFakeBlockedTime;
float m_flAlertTime;
float m_flFlockNextSoundTime;
};
LINK_ENTITY_TO_CLASS( monster_flyer, CFlockingFlyer );
LINK_ENTITY_TO_CLASS( monster_flyer_flock, CFlockingFlyerFlock );
TYPEDESCRIPTION CFlockingFlyer::m_SaveData[] =
{
DEFINE_FIELD( CFlockingFlyer, m_pSquadLeader, FIELD_CLASSPTR ),
DEFINE_FIELD( CFlockingFlyer, m_pSquadNext, FIELD_CLASSPTR ),
DEFINE_FIELD( CFlockingFlyer, m_fTurning, FIELD_BOOLEAN ),
DEFINE_FIELD( CFlockingFlyer, m_fCourseAdjust, FIELD_BOOLEAN ),
DEFINE_FIELD( CFlockingFlyer, m_fPathBlocked, FIELD_BOOLEAN ),
DEFINE_FIELD( CFlockingFlyer, m_vecReferencePoint, FIELD_POSITION_VECTOR ),
DEFINE_FIELD( CFlockingFlyer, m_vecAdjustedVelocity, FIELD_VECTOR ),
DEFINE_FIELD( CFlockingFlyer, m_flGoalSpeed, FIELD_FLOAT ),
DEFINE_FIELD( CFlockingFlyer, m_flLastBlockedTime, FIELD_TIME ),
DEFINE_FIELD( CFlockingFlyer, m_flFakeBlockedTime, FIELD_TIME ),
DEFINE_FIELD( CFlockingFlyer, m_flAlertTime, FIELD_TIME ),
// DEFINE_FIELD( CFlockingFlyer, m_flFlockNextSoundTime, FIELD_TIME ), // don't need to save
};
IMPLEMENT_SAVERESTORE( CFlockingFlyer, CBaseMonster );
//=========================================================
//=========================================================
void CFlockingFlyerFlock :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "iFlockSize"))
{
m_cFlockSize = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "flFlockRadius"))
{
m_flFlockRadius = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
}
//=========================================================
//=========================================================
void CFlockingFlyerFlock :: Spawn( )
{
Precache( );
SpawnFlock();
REMOVE_ENTITY(ENT(pev)); // dump the spawn ent
}
//=========================================================
//=========================================================
void CFlockingFlyerFlock :: Precache( )
{
//PRECACHE_MODEL("models/aflock.mdl");
PRECACHE_MODEL("models/boid.mdl");
PrecacheFlockSounds();
}
void CFlockingFlyerFlock :: PrecacheFlockSounds( void )
{
PRECACHE_SOUND("boid/boid_alert1.wav" );
PRECACHE_SOUND("boid/boid_alert2.wav" );
PRECACHE_SOUND("boid/boid_idle1.wav" );
PRECACHE_SOUND("boid/boid_idle2.wav" );
}
//=========================================================
//=========================================================
void CFlockingFlyerFlock :: SpawnFlock( void )
{
float R = m_flFlockRadius;
int iCount;
Vector vecSpot;
CFlockingFlyer *pBoid, *pLeader;
pLeader = pBoid = NULL;
for ( iCount = 0 ; iCount < m_cFlockSize ; iCount++ )
{
pBoid = GetClassPtr( (CFlockingFlyer *)NULL );
if ( !pLeader )
{
// make this guy the leader.
pLeader = pBoid;
pLeader->m_pSquadLeader = pLeader;
pLeader->m_pSquadNext = NULL;
}
vecSpot.x = RANDOM_FLOAT( -R, R );
vecSpot.y = RANDOM_FLOAT( -R, R );
vecSpot.z = RANDOM_FLOAT( 0, 16 );
vecSpot = pev->origin + vecSpot;
UTIL_SetOrigin(pBoid->pev, vecSpot);
pBoid->pev->movetype = MOVETYPE_FLY;
pBoid->SpawnCommonCode();
pBoid->pev->flags &= ~FL_ONGROUND;
pBoid->pev->velocity = g_vecZero;
pBoid->pev->angles = pev->angles;
pBoid->pev->frame = 0;
pBoid->pev->nextthink = gpGlobals->time + 0.2;
pBoid->SetThink( CFlockingFlyer :: IdleThink );
if ( pBoid != pLeader )
{
pLeader->SquadAdd( pBoid );
}
}
}
//=========================================================
//=========================================================
void CFlockingFlyer :: Spawn( )
{
Precache( );
SpawnCommonCode();
pev->frame = 0;
pev->nextthink = gpGlobals->time + 0.1;
SetThink( IdleThink );
}
//=========================================================
//=========================================================
void CFlockingFlyer :: Precache( )
{
//PRECACHE_MODEL("models/aflock.mdl");
PRECACHE_MODEL("models/boid.mdl");
CFlockingFlyerFlock::PrecacheFlockSounds();
}
//=========================================================
//=========================================================
void CFlockingFlyer :: MakeSound( void )
{
if ( m_flAlertTime > gpGlobals->time )
{
// make agitated sounds
switch ( RANDOM_LONG( 0, 1 ) )
{
case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "boid/boid_alert1.wav", 1, ATTN_NORM ); break;
case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "boid/boid_alert2.wav", 1, ATTN_NORM ); break;
}
return;
}
// make normal sound
switch ( RANDOM_LONG( 0, 1 ) )
{
case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "boid/boid_idle1.wav", 1, ATTN_NORM ); break;
case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "boid/boid_idle2.wav", 1, ATTN_NORM ); break;
}
}
//=========================================================
//=========================================================
void CFlockingFlyer :: Killed( entvars_t *pevAttacker, int iGib )
{
CFlockingFlyer *pSquad;
pSquad = (CFlockingFlyer *)m_pSquadLeader;
while ( pSquad )
{
pSquad->m_flAlertTime = gpGlobals->time + 15;
pSquad = (CFlockingFlyer *)pSquad->m_pSquadNext;
}
if ( m_pSquadLeader )
{
m_pSquadLeader->SquadRemove( this );
}
pev->deadflag = DEAD_DEAD;
pev->framerate = 0;
pev->effects = EF_NOINTERP;
UTIL_SetSize( pev, Vector(0,0,0), Vector(0,0,0) );
pev->movetype = MOVETYPE_TOSS;
SetThink ( FallHack );
pev->nextthink = gpGlobals->time + 0.1;
}
void CFlockingFlyer :: FallHack( void )
{
if ( pev->flags & FL_ONGROUND )
{
if ( !FClassnameIs ( pev->groundentity, "worldspawn" ) )
{
pev->flags &= ~FL_ONGROUND;
pev->nextthink = gpGlobals->time + 0.1;
}
else
{
pev->velocity = g_vecZero;
SetThink( NULL );
}
}
}
//=========================================================
//=========================================================
void CFlockingFlyer :: SpawnCommonCode( )
{
pev->deadflag = DEAD_NO;
pev->classname = MAKE_STRING("monster_flyer");
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_FLY;
pev->takedamage = DAMAGE_NO;
pev->health = 1;
m_fPathBlocked = FALSE;// obstacles will be detected
m_flFieldOfView = 0.2;
//SET_MODEL(ENT(pev), "models/aflock.mdl");
SET_MODEL(ENT(pev), "models/boid.mdl");
// UTIL_SetSize(pev, Vector(0,0,0), Vector(0,0,0));
UTIL_SetSize(pev, Vector(-5,-5,0), Vector(5,5,2));
}
//=========================================================
//=========================================================
void CFlockingFlyer :: BoidAdvanceFrame ( )
{
float flapspeed = (pev->speed - pev->armorvalue) / AFLOCK_ACCELERATE;
pev->armorvalue = pev->armorvalue * .8 + pev->speed * .2;
if (flapspeed < 0) flapspeed = -flapspeed;
if (flapspeed < 0.25) flapspeed = 0.25;
if (flapspeed > 1.9) flapspeed = 1.9;
pev->framerate = flapspeed;
// lean
pev->avelocity.x = - (pev->angles.x + flapspeed * 5);
// bank
pev->avelocity.z = - (pev->angles.z + pev->avelocity.y);
// pev->framerate = flapspeed;
StudioFrameAdvance( 0.1 );
}
//=========================================================
//=========================================================
void CFlockingFlyer :: IdleThink( void )
{
pev->nextthink = gpGlobals->time + 0.2;
// see if there's a client in the same pvs as the monster
if ( !FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) )
{
SetThink( Start );
pev->nextthink = gpGlobals->time + 0.1;
}
}
//=========================================================
// Start - player enters the pvs, so get things going.
//=========================================================
void CFlockingFlyer :: Start( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if ( IsLeader() )
{
SetThink( FlockLeaderThink );
}
else
{
SetThink( FlockFollowerThink );
}
/*
Vector vecTakeOff;
vecTakeOff = Vector ( 0 , 0 , 0 );
vecTakeOff.z = 50 + RANDOM_FLOAT ( 0, 100 );
vecTakeOff.x = 20 - RANDOM_FLOAT ( 0, 40);
vecTakeOff.y = 20 - RANDOM_FLOAT ( 0, 40);
pev->velocity = vecTakeOff;
pev->speed = pev->velocity.Length();
pev->sequence = 0;
*/
SetActivity ( ACT_FLY );
ResetSequenceInfo( );
BoidAdvanceFrame( );
pev->speed = AFLOCK_FLY_SPEED;// no delay!
}
//=========================================================
// Leader boid calls this to form a flock from surrounding boids
//=========================================================
void CFlockingFlyer :: FormFlock( void )
{
if ( !InSquad() )
{
// I am my own leader
m_pSquadLeader = this;
m_pSquadNext = NULL;
int squadCount = 1;
CBaseEntity *pEntity = NULL;
while ((pEntity = UTIL_FindEntityInSphere( pEntity, pev->origin, AFLOCK_MAX_RECRUIT_RADIUS )) != NULL)
{
CBaseMonster *pRecruit = pEntity->MyMonsterPointer( );
if ( pRecruit && pRecruit != this && pRecruit->IsAlive() && !pRecruit->m_pCine )
{
// Can we recruit this guy?
if ( FClassnameIs ( pRecruit->pev, "monster_flyer" ) )
{
squadCount++;
SquadAdd( (CFlockingFlyer *)pRecruit );
}
}
}
}
SetThink( IdleThink );// now that flock is formed, go to idle and wait for a player to come along.
pev->nextthink = gpGlobals->time;
}
//=========================================================
// Searches for boids that are too close and pushes them away
//=========================================================
void CFlockingFlyer :: SpreadFlock( )
{
Vector vecDir;
float flSpeed;// holds vector magnitude while we fiddle with the direction
CFlockingFlyer *pList = m_pSquadLeader;
while ( pList )
{
if ( pList != this && ( pev->origin - pList->pev->origin ).Length() <= AFLOCK_TOO_CLOSE )
{
// push the other away
vecDir = ( pList->pev->origin - pev->origin );
vecDir = vecDir.Normalize();
// store the magnitude of the other boid's velocity, and normalize it so we
// can average in a course that points away from the leader.
flSpeed = pList->pev->velocity.Length();
pList->pev->velocity = pList->pev->velocity.Normalize();
pList->pev->velocity = ( pList->pev->velocity + vecDir ) * 0.5;
pList->pev->velocity = pList->pev->velocity * flSpeed;
}
pList = pList->m_pSquadNext;
}
}
//=========================================================
// Alters the caller's course if he's too close to others
//
// This function should **ONLY** be called when Caller's velocity is normalized!!
//=========================================================
void CFlockingFlyer :: SpreadFlock2 ( )
{
Vector vecDir;
CFlockingFlyer *pList = m_pSquadLeader;
while ( pList )
{
if ( pList != this && ( pev->origin - pList->pev->origin ).Length() <= AFLOCK_TOO_CLOSE )
{
vecDir = ( pev->origin - pList->pev->origin );
vecDir = vecDir.Normalize();
pev->velocity = (pev->velocity + vecDir);
}
pList = pList->m_pSquadNext;
}
}
//=========================================================
// FBoidPathBlocked - returns TRUE if there is an obstacle ahead
//=========================================================
BOOL CFlockingFlyer :: FPathBlocked( )
{
TraceResult tr;
Vector vecDist;// used for general measurements
Vector vecDir;// used for general measurements
BOOL fBlocked;
if ( m_flFakeBlockedTime > gpGlobals->time )
{
m_flLastBlockedTime = gpGlobals->time;
return TRUE;
}
// use VELOCITY, not angles, not all boids point the direction they are flying
//vecDir = UTIL_VecToAngles( pevBoid->velocity );
UTIL_MakeVectors ( pev->angles );
fBlocked = FALSE;// assume the way ahead is clear
// check for obstacle ahead
UTIL_TraceLine(pev->origin, pev->origin + gpGlobals->v_forward * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
m_flLastBlockedTime = gpGlobals->time;
fBlocked = TRUE;
}
// extra wide checks
UTIL_TraceLine(pev->origin + gpGlobals->v_right * 12, pev->origin + gpGlobals->v_right * 12 + gpGlobals->v_forward * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
m_flLastBlockedTime = gpGlobals->time;
fBlocked = TRUE;
}
UTIL_TraceLine(pev->origin - gpGlobals->v_right * 12, pev->origin - gpGlobals->v_right * 12 + gpGlobals->v_forward * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0)
{
m_flLastBlockedTime = gpGlobals->time;
fBlocked = TRUE;
}
if ( !fBlocked && gpGlobals->time - m_flLastBlockedTime > 6 )
{
// not blocked, and it's been a few seconds since we've actually been blocked.
m_flFakeBlockedTime = gpGlobals->time + RANDOM_LONG(1, 3);
}
return fBlocked;
}
//=========================================================
// Leader boids use this think every tenth
//=========================================================
void CFlockingFlyer :: FlockLeaderThink( void )
{
TraceResult tr;
Vector vecDist;// used for general measurements
Vector vecDir;// used for general measurements
int cProcessed = 0;// keep track of how many other boids we've processed
float flLeftSide;
float flRightSide;
pev->nextthink = gpGlobals->time + 0.1;
UTIL_MakeVectors ( pev->angles );
// is the way ahead clear?
if ( !FPathBlocked () )
{
// if the boid is turning, stop the trend.
if ( m_fTurning )
{
m_fTurning = FALSE;
pev->avelocity.y = 0;
}
m_fPathBlocked = FALSE;
if (pev->speed <= AFLOCK_FLY_SPEED )
pev->speed+= 5;
pev->velocity = gpGlobals->v_forward * pev->speed;
BoidAdvanceFrame( );
return;
}
// IF we get this far in the function, the leader's path is blocked!
m_fPathBlocked = TRUE;
if ( !m_fTurning)// something in the way and boid is not already turning to avoid
{
// measure clearance on left and right to pick the best dir to turn
UTIL_TraceLine(pev->origin, pev->origin + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
vecDist = (tr.vecEndPos - pev->origin);
flRightSide = vecDist.Length();
UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
vecDist = (tr.vecEndPos - pev->origin);
flLeftSide = vecDist.Length();
// turn right if more clearance on right side
if ( flRightSide > flLeftSide )
{
pev->avelocity.y = -AFLOCK_TURN_RATE;
m_fTurning = TRUE;
}
// default to left turn :)
else if ( flLeftSide > flRightSide )
{
pev->avelocity.y = AFLOCK_TURN_RATE;
m_fTurning = TRUE;
}
else
{
// equidistant. Pick randomly between left and right.
m_fTurning = TRUE;
if ( RANDOM_LONG( 0, 1 ) == 0 )
{
pev->avelocity.y = AFLOCK_TURN_RATE;
}
else
{
pev->avelocity.y = -AFLOCK_TURN_RATE;
}
}
}
SpreadFlock( );
pev->velocity = gpGlobals->v_forward * pev->speed;
// check and make sure we aren't about to plow into the ground, don't let it happen
UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_up * 16, ignore_monsters, ENT(pev), &tr);
if (tr.flFraction != 1.0 && pev->velocity.z < 0 )
pev->velocity.z = 0;
// maybe it did, though.
if ( FBitSet (pev->flags, FL_ONGROUND) )
{
UTIL_SetOrigin (pev, pev->origin + Vector ( 0 , 0 , 1 ) );
pev->velocity.z = 0;
}
if ( m_flFlockNextSoundTime < gpGlobals->time )
{
MakeSound();
m_flFlockNextSoundTime = gpGlobals->time + RANDOM_FLOAT( 1, 3 );
}
BoidAdvanceFrame( );
return;
}
//=========================================================
// follower boids execute this code when flocking
//=========================================================
void CFlockingFlyer :: FlockFollowerThink( void )
{
TraceResult tr;
Vector vecDist;
Vector vecDir;
Vector vecDirToLeader;
float flDistToLeader;
pev->nextthink = gpGlobals->time + 0.1;
if ( IsLeader() || !InSquad() )
{
// the leader has been killed and this flyer suddenly finds himself the leader.
SetThink ( FlockLeaderThink );
return;
}
vecDirToLeader = ( m_pSquadLeader->pev->origin - pev->origin );
flDistToLeader = vecDirToLeader.Length();
// match heading with leader
pev->angles = m_pSquadLeader->pev->angles;
//
// We can see the leader, so try to catch up to it
//
if ( FInViewCone ( m_pSquadLeader ) )
{
// if we're too far away, speed up
if ( flDistToLeader > AFLOCK_TOO_FAR )
{
m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 1.5;
}
// if we're too close, slow down
else if ( flDistToLeader < AFLOCK_TOO_CLOSE )
{
m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5;
}
}
else
{
// wait up! the leader isn't out in front, so we slow down to let him pass
m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5;
}
SpreadFlock2();
pev->speed = pev->velocity.Length();
pev->velocity = pev->velocity.Normalize();
// if we are too far from leader, average a vector towards it into our current velocity
if ( flDistToLeader > AFLOCK_TOO_FAR )
{
vecDirToLeader = vecDirToLeader.Normalize();
pev->velocity = (pev->velocity + vecDirToLeader) * 0.5;
}
// clamp speeds and handle acceleration
if ( m_flGoalSpeed > AFLOCK_FLY_SPEED * 2 )
{
m_flGoalSpeed = AFLOCK_FLY_SPEED * 2;
}
if ( pev->speed < m_flGoalSpeed )
{
pev->speed += AFLOCK_ACCELERATE;
}
else if ( pev->speed > m_flGoalSpeed )
{
pev->speed -= AFLOCK_ACCELERATE;
}
pev->velocity = pev->velocity * pev->speed;
BoidAdvanceFrame( );
}
/*
// Is this boid's course blocked?
if ( FBoidPathBlocked (pev) )
{
// course is still blocked from last time. Just keep flying along adjusted
// velocity
if ( m_fCourseAdjust )
{
pev->velocity = m_vecAdjustedVelocity * pev->speed;
return;
}
else // set course adjust flag and calculate adjusted velocity
{
m_fCourseAdjust = TRUE;
// use VELOCITY, not angles, not all boids point the direction they are flying
//vecDir = UTIL_VecToAngles( pev->velocity );
//UTIL_MakeVectors ( vecDir );
UTIL_MakeVectors ( pev->angles );
// measure clearance on left and right to pick the best dir to turn
UTIL_TraceLine(pev->origin, pev->origin + gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
vecDist = (tr.vecEndPos - pev->origin);
flRightSide = vecDist.Length();
UTIL_TraceLine(pev->origin, pev->origin - gpGlobals->v_right * AFLOCK_CHECK_DIST, ignore_monsters, ENT(pev), &tr);
vecDist = (tr.vecEndPos - pev->origin);
flLeftSide = vecDist.Length();
// slide right if more clearance on right side
if ( flRightSide > flLeftSide )
{
m_vecAdjustedVelocity = gpGlobals->v_right;
}
// else slide left
else
{
m_vecAdjustedVelocity = gpGlobals->v_right * -1;
}
}
return;
}
// if we make it this far, boids path is CLEAR!
m_fCourseAdjust = FALSE;
*/
//=========================================================
//
// SquadUnlink(), Unlink the squad pointers.
//
//=========================================================
void CFlockingFlyer :: SquadUnlink( void )
{
m_pSquadLeader = NULL;
m_pSquadNext = NULL;
}
//=========================================================
//
// SquadAdd(), add pAdd to my squad
//
//=========================================================
void CFlockingFlyer :: SquadAdd( CFlockingFlyer *pAdd )
{
ASSERT( pAdd!=NULL );
ASSERT( !pAdd->InSquad() );
ASSERT( this->IsLeader() );
pAdd->m_pSquadNext = m_pSquadNext;
m_pSquadNext = pAdd;
pAdd->m_pSquadLeader = this;
}
//=========================================================
//
// SquadRemove(), remove pRemove from my squad.
// If I am pRemove, promote m_pSquadNext to leader
//
//=========================================================
void CFlockingFlyer :: SquadRemove( CFlockingFlyer *pRemove )
{
ASSERT( pRemove!=NULL );
ASSERT( this->IsLeader() );
ASSERT( pRemove->m_pSquadLeader == this );
if ( SquadCount() > 2 )
{
// Removing the leader, promote m_pSquadNext to leader
if ( pRemove == this )
{
CFlockingFlyer *pLeader = m_pSquadNext;
// copy the enemy LKP to the new leader
pLeader->m_vecEnemyLKP = m_vecEnemyLKP;
if ( pLeader )
{
CFlockingFlyer *pList = pLeader;
while ( pList )
{
pList->m_pSquadLeader = pLeader;
pList = pList->m_pSquadNext;
}
}
SquadUnlink();
}
else // removing a node
{
CFlockingFlyer *pList = this;
// Find the node before pRemove
while ( pList->m_pSquadNext != pRemove )
{
// assert to test valid list construction
ASSERT( pList->m_pSquadNext != NULL );
pList = pList->m_pSquadNext;
}
// List validity
ASSERT( pList->m_pSquadNext == pRemove );
// Relink without pRemove
pList->m_pSquadNext = pRemove->m_pSquadNext;
// Unlink pRemove
pRemove->SquadUnlink();
}
}
else
SquadDisband();
}
//=========================================================
//
// SquadCount(), return the number of members of this squad
// callable from leaders & followers
//
//=========================================================
int CFlockingFlyer :: SquadCount( void )
{
CFlockingFlyer *pList = m_pSquadLeader;
int squadCount = 0;
while ( pList )
{
squadCount++;
pList = pList->m_pSquadNext;
}
return squadCount;
}
//=========================================================
//
// SquadDisband(), Unlink all squad members
//
//=========================================================
void CFlockingFlyer :: SquadDisband( void )
{
CFlockingFlyer *pList = m_pSquadLeader;
CFlockingFlyer *pNext;
while ( pList )
{
pNext = pList->m_pSquadNext;
pList->SquadUnlink();
pList = pNext;
}
}

1177
dlls/agrunt.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.
@ -295,13 +295,18 @@ void CBaseAnimating :: SetSequenceBox( void )
transformed.y = xvector.y*base.x + yvector.y*base.y;
transformed.z = base.z;
for ( int l = 0; l < 3; l++ )
{
if (transformed[l] < rmin[l])
rmin[l] = transformed[l];
if (transformed[l] > rmax[l])
rmax[l] = transformed[l];
}
if (transformed.x < rmin.x)
rmin.x = transformed.x;
if (transformed.x > rmax.x)
rmax.x = transformed.x;
if (transformed.y < rmin.y)
rmin.y = transformed.y;
if (transformed.y > rmax.y)
rmax.y = transformed.y;
if (transformed.z < rmin.z)
rmin.z = transformed.z;
if (transformed.z > rmax.z)
rmax.z = transformed.z;
}
}
}

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.
@ -16,7 +16,11 @@
#include <stdlib.h>
#include <string.h>
typedef bool BOOL;
#include "../common/nowin.h"
typedef int BOOL;
#define TRUE 1
#define FALSE 0
// hack into header files that we can ship
typedef int qboolean;
@ -29,8 +33,6 @@ typedef unsigned char byte;
#include "studio.h"
#include "../engine/studio.h"
#ifndef ACTIVITY_H
#include "activity.h"
#endif

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

1050
dlls/apache.cpp Normal file

File diff suppressed because it is too large Load diff

428
dlls/barnacle.cpp Normal file
View file

@ -0,0 +1,428 @@
/***
*
* 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.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// barnacle - stationary ceiling mounted 'fishing' monster
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
#define BARNACLE_BODY_HEIGHT 44 // how 'tall' the barnacle's model is.
#define BARNACLE_PULL_SPEED 8
#define BARNACLE_KILL_VICTIM_DELAY 5 // how many seconds after pulling prey in to gib them.
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define BARNACLE_AE_PUKEGIB 2
class CBarnacle : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
CBaseEntity *TongueTouchEnt ( float *pflLength );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void EXPORT BarnacleThink ( void );
void EXPORT WaitTillDead ( void );
void Killed( entvars_t *pevAttacker, int iGib );
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
float m_flAltitude;
float m_flKillVictimTime;
int m_cGibs;// barnacle loads up on gibs each time it kills something.
BOOL m_fTongueExtended;
BOOL m_fLiftingPrey;
float m_flTongueAdj;
};
LINK_ENTITY_TO_CLASS( monster_barnacle, CBarnacle );
TYPEDESCRIPTION CBarnacle::m_SaveData[] =
{
DEFINE_FIELD( CBarnacle, m_flAltitude, FIELD_FLOAT ),
DEFINE_FIELD( CBarnacle, m_flKillVictimTime, FIELD_TIME ),
DEFINE_FIELD( CBarnacle, m_cGibs, FIELD_INTEGER ),// barnacle loads up on gibs each time it kills something.
DEFINE_FIELD( CBarnacle, m_fTongueExtended, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarnacle, m_fLiftingPrey, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarnacle, m_flTongueAdj, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CBarnacle, CBaseMonster );
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CBarnacle :: Classify ( void )
{
return CLASS_ALIEN_MONSTER;
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CBarnacle :: HandleAnimEvent( MonsterEvent_t *pEvent )
{
switch( pEvent->event )
{
case BARNACLE_AE_PUKEGIB:
CGib::SpawnRandomGibs( pev, 1, 1 );
break;
default:
CBaseMonster::HandleAnimEvent( pEvent );
break;
}
}
//=========================================================
// Spawn
//=========================================================
void CBarnacle :: Spawn()
{
Precache( );
SET_MODEL(ENT(pev), "models/barnacle.mdl");
UTIL_SetSize( pev, Vector(-16, -16, -32), Vector(16, 16, 0) );
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_NONE;
pev->takedamage = DAMAGE_AIM;
m_bloodColor = BLOOD_COLOR_RED;
pev->effects = EF_INVLIGHT; // take light from the ceiling
pev->health = 25;
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
m_flKillVictimTime = 0;
m_cGibs = 0;
m_fLiftingPrey = FALSE;
m_flTongueAdj = -100;
InitBoneControllers();
SetActivity ( ACT_IDLE );
SetThink ( BarnacleThink );
pev->nextthink = gpGlobals->time + 0.5;
UTIL_SetOrigin ( pev, pev->origin );
}
int CBarnacle::TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
if ( bitsDamageType & DMG_CLUB )
{
flDamage = pev->health;
}
return CBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
//=========================================================
//=========================================================
void CBarnacle :: BarnacleThink ( void )
{
CBaseEntity *pTouchEnt;
CBaseMonster *pVictim;
float flLength;
pev->nextthink = gpGlobals->time + 0.1;
if ( m_hEnemy != NULL )
{
// barnacle has prey.
if ( !m_hEnemy->IsAlive() )
{
// someone (maybe even the barnacle) killed the prey. Reset barnacle.
m_fLiftingPrey = FALSE;// indicate that we're not lifting prey.
m_hEnemy = NULL;
return;
}
if ( m_fLiftingPrey )
{
if ( m_hEnemy != NULL && m_hEnemy->pev->deadflag != DEAD_NO )
{
// crap, someone killed the prey on the way up.
m_hEnemy = NULL;
m_fLiftingPrey = FALSE;
return;
}
// still pulling prey.
Vector vecNewEnemyOrigin = m_hEnemy->pev->origin;
vecNewEnemyOrigin.x = pev->origin.x;
vecNewEnemyOrigin.y = pev->origin.y;
// guess as to where their neck is
vecNewEnemyOrigin.x -= 6 * cos(m_hEnemy->pev->angles.y * M_PI/180.0);
vecNewEnemyOrigin.y -= 6 * sin(m_hEnemy->pev->angles.y * M_PI/180.0);
m_flAltitude -= BARNACLE_PULL_SPEED;
vecNewEnemyOrigin.z += BARNACLE_PULL_SPEED;
if ( fabs( pev->origin.z - ( vecNewEnemyOrigin.z + m_hEnemy->pev->view_ofs.z - 8 ) ) < BARNACLE_BODY_HEIGHT )
{
// prey has just been lifted into position ( if the victim origin + eye height + 8 is higher than the bottom of the barnacle, it is assumed that the head is within barnacle's body )
m_fLiftingPrey = FALSE;
EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_bite3.wav", 1, ATTN_NORM );
pVictim = m_hEnemy->MyMonsterPointer();
m_flKillVictimTime = gpGlobals->time + 10;// now that the victim is in place, the killing bite will be administered in 10 seconds.
if ( pVictim )
{
pVictim->BarnacleVictimBitten( pev );
SetActivity ( ACT_EAT );
}
}
UTIL_SetOrigin ( m_hEnemy->pev, vecNewEnemyOrigin );
}
else
{
// prey is lifted fully into feeding position and is dangling there.
pVictim = m_hEnemy->MyMonsterPointer();
if ( m_flKillVictimTime != -1 && gpGlobals->time > m_flKillVictimTime )
{
// kill!
if ( pVictim )
{
pVictim->TakeDamage ( pev, pev, pVictim->pev->health, DMG_SLASH | DMG_ALWAYSGIB );
m_cGibs = 3;
}
return;
}
// bite prey every once in a while
if ( pVictim && ( RANDOM_LONG(0,49) == 0 ) )
{
switch ( RANDOM_LONG(0,2) )
{
case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM ); break;
case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM ); break;
case 2: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM ); break;
}
pVictim->BarnacleVictimBitten( pev );
}
}
}
else
{
// barnacle has no prey right now, so just idle and check to see if anything is touching the tongue.
// If idle and no nearby client, don't think so often
if ( FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) )
pev->nextthink = gpGlobals->time + RANDOM_FLOAT(1,1.5); // Stagger a bit to keep barnacles from thinking on the same frame
if ( m_fSequenceFinished )
{// this is done so barnacle will fidget.
SetActivity ( ACT_IDLE );
m_flTongueAdj = -100;
}
if ( m_cGibs && RANDOM_LONG(0,99) == 1 )
{
// cough up a gib.
CGib::SpawnRandomGibs( pev, 1, 1 );
m_cGibs--;
switch ( RANDOM_LONG(0,2) )
{
case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew1.wav", 1, ATTN_NORM ); break;
case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew2.wav", 1, ATTN_NORM ); break;
case 2: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_chew3.wav", 1, ATTN_NORM ); break;
}
}
pTouchEnt = TongueTouchEnt( &flLength );
if ( pTouchEnt != NULL && m_fTongueExtended )
{
// tongue is fully extended, and is touching someone.
if ( pTouchEnt->FBecomeProne() )
{
EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_alert2.wav", 1, ATTN_NORM );
SetSequenceByName ( "attack1" );
m_flTongueAdj = -20;
m_hEnemy = pTouchEnt;
pTouchEnt->pev->movetype = MOVETYPE_FLY;
pTouchEnt->pev->velocity = g_vecZero;
pTouchEnt->pev->basevelocity = g_vecZero;
pTouchEnt->pev->origin.x = pev->origin.x;
pTouchEnt->pev->origin.y = pev->origin.y;
m_fLiftingPrey = TRUE;// indicate that we should be lifting prey.
m_flKillVictimTime = -1;// set this to a bogus time while the victim is lifted.
m_flAltitude = (pev->origin.z - pTouchEnt->EyePosition().z);
}
}
else
{
// calculate a new length for the tongue to be clear of anything else that moves under it.
if ( m_flAltitude < flLength )
{
// if tongue is higher than is should be, lower it kind of slowly.
m_flAltitude += BARNACLE_PULL_SPEED;
m_fTongueExtended = FALSE;
}
else
{
m_flAltitude = flLength;
m_fTongueExtended = TRUE;
}
}
}
// ALERT( at_console, "tounge %f\n", m_flAltitude + m_flTongueAdj );
SetBoneController( 0, -(m_flAltitude + m_flTongueAdj) );
StudioFrameAdvance( 0.1 );
}
//=========================================================
// Killed.
//=========================================================
void CBarnacle :: Killed( entvars_t *pevAttacker, int iGib )
{
CBaseMonster *pVictim;
pev->solid = SOLID_NOT;
pev->takedamage = DAMAGE_NO;
if ( m_hEnemy != NULL )
{
pVictim = m_hEnemy->MyMonsterPointer();
if ( pVictim )
{
pVictim->BarnacleVictimReleased();
}
}
// CGib::SpawnRandomGibs( pev, 4, 1 );
switch ( RANDOM_LONG ( 0, 1 ) )
{
case 0: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_die1.wav", 1, ATTN_NORM ); break;
case 1: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "barnacle/bcl_die3.wav", 1, ATTN_NORM ); break;
}
SetActivity ( ACT_DIESIMPLE );
SetBoneController( 0, 0 );
StudioFrameAdvance( 0.1 );
pev->nextthink = gpGlobals->time + 0.1;
SetThink ( WaitTillDead );
}
//=========================================================
//=========================================================
void CBarnacle :: WaitTillDead ( void )
{
pev->nextthink = gpGlobals->time + 0.1;
float flInterval = StudioFrameAdvance( 0.1 );
DispatchAnimEvents ( flInterval );
if ( m_fSequenceFinished )
{
// death anim finished.
StopAnimation();
SetThink ( NULL );
}
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CBarnacle :: Precache()
{
PRECACHE_MODEL("models/barnacle.mdl");
PRECACHE_SOUND("barnacle/bcl_alert2.wav");//happy, lifting food up
PRECACHE_SOUND("barnacle/bcl_bite3.wav");//just got food to mouth
PRECACHE_SOUND("barnacle/bcl_chew1.wav");
PRECACHE_SOUND("barnacle/bcl_chew2.wav");
PRECACHE_SOUND("barnacle/bcl_chew3.wav");
PRECACHE_SOUND("barnacle/bcl_die1.wav" );
PRECACHE_SOUND("barnacle/bcl_die3.wav" );
}
//=========================================================
// TongueTouchEnt - does a trace along the barnacle's tongue
// to see if any entity is touching it. Also stores the length
// of the trace in the int pointer provided.
//=========================================================
#define BARNACLE_CHECK_SPACING 8
CBaseEntity *CBarnacle :: TongueTouchEnt ( float *pflLength )
{
TraceResult tr;
float length;
// trace once to hit architecture and see if the tongue needs to change position.
UTIL_TraceLine ( pev->origin, pev->origin - Vector ( 0 , 0 , 2048 ), ignore_monsters, ENT(pev), &tr );
length = fabs( pev->origin.z - tr.vecEndPos.z );
if ( pflLength )
{
*pflLength = length;
}
Vector delta = Vector( BARNACLE_CHECK_SPACING, BARNACLE_CHECK_SPACING, 0 );
Vector mins = pev->origin - delta;
Vector maxs = pev->origin + delta;
maxs.z = pev->origin.z;
mins.z -= length;
CBaseEntity *pList[10];
int count = UTIL_EntitiesInBox( pList, 10, mins, maxs, (FL_CLIENT|FL_MONSTER) );
if ( count )
{
for ( int i = 0; i < count; i++ )
{
// only clients and monsters
if ( pList[i] != this && IRelationship( pList[i] ) > R_NO && pList[ i ]->pev->deadflag == DEAD_NO ) // this ent is one of our enemies. Barnacle tries to eat it.
{
return pList[i];
}
}
}
return NULL;
}

841
dlls/barney.cpp Normal file
View file

@ -0,0 +1,841 @@
/***
*
* 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.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// monster template
//=========================================================
// UNDONE: Holster weapon?
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "talkmonster.h"
#include "schedule.h"
#include "defaultai.h"
#include "scripted.h"
#include "weapons.h"
#include "soundent.h"
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
// first flag is barney dying for scripted sequences?
#define BARNEY_AE_DRAW ( 2 )
#define BARNEY_AE_SHOOT ( 3 )
#define BARNEY_AE_HOLSTER ( 4 )
#define BARNEY_BODY_GUNHOLSTERED 0
#define BARNEY_BODY_GUNDRAWN 1
#define BARNEY_BODY_GUNGONE 2
class CBarney : public CTalkMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int ISoundMask( void );
void BarneyFirePistol( void );
void AlertSound( void );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void RunTask( Task_t *pTask );
void StartTask( Task_t *pTask );
virtual int ObjectCaps( void ) { return CTalkMonster :: ObjectCaps() | FCAP_IMPULSE_USE; }
int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
BOOL CheckRangeAttack1 ( float flDot, float flDist );
void DeclineFollowing( void );
// Override these to set behavior
Schedule_t *GetScheduleOfType ( int Type );
Schedule_t *GetSchedule ( void );
MONSTERSTATE GetIdealState ( void );
void DeathSound( void );
void PainSound( void );
void TalkInit( void );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
void Killed( entvars_t *pevAttacker, int iGib );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
BOOL m_fGunDrawn;
float m_painTime;
float m_checkAttackTime;
BOOL m_lastAttackCheck;
// UNDONE: What is this for? It isn't used?
float m_flPlayerDamage;// how much pain has the player inflicted on me?
CUSTOM_SCHEDULES;
};
LINK_ENTITY_TO_CLASS( monster_barney, CBarney );
TYPEDESCRIPTION CBarney::m_SaveData[] =
{
DEFINE_FIELD( CBarney, m_fGunDrawn, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarney, m_painTime, FIELD_TIME ),
DEFINE_FIELD( CBarney, m_checkAttackTime, FIELD_TIME ),
DEFINE_FIELD( CBarney, m_lastAttackCheck, FIELD_BOOLEAN ),
DEFINE_FIELD( CBarney, m_flPlayerDamage, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CBarney, CTalkMonster );
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
Task_t tlBaFollow[] =
{
{ TASK_MOVE_TO_TARGET_RANGE,(float)128 }, // Move within 128 of target ent (client)
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_FACE },
};
Schedule_t slBaFollow[] =
{
{
tlBaFollow,
ARRAYSIZE ( tlBaFollow ),
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND |
bits_COND_PROVOKED,
bits_SOUND_DANGER,
"Follow"
},
};
//=========================================================
// BarneyDraw- much better looking draw schedule for when
// barney knows who he's gonna attack.
//=========================================================
Task_t tlBarneyEnemyDraw[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_FACE_ENEMY, 0 },
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float) ACT_ARM },
};
Schedule_t slBarneyEnemyDraw[] =
{
{
tlBarneyEnemyDraw,
ARRAYSIZE ( tlBarneyEnemyDraw ),
0,
0,
"Barney Enemy Draw"
}
};
Task_t tlBaFaceTarget[] =
{
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
{ TASK_FACE_TARGET, (float)0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
{ TASK_SET_SCHEDULE, (float)SCHED_TARGET_CHASE },
};
Schedule_t slBaFaceTarget[] =
{
{
tlBaFaceTarget,
ARRAYSIZE ( tlBaFaceTarget ),
bits_COND_CLIENT_PUSH |
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND |
bits_COND_PROVOKED,
bits_SOUND_DANGER,
"FaceTarget"
},
};
Task_t tlIdleBaStand[] =
{
{ TASK_STOP_MOVING, 0 },
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
{ TASK_WAIT, (float)2 }, // repick IDLESTAND every two seconds.
{ TASK_TLK_HEADRESET, (float)0 }, // reset head position
};
Schedule_t slIdleBaStand[] =
{
{
tlIdleBaStand,
ARRAYSIZE ( tlIdleBaStand ),
bits_COND_NEW_ENEMY |
bits_COND_LIGHT_DAMAGE |
bits_COND_HEAVY_DAMAGE |
bits_COND_HEAR_SOUND |
bits_COND_SMELL |
bits_COND_PROVOKED,
bits_SOUND_COMBAT |// sound flags - change these, and you'll break the talking code.
//bits_SOUND_PLAYER |
//bits_SOUND_WORLD |
bits_SOUND_DANGER |
bits_SOUND_MEAT |// scents
bits_SOUND_CARCASS |
bits_SOUND_GARBAGE,
"IdleStand"
},
};
DEFINE_CUSTOM_SCHEDULES( CBarney )
{
slBaFollow,
slBarneyEnemyDraw,
slBaFaceTarget,
slIdleBaStand,
};
IMPLEMENT_CUSTOM_SCHEDULES( CBarney, CTalkMonster );
void CBarney :: StartTask( Task_t *pTask )
{
CTalkMonster::StartTask( pTask );
}
void CBarney :: RunTask( Task_t *pTask )
{
switch ( pTask->iTask )
{
case TASK_RANGE_ATTACK1:
if (m_hEnemy != NULL && (m_hEnemy->IsPlayer()))
{
pev->framerate = 1.5;
}
CTalkMonster::RunTask( pTask );
break;
default:
CTalkMonster::RunTask( pTask );
break;
}
}
//=========================================================
// ISoundMask - returns a bit mask indicating which types
// of sounds this monster regards.
//=========================================================
int CBarney :: ISoundMask ( void)
{
return bits_SOUND_WORLD |
bits_SOUND_COMBAT |
bits_SOUND_CARCASS |
bits_SOUND_MEAT |
bits_SOUND_GARBAGE |
bits_SOUND_DANGER |
bits_SOUND_PLAYER;
}
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CBarney :: Classify ( void )
{
return CLASS_PLAYER_ALLY;
}
//=========================================================
// ALertSound - barney says "Freeze!"
//=========================================================
void CBarney :: AlertSound( void )
{
if ( m_hEnemy != NULL )
{
if ( FOkToSpeak() )
{
PlaySentence( "BA_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE );
}
}
}
//=========================================================
// SetYawSpeed - allows each sequence to have a different
// turn rate associated with it.
//=========================================================
void CBarney :: SetYawSpeed ( void )
{
int ys;
ys = 0;
switch ( m_Activity )
{
case ACT_IDLE:
ys = 70;
break;
case ACT_WALK:
ys = 70;
break;
case ACT_RUN:
ys = 90;
break;
default:
ys = 70;
break;
}
pev->yaw_speed = ys;
}
//=========================================================
// CheckRangeAttack1
//=========================================================
BOOL CBarney :: CheckRangeAttack1 ( float flDot, float flDist )
{
if ( flDist <= 1024 && flDot >= 0.5 )
{
if ( gpGlobals->time > m_checkAttackTime )
{
TraceResult tr;
Vector shootOrigin = pev->origin + Vector( 0, 0, 55 );
CBaseEntity *pEnemy = m_hEnemy;
Vector shootTarget = ( (pEnemy->BodyTarget( shootOrigin ) - pEnemy->pev->origin) + m_vecEnemyLKP );
UTIL_TraceLine( shootOrigin, shootTarget, dont_ignore_monsters, ENT(pev), &tr );
m_checkAttackTime = gpGlobals->time + 1;
if ( tr.flFraction == 1.0 || (tr.pHit != NULL && CBaseEntity::Instance(tr.pHit) == pEnemy) )
m_lastAttackCheck = TRUE;
else
m_lastAttackCheck = FALSE;
m_checkAttackTime = gpGlobals->time + 1.5;
}
return m_lastAttackCheck;
}
return FALSE;
}
//=========================================================
// BarneyFirePistol - shoots one round from the pistol at
// the enemy barney is facing.
//=========================================================
void CBarney :: BarneyFirePistol ( void )
{
Vector vecShootOrigin;
UTIL_MakeVectors(pev->angles);
vecShootOrigin = pev->origin + Vector( 0, 0, 55 );
Vector vecShootDir = ShootAtEnemy( vecShootOrigin );
Vector angDir = UTIL_VecToAngles( vecShootDir );
SetBlending( 0, angDir.x );
pev->effects = EF_MUZZLEFLASH;
FireBullets(1, vecShootOrigin, vecShootDir, VECTOR_CONE_2DEGREES, 1024, BULLET_MONSTER_9MM );
int pitchShift = RANDOM_LONG( 0, 20 );
// Only shift about half the time
if ( pitchShift > 10 )
pitchShift = 0;
else
pitchShift -= 5;
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "barney/ba_attack2.wav", 1, ATTN_NORM, 0, 100 + pitchShift );
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, 384, 0.3 );
// UNDONE: Reload?
m_cAmmoLoaded--;// take away a bullet!
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//
// Returns number of events handled, 0 if none.
//=========================================================
void CBarney :: HandleAnimEvent( MonsterEvent_t *pEvent )
{
switch( pEvent->event )
{
case BARNEY_AE_SHOOT:
BarneyFirePistol();
break;
case BARNEY_AE_DRAW:
// barney's bodygroup switches here so he can pull gun from holster
pev->body = BARNEY_BODY_GUNDRAWN;
m_fGunDrawn = TRUE;
break;
case BARNEY_AE_HOLSTER:
// change bodygroup to replace gun in holster
pev->body = BARNEY_BODY_GUNHOLSTERED;
m_fGunDrawn = FALSE;
break;
default:
CTalkMonster::HandleAnimEvent( pEvent );
}
}
//=========================================================
// Spawn
//=========================================================
void CBarney :: Spawn()
{
Precache( );
SET_MODEL(ENT(pev), "models/barney.mdl");
UTIL_SetSize(pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX);
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_STEP;
m_bloodColor = BLOOD_COLOR_RED;
pev->health = gSkillData.barneyHealth;
pev->view_ofs = Vector ( 0, 0, 50 );// position of the eyes relative to monster's origin.
m_flFieldOfView = VIEW_FIELD_WIDE; // NOTE: we need a wide field of view so npc will notice player and say hello
m_MonsterState = MONSTERSTATE_NONE;
pev->body = 0; // gun in holster
m_fGunDrawn = FALSE;
m_afCapability = bits_CAP_HEAR | bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP;
MonsterInit();
SetUse( FollowerUse );
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CBarney :: Precache()
{
PRECACHE_MODEL("models/barney.mdl");
PRECACHE_SOUND("barney/ba_attack1.wav" );
PRECACHE_SOUND("barney/ba_attack2.wav" );
PRECACHE_SOUND("barney/ba_pain1.wav");
PRECACHE_SOUND("barney/ba_pain2.wav");
PRECACHE_SOUND("barney/ba_pain3.wav");
PRECACHE_SOUND("barney/ba_die1.wav");
PRECACHE_SOUND("barney/ba_die2.wav");
PRECACHE_SOUND("barney/ba_die3.wav");
// every new barney must call this, otherwise
// when a level is loaded, nobody will talk (time is reset to 0)
TalkInit();
CTalkMonster::Precache();
}
// Init talk data
void CBarney :: TalkInit()
{
CTalkMonster::TalkInit();
// scientists speach group names (group names are in sentences.txt)
m_szGrp[TLK_ANSWER] = "BA_ANSWER";
m_szGrp[TLK_QUESTION] = "BA_QUESTION";
m_szGrp[TLK_IDLE] = "BA_IDLE";
m_szGrp[TLK_STARE] = "BA_STARE";
m_szGrp[TLK_USE] = "BA_OK";
m_szGrp[TLK_UNUSE] = "BA_WAIT";
m_szGrp[TLK_STOP] = "BA_STOP";
m_szGrp[TLK_NOSHOOT] = "BA_SCARED";
m_szGrp[TLK_HELLO] = "BA_HELLO";
m_szGrp[TLK_PLHURT1] = "!BA_CUREA";
m_szGrp[TLK_PLHURT2] = "!BA_CUREB";
m_szGrp[TLK_PLHURT3] = "!BA_CUREC";
m_szGrp[TLK_PHELLO] = NULL; //"BA_PHELLO"; // UNDONE
m_szGrp[TLK_PIDLE] = NULL; //"BA_PIDLE"; // UNDONE
m_szGrp[TLK_PQUESTION] = "BA_PQUEST"; // UNDONE
m_szGrp[TLK_SMELL] = "BA_SMELL";
m_szGrp[TLK_WOUND] = "BA_WOUND";
m_szGrp[TLK_MORTAL] = "BA_MORTAL";
// get voice for head - just one barney voice for now
m_voicePitch = 100;
}
static BOOL IsFacing( entvars_t *pevTest, const Vector &reference )
{
Vector vecDir = (reference - pevTest->origin);
vecDir.z = 0;
vecDir = vecDir.Normalize();
Vector forward, angle;
angle = pevTest->v_angle;
angle.x = 0;
UTIL_MakeVectorsPrivate( angle, forward, NULL, NULL );
// He's facing me, he meant it
if ( DotProduct( forward, vecDir ) > 0.96 ) // +/- 15 degrees or so
{
return TRUE;
}
return FALSE;
}
int CBarney :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType)
{
// make sure friends talk about it if player hurts talkmonsters...
int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
if ( !IsAlive() || pev->deadflag == DEAD_DYING )
return ret;
if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) )
{
m_flPlayerDamage += flDamage;
// This is a heurstic to determine if the player intended to harm me
// If I have an enemy, we can't establish intent (may just be crossfire)
if ( m_hEnemy == NULL )
{
// If the player was facing directly at me, or I'm already suspicious, get mad
if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) )
{
// Alright, now I'm pissed!
PlaySentence( "BA_MAD", 4, VOL_NORM, ATTN_NORM );
Remember( bits_MEMORY_PROVOKED );
StopFollowing( TRUE );
}
else
{
// Hey, be careful with that
PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM );
Remember( bits_MEMORY_SUSPICIOUS );
}
}
else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO )
{
PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM );
}
}
return ret;
}
//=========================================================
// PainSound
//=========================================================
void CBarney :: PainSound ( void )
{
if (gpGlobals->time < m_painTime)
return;
m_painTime = gpGlobals->time + RANDOM_FLOAT(0.5, 0.75);
switch (RANDOM_LONG(0,2))
{
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_pain3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
}
}
//=========================================================
// DeathSound
//=========================================================
void CBarney :: DeathSound ( void )
{
switch (RANDOM_LONG(0,2))
{
case 0: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die1.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
case 1: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die2.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
case 2: EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "barney/ba_die3.wav", 1, ATTN_NORM, 0, GetVoicePitch()); break;
}
}
void CBarney::TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType)
{
switch( ptr->iHitgroup)
{
case HITGROUP_CHEST:
case HITGROUP_STOMACH:
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_BLAST))
{
flDamage = flDamage / 2;
}
break;
case 10:
if (bitsDamageType & (DMG_BULLET | DMG_SLASH | DMG_CLUB))
{
flDamage -= 20;
if (flDamage <= 0)
{
UTIL_Ricochet( ptr->vecEndPos, 1.0 );
flDamage = 0.01;
}
}
// always a head shot
ptr->iHitgroup = HITGROUP_HEAD;
break;
}
CTalkMonster::TraceAttack( pevAttacker, flDamage, vecDir, ptr, bitsDamageType );
}
void CBarney::Killed( entvars_t *pevAttacker, int iGib )
{
if ( pev->body < BARNEY_BODY_GUNGONE )
{// drop the gun!
Vector vecGunPos;
Vector vecGunAngles;
pev->body = BARNEY_BODY_GUNGONE;
GetAttachment( 0, vecGunPos, vecGunAngles );
CBaseEntity *pGun = DropItem( "weapon_9mmhandgun", vecGunPos, vecGunAngles );
}
SetUse( NULL );
CTalkMonster::Killed( pevAttacker, iGib );
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================
Schedule_t* CBarney :: GetScheduleOfType ( int Type )
{
Schedule_t *psched;
switch( Type )
{
case SCHED_ARM_WEAPON:
if ( m_hEnemy != NULL )
{
// face enemy, then draw.
return slBarneyEnemyDraw;
}
break;
// Hook these to make a looping schedule
case SCHED_TARGET_FACE:
// call base class default so that barney will talk
// when 'used'
psched = CTalkMonster::GetScheduleOfType(Type);
if (psched == slIdleStand)
return slBaFaceTarget; // override this for different target face behavior
else
return psched;
case SCHED_TARGET_CHASE:
return slBaFollow;
case SCHED_IDLE_STAND:
// call base class default so that scientist will talk
// when standing during idle
psched = CTalkMonster::GetScheduleOfType(Type);
if (psched == slIdleStand)
{
// just look straight ahead.
return slIdleBaStand;
}
else
return psched;
}
return CTalkMonster::GetScheduleOfType( Type );
}
//=========================================================
// GetSchedule - Decides which type of schedule best suits
// the monster's current state and conditions. Then calls
// monster's member function to get a pointer to a schedule
// of the proper type.
//=========================================================
Schedule_t *CBarney :: GetSchedule ( void )
{
if ( HasConditions( bits_COND_HEAR_SOUND ) )
{
CSound *pSound;
pSound = PBestSound();
ASSERT( pSound != NULL );
if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) )
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND );
}
if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() )
{
PlaySentence( "BA_KILL", 4, VOL_NORM, ATTN_NORM );
}
switch( m_MonsterState )
{
case MONSTERSTATE_COMBAT:
{
// dead enemy
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
{
// call base class, all code to handle dead enemies is centralized there.
return CBaseMonster :: GetSchedule();
}
// always act surprized with a new enemy
if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) )
return GetScheduleOfType( SCHED_SMALL_FLINCH );
// wait for one schedule to draw gun
if (!m_fGunDrawn )
return GetScheduleOfType( SCHED_ARM_WEAPON );
if ( HasConditions( bits_COND_HEAVY_DAMAGE ) )
return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY );
}
break;
case MONSTERSTATE_ALERT:
case MONSTERSTATE_IDLE:
if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE))
{
// flinch if hurt
return GetScheduleOfType( SCHED_SMALL_FLINCH );
}
if ( m_hEnemy == NULL && IsFollowing() )
{
if ( !m_hTargetEnt->IsAlive() )
{
// UNDONE: Comment about the recently dead player here?
StopFollowing( FALSE );
break;
}
else
{
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
{
return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW );
}
return GetScheduleOfType( SCHED_TARGET_FACE );
}
}
if ( HasConditions( bits_COND_CLIENT_PUSH ) )
{
return GetScheduleOfType( SCHED_MOVE_AWAY );
}
// try to say something about smells
TrySmellTalk();
break;
}
return CTalkMonster::GetSchedule();
}
MONSTERSTATE CBarney :: GetIdealState ( void )
{
return CTalkMonster::GetIdealState();
}
void CBarney::DeclineFollowing( void )
{
PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM );
}
//=========================================================
// DEAD BARNEY PROP
//
// Designer selects a pose in worldcraft, 0 through num_poses-1
// this value is added to what is selected as the 'first dead pose'
// among the monster's normal animations. All dead poses must
// appear sequentially in the model file. Be sure and set
// the m_iFirstPose properly!
//
//=========================================================
class CDeadBarney : public CBaseMonster
{
public:
void Spawn( void );
int Classify ( void ) { return CLASS_PLAYER_ALLY; }
void KeyValue( KeyValueData *pkvd );
int m_iPose;// which sequence to display -- temporary, don't need to save
static char *m_szPoses[3];
};
char *CDeadBarney::m_szPoses[] = { "lying_on_back", "lying_on_side", "lying_on_stomach" };
void CDeadBarney::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "pose"))
{
m_iPose = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CBaseMonster::KeyValue( pkvd );
}
LINK_ENTITY_TO_CLASS( monster_barney_dead, CDeadBarney );
//=========================================================
// ********** DeadBarney SPAWN **********
//=========================================================
void CDeadBarney :: Spawn( )
{
PRECACHE_MODEL("models/barney.mdl");
SET_MODEL(ENT(pev), "models/barney.mdl");
pev->effects = 0;
pev->yaw_speed = 8;
pev->sequence = 0;
m_bloodColor = BLOOD_COLOR_RED;
pev->sequence = LookupSequence( m_szPoses[m_iPose] );
if (pev->sequence == -1)
{
ALERT ( at_console, "Dead barney with bad pose\n" );
}
// Corpses have less health
pev->health = 8;//gSkillData.barneyHealth;
MonsterInitDead();
}

View file

@ -1,94 +1,339 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* Copyright (c) 1999, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
#ifndef BASEMONSTER_H
#define BASEMONSTER_H
//
// generic Monster
//
class CBaseMonster : public CBaseToggle
{
private:
int m_afConditions;
public:
Activity m_Activity;// what the monster is doing (animation)
Activity m_IdealActivity;// monster should switch to this activity
int m_LastHitGroup; // the last body region that took damage
int m_bitsDamageType; // what types of damage has monster (player) taken
BYTE m_rgbTimeBasedDamage[CDMG_TIMEBASED];
MONSTERSTATE m_MonsterState;// monster's current state
MONSTERSTATE m_IdealMonsterState;// monster should change to this state
int m_afConditions;
int m_afMemory;
float m_flNextAttack; // cannot attack again until this time
EHANDLE m_hEnemy; // the entity that the monster is fighting.
EHANDLE m_hTargetEnt; // the entity that the monster is trying to reach
float m_flFieldOfView;// width of monster's field of view ( dot product )
int m_bloodColor; // color of blood particless
Vector m_HackedGunPos; // HACK until we can query end of gun
typedef enum
{
SCRIPT_PLAYING = 0, // Playing the sequence
SCRIPT_WAIT, // Waiting on everyone in the script to be ready
SCRIPT_CLEANUP, // Cancelling the script / cleaning up
SCRIPT_WALK_TO_MARK,
SCRIPT_RUN_TO_MARK,
} SCRIPTSTATE;
// these fields have been added in the process of reworking the state machine. (sjb)
EHANDLE m_hEnemy; // the entity that the monster is fighting.
EHANDLE m_hTargetEnt; // the entity that the monster is trying to reach
EHANDLE m_hOldEnemy[ MAX_OLD_ENEMIES ];
Vector m_vecOldEnemy[ MAX_OLD_ENEMIES ];
float m_flFieldOfView;// width of monster's field of view ( dot product )
float m_flWaitFinished;// if we're told to wait, this is the time that the wait will be over.
float m_flMoveWaitFinished;
Activity m_Activity;// what the monster is doing (animation)
Activity m_IdealActivity;// monster should switch to this activity
int m_LastHitGroup; // the last body region that took damage
MONSTERSTATE m_MonsterState;// monster's current state
MONSTERSTATE m_IdealMonsterState;// monster should change to this state
int m_iTaskStatus;
Schedule_t *m_pSchedule;
int m_iScheduleIndex;
WayPoint_t m_Route[ ROUTE_SIZE ]; // Positions of movement
int m_movementGoal; // Goal that defines route
int m_iRouteIndex; // index into m_Route[]
float m_moveWaitTime; // How long I should wait for something to move
Vector m_vecMoveGoal; // kept around for node graph moves, so we know our ultimate goal
Activity m_movementActivity; // When moving, set this activity
int m_iAudibleList; // first index of a linked list of sounds that the monster can hear.
int m_afSoundTypes;
Vector m_vecLastPosition;// monster sometimes wants to return to where it started after an operation.
int m_iHintNode; // this is the hint node that the monster is moving towards or performing active idle on.
int m_afMemory;
int m_iMaxHealth;// keeps track of monster's maximum health value (for re-healing, etc)
Vector m_vecEnemyLKP;// last known position of enemy. (enemy's origin)
int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences)
int m_afCapability;// tells us what a monster can/can't do.
float m_flNextAttack; // cannot attack again until this time
int m_bitsDamageType; // what types of damage has monster (player) taken
BYTE m_rgbTimeBasedDamage[CDMG_TIMEBASED];
int m_lastDamageAmount;// how much damage did monster (player) last take
// time based damage counters, decr. 1 per 2 seconds
int m_bloodColor; // color of blood particless
int m_failSchedule; // Schedule type to choose if current schedule fails
float m_flHungryTime;// set this is a future time to stop the monster from eating for a while.
float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in CheckEnemy
float m_flDistLook; // distance monster sees (Default 2048)
int m_iTriggerCondition;// for scripted AI, this is the condition that will cause the activation of the monster's TriggerTarget
string_t m_iszTriggerTarget;// name of target that should be fired.
Vector m_HackedGunPos; // HACK until we can query end of gun
// Scripted sequence Info
SCRIPTSTATE m_scriptState; // internal cinematic state
CCineMonster *m_pCine;
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void KeyValue( KeyValueData *pkvd );
void MakeIdealYaw( Vector vecTarget );
// monster use function
void EXPORT MonsterUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT CorpseUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
// overrideable Monster member functions
virtual int BloodColor( void ) { return m_bloodColor; }
virtual CBaseMonster *MyMonsterPointer( void ) { return this; }
virtual void Look ( int iDistance );// basic sight function for monsters
virtual void RunAI ( void );// core ai function!
void Listen ( void );
virtual BOOL IsAlive( void ) { return (pev->deadflag != DEAD_DEAD); }
virtual BOOL ShouldFadeOnDeath( void );
// Basic Monster AI functions
virtual float ChangeYaw ( int speed );
virtual BOOL HasHumanGibs( void );
virtual BOOL HasAlienGibs( void );
virtual void FadeMonster( void ); // Called instead of GibMonster() when gibs are disabled
virtual void GibMonster( void );
float VecToYaw( Vector vecDir );
float FlYawDiff ( void );
float DamageForce( float damage );
// stuff written for new state machine
virtual void MonsterThink( void );
void EXPORT CallMonsterThink( void ) { this->MonsterThink(); }
virtual int IRelationship ( CBaseEntity *pTarget );
virtual void MonsterInit ( void );
virtual void MonsterInitDead( void ); // Call after animation/pose is set up
virtual void BecomeDead( void );
void EXPORT CorpseFallThink( void );
void EXPORT MonsterInitThink ( void );
virtual void StartMonster ( void );
virtual CBaseEntity* BestVisibleEnemy ( void );// finds best visible enemy for attack
virtual BOOL FInViewCone ( CBaseEntity *pEntity );// see if pEntity is in monster's view cone
virtual BOOL FInViewCone ( Vector *pOrigin );// see if given location is in monster's view cone
virtual void HandleAnimEvent( MonsterEvent_t *pEvent );
virtual int CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, CBaseEntity *pTarget, float *pflDist );// check validity of a straight move through space
virtual void Move( float flInterval = 0.1 );
virtual void MoveExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flInterval );
virtual BOOL ShouldAdvanceRoute( float flWaypointDist );
virtual Activity GetStoppedActivity( void ) { return ACT_IDLE; }
virtual void Stop( void ) { m_IdealActivity = GetStoppedActivity(); }
// This will stop animation until you call ResetSequenceInfo() at some point in the future
inline void StopAnimation( void ) { pev->framerate = 0; }
// these functions will survey conditions and set appropriate conditions bits for attack types.
virtual BOOL CheckRangeAttack1( float flDot, float flDist );
virtual BOOL CheckRangeAttack2( float flDot, float flDist );
virtual BOOL CheckMeleeAttack1( float flDot, float flDist );
virtual BOOL CheckMeleeAttack2( float flDot, float flDist );
BOOL FHaveSchedule( void );
BOOL FScheduleValid ( void );
void ClearSchedule( void );
BOOL FScheduleDone ( void );
void ChangeSchedule ( Schedule_t *pNewSchedule );
void NextScheduledTask ( void );
Schedule_t *ScheduleInList( const char *pName, Schedule_t **pList, int listCount );
virtual Schedule_t *ScheduleFromName( const char *pName );
static Schedule_t *m_scheduleList[];
void MaintainSchedule ( void );
virtual void StartTask ( Task_t *pTask );
virtual void RunTask ( Task_t *pTask );
virtual Schedule_t *GetScheduleOfType( int Type );
virtual Schedule_t *GetSchedule( void );
virtual void ScheduleChange( void ) {}
// virtual int CanPlaySequence( void ) { return ((m_pCine == NULL) && (m_MonsterState == MONSTERSTATE_NONE || m_MonsterState == MONSTERSTATE_IDLE || m_IdealMonsterState == MONSTERSTATE_IDLE)); }
virtual int CanPlaySequence( BOOL fDisregardState, int interruptLevel );
virtual int CanPlaySentence( BOOL fDisregardState ) { return IsAlive(); }
virtual void PlaySentence( const char *pszSentence, float duration, float volume, float attenuation );
virtual void PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, BOOL bConcurrent, CBaseEntity *pListener );
virtual void SentenceStop( void );
Task_t *GetTask ( void );
virtual MONSTERSTATE GetIdealState ( void );
virtual void SetActivity ( Activity NewActivity );
void SetSequenceByName ( char *szSequence );
void SetState ( MONSTERSTATE State );
virtual void ReportAIState( void );
void CheckAttacks ( CBaseEntity *pTarget, float flDist );
virtual int CheckEnemy ( CBaseEntity *pEnemy );
void PushEnemy( CBaseEntity *pEnemy, Vector &vecLastKnownPos );
BOOL PopEnemy( void );
BOOL FGetNodeRoute ( Vector vecDest );
inline void TaskComplete( void ) { if ( !HasConditions(bits_COND_TASK_FAILED) ) m_iTaskStatus = TASKSTATUS_COMPLETE; }
void MovementComplete( void );
inline void TaskFail( void ) { SetConditions(bits_COND_TASK_FAILED); }
inline void TaskBegin( void ) { m_iTaskStatus = TASKSTATUS_RUNNING; }
int TaskIsRunning( void );
inline int TaskIsComplete( void ) { return (m_iTaskStatus == TASKSTATUS_COMPLETE); }
inline int MovementIsComplete( void ) { return (m_movementGoal == MOVEGOAL_NONE); }
int IScheduleFlags ( void );
BOOL FRefreshRoute( void );
BOOL FRouteClear ( void );
void RouteSimplify( CBaseEntity *pTargetEnt );
void AdvanceRoute ( float distance );
virtual BOOL FTriangulate ( const Vector &vecStart , const Vector &vecEnd, float flDist, CBaseEntity *pTargetEnt, Vector *pApex );
void MakeIdealYaw( Vector vecTarget );
virtual void SetYawSpeed ( void ) { return; };// allows different yaw_speeds for each activity
BOOL BuildRoute ( const Vector &vecGoal, int iMoveFlag, CBaseEntity *pTarget );
virtual BOOL BuildNearestRoute ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist );
int RouteClassify( int iMoveFlag );
void InsertWaypoint ( Vector vecLocation, int afMoveFlags );
BOOL FindLateralCover ( const Vector &vecThreat, const Vector &vecViewOffset );
virtual BOOL FindCover ( Vector vecThreat, Vector vecViewOffset, float flMinDist, float flMaxDist );
virtual BOOL FValidateCover ( const Vector &vecCoverLocation ) { return TRUE; };
virtual float CoverRadius( void ) { return 784; } // Default cover radius
virtual BOOL FCanCheckAttacks ( void );
virtual void CheckAmmo( void ) { return; };
virtual int IgnoreConditions ( void );
inline void SetConditions( int iConditions ) { m_afConditions |= iConditions; }
inline void ClearConditions( int iConditions ) { m_afConditions &= ~iConditions; }
inline BOOL HasConditions( int iConditions ) { if ( m_afConditions & iConditions ) return TRUE; return FALSE; }
inline BOOL HasAllConditions( int iConditions ) { if ( (m_afConditions & iConditions) == iConditions ) return TRUE; return FALSE; }
virtual BOOL FValidateHintType( short sHint );
int FindHintNode ( void );
virtual BOOL FCanActiveIdle ( void );
void SetTurnActivity ( void );
float FLSoundVolume ( CSound *pSound );
BOOL MoveToNode( Activity movementAct, float waitTime, const Vector &goal );
BOOL MoveToTarget( Activity movementAct, float waitTime );
BOOL MoveToLocation( Activity movementAct, float waitTime, const Vector &goal );
BOOL MoveToEnemy( Activity movementAct, float waitTime );
// Returns the time when the door will be open
float OpenDoorAndWait( entvars_t *pevDoor );
virtual int ISoundMask( void );
virtual CSound* PBestSound ( void );
virtual CSound* PBestScent ( void );
virtual float HearingSensitivity( void ) { return 1.0; };
BOOL FBecomeProne ( void );
virtual void BarnacleVictimBitten( entvars_t *pevBarnacle );
virtual void BarnacleVictimReleased( void );
void SetEyePosition ( void );
BOOL FShouldEat( void );// see if a monster is 'hungry'
void Eat ( float flFullDuration );// make the monster 'full' for a while.
CBaseEntity *CheckTraceHullAttack( float flDist, int iDamage, int iDmgType );
BOOL FacingIdeal( void );
BOOL FCheckAITrigger( void );// checks and, if necessary, fires the monster's trigger target.
BOOL NoFriendlyFire( void );
BOOL BBoxFlat( void );
// PrescheduleThink
virtual void PrescheduleThink( void ) { return; };
BOOL GetEnemy ( void );
void MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir );
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
// combat functions
float UpdateTarget ( entvars_t *pevTarget );
virtual Activity GetDeathActivity ( void );
Activity GetSmallFlinchActivity( void );
virtual void BecomeDead( void );
virtual void Killed( entvars_t *pevAttacker, int iGib );
virtual void GibMonster( void );
BOOL ShouldGibMonster( int iGib );
void CallGibMonster( void );
virtual BOOL ShouldFadeOnDeath( void );
BOOL FCheckAITrigger( void );// checks and, if necessary, fires the monster's trigger target.
virtual int IRelationship ( CBaseEntity *pTarget );
virtual BOOL HasHumanGibs( void );
virtual BOOL HasAlienGibs( void );
virtual void FadeMonster( void ); // Called instead of GibMonster() when gibs are disabled
Vector ShootAtEnemy( const Vector &shootOrigin );
virtual Vector BodyTarget( const Vector &posSrc ) { return Center( ) * 0.75 + EyePosition() * 0.25; }; // position to shoot at
virtual Vector GetGunPosition( void );
virtual int TakeHealth( float flHealth, int bitsDamageType );
virtual int TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType);
int DeadTakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
float DamageForce( float damage );
virtual void Killed( entvars_t *pevAttacker, int iGib );
virtual void PainSound ( void ) { return; };
void RadiusDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType );
void RadiusDamage(Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType );
virtual int IsMoving( void ) { return m_movementGoal != MOVEGOAL_NONE; }
inline void SetConditions( int iConditions ) { m_afConditions |= iConditions; }
inline void ClearConditions( int iConditions ) { m_afConditions &= ~iConditions; }
inline BOOL HasConditions( int iConditions ) { if ( m_afConditions & iConditions ) return TRUE; return FALSE; }
inline BOOL HasAllConditions( int iConditions ) { if ( (m_afConditions & iConditions) == iConditions ) return TRUE; return FALSE; }
void RouteClear( void );
void RouteNew( void );
virtual void DeathSound ( void ) { return; };
virtual void AlertSound ( void ) { return; };
virtual void IdleSound ( void ) { return; };
virtual void PainSound ( void ) { return; };
virtual void StopFollowing( BOOL clearSchedule ) {}
inline void Remember( int iMemory ) { m_afMemory |= iMemory; }
inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; }
inline BOOL HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; }
inline BOOL HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; }
// This will stop animation until you call ResetSequenceInfo() at some point in the future
inline void StopAnimation( void ) { pev->framerate = 0; }
virtual void ReportAIState( void );
virtual void MonsterInitDead( void ); // Call after animation/pose is set up
void EXPORT CorpseFallThink( void );
virtual void Look ( int iDistance );// basic sight function for monsters
virtual CBaseEntity* BestVisibleEnemy ( void );// finds best visible enemy for attack
CBaseEntity *CheckTraceHullAttack( float flDist, int iDamage, int iDmgType );
virtual BOOL FInViewCone ( CBaseEntity *pEntity );// see if pEntity is in monster's view cone
virtual BOOL FInViewCone ( Vector *pOrigin );// see if given location is in monster's view cone
void TraceAttack( entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
void MakeDamageBloodDecal ( int cCount, float flNoise, TraceResult *ptr, const Vector &vecDir );
virtual BOOL IsAlive( void ) { return (pev->deadflag != DEAD_DEAD); }
BOOL ExitScriptedSequence( );
BOOL CineCleanup( );
CBaseEntity* DropItem ( char *pszItemName, const Vector &vecPos, const Vector &vecAng );// drop an item.
};
#endif
#endif // BASEMONSTER_H

1251
dlls/bigmomma.cpp Normal file

File diff suppressed because it is too large Load diff

219
dlls/bloater.cpp Normal file
View file

@ -0,0 +1,219 @@
/***
*
* 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.
*
* This source code contains proprietary and confidential information of
* Valve LLC and its suppliers. Access to this code is restricted to
* persons who have executed a written SDK license with Valve. Any access,
* use or distribution of this code by or to any unlicensed person is illegal.
*
****/
//=========================================================
// Bloater
//=========================================================
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "schedule.h"
//=========================================================
// Monster's Anim Events Go Here
//=========================================================
#define BLOATER_AE_ATTACK_MELEE1 0x01
class CBloater : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void SetYawSpeed( void );
int Classify ( void );
void HandleAnimEvent( MonsterEvent_t *pEvent );
void PainSound( void );
void AlertSound( void );
void IdleSound( void );
void AttackSnd( void );
// No range attacks
BOOL CheckRangeAttack1 ( float flDot, float flDist ) { return FALSE; }
BOOL CheckRangeAttack2 ( float flDot, float flDist ) { return FALSE; }
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
};
LINK_ENTITY_TO_CLASS( monster_bloater, CBloater );
//=========================================================
// Classify - indicates this monster's place in the
// relationship table.
//=========================================================
int CBloater :: Classify ( void )
{
return CLASS_ALIEN_MONSTER;
}
//=========================================================
// SetYawSpeed - allows each sequence to have a different
// turn rate associated with it.
//=========================================================
void CBloater :: SetYawSpeed ( void )
{
int ys;
ys = 120;
#if 0
switch ( m_Activity )
{
}
#endif
pev->yaw_speed = ys;
}
int CBloater :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
PainSound();
return CBaseMonster::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
void CBloater :: PainSound( void )
{
#if 0
int pitch = 95 + RANDOM_LONG(0,9);
switch (RANDOM_LONG(0,5))
{
case 0:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_pain1.wav", 1.0, ATTN_NORM, 0, pitch);
break;
case 1:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_pain2.wav", 1.0, ATTN_NORM, 0, pitch);
break;
default:
break;
}
#endif
}
void CBloater :: AlertSound( void )
{
#if 0
int pitch = 95 + RANDOM_LONG(0,9);
switch (RANDOM_LONG(0,2))
{
case 0:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_alert10.wav", 1.0, ATTN_NORM, 0, pitch);
break;
case 1:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_alert20.wav", 1.0, ATTN_NORM, 0, pitch);
break;
case 2:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_alert30.wav", 1.0, ATTN_NORM, 0, pitch);
break;
}
#endif
}
void CBloater :: IdleSound( void )
{
#if 0
int pitch = 95 + RANDOM_LONG(0,9);
switch (RANDOM_LONG(0,2))
{
case 0:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_idle1.wav", 1.0, ATTN_NORM, 0, pitch);
break;
case 1:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_idle2.wav", 1.0, ATTN_NORM, 0, pitch);
break;
case 2:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_idle3.wav", 1.0, ATTN_NORM, 0, pitch);
break;
}
#endif
}
void CBloater :: AttackSnd( void )
{
#if 0
int pitch = 95 + RANDOM_LONG(0,9);
switch (RANDOM_LONG(0,1))
{
case 0:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_attack1.wav", 1.0, ATTN_NORM, 0, pitch);
break;
case 1:
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "zombie/zo_attack2.wav", 1.0, ATTN_NORM, 0, pitch);
break;
}
#endif
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CBloater :: HandleAnimEvent( MonsterEvent_t *pEvent )
{
switch( pEvent->event )
{
case BLOATER_AE_ATTACK_MELEE1:
{
// do stuff for this event.
AttackSnd();
}
break;
default:
CBaseMonster::HandleAnimEvent( pEvent );
break;
}
}
//=========================================================
// Spawn
//=========================================================
void CBloater :: Spawn()
{
Precache( );
SET_MODEL(ENT(pev), "models/floater.mdl");
UTIL_SetSize( pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
pev->solid = SOLID_SLIDEBOX;
pev->movetype = MOVETYPE_FLY;
pev->spawnflags |= FL_FLY;
m_bloodColor = BLOOD_COLOR_GREEN;
pev->health = 40;
pev->view_ofs = VEC_VIEW;// position of the eyes relative to monster's origin.
m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result )
m_MonsterState = MONSTERSTATE_NONE;
MonsterInit();
}
//=========================================================
// Precache - precaches all resources this monster needs
//=========================================================
void CBloater :: Precache()
{
PRECACHE_MODEL("models/floater.mdl");
}
//=========================================================
// AI Schedules Specific to this monster
//=========================================================

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

1275
dlls/bullsquid.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.
@ -21,12 +21,12 @@
#include "gamerules.h"
#include "game.h"
void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd );
extern "C" void PM_Move ( struct playermove_s *ppmove, int server );
extern "C" void PM_Init ( struct playermove_s *ppmove );
extern "C" char PM_FindTextureType( char *name );
void EntvarsKeyvalue( entvars_t *pev, KeyValueData *pkvd );
extern Vector VecBModelOrigin( entvars_t* pevBModel );
extern DLL_GLOBAL Vector g_vecAttackDir;
extern DLL_GLOBAL int g_iSkillLevel;
@ -73,7 +73,7 @@ static DLL_FUNCTIONS gFunctionTable =
SpectatorConnect, //pfnSpectatorConnect Called when spectator joins server
SpectatorDisconnect, //pfnSpectatorDisconnect Called when spectator leaves the server
SpectatorThink, //pfnSpectatorThink Called when spectator sends a command packet (usercmd_t)
Sys_Error, //pfnSys_Error Called when engine has encountered an error
PM_Move, //pfnPM_Move
@ -97,6 +97,9 @@ static DLL_FUNCTIONS gFunctionTable =
static void SetObjectCollisionBox( entvars_t *pev );
#ifndef _WIN32
extern "C" {
#endif
int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion )
{
if ( !pFunctionTable || interfaceVersion != INTERFACE_VERSION )
@ -121,6 +124,11 @@ int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion )
return TRUE;
}
#ifndef _WIN32
}
#endif
int DispatchSpawn( edict_t *pent )
{
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pent);
@ -631,17 +639,17 @@ void SetObjectCollisionBox( entvars_t *pev )
max = 0;
for (i=0 ; i<3 ; i++)
{
v = fabs( pev->mins[i]);
v = fabs( ((float *)pev->mins)[i]);
if (v > max)
max = v;
v = fabs( pev->maxs[i]);
v = fabs( ((float *)pev->maxs)[i]);
if (v > max)
max = v;
}
for (i=0 ; i<3 ; i++)
{
pev->absmin[i] = pev->origin[i] - max;
pev->absmax[i] = pev->origin[i] + max;
((float *)pev->absmin)[i] = ((float *)pev->origin)[i] - max;
((float *)pev->absmax)[i] = ((float *)pev->origin)[i] + max;
}
}
else

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.
@ -54,7 +54,7 @@ CBaseEntity
#ifdef _WIN32
#define EXPORT _declspec( dllexport )
#else
#define EXPORT
#define EXPORT /* */
#endif
extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
@ -240,6 +240,7 @@ public:
void EXPORT SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); }
int ShouldToggle( USE_TYPE useType, BOOL currentState );
void FireBullets( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL );
Vector FireBulletsPlayer( ULONG cShots, Vector vecSrc, Vector vecDirShooting, Vector vecSpread, float flDistance, int iBulletType, int iTracerFreq = 4, int iDamage = 0, entvars_t *pevAttacker = NULL, int shared_rand = 0 );
virtual CBaseEntity *Respawn( void ) { return NULL; }
@ -250,16 +251,6 @@ public:
int IsDormant( void );
BOOL IsLockedByMaster( void ) { return FALSE; }
#ifdef _DEBUG
static CBaseEntity *Instance( edict_t *pent )
{
if ( !pent )
pent = ENT(0);
CBaseEntity *pEnt = (CBaseEntity *)GET_PRIVATE(pent);
ASSERT(pEnt!=NULL);
return pEnt;
}
#else
static CBaseEntity *Instance( edict_t *pent )
{
if ( !pent )
@ -267,7 +258,6 @@ public:
CBaseEntity *pEnt = (CBaseEntity *)GET_PRIVATE(pent);
return pEnt;
}
#endif
static CBaseEntity *Instance( entvars_t *pev ) { return Instance( ENT( pev ) ); }
static CBaseEntity *Instance( int eoffset) { return Instance( ENT( eoffset) ); }
@ -292,10 +282,8 @@ public:
#ifdef _DEBUG
void FunctionCheck( void *pFunction, char *name )
{
#ifdef _WIN32
if (pFunction && !NAME_FOR_FUNCTION((unsigned long)(pFunction)) )
ALERT( at_error, "No EXPORT: %s:%s (%08lx)\n", STRING(pev->classname), name, (unsigned long)pFunction );
#endif // _WIN32
}
BASEPTR ThinkSet( BASEPTR func, char *name )
@ -349,6 +337,24 @@ public:
virtual BOOL FVisible ( CBaseEntity *pEntity );
virtual BOOL FVisible ( const Vector &vecOrigin );
//We use this variables to store each ammo count.
int ammo_9mm;
int ammo_357;
int ammo_bolts;
int ammo_buckshot;
int ammo_rockets;
int ammo_uranium;
int ammo_hornets;
int ammo_argrens;
//Special stuff for grenades and satchels.
float m_flStartThrow;
float m_flReleaseThrow;
int m_chargeReady;
int m_fInAttack;
enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
int m_fireState;
};

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.
@ -32,6 +32,7 @@
#include "client.h"
#include "soundent.h"
#include "gamerules.h"
#include "game.h"
#include "customentity.h"
#include "weapons.h"
#include "weaponinfo.h"
@ -47,7 +48,10 @@ extern void CopyToBodyQue(entvars_t* pev);
extern int giPrecacheGrunt;
extern int gmsgSayText;
extern int g_teamplay;
void LinkUserMessages( void );
/*
* used by kill command and disconnect command
* ROBIN: Moved here from player.cpp, to allow multiple player models
@ -189,7 +193,7 @@ void ClientPutInServer( edict_t *pEntity )
pPlayer->SetCustomDecalFrames(-1); // Assume none;
// Allocate a CBasePlayer for pev, and call spawn
pPlayer->Spawn();
pPlayer->Spawn() ;
// Reset interpolation during first frame
pPlayer->pev->effects |= EF_NOINTERP;
@ -309,6 +313,34 @@ void Host_Say( edict_t *pEntity, int teamonly )
// echo to server console
g_engfuncs.pfnServerPrint( text );
char * temp;
if ( teamonly )
temp = "say_team";
else
temp = "say";
// team match?
if ( g_teamplay )
{
UTIL_LogPrintf( "\"%s<%i><%u><%s>\" %s \"%s\"\n",
STRING( pEntity->v.netname ),
GETPLAYERUSERID( pEntity ),
GETPLAYERWONID( pEntity ),
g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pEntity ), "model" ),
temp,
p );
}
else
{
UTIL_LogPrintf( "\"%s<%i><%u><%i>\" %s \"%s\"\n",
STRING( pEntity->v.netname ),
GETPLAYERUSERID( pEntity ),
GETPLAYERWONID( pEntity ),
GETPLAYERUSERID( pEntity ),
temp,
p );
}
}
@ -384,7 +416,15 @@ void ClientCommand( edict_t *pEntity )
else
{
// tell the user they entered an unknown command
ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", pcmd ) );
char command[128];
// check the length of the command (prevents crash)
// max total length is 192 ...and we're adding a string below ("Unknown command: %s\n")
strncpy( command, pcmd, 127 );
command[127] = '\0';
// tell the user they entered an unknown command
ClientPrint( &pEntity->v, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", command ) );
}
}
@ -407,6 +447,22 @@ void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer )
// msg everyone if someone changes their name, and it isn't the first time (changing no name to current name)
if ( pEntity->v.netname && STRING(pEntity->v.netname)[0] != 0 && !FStrEq( STRING(pEntity->v.netname), g_engfuncs.pfnInfoKeyValue( infobuffer, "name" )) )
{
char sName[256];
char *pName = g_engfuncs.pfnInfoKeyValue( infobuffer, "name" );
strncpy( sName, pName, sizeof(sName) - 1 );
sName[ sizeof(sName) - 1 ] = '\0';
// First parse the name and remove any %'s
for ( char *pApersand = sName; pApersand != NULL && *pApersand != 0; pApersand++ )
{
// Replace it with a space
if ( *pApersand == '%' )
*pApersand = ' ';
}
// Set the name
g_engfuncs.pfnSetClientKeyValue( ENTINDEX(pEntity), infobuffer, "name", sName );
char text[256];
sprintf( text, "* %s changed name to %s\n", STRING(pEntity->v.netname), g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) );
MESSAGE_BEGIN( MSG_ALL, gmsgSayText, NULL );
@ -414,7 +470,25 @@ void ClientUserInfoChanged( edict_t *pEntity, char *infobuffer )
WRITE_STRING( text );
MESSAGE_END();
UTIL_LogPrintf( "\"%s<%i>\" changed name to \"%s<%i>\"\n", STRING( pEntity->v.netname ), GETPLAYERUSERID( pEntity ), g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ), GETPLAYERUSERID( pEntity ) );
// team match?
if ( g_teamplay )
{
UTIL_LogPrintf( "\"%s<%i><%u><%s>\" changed name to \"%s\"\n",
STRING( pEntity->v.netname ),
GETPLAYERUSERID( pEntity ),
GETPLAYERWONID( pEntity ),
g_engfuncs.pfnInfoKeyValue( infobuffer, "model" ),
g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) );
}
else
{
UTIL_LogPrintf( "\"%s<%i><%u><%i>\" changed name to \"%s\"\n",
STRING( pEntity->v.netname ),
GETPLAYERUSERID( pEntity ),
GETPLAYERWONID( pEntity ),
GETPLAYERUSERID( pEntity ),
g_engfuncs.pfnInfoKeyValue( infobuffer, "name" ) );
}
}
g_pGameRules->ClientUserInfoChanged( GetClassPtr((CBasePlayer *)&pEntity->v), infobuffer );
@ -435,16 +509,6 @@ void ServerDeactivate( void )
// Peform any shutdown operations here...
//
#ifdef PERSISTENCE_SAMPLE
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer *pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i );
if(pPlayer && pPlayer->IsPlayer())
{
pPlayer->m_PersistenceInfo.SendInfo();
}
}
#endif
}
void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
@ -542,8 +606,7 @@ void StartFrame( void )
if ( g_fGameOver )
return;
gpGlobals->teamplay = CVAR_GET_FLOAT("teamplay");
g_iSkillLevel = CVAR_GET_FLOAT("skill");
gpGlobals->teamplay = teamplay.value;
g_ulFrameCount++;
}
@ -665,7 +728,7 @@ void ClientPrecache( void )
/*
===============
const char *GetGameDescription()
GetGameDescription
Returns the descriptive name of this .dll. E.g., Half-Life, or Team Fortress 2
===============
@ -780,7 +843,6 @@ void SpectatorThink( edict_t *pEntity )
pPlayer->SpectatorThink( );
}
////////////////////////////////////////////////////////
// PAS and PVS routines for client messaging
//
@ -810,6 +872,13 @@ void SetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char **pv
pView = pViewEntity;
}
if ( pClient->v.flags & FL_PROXY )
{
*pvs = NULL; // the spectator proxy sees
*pas = NULL; // and hears everything
return;
}
org = pView->v.origin + pView->v.view_ofs;
if ( pView->v.flags & FL_DUCKING )
{
@ -946,6 +1015,7 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
state->scale = ent->v.scale;
state->solid = ent->v.solid;
state->colormap = ent->v.colormap;
state->movetype = ent->v.movetype;
state->sequence = ent->v.sequence;
state->framerate = ent->v.framerate;
@ -964,9 +1034,9 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
state->rendermode = ent->v.rendermode;
state->renderamt = ent->v.renderamt;
state->renderfx = ent->v.renderfx;
state->rendercolor.r = ent->v.rendercolor[0];
state->rendercolor.g = ent->v.rendercolor[1];
state->rendercolor.b = ent->v.rendercolor[2];
state->rendercolor.r = ent->v.rendercolor.x;
state->rendercolor.g = ent->v.rendercolor.y;
state->rendercolor.b = ent->v.rendercolor.z;
state->aiment = 0;
if ( ent->v.aiment )
@ -1005,7 +1075,7 @@ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *h
state->gravity = ent->v.gravity;
// state->team = ent->v.team;
// state->playerclass = ent->v.playerclass;
//
state->usehull = ( ent->v.flags & FL_DUCKING ) ? 1 : 0;
state->health = ent->v.health;
}
@ -1033,9 +1103,9 @@ void CreateBaseline( int player, int eindex, struct entity_state_s *baseline, st
// render information
baseline->rendermode = (byte)entity->v.rendermode;
baseline->renderamt = (byte)entity->v.renderamt;
baseline->rendercolor.r = (byte)entity->v.rendercolor[0];
baseline->rendercolor.g = (byte)entity->v.rendercolor[1];
baseline->rendercolor.b = (byte)entity->v.rendercolor[2];
baseline->rendercolor.r = (byte)entity->v.rendercolor.x;
baseline->rendercolor.g = (byte)entity->v.rendercolor.y;
baseline->rendercolor.b = (byte)entity->v.rendercolor.z;
baseline->renderfx = (byte)entity->v.renderfx;
if ( player )
@ -1114,7 +1184,6 @@ FIXME: Move to script
void Entity_Encode( struct delta_s *pFields, const unsigned char *from, const unsigned char *to )
{
entity_state_t *f, *t;
int localplayer = 0;
static int initialized = 0;
@ -1361,7 +1430,7 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
if ( II.iId >= 0 && II.iId < 32 )
{
item = &info[ II.iId ];
item->m_iId = II.iId;
item->m_iClip = gun->m_iClip;
@ -1369,6 +1438,16 @@ int GetWeaponData( struct edict_s *player, struct weapon_data_s *info )
item->m_flNextPrimaryAttack = max( gun->m_flNextPrimaryAttack, -0.001 );
item->m_flNextSecondaryAttack = max( gun->m_flNextSecondaryAttack, -0.001 );
item->m_fInReload = gun->m_fInReload;
item->m_fInSpecialReload = gun->m_fInSpecialReload;
item->fuser1 = max( gun->pev->fuser1, -0.001 );
item->fuser2 = gun->m_flStartThrow;
item->fuser3 = gun->m_flReleaseThrow;
item->iuser1 = gun->m_chargeReady;
item->iuser2 = gun->m_fInAttack;
item->iuser3 = gun->m_fireState;
// item->m_flPumpTime = max( gun->m_flPumpTime, -0.001 );
}
}
pPlayerItem = pPlayerItem->m_pNext;
@ -1395,6 +1474,7 @@ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clien
cd->health = ent->v.health;
cd->viewmodel = MODEL_INDEX( STRING( ent->v.viewmodel ) );
cd->waterlevel = ent->v.waterlevel;
cd->watertype = ent->v.watertype;
cd->weapons = ent->v.weapons;
@ -1428,6 +1508,17 @@ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clien
if ( pl )
{
cd->m_flNextAttack = pl->m_flNextAttack;
cd->fuser2 = pl->m_flNextAmmoBurn;
cd->fuser3 = pl->m_flAmmoStartCharge;
cd->vuser1.x = pl->ammo_9mm;
cd->vuser1.y = pl->ammo_357;
cd->vuser1.z = pl->ammo_argrens;
cd->ammo_nails = pl->ammo_bolts;
cd->ammo_shells = pl->ammo_buckshot;
cd->ammo_rockets = pl->ammo_rockets;
cd->ammo_cells = pl->ammo_uranium;
cd->vuser2.x = pl->ammo_hornets;
if ( pl->m_pActiveItem )
{
@ -1440,6 +1531,17 @@ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clien
gun->GetItemInfo( &II );
cd->m_iId = II.iId;
cd->vuser3.z = gun->m_iSecondaryAmmoType;
cd->vuser4.x = gun->m_iPrimaryAmmoType;
cd->vuser4.y = pl->m_rgAmmo[gun->m_iPrimaryAmmoType];
cd->vuser4.z = pl->m_rgAmmo[gun->m_iSecondaryAmmoType];
if ( pl->m_pActiveItem->m_iId == WEAPON_RPG )
{
cd->vuser2.y = ( ( CRpg * )pl->m_pActiveItem)->m_fSpotActive;
cd->vuser2.z = ( ( CRpg * )pl->m_pActiveItem)->m_cActiveRockets;
}
}
}
}
@ -1604,4 +1706,3 @@ int AllowLagCompensation( void )
{
return 0;
}

View file

@ -1,6 +1,6 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
* 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.

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