1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-23 01:59:43 +08:00

Added original SDK code for Alien Swarm.

This commit is contained in:
Scott Ehlert 2010-07-22 01:46:14 -05:00
commit c0a96ff1e8
3740 changed files with 1243478 additions and 0 deletions

116
common/ConfigManager.h Normal file
View File

@ -0,0 +1,116 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef CONFIGMANAGER_H
#define CONFIGMANAGER_H
#ifdef _WIN32
#pragma once
#endif
#include "KeyValues.h"
#include "utlvector.h"
#include "filesystem_init.h"
// See filesystem_init for the vconfig registry values.
#define TOKEN_GAMES "Games"
#define TOKEN_GAME_DIRECTORY "GameDir"
#define TOKEN_TOOLS "Tools"
// STEAM CLOUD FLAGS
#define STEAMREMOTESTORAGE_CLOUD_CONFIG (1<<0)
#define STEAMREMOTESTORAGE_CLOUD_SPRAY (1<<1)
#define STEAMREMOTESTORAGE_CLOUD_ALL 0x7fff // all bits set, so any new items added will be on by default
struct defaultConfigInfo_t
{
char gameName[MAX_PATH];
char gameDir[MAX_PATH];
char FGD[MAX_PATH];
char steamPath[MAX_PATH];
char defaultPointEntity[MAX_PATH];
char exeName[MAX_PATH];
int steamAppID;
};
enum eSDKEpochs
{
HL2 = 1,
EP1 = 2,
EP2 = 3,
SWARM = 4,
};
extern defaultConfigInfo_t *gDefaultConfigs[];
class CGameConfigManager
{
public:
enum loadStatus_t
{
LOADSTATUS_NONE = 0, // Configs were loaded with no error
LOADSTATUS_CONVERTED, // GameConfig.txt did not exist and was created by converting GameCfg.INI
LOADSTATUS_CREATED, // GameCfg.INI was not found, the system created the default configuration based on found GameInfo.txt resources
LOADSTATUS_ERROR, // File was not loaded and was unable to perform the above fail-safe procedures
};
CGameConfigManager( void );
CGameConfigManager( const char *fileName );
~CGameConfigManager( void );
bool LoadConfigs( const char *baseDir = NULL );
bool SaveConfigs( const char *baseDir = NULL );
bool ResetConfigs( const char *baseDir = NULL );
int GetNumConfigs( void );
KeyValues *GetGameBlock( void );
KeyValues *GetGameSubBlock( const char *keyName );
bool GetDefaultGameBlock( KeyValues *pIn );
bool IsLoaded( void ) const { return m_pData != NULL; }
bool WasConvertedOnLoad( void ) const { return m_LoadStatus == LOADSTATUS_CONVERTED; }
bool WasCreatedOnLoad( void ) const { return m_LoadStatus == LOADSTATUS_CREATED; }
bool AddDefaultConfig( const defaultConfigInfo_t &info, KeyValues *out, const char *rootDirectory, const char *gameExeDir );
void SetBaseDirectory( const char *pDirectory );
void GetRootGameDirectory( char *out, size_t outLen, const char *rootDir, const char *steamDir );
const char *GetRootDirectory( void );
void SetSDKEpoch( eSDKEpochs epoch ) { m_eSDKEpoch = epoch; };
private:
void GetRootContentDirectory( char *out, size_t outLen, const char *rootDir );
const char *GetBaseDirectory( void );
const char *GetIniFilePath( void );
bool LoadConfigsInternal( const char *baseDir, bool bRecursiveCall );
void UpdateConfigsInternal( void );
void VersionConfig( void );
bool IsConfigCurrent( void );
bool ConvertGameConfigsINI( void );
bool CreateAllDefaultConfigs( void );
bool IsAppSubscribed( int nAppID );
loadStatus_t m_LoadStatus; // Holds various state about what occured while loading
KeyValues *m_pData; // Data as read from configuration file
char m_szBaseDirectory[MAX_PATH]; // Default directory
eSDKEpochs m_eSDKEpoch; // Holds the "working version" of the SDK for times when we need to create an older set of game configurations.
// This is required now that the SDK is deploying the tools for both the latest and previous versions of the engine.
};
#endif // CONFIGMANAGER_H

View File

@ -0,0 +1,41 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef IGAMECONSOLE_H
#define IGAMECONSOLE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
//-----------------------------------------------------------------------------
// Purpose: interface to game/dev console
//-----------------------------------------------------------------------------
abstract_class IGameConsole : public IBaseInterface
{
public:
// activates the console, makes it visible and brings it to the foreground
virtual void Activate() = 0;
virtual void Initialize() = 0;
// hides the console
virtual void Hide() = 0;
// clears the console
virtual void Clear() = 0;
// return true if the console has focus
virtual bool IsConsoleVisible() = 0;
virtual void SetParent( int parent ) = 0;
};
#define GAMECONSOLE_INTERFACE_VERSION "GameConsole004"
#endif // IGAMECONSOLE_H

103
common/GameUI/IGameUI.h Normal file
View File

@ -0,0 +1,103 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IGAMEUI_H
#define IGAMEUI_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include "vgui/ipanel.h"
#if !defined( _X360 )
#include "xbox/xboxstubs.h"
#endif
class CCommand;
// reasons why the user can't connect to a game server
enum ESteamLoginFailure
{
STEAMLOGINFAILURE_NONE,
STEAMLOGINFAILURE_BADTICKET,
STEAMLOGINFAILURE_NOSTEAMLOGIN,
STEAMLOGINFAILURE_VACBANNED,
STEAMLOGINFAILURE_LOGGED_IN_ELSEWHERE
};
enum ESystemNotify
{
SYSTEMNOTIFY_STORAGEDEVICES_CHANGED,
SYSTEMNOTIFY_USER_SIGNEDIN,
SYSTEMNOTIFY_USER_SIGNEDOUT,
SYSTEMNOTIFY_XLIVE_LOGON_ESTABLISHED, // we are logged into live service
SYSTEMNOTIFY_XLIVE_LOGON_CLOSED, // no longer logged into live - either from natural (signed out) or unnatural (e.g. severed net connection) causes
SYSTEMNOTIFY_XUIOPENING,
SYSTEMNOTIFY_XUICLOSED,
SYSTEMNOTIFY_INVITE_SHUTDOWN, // Cross-game invite is causing us to shutdown
SYSTEMNOTIFY_MUTECHANGED, // Player changed mute settings
SYSTEMNOTIFY_INPUTDEVICESCHANGED, // Input device has changed (used for controller disconnection)
SYSTEMNOTIFY_PROFILE_UNAVAILABLE, // Profile failed to read or write
};
//-----------------------------------------------------------------------------
// Purpose: contains all the functions that the GameUI dll exports
//-----------------------------------------------------------------------------
abstract_class IGameUI
{
public:
// initialization/shutdown
virtual void Initialize( CreateInterfaceFn appFactory ) = 0;
virtual void PostInit() = 0;
// connect to other interfaces at the same level (gameui.dll/server.dll/client.dll)
virtual void Connect( CreateInterfaceFn gameFactory ) = 0;
virtual void Start() = 0;
virtual void Shutdown() = 0;
virtual void RunFrame() = 0;
// notifications
virtual void OnGameUIActivated() = 0;
virtual void OnGameUIHidden() = 0;
// OLD: Use OnConnectToServer2
virtual void OLD_OnConnectToServer(const char *game, int IP, int port) = 0;
virtual void OnDisconnectFromServer_OLD( uint8 eSteamLoginFailure, const char *username ) = 0;
virtual void OnLevelLoadingStarted( const char *levelName, bool bShowProgressDialog ) = 0;
virtual void OnLevelLoadingFinished(bool bError, const char *failureReason, const char *extendedReason) = 0;
// level loading progress, returns true if the screen needs updating
virtual bool UpdateProgressBar(float progress, const char *statusText) = 0;
// Shows progress desc, returns previous setting... (used with custom progress bars )
virtual bool SetShowProgressText( bool show ) = 0;
// !!!!!!!!!members added after "GameUI011" initial release!!!!!!!!!!!!!!!!!!!
// Allows the level loading progress to show map-specific info
virtual void SetProgressLevelName( const char *levelName ) = 0;
// inserts specified panel as background for level load dialog
virtual void SetLoadingBackgroundDialog( vgui::VPANEL panel ) = 0;
virtual void OnConnectToServer2(const char *game, int IP, int connectionPort, int queryPort) = 0;
virtual void SetProgressOnStart() = 0;
virtual void OnDisconnectFromServer( uint8 eSteamLoginFailure ) = 0;
virtual void NeedConnectionProblemWaitScreen() = 0;
virtual void ShowPasswordUI( char const *pchCurrentPW ) = 0;
#if defined( _X360 ) && defined( _DEMO )
virtual void OnDemoTimeout( void ) = 0;
#endif
};
#define GAMEUI_INTERFACE_VERSION "GameUI011"
#endif // IGAMEUI_H

81
common/IRunGameEngine.h Normal file
View File

@ -0,0 +1,81 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IRUNGAMEENGINE_H
#define IRUNGAMEENGINE_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#ifdef GetUserName
#undef GetUserName
#endif
//-----------------------------------------------------------------------------
// Purpose: Interface to running the game engine
//-----------------------------------------------------------------------------
abstract_class IRunGameEngine : public IBaseInterface
{
public:
// Returns true if the engine is running, false otherwise.
virtual bool IsRunning() = 0;
// Adds text to the engine command buffer. Only works if IsRunning()
// returns true on success, false on failure
virtual bool AddTextCommand(const char *text) = 0;
// runs the engine with the specified command line parameters. Only works if !IsRunning()
// returns true on success, false on failure
virtual bool RunEngine(const char *gameDir, const char *commandLineParams) = 0;
// returns true if the player is currently connected to a game server
virtual bool IsInGame() = 0;
// gets information about the server the engine is currently connected to
// returns true on success, false on failure
virtual bool GetGameInfo(char *infoBuffer, int bufferSize) = 0;
// tells the engine our userID
virtual void SetTrackerUserID(int trackerID, const char *trackerName) = 0;
// this next section could probably moved to another interface
// iterates users
// returns the number of user
virtual int GetPlayerCount() = 0;
// returns a playerID for a player
// playerIndex is in the range [0, GetPlayerCount)
virtual unsigned int GetPlayerFriendsID(int playerIndex) = 0;
// gets the in-game name of another user, returns NULL if that user doesn't exists
virtual const char *GetPlayerName(int friendsID) = 0;
// gets the friends name of a player
virtual const char *GetPlayerFriendsName(int friendsID) = 0;
// returns the engine build number and mod version string for server versioning
virtual unsigned int GetEngineBuildNumber() = 0;
virtual const char *GetProductVersionString() = 0;
// new interface to RunEngine (done so we don't have to roll the interface version)
virtual bool RunEngine2(const char *gameDir, const char *commandLineParams, bool isSourceGame) = 0;
enum ERunResult
{
k_ERunResultOkay = 0,
k_ERunResultModNotInstalled = 1,
k_ERunResultAppNotFound = 2,
k_ERunResultNotInitialized = 3,
};
virtual ERunResult RunEngine( int iAppID, const char *gameDir, const char *commandLineParams ) = 0;
};
#define RUNGAMEENGINE_INTERFACE_VERSION "RunGameEngine005"
#endif // IRUNGAMEENGINE_H

64
common/IVGuiModule.h Normal file
View File

@ -0,0 +1,64 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IVGUIMODULE_H
#define IVGUIMODULE_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
#include <vgui/VGUI.h>
//-----------------------------------------------------------------------------
// Purpose: Standard interface to loading vgui modules
//-----------------------------------------------------------------------------
abstract_class IVGuiModule : public IBaseInterface
{
public:
// called first to setup the module with the vgui
// returns true on success, false on failure
virtual bool Initialize(CreateInterfaceFn *vguiFactories, int factoryCount) = 0;
// called after all the modules have been initialized
// modules should use this time to link to all the other module interfaces
virtual bool PostInitialize(CreateInterfaceFn *modules, int factoryCount) = 0;
// called when the module is selected from the menu or otherwise activated
virtual bool Activate() = 0;
// returns true if the module is successfully initialized and available
virtual bool IsValid() = 0;
// requests that the UI is temporarily disabled and all data files saved
virtual void Deactivate() = 0;
// restart from a Deactivate()
virtual void Reactivate() = 0;
// called when the module is about to be shutdown
virtual void Shutdown() = 0;
// returns a handle to the main module panel
virtual vgui::VPANEL GetPanel() = 0;
// sets the parent of the main module panel
virtual void SetParent(vgui::VPANEL parent) = 0;
// messages sent through through the panel returned by GetPanel():
//
// "ConnectedToGame" "ip" "port" "gamedir"
// "DisconnectedFromGame"
// "ActiveGameName" "name"
// "LoadingStarted" "type" "name"
// "LoadingFinished" "type" "name"
};
#define VGUIMODULE_INTERFACE_VERSION "VGuiModule002"
#endif // IVGUIMODULE_H

View File

@ -0,0 +1,33 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef IVGUIMODULELOADER_H
#define IVGUIMODULELOADER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
//-----------------------------------------------------------------------------
// Purpose: interface to accessing all loaded modules
//-----------------------------------------------------------------------------
abstract_class IVGuiModuleLoader : public IBaseInterface
{
public:
virtual int GetModuleCount() = 0;
virtual const char *GetModuleLabel(int moduleIndex) = 0;
virtual CreateInterfaceFn GetModuleFactory(int moduleIndex) = 0;
virtual bool ActivateModule(int moduleIndex) = 0;
virtual bool ActivateModule(const char *moduleName) = 0;
virtual void SetPlatformToRestart() = 0;
};
#define VGUIMODULELOADER_INTERFACE_VERSION "VGuiModuleLoader003"
#endif // IVGUIMODULELOADER_H

View File

@ -0,0 +1,45 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ISERVERBROWSER_H
#define ISERVERBROWSER_H
#ifdef _WIN32
#pragma once
#endif
#include "interface.h"
//-----------------------------------------------------------------------------
// Purpose: Interface to server browser module
//-----------------------------------------------------------------------------
abstract_class IServerBrowser
{
public:
// activates the server browser window, brings it to the foreground
virtual bool Activate() = 0;
// joins a game directly
virtual bool JoinGame( uint32 unGameIP, uint16 usGamePort ) = 0;
// joins a specified game - game info dialog will only be opened if the server is fully or passworded
virtual bool JoinGame( uint64 ulSteamIDFriend ) = 0;
// opens a game info dialog to watch the specified server; associated with the friend 'userName'
virtual bool OpenGameInfoDialog( uint64 ulSteamIDFriend ) = 0;
// forces the game info dialog closed
virtual void CloseGameInfoDialog( uint64 ulSteamIDFriend ) = 0;
// closes all the game info dialogs
virtual void CloseAllGameInfoDialogs() = 0;
};
#define SERVERBROWSER_INTERFACE_VERSION "ServerBrowser003"
#endif // ISERVERBROWSER_H

View File

@ -0,0 +1,48 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "../../engine/iblackbox.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern IBlackBox *blackboxrecorder;
void BlackBox_Record( const char *type, const char *pFormat, ... )
{
static ConVarRef blackbox( "blackbox" );
if ( IsX360() )
return;
if ( !blackbox.IsValid() || !blackbox.GetBool() )
return;
int type_num;
for ( type_num = 0; type_num < blackboxrecorder->GetTypeCount(); type_num++ )
{
if ( !V_strcasecmp( blackboxrecorder->GetTypeName( type_num ), type ) )
break;
}
if ( type_num >= blackboxrecorder->GetTypeCount() )
{
Msg( "Invalid blackbox type: %s\n", type );
return;
}
char szMessage[1024];
va_list marker;
va_start( marker, pFormat);
Q_vsnprintf( szMessage, sizeof( szMessage ), pFormat, marker);
va_end( marker );
//Msg( "Record: %s: %s\n", type, szMessage );
blackboxrecorder->Record( type_num, szMessage );
}

11
common/blackbox_helper.h Normal file
View File

@ -0,0 +1,11 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BLACKBOX_HELPER_H
#define BLACKBOX_HELPER_H 1
void BlackBox_Record(const char * type, const char *fmt, ...);
#endif

View File

@ -0,0 +1,103 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Swap a compiled caption file.
//
// $NoKeywords: $
//=============================================================================//
#include "utlbuffer.h"
#include "byteswap.h"
#include "filesystem.h"
#include "tier2/fileutils.h"
#include "captioncompiler.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_BYTESWAP_DATADESC( CompiledCaptionHeader_t )
DEFINE_FIELD( magic, FIELD_INTEGER ),
DEFINE_FIELD( version, FIELD_INTEGER ),
DEFINE_FIELD( numblocks, FIELD_INTEGER ),
DEFINE_FIELD( blocksize, FIELD_INTEGER ),
DEFINE_FIELD( directorysize, FIELD_INTEGER ),
DEFINE_FIELD( dataoffset, FIELD_INTEGER ),
END_BYTESWAP_DATADESC()
BEGIN_BYTESWAP_DATADESC( CaptionLookup_t )
DEFINE_FIELD( hash, FIELD_INTEGER ),
DEFINE_FIELD( blockNum, FIELD_INTEGER ),
DEFINE_FIELD( offset, FIELD_SHORT ),
DEFINE_FIELD( length, FIELD_SHORT ),
END_BYTESWAP_DATADESC()
//-----------------------------------------------------------------------------
// Swap a compiled closecaption file
//-----------------------------------------------------------------------------
bool SwapClosecaptionFile( void *pData )
{
CByteswap swap;
swap.ActivateByteSwapping( true );
CompiledCaptionHeader_t *pHdr = (CompiledCaptionHeader_t*)pData;
if ( IsX360() )
{
// pre-swap file header
swap.SwapFieldsToTargetEndian( pHdr );
}
if ( pHdr->magic != COMPILED_CAPTION_FILEID || pHdr->version != COMPILED_CAPTION_VERSION )
{
// bad data
return false;
}
// lookup headers
pData = (byte*)pData + sizeof(CompiledCaptionHeader_t);
swap.SwapFieldsToTargetEndian( (CaptionLookup_t*)pData, pHdr->directorysize );
// unicode data
pData = (byte*)pHdr + pHdr->dataoffset;
swap.SwapBufferToTargetEndian( (wchar_t*)pData, (wchar_t*)pData, pHdr->numblocks * pHdr->blocksize / sizeof(wchar_t) );
if ( IsPC() )
{
// post-swap file header
swap.SwapFieldsToTargetEndian( pHdr );
}
return true;
}
#if defined( CLIENT_DLL ) || defined( GAME_DLL )
//-----------------------------------------------------------------------------
// Callback for UpdateOrCreate - generates .360 file
//-----------------------------------------------------------------------------
static bool CaptionCreateCallback( const char *pSourceName, const char *pTargetName, const char *pPathID, void *pExtraData )
{
// Generate the file
CUtlBuffer buf;
bool bOk = g_pFullFileSystem->ReadFile( pSourceName, pPathID, buf );
if ( bOk )
{
bOk = SwapClosecaptionFile( buf.Base() );
if ( bOk )
{
bOk = g_pFullFileSystem->WriteFile( pTargetName, pPathID, buf );
}
else
{
Warning( "Failed to create %s\n", pTargetName );
}
}
return bOk;
}
//-----------------------------------------------------------------------------
// Calls utility function UpdateOrCreate
//-----------------------------------------------------------------------------
int UpdateOrCreateCaptionFile( const char *pSourceName, char *pTargetName, int maxLen, bool bForce )
{
return ::UpdateOrCreate( pSourceName, pTargetName, maxLen, "GAME", CaptionCreateCallback, bForce );
}
#endif

View File

@ -0,0 +1,16 @@
//======= Copyright © 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose: Add a specially formatted string to each debug DLL of the form
// "%DLLNAME%.dll is built debug!". We can search for this string via
// a Perforce trigger to ensure that debug LIBs are not checked in.
//
//=============================================================================//
#if defined(DEBUG) || defined(_DEBUG)
#include "tier0/platform.h"
#define _DEBUGONLYSTRING(x) #x
#define DEBUGONLYSTRING(x) _DEBUGONLYSTRING(x)
DLL_GLOBAL_EXPORT char const *pDebugString = DEBUGONLYSTRING(DLLNAME) ".dll is built debug!";
#endif

View File

@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef IFILESYSTEMOPENDIALOG_H
#define IFILESYSTEMOPENDIALOG_H
#ifdef _WIN32
#pragma once
#endif
#define FILESYSTEMOPENDIALOG_VERSION "FileSystemOpenDlg003"
class IFileSystem;
abstract_class IFileSystemOpenDialog
{
public:
// You must call this first to set the hwnd.
virtual void Init( CreateInterfaceFn factory, void *parentHwnd ) = 0;
// Call this to free the dialog.
virtual void Release() = 0;
// Use these to configure the dialog.
virtual void AddFileMask( const char *pMask ) = 0;
virtual void SetInitialDir( const char *pDir, const char *pPathID = NULL ) = 0;
virtual void SetFilterMdlAndJpgFiles( bool bFilter ) = 0;
virtual void GetFilename( char *pOut, int outLen ) const = 0; // Get the filename they chose.
// Call this to make the dialog itself. Returns true if they clicked OK and false
// if they canceled it.
virtual bool DoModal() = 0;
// This uses the standard windows file open dialog.
virtual bool DoModal_WindowsDialog() = 0;
// Mark the dialog as allowing us to multi-select
virtual void AllowMultiSelect( bool bAllow ) = 0;
// Request the length of the buffer sufficient enough to hold the entire filename result
virtual int GetFilenameBufferSize() const = 0;
};
#endif // IFILESYSTEMOPENDIALOG_H

116
common/language.cpp Normal file
View File

@ -0,0 +1,116 @@
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
//
// Purpose: languages definition
//
//=============================================================================
#include "language.h"
#include "tier0/dbg.h"
#include "tier1/strtools.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
struct Language_t
{
char *m_pchName;
char *m_pchShortName;
char *m_pchVGUILocalizationName;
ELanguage m_ELanguage;
};
static Language_t s_LanguageNames[] =
{
{ "None", "none", "None", k_Lang_None },
{ "English", "english", "#GameUI_Language_English", k_Lang_English },
{ "German", "german", "#GameUI_Language_German", k_Lang_German } ,
{ "French", "french", "#GameUI_Language_French", k_Lang_French } ,
{ "Italian", "italian", "#GameUI_Language_Italian", k_Lang_Italian } ,
{ "Korean", "koreana", "#GameUI_Language_Korean", k_Lang_Korean } ,
{ "Spanish", "spanish", "#GameUI_Language_Spanish", k_Lang_Spanish },
{ "Simplified_Chinese", "schinese", "#GameUI_Language_Simplified_Chinese", k_Lang_Simplified_Chinese } ,
{ "Traditional_Chinese", "tchinese", "#GameUI_Language_Traditional_Chinese", k_Lang_Traditional_Chinese } ,
{ "Russian", "russian", "#GameUI_Language_Russian", k_Lang_Russian } ,
{ "Thai", "thai", "#GameUI_Language_Thai", k_Lang_Thai } ,
{ "Japanese", "japanese", "#GameUI_Language_Japanese", k_Lang_Japanese } ,
{ "Portuguese", "portuguese", "#GameUI_Language_Portuguese", k_Lang_Portuguese } ,
{ "Polish", "polish", "#GameUI_Language_Polish", k_Lang_Polish } ,
{ "Danish", "danish", "#GameUI_Language_Danish", k_Lang_Danish } ,
{ "Dutch", "dutch", "#GameUI_Language_Dutch", k_Lang_Dutch } ,
{ "Finnish", "finnish", "#GameUI_Language_Finnish", k_Lang_Finnish } ,
{ "Norwegian", "norwegian", "#GameUI_Language_Norwegian", k_Lang_Norwegian } ,
{ "Swedish", "swedish", "#GameUI_Language_Swedish", k_Lang_Swedish } ,
};
//-----------------------------------------------------------------------------
// STATIC
// Purpose: find the language by name
//-----------------------------------------------------------------------------
ELanguage PchLanguageToELanguage( const char *pchShortName )
{
Assert( ARRAYSIZE(s_LanguageNames) == k_Lang_MAX + 1 );
if ( !pchShortName )
return k_Lang_English;
for ( int iLang = 0; iLang < Q_ARRAYSIZE(s_LanguageNames); ++iLang )
{
if ( !Q_stricmp( pchShortName, s_LanguageNames[iLang].m_pchShortName ) )
{
return s_LanguageNames[iLang].m_ELanguage;
}
}
// default to English
return k_Lang_English;
}
//-----------------------------------------------------------------------------
// Purpose: return the short string name used for this language by SteamUI
//-----------------------------------------------------------------------------
const char *GetLanguageShortName( ELanguage eLang )
{
Assert( Q_ARRAYSIZE(s_LanguageNames) == k_Lang_MAX + 1 );
if ( s_LanguageNames[ eLang + 1 ].m_ELanguage == eLang )
{
return s_LanguageNames[ eLang + 1 ].m_pchShortName;
}
Assert( !"enum ELanguage order mismatched from Language_t s_LanguageNames, fix it!" );
return s_LanguageNames[0].m_pchShortName;
}
//-----------------------------------------------------------------------------
// Purpose: return the short string name used for this language by SteamUI
//-----------------------------------------------------------------------------
const char *GetLanguageName( ELanguage eLang )
{
Assert( Q_ARRAYSIZE(s_LanguageNames) == k_Lang_MAX + 1 );
if ( s_LanguageNames[ eLang + 1 ].m_ELanguage == eLang )
{
return s_LanguageNames[ eLang + 1 ].m_pchName;
}
Assert( !"enum ELanguage order mismatched from Language_t s_LanguageNames, fix it!" );
return s_LanguageNames[0].m_pchShortName;
}
//-----------------------------------------------------------------------------
// Purpose: return the short string name used for this language by SteamUI
//-----------------------------------------------------------------------------
const char *GetLanguageVGUILocalization( ELanguage eLang )
{
Assert( Q_ARRAYSIZE(s_LanguageNames) == k_Lang_MAX + 1 );
if ( s_LanguageNames[ eLang + 1 ].m_ELanguage == eLang )
{
return s_LanguageNames[ eLang + 1 ].m_pchVGUILocalizationName;
}
Assert( !"enum ELanguage order mismatched from Language_t s_LanguageNames, fix it!" );
return s_LanguageNames[0].m_pchVGUILocalizationName;
}

43
common/language.h Normal file
View File

@ -0,0 +1,43 @@
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
//
// Purpose: represent a canonical list of the languages we support,
//
//=============================================================================
#ifndef LANG_H
#define LANG_H
#ifdef _WIN32
#pragma once
#endif
// if you change this enum also change language.cpp:s_LanguageNames
enum ELanguage
{
k_Lang_None = -1,
k_Lang_English = 0,
k_Lang_German,
k_Lang_French,
k_Lang_Italian,
k_Lang_Korean,
k_Lang_Spanish,
k_Lang_Simplified_Chinese,
k_Lang_Traditional_Chinese,
k_Lang_Russian,
k_Lang_Thai,
k_Lang_Japanese,
k_Lang_Portuguese,
k_Lang_Polish,
k_Lang_Danish,
k_Lang_Dutch,
k_Lang_Finnish,
k_Lang_Norwegian,
k_Lang_Swedish,
k_Lang_MAX
};
ELanguage PchLanguageToELanguage(const char *pchShortName);
const char *GetLanguageShortName( ELanguage eLang );
const char *GetLanguageVGUILocalization( ELanguage eLang );
const char *GetLanguageName( ELanguage eLang );
#endif /* LANG_H */

View File

@ -0,0 +1,92 @@
//===== Copyright © 1996-2009, Valve Corporation, All rights reserved. ======//
//
// Purpose: common routines to operate on matchmaking sessions and members
// Assumptions: caller should include all required headers before including mm_helpers.h
//
//===========================================================================//
#ifndef __COMMON__MM_HELPERS_H_
#define __COMMON__MM_HELPERS_H_
#ifdef _WIN32
#pragma once
#endif
#include "tier1/keyvalues.h"
#include "tier1/fmtstr.h"
//
// Contains inline functions to deal with common tasks involving matchmaking and sessions
//
inline KeyValues * SessionMembersFindPlayer( KeyValues *pSessionSettings, XUID xuidPlayer, KeyValues **ppMachine = NULL )
{
if ( ppMachine )
*ppMachine = NULL;
if ( !pSessionSettings )
return NULL;
KeyValues *pMembers = pSessionSettings->FindKey( "Members" );
if ( !pMembers )
return NULL;
int numMachines = pMembers->GetInt( "numMachines" );
for ( int k = 0; k < numMachines; ++ k )
{
KeyValues *pMachine = pMembers->FindKey( CFmtStr( "machine%d", k ) );
if ( !pMachine )
continue;
int numPlayers = pMachine->GetInt( "numPlayers" );
for ( int j = 0; j < numPlayers; ++ j )
{
KeyValues *pPlayer = pMachine->FindKey( CFmtStr( "player%d", j ) );
if ( !pPlayer )
continue;
if ( pPlayer->GetUint64( "xuid" ) == xuidPlayer )
{
if ( ppMachine )
*ppMachine = pMachine;
return pPlayer;
}
}
}
return NULL;
}
inline XUID SessionMembersFindNonGuestXuid( XUID xuid )
{
#ifdef _X360
if ( !g_pMatchFramework )
return xuid;
if ( !g_pMatchFramework->GetMatchSession() )
return xuid;
KeyValues *pMachine = NULL;
KeyValues *pPlayer = SessionMembersFindPlayer( g_pMatchFramework->GetMatchSession()->GetSessionSettings(), xuid, &pMachine );
if ( !pPlayer || !pMachine )
return xuid;
if ( !strchr( pPlayer->GetString( "name" ), '(' ) )
return xuid;
int numPlayers = pMachine->GetInt( "numPlayers" );
for ( int k = 0; k < numPlayers; ++ k )
{
XUID xuidOtherPlayer = pMachine->GetUint64( CFmtStr( "player%d/xuid", k ) );
if ( xuidOtherPlayer && !strchr( pMachine->GetString( CFmtStr( "player%d/xuid", k ) ), '(' ) )
return xuidOtherPlayer; // found a replacement that is not guest
}
#endif
return xuid;
}
#endif // __COMMON__MM_HELPERS_H_

176
common/protocol.h Normal file
View File

@ -0,0 +1,176 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// protocol.h -- communications protocols
#ifndef PROTOCOL_H
#define PROTOCOL_H
#ifdef _WIN32
#pragma once
#endif
// Used to classify entity update types in DeltaPacketEntities.
enum UpdateType
{
EnterPVS = 0, // Entity came back into pvs, create new entity if one doesn't exist
LeavePVS, // Entity left pvs
DeltaEnt, // There is a delta for this entity.
PreserveEnt, // Entity stays alive but no delta ( could be LOD, or just unchanged )
Finished, // finished parsing entities successfully
Failed, // parsing error occured while reading entities
};
// Flags for delta encoding header
enum
{
FHDR_ZERO = 0x0000,
FHDR_LEAVEPVS = 0x0001,
FHDR_DELETE = 0x0002,
FHDR_ENTERPVS = 0x0004,
};
#define INSTANCE_BASELINE_TABLENAME "instancebaseline"
#define LIGHT_STYLES_TABLENAME "lightstyles"
#define USER_INFO_TABLENAME "userinfo"
#define SERVER_STARTUP_DATA_TABLENAME "server_query_info" // the name is a remnant...
//#define CURRENT_PROTOCOL 1
#define DELTA_OFFSET_BITS 5
#define DELTA_OFFSET_MAX ( ( 1 << DELTA_OFFSET_BITS ) - 1 )
#define DELTASIZE_BITS 20 // must be: 2^DELTASIZE_BITS > (NET_MAX_PAYLOAD * 8)
// Largest # of commands to send in a packet
#define NUM_NEW_COMMAND_BITS 4
#define MAX_NEW_COMMANDS ((1 << NUM_NEW_COMMAND_BITS)-1)
// Max number of history commands to send ( 2 by default ) in case of dropped packets
#define NUM_BACKUP_COMMAND_BITS 3
#define MAX_BACKUP_COMMANDS ((1 << NUM_BACKUP_COMMAND_BITS)-1)
#define PROTOCOL_AUTHCERTIFICATE 0x01 // Connection from client is using a WON authenticated certificate
#define PROTOCOL_HASHEDCDKEY 0x02 // Connection from client is using hashed CD key because WON comm. channel was unreachable
#define PROTOCOL_STEAM 0x03 // Steam certificates
#define PROTOCOL_LASTVALID 0x03 // Last valid protocol
#define CONNECTIONLESS_HEADER 0xFFFFFFFF // all OOB packet start with this sequence
#define STEAM_KEYSIZE 2048 // max size needed to contain a steam authentication key (both server and client)
// each channel packet has 1 byte of FLAG bits
#define PACKET_FLAG_RELIABLE (1<<0) // packet contains subchannel stream data
#define PACKET_FLAG_COMPRESSED (1<<1) // packet is compressed
#define PACKET_FLAG_ENCRYPTED (1<<2) // packet is encrypted
#define PACKET_FLAG_SPLIT (1<<3) // packet is split
#define PACKET_FLAG_CHOKED (1<<4) // packet was choked by sender
// NOTE: Bits 5, 6, and 7 are used to specify the # of padding bits at the end of the packet!!!
#define ENCODE_PAD_BITS( x ) ( ( x << 5 ) & 0xff )
#define DECODE_PAD_BITS( x ) ( ( x >> 5 ) & 0xff )
// shared commands used by all streams, handled by stream layer, TODO
#define net_NOP 0 // nop command used for padding
#define net_Disconnect 1 // disconnect, last message in connection
#define net_File 2 // file transmission message request/deny
#define net_LastControlMessage 2
#define net_SplitScreenUser 3 // Changes split screen user
#define net_Tick 4 // send last world tick
#define net_StringCmd 5 // a string command
#define net_SetConVar 6 // sends one/multiple convar settings
#define net_SignonState 7 // signals current signon state
//
// server to client
//
#define svc_ServerInfo 8 // first message from server about game, map etc
#define svc_SendTable 9 // sends a sendtable description for a game class
#define svc_ClassInfo 10 // Info about classes (first byte is a CLASSINFO_ define).
#define svc_SetPause 11 // tells client if server paused or unpaused
#define svc_CreateStringTable 12 // inits shared string tables
#define svc_UpdateStringTable 13 // updates a string table
#define svc_VoiceInit 14 // inits used voice codecs & quality
#define svc_VoiceData 15 // Voicestream data from the server
#define svc_Print 16 // print text to console
#define svc_Sounds 17 // starts playing sound
#define svc_SetView 18 // sets entity as point of view
#define svc_FixAngle 19 // sets/corrects players viewangle
#define svc_CrosshairAngle 20 // adjusts crosshair in auto aim mode to lock on traget
#define svc_BSPDecal 21 // add a static decal to the world BSP
#define svc_SplitScreen 22 // split screen style message
// Message from server side to client side entity
#define svc_UserMessage 23 // a game specific message
#define svc_EntityMessage 24 // a message for an entity
#define svc_GameEvent 25 // global game event fired
#define svc_PacketEntities 26 // non-delta compressed entities
#define svc_TempEntities 27 // non-reliable event object
#define svc_Prefetch 28 // only sound indices for now
#define svc_Menu 29 // display a menu from a plugin
#define svc_GameEventList 30 // list of known games events and fields
#define svc_GetCvarValue 31 // Server wants to know the value of a cvar on the client
#define svc_CmdKeyValues 32 // Server submits KeyValues command for the client
#define SVC_LASTMSG 32 // last known server messages
//
// client to server
//
#define clc_ClientInfo 8 // client info (table CRC etc)
#define clc_Move 9 // [CUserCmd]
#define clc_VoiceData 10 // Voicestream data from a client
#define clc_BaselineAck 11 // client acknowledges a new baseline seqnr
#define clc_ListenEvents 12 // client acknowledges a new baseline seqnr
#define clc_RespondCvarValue 13 // client is responding to a svc_GetCvarValue message.
#define clc_FileCRCCheck 14 // client is sending a file's CRC to the server to be verified.
#define clc_LoadingProgress 15 // client loading progress
#define clc_SplitPlayerConnect 16
#define clc_CmdKeyValues 17
#define CLC_LASTMSG 17 // last known client message
#define RES_FATALIFMISSING (1<<0) // Disconnect if we can't get this file.
#define RES_PRELOAD (1<<1) // Load on client rather than just reserving name
#define SIGNONSTATE_NONE 0 // no state yet, about to connect
#define SIGNONSTATE_CHALLENGE 1 // client challenging server, all OOB packets
#define SIGNONSTATE_CONNECTED 2 // client is connected to server, netchans ready
#define SIGNONSTATE_NEW 3 // just got serverinfo and string tables
#define SIGNONSTATE_PRESPAWN 4 // received signon buffers
#define SIGNONSTATE_SPAWN 5 // ready to receive entity packets
#define SIGNONSTATE_FULL 6 // we are fully connected, first non-delta packet received
#define SIGNONSTATE_CHANGELEVEL 7 // server is changing level, please wait
#endif // PROTOCOL_H

35
common/qlimits.h Normal file
View File

@ -0,0 +1,35 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef QLIMITS_H
#define QLIMITS_H
#if defined( _WIN32 )
#pragma once
#endif
// DATA STRUCTURE INFO
#define MAX_NUM_ARGVS 50
// SYSTEM INFO
#define MAX_QPATH 96 // max length of a game pathname
#define MAX_OSPATH 260 // max length of a filesystem pathname
#define ON_EPSILON 0.1 // point on plane side epsilon
// Resource counts;
#define MAX_MODEL_INDEX_BITS 10 // sent as a short
#define MAX_MODELS (1<<MAX_MODEL_INDEX_BITS)
#define MAX_GENERIC_INDEX_BITS 9
#define MAX_GENERIC (1<<MAX_GENERIC_INDEX_BITS)
#define MAX_DECAL_INDEX_BITS 9
#define MAX_BASE_DECALS (1<<MAX_DECAL_INDEX_BITS)
#endif // QLIMITS_H

27
common/randoverride.cpp Normal file
View File

@ -0,0 +1,27 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
#include "stdlib.h"
#include "vstdlib/random.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef GNUC
#define __cdecl
#endif
void __cdecl srand(unsigned int)
{
}
int __cdecl rand()
{
return RandomInt( 0, 0x7fff );
}
#endif // !_STATIC_LINKED || _SHARED_LIB

2636
common/studiobyteswap.cpp Normal file

File diff suppressed because it is too large Load Diff

40
common/studiobyteswap.h Normal file
View File

@ -0,0 +1,40 @@
//========= Copyright © 1996-2006, Valve LLC, All rights reserved. ============
//
// Purpose: StudioMDL byteswapping functions.
//
// $NoKeywords: $
//=============================================================================
#ifndef STUDIOBYTESWAP_H
#define STUDIOBYTESWAP_H
#if defined(_WIN32)
#pragma once
#endif
#include "byteswap.h"
struct studiohdr_t;
class IPhysicsCollision;
namespace StudioByteSwap
{
typedef bool (*CompressFunc_t)( const void *pInput, int inputSize, void **pOutput, int *pOutputSize );
//void SetTargetBigEndian( bool bigEndian );
void ActivateByteSwapping( bool bActivate );
void SourceIsNative( bool bActivate );
void SetVerbose( bool bVerbose );
void SetCollisionInterface( IPhysicsCollision *pPhysicsCollision );
int ByteswapStudioFile( const char *pFilename, void *pOutBase, int outBaseSize, const void *pFileBase, int fileSize, studiohdr_t *pHdr, CompressFunc_t pCompressFunc = NULL );
int ByteswapPHY( void *pOutBase, int outBaseSize, const void *pFileBase, int fileSize );
int ByteswapANI( studiohdr_t* pHdr, void *pOutBase, int outBaseSize, const void *pFileBase, int filesize );
int ByteswapVVD( void *pOutBase, int outBaseSize, const void *pFileBase, int fileSize );
int ByteswapVTX( void *pOutBase, int outBaseSize, const void *pFileBase, int fileSize );
int ByteswapMDL( void *pOutBase, int OutBaseSize, const void *pFileBase, int fileSize );
#define BYTESWAP_ALIGNMENT_PADDING 4096
#define ERROR_MISALIGNED_DATA -1
#define ERROR_VERSION -2
}
#endif // STUDIOBYTESWAP_H

View File

@ -0,0 +1,107 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef IFONTSURFACE_H
#define IFONTSURFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/vector2d.h" // must be before the namespace line
#ifdef CreateFont
#undef CreateFont
#endif
// returns true if the surface supports minimize & maximize capabilities
// Numbered this way to prevent interface change in surface.
enum FontFeature_t
{
FONT_FEATURE_ANTIALIASED_FONTS = 1,
FONT_FEATURE_DROPSHADOW_FONTS = 2,
FONT_FEATURE_OUTLINE_FONTS = 6,
};
// adds to the font
enum FontFlags_t
{
FONTFLAG_NONE,
FONTFLAG_ITALIC = 0x001,
FONTFLAG_UNDERLINE = 0x002,
FONTFLAG_STRIKEOUT = 0x004,
FONTFLAG_SYMBOL = 0x008,
FONTFLAG_ANTIALIAS = 0x010,
FONTFLAG_GAUSSIANBLUR = 0x020,
FONTFLAG_ROTARY = 0x040,
FONTFLAG_DROPSHADOW = 0x080,
FONTFLAG_ADDITIVE = 0x100,
FONTFLAG_OUTLINE = 0x200,
FONTFLAG_CUSTOM = 0x400, // custom generated font - never fall back to asian compatibility mode
FONTFLAG_BITMAP = 0x800, // compiled bitmap font - no fallbacks
};
enum FontDrawType_t
{
// Use the "additive" value from the scheme file
FONT_DRAW_DEFAULT = 0,
// Overrides
FONT_DRAW_NONADDITIVE,
FONT_DRAW_ADDITIVE,
FONT_DRAW_TYPE_COUNT = 2,
};
struct FontVertex_t
{
FontVertex_t() {}
FontVertex_t( const Vector2D &pos, const Vector2D &coord = Vector2D( 0, 0 ) )
{
m_Position = pos;
m_TexCoord = coord;
}
void Init( const Vector2D &pos, const Vector2D &coord = Vector2D( 0, 0 ) )
{
m_Position = pos;
m_TexCoord = coord;
}
Vector2D m_Position;
Vector2D m_TexCoord;
};
typedef unsigned long FontHandle_t;
struct FontCharRenderInfo
{
// Text pos
int x, y;
// Top left and bottom right
// This is now a pointer to an array maintained by the surface, to avoid copying the data on the 360
FontVertex_t *verts;
int textureId;
int abcA;
int abcB;
int abcC;
int fontTall;
FontHandle_t currentFont;
// In:
FontDrawType_t drawType;
wchar_t ch;
// Out
bool valid;
// In/Out (true by default)
bool shouldclip;
};
#endif // IFONTSURFACE_H

409
common/xbox/xboxstubs.h Normal file
View File

@ -0,0 +1,409 @@
//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============
//
// Purpose: Win32 replacements for XBox.
//
//=============================================================================
#if !defined( XBOXSTUBS_H ) && !defined( _X360 )
#define XBOXSTUBS_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
// Content creation/open flags
#define XCONTENTFLAG_NONE 0x00
#define XCONTENTFLAG_CREATENEW 0x00
#define XCONTENTFLAG_CREATEALWAYS 0x00
#define XCONTENTFLAG_OPENEXISTING 0x00
#define XCONTENTFLAG_OPENALWAYS 0x00
#define XCONTENTFLAG_TRUNCATEEXISTING 0x00
// Content attributes
#define XCONTENTFLAG_NOPROFILE_TRANSFER 0x00
#define XCONTENTFLAG_NODEVICE_TRANSFER 0x00
#define XCONTENTFLAG_STRONG_SIGNED 0x00
#define XCONTENTFLAG_ALLOWPROFILE_TRANSFER 0x00
#define XCONTENTFLAG_MOVEONLY_TRANSFER 0x00
// XNet flags
#define XNET_GET_XNADDR_PENDING 0x00000000 // Address acquisition is not yet complete
#define XNET_GET_XNADDR_NONE 0x00000001 // XNet is uninitialized or no debugger found
#define XNET_GET_XNADDR_ETHERNET 0x00000002 // Host has ethernet address (no IP address)
#define XNET_GET_XNADDR_STATIC 0x00000004 // Host has statically assigned IP address
#define XNET_GET_XNADDR_DHCP 0x00000008 // Host has DHCP assigned IP address
#define XNET_GET_XNADDR_PPPOE 0x00000010 // Host has PPPoE assigned IP address
#define XNET_GET_XNADDR_GATEWAY 0x00000020 // Host has one or more gateways configured
#define XNET_GET_XNADDR_DNS 0x00000040 // Host has one or more DNS servers configured
#define XNET_GET_XNADDR_ONLINE 0x00000080 // Host is currently connected to online service
#define XNET_GET_XNADDR_TROUBLESHOOT 0x00008000 // Network configuration requires troubleshooting
// Console device ports
#define XDEVICE_PORT0 0
#define XDEVICE_PORT1 1
#define XDEVICE_PORT2 2
#define XDEVICE_PORT3 3
#define XUSER_MAX_COUNT 4
#define XUSER_INDEX_NONE 0x000000FE
#define XBX_CLR_DEFAULT 0xFF000000
#define XBX_CLR_WARNING 0x0000FFFF
#define XBX_CLR_ERROR 0x000000FF
#define XBOX_MINBORDERSAFE 0
#define XBOX_MAXBORDERSAFE 0
typedef enum
{
XK_NULL,
XK_BUTTON_UP,
XK_BUTTON_DOWN,
XK_BUTTON_LEFT,
XK_BUTTON_RIGHT,
XK_BUTTON_START,
XK_BUTTON_BACK,
XK_BUTTON_STICK1,
XK_BUTTON_STICK2,
XK_BUTTON_A,
XK_BUTTON_B,
XK_BUTTON_X,
XK_BUTTON_Y,
XK_BUTTON_LEFT_SHOULDER,
XK_BUTTON_RIGHT_SHOULDER,
XK_BUTTON_LTRIGGER,
XK_BUTTON_RTRIGGER,
XK_STICK1_UP,
XK_STICK1_DOWN,
XK_STICK1_LEFT,
XK_STICK1_RIGHT,
XK_STICK2_UP,
XK_STICK2_DOWN,
XK_STICK2_LEFT,
XK_STICK2_RIGHT,
XK_BUTTON_INACTIVE_START,
XK_MAX_KEYS,
} xKey_t;
//typedef enum
//{
// XVRB_NONE, // off
// XVRB_ERROR, // fatal error
// XVRB_ALWAYS, // no matter what
// XVRB_WARNING, // non-fatal warnings
// XVRB_STATUS, // status reports
// XVRB_ALL,
//} xverbose_e;
typedef unsigned short WORD;
typedef unsigned long DWORD;
#ifndef POSIX
typedef void* HANDLE;
typedef unsigned __int64 ULONGLONG;
#endif
#ifdef POSIX
typedef int32 COLORREF;
#endif
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
#endif
/*
* Internet address (old style... should be updated)
*/
#ifdef _POSIX
struct ip4_addr {
union {
struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { unsigned short s_w1,s_w2; } S_un_w;
unsigned long S_addr;
} S_un;
};
typedef struct ip4_addr IN_ADDR;
#else
#ifndef s_addr
/*
* Internet address (old style... should be updated)
*/
struct in_addr {
union {
struct { unsigned char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { unsigned short s_w1,s_w2; } S_un_w;
unsigned long S_addr;
} S_un;
#define s_addr S_un.S_addr
/* can be used for most tcp & ip code */
#define s_host S_un.S_un_b.s_b2
/* host on imp */
#define s_net S_un.S_un_b.s_b1
/* network */
#define s_imp S_un.S_un_w.s_w2
/* imp */
#define s_impno S_un.S_un_b.s_b4
/* imp # */
#define s_lh S_un.S_un_b.s_b3
/* logical host */
};
typedef struct in_addr IN_ADDR;
#endif
#endif
typedef unsigned int XIN_ADDR;
typedef struct {
IN_ADDR ina; // IP address (zero if not static/DHCP)
IN_ADDR inaOnline; // Online IP address (zero if not online)
WORD wPortOnline; // Online port
BYTE abEnet[6]; // Ethernet MAC address
BYTE abOnline[20]; // Online identification
} XNADDR;
typedef uint64 XUID;
typedef struct {
BYTE ab[8]; // xbox to xbox key identifier
} XNKID;
typedef struct {
BYTE ab[16]; // xbox to xbox key exchange key
} XNKEY;
typedef struct _XSESSION_INFO
{
XNKID sessionID; // 8 bytes
XNADDR hostAddress; // 36 bytes
XNKEY keyExchangeKey; // 16 bytes
} XSESSION_INFO, *PXSESSION_INFO;
typedef struct _XUSER_DATA
{
BYTE type;
union
{
int nData; // XUSER_DATA_TYPE_INT32
int64 i64Data; // XUSER_DATA_TYPE_INT64
double dblData; // XUSER_DATA_TYPE_DOUBLE
struct // XUSER_DATA_TYPE_UNICODE
{
uint cbData; // Includes null-terminator
char * pwszData;
} string;
float fData; // XUSER_DATA_TYPE_FLOAT
struct // XUSER_DATA_TYPE_BINARY
{
uint cbData;
char * pbData;
} binary;
};
} XUSER_DATA, *PXUSER_DATA;
typedef struct _XUSER_PROPERTY
{
DWORD dwPropertyId;
XUSER_DATA value;
} XUSER_PROPERTY, *PXUSER_PROPERTY;
typedef struct _XUSER_CONTEXT
{
DWORD dwContextId;
DWORD dwValue;
} XUSER_CONTEXT, *PXUSER_CONTEXT;
typedef struct _XSESSION_SEARCHRESULT
{
XSESSION_INFO info;
DWORD dwOpenPublicSlots;
DWORD dwOpenPrivateSlots;
DWORD dwFilledPublicSlots;
DWORD dwFilledPrivateSlots;
DWORD cProperties;
DWORD cContexts;
PXUSER_PROPERTY pProperties;
PXUSER_CONTEXT pContexts;
} XSESSION_SEARCHRESULT, *PXSESSION_SEARCHRESULT;
typedef struct _XSESSION_SEARCHRESULT_HEADER
{
DWORD dwSearchResults;
XSESSION_SEARCHRESULT *pResults;
} XSESSION_SEARCHRESULT_HEADER, *PXSESSION_SEARCHRESULT_HEADER;
typedef struct _XSESSION_REGISTRANT
{
uint64 qwMachineID;
DWORD bTrustworthiness;
DWORD bNumUsers;
XUID *rgUsers;
} XSESSION_REGISTRANT;
typedef struct _XSESSION_REGISTRATION_RESULTS
{
DWORD wNumRegistrants;
XSESSION_REGISTRANT *rgRegistrants;
} XSESSION_REGISTRATION_RESULTS, *PXSESSION_REGISTRATION_RESULTS;
typedef struct {
BYTE bFlags;
BYTE bReserved;
WORD cProbesXmit;
WORD cProbesRecv;
WORD cbData;
BYTE * pbData;
WORD wRttMinInMsecs;
WORD wRttMedInMsecs;
DWORD dwUpBitsPerSec;
DWORD dwDnBitsPerSec;
} XNQOSINFO;
typedef struct {
uint cxnqos;
uint cxnqosPending;
XNQOSINFO axnqosinfo[1];
} XNQOS;
#define XSESSION_CREATE_HOST 0
#define XSESSION_CREATE_USES_ARBITRATION 0
#define XNET_QOS_LISTEN_ENABLE 0
#define XNET_QOS_LISTEN_DISABLE 0
#define XNET_QOS_LISTEN_SET_DATA 0
#define XUSER_DATA_TYPE_CONTEXT ((BYTE)0)
#define XUSER_DATA_TYPE_INT32 ((BYTE)1)
#define XUSER_DATA_TYPE_INT64 ((BYTE)2)
#define XUSER_DATA_TYPE_DOUBLE ((BYTE)3)
#define XUSER_DATA_TYPE_UNICODE ((BYTE)4)
#define XUSER_DATA_TYPE_FLOAT ((BYTE)5)
#define XUSER_DATA_TYPE_BINARY ((BYTE)6)
#define XUSER_DATA_TYPE_DATETIME ((BYTE)7)
#define XUSER_DATA_TYPE_NULL ((BYTE)0xFF)
#define XPROFILE_TITLE_SPECIFIC1 0x3FFF
#define XPROFILE_TITLE_SPECIFIC2 0x3FFE
#define XPROFILE_TITLE_SPECIFIC3 0x3FFD
#define XPROFILE_SETTING_MAX_SIZE 1000
FORCEINLINE DWORD XBX_GetNumGameUsers() { return 1; }
FORCEINLINE void XBX_ProcessEvents() {}
FORCEINLINE void XBX_DispatchEventsQueue() {}
FORCEINLINE unsigned int XBX_GetSystemTime() { return 0; }
FORCEINLINE DWORD XBX_GetPrimaryUserId() { return 0; }
FORCEINLINE void XBX_SetPrimaryUserId( DWORD idx ) {}
FORCEINLINE void XBX_ResetStorageDeviceInfo() {}
FORCEINLINE DWORD XBX_DescribeStorageDevice( DWORD nStorageID ) { return 1; }
FORCEINLINE DWORD XBX_GetStorageDeviceId(int) { return 0; }
FORCEINLINE void XBX_SetStorageDeviceId( int, DWORD ) {}
FORCEINLINE const char *XBX_GetLanguageString() { return ""; }
FORCEINLINE bool XBX_IsLocalized() { return false; }
FORCEINLINE bool XBX_IsAudioLocalized() { return false; }
FORCEINLINE const char *XBX_GetNextSupportedLanguage( const char *pLanguage, bool *pbHasAudio ) { return NULL; }
FORCEINLINE bool XBX_IsRestrictiveLanguage() { return false; }
FORCEINLINE int XBX_GetUserId( int nSlot ) { return nSlot; }
FORCEINLINE void XBX_SetUserId( int nSlot, int idx ) {}
#define XCONTENT_MAX_DISPLAYNAME_LENGTH 128
#define XCONTENT_MAX_FILENAME_LENGTH 42
#define XBX_INVALID_STORAGE_ID ((DWORD) -1)
#define XBX_STORAGE_DECLINED ((DWORD) -2)
enum XUSER_SIGNIN_STATE
{
eXUserSigninState_NotSignedIn,
eXUserSigninState_SignedInLocally,
eXUserSigninState_SignedInToLive,
};
#if (defined(_POSIX))
typedef size_t ULONG_PTR;
#else
typedef _W64 unsigned long ULONG_PTR;
#endif
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
typedef void * PXOVERLAPPED_COMPLETION_ROUTINE;
#ifndef _POSIX
typedef struct _XOVERLAPPED {
ULONG_PTR InternalLow;
ULONG_PTR InternalHigh;
ULONG_PTR InternalContext;
HANDLE hEvent;
PXOVERLAPPED_COMPLETION_ROUTINE pCompletionRoutine;
DWORD_PTR dwCompletionContext;
DWORD dwExtendedError;
} XOVERLAPPED, *PXOVERLAPPED;
#endif
#ifndef MAX_RICHPRESENCE_SIZE
#define MAX_RICHPRESENCE_SIZE 64
#endif
#ifndef XUSER_NAME_SIZE
#define XUSER_NAME_SIZE 16
#endif
#ifndef GPU_RESOLVE_ALIGNMENT
#define GPU_RESOLVE_ALIGNMENT 8
#endif
#define XCONTENT_MAX_DISPLAYNAME_LENGTH 128
#define XCONTENT_MAX_FILENAME_LENGTH 42
#define XCONTENTDEVICE_MAX_NAME_LENGTH 27
typedef DWORD XCONTENTDEVICEID, *PXCONTENTDEVICEID;
typedef struct _XCONTENT_DATA
{
XCONTENTDEVICEID DeviceID;
DWORD dwContentType;
wchar_t szDisplayName[XCONTENT_MAX_DISPLAYNAME_LENGTH];
char szFileName[XCONTENT_MAX_FILENAME_LENGTH];
} XCONTENT_DATA, *PXCONTENT_DATA;
#define X_CONTEXT_PRESENCE 0x00010001
#define X_CONTEXT_GAME_TYPE 0x0001000A
#define X_CONTEXT_GAME_MODE 0x0001000B
#define X_PROPERTY_RANK 0x00011001
#define X_PROPERTY_GAMERNAME 0x00011002
#define X_PROPERTY_SESSION_ID 0x00011003
// System attributes used in matchmaking queries
#define X_PROPERTY_GAMER_ZONE 0x00011101
#define X_PROPERTY_GAMER_COUNTRY 0x00011102
#define X_PROPERTY_GAMER_LANGUAGE 0x00011103
#define X_PROPERTY_GAMER_RATING 0x00011104
#define X_PROPERTY_GAMER_MU 0x00011105
#define X_PROPERTY_GAMER_SIGMA 0x00011106
#define X_PROPERTY_GAMER_PUID 0x00011107
#define X_PROPERTY_AFFILIATE_SCORE 0x00011108
#define X_PROPERTY_GAMER_HOSTNAME 0x00011109
// Properties used to write to skill leaderboards
#define X_PROPERTY_RELATIVE_SCORE 0x0001100A
#define X_PROPERTY_SESSION_TEAM 0x0001100B
// Properties written at the session level to override TrueSkill parameters
#define X_PROPERTY_PLAYER_PARTIAL_PLAY_PERCENTAGE 0x0001100C
#define X_PROPERTY_PLAYER_SKILL_UPDATE_WEIGHTING_FACTOR 0x0001100D
#define X_PROPERTY_SESSION_SKILL_BETA 0x0001100E
#define X_PROPERTY_SESSION_SKILL_TAU 0x0001100F
#define X_PROPERTY_SESSION_SKILL_DRAW_PROBABILITY 0x00011010
// Attachment size is written to a leaderboard when the entry qualifies for
// a gamerclip. The rating can be retrieved via XUserEstimateRankForRating.
#define X_PROPERTY_ATTACHMENT_SIZE 0x00011011
// Values for X_CONTEXT_GAME_TYPE
#define X_CONTEXT_GAME_TYPE_RANKED 0
#define X_CONTEXT_GAME_TYPE_STANDARD 1
#endif // XBOXSTUBS_H

19
engine/iblackbox.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef IBLACKBOX_H
#define IBLACKBOX_H
#define BLACKBOX_INTERFACE_VERSION "BlackBoxVersion001"
class IBlackBox
{
public:
virtual void Record(int type, const char *fmt) = 0;
virtual void SetLimit(int type, unsigned int count) = 0;
virtual const char *Get(int type, unsigned int index) = 0;
virtual int Count(int type) = 0;
virtual void Flush(int type) = 0;
virtual const char *GetTypeName(int type) = 0;
virtual int GetTypeCount() = 0;
};
#endif

View File

@ -0,0 +1,54 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Acts exactly like "AnimatedTexture", but ONLY if the texture
// it's working on matches the desired texture to work on.
//
// This assumes that some other proxy will be switching out the textures.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/ITexture.h"
#include "BaseAnimatedTextureProxy.h"
#include "utlstring.h"
#include <KeyValues.h>
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimateSpecificTexture : public CBaseAnimatedTextureProxy
{
private:
CUtlString m_OnlyAnimateOnTexture;
public:
virtual float GetAnimationStartTime( void* pBaseEntity ) { return 0; }
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
};
bool CAnimateSpecificTexture::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pszAnimateOnTexture = pKeyValues->GetString( "onlyAnimateOnTexture" );
if( !pszAnimateOnTexture )
return false;
m_OnlyAnimateOnTexture.Set( pszAnimateOnTexture );
return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
}
void CAnimateSpecificTexture::OnBind( void *pC_BaseEntity )
{
if( FStrEq( m_AnimatedTextureVar->GetTextureValue()->GetName(), m_OnlyAnimateOnTexture ) )
{
CBaseAnimatedTextureProxy::OnBind( pC_BaseEntity );
}
//else do nothing
}
EXPOSE_MATERIAL_PROXY( CAnimateSpecificTexture, AnimateSpecificTexture );

View File

@ -0,0 +1,785 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Material Modify control entity.
//
//=============================================================================//
#include "cbase.h"
#include "ProxyEntity.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/ITexture.h"
#include "iviewrender.h"
#include "texture_group_names.h"
#include "BaseAnimatedTextureProxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define MATERIAL_MODIFY_STRING_SIZE 255
#define MATERIAL_MODIFY_ANIMATION_UNSET -1
// Must match MaterialModifyControl.cpp
enum MaterialModifyMode_t
{
MATERIAL_MODIFY_MODE_NONE = 0,
MATERIAL_MODIFY_MODE_SETVAR = 1,
MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2,
MATERIAL_MODIFY_MODE_FLOAT_LERP = 3,
};
ConVar debug_materialmodifycontrol_client( "debug_materialmodifycontrol_client", "0" );
struct materialanimcommands_t
{
int iFrameStart;
int iFrameEnd;
bool bWrap;
float flFrameRate;
};
struct materialfloatlerpcommands_t
{
int flStartValue;
int flEndValue;
float flTransitionTime;
};
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
class C_MaterialModifyControl : public C_BaseEntity
{
public:
DECLARE_CLASS( C_MaterialModifyControl, C_BaseEntity );
C_MaterialModifyControl();
void OnPreDataChanged( DataUpdateType_t updateType );
void OnDataChanged( DataUpdateType_t updateType );
bool ShouldDraw();
IMaterial *GetMaterial( void ) { return m_pMaterial; }
const char *GetMaterialVariableName( void ) { return m_szMaterialVar; }
const char *GetMaterialVariableValue( void ) { return m_szMaterialVarValue; }
DECLARE_CLIENTCLASS();
// Animated texture and Float Lerp usage
bool HasNewAnimationCommands( void ) { return m_bHasNewAnimationCommands; }
void ClearAnimationCommands( void ) { m_bHasNewAnimationCommands = false; }
// Animated texture usage
void GetAnimationCommands( materialanimcommands_t *pCommands );
// FloatLerp usage
void GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands );
void SetAnimationStartTime( float flTime )
{
m_flAnimationStartTime = flTime;
}
float GetAnimationStartTime( void ) const
{
return m_flAnimationStartTime;
}
MaterialModifyMode_t GetModifyMode( void ) const
{
return ( MaterialModifyMode_t)m_nModifyMode;
}
private:
char m_szMaterialName[MATERIAL_MODIFY_STRING_SIZE];
char m_szMaterialVar[MATERIAL_MODIFY_STRING_SIZE];
char m_szMaterialVarValue[MATERIAL_MODIFY_STRING_SIZE];
IMaterial *m_pMaterial;
bool m_bHasNewAnimationCommands;
// Animation commands from the server
int m_iFrameStart;
int m_iFrameEnd;
bool m_bWrap;
float m_flFramerate;
bool m_bNewAnimCommandsSemaphore;
bool m_bOldAnimCommandsSemaphore;
// Float lerp commands from the server
float m_flFloatLerpStartValue;
float m_flFloatLerpEndValue;
float m_flFloatLerpTransitionTime;
bool m_bFloatLerpWrap;
float m_flAnimationStartTime;
int m_nModifyMode;
};
IMPLEMENT_CLIENTCLASS_DT(C_MaterialModifyControl, DT_MaterialModifyControl, CMaterialModifyControl)
RecvPropString( RECVINFO( m_szMaterialName ) ),
RecvPropString( RECVINFO( m_szMaterialVar ) ),
RecvPropString( RECVINFO( m_szMaterialVarValue ) ),
RecvPropInt( RECVINFO(m_iFrameStart) ),
RecvPropInt( RECVINFO(m_iFrameEnd) ),
RecvPropInt( RECVINFO(m_bWrap) ),
RecvPropFloat( RECVINFO(m_flFramerate) ),
RecvPropInt( RECVINFO(m_bNewAnimCommandsSemaphore) ),
RecvPropFloat( RECVINFO(m_flFloatLerpStartValue) ),
RecvPropFloat( RECVINFO(m_flFloatLerpEndValue) ),
RecvPropFloat( RECVINFO(m_flFloatLerpTransitionTime) ),
RecvPropInt( RECVINFO(m_bFloatLerpWrap) ),
RecvPropInt( RECVINFO(m_nModifyMode) ),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
C_MaterialModifyControl::C_MaterialModifyControl()
{
m_pMaterial = NULL;
m_bOldAnimCommandsSemaphore = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::OnPreDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnPreDataChanged( updateType );
m_bOldAnimCommandsSemaphore = m_bNewAnimCommandsSemaphore;
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void C_MaterialModifyControl::OnDataChanged( DataUpdateType_t updateType )
{
if( updateType == DATA_UPDATE_CREATED )
{
m_pMaterial = materials->FindMaterial( m_szMaterialName, TEXTURE_GROUP_OTHER );
// Clear out our variables
m_bHasNewAnimationCommands = true;
}
// Detect changes in the anim commands
if ( m_bNewAnimCommandsSemaphore != m_bOldAnimCommandsSemaphore )
{
m_bHasNewAnimationCommands = true;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::GetAnimationCommands( materialanimcommands_t *pCommands )
{
pCommands->iFrameStart = m_iFrameStart;
pCommands->iFrameEnd = m_iFrameEnd;
pCommands->bWrap = m_bWrap;
pCommands->flFrameRate = m_flFramerate;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_MaterialModifyControl::GetFloatLerpCommands( materialfloatlerpcommands_t *pCommands )
{
pCommands->flStartValue = m_flFloatLerpStartValue;
pCommands->flEndValue = m_flFloatLerpEndValue;
pCommands->flTransitionTime = m_flFloatLerpTransitionTime;
}
//------------------------------------------------------------------------------
// Purpose: We don't draw.
//------------------------------------------------------------------------------
bool C_MaterialModifyControl::ShouldDraw()
{
return false;
}
//=============================================================================
//
// THE MATERIALMODIFYPROXY ITSELF
//
class CMaterialModifyProxy : public CBaseAnimatedTextureProxy
{
public:
CMaterialModifyProxy();
virtual ~CMaterialModifyProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pEntity );
virtual IMaterial *GetMaterial();
private:
void OnBindSetVar( C_MaterialModifyControl *pControl );
void OnBindAnimatedTexture( C_MaterialModifyControl *pControl );
void OnBindFloatLerp( C_MaterialModifyControl *pControl );
float GetAnimationStartTime( void* pArg );
void AnimationWrapped( void* pArg );
IMaterial *m_pMaterial;
// texture animation stuff
int m_iFrameStart;
int m_iFrameEnd;
bool m_bReachedEnd;
bool m_bCustomWrap;
float m_flCustomFramerate;
// float lerp stuff
IMaterialVar *m_pMaterialVar;
int m_flStartValue;
int m_flEndValue;
float m_flStartTime;
float m_flTransitionTime;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMaterialModifyProxy::CMaterialModifyProxy()
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CMaterialModifyProxy::~CMaterialModifyProxy()
{
}
bool CMaterialModifyProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
// set var stuff
m_pMaterial = pMaterial;
// float lerp stuff
m_flStartValue = MATERIAL_MODIFY_ANIMATION_UNSET;
m_flEndValue = MATERIAL_MODIFY_ANIMATION_UNSET;
// animated stuff
// m_pMaterial = pMaterial;
// m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
// m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
// m_bReachedEnd = false;
// return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
return true;
}
void CMaterialModifyProxy::OnBind( void *pEntity )
{
// Get the modified material vars from the entity input
IClientRenderable *pRend = (IClientRenderable *)pEntity;
if ( pRend )
{
C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pBaseEntity )
{
if( debug_materialmodifycontrol_client.GetBool() )
{
// DevMsg( 1, "%s\n", pBaseEntity->GetDebugName() );
}
int numChildren = 0;
bool gotOne = false;
for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
{
numChildren++;
C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
if ( !pControl )
continue;
if( debug_materialmodifycontrol_client.GetBool() )
{
// DevMsg( 1, "pControl: 0x%p\n", pControl );
}
switch( pControl->GetModifyMode() )
{
case MATERIAL_MODIFY_MODE_NONE:
break;
case MATERIAL_MODIFY_MODE_SETVAR:
gotOne = true;
OnBindSetVar( pControl );
break;
case MATERIAL_MODIFY_MODE_ANIM_SEQUENCE:
OnBindAnimatedTexture( pControl );
break;
case MATERIAL_MODIFY_MODE_FLOAT_LERP:
OnBindFloatLerp( pControl );
break;
default:
Assert( 0 );
break;
}
}
if( gotOne )
{
// DevMsg( 1, "numChildren: %d\n", numChildren );
}
}
}
}
IMaterial *CMaterialModifyProxy::GetMaterial()
{
return m_pMaterial;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindSetVar( C_MaterialModifyControl *pControl )
{
IMaterial *pMaterial = pControl->GetMaterial();
if( !pMaterial )
{
Assert( 0 );
return;
}
if ( pMaterial != m_pMaterial )
{
// Warning( "\t%s!=%s\n", pMaterial->GetName(), m_pMaterial->GetName() );
return;
}
bool bFound;
IMaterialVar *pMaterialVar = pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
if ( !bFound )
return;
if( Q_strcmp( pControl->GetMaterialVariableValue(), "" ) )
{
// const char *pMaterialName = m_pMaterial->GetName();
// const char *pMaterialVarName = pMaterialVar->GetName();
// const char *pMaterialVarValue = pControl->GetMaterialVariableValue();
// if( debug_materialmodifycontrol_client.GetBool()
// && Q_stristr( m_pMaterial->GetName(), "faceandhair" )
// && Q_stristr( pMaterialVar->GetName(), "self" )
// )
// {
// static int count = 0;
// DevMsg( 1, "CMaterialModifyProxy::OnBindSetVar \"%s\" %s=%s %d pControl=0x%p\n",
// m_pMaterial->GetName(), pMaterialVar->GetName(), pControl->GetMaterialVariableValue(), count++, pControl );
// }
pMaterialVar->SetValueAutodetectType( pControl->GetMaterialVariableValue() );
}
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindAnimatedTexture( C_MaterialModifyControl *pControl )
{
assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
return;
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
if ( !pControl )
return;
if ( pControl->HasNewAnimationCommands() )
{
// Read the data from the modify entity
materialanimcommands_t sCommands;
pControl->GetAnimationCommands( &sCommands );
m_iFrameStart = sCommands.iFrameStart;
m_iFrameEnd = sCommands.iFrameEnd;
m_bCustomWrap = sCommands.bWrap;
m_flCustomFramerate = sCommands.flFrameRate;
m_bReachedEnd = false;
m_flStartTime = gpGlobals->curtime;
pControl->ClearAnimationCommands();
}
// Init all the vars based on whether we're using the base material settings,
// or the custom ones from the entity input.
int numFrames;
bool bWrapAnimation;
float flFrameRate;
int iLastFrame;
// Do we have a custom frame section from the server?
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
{
m_iFrameEnd = pTexture->GetNumAnimationFrames();
}
numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
bWrapAnimation = m_bCustomWrap;
flFrameRate = m_flCustomFramerate;
iLastFrame = (m_iFrameEnd - 1);
}
else
{
numFrames = pTexture->GetNumAnimationFrames();
bWrapAnimation = m_WrapAnimation;
flFrameRate = m_FrameRate;
iLastFrame = (numFrames - 1);
}
// Have we already reached the end? If so, stay there.
if ( m_bReachedEnd && !bWrapAnimation )
{
m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
startTime = m_flStartTime;
}
else
{
startTime = GetAnimationStartTime(pControl);
}
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = flFrameRate * deltaTime;
float prevFrame = flFrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
intFrame += m_iFrameStart;
intPrevFrame += m_iFrameStart;
}
// Report wrap situation...
if (intPrevFrame > intFrame)
{
m_bReachedEnd = true;
if (bWrapAnimation)
{
AnimationWrapped( pControl );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pControl );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CMaterialModifyProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyProxy::OnBindFloatLerp( C_MaterialModifyControl *pControl )
{
if ( !pControl )
return;
if ( pControl->HasNewAnimationCommands() )
{
pControl->SetAnimationStartTime( gpGlobals->curtime );
pControl->ClearAnimationCommands();
}
// Read the data from the modify entity
materialfloatlerpcommands_t sCommands;
pControl->GetFloatLerpCommands( &sCommands );
m_flStartValue = sCommands.flStartValue;
m_flEndValue = sCommands.flEndValue;
m_flTransitionTime = sCommands.flTransitionTime;
m_flStartTime = pControl->GetAnimationStartTime();
bool bFound;
m_pMaterialVar = m_pMaterial->FindVar( pControl->GetMaterialVariableName(), &bFound, false );
if( bFound )
{
float currentValue;
if( m_flTransitionTime > 0.0f )
{
currentValue = m_flStartValue + ( m_flEndValue - m_flStartValue ) * clamp( ( ( gpGlobals->curtime - m_flStartTime ) / m_flTransitionTime ), 0.0f, 1.0f );
}
else
{
currentValue = m_flEndValue;
}
if( debug_materialmodifycontrol_client.GetBool() && Q_stristr( m_pMaterial->GetName(), "faceandhair" ) && Q_stristr( m_pMaterialVar->GetName(), "warp" ) )
{
static int count = 0;
DevMsg( 1, "CMaterialFloatLerpProxy::OnBind \"%s\" %s=%f %d\n", m_pMaterial->GetName(), m_pMaterialVar->GetName(), currentValue, count++ );
}
m_pMaterialVar->SetFloatValue( currentValue );
}
}
//=============================================================================
//
// MATERIALMODIFYANIMATED PROXY
//
class CMaterialModifyAnimatedProxy : public CBaseAnimatedTextureProxy
{
public:
CMaterialModifyAnimatedProxy() {};
virtual ~CMaterialModifyAnimatedProxy() {};
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pEntity );
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void AnimationWrapped( void* pC_BaseEntity );
private:
IMaterial *m_pMaterial;
int m_iFrameStart;
int m_iFrameEnd;
bool m_bReachedEnd;
float m_flStartTime;
bool m_bCustomWrap;
float m_flCustomFramerate;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CMaterialModifyAnimatedProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMaterial = pMaterial;
m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET;
m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET;
m_bReachedEnd = false;
return CBaseAnimatedTextureProxy::Init( pMaterial, pKeyValues );
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::OnBind( void *pEntity )
{
assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
return;
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
// Get the modified material vars from the entity input
IClientRenderable *pRend = (IClientRenderable *)pEntity;
if ( pRend )
{
C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pBaseEntity )
{
for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() )
{
C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild );
if ( !pControl )
continue;
if ( !pControl->HasNewAnimationCommands() )
continue;
// Read the data from the modify entity
materialanimcommands_t sCommands;
pControl->GetAnimationCommands( &sCommands );
m_iFrameStart = sCommands.iFrameStart;
m_iFrameEnd = sCommands.iFrameEnd;
m_bCustomWrap = sCommands.bWrap;
m_flCustomFramerate = sCommands.flFrameRate;
m_bReachedEnd = false;
m_flStartTime = gpGlobals->curtime;
pControl->ClearAnimationCommands();
}
}
}
// Init all the vars based on whether we're using the base material settings,
// or the custom ones from the entity input.
int numFrames;
bool bWrapAnimation;
float flFrameRate;
int iLastFrame;
// Do we have a custom frame section from the server?
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET )
{
m_iFrameEnd = pTexture->GetNumAnimationFrames();
}
numFrames = (m_iFrameEnd - m_iFrameStart) + 1;
bWrapAnimation = m_bCustomWrap;
flFrameRate = m_flCustomFramerate;
iLastFrame = (m_iFrameEnd - 1);
}
else
{
numFrames = pTexture->GetNumAnimationFrames();
bWrapAnimation = m_WrapAnimation;
flFrameRate = m_FrameRate;
iLastFrame = (numFrames - 1);
}
// Have we already reached the end? If so, stay there.
if ( m_bReachedEnd && !bWrapAnimation )
{
m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
startTime = m_flStartTime;
}
else
{
startTime = GetAnimationStartTime(pEntity);
}
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = flFrameRate * deltaTime;
float prevFrame = flFrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET )
{
intFrame += m_iFrameStart;
intPrevFrame += m_iFrameStart;
}
// Report wrap situation...
if (intPrevFrame > intFrame)
{
m_bReachedEnd = true;
if (bWrapAnimation)
{
AnimationWrapped( pEntity );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pEntity );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CMaterialModifyAnimatedProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CMaterialModifyAnimatedProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}
EXPOSE_MATERIAL_PROXY( CMaterialModifyProxy, MaterialModify );
EXPOSE_MATERIAL_PROXY( CMaterialModifyAnimatedProxy, MaterialModifyAnimated );

View File

@ -0,0 +1,60 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Water LOD control entity.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "iviewrender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Purpose : Water LOD control entity
//------------------------------------------------------------------------------
class C_WaterLODControl : public C_BaseEntity
{
public:
DECLARE_CLASS( C_WaterLODControl, C_BaseEntity );
DECLARE_CLIENTCLASS();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
private:
float m_flCheapWaterStartDistance;
float m_flCheapWaterEndDistance;
};
IMPLEMENT_CLIENTCLASS_DT(C_WaterLODControl, DT_WaterLODControl, CWaterLODControl)
RecvPropFloat(RECVINFO(m_flCheapWaterStartDistance)),
RecvPropFloat(RECVINFO(m_flCheapWaterEndDistance)),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_WaterLODControl::OnDataChanged(DataUpdateType_t updateType)
{
view->SetCheapWaterStartDistance( m_flCheapWaterStartDistance );
view->SetCheapWaterEndDistance( m_flCheapWaterEndDistance );
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_WaterLODControl::ShouldDraw()
{
return false;
}

View File

@ -0,0 +1,231 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility code.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "IEffects.h"
#include "fx.h"
#include "c_te_legacytempents.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Client-server neutral effects interface
//-----------------------------------------------------------------------------
class CEffectsClient : public IEffects
{
public:
CEffectsClient();
virtual ~CEffectsClient();
// Members of the IEffect interface
virtual void Beam( const Vector &Start, const Vector &End, int nModelIndex,
int nHaloIndex, unsigned char frameStart, unsigned char frameRate,
float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength,
unsigned char noise, unsigned char red, unsigned char green,
unsigned char blue, unsigned char brightness, unsigned char speed);
virtual void Smoke( const Vector &origin, int modelIndex, float scale, float framerate );
virtual void Sparks( const Vector &position, int nMagnitude = 1, int nTrailLength = 1, const Vector *pvecDir = NULL );
virtual void Dust( const Vector &pos, const Vector &dir, float size, float speed );
virtual void MuzzleFlash( const Vector &origin, const QAngle &angles, float fScale, int type );
virtual void MetalSparks( const Vector &position, const Vector &direction );
virtual void EnergySplash( const Vector &position, const Vector &direction, bool bExplosive = false );
virtual void Ricochet( const Vector &position, const Vector &direction );
// FIXME: Should these methods remain in this interface? Or go in some
// other client-server neutral interface?
virtual float Time();
virtual bool IsServer();
virtual void SuppressEffectsSounds( bool bSuppress );
private:
//-----------------------------------------------------------------------------
// Purpose: Returning true means don't even call TE func
// Input : filter -
// *suppress_host -
// Output : static bool
//-----------------------------------------------------------------------------
bool SuppressTE( C_RecipientFilter& filter )
{
if ( !CanPredict() )
return true;
if ( !filter.GetRecipientCount() )
{
// Suppress it
return true;
}
// There's at least one recipient
return false;
}
bool m_bSuppressSound;
};
//-----------------------------------------------------------------------------
// Client-server neutral effects interface accessor
//-----------------------------------------------------------------------------
static CEffectsClient s_EffectClient;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEffectsClient, IEffects, IEFFECTS_INTERFACE_VERSION, s_EffectClient);
IEffects *g_pEffects = &s_EffectClient;
ConVar r_decals( "r_decals", "2048" );
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CEffectsClient::CEffectsClient()
{
m_bSuppressSound = false;
}
CEffectsClient::~CEffectsClient()
{
}
//-----------------------------------------------------------------------------
// Suppress sound on effects
//-----------------------------------------------------------------------------
void CEffectsClient::SuppressEffectsSounds( bool bSuppress )
{
m_bSuppressSound = bSuppress;
}
//-----------------------------------------------------------------------------
// Generates a beam
//-----------------------------------------------------------------------------
void CEffectsClient::Beam( const Vector &vecStartPoint, const Vector &vecEndPoint,
int nModelIndex, int nHaloIndex, unsigned char frameStart, unsigned char nFrameRate,
float flLife, unsigned char nWidth, unsigned char nEndWidth, unsigned char nFadeLength,
unsigned char noise, unsigned char r, unsigned char g,
unsigned char b, unsigned char brightness, unsigned char nSpeed)
{
Assert(0);
// CBroadcastRecipientFilter filter;
// if ( !SuppressTE( filter ) )
// {
// beams->CreateBeamPoints( vecStartPoint, vecEndPoint, nModelIndex, nHaloIndex,
// m_fHaloScale,
// flLife, 0.1 * nWidth, 0.1 * nEndWidth, nFadeLength, 0.01 * nAmplitude, a, 0.1 * nSpeed,
// m_nStartFrame, 0.1 * nFrameRate, r, g, b );
// }
}
//-----------------------------------------------------------------------------
// Generates various tempent effects
//-----------------------------------------------------------------------------
void CEffectsClient::Smoke( const Vector &vecOrigin, int modelIndex, float scale, float framerate )
{
CPVSFilter filter( vecOrigin );
if ( !SuppressTE( filter ) )
{
int iColor = random->RandomInt(20,35);
color32 color;
color.r = iColor;
color.g = iColor;
color.b = iColor;
color.a = iColor;
QAngle angles;
VectorAngles( Vector(0,0,1), angles );
FX_Smoke( vecOrigin, angles, scale * 0.1f, 4, (unsigned char *)&color, 255 );
}
}
void CEffectsClient::Sparks( const Vector &position, int nMagnitude, int nTrailLength, const Vector *pVecDir )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_ElectricSpark( position, nMagnitude, nTrailLength, pVecDir );
}
}
void CEffectsClient::Dust( const Vector &pos, const Vector &dir, float size, float speed )
{
CPVSFilter filter( pos );
if ( !SuppressTE( filter ) )
{
FX_Dust( pos, dir, size, speed );
}
}
void CEffectsClient::MuzzleFlash( const Vector &vecOrigin, const QAngle &vecAngles, float flScale, int iType )
{
CPVSFilter filter( vecOrigin );
if ( !SuppressTE( filter ) )
{
switch( iType )
{
case MUZZLEFLASH_TYPE_DEFAULT:
FX_MuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
break;
case MUZZLEFLASH_TYPE_GUNSHIP:
FX_GunshipMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
break;
case MUZZLEFLASH_TYPE_STRIDER:
FX_StriderMuzzleEffect( vecOrigin, vecAngles, flScale, INVALID_EHANDLE_INDEX );
break;
default:
Msg("No case for Muzzleflash type: %d\n", iType );
break;
}
}
}
void CEffectsClient::MetalSparks( const Vector &position, const Vector &direction )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_MetalSpark( position, direction, direction );
}
}
void CEffectsClient::EnergySplash( const Vector &position, const Vector &direction, bool bExplosive )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_EnergySplash( position, direction, bExplosive );
}
}
void CEffectsClient::Ricochet( const Vector &position, const Vector &direction )
{
CPVSFilter filter( position );
if ( !SuppressTE( filter ) )
{
FX_MetalSpark( position, direction, direction );
if ( !m_bSuppressSound )
{
FX_RicochetSound( position );
}
}
}
// FIXME: Should these methods remain in this interface? Or go in some
// other client-server neutral interface?
float CEffectsClient::Time()
{
return gpGlobals->curtime;
}
bool CEffectsClient::IsServer()
{
return false;
}

View File

@ -0,0 +1,56 @@
//========= Copyright © 1996-2007, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "FunctionProxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Returns the player health (from 0 to 1)
//-----------------------------------------------------------------------------
class CProxyIsNPC : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CProxyIsNPC::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CProxyIsNPC::OnBind( void *pC_BaseEntity )
{
if ( !pC_BaseEntity )
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
if ( pEntity && pEntity->IsNPC() )
{
SetFloatResult( m_Factor.GetFloat() );
}
else
{
SetFloatResult( 0.0f );
}
}
EXPOSE_MATERIAL_PROXY( CProxyIsNPC, IsNPC );

View File

@ -0,0 +1,65 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
// $monitorTextureVar
class CMonitorMaterialProxy : public IMaterialProxy
{
public:
CMonitorMaterialProxy();
virtual ~CMonitorMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
private:
IMaterialVar *m_pMonitorTextureVar;
};
CMonitorMaterialProxy::CMonitorMaterialProxy()
{
m_pMonitorTextureVar = NULL;
}
CMonitorMaterialProxy::~CMonitorMaterialProxy()
{
m_pMonitorTextureVar = NULL;
}
bool CMonitorMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pMonitorTextureVarName = pKeyValues->getString( "$monitorTextureVar" );
if( !pMonitorTextureVarName )
return false;
bool foundVar;
m_pMonitorTextureVar = pMaterial->FindVar( pMonitorTextureVarName, &foundVar, false );
if( !foundVar )
{
m_pMonitorTextureVar = NULL;
return false;
}
return true;
}
void CMonitorMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !m_pMonitorTextureVar )
{
return;
}
}
EXPOSE_MATERIAL_PROXY( CMonitorMaterialProxy, Monitor );

101
game/client/NPSClient.h Normal file
View File

@ -0,0 +1,101 @@
// *******************************************************************************
// *
// * Module Name:
// * NPSClient.h
// *
// * Abstract:
// * Header for NaturalPoint Simple Game Client API.
// *
// * Environment:
// * Microsoft Windows -- User mode
// *
// *******************************************************************************
#ifndef _NPSCLIENT_H_DEFINED_
#define _NPSCLIENT_H_DEFINED_
#pragma pack( push, npsclient_h ) // Save current pack value
#pragma pack(1)
#ifdef __cplusplus
extern "C"{
#endif
//////////////////
/// Typedefs /////////////////////////////////////////////////////////////////////
/////////////////
#ifndef _NPCLIENT_H_DEFINED_
// NPESULT values are returned from the Game Client API functions.
//
typedef enum tagNPResult
{
NP_OK = 0,
NP_ERR_DEVICE_NOT_PRESENT,
NP_ERR_UNSUPPORTED_OS,
NP_ERR_INVALID_ARG,
NP_ERR_DLL_NOT_FOUND,
NP_ERR_NO_DATA,
NP_ERR_INTERNAL_DATA,
NP_ERR_ALREADY_REGISTERED, // a window handle or game ID is already registered
NP_ERR_UNKNOWN_ID, // unknown game ID registered
NP_ERR_READ_ONLY, // parameter is read only
} NPRESULT;
typedef struct tagTrackIRData
{
unsigned short wNPStatus;
unsigned short wPFrameSignature;
unsigned long dwNPIOData;
float fNPRoll;
float fNPPitch;
float fNPYaw;
float fNPX;
float fNPY;
float fNPZ;
float fNPRawX;
float fNPRawY;
float fNPRawZ;
float fNPDeltaX;
float fNPDeltaY;
float fNPDeltaZ;
float fNPSmoothX;
float fNPSmoothY;
float fNPSmoothZ;
} TRACKIRDATA, *LPTRACKIRDATA;
#endif
typedef NPRESULT (__stdcall *PF_NPS_INIT)( HWND );
typedef NPRESULT (__stdcall *PF_NPS_SHUTDOWN)( void );
typedef NPRESULT (__stdcall *PF_NPS_GETDATA)( LPTRACKIRDATA );
//// Function Prototypes ///////////////////////////////////////////////
//
// Functions exported from game client API DLL ( note __stdcall calling convention
// is used for ease of interface to clients of differing implementations including
// C, C++, Pascal (Delphi) and VB. )
//
NPRESULT __stdcall NPS_Init( HWND hWnd );
NPRESULT __stdcall NPS_Shutdown( void );
NPRESULT __stdcall NPS_GetData( LPTRACKIRDATA pTID );
/////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif
#pragma pack( pop, npsclient_h ) // Ensure previous pack value is restored
#endif // #ifdef NPCLIENT_H_DEFINED_
//
// *** End of file: NPSClient.h ***
//

View File

@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "FunctionProxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Returns the player health (from 0 to 1)
//-----------------------------------------------------------------------------
class CProxyHealth : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
CFloatInput m_Factor;
};
bool CProxyHealth::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
if (!m_Factor.Init( pMaterial, pKeyValues, "scale", 1 ))
return false;
return true;
}
void CProxyHealth::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Assert( m_pResult );
SetFloatResult( pEntity->HealthFraction() * m_Factor.GetFloat() );
}
EXPOSE_MATERIAL_PROXY( CProxyHealth, Health );

View File

@ -0,0 +1,316 @@
#include "cbase.h"
#include "keyvalues.h"
#include "cdll_client_int.h"
#include "view_scene.h"
#include "viewrender.h"
#include "tier0/icommandline.h"
#include "materialsystem/IMesh.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialSystemHardwareConfig.h"
#include "materialsystem/IMaterialVar.h"
#include "ScreenSpaceEffects.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// CScreenSpaceEffectRegistration code
// Used to register and effect with the IScreenSpaceEffectManager
//------------------------------------------------------------------------------
CScreenSpaceEffectRegistration *CScreenSpaceEffectRegistration::s_pHead = NULL;
CScreenSpaceEffectRegistration::CScreenSpaceEffectRegistration( const char *pName, IScreenSpaceEffect *pEffect )
{
m_pEffectName = pName;
m_pEffect = pEffect;
m_pNext = s_pHead;
s_pHead = this;
}
//------------------------------------------------------------------------------
// CScreenSpaceEffectManager - Implementation of IScreenSpaceEffectManager
//------------------------------------------------------------------------------
class CScreenSpaceEffectManager : public IScreenSpaceEffectManager
{
public:
virtual void InitScreenSpaceEffects( );
virtual void ShutdownScreenSpaceEffects( );
virtual IScreenSpaceEffect *GetScreenSpaceEffect( const char *pEffectName );
virtual void SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params );
virtual void SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params );
virtual void EnableScreenSpaceEffect( const char *pEffectName );
virtual void EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect );
virtual void DisableScreenSpaceEffect( const char *pEffectName );
virtual void DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect );
virtual void DisableAllScreenSpaceEffects( );
virtual void RenderEffects( int x, int y, int w, int h );
};
CScreenSpaceEffectManager g_ScreenSpaceEffectManager;
IScreenSpaceEffectManager *g_pScreenSpaceEffects = &g_ScreenSpaceEffectManager;
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::InitScreenSpaceEffects - Initialise all registered effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::InitScreenSpaceEffects( )
{
if ( CommandLine()->FindParm( "-filmgrain" ) )
{
GetScreenSpaceEffect( "filmgrain" )->Enable( true );
}
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
bool bIsEnabled = pEffect->IsEnabled( );
pEffect->Init( );
pEffect->Enable( bIsEnabled );
}
}
}
//----------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::ShutdownScreenSpaceEffects - Shutdown all registered effects
//----------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::ShutdownScreenSpaceEffects( )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Shutdown( );
}
}
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::GetScreenSpaceEffect - Returns a point to the named effect
//---------------------------------------------------------------------------------------
IScreenSpaceEffect *CScreenSpaceEffectManager::GetScreenSpaceEffect( const char *pEffectName )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
if( !Q_stricmp( pReg->m_pEffectName, pEffectName ) )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
return pEffect;
}
}
Warning( "Could not find screen space effect %s\n", pEffectName );
return NULL;
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::SetScreenSpaceEffectParams
// - Assign parameters to the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
SetScreenSpaceEffectParams( pEffect, params );
}
void CScreenSpaceEffectManager::SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params )
{
if( pEffect )
pEffect->SetParameters( params );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::EnableScreenSpaceEffect
// - Enables the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::EnableScreenSpaceEffect( const char *pEffectName )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
EnableScreenSpaceEffect( pEffect );
}
void CScreenSpaceEffectManager::EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect )
{
if( pEffect )
pEffect->Enable( true );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::DisableScreenSpaceEffect
// - Disables the specified effect
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::DisableScreenSpaceEffect( const char *pEffectName )
{
IScreenSpaceEffect *pEffect = GetScreenSpaceEffect( pEffectName );
if( pEffect )
DisableScreenSpaceEffect( pEffect );
}
void CScreenSpaceEffectManager::DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect )
{
if( pEffect )
pEffect->Enable( false );
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::DisableAllScreenSpaceEffects
// - Disables all registered screen space effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::DisableAllScreenSpaceEffects( )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Enable( false );
}
}
}
//---------------------------------------------------------------------------------------
// CScreenSpaceEffectManager::RenderEffects
// - Renders all registered screen space effects
//---------------------------------------------------------------------------------------
void CScreenSpaceEffectManager::RenderEffects( int x, int y, int w, int h )
{
for( CScreenSpaceEffectRegistration *pReg=CScreenSpaceEffectRegistration::s_pHead; pReg!=NULL; pReg=pReg->m_pNext )
{
IScreenSpaceEffect *pEffect = pReg->m_pEffect;
if( pEffect )
{
pEffect->Render( x, y, w, h );
}
}
}
//------------------------------------------------------------------------------
// Example post-processing effect
//------------------------------------------------------------------------------
class CExampleEffect : public IScreenSpaceEffect
{
public:
CExampleEffect( );
~CExampleEffect( );
void Init( );
void Shutdown( );
void SetParameters( KeyValues *params );
void Render( int x, int y, int w, int h );
void Enable( bool bEnable );
bool IsEnabled( );
private:
bool m_bEnable;
CMaterialReference m_Material;
};
ADD_SCREENSPACE_EFFECT( CExampleEffect, exampleeffect );
//------------------------------------------------------------------------------
// CExampleEffect constructor
//------------------------------------------------------------------------------
CExampleEffect::CExampleEffect( )
{
m_bEnable = false;
}
//------------------------------------------------------------------------------
// CExampleEffect destructor
//------------------------------------------------------------------------------
CExampleEffect::~CExampleEffect( )
{
}
//------------------------------------------------------------------------------
// CExampleEffect init
//------------------------------------------------------------------------------
void CExampleEffect::Init( )
{
// This is just example code, init your effect material here
//m_Material.Init( "engine/exampleeffect", TEXTURE_GROUP_OTHER );
m_bEnable = false;
}
//------------------------------------------------------------------------------
// CExampleEffect shutdown
//------------------------------------------------------------------------------
void CExampleEffect::Shutdown( )
{
m_Material.Shutdown();
}
//------------------------------------------------------------------------------
// CExampleEffect enable
//------------------------------------------------------------------------------
void CExampleEffect::Enable( bool bEnable )
{
// This is just example code, don't enable it
// m_bEnable = bEnable;
}
bool CExampleEffect::IsEnabled( )
{
return m_bEnable;
}
//------------------------------------------------------------------------------
// CExampleEffect SetParameters
//------------------------------------------------------------------------------
void CExampleEffect::SetParameters( KeyValues *params )
{
if( params->GetDataType( "example_param" ) == KeyValues::TYPE_STRING )
{
// ...
}
}
//------------------------------------------------------------------------------
// CExampleEffect render
//------------------------------------------------------------------------------
void CExampleEffect::Render( int x, int y, int w, int h )
{
if ( !IsEnabled() )
return;
// Render Effect
Rect_t actualRect;
UpdateScreenEffectTexture( 0, x, y, w, h, false, &actualRect );
ITexture *pTexture = GetFullFrameFrameBufferTexture( 0 );
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->DrawScreenSpaceRectangle( m_Material, x, y, w, h,
actualRect.x, actualRect.y, actualRect.x+actualRect.width-1, actualRect.y+actualRect.height-1,
pTexture->GetActualWidth(), pTexture->GetActualHeight() );
}

View File

@ -0,0 +1,88 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=====================================================================================//
#ifndef SCREENSPACEEFFECTS_H
#define SCREENSPACEEFFECTS_H
#ifdef _WIN32
#pragma once
#endif
class KeyValues;
//------------------------------------------------------------------------------
// Simple base class for screen space post-processing effects
//------------------------------------------------------------------------------
abstract_class IScreenSpaceEffect
{
public:
virtual void Init( ) = 0;
virtual void Shutdown( ) = 0;
virtual void SetParameters( KeyValues *params ) = 0;
virtual void Render( int x, int y, int w, int h ) = 0;
virtual void Enable( bool bEnable ) = 0;
virtual bool IsEnabled( ) = 0;
};
//------------------------------------------------------------------------------
// Interface class for managing screen space post-processing effects
//------------------------------------------------------------------------------
abstract_class IScreenSpaceEffectManager
{
public:
virtual void InitScreenSpaceEffects( ) = 0;
virtual void ShutdownScreenSpaceEffects( ) = 0;
virtual IScreenSpaceEffect *GetScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void SetScreenSpaceEffectParams( const char *pEffectName, KeyValues *params ) = 0;
virtual void SetScreenSpaceEffectParams( IScreenSpaceEffect *pEffect, KeyValues *params ) = 0;
virtual void EnableScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void EnableScreenSpaceEffect( IScreenSpaceEffect *pEffect ) = 0;
virtual void DisableScreenSpaceEffect( const char *pEffectName ) = 0;
virtual void DisableScreenSpaceEffect( IScreenSpaceEffect *pEffect ) = 0;
virtual void DisableAllScreenSpaceEffects( ) = 0;
virtual void RenderEffects( int x, int y, int w, int h ) = 0;
};
extern IScreenSpaceEffectManager *g_pScreenSpaceEffects;
//-------------------------------------------------------------------------------------
// Registration class for adding screen space effects to the IScreenSpaceEffectManager
//-------------------------------------------------------------------------------------
class CScreenSpaceEffectRegistration
{
public:
CScreenSpaceEffectRegistration( const char *pName, IScreenSpaceEffect *pEffect );
const char *m_pEffectName;
IScreenSpaceEffect *m_pEffect;
CScreenSpaceEffectRegistration *m_pNext;
static CScreenSpaceEffectRegistration *s_pHead;
};
#define ADD_SCREENSPACE_EFFECT( CEffect, pEffectName ) CEffect pEffectName##_effect; \
CScreenSpaceEffectRegistration pEffectName##_reg( #pEffectName, &pEffectName##_effect );
#endif

View File

@ -0,0 +1,172 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "teambitmapimage.h"
#include <KeyValues.h>
#include "vgui_BitmapImage.h"
#include "PanelMetaClassMgr.h"
#include "vguimatsurface/IMatSystemSurface.h"
#include <vgui_controls/Panel.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// A multiplexer bitmap that chooses a bitmap based on team
//-----------------------------------------------------------------------------
CTeamBitmapImage::CTeamBitmapImage() : m_Alpha(1.0f)
{
memset( m_ppImage, 0, BITMAP_COUNT * sizeof(BitmapImage*) );
m_pEntity = NULL;
m_bRelativeTeams = 0;
}
CTeamBitmapImage::~CTeamBitmapImage()
{
int i;
for ( i = 0; i < BITMAP_COUNT; ++i )
{
if (m_ppImage[i])
delete m_ppImage[i];
}
}
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
bool CTeamBitmapImage::Init( vgui::Panel *pParent, KeyValues* pInitData, C_BaseEntity* pEntity )
{
static char *pRelativeTeamNames[BITMAP_COUNT] =
{
"NoTeam",
"MyTeam",
"EnemyTeam",
};
static char *pAbsoluteTeamNames[BITMAP_COUNT] =
{
"Team0",
"Team1",
"Team2",
};
m_pEntity = pEntity;
m_bRelativeTeams = (pInitData->GetInt( "relativeteam" ) != 0);
char **ppTeamNames = m_bRelativeTeams ? pRelativeTeamNames : pAbsoluteTeamNames;
int i;
for ( i = 0 ; i < BITMAP_COUNT; ++i )
{
// Default to null
m_ppImage[i] = NULL;
// Look for team section
KeyValues *pTeamKV = pInitData->FindKey( ppTeamNames[i] );
if ( !pTeamKV )
continue;
char const* pClassImage = pTeamKV->GetString( "material" );
if ( !pClassImage || !pClassImage[ 0 ] )
return false;
// modulation color
Color color;
if (!ParseRGBA( pTeamKV, "color", color ))
color.SetColor( 255, 255, 255, 255 );
// hook in the bitmap
m_ppImage[i] = new BitmapImage( pParent->GetVPanel(), pClassImage );
m_ppImage[i]->SetColor( color );
}
return true;
}
//-----------------------------------------------------------------------------
// Alpha modulate...
//-----------------------------------------------------------------------------
void CTeamBitmapImage::SetAlpha( float alpha )
{
m_Alpha = clamp( alpha, 0.0f, 1.0f );
}
//-----------------------------------------------------------------------------
// draw
//-----------------------------------------------------------------------------
void CTeamBitmapImage::Paint( float yaw /*= 0.0f*/ )
{
if (m_Alpha == 0.0f)
return;
int team = 0;
if (m_bRelativeTeams)
{
if (GetEntity())
{
if (GetEntity()->GetTeamNumber() != 0)
{
team = GetEntity()->InLocalTeam() ? 1 : 2;
}
}
}
else
{
if (GetEntity())
team = GetEntity()->GetTeamNumber();
}
// Paint the image for the current team
if (m_ppImage[team])
{
// Modulate the color based on the alpha....
Color color = m_ppImage[team]->GetColor();
int alpha = color[3];
color[3] = (alpha * m_Alpha);
m_ppImage[team]->SetColor( color );
if ( yaw != 0.0f )
{
g_pMatSystemSurface->DisableClipping( true );
m_ppImage[team]->DoPaint( m_ppImage[team]->GetRenderSizePanel(), yaw );
g_pMatSystemSurface->DisableClipping( false );
}
else
{
// Paint
m_ppImage[team]->Paint();
}
// restore previous color
color[3] = alpha;
m_ppImage[team]->SetColor( color );
}
}
//-----------------------------------------------------------------------------
// Helper method to initialize a team image from KeyValues data..
//-----------------------------------------------------------------------------
bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName, vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pTeamImage )
{
KeyValues *pTeamImageSection = pInitData;
if (pSectionName)
{
pTeamImageSection = pInitData->FindKey( pSectionName );
if ( !pTeamImageSection )
return false;
}
return pTeamImage->Init( pParent, pTeamImageSection, pEntity );
}

View File

@ -0,0 +1,80 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef TEAMBITMAPIMAGE_H
#define TEAMBITMAPIMAGE_H
#ifdef _WIN32
#pragma once
#endif
//#include "tf_shareddefs.h"
#include <vgui/VGUI.h>
namespace vgui
{
class Panel;
}
class BitmapImage;
class C_BaseEntity;
class KeyValues;
//-----------------------------------------------------------------------------
// A multiplexer bitmap that chooses a bitmap based on team
//-----------------------------------------------------------------------------
class CTeamBitmapImage
{
public:
// construction, destruction
CTeamBitmapImage();
~CTeamBitmapImage();
// initialization
bool Init( vgui::Panel *pParent, KeyValues* pInitData, C_BaseEntity* pEntity );
// Alpha override...
void SetAlpha( float alpha );
// Paint the sucka. Paint it the size of the parent panel
void Paint( float yaw = 0.0f );
protected:
// Wrapper so we can implement this with EHANDLES some day
C_BaseEntity *GetEntity() { return m_pEntity; }
private:
enum
{
// NOTE: Was MAX_TF_TEAMS not 4, but I don't like the dependency here.
BITMAP_COUNT = 4 + 1
};
BitmapImage *m_ppImage[ BITMAP_COUNT ];
C_BaseEntity *m_pEntity;
float m_Alpha;
bool m_bRelativeTeams;
};
//-----------------------------------------------------------------------------
// Helper method to initialize a team image from KeyValues data..
// KeyValues contains the bitmap data. pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeTeamImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, C_BaseEntity *pEntity, CTeamBitmapImage* pBitmapImage );
#endif // TEAMBITMAPIMAGE_H

View File

@ -0,0 +1,83 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which is rendered image on top of an entity
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ViewConeImage.h"
#include <KeyValues.h>
#include <vgui_controls/Panel.h>
#include "vguimatsurface/IMatSystemSurface.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
bool CViewConeImage::Init( vgui::Panel *pParent, KeyValues* pInitData )
{
Assert( pParent );
// Load viewcone material
if (!m_Image.Init( pParent->GetVPanel(), pInitData ))
return false;
// Position the view cone...
int viewconesize = pInitData->GetInt( "size", 32 );
m_Image.SetRenderSize( viewconesize, viewconesize );
int cx, cy;
pParent->GetSize( cx, cy );
m_Image.SetPos( (cx - viewconesize) / 2, (cy - viewconesize) / 2 );
return true;
}
//-----------------------------------------------------------------------------
// Paint the sucka
//-----------------------------------------------------------------------------
void CViewConeImage::Paint( float yaw )
{
g_pMatSystemSurface->DisableClipping( true );
m_Image.DoPaint( NULL, yaw );
g_pMatSystemSurface->DisableClipping( false );
}
void CViewConeImage::SetColor( int r, int g, int b )
{
m_Image.SetColor( Color( r, g, b, 255 ) );
}
//-----------------------------------------------------------------------------
// Helper method to initialize a view cone image from KeyValues data..
// KeyValues contains the bitmap data, pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage )
{
KeyValues *pViewConeImageSection;
if (pSectionName)
{
pViewConeImageSection = pInitData->FindKey( pSectionName );
if ( !pViewConeImageSection )
return false;
}
else
{
pViewConeImageSection = pInitData;
}
return pViewConeImage->Init( pParent, pViewConeImageSection );
}

View File

@ -0,0 +1,56 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: This is a panel which draws a viewcone
//
// $Revision: $
// $NoKeywords: $
//=============================================================================//
#ifndef VIEWCONEIMAGE_H
#define VIEWCONEIMAGE_H
#include "shareddefs.h"
#include "VGUI_BitmapImage.h"
namespace vgui
{
class Panel;
}
class C_BaseEntity;
class KeyValues;
//-----------------------------------------------------------------------------
// A bitmap that renders a view cone based on angles
//-----------------------------------------------------------------------------
class CViewConeImage
{
public:
// initialization
bool Init( vgui::Panel *pParent, KeyValues* pInitData );
// Paint the sucka
void Paint( float yaw );
void SetColor( int r, int g, int b );
private:
BitmapImage m_Image;
};
//-----------------------------------------------------------------------------
// Helper method to initialize a view cone image from KeyValues data..
// KeyValues contains the bitmap data, pSectionName, if it exists,
// indicates which subsection of pInitData should be looked at to get at the
// image data. The final argument is the bitmap image to initialize.
// The function returns true if it succeeded.
//
// NOTE: This function looks for the key values 'material' and 'color'
// and uses them to set up the material + modulation color of the image
//-----------------------------------------------------------------------------
bool InitializeViewConeImage( KeyValues *pInitData, const char* pSectionName,
vgui::Panel *pParent, CViewConeImage* pViewConeImage );
#endif // VIEWCONEIMAGE_H

View File

@ -0,0 +1,75 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "iviewrender.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// no inputs, assumes that the results go into $CHEAPWATERSTARTDISTANCE and $CHEAPWATERENDDISTANCE
class CWaterLODMaterialProxy : public IMaterialProxy
{
public:
CWaterLODMaterialProxy();
virtual ~CWaterLODMaterialProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
private:
IMaterialVar *m_pCheapWaterStartDistanceVar;
IMaterialVar *m_pCheapWaterEndDistanceVar;
};
CWaterLODMaterialProxy::CWaterLODMaterialProxy()
{
m_pCheapWaterStartDistanceVar = NULL;
m_pCheapWaterEndDistanceVar = NULL;
}
CWaterLODMaterialProxy::~CWaterLODMaterialProxy()
{
}
bool CWaterLODMaterialProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool foundVar;
m_pCheapWaterStartDistanceVar = pMaterial->FindVar( "$CHEAPWATERSTARTDISTANCE", &foundVar, false );
if( !foundVar )
return false;
m_pCheapWaterEndDistanceVar = pMaterial->FindVar( "$CHEAPWATERENDDISTANCE", &foundVar, false );
if( !foundVar )
return false;
return true;
}
void CWaterLODMaterialProxy::OnBind( void *pC_BaseEntity )
{
if( !m_pCheapWaterStartDistanceVar || !m_pCheapWaterEndDistanceVar )
{
return;
}
float start, end;
view->GetWaterLODParams( start, end );
m_pCheapWaterStartDistanceVar->SetFloatValue( start );
m_pCheapWaterEndDistanceVar->SetFloatValue( end );
}
IMaterial *CWaterLODMaterialProxy::GetMaterial()
{
return m_pCheapWaterStartDistanceVar->GetOwningMaterial();
}
EXPOSE_MATERIAL_PROXY( CWaterLODMaterialProxy, WaterLOD );

View File

@ -0,0 +1,70 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "c_world.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CWorldDimsProxy : public IMaterialProxy
{
public:
CWorldDimsProxy();
virtual ~CWorldDimsProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
public:
IMaterialVar *m_pMinsVar;
IMaterialVar *m_pMaxsVar;
};
CWorldDimsProxy::CWorldDimsProxy()
{
m_pMinsVar = m_pMaxsVar = NULL;
}
CWorldDimsProxy::~CWorldDimsProxy()
{
}
bool CWorldDimsProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMinsVar = pMaterial->FindVar( "$world_mins", NULL, false );
m_pMaxsVar = pMaterial->FindVar( "$world_maxs", NULL, false );
return true;
}
void CWorldDimsProxy::OnBind( void *pC_BaseEntity )
{
if ( m_pMinsVar && m_pMaxsVar )
{
C_World *pWorld = GetClientWorldEntity();
if ( pWorld )
{
m_pMinsVar->SetVecValue( (const float*)&pWorld->m_WorldMins, 3 );
m_pMaxsVar->SetVecValue( (const float*)&pWorld->m_WorldMaxs, 3 );
}
}
}
IMaterial *CWorldDimsProxy::GetMaterial()
{
return m_pMinsVar->GetOwningMaterial();
}
EXPOSE_MATERIAL_PROXY( CWorldDimsProxy, WorldDims );

View File

@ -0,0 +1,272 @@
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "hud.h"
#include "hud_macros.h"
#include "hudelement.h"
#include "iclientmode.h"
#include "ienginevgui.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGUI.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/Label.h>
#include <vgui_controls/ImagePanel.h>
#include "achievement_notification_panel.h"
#include "steam/steam_api.h"
#include "iachievementmgr.h"
#include "fmtstr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
#define ACHIEVEMENT_NOTIFICATION_DURATION 10.0f
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
// DECLARE_HUDELEMENT_DEPTH( CAchievementNotificationPanel, 100 );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CAchievementNotificationPanel::CAchievementNotificationPanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "AchievementNotificationPanel" )
{
Panel *pParent = GetClientMode()->GetViewport();
SetParent( pParent );
m_flHideTime = 0;
m_pPanelBackground = new EditablePanel( this, "Notification_Background" );
m_pIcon = new ImagePanel( this, "Notification_Icon" );
m_pLabelHeading = new Label( this, "HeadingLabel", "" );
m_pLabelTitle = new Label( this, "TitleLabel", "" );
m_pIcon->SetShouldScaleImage( true );
vgui::ivgui()->AddTickSignal( GetVPanel() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::Init()
{
ListenForGameEvent( "achievement_event" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::ApplySchemeSettings( IScheme *pScheme )
{
// load control settings...
LoadControlSettings( "resource/UI/AchievementNotification.res" );
BaseClass::ApplySchemeSettings( pScheme );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::PerformLayout( void )
{
BaseClass::PerformLayout();
// Set background color of various elements. Need to do this in code, if we do it in res file it gets slammed by the
// scheme. (Incl. label background: some products don't have label background colors set in their scheme and helpfully slam it to white.)
SetBgColor( Color( 0, 0, 0, 0 ) );
m_pLabelHeading->SetBgColor( Color( 0, 0, 0, 0 ) );
m_pLabelTitle->SetBgColor( Color( 0, 0, 0, 0 ) );
m_pPanelBackground->SetBgColor( Color( 62,70,55, 200 ) );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::FireGameEvent( IGameEvent * event )
{
const char *name = event->GetName();
if ( 0 == Q_strcmp( name, "achievement_event" ) )
{
const char *pchName = event->GetString( "achievement_name" );
int iCur = event->GetInt( "cur_val" );
int iMax = event->GetInt( "max_val" );
wchar_t szLocalizedName[256]=L"";
if ( IsPC() )
{
// shouldn't ever get achievement progress if steam not running and user logged in, but check just in case
if ( !steamapicontext->SteamUserStats() )
{
Msg( "Steam not running, achievement progress notification not displayed\n" );
}
else
{
// use Steam to show achievement progress UI
steamapicontext->SteamUserStats()->IndicateAchievementProgress( pchName, iCur, iMax );
}
}
else
{
// on X360 we need to show our own achievement progress UI
const wchar_t *pchLocalizedName = ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( pchName );
Assert( pchLocalizedName );
if ( !pchLocalizedName || !pchLocalizedName[0] )
return;
Q_wcsncpy( szLocalizedName, pchLocalizedName, sizeof( szLocalizedName ) );
// this is achievement progress, compose the message of form: "<name> (<#>/<max>)"
wchar_t szFmt[128]=L"";
wchar_t szText[512]=L"";
wchar_t szNumFound[16]=L"";
wchar_t szNumTotal[16]=L"";
_snwprintf( szNumFound, ARRAYSIZE( szNumFound ), L"%i", iCur );
_snwprintf( szNumTotal, ARRAYSIZE( szNumTotal ), L"%i", iMax );
const wchar_t *pchFmt = g_pVGuiLocalize->Find( "#GameUI_Achievement_Progress_Fmt" );
if ( !pchFmt || !pchFmt[0] )
return;
Q_wcsncpy( szFmt, pchFmt, sizeof( szFmt ) );
g_pVGuiLocalize->ConstructString( szText, sizeof( szText ), szFmt, 3, szLocalizedName, szNumFound, szNumTotal );
AddNotification( pchName, g_pVGuiLocalize->FindSafe( "#GameUI_Achievement_Progress" ), szText );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Called on each tick
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::OnTick( void )
{
if ( ( m_flHideTime > 0 ) && ( m_flHideTime < gpGlobals->curtime ) )
{
m_flHideTime = 0;
ShowNextNotification();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CAchievementNotificationPanel::ShouldDraw( void )
{
return ( ( m_flHideTime > 0 ) && ( m_flHideTime > gpGlobals->curtime ) && CHudElement::ShouldDraw() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::AddNotification( const char *szIconBaseName, const wchar_t *pHeading, const wchar_t *pTitle )
{
// put this notification in our queue
int iQueueItem = m_queueNotification.AddToTail();
Notification_t &notification = m_queueNotification[iQueueItem];
Q_strncpy( notification.szIconBaseName, szIconBaseName, ARRAYSIZE( notification.szIconBaseName ) );
Q_wcsncpy( notification.szHeading, pHeading, sizeof( notification.szHeading ) );
Q_wcsncpy( notification.szTitle, pTitle, sizeof( notification.szTitle ) );
// if we are not currently displaying a notification, go ahead and show this one
if ( 0 == m_flHideTime )
{
ShowNextNotification();
}
}
//-----------------------------------------------------------------------------
// Purpose: Shows next notification in queue if there is one
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::ShowNextNotification()
{
// see if we have anything to do
if ( 0 == m_queueNotification.Count() )
{
m_flHideTime = 0;
return;
}
Notification_t &notification = m_queueNotification[ m_queueNotification.Head() ];
m_flHideTime = gpGlobals->curtime + ACHIEVEMENT_NOTIFICATION_DURATION;
// set the text and icon in the dialog
SetDialogVariable( "heading", notification.szHeading );
SetDialogVariable( "title", notification.szTitle );
const char *pchIconBaseName = notification.szIconBaseName;
if ( pchIconBaseName && pchIconBaseName[0] )
{
m_pIcon->SetImage( CFmtStr( "achievements/%s.vmt", pchIconBaseName ) );
}
// resize the panel so it always looks good
// get fonts
HFont hFontHeading = m_pLabelHeading->GetFont();
HFont hFontTitle = m_pLabelTitle->GetFont();
// determine how wide the text strings are
int iHeadingWidth = UTIL_ComputeStringWidth( hFontHeading, notification.szHeading );
int iTitleWidth = UTIL_ComputeStringWidth( hFontTitle, notification.szTitle );
// use the widest string
int iTextWidth = MAX( iHeadingWidth, iTitleWidth );
// don't let it be insanely wide
iTextWidth = MIN( iTextWidth, XRES( 300 ) );
int iIconWidth = m_pIcon->GetWide();
int iSpacing = XRES( 10 );
int iPanelWidth = iSpacing + iIconWidth + iSpacing + iTextWidth + iSpacing;
int iPanelX = GetWide() - iPanelWidth;
int iIconX = iPanelX + iSpacing;
int iTextX = iIconX + iIconWidth + iSpacing;
// resize all the elements
SetXAndWide( m_pPanelBackground, iPanelX, iPanelWidth );
SetXAndWide( m_pIcon, iIconX, iIconWidth );
SetXAndWide( m_pLabelHeading, iTextX, iTextWidth );
SetXAndWide( m_pLabelTitle, iTextX, iTextWidth );
m_queueNotification.Remove( m_queueNotification.Head() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CAchievementNotificationPanel::SetXAndWide( Panel *pPanel, int x, int wide )
{
int xCur, yCur;
pPanel->GetPos( xCur, yCur );
pPanel->SetPos( x, yCur );
pPanel->SetWide( wide );
}
CON_COMMAND_F( achievement_notification_test, "Test the hud notification UI", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY )
{
static int iCount=0;
CAchievementNotificationPanel *pPanel = GET_HUDELEMENT( CAchievementNotificationPanel );
if ( pPanel )
{
pPanel->AddNotification( "HL2_KILL_ODESSAGUNSHIP", L"Achievement Progress", ( 0 == ( iCount % 2 ) ? L"Test Notification Message A (1/10)" :
L"Test Message B" ) );
}
#if 0
IGameEvent *event = gameeventmanager->CreateEvent( "achievement_event" );
if ( event )
{
const char *szTestStr[] = { "TF_GET_HEADSHOTS", "TF_PLAY_GAME_EVERYMAP", "TF_PLAY_GAME_EVERYCLASS", "TF_GET_HEALPOINTS" };
event->SetString( "achievement_name", szTestStr[iCount%ARRAYSIZE(szTestStr)] );
event->SetInt( "cur_val", ( iCount%9 ) + 1 );
event->SetInt( "max_val", 10 );
gameeventmanager->FireEvent( event );
}
#endif
iCount++;
}

View File

@ -0,0 +1,57 @@
//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ACHIEVEMENT_NOTIFICATION_PANEL_H
#define ACHIEVEMENT_NOTIFICATION_PANEL_H
#ifdef _WIN32
#pragma once
#endif
#include <vgui_controls/EditablePanel.h>
#include "hudelement.h"
using namespace vgui;
class CAchievementNotificationPanel : public CHudElement, public EditablePanel
{
DECLARE_CLASS_SIMPLE( CAchievementNotificationPanel, EditablePanel );
public:
CAchievementNotificationPanel( const char *pElementName );
virtual void Init();
virtual void ApplySchemeSettings( IScheme *scheme );
virtual bool ShouldDraw( void );
virtual void PerformLayout( void );
virtual void LevelInit( void ) { m_flHideTime = 0; }
virtual void FireGameEvent( IGameEvent * event );
virtual void OnTick( void );
void AddNotification( const char *szIconBaseName, const wchar_t *pHeading, const wchar_t *pTitle );
private:
void ShowNextNotification();
void SetXAndWide( Panel *pPanel, int x, int wide );
float m_flHideTime;
Label *m_pLabelHeading;
Label *m_pLabelTitle;
EditablePanel *m_pPanelBackground;
ImagePanel *m_pIcon;
struct Notification_t
{
char szIconBaseName[255];
wchar_t szHeading[255];
wchar_t szTitle[255];
};
CUtlLinkedList<Notification_t> m_queueNotification;
};
#endif // ACHIEVEMENT_NOTIFICATION_PANEL_H

View File

@ -0,0 +1,52 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedEntityTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedEntityTextureProxy() {}
virtual ~CAnimatedEntityTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void AnimationWrapped( void* pC_BaseEntity );
};
EXPOSE_MATERIAL_PROXY( CAnimatedEntityTextureProxy, AnimatedEntityTexture );
float CAnimatedEntityTextureProxy::GetAnimationStartTime( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return 0.0f;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
return pEntity->GetTextureAnimationStartTime();
}
return 0.0f;
}
void CAnimatedEntityTextureProxy::AnimationWrapped( void* pArg )
{
IClientRenderable *pRend = (IClientRenderable *)pArg;
if (!pRend)
return;
C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity();
if (pEntity)
{
pEntity->TextureAnimationWrapped();
}
}

View File

@ -0,0 +1,57 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedOffsetTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedOffsetTextureProxy() : m_flFrameOffset( 0.0f ) {}
virtual ~CAnimatedOffsetTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
virtual void OnBind( void *pBaseEntity );
protected:
float m_flFrameOffset;
};
EXPOSE_MATERIAL_PROXY( CAnimatedOffsetTextureProxy, AnimatedOffsetTexture );
//-----------------------------------------------------------------------------
// Purpose:
// Input : pArg -
// Output : float
//-----------------------------------------------------------------------------
float CAnimatedOffsetTextureProxy::GetAnimationStartTime( void* pArg )
{
return m_flFrameOffset;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pBaseEntity -
//-----------------------------------------------------------------------------
void CAnimatedOffsetTextureProxy::OnBind( void *pBaseEntity )
{
C_BaseEntity* pEntity = (C_BaseEntity*)pBaseEntity;
if ( pEntity )
{
m_flFrameOffset = pEntity->GetTextureAnimationStartTime();
}
// Call into the base class
CBaseAnimatedTextureProxy::OnBind( pBaseEntity );
}

View File

@ -0,0 +1,30 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
#include "imaterialproxydict.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class CAnimatedTextureProxy : public CBaseAnimatedTextureProxy
{
public:
CAnimatedTextureProxy() {}
virtual ~CAnimatedTextureProxy() {}
virtual float GetAnimationStartTime( void* pBaseEntity );
};
EXPOSE_MATERIAL_PROXY( CAnimatedTextureProxy, AnimatedTexture );
#pragma warning (disable : 4100)
float CAnimatedTextureProxy::GetAnimationStartTime( void* pBaseEntity )
{
return 0;
}

View File

@ -0,0 +1,326 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef ANIMATIONLAYER_H
#define ANIMATIONLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "rangecheckedvar.h"
#include "tier1/lerp_functions.h"
#ifdef CLIENT_DLL
class C_BaseAnimatingOverlay;
#endif
class C_AnimationLayer
{
public:
// This allows the datatables to access private members.
ALLOW_DATATABLES_PRIVATE_ACCESS();
C_AnimationLayer();
void Reset();
#ifdef CLIENT_DLL
void SetOwner( C_BaseAnimatingOverlay *pOverlay );
C_BaseAnimatingOverlay *GetOwner() const;
#endif
void SetOrder( int order );
bool IsActive( void );
float GetFadeout( float flCurTime );
void SetSequence( int nSequence );
void SetCycle( float flCycle );
void SetPrevCycle( float flCycle );
void SetPlaybackRate( float flPlaybackRate );
void SetWeight( float flWeight );
int GetOrder() const;
int GetSequence( ) const;
float GetCycle( ) const;
float GetPrevCycle( ) const;
float GetPlaybackRate( ) const;
float GetWeight( ) const;
#ifdef CLIENT_DLL
// If the weights, cycle or sequence #s changed due to interpolation then
// we'll need to recompute the bbox
int GetInvalidatePhysicsBits() const;
void SetInvalidatePhysicsBits( int iBit ) { m_nInvalidatePhysicsBits = iBit; }
#endif
public:
float m_flLayerAnimtime;
float m_flLayerFadeOuttime;
private:
int m_nOrder;
CRangeCheckedVar<int, -1, 65535, 0> m_nSequence;
CRangeCheckedVar<float, -2, 2, 0> m_flPrevCycle;
CRangeCheckedVar<float, -5, 5, 0> m_flWeight;
// used for automatic crossfades between sequence changes
CRangeCheckedVar<float, -50, 50, 1> m_flPlaybackRate;
CRangeCheckedVar<float, -2, 2, 0> m_flCycle;
#ifdef CLIENT_DLL
C_BaseAnimatingOverlay *m_pOwner;
int m_nInvalidatePhysicsBits;
#endif
friend class C_BaseAnimatingOverlay;
friend C_AnimationLayer LoopingLerp( float flPercent, C_AnimationLayer& from, C_AnimationLayer& to );
friend C_AnimationLayer Lerp( float flPercent, const C_AnimationLayer& from, const C_AnimationLayer& to );
friend C_AnimationLayer LoopingLerp_Hermite( const C_AnimationLayer& current, float flPercent, C_AnimationLayer& prev, C_AnimationLayer& from, C_AnimationLayer& to );
friend C_AnimationLayer Lerp_Hermite( const C_AnimationLayer& current, float flPercent, const C_AnimationLayer& prev, const C_AnimationLayer& from, const C_AnimationLayer& to );
friend void Lerp_Clamp( C_AnimationLayer &val );
friend int CheckForSequenceBoxChanges( const C_AnimationLayer& newLayer, const C_AnimationLayer& oldLayer );
};
#ifdef CLIENT_DLL
#define CAnimationLayer C_AnimationLayer
#endif
inline C_AnimationLayer::C_AnimationLayer()
{
#ifdef CLIENT_DLL
m_pOwner = NULL;
m_nInvalidatePhysicsBits = 0;
#endif
Reset();
}
#ifdef GAME_DLL
inline void C_AnimationLayer::SetSequence( int nSequence )
{
m_nSequence = nSequence;
}
inline void C_AnimationLayer::SetCycle( float flCycle )
{
m_flCycle = flCycle;
}
inline void C_AnimationLayer::SetWeight( float flWeight )
{
m_flWeight = flWeight;
}
#endif // GAME_DLL
FORCEINLINE void C_AnimationLayer::SetPrevCycle( float flPrevCycle )
{
m_flPrevCycle = flPrevCycle;
}
FORCEINLINE void C_AnimationLayer::SetPlaybackRate( float flPlaybackRate )
{
m_flPlaybackRate = flPlaybackRate;
}
FORCEINLINE int C_AnimationLayer::GetSequence( ) const
{
return m_nSequence;
}
FORCEINLINE float C_AnimationLayer::GetCycle( ) const
{
return m_flCycle;
}
FORCEINLINE float C_AnimationLayer::GetPrevCycle( ) const
{
return m_flPrevCycle;
}
FORCEINLINE float C_AnimationLayer::GetPlaybackRate( ) const
{
return m_flPlaybackRate;
}
FORCEINLINE float C_AnimationLayer::GetWeight( ) const
{
return m_flWeight;
}
FORCEINLINE int C_AnimationLayer::GetOrder() const
{
return m_nOrder;
}
inline float C_AnimationLayer::GetFadeout( float flCurTime )
{
float s;
if (m_flLayerFadeOuttime <= 0.0f)
{
s = 0;
}
else
{
// blend in over 0.2 seconds
s = 1.0 - (flCurTime - m_flLayerAnimtime) / m_flLayerFadeOuttime;
if (s > 0 && s <= 1.0)
{
// do a nice spline curve
s = 3 * s * s - 2 * s * s * s;
}
else if ( s > 1.0f )
{
// Shouldn't happen, but maybe curtime is behind animtime?
s = 1.0f;
}
}
return s;
}
#ifdef CLIENT_DLL
FORCEINLINE int C_AnimationLayer::GetInvalidatePhysicsBits() const
{
return m_nInvalidatePhysicsBits;
}
#endif
inline C_AnimationLayer LoopingLerp( float flPercent, C_AnimationLayer& from, C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = LoopingLerp( flPercent, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
#endif
return output;
}
inline C_AnimationLayer Lerp( float flPercent, const C_AnimationLayer& from, const C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = Lerp( flPercent, from.m_flCycle, to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
#endif
return output;
}
inline int CheckForSequenceBoxChanges( const C_AnimationLayer& newLayer, const C_AnimationLayer& oldLayer )
{
int nChangeFlags = 0;
bool bOldIsZero = ( oldLayer.GetWeight() == 0.0f );
bool bNewIsZero = ( newLayer.GetWeight() == 0.0f );
if ( ( newLayer.GetSequence() != oldLayer.GetSequence() ) ||
( bNewIsZero != bOldIsZero ) )
{
nChangeFlags |= SEQUENCE_CHANGED | BOUNDS_CHANGED;
}
if ( newLayer.GetCycle() != oldLayer.GetCycle() )
{
nChangeFlags |= ANIMATION_CHANGED;
}
if ( newLayer.GetOrder() != oldLayer.GetOrder() )
{
nChangeFlags |= BOUNDS_CHANGED;
}
return nChangeFlags;
}
inline C_AnimationLayer LoopingLerp_Hermite( const C_AnimationLayer& current, float flPercent, C_AnimationLayer& prev, C_AnimationLayer& from, C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( prev.GetOwner() == from.GetOwner() );
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = LoopingLerp_Hermite( (float)current.m_flCycle, flPercent, (float)prev.m_flCycle, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
output.m_nInvalidatePhysicsBits = CheckForSequenceBoxChanges( output, current );
#endif
return output;
}
// YWB: Specialization for interpolating euler angles via quaternions...
inline C_AnimationLayer Lerp_Hermite( const C_AnimationLayer& current, float flPercent, const C_AnimationLayer& prev, const C_AnimationLayer& from, const C_AnimationLayer& to )
{
#ifdef CLIENT_DLL
Assert( prev.GetOwner() == from.GetOwner() );
Assert( from.GetOwner() == to.GetOwner() );
#endif
C_AnimationLayer output;
output.m_nSequence = to.m_nSequence;
output.m_flCycle = Lerp_Hermite( (float)current.m_flCycle, flPercent, (float)prev.m_flCycle, (float)from.m_flCycle, (float)to.m_flCycle );
output.m_flPrevCycle = to.m_flPrevCycle;
output.m_flWeight = Lerp( flPercent, from.m_flWeight, to.m_flWeight );
output.m_nOrder = to.m_nOrder;
output.m_flLayerAnimtime = to.m_flLayerAnimtime;
output.m_flLayerFadeOuttime = to.m_flLayerFadeOuttime;
#ifdef CLIENT_DLL
output.SetOwner( to.GetOwner() );
output.m_nInvalidatePhysicsBits = CheckForSequenceBoxChanges( output, current );
#endif
return output;
}
inline void Lerp_Clamp( C_AnimationLayer &val )
{
Lerp_Clamp( val.m_nSequence );
Lerp_Clamp( val.m_flCycle );
Lerp_Clamp( val.m_flPrevCycle );
Lerp_Clamp( val.m_flWeight );
Lerp_Clamp( val.m_nOrder );
Lerp_Clamp( val.m_flLayerAnimtime );
Lerp_Clamp( val.m_flLayerFadeOuttime );
}
#endif // ANIMATIONLAYER_H

View File

@ -0,0 +1,129 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "BaseAnimatedTextureProxy.h"
#include "materialsystem/IMaterial.h"
#include "materialsystem/IMaterialVar.h"
#include "materialsystem/ITexture.h"
#include "tier1/KeyValues.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Constructor, destructor:
//-----------------------------------------------------------------------------
CBaseAnimatedTextureProxy::CBaseAnimatedTextureProxy()
{
Cleanup();
}
CBaseAnimatedTextureProxy::~CBaseAnimatedTextureProxy()
{
Cleanup();
}
//-----------------------------------------------------------------------------
// Initialization, shutdown
//-----------------------------------------------------------------------------
bool CBaseAnimatedTextureProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
char const* pAnimatedTextureVarName = pKeyValues->GetString( "animatedTextureVar" );
if( !pAnimatedTextureVarName )
return false;
bool foundVar;
m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false );
if( !foundVar )
return false;
char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" );
if( !pAnimatedTextureFrameNumVarName )
return false;
m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false );
if( !foundVar )
return false;
m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 );
m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 );
return true;
}
void CBaseAnimatedTextureProxy::Cleanup()
{
m_AnimatedTextureVar = NULL;
m_AnimatedTextureFrameNumVar = NULL;
}
//-----------------------------------------------------------------------------
// Does the dirty deed
//-----------------------------------------------------------------------------
void CBaseAnimatedTextureProxy::OnBind( void *pEntity )
{
Assert ( m_AnimatedTextureVar );
if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE )
{
return;
}
ITexture *pTexture;
pTexture = m_AnimatedTextureVar->GetTextureValue();
int numFrames = pTexture->GetNumAnimationFrames();
if ( numFrames <= 0 )
{
Assert( !"0 frames in material calling animated texture proxy" );
return;
}
// NOTE: Must not use relative time based methods here
// because the bind proxy can be called many times per frame.
// Prevent multiple Wrap callbacks to be sent for no wrap mode
float startTime = GetAnimationStartTime(pEntity);
float deltaTime = gpGlobals->curtime - startTime;
float prevTime = deltaTime - gpGlobals->frametime;
// Clamp..
if (deltaTime < 0.0f)
deltaTime = 0.0f;
if (prevTime < 0.0f)
prevTime = 0.0f;
float frame = m_FrameRate * deltaTime;
float prevFrame = m_FrameRate * prevTime;
int intFrame = ((int)frame) % numFrames;
int intPrevFrame = ((int)prevFrame) % numFrames;
// Report wrap situation...
if (intPrevFrame > intFrame)
{
if (m_WrapAnimation)
{
AnimationWrapped( pEntity );
}
else
{
// Only sent the wrapped message once.
// when we're in non-wrapping mode
if (prevFrame < numFrames)
AnimationWrapped( pEntity );
intFrame = numFrames - 1;
}
}
m_AnimatedTextureFrameNumVar->SetIntValue( intFrame );
}
IMaterial *CBaseAnimatedTextureProxy::GetMaterial()
{
return m_AnimatedTextureVar->GetOwningMaterial();
}

View File

@ -0,0 +1,47 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef BASEANIMATEDTEXTUREPROXY
#define BASEANIMATEDTEXTUREPROXY
#include "materialsystem/IMaterialProxy.h"
class IMaterial;
class IMaterialVar;
#pragma warning (disable : 4100)
class CBaseAnimatedTextureProxy : public IMaterialProxy
{
public:
CBaseAnimatedTextureProxy();
virtual ~CBaseAnimatedTextureProxy();
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pC_BaseEntity );
virtual void Release( void ) { delete this; }
virtual IMaterial *GetMaterial();
protected:
// derived classes must implement this; it returns the time
// that the animation began
virtual float GetAnimationStartTime( void* pBaseEntity ) = 0;
// Derived classes may implement this if they choose;
// this method is called whenever the animation wraps...
virtual void AnimationWrapped( void* pBaseEntity ) {}
protected:
void Cleanup();
IMaterialVar *m_AnimatedTextureVar;
IMaterialVar *m_AnimatedTextureFrameNumVar;
float m_FrameRate;
bool m_WrapAnimation;
};
#endif // BASEANIMATEDTEXTUREPROXY

View File

@ -0,0 +1,125 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation for CBaseClientRenderTargets class.
// Provides Init functions for common render textures used by the engine.
// Mod makers can inherit from this class, and call the Create functions for
// only the render textures the want for their mod.
//=============================================================================//
#include "cbase.h"
#include "baseclientrendertargets.h" // header
#include "materialsystem/imaterialsystemhardwareconfig.h" // Hardware config checks
#include "materialsystem/itexture.h" // Hardware config checks
#include "tier0/icommandline.h"
#ifdef GAMEUI_UISYSTEM2_ENABLED
#include "gameui.h"
#endif
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
ConVar cl_disable_water_render_targets( "cl_disable_water_render_targets", "0" );
ITexture* CBaseClientRenderTargets::CreateWaterReflectionTexture( IMaterialSystem* pMaterialSystem, int iSize )
{
iSize = CommandLine()->ParmValue( "-reflectionTextureSize", iSize );
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_WaterReflection",
iSize, iSize, RT_SIZE_PICMIP,
pMaterialSystem->GetBackBufferFormat(),
MATERIAL_RT_DEPTH_SHARED,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
}
ITexture* CBaseClientRenderTargets::CreateWaterRefractionTexture( IMaterialSystem* pMaterialSystem, int iSize )
{
iSize = CommandLine()->ParmValue( "-reflectionTextureSize", iSize );
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_WaterRefraction",
iSize, iSize, RT_SIZE_PICMIP,
// This is different than reflection because it has to have alpha for fog factor.
IMAGE_FORMAT_RGBA8888,
MATERIAL_RT_DEPTH_SHARED,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
CREATERENDERTARGETFLAGS_HDR );
}
ITexture* CBaseClientRenderTargets::CreateCameraTexture( IMaterialSystem* pMaterialSystem, int iSize )
{
iSize = CommandLine()->ParmValue( "-monitorTextureSize", iSize );
return pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_Camera",
iSize, iSize, RT_SIZE_DEFAULT,
pMaterialSystem->GetBackBufferFormat(),
MATERIAL_RT_DEPTH_SHARED,
0,
CREATERENDERTARGETFLAGS_HDR );
}
//-----------------------------------------------------------------------------
// Purpose: Called by the engine in material system init and shutdown.
// Clients should override this in their inherited version, but the base
// is to init all standard render targets for use.
// Input : pMaterialSystem - the engine's material system (our singleton is not yet inited at the time this is called)
// pHardwareConfig - the user hardware config, useful for conditional render target setup
//-----------------------------------------------------------------------------
void CBaseClientRenderTargets::SetupClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig, int iWaterTextureSize, int iCameraTextureSize )
{
IMaterialSystem *pSave = materials;
// Make sure our config is loaded before we try to init rendertargets
ConfigureCurrentSystemLevel();
// Water effects
materials = pMaterialSystem; // in case not initted yet for mat system util
g_pMaterialSystem = pMaterialSystem;
g_pMaterialSystemHardwareConfig = pHardwareConfig;
if ( iWaterTextureSize && !cl_disable_water_render_targets.GetBool() )
{
m_WaterReflectionTexture.Init( CreateWaterReflectionTexture( pMaterialSystem, iWaterTextureSize ) );
m_WaterRefractionTexture.Init( CreateWaterRefractionTexture( pMaterialSystem, iWaterTextureSize ) );
}
// Monitors
if ( iCameraTextureSize )
m_CameraTexture.Init( CreateCameraTexture( pMaterialSystem, iCameraTextureSize ) );
ITexture *pGlintTexture = pMaterialSystem->CreateNamedRenderTargetTextureEx2(
"_rt_eyeglint", 32, 32, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_BGRA8888, MATERIAL_RT_DEPTH_NONE );
pGlintTexture->IncrementReferenceCount();
g_pClientShadowMgr->InitRenderTargets();
#ifdef GAMEUI_UISYSTEM2_ENABLED
g_pGameUIGameSystem->InitRenderTargets();
#endif
materials = pSave;
}
void CBaseClientRenderTargets::InitClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig )
{
SetupClientRenderTargets( pMaterialSystem, pHardwareConfig );
}
//-----------------------------------------------------------------------------
// Purpose: Shut down each CTextureReference we created in InitClientRenderTargets.
// Called by the engine in material system shutdown.
// Input : -
//-----------------------------------------------------------------------------
void CBaseClientRenderTargets::ShutdownClientRenderTargets()
{
// Water effects
m_WaterReflectionTexture.Shutdown();
m_WaterRefractionTexture.Shutdown();
// Monitors
m_CameraTexture.Shutdown();
g_pClientShadowMgr->ShutdownRenderTargets();
}
static CBaseClientRenderTargets g_BaseClientRenderTargets;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CBaseClientRenderTargets, IClientRenderTargets,
CLIENTRENDERTARGETS_INTERFACE_VERSION, g_BaseClientRenderTargets );

View File

@ -0,0 +1,62 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Has init functions for all the standard render targets used by most games.
// Mods who wish to make their own render targets can inherit from this class
// and in the 'InitClientRenderTargets' interface called by the engine, set up
// their own render targets as well as calling the init functions for various
// common render targets provided by this class.
//
// Note: Unless the client defines a singleton interface by inheriting from
// this class and exposing the singleton instance, these init and shutdown
// functions WILL NOT be called by the engine.
//
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef CLIENTRENDERTARTETS_H_
#define CLIENTRENDERTARTETS_H_
#ifdef _WIN32
#pragma once
#endif
#include "game/client/iclientrendertargets.h" // base class with interfaces called by the engine
#include "materialsystem/imaterialsystem.h" // for material system classes and interfaces
// Externs
class IMaterialSystem;
class IMaterialSystemHardwareConfig;
class CBaseClientRenderTargets : public IClientRenderTargets
{
// no networked vars
DECLARE_CLASS_GAMEROOT( CBaseClientRenderTargets, IClientRenderTargets );
public:
// Interface called by engine during material system startup.
virtual void InitClientRenderTargets ( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig );
// Shutdown all custom render targets here.
virtual void ShutdownClientRenderTargets ( void );
protected:
void SetupClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig, int iWaterTextureSize = 1024, int iCameraTextureSize = 256 );
// Standard render textures used by most mods-- Classes inheriting from
// this can choose to init these or not depending on their needs.
// For reflective and refracting water
CTextureReference m_WaterReflectionTexture;
CTextureReference m_WaterRefractionTexture;
// Used for monitors
CTextureReference m_CameraTexture;
// Init functions for the common render targets
ITexture* CreateWaterReflectionTexture( IMaterialSystem* pMaterialSystem, int iSize = 1024 );
ITexture* CreateWaterRefractionTexture( IMaterialSystem* pMaterialSystem, int iSize = 1024 );
ITexture* CreateCameraTexture( IMaterialSystem* pMaterialSystem, int iSize = 256 );
};
#endif // CLIENTRENDERTARTETS_H_

1527
game/client/beamdraw.cpp Normal file

File diff suppressed because it is too large Load Diff

167
game/client/beamdraw.h Normal file
View File

@ -0,0 +1,167 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#if !defined( BEAMDRAW_H )
#define BEAMDRAW_H
#ifdef _WIN32
#pragma once
#endif
#include "materialsystem/imaterial.h"
#include "materialsystem/imesh.h"
#include "mathlib/vector.h"
#include "tier2/beamsegdraw.h"
#include "c_pixel_visibility.h"
#define NOISE_DIVISIONS 128
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
struct model_t;
struct BeamTrail_t;
//-----------------------------------------------------------------------------
// Purpose: Beams fill out this data structure
// This is also used for rendering
//-----------------------------------------------------------------------------
class Beam_t : public CDefaultClientRenderable
{
public:
Beam_t();
// Methods of IClientRenderable
virtual const Vector& GetRenderOrigin( void );
virtual const QAngle& GetRenderAngles( void );
virtual const matrix3x4_t &RenderableToWorldTransform();
virtual void GetRenderBounds( Vector& mins, Vector& maxs );
virtual bool ShouldDraw( void );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
// Resets the beam state
void Reset();
// Method to computing the bounding box
void ComputeBounds();
// Bounding box...
Vector m_Mins;
Vector m_Maxs;
pixelvis_handle_t *m_queryHandleHalo;
float m_haloProxySize;
// Data is below..
// Next beam in list
Beam_t* next;
// Type of beam
int type;
int flags;
// Control points for the beam
int numAttachments;
Vector attachment[MAX_BEAM_ENTS];
Vector delta;
// 0 .. 1 over lifetime of beam
float t;
float freq;
// Time when beam should die
float die;
float width;
float endWidth;
float fadeLength;
float amplitude;
float life;
// Color
float r, g, b;
float brightness;
// Speed
float speed;
// Animation
float frameRate;
float frame;
int segments;
// Attachment entities for the beam
EHANDLE entity[MAX_BEAM_ENTS];
int attachmentIndex[MAX_BEAM_ENTS];
// Model info
int modelIndex;
int haloIndex;
float haloScale;
int frameCount;
float rgNoise[NOISE_DIVISIONS+1];
// Popcorn trail for beam follows to use
BeamTrail_t* trail;
// for TE_BEAMRINGPOINT
float start_radius;
float end_radius;
// for FBEAM_ONLYNOISEONCE
bool m_bCalculatedNoise;
float m_flHDRColorScale;
};
int ScreenTransform( const Vector& point, Vector& screen );
void DrawSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawTeslaSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawSplineSegs( int noise_divisions, float *prgNoise,
const model_t* beammodel, const model_t* halomodel, float flHaloScale,
float frame, int rendermode, int numAttachments, Vector* attachment,
float startWidth, float endWidth, float scale, float freq, float speed, int segments,
int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f );
void DrawHalo(IMaterial* pMaterial, const Vector& source, float scale, float const* color, float flHDRColorScale = 1.0f );
void BeamDrawHalo( const model_t* spritemodel, float frame, int rendermode, const Vector& source,
float scale, float* color, float flHDRColorScale = 1.0f );
void DrawDisk( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source, const Vector& delta,
float width, float scale, float freq, float speed,
int segments, float* color, float flHDRColorScale = 1.0f );
void DrawCylinder( int noise_divisions, float *prgNoise, const model_t* spritemodel,
float frame, int rendermode, const Vector& source,
const Vector& delta, float width, float scale, float freq,
float speed, int segments, float* color, float flHDRColorScale = 1.0f );
void DrawRing( int noise_divisions, float *prgNoise, void (*pfnNoise)( float *noise, int divs, float scale ),
const model_t* spritemodel, float frame, int rendermode,
const Vector& source, const Vector& delta, float width, float amplitude,
float freq, float speed, int segments, float* color, float flHDRColorScale = 1.0f );
void DrawBeamFollow( const model_t* spritemodel, BeamTrail_t* pHead, int frame, int rendermode, Vector& delta,
Vector& screen, Vector& screenLast, float die, const Vector& source,
int flags, float width, float amplitude, float freq, float* color, float flHDRColorScale = 1.0f );
void DrawBeamQuadratic( const Vector &start, const Vector &control, const Vector &end, float width, const Vector &color, float scrollOffset, float flHDRColorScale = 1.0f );
class CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode );
//-----------------------------------------------------------------------------
// Assumes the material has already been bound
//-----------------------------------------------------------------------------
void DrawSprite( const Vector &vecOrigin, float flWidth, float flHeight, color32 color );
#endif // BEAMDRAW_H

View File

@ -0,0 +1,193 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "bone_merge_cache.h"
#include "bone_setup.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// CBoneMergeCache
//-----------------------------------------------------------------------------
CBoneMergeCache::CBoneMergeCache()
{
m_pOwner = NULL;
m_pFollow = NULL;
m_pFollowHdr = NULL;
m_pOwnerHdr = NULL;
m_nFollowBoneSetupMask = 0;
}
void CBoneMergeCache::Init( C_BaseAnimating *pOwner )
{
m_pOwner = pOwner;
m_pFollow = NULL;
m_pFollowHdr = NULL;
m_pOwnerHdr = NULL;
m_nFollowBoneSetupMask = 0;
}
void CBoneMergeCache::UpdateCache()
{
if ( !m_pOwner )
return;
CStudioHdr *pOwnerHdr = m_pOwner->GetModelPtr();
if ( !pOwnerHdr )
return;
C_BaseAnimating *pTestFollow = m_pOwner->FindFollowedEntity();
CStudioHdr *pTestHdr = (pTestFollow ? pTestFollow->GetModelPtr() : NULL);
// if the follow parent has changed, or any of the underlying models has changed, reset the MergedBones list
if ( pTestFollow != m_pFollow || pTestHdr != m_pFollowHdr || pOwnerHdr != m_pOwnerHdr )
{
m_MergedBones.Purge();
// Update the cache.
if ( pTestFollow && pTestHdr && pOwnerHdr )
{
m_pFollow = pTestFollow;
m_pFollowHdr = pTestHdr;
m_pOwnerHdr = pOwnerHdr;
m_BoneMergeBits.Resize( pOwnerHdr->numbones() );
m_BoneMergeBits.ClearAll();
mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 );
m_nFollowBoneSetupMask = BONE_USED_BY_BONE_MERGE;
const bool bDeveloperDebugPrints = developer.GetBool();
for ( int i = 0; i < m_pOwnerHdr->numbones(); i++ )
{
int parentBoneIndex = Studio_BoneIndexByName( m_pFollowHdr, pOwnerBones[i].pszName() );
if ( parentBoneIndex < 0 )
continue;
// Add a merged bone here.
CMergedBone mergedBone;
mergedBone.m_iMyBone = i;
mergedBone.m_iParentBone = parentBoneIndex;
m_MergedBones.AddToTail( mergedBone );
m_BoneMergeBits.Set( i );
// Warn for performance-negative ad hoc bone merges. They're bad. Don't do them.
if ( ( m_pFollowHdr->boneFlags( parentBoneIndex ) & BONE_USED_BY_BONE_MERGE ) == 0 )
{
// go ahead and mark the bone and its parents
int n = parentBoneIndex;
while (n != -1)
{
m_pFollowHdr->setBoneFlags( n, BONE_USED_BY_BONE_MERGE );
n = m_pFollowHdr->boneParent( n );
}
// dump out a warning
if ( bDeveloperDebugPrints )
{
char sz[ 256 ];
Q_snprintf( sz, sizeof( sz ), "Performance warning: Add $bonemerge \"%s\" to QC that builds \"%s\"\n",
m_pFollowHdr->pBone( parentBoneIndex )->pszName(), m_pFollowHdr->pszName() );
static CUtlSymbolTableMT s_FollowerWarnings;
if ( UTL_INVAL_SYMBOL == s_FollowerWarnings.Find( sz ) )
{
s_FollowerWarnings.AddString( sz );
Warning( "%s", sz );
}
}
}
}
// No merged bones found? Slam the mask to 0
if ( !m_MergedBones.Count() )
{
m_nFollowBoneSetupMask = 0;
}
}
else
{
m_pFollow = NULL;
m_pFollowHdr = NULL;
m_pOwnerHdr = NULL;
m_nFollowBoneSetupMask = 0;
}
}
}
void CBoneMergeCache::MergeMatchingBones( int boneMask, CBoneBitList &boneComputed )
{
UpdateCache();
// If this is set, then all the other cache data is set.
if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
return;
// Have the entity we're following setup its bones.
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
// Now copy the bone matrices.
for ( int i=0; i < m_MergedBones.Count(); i++ )
{
int iOwnerBone = m_MergedBones[i].m_iMyBone;
int iParentBone = m_MergedBones[i].m_iParentBone;
// Only update bones reference by the bone mask.
if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) )
continue;
// INFESTED_DLL temp comment
//MatrixCopy( m_pFollow->GetBone( iParentBone ), m_pOwner->GetBoneForWrite( iOwnerBone ) );
// INFESTED_DLL hack
matrix3x4_t matPitchUp;
AngleMatrix( QAngle( 15, 0, 0 ), matPitchUp );
ConcatTransforms( m_pFollow->GetBone( iParentBone ), matPitchUp, m_pOwner->GetBoneForWrite( iOwnerBone ) );
boneComputed.Set( i );
}
}
bool CBoneMergeCache::GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles )
{
UpdateCache();
// If this is set, then all the other cache data is set.
if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 )
return false;
// We want the abs origin such that if we put the entity there, the first merged bone
// will be aligned. This way the entity will be culled in the correct position.
//
// ie: mEntity * mBoneLocal = mFollowBone
// so: mEntity = mFollowBone * Inverse( mBoneLocal )
//
// Note: the code below doesn't take animation into account. If the attached entity animates
// all over the place, then this won't get the right results.
// Get mFollowBone.
ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime );
const matrix3x4_t &mFollowBone = m_pFollow->GetBone( m_MergedBones[0].m_iParentBone );
// Get Inverse( mBoneLocal )
matrix3x4_t mBoneLocal, mBoneLocalInv;
SetupSingleBoneMatrix( m_pOwnerHdr, m_pOwner->GetSequence(), 0, m_MergedBones[0].m_iMyBone, mBoneLocal );
MatrixInvert( mBoneLocal, mBoneLocalInv );
// Now calculate mEntity = mFollowBone * Inverse( mBoneLocal )
matrix3x4_t mEntity;
ConcatTransforms( mFollowBone, mBoneLocalInv, mEntity );
MatrixAngles( mEntity, *pAbsAngles, *pAbsOrigin );
return true;
}

View File

@ -0,0 +1,79 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef BONE_MERGE_CACHE_H
#define BONE_MERGE_CACHE_H
#ifdef _WIN32
#pragma once
#endif
class C_BaseAnimating;
class CStudioHdr;
class CBoneBitList;
#include "mathlib/vector.h"
class CBoneMergeCache
{
public:
CBoneMergeCache();
void Init( C_BaseAnimating *pOwner );
// Updates the lookups that let it merge bones quickly.
void UpdateCache();
// This copies the transform from all bones in the followed entity that have
// names that match our bones.
virtual void MergeMatchingBones( int boneMask, CBoneBitList &boneComputed );
// Returns true if the specified bone is one that gets merged in MergeMatchingBones.
int IsBoneMerged( int iBone ) const;
// Gets the origin for the first merge bone on the parent.
bool GetAimEntOrigin( Vector *pAbsOrigin, QAngle *pAbsAngles );
protected:
// This is the entity that we're keeping the cache updated for.
C_BaseAnimating *m_pOwner;
// All the cache data is based off these. When they change, the cache data is regenerated.
// These are either all valid pointers or all NULL.
C_BaseAnimating *m_pFollow;
CStudioHdr *m_pFollowHdr;
CStudioHdr *m_pOwnerHdr;
// This is the mask we need to use to set up bones on the followed entity to do the bone merge
int m_nFollowBoneSetupMask;
// Cache data.
class CMergedBone
{
public:
unsigned short m_iMyBone;
unsigned short m_iParentBone;
};
CUtlVector<CMergedBone> m_MergedBones;
CVarBitVec m_BoneMergeBits; // One bit for each bone. The bit is set if the bone gets merged.
};
inline int CBoneMergeCache::IsBoneMerged( int iBone ) const
{
if ( m_pOwnerHdr )
return m_BoneMergeBits.Get( iBone );
else
return 0;
}
#endif // BONE_MERGE_CACHE_H

View File

@ -0,0 +1,71 @@
//========== Copyright © 2006, Valve Corporation, All rights reserved. ========
//
// Purpose:
//
//=============================================================================
#ifndef BONETOWORLDARRAY_H
#define BONETOWORLDARRAY_H
#include "tier0/tslist.h"
#if defined( _WIN32 )
#pragma once
#endif
#include "tier0/memdbgon.h" // for _aligned_malloc usage below
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
template <int NUM_ARRAYS>
class CBoneToWorldArrays
{
public:
enum
{
ALIGNMENT = 128,
};
CBoneToWorldArrays()
{
const int SIZE_ARRAY = AlignValue( sizeof(matrix3x4_t) * MAXSTUDIOBONES, ALIGNMENT );
m_pBase = (matrix3x4_t *)_aligned_malloc( SIZE_ARRAY * NUM_ARRAYS, ALIGNMENT );
for ( int i = 0; i < NUM_ARRAYS; i++ )
{
matrix3x4_t *pArray = (matrix3x4_t *)((byte *)m_pBase + SIZE_ARRAY * i);
Assert( (size_t)pArray % ALIGNMENT == 0 );
Free( pArray );
}
}
~CBoneToWorldArrays()
{
_aligned_free( m_pBase );
}
int NumArrays()
{
return NUM_ARRAYS;
}
matrix3x4_t *Alloc( bool bBlock = true )
{
TSLNodeBase_t *p;
while ( ( p = m_Free.Pop() ) == NULL && bBlock )
{
ThreadPause();
}
return (matrix3x4_t *)p;
}
void Free( matrix3x4_t *p )
{
m_Free.Push( (TSLNodeBase_t *) p );
}
private:
CTSListBase m_Free;
matrix3x4_t *m_pBase;
};
#endif // BONETOWORLDARRAY_H

View File

@ -0,0 +1,169 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if 0
class C_AI_BaseHumanoid : public C_AI_BaseNPC
{
public:
DECLARE_CLASS( C_AI_BaseHumanoid, C_AI_BaseNPC );
DECLARE_CLIENTCLASS();
C_AI_BaseHumanoid();
// model specific
virtual bool Interpolate( float currentTime );
virtual void StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask );
float m_recanimtime[3];
AnimationLayer_t m_Layer[4][3];
};
C_AI_BaseHumanoid::C_AI_BaseHumanoid()
{
memset(m_recanimtime, 0, sizeof(m_recanimtime));
memset(m_Layer, 0, sizeof(m_Layer));
}
BEGIN_RECV_TABLE_NOBASE(AnimationLayer_t, DT_Animationlayer)
RecvPropInt(RECVINFO_NAME(nSequence,sequence)),
RecvPropFloat(RECVINFO_NAME(flCycle,cycle)),
RecvPropFloat(RECVINFO_NAME(flPlaybackrate,playbackrate)),
RecvPropFloat(RECVINFO_NAME(flWeight,weight))
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT(C_AI_BaseHumanoid, DT_BaseHumanoid, CAI_BaseHumanoid)
/*
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[0][2],m_Layer0),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[1][2],m_Layer1),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[2][2],m_Layer2),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
RecvPropDataTable(RECVINFO_DTNAME(m_Layer[3][2],m_Layer3),0, &REFERENCE_RECV_TABLE(DT_Animationlayer)),
*/
RecvPropInt(RECVINFO_NAME(m_Layer[0][2].nSequence,sequence0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flCycle,cycle0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flPlaybackrate,playbackrate0)),
RecvPropFloat(RECVINFO_NAME(m_Layer[0][2].flWeight,weight0)),
RecvPropInt(RECVINFO_NAME(m_Layer[1][2].nSequence,sequence1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flCycle,cycle1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flPlaybackrate,playbackrate1)),
RecvPropFloat(RECVINFO_NAME(m_Layer[1][2].flWeight,weight1)),
RecvPropInt(RECVINFO_NAME(m_Layer[2][2].nSequence,sequence2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flCycle,cycle2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flPlaybackrate,playbackrate2)),
RecvPropFloat(RECVINFO_NAME(m_Layer[2][2].flWeight,weight2)),
RecvPropInt(RECVINFO_NAME(m_Layer[3][2].nSequence,sequence3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flCycle,cycle3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flPlaybackrate,playbackrate3)),
RecvPropFloat(RECVINFO_NAME(m_Layer[3][2].flWeight,weight3))
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_AI_BaseHumanoid::StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], float currentTime, int boneMask )
{
VPROF( "C_AI_BaseHumanoid::StandardBlendingRules" );
BaseClass::StandardBlendingRules( pStudioHdr, pos, q, currentTime, boneMask );
if ( !hdr )
{
return;
}
#if 0
float poseparam[MAXSTUDIOPOSEPARAM];
if ( GetSequence() >= hdr->numseq )
{
SetSequence( 0 );
}
// interpolate pose parameters
for (int i = 0; i < hdr->numposeparameters; i++)
{
poseparam[ i ] = m_flPoseParameter[i];
}
// build root animation
float fCycle = GetCycle();
CalcPose( hdr, NULL, pos, q, GetSequence(), fCycle, poseparam );
// debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, "%30s %6.2f : %6.2f", hdr->pSeqdesc( GetSequence() )->pszLabel( ), fCycle, 1.0 );
MaintainSequenceTransitions( hdr, fCycle, poseparam, pos, q, boneMask );
#if 1
for (i = 0; i < 4; i++)
{
if (m_Layer[i][2].nSequence != m_Layer[i][1].nSequence)
{
if (m_Layer[i][2].flWeight > 0.5) m_Layer[i][1].flWeight = 1.0; else m_Layer[i][1].flWeight = 0;
}
}
#endif
#if 1
for (i = 0; i < 4; i++)
{
Vector pos2[MAXSTUDIOBONES];
Quaternion q2[MAXSTUDIOBONES];
float fWeight = m_Layer[i][1].flWeight * (1 - dadt) + m_Layer[i][2].flWeight * dadt;
/*
debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -i - 1, 0,
"%2d %6.2f %6.2f : %2d %6.2f %6.2f : %2d %6.2f %6.2f",
m_Layer[i][0].nSequence, m_Layer[i][0].flCycle, m_Layer[i][0].flWeight,
m_Layer[i][1].nSequence, m_Layer[i][1].flCycle, m_Layer[i][1].flWeight,
m_Layer[i][2].nSequence, m_Layer[i][2].flCycle, m_Layer[i][2].flWeight );
*/
if (fWeight > 0)
{
mstudioseqdesc_t *pseqdesc = hdr->pSeqdesc( m_Layer[i][2].nSequence );
float fCycle = m_Layer[i][2].flCycle;
// UNDONE: Do IK here.
CalcPose( hdr, NULL, pos2, q2, m_Layer[i][2].nSequence, fCycle, poseparam );
if (fWeight > 1)
fWeight = 1;
SlerpBones( hdr, q, pos, pseqdesc, q2, pos2, fWeight );
engine->Con_NPrintf( 10 + i, "%30s %6.2f : %6.2f", pseqdesc->pszLabel(), fCycle, fWeight );
}
else
{
engine->Con_NPrintf( 10 + i, "%30s %6.2f : %6.2f", " ", 0, 0 );
}
}
#endif
CIKContext auto_ik;
auto_ik.Init( hdr, GetRenderAngles(), GetRenderOrigin(), gpGlobals->curtime );
CalcAutoplaySequences( hdr, &auto_ik, pos, q, poseparam, boneMask, currentTime );
float controllers[MAXSTUDIOBONECTRLS];
GetBoneControllers(controllers);
CalcBoneAdj( hdr, pos, q, controllers );
#endif
}
#endif

View File

@ -0,0 +1,173 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_AI_BaseNPC.h"
#include "engine/IVDebugOverlay.h"
#if defined( HL2_DLL ) || defined( HL2_EPISODIC )
#include "c_basehlplayer.h"
#endif
#include "death_pose.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define PING_MAX_TIME 2.0
IMPLEMENT_CLIENTCLASS_DT( C_AI_BaseNPC, DT_AI_BaseNPC, CAI_BaseNPC )
RecvPropInt( RECVINFO( m_lifeState ) ),
RecvPropBool( RECVINFO( m_bPerformAvoidance ) ),
RecvPropBool( RECVINFO( m_bIsMoving ) ),
RecvPropBool( RECVINFO( m_bFadeCorpse ) ),
RecvPropInt( RECVINFO ( m_iDeathPose) ),
RecvPropInt( RECVINFO( m_iDeathFrame) ),
RecvPropInt( RECVINFO( m_iSpeedModRadius ) ),
RecvPropInt( RECVINFO( m_iSpeedModSpeed ) ),
RecvPropInt( RECVINFO( m_bSpeedModActive ) ),
RecvPropBool( RECVINFO( m_bImportanRagdoll ) ),
RecvPropFloat( RECVINFO( m_flTimePingEffect ) ),
END_RECV_TABLE()
extern ConVar cl_npc_speedmod_intime;
bool NPC_IsImportantNPC( C_BaseAnimating *pAnimating )
{
C_AI_BaseNPC *pBaseNPC = pAnimating->MyNPCPointer();
if ( pBaseNPC == NULL )
return false;
return pBaseNPC->ImportantRagdoll();
}
C_AI_BaseNPC::C_AI_BaseNPC()
{
}
//-----------------------------------------------------------------------------
// Makes ragdolls ignore npcclip brushes
//-----------------------------------------------------------------------------
unsigned int C_AI_BaseNPC::PhysicsSolidMaskForEntity( void ) const
{
// This allows ragdolls to move through npcclip brushes
if ( !IsRagdoll() )
{
return MASK_NPCSOLID;
}
return MASK_SOLID;
}
void C_AI_BaseNPC::ClientThink( void )
{
BaseClass::ClientThink();
#ifdef HL2_DLL
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( ShouldModifyPlayerSpeed() == true )
{
if ( pPlayer )
{
float flDist = (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr();
if ( flDist <= GetSpeedModifyRadius() )
{
if ( pPlayer->m_hClosestNPC )
{
if ( pPlayer->m_hClosestNPC != this )
{
float flDistOther = (pPlayer->m_hClosestNPC->GetAbsOrigin() - pPlayer->GetAbsOrigin()).Length();
//If I'm closer than the other NPC then replace it with myself.
if ( flDist < flDistOther )
{
pPlayer->m_hClosestNPC = this;
pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
}
}
}
else
{
pPlayer->m_hClosestNPC = this;
pPlayer->m_flSpeedModTime = gpGlobals->curtime + cl_npc_speedmod_intime.GetFloat();
}
}
}
}
#endif // HL2_DLL
#ifdef HL2_EPISODIC
C_BaseHLPlayer *pPlayer = dynamic_cast<C_BaseHLPlayer*>( C_BasePlayer::GetLocalPlayer() );
if ( pPlayer && m_flTimePingEffect > gpGlobals->curtime )
{
float fPingEffectTime = m_flTimePingEffect - gpGlobals->curtime;
if ( fPingEffectTime > 0.0f )
{
Vector vRight, vUp;
Vector vMins, vMaxs;
float fFade;
if( fPingEffectTime <= 1.0f )
{
fFade = 1.0f - (1.0f - fPingEffectTime);
}
else
{
fFade = 1.0f;
}
GetRenderBounds( vMins, vMaxs );
AngleVectors (pPlayer->GetAbsAngles(), NULL, &vRight, &vUp );
Vector p1 = GetAbsOrigin() + vRight * vMins.x + vUp * vMins.z;
Vector p2 = GetAbsOrigin() + vRight * vMaxs.x + vUp * vMins.z;
Vector p3 = GetAbsOrigin() + vUp * vMaxs.z;
int r = 0 * fFade;
int g = 255 * fFade;
int b = 0 * fFade;
debugoverlay->AddLineOverlay( p1, p2, r, g, b, true, 0.05f );
debugoverlay->AddLineOverlay( p2, p3, r, g, b, true, 0.05f );
debugoverlay->AddLineOverlay( p3, p1, r, g, b, true, 0.05f );
}
}
#endif
}
void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( ( ShouldModifyPlayerSpeed() == true ) || ( m_flTimePingEffect > gpGlobals->curtime ) )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt )
{
ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt );
GetRagdollCurSequenceWithDeathPose( this, pDeltaBones1, gpGlobals->curtime, m_iDeathPose, m_iDeathFrame );
float ragdollCreateTime = PhysGetSyncCreateTime();
if ( ragdollCreateTime != gpGlobals->curtime )
{
// The next simulation frame begins before the end of this frame
// so initialize the ragdoll at that time so that it will reach the current
// position at curtime. Otherwise the ragdoll will simulate forward from curtime
// and pop into the future a bit at this point of transition
ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime );
}
else
{
SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime );
}
}

View File

@ -0,0 +1,61 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_AI_BASENPC_H
#define C_AI_BASENPC_H
#ifdef _WIN32
#pragma once
#endif
#include "c_basecombatcharacter.h"
// NOTE: MOved all controller code into c_basestudiomodel
class C_AI_BaseNPC : public C_BaseCombatCharacter
{
DECLARE_CLASS( C_AI_BaseNPC, C_BaseCombatCharacter );
public:
DECLARE_CLIENTCLASS();
C_AI_BaseNPC();
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
virtual bool IsNPC( void ) { return true; }
bool IsMoving( void ){ return m_bIsMoving; }
bool ShouldAvoidObstacle( void ){ return m_bPerformAvoidance; }
virtual bool AddRagdollToFadeQueue( void ) { return m_bFadeCorpse; }
virtual void GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt );
int GetDeathPose( void ) { return m_iDeathPose; }
bool ShouldModifyPlayerSpeed( void ) { return m_bSpeedModActive; }
int GetSpeedModifyRadius( void ) { return m_iSpeedModRadius; }
int GetSpeedModifySpeed( void ) { return m_iSpeedModSpeed; }
void ClientThink( void );
void OnDataChanged( DataUpdateType_t type );
bool ImportantRagdoll( void ) { return m_bImportanRagdoll; }
private:
C_AI_BaseNPC( const C_AI_BaseNPC & ); // not defined, not accessible
float m_flTimePingEffect;
int m_iDeathPose;
int m_iDeathFrame;
int m_iSpeedModRadius;
int m_iSpeedModSpeed;
bool m_bPerformAvoidance;
bool m_bIsMoving;
bool m_bFadeCorpse;
bool m_bSpeedModActive;
bool m_bImportanRagdoll;
};
#endif // C_AI_BASENPC_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,850 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $NoKeywords: $
//===========================================================================//
#ifndef C_BASEANIMATING_H
#define C_BASEANIMATING_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "studio.h"
#include "UtlVector.h"
#include "ragdoll.h"
#include "mouthinfo.h"
// Shared activities
#include "ai_activity.h"
#include "animationlayer.h"
#include "sequence_transitioner.h"
#include "bone_accessor.h"
#include "bone_merge_cache.h"
#include "ragdoll_shared.h"
#include "tier0/threadtools.h"
#include "datacache/idatacache.h"
#include "toolframework/itoolframework.h"
#define LIPSYNC_POSEPARAM_NAME "mouth"
#define NUM_HITBOX_FIRES 10
/*
class C_BaseClientShader
{
virtual void RenderMaterial( C_BaseEntity *pEntity, int count, const vec4_t *verts, const vec4_t *normals, const vec2_t *texcoords, vec4_t *lightvalues );
};
*/
class IRagdoll;
class C_ClientRagdoll;
class CIKContext;
class CIKState;
class ConVar;
class C_RopeKeyframe;
class CBoneBitList;
class CBoneList;
class KeyValues;
class CJiggleBones;
class IBoneSetup;
FORWARD_DECLARE_HANDLE( memhandle_t );
typedef unsigned short MDLHandle_t;
extern ConVar vcollide_wireframe;
extern IDataCache *datacache;
struct ClientModelRenderInfo_t : public ModelRenderInfo_t
{
// Added space for lighting origin override. Just allocated space, need to set base pointer
matrix3x4_t lightingOffset;
// Added space for model to world matrix. Just allocated space, need to set base pointer
matrix3x4_t modelToWorld;
};
struct RagdollInfo_t
{
bool m_bActive;
float m_flSaveTime;
int m_nNumBones;
Vector m_rgBonePos[MAXSTUDIOBONES];
Quaternion m_rgBoneQuaternion[MAXSTUDIOBONES];
};
class CAttachmentData
{
public:
matrix3x4_t m_AttachmentToWorld;
QAngle m_angRotation;
Vector m_vOriginVelocity;
int m_nLastFramecount : 31;
int m_bAnglesComputed : 1;
};
typedef unsigned int ClientSideAnimationListHandle_t;
#define INVALID_CLIENTSIDEANIMATION_LIST_HANDLE (ClientSideAnimationListHandle_t)~0
class C_BaseAnimating : public C_BaseEntity, public IClientModelRenderable
{
public:
DECLARE_CLASS( C_BaseAnimating, C_BaseEntity );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
DECLARE_FRIEND_DATADESC_ACCESS();
DECLARE_ENT_SCRIPTDESC();
enum
{
NUM_POSEPAREMETERS = 24,
NUM_BONECTRLS = 4
};
// Inherited from IClientUnknown
public:
virtual IClientModelRenderable* GetClientModelRenderable();
// Inherited from IClientModelRenderable
public:
virtual bool GetRenderData( void *pData, ModelDataCategory_t nCategory );
public:
C_BaseAnimating();
~C_BaseAnimating();
virtual C_BaseAnimating* GetBaseAnimating() { return this; }
int GetRenderFlags( void );
virtual bool Interpolate( float currentTime );
virtual bool Simulate();
virtual void Release();
float GetAnimTimeInterval( void ) const;
// Get bone controller values.
virtual void GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS]);
virtual float SetBoneController ( int iController, float flValue );
LocalFlexController_t GetNumFlexControllers( void );
const char *GetFlexDescFacs( int iFlexDesc );
const char *GetFlexControllerName( LocalFlexController_t iFlexController );
const char *GetFlexControllerType( LocalFlexController_t iFlexController );
virtual void GetAimEntOrigin( IClientEntity *pAttachedTo, Vector *pAbsOrigin, QAngle *pAbsAngles );
// Computes a box that surrounds all hitboxes
bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
// Gets the hitbox-to-world transforms, returns false if there was a problem
bool HitboxToWorldTransforms( matrix3x4_t *pHitboxToWorld[MAXSTUDIOBONES] );
// base model functionality
float ClampCycle( float cycle, bool isLooping );
virtual void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] );
virtual void CalcBoneMerge( CStudioHdr *hdr, int boneMask, CBoneBitList &boneComputed );
virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
void BuildJiggleTransformations( int boneIndex, const mstudiojigglebone_t *jiggleParams, const matrix3x4_t &goalMX );
virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform );
virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax );
// model specific
virtual bool SetupBones( matrix3x4a_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime );
virtual void UpdateIKLocks( float currentTime );
virtual void CalculateIKLocks( float currentTime );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual int InternalDrawModel( int flags, const RenderableInstance_t &instance );
virtual bool OnInternalDrawModel( ClientModelRenderInfo_t *pInfo );
virtual bool OnPostInternalDrawModel( ClientModelRenderInfo_t *pInfo );
void DoInternalDrawModel( ClientModelRenderInfo_t *pInfo, DrawModelState_t *pState, matrix3x4_t *pBoneToWorldArray = NULL );
//
virtual CMouthInfo *GetMouth();
virtual void ControlMouth( CStudioHdr *pStudioHdr );
// override in sub-classes
virtual void DoAnimationEvents( CStudioHdr *pStudio );
virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual void FireObsoleteEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
// Parses and distributes muzzle flash events
virtual bool DispatchMuzzleEffect( const char *options, bool isFirstPerson );
virtual void EjectParticleBrass( const char *pEffectName, const int iAttachment );
// virtual void AllocateMaterials( void );
// virtual void FreeMaterials( void );
virtual CStudioHdr *OnNewModel( void );
CStudioHdr *GetModelPtr() const;
void InvalidateMdlCache();
virtual void SetPredictable( bool state );
void UseClientSideAnimation();
bool IsUsingClientSideAnimation() { return m_bClientSideAnimation; }
// C_BaseClientShader **p_ClientShaders;
virtual void StandardBlendingRules( CStudioHdr *pStudioHdr, Vector pos[], QuaternionAligned q[], float currentTime, int boneMask );
void UnragdollBlend( CStudioHdr *hdr, Vector pos[], Quaternion q[], float currentTime );
void MaintainSequenceTransitions( IBoneSetup &boneSetup, float flCycle, Vector pos[], Quaternion q[] );
virtual void AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime );
// Attachments
virtual int LookupAttachment( const char *pAttachmentName );
int LookupRandomAttachment( const char *pAttachmentNameSubstring );
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
inline int LookupPoseParameter( const char *szName ) { return LookupPoseParameter(GetModelPtr(), szName); }
float SetPoseParameter( CStudioHdr *pStudioHdr, const char *szName, float flValue );
inline float SetPoseParameter( const char *szName, float flValue ) { return SetPoseParameter( GetModelPtr(), szName, flValue ); }
float SetPoseParameter( CStudioHdr *pStudioHdr, int iParameter, float flValue );
inline float SetPoseParameter( int iParameter, float flValue ) { return SetPoseParameter( GetModelPtr(), iParameter, flValue ); }
float GetPoseParameter( int iParameter );
float GetPoseParameterRaw( int iPoseParameter ); // returns raw 0..1 value
bool GetPoseParameterRange( int iPoseParameter, float &minValue, float &maxValue );
int LookupBone( const char *szName );
void GetBonePosition( int iBone, Vector &origin, QAngle &angles );
void GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld );
void CopySequenceTransitions( C_BaseAnimating *pCopyFrom );
//bool solveIK(float a, float b, const Vector &Foot, const Vector &Knee1, Vector &Knee2);
//void DebugIK( mstudioikchain_t *pikchain );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
// This can be used to force client side animation to be on. Only use if you know what you're doing!
// Normally, the server entity should set this.
void ForceClientSideAnimationOn();
void AddToClientSideAnimationList();
void RemoveFromClientSideAnimationList();
virtual bool IsSelfAnimating();
virtual void ResetLatched();
// implements these so ragdolls can handle frustum culling & leaf visibility
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual const Vector& GetRenderOrigin( void );
virtual const QAngle& GetRenderAngles( void );
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
// Attachments.
bool GetAttachment( const char *szName, Vector &absOrigin );
bool GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles );
// Inherited from C_BaseEntity
virtual bool GetAttachment( int number, Vector &origin );
virtual bool GetAttachment( int number, Vector &origin, QAngle &angles );
virtual bool GetAttachment( int number, matrix3x4_t &matrix );
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );
virtual void InvalidateAttachments();
// Returns the attachment in local space
bool GetAttachmentLocal( int iAttachment, matrix3x4_t &attachmentToLocal );
bool GetAttachmentLocal( int iAttachment, Vector &origin, QAngle &angles );
bool GetAttachmentLocal( int iAttachment, Vector &origin );
// Should this object cast render-to-texture shadows?
virtual ShadowType_t ShadowCastType();
// Should we collide?
virtual CollideType_t GetCollideType( void );
virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr );
// returns true if we are of type C_ClientRagdoll
virtual bool IsClientRagdoll() const { return false; }
// returns true if we're currently being ragdolled
bool IsRagdoll() const;
virtual C_BaseAnimating *BecomeRagdollOnClient();
virtual C_ClientRagdoll *CreateClientRagdoll( bool bRestoring = false );
C_BaseAnimating *CreateRagdollCopy();
bool InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt );
void IgniteRagdoll( C_BaseAnimating *pSource );
void TransferDissolveFrom( C_BaseAnimating *pSource );
virtual void SaveRagdollInfo( int numbones, const matrix3x4_t &cameraTransform, CBoneAccessor &pBoneToWorld );
virtual bool RetrieveRagdollInfo( Vector *pos, Quaternion *q );
virtual void Clear( void );
void ClearRagdoll();
void CreateUnragdollInfo( C_BaseAnimating *pRagdoll );
void ForceSetupBonesAtTime( matrix3x4a_t *pBonesOut, float flTime );
virtual void GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt );
// For shadows rendering the correct body + sequence...
virtual int GetBody() { return m_nBody; }
virtual int GetSkin() { return m_nSkin; }
bool IsOnFire() { return ( (GetFlags() & FL_ONFIRE) != 0 ); }
float GetFrozenAmount() { return m_flFrozen; }
inline float GetPlaybackRate() const;
inline void SetPlaybackRate( float rate );
void SetModelScale( float scale );
inline float GetModelScale() const { return m_flModelScale; }
inline bool IsModelScaleFractional() const; /// very fast way to ask if the model scale is < 1.0f (faster than if (GetModelScale() < 1.0f) )
int GetSequence();
void SetSequence(int nSequence);
inline void ResetSequence(int nSequence);
void OnNewSequence( );
float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence );
inline float GetSequenceGroundSpeed( int iSequence ) { return GetSequenceGroundSpeed(GetModelPtr(), iSequence); }
bool IsSequenceLooping( CStudioHdr *pStudioHdr, int iSequence );
inline bool IsSequenceLooping( int iSequence ) { return IsSequenceLooping(GetModelPtr(),iSequence); }
float GetSequenceMoveDist( CStudioHdr *pStudioHdr, int iSequence );
void GetSequenceLinearMotion( int iSequence, Vector *pVec );
float GetSequenceLinearMotionAndDuration( int iSequence, Vector *pVec );
bool GetSequenceMovement( int nSequence, float fromCycle, float toCycle, Vector &deltaPosition, QAngle &deltaAngles );
void GetBlendedLinearVelocity( Vector *pVec );
void SetMovementPoseParams( const Vector &vecLocalVelocity, int iMoveX, int iMoveY, int iXSign = 1, int iYSign = 1 );
int LookupSequence ( const char *label );
int LookupActivity( const char *label );
char const *GetSequenceName( int iSequence );
char const *GetSequenceActivityName( int iSequence );
Activity GetSequenceActivity( int iSequence );
virtual void StudioFrameAdvance(); // advance animation frame to some time in the future
void ExtractBbox( int nSequence, Vector &mins, Vector &maxs );
// Clientside animation
virtual float FrameAdvance( float flInterval = 0.0f );
virtual float GetSequenceCycleRate( CStudioHdr *pStudioHdr, int iSequence );
virtual void UpdateClientSideAnimation();
void ClientSideAnimationChanged();
virtual unsigned int ComputeClientSideAnimationFlags();
float GetGroundSpeed( void ) { return m_flGroundSpeed; }
virtual void ReachedEndOfSequence() { return; }
void SetCycle( float flCycle );
float GetCycle() const;
void SetBodygroup( int iGroup, int iValue );
int GetBodygroup( int iGroup );
void SetSkin( int iSkin );
void SetBody( int iBody );
const char *GetBodygroupName( int iGroup );
int FindBodygroupByName( const char *name );
int GetBodygroupCount( int iGroup );
int GetNumBodyGroups( void );
void SetHitboxSet( int setnum );
void SetHitboxSetByName( const char *setname );
int GetHitboxSet( void );
char const *GetHitboxSetName( void );
int GetHitboxSetCount( void );
void DrawClientHitboxes( float duration = 0.0f, bool monocolor = false );
void DrawSkeleton( CStudioHdr const* pHdr, int iBoneMask ) const;
C_BaseAnimating* FindFollowedEntity();
virtual bool IsActivityFinished( void ) { return m_bSequenceFinished; }
inline bool IsSequenceFinished( void );
inline bool SequenceLoops( void ) { return m_bSequenceLoops; }
// All view model attachments origins are stretched so you can place entities at them and
// they will match up with where the attachment winds up being drawn on the view model, since
// the view models are drawn with a different FOV.
//
// If you're drawing something inside of a view model's DrawModel() function, then you want the
// original attachment origin instead of the adjusted one. To get that, call this on the
// adjusted attachment origin.
virtual void UncorrectViewModelAttachment( Vector &vOrigin ) {}
// Call this if SetupBones() has already been called this frame but you need to move the
// entity and rerender.
void InvalidateBoneCache();
bool IsBoneCacheValid() const; // Returns true if the bone cache is considered good for this frame.
void GetCachedBoneMatrix( int boneIndex, matrix3x4_t &out );
// Wrappers for CBoneAccessor.
const matrix3x4a_t& GetBone( int iBone ) const;
matrix3x4a_t& GetBoneForWrite( int iBone );
matrix3x4a_t* GetBoneArrayForWrite();
// Used for debugging. Will produce asserts if someone tries to setup bones or
// attachments before it's allowed.
// Use the "AutoAllowBoneAccess" class to auto push/pop bone access.
// Use a distinct "tag" when pushing/popping - asserts when push/pop tags do not match.
struct AutoAllowBoneAccess
{
AutoAllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels );
~AutoAllowBoneAccess( void );
};
static void PushAllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels, char const *tagPush );
static void PopBoneAccess( char const *tagPop );
static void ThreadedBoneSetup();
static bool InThreadedBoneSetup();
static void InitBoneSetupThreadPool();
static void ShutdownBoneSetupThreadPool();
void MarkForThreadedBoneSetup();
static void SetupBonesOnBaseAnimating( C_BaseAnimating *&pBaseAnimating );
// Invalidate bone caches so all SetupBones() calls force bone transforms to be regenerated.
static void InvalidateBoneCaches();
// Purpose: My physics object has been updated, react or extract data
virtual void VPhysicsUpdate( IPhysicsObject *pPhysics );
void DisableMuzzleFlash(); // Turn off the muzzle flash (ie: signal that we handled the server's event).
virtual void DoMuzzleFlash(); // Force a muzzle flash event. Note: this only QUEUES an event, so
// ProcessMuzzleFlashEvent will get called later.
bool ShouldMuzzleFlash() const; // Is the muzzle flash event on?
// This is called to do the actual muzzle flash effect.
virtual void ProcessMuzzleFlashEvent();
// Update client side animations
static void UpdateClientSideAnimations();
// Load the model's keyvalues section and create effects listed inside it
void InitModelEffects( void );
// Sometimes the server wants to update the client's cycle to get the two to run in sync (for proper hit detection)
virtual void SetServerIntendedCycle( float intended ) { intended; }
virtual float GetServerIntendedCycle( void ) { return -1.0f; }
// For prediction
int SelectWeightedSequence ( int activity );
int SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount );
void ResetSequenceInfo( void );
float SequenceDuration( void );
float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence );
inline float SequenceDuration( int iSequence ) { return SequenceDuration(GetModelPtr(), iSequence); }
int FindTransitionSequence( int iCurrentSequence, int iGoalSequence, int *piDir );
void RagdollMoved( void );
virtual void GetToolRecordingState( KeyValues *msg );
virtual void CleanupToolRecordingState( KeyValues *msg );
void SetReceivedSequence( void );
virtual bool ShouldResetSequenceOnNewModel( void );
// View models say yes to this.
virtual bool IsViewModel() const;
// viewmodel or viewmodelattachmentmodel or lowerbody
virtual bool IsViewModelOrAttachment() const;
void EnableJiggleBones( void );
void DisableJiggleBones( void );
void ScriptSetPoseParameter( const char *szName, float fValue );
protected:
// View models scale their attachment positions to account for FOV. To get the unmodified
// attachment position (like if you're rendering something else during the view model's DrawModel call),
// use TransformViewModelAttachmentToWorld.
virtual void FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld ) {}
bool IsBoneAccessAllowed() const;
CMouthInfo& MouthInfo();
// Models used in a ModelPanel say yes to this
virtual bool IsMenuModel() const;
// Allow studio models to tell C_BaseEntity what their m_nBody value is
virtual int GetStudioBody( void ) { return m_nBody; }
virtual bool CalcAttachments();
virtual bool ComputeStencilState( ShaderStencilState_t *pStencilState );
virtual bool WantsInterpolatedVars() { return true; }
virtual void ResetSequenceLooping() { m_bSequenceFinished = false; }
private:
// This method should return true if the bones have changed + SetupBones needs to be called
virtual float LastBoneChangedTime() { return FLT_MAX; }
CBoneList* RecordBones( CStudioHdr *hdr, matrix3x4_t *pBoneState );
bool PutAttachment( int number, const matrix3x4_t &attachmentToWorld );
void TermRopes();
void DelayedInitModelEffects( void );
void ParseModelEffects( KeyValues *modelKeyValues );
void UpdateRelevantInterpolatedVars();
void AddBaseAnimatingInterpolatedVars();
void RemoveBaseAnimatingInterpolatedVars();
void LockStudioHdr();
void UnlockStudioHdr();
public:
CRagdoll *m_pRagdoll;
CBaseAnimating *m_pClientsideRagdoll;
// Hitbox set to use (default 0)
int m_nHitboxSet;
CSequenceTransitioner m_SequenceTransitioner;
private:
// BEGIN PREDICTION DATA COMPACTION (these fields are together to allow for faster copying in prediction system)
// FTYPEDESC_INSENDTABLE STUFF
int m_nPrevSequence;
protected:
//float m_flCycle;
// This needs to be ranged checked because some interpolation edge cases
// can assign it to values far out of range. Interpolation vars will only
// clamp range checked vars.
CRangeCheckedVar<float, -2, 2, 0> m_flCycle;
float m_flPlaybackRate;// Animation playback framerate
// FTYPEDESC_INSENDTABLE STUFF (end)
int m_nSkin;// Texture group to use
int m_nBody;// Object bodygroup
int m_nNewSequenceParity;
int m_nResetEventsParity;
int m_nPrevNewSequenceParity;
int m_nPrevResetEventsParity;
float m_flEncodedController[MAXSTUDIOBONECTRLS];
private:
// This is compared against m_nOldMuzzleFlashParity to determine if the entity should muzzle flash.
unsigned char m_nMuzzleFlashParity;
// END PREDICTION DATA COMPACTION
protected:
CIKContext *m_pIk;
int m_iEyeAttachment;
// Decomposed ragdoll info
bool m_bStoreRagdollInfo;
RagdollInfo_t *m_pRagdollInfo;
Vector m_vecForce;
int m_nForceBone;
// Is bone cache valid
// bone transformation matrix
unsigned long m_iMostRecentModelBoneCounter;
unsigned long m_iMostRecentBoneSetupRequest;
C_BaseAnimating * m_pNextForThreadedBoneSetup;
int m_iPrevBoneMask;
int m_iAccumulatedBoneMask;
CBoneAccessor m_BoneAccessor;
CThreadFastMutex m_BoneSetupLock;
ClientSideAnimationListHandle_t m_ClientSideAnimationListHandle;
// Client-side animation
bool m_bClientSideFrameReset;
protected:
float m_flFrozen;
// Can we use the fast rendering path?
bool m_bCanUseFastPath;
private:
float m_flGroundSpeed; // computed linear movement rate for current sequence
float m_flLastEventCheck; // cycle index of when events were last checked
bool m_bSequenceFinished;// flag set when StudioAdvanceFrame moves across a frame boundry
bool m_bSequenceLoops; // true if the sequence loops
bool m_bIsUsingRelativeLighting;
// Mouth lipsync/envelope following values
CMouthInfo m_mouth;
CNetworkVar( float, m_flModelScale );
int m_nRestoreSequence;
// Ropes that got spawned when the model was created.
CUtlLinkedList<C_RopeKeyframe*,unsigned short> m_Ropes;
// event processing info
float m_flPrevEventCycle;
int m_nEventSequence;
// Animation blending factors
float m_flPoseParameter[MAXSTUDIOPOSEPARAM];
CInterpolatedVarArray< float, MAXSTUDIOPOSEPARAM > m_iv_flPoseParameter;
float m_flOldPoseParameters[MAXSTUDIOPOSEPARAM];
CInterpolatedVarArray< float, MAXSTUDIOBONECTRLS > m_iv_flEncodedController;
float m_flOldEncodedController[MAXSTUDIOBONECTRLS];
// Clientside animation
bool m_bClientSideAnimation;
bool m_bLastClientSideFrameReset;
Vector m_vecPreRagdollMins;
Vector m_vecPreRagdollMaxs;
bool m_builtRagdoll;
bool m_bReceivedSequence;
bool m_bIsStaticProp;
// Current animation sequence
int m_nSequence;
// Current cycle location from server
protected:
CInterpolatedVar< CRangeCheckedVar<float, -2, 2, 0> > m_iv_flCycle;
//CInterpolatedVar< float > m_iv_flCycle;
float m_flOldCycle;
float m_prevClientCycle;
float m_prevClientAnimTime;
// True if bone setup should latch bones for demo polish subsystem
bool m_bBonePolishSetup;
CBoneMergeCache *m_pBoneMergeCache; // This caches the strcmp lookups that it has to do
// when merg
private:
int m_nPrevBody;
int m_nPrevSkin;
float m_flOldModelScale;
int m_nOldSequence;
CUtlVector< matrix3x4a_t, CUtlMemoryAligned<matrix3x4a_t,16> > m_CachedBoneData; // never access this directly. Use m_BoneAccessor.
float m_flLastBoneSetupTime;
CJiggleBones *m_pJiggleBones;
bool m_isJiggleBonesEnabled;
// Calculated attachment points
CUtlVector<CAttachmentData> m_Attachments;
void SetupBones_AttachmentHelper( CStudioHdr *pStudioHdr );
EHANDLE m_hLightingOrigin;
unsigned char m_nOldMuzzleFlashParity;
bool m_bInitModelEffects;
static bool m_bBoneListInUse;
static CBoneList m_recordingBoneList;
private:
mutable CStudioHdr *m_pStudioHdr;
mutable MDLHandle_t m_hStudioHdr;
CThreadFastMutex m_StudioHdrInitLock;
CUtlReference<CNewParticleEffect> m_ejectBrassEffect;
int m_iEjectBrassAttachment;
};
enum
{
RAGDOLL_FRICTION_OFF = -2,
RAGDOLL_FRICTION_NONE,
RAGDOLL_FRICTION_IN,
RAGDOLL_FRICTION_HOLD,
RAGDOLL_FRICTION_OUT,
};
class C_ClientRagdoll : public C_BaseAnimating, public IPVSNotify
{
public:
C_ClientRagdoll( bool bRestoring = true , bool fullInit = true);
public:
DECLARE_CLASS( C_ClientRagdoll, C_BaseAnimating );
DECLARE_DATADESC();
// inherited from IClientUnknown
virtual IClientModelRenderable* GetClientModelRenderable();
// inherited from IPVSNotify
virtual void OnPVSStatusChanged( bool bInPVS );
virtual void Release( void );
virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights );
virtual void ImpactTrace( trace_t *pTrace, int iDamageType, char *pCustomImpactName );
void ClientThink( void );
void ReleaseRagdoll( void ) { m_bReleaseRagdoll = true; }
bool ShouldSavePhysics( void ) { return true; }
virtual void OnSave();
virtual void OnRestore();
virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_SAVE_NON_NETWORKABLE; }
virtual IPVSNotify* GetPVSNotifyInterface() { return this; }
void HandleAnimatedFriction( void );
virtual void SUB_Remove( void );
void FadeOut( void );
virtual float LastBoneChangedTime();
inline bool IsFadingOut() { return m_bFadingOut; }
bool m_bFadeOut;
bool m_bImportant;
float m_flEffectTime;
// returns true if we are of type C_ClientRagdoll
virtual bool IsClientRagdoll() const { return true; }
protected:
bool m_bReleaseRagdoll;
private:
int m_iCurrentFriction;
int m_iMinFriction;
int m_iMaxFriction;
float m_flFrictionModTime;
float m_flFrictionTime;
int m_iFrictionAnimState;
bool m_bFadingOut;
float m_flScaleEnd[NUM_HITBOX_FIRES];
float m_flScaleTimeStart[NUM_HITBOX_FIRES];
float m_flScaleTimeEnd[NUM_HITBOX_FIRES];
};
//-----------------------------------------------------------------------------
// Purpose: Serves the 90% case of calling SetSequence / ResetSequenceInfo.
//-----------------------------------------------------------------------------
inline void C_BaseAnimating::ResetSequence(int nSequence)
{
SetSequence( nSequence );
ResetSequenceInfo();
}
inline float C_BaseAnimating::GetPlaybackRate() const
{
return m_flPlaybackRate * clamp( 1.0f - m_flFrozen, 0.0f, 1.0f );
}
inline void C_BaseAnimating::SetPlaybackRate( float rate )
{
m_flPlaybackRate = rate;
}
inline const matrix3x4a_t& C_BaseAnimating::GetBone( int iBone ) const
{
return m_BoneAccessor.GetBone( iBone );
}
inline matrix3x4a_t& C_BaseAnimating::GetBoneForWrite( int iBone )
{
return m_BoneAccessor.GetBoneForWrite( iBone );
}
inline matrix3x4a_t* C_BaseAnimating::GetBoneArrayForWrite()
{
return m_BoneAccessor.GetBoneArrayForWrite();
}
inline bool C_BaseAnimating::ShouldMuzzleFlash() const
{
return m_nOldMuzzleFlashParity != m_nMuzzleFlashParity;
}
inline float C_BaseAnimating::GetCycle() const
{
return m_flCycle;
}
//-----------------------------------------------------------------------------
// Purpose: return a pointer to an updated studiomdl cache cache
//-----------------------------------------------------------------------------
inline CStudioHdr *C_BaseAnimating::GetModelPtr() const
{
#ifdef _DEBUG
#ifndef _X360
// 360's don't need to lock the modeldata cache since it never flushes
static IDataCacheSection *pModelCache = g_pDataCache->FindSection( "ModelData" );
AssertOnce( pModelCache->IsFrameLocking() );
#endif
#endif
// GetModelPtr() is often called before OnNewModel() so go ahead and set it up first chance.
if ( !m_pStudioHdr && GetModel() )
{
const_cast<C_BaseAnimating *>(this)->LockStudioHdr();
}
return ( m_pStudioHdr && m_pStudioHdr->IsValid() ) ? m_pStudioHdr : NULL;
}
inline void C_BaseAnimating::InvalidateMdlCache()
{
UnlockStudioHdr();
if ( m_pStudioHdr != NULL )
{
delete m_pStudioHdr;
m_pStudioHdr = NULL;
}
}
inline bool C_BaseAnimating::IsModelScaleFractional() const /// very fast way to ask if the model scale is < 1.0f
{
COMPILE_TIME_ASSERT( sizeof( m_flModelScale ) == sizeof( int ) );
return *((const int *) &m_flModelScale) < 0x3f800000;
}
//-----------------------------------------------------------------------------
// Sequence access
//-----------------------------------------------------------------------------
inline int C_BaseAnimating::GetSequence()
{
return m_nSequence;
}
inline bool C_BaseAnimating::IsSequenceFinished( void )
{
return m_bSequenceFinished;
}
inline float C_BaseAnimating::SequenceDuration( void )
{
return SequenceDuration( GetSequence() );
}
//-----------------------------------------------------------------------------
// Mouth
//-----------------------------------------------------------------------------
inline CMouthInfo& C_BaseAnimating::MouthInfo()
{
return m_mouth;
}
// FIXME: move these to somewhere that makes sense
void GetColumn( matrix3x4_t& src, int column, Vector &dest );
void SetColumn( Vector &src, int column, matrix3x4_t& dest );
EXTERN_RECV_TABLE(DT_BaseAnimating);
extern void DevMsgRT( char const* pMsg, ... );
#endif // C_BASEANIMATING_H

View File

@ -0,0 +1,753 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_baseanimatingoverlay.h"
#include "animation.h"
#include "bone_setup.h"
#include "tier0/vprof.h"
#include "engine/IVDebugOverlay.h"
#include "datacache/imdlcache.h"
#include "eventlist.h"
#include "toolframework_client.h"
#include "dt_utlvector_recv.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern ConVar r_sequence_debug;
template class CInterpolatedVar<CAnimationLayer>;
mstudioevent_for_client_server_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc );
void C_AnimationLayer::SetOwner( C_BaseAnimatingOverlay *pOverlay )
{
m_pOwner = pOverlay;
}
C_BaseAnimatingOverlay *C_AnimationLayer::GetOwner() const
{
return m_pOwner;
}
void C_AnimationLayer::Reset()
{
if ( m_pOwner )
{
int nFlags = 0;
if ( m_nSequence != 0 || m_flWeight != 0.0f )
{
nFlags |= BOUNDS_CHANGED;
}
if ( m_flCycle != 0.0f )
{
nFlags |= ANIMATION_CHANGED;
}
if ( nFlags )
{
m_pOwner->InvalidatePhysicsRecursive( nFlags );
}
}
m_nSequence = 0;
m_flPrevCycle = 0;
m_flWeight = 0;
m_flPlaybackRate = 0;
m_flCycle = 0;
m_flLayerAnimtime = 0;
m_flLayerFadeOuttime = 0;
}
void C_AnimationLayer::SetSequence( int nSequence )
{
if ( m_pOwner && m_nSequence != nSequence )
{
m_pOwner->InvalidatePhysicsRecursive( BOUNDS_CHANGED );
}
m_nSequence = nSequence;
}
void C_AnimationLayer::SetCycle( float flCycle )
{
if ( m_pOwner && m_flCycle != flCycle )
{
m_pOwner->InvalidatePhysicsRecursive( ANIMATION_CHANGED );
}
m_flCycle = flCycle;
}
void C_AnimationLayer::SetOrder( int order )
{
if ( m_pOwner && ( m_nOrder != order ) )
{
if ( m_nOrder == C_BaseAnimatingOverlay::MAX_OVERLAYS || order == C_BaseAnimatingOverlay::MAX_OVERLAYS )
{
m_pOwner->InvalidatePhysicsRecursive( BOUNDS_CHANGED );
}
}
m_nOrder = order;
}
void C_AnimationLayer::SetWeight( float flWeight )
{
if ( m_pOwner && m_flWeight != flWeight )
{
if ( m_flWeight == 0.0f || flWeight == 0.0f )
{
m_pOwner->InvalidatePhysicsRecursive( BOUNDS_CHANGED );
}
}
m_flWeight = flWeight;
}
C_BaseAnimatingOverlay::C_BaseAnimatingOverlay()
{
// NOTE: We zero the memory in the max capacity m_Layer vector in dt_ultvector_common.h
// FIXME: where does this initialization go now?
// AddVar( m_Layer, &m_iv_AnimOverlay, LATCH_ANIMATION_VAR );
}
#undef CBaseAnimatingOverlay
void RecvProxy_SequenceChanged( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CAnimationLayer *pLayer = (CAnimationLayer *)pStruct;
pLayer->SetSequence( pData->m_Value.m_Int );
}
void RecvProxy_WeightChanged( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CAnimationLayer *pLayer = (CAnimationLayer *)pStruct;
pLayer->SetWeight( pData->m_Value.m_Float );
}
void RecvProxy_CycleChanged( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CAnimationLayer *pLayer = (CAnimationLayer *)pStruct;
pLayer->SetCycle( pData->m_Value.m_Float );
}
void RecvProxy_OrderChanged( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
CAnimationLayer *pLayer = (CAnimationLayer *)pStruct;
pLayer->SetOrder( pData->m_Value.m_Int );
}
BEGIN_RECV_TABLE_NOBASE(CAnimationLayer, DT_Animationlayer)
RecvPropInt( RECVINFO_NAME(m_nSequence, m_nSequence), 0, RecvProxy_SequenceChanged ),
RecvPropFloat( RECVINFO_NAME(m_flCycle, m_flCycle), 0, RecvProxy_CycleChanged ),
RecvPropFloat( RECVINFO_NAME(m_flPrevCycle, m_flPrevCycle)),
RecvPropFloat( RECVINFO_NAME(m_flWeight, m_flWeight), 0, RecvProxy_WeightChanged ),
RecvPropInt( RECVINFO_NAME(m_nOrder, m_nOrder), 0, RecvProxy_OrderChanged )
END_RECV_TABLE()
const char *s_m_iv_AnimOverlayNames[C_BaseAnimatingOverlay::MAX_OVERLAYS] =
{
"C_BaseAnimatingOverlay::m_iv_AnimOverlay00",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay01",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay02",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay03",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay04",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay05",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay06",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay07",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay08",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay09",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay10",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay11",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay12",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay13",
"C_BaseAnimatingOverlay::m_iv_AnimOverlay14"
};
void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len )
{
C_BaseAnimatingOverlay *pEnt = (C_BaseAnimatingOverlay*)pStruct;
CUtlVector < CAnimationLayer > *pVec = &pEnt->m_AnimOverlay;
CUtlVector< CInterpolatedVar< CAnimationLayer > > *pVecIV = &pEnt->m_iv_AnimOverlay;
Assert( (char*)pVec - (char*)pEnt == offsetToUtlVector );
Assert( pVec->Count() == pVecIV->Count() );
Assert( pVec->Count() <= C_BaseAnimatingOverlay::MAX_OVERLAYS );
int diff = len - pVec->Count();
if ( diff != 0 )
{
// remove all entries
for ( int i=0; i < pVec->Count(); i++ )
{
pEnt->RemoveVar( &pVec->Element( i ) );
}
pEnt->InvalidatePhysicsRecursive( BOUNDS_CHANGED );
// adjust vector sizes
if ( diff > 0 )
{
for ( int i = 0; i < diff; ++i )
{
int j = pVec->AddToTail( );
(*pVec)[j].SetOwner( pEnt );
}
pVecIV->AddMultipleToTail( diff );
}
else
{
pVec->RemoveMultiple( len, -diff );
pVecIV->RemoveMultiple( len, -diff );
}
// Rebind all the variables in the ent's list.
for ( int i=0; i < len; i++ )
{
IInterpolatedVar *pWatcher = &pVecIV->Element( i );
pWatcher->SetDebugName( s_m_iv_AnimOverlayNames[i] );
pEnt->AddVar( &pVec->Element( i ), pWatcher, LATCH_ANIMATION_VAR, true );
}
}
// FIXME: need to set historical values of nOrder in pVecIV to MAX_OVERLAY
// Ensure capacity
pVec->EnsureCapacity( len );
int nNumAllocated = pVec->NumAllocated();
// This is important to do because EnsureCapacity doesn't actually call the constructors
// on the elements, but we need them to be initialized, otherwise it'll have out-of-range
// values which will piss off the datatable encoder.
UtlVector_InitializeAllocatedElements( pVec->Base() + pVec->Count(), nNumAllocated - pVec->Count() );
}
BEGIN_RECV_TABLE_NOBASE( C_BaseAnimatingOverlay, DT_OverlayVars )
RecvPropUtlVector(
RECVINFO_UTLVECTOR_SIZEFN( m_AnimOverlay, ResizeAnimationLayerCallback ),
C_BaseAnimatingOverlay::MAX_OVERLAYS,
RecvPropDataTable(NULL, 0, 0, &REFERENCE_RECV_TABLE( DT_Animationlayer ) ) )
END_RECV_TABLE()
IMPLEMENT_CLIENTCLASS_DT( C_BaseAnimatingOverlay, DT_BaseAnimatingOverlay, CBaseAnimatingOverlay )
RecvPropDataTable( "overlay_vars", 0, 0, &REFERENCE_RECV_TABLE( DT_OverlayVars ) )
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseAnimatingOverlay )
/*
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[0][2].m_flWeight, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[1][2].m_flWeight, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[2][2].m_flWeight, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_nSequence, FIELD_INTEGER ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flCycle, FIELD_FLOAT ),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flPlaybackRate, FIELD_FLOAT),
DEFINE_FIELD( C_BaseAnimatingOverlay, m_Layer[3][2].m_flWeight, FIELD_FLOAT),
*/
END_PREDICTION_DATA()
CAnimationLayer* C_BaseAnimatingOverlay::GetAnimOverlay( int i )
{
Assert( i >= 0 && i < MAX_OVERLAYS );
return &m_AnimOverlay[i];
}
void C_BaseAnimatingOverlay::SetNumAnimOverlays( int num )
{
if ( m_AnimOverlay.Count() < num )
{
int nCountToAdd = num - m_AnimOverlay.Count();
for ( int i = 0; i < nCountToAdd; ++i )
{
int j = m_AnimOverlay.AddToTail( );
m_AnimOverlay[j].SetOwner( this );
}
}
else if ( m_AnimOverlay.Count() > num )
{
m_AnimOverlay.RemoveMultiple( num, m_AnimOverlay.Count() - num );
InvalidatePhysicsRecursive( BOUNDS_CHANGED );
}
// Ensure capacity
m_AnimOverlay.EnsureCapacity( C_BaseAnimatingOverlay::MAX_OVERLAYS );
int nNumAllocated = m_AnimOverlay.NumAllocated();
// This is important to do because EnsureCapacity doesn't actually call the constructors
// on the elements, but we need them to be initialized, otherwise it'll have out-of-range
// values which will piss off the datatable encoder.
UtlVector_InitializeAllocatedElements( m_AnimOverlay.Base() + m_AnimOverlay.Count(), nNumAllocated - m_AnimOverlay.Count() );
}
int C_BaseAnimatingOverlay::GetNumAnimOverlays() const
{
return m_AnimOverlay.Count();
}
void C_BaseAnimatingOverlay::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
BaseClass::GetRenderBounds( theMins, theMaxs );
if ( IsRagdoll() )
return;
CStudioHdr *pStudioHdr = GetModelPtr();
if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
return;
int nSequences = pStudioHdr->GetNumSeq();
int i;
for (i = 0; i < m_AnimOverlay.Count(); i++)
{
if ( m_AnimOverlay[i].m_flWeight > 0.0 && m_AnimOverlay[i].m_nOrder != MAX_OVERLAYS )
{
if ( m_AnimOverlay[i].m_nSequence >= nSequences )
continue;
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[i].m_nSequence );
VectorMin( seqdesc.bbmin, theMins, theMins );
VectorMax( seqdesc.bbmax, theMaxs, theMaxs );
}
}
}
bool C_BaseAnimatingOverlay::Interpolate( float flCurrentTime )
{
bool bOk = BaseClass::Interpolate( flCurrentTime );
CheckForLayerPhysicsInvalidate();
return bOk;
}
void C_BaseAnimatingOverlay::CheckForLayerChanges( CStudioHdr *hdr, float currentTime )
{
CDisableRangeChecks disableRangeChecks;
// FIXME: damn, there has to be a better way than this.
int i;
for (i = 0; i < m_iv_AnimOverlay.Count(); i++)
{
CDisableRangeChecks disableRangeChecks;
int iHead, iPrev1, iPrev2;
m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 );
// fake up previous cycle values.
float t0;
CAnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 );
// reset previous
float t1;
CAnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 );
// reset previous previous
float t2;
CAnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 );
if ( !pHead || !pPrev1 || pHead->m_nSequence == pPrev1->m_nSequence )
continue;
#if 1 // _DEBUG
if (r_sequence_debug.GetInt() == entindex())
{
DevMsgRT( "(%7.4f : %30s : %5.3f : %4.2f : %1d)\n", t0, hdr->pSeqdesc( pHead->m_nSequence ).pszLabel(), (float)pHead->m_flCycle, (float)pHead->m_flWeight, i );
DevMsgRT( "(%7.4f : %30s : %5.3f : %4.2f : %1d)\n", t1, hdr->pSeqdesc( pPrev1->m_nSequence ).pszLabel(), (float)pPrev1->m_flCycle, (float)pPrev1->m_flWeight, i );
if (pPrev2)
DevMsgRT( "(%7.4f : %30s : %5.3f : %4.2f : %1d)\n", t2, hdr->pSeqdesc( pPrev2->m_nSequence ).pszLabel(), (float)pPrev2->m_flCycle, (float)pPrev2->m_flWeight, i );
}
#endif
pPrev1->m_nSequence = pHead->m_nSequence;
pPrev1->m_flCycle = pHead->m_flPrevCycle;
pPrev1->m_flWeight = pHead->m_flWeight;
if (pPrev2)
{
float num = 0;
if ( fabs( t0 - t1 ) > 0.001f )
num = (t2 - t1) / (t0 - t1);
pPrev2->m_nSequence = pHead->m_nSequence;
float flTemp;
if (IsSequenceLooping( hdr, pHead->m_nSequence ))
{
flTemp = LoopingLerp( num, (float)pHead->m_flPrevCycle, (float)pHead->m_flCycle );
}
else
{
flTemp = Lerp( num, (float)pHead->m_flPrevCycle, (float)pHead->m_flCycle );
}
pPrev2->m_flCycle = flTemp;
pPrev2->m_flWeight = pHead->m_flWeight;
}
/*
if (stricmp( r_seq_overlay_debug.GetString(), hdr->name ) == 0)
{
DevMsgRT( "(%30s %6.2f : %6.2f : %6.2f)\n", hdr->pSeqdesc( pHead->nSequence ).pszLabel(), (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle );
}
*/
m_iv_AnimOverlay[i].SetLooping( IsSequenceLooping( hdr, pHead->m_nSequence ) );
m_iv_AnimOverlay[i].Interpolate( currentTime );
// reset event indexes
m_flOverlayPrevEventCycle[i] = pHead->m_flPrevCycle - 0.01;
}
}
//#define DEBUG_TF2_OVERLAYS
void C_BaseAnimatingOverlay::AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime )
{
BaseClass::AccumulateLayers( boneSetup, pos, q, currentTime );
int i;
// resort the layers
int layer[MAX_OVERLAYS];
for (i = 0; i < MAX_OVERLAYS; i++)
{
layer[i] = MAX_OVERLAYS;
}
for (i = 0; i < m_AnimOverlay.Count(); i++)
{
if (m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS)
{
/*
Assert( layer[m_AnimOverlay[i].m_nOrder] == MAX_OVERLAYS );
layer[m_AnimOverlay[i].m_nOrder] = i;
*/
// hacky code until initialization of new layers is finished
if ( layer[m_AnimOverlay[i].m_nOrder] != MAX_OVERLAYS )
{
m_AnimOverlay[i].SetOrder( MAX_OVERLAYS );
}
else
{
layer[m_AnimOverlay[i].m_nOrder] = i;
}
}
}
CheckForLayerChanges( boneSetup.GetStudioHdr(), currentTime );
int nSequences = boneSetup.GetStudioHdr()->GetNumSeq();
// add in the overlay layers
int j;
for (j = 0; j < MAX_OVERLAYS; j++)
{
i = layer[ j ];
if ( i >= m_AnimOverlay.Count() )
{
#if defined( DEBUG_TF2_OVERLAYS )
engine->Con_NPrintf( 10 + j, "%30s %6.2f : %6.2f : %1d", " ", 0.f, 0.f, i );
#endif
continue;
}
if ( m_AnimOverlay[i].m_nSequence >= nSequences )
continue;
/*
DevMsgRT( 1 , "%.3f %.3f %.3f\n", currentTime, fWeight, dadt );
debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), -j - 1, 0,
"%2d(%s) : %6.2f : %6.2f",
m_AnimOverlay[i].m_nSequence,
boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence )->pszLabel(),
m_AnimOverlay[i].m_flCycle,
m_AnimOverlay[i].m_flWeight
);
*/
float fWeight = m_AnimOverlay[i].m_flWeight;
if ( fWeight <= 0.0f )
{
#if defined( DEBUG_TF2_OVERLAYS )
engine->Con_NPrintf( 10 + j, "%30s %6.2f : %6.2f : %1d", " ", 0.f, 0.f, i );
#endif
continue;
}
// check to see if the sequence changed
// FIXME: move this to somewhere more reasonable
// do a nice spline interpolation of the values
// if ( m_AnimOverlay[i].m_nSequence != m_iv_AnimOverlay.GetPrev( i )->nSequence )
float fCycle = m_AnimOverlay[ i ].m_flCycle;
fCycle = ClampCycle( fCycle, IsSequenceLooping( m_AnimOverlay[i].m_nSequence ) );
if (fWeight > 1.0f)
{
fWeight = 1.0f;
}
boneSetup.AccumulatePose( pos, q, m_AnimOverlay[i].m_nSequence, fCycle, fWeight, currentTime, m_pIk );
#if defined( DEBUG_TF2_OVERLAYS )
engine->Con_NPrintf( 10 + j, "%30s %6.2f : %6.2f : %1d", boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i );
#endif
#if 1 // _DEBUG
if (r_sequence_debug.GetInt() == entindex())
{
if (1)
{
DevMsgRT( "%8.4f : %30s : %5.3f : %4.2f : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i );
}
else
{
int iHead, iPrev1, iPrev2;
m_iv_AnimOverlay[i].GetInterpolationInfo( currentTime, &iHead, &iPrev1, &iPrev2 );
// fake up previous cycle values.
float t0;
CAnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 );
// reset previous
float t1;
CAnimationLayer *pPrev1 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 );
// reset previous previous
float t2;
CAnimationLayer *pPrev2 = m_iv_AnimOverlay[i].GetHistoryValue( iPrev2, t2 );
if ( pHead && pPrev1 && pPrev2 )
{
DevMsgRT( "%6.2f : %30s %6.2f (%6.2f:%6.2f:%6.2f) : %6.2f (%6.2f:%6.2f:%6.2f) : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(),
fCycle, (float)pPrev2->m_flCycle, (float)pPrev1->m_flCycle, (float)pHead->m_flCycle,
fWeight, (float)pPrev2->m_flWeight, (float)pPrev1->m_flWeight, (float)pHead->m_flWeight,
i );
}
else
{
DevMsgRT( "%6.2f : %30s %6.2f : %6.2f : %1d\n", currentTime, boneSetup.GetStudioHdr()->pSeqdesc( m_AnimOverlay[i].m_nSequence ).pszLabel(), fCycle, fWeight, i );
}
}
}
#endif
}
}
void C_BaseAnimatingOverlay::DoAnimationEvents( CStudioHdr *pStudioHdr )
{
MDLCACHE_CRITICAL_SECTION();
if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
return;
int nSequences = pStudioHdr->GetNumSeq();
BaseClass::DoAnimationEvents( pStudioHdr );
bool watch = false; // Q_strstr( hdr->name, "rifle" ) ? true : false;
CheckForLayerChanges( pStudioHdr, gpGlobals->curtime ); // !!!
int j;
for (j = 0; j < m_AnimOverlay.Count(); j++)
{
if ( m_AnimOverlay[j].m_nSequence >= nSequences )
{
continue;
}
// Don't bother with 0-weight layers
if ( m_AnimOverlay[j].m_flWeight == 0.0f || m_AnimOverlay[j].m_nOrder == MAX_OVERLAYS )
{
continue;
}
mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[j].m_nSequence );
if ( seqdesc.numevents == 0 )
continue;
// stalled?
if (m_AnimOverlay[j].m_flCycle == m_flOverlayPrevEventCycle[j])
continue;
bool bLoopingSequence = IsSequenceLooping( m_AnimOverlay[j].m_nSequence );
bool bLooped = false;
//in client code, m_flOverlayPrevEventCycle is set to -1 when we first start an overlay, looping or not
if ( bLoopingSequence &&
m_flOverlayPrevEventCycle[j] > 0.0f &&
m_AnimOverlay[j].m_flCycle <= m_flOverlayPrevEventCycle[j] )
{
if (m_flOverlayPrevEventCycle[j] - m_AnimOverlay[j].m_flCycle > 0.5)
{
bLooped = true;
}
else
{
// things have backed up, which is bad since it'll probably result in a hitch in the animation playback
// but, don't play events again for the same time slice
return;
}
}
mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc );
// This makes sure events that occur at the end of a sequence occur are
// sent before events that occur at the beginning of a sequence.
if (bLooped)
{
for (int i = 0; i < (int)seqdesc.numevents; i++)
{
// ignore all non-client-side events
if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
{
if ( !(pevent[i].type & AE_TYPE_CLIENT) )
continue;
}
else if ( pevent[i].Event_OldSystem() < EVENT_CLIENT ) //Adrian - Support the old event system
continue;
if ( pevent[i].cycle <= m_flOverlayPrevEventCycle[j] )
continue;
if ( watch )
{
Msg( "%i FE %i Looped cycle %f, prev %f ev %f (time %.3f)\n",
gpGlobals->tickcount,
pevent[i].Event(),
pevent[i].cycle,
(float)m_flOverlayPrevEventCycle[j],
(float)m_AnimOverlay[j].m_flCycle,
gpGlobals->curtime );
}
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].Event(), pevent[ i ].pszOptions() );
}
// Necessary to get the next loop working
m_flOverlayPrevEventCycle[j] = -0.01;
}
for (int i = 0; i < (int)seqdesc.numevents; i++)
{
if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM )
{
if ( !(pevent[i].type & AE_TYPE_CLIENT) )
continue;
}
else if ( pevent[i].Event_OldSystem() < EVENT_CLIENT ) //Adrian - Support the old event system
continue;
bool bStartedSequence = ( m_flOverlayPrevEventCycle[j] > m_AnimOverlay[j].m_flCycle || m_flOverlayPrevEventCycle[j] == 0 );
if ( ( ( pevent[i].cycle > m_flOverlayPrevEventCycle[j] || bStartedSequence && pevent[i].cycle == 0 ) && pevent[i].cycle <= m_AnimOverlay[j].m_flCycle) )
{
if ( watch )
{
Msg( "%i (seq: %d) FE %i Normal cycle %f, prev %f ev %f (time %.3f)\n",
gpGlobals->tickcount,
(int)m_AnimOverlay[j].m_nSequence,
(int)pevent[i].Event(),
(float)pevent[i].cycle,
(float)m_flOverlayPrevEventCycle[j],
(float)m_AnimOverlay[j].m_flCycle,
gpGlobals->curtime );
}
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].Event(), pevent[ i ].pszOptions() );
}
}
m_flOverlayPrevEventCycle[j] = m_AnimOverlay[j].m_flCycle;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CStudioHdr *C_BaseAnimatingOverlay::OnNewModel()
{
CStudioHdr *hdr = BaseClass::OnNewModel();
// Clear out animation layers
for ( int i=0; i < m_AnimOverlay.Count(); i++ )
{
m_AnimOverlay[i].Reset();
m_AnimOverlay[i].m_nOrder = MAX_OVERLAYS;
}
return hdr;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseAnimatingOverlay::CheckInterpChanges( void )
{
CDisableRangeChecks disableRangeChecks;
for (int i = 0; i < m_AnimOverlay.Count(); i++)
{
int iHead, iPrev1, iPrev2;
m_iv_AnimOverlay[i].GetInterpolationInfo( gpGlobals->curtime, &iHead, &iPrev1, &iPrev2 );
float t0;
CAnimationLayer *pHead = m_iv_AnimOverlay[i].GetHistoryValue( iHead, t0 );
float t1;
CAnimationLayer *pPrev = m_iv_AnimOverlay[i].GetHistoryValue( iPrev1, t1 );
if ( !pHead || !pPrev )
continue;
m_AnimOverlay[ i ].m_nInvalidatePhysicsBits = CheckForSequenceBoxChanges( *pHead, *pPrev );
}
CheckForLayerPhysicsInvalidate();
}
void C_BaseAnimatingOverlay::CheckForLayerPhysicsInvalidate( void )
{
// When the layers interpolate they may change the animation or bbox so we
// have them accumulate the changes and call InvalidatePhysicsRecursive if any
// changes are needed.
int nInvalidatePhysicsChangeBits = 0;
int nLayerCount = m_AnimOverlay.Count();
for ( int i = 0; i < nLayerCount; ++i )
{
int nChangeBits = m_AnimOverlay[ i ].m_nInvalidatePhysicsBits;
if ( nChangeBits )
{
nInvalidatePhysicsChangeBits |= nChangeBits;
continue;
}
}
if ( nInvalidatePhysicsChangeBits )
{
InvalidatePhysicsRecursive( nInvalidatePhysicsChangeBits );
}
}

View File

@ -0,0 +1,77 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef C_BASEANIMATINGOVERLAY_H
#define C_BASEANIMATINGOVERLAY_H
#pragma once
#include "c_baseanimating.h"
#include "toolframework/itoolframework.h"
// For shared code.
#define CBaseAnimatingOverlay C_BaseAnimatingOverlay
class C_BaseAnimatingOverlay : public C_BaseAnimating
{
DECLARE_CLASS( C_BaseAnimatingOverlay, C_BaseAnimating );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
// Inherited from C_BaseAnimating
public:
virtual void AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime );
virtual void DoAnimationEvents( CStudioHdr *pStudioHdr );
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual CStudioHdr *OnNewModel();
virtual bool Interpolate( float flCurrentTime );
public:
enum
{
MAX_OVERLAYS = 15,
};
C_BaseAnimatingOverlay();
CAnimationLayer* GetAnimOverlay( int i );
void SetNumAnimOverlays( int num ); // This makes sure there is space for this # of layers.
int GetNumAnimOverlays() const;
void SetOverlayPrevEventCycle( int nSlot, float flValue );
void CheckInterpChanges( void );
void CheckForLayerPhysicsInvalidate( void );
private:
void CheckForLayerChanges( CStudioHdr *hdr, float currentTime );
CUtlVector < CAnimationLayer > m_AnimOverlay;
CUtlVector < CInterpolatedVar< CAnimationLayer > > m_iv_AnimOverlay;
float m_flOverlayPrevEventCycle[ MAX_OVERLAYS ];
C_BaseAnimatingOverlay( const C_BaseAnimatingOverlay & ); // not defined, not accessible
friend void ResizeAnimationLayerCallback( void *pStruct, int offsetToUtlVector, int len );
};
inline void C_BaseAnimatingOverlay::SetOverlayPrevEventCycle( int nSlot, float flValue )
{
m_flOverlayPrevEventCycle[nSlot] = flValue;
}
EXTERN_RECV_TABLE(DT_BaseAnimatingOverlay);
#endif // C_BASEANIMATINGOVERLAY_H

View File

@ -0,0 +1,96 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's C_BaseCombatCharacter entity
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basecombatcharacter.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if defined( CBaseCombatCharacter )
#undef CBaseCombatCharacter
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseCombatCharacter::C_BaseCombatCharacter()
{
for ( int i=0; i < m_iAmmo.Count(); i++ )
m_iAmmo.Set( i, 0 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BaseCombatCharacter::~C_BaseCombatCharacter()
{
}
/*
//-----------------------------------------------------------------------------
// Purpose: Returns the amount of ammunition of the specified type the character's carrying
//-----------------------------------------------------------------------------
int C_BaseCombatCharacter::GetAmmoCount( char *szName ) const
{
return GetAmmoCount( g_pGameRules->GetAmmoDef()->Index(szName) );
}
*/
//-----------------------------------------------------------------------------
// Purpose: Overload our muzzle flash and send it to any actively held weapon
//-----------------------------------------------------------------------------
void C_BaseCombatCharacter::DoMuzzleFlash()
{
// Our weapon takes our muzzle flash command
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
if ( pWeapon )
{
pWeapon->DoMuzzleFlash();
//NOTENOTE: We do not chain to the base here
}
else
{
BaseClass::DoMuzzleFlash();
}
}
IMPLEMENT_CLIENTCLASS(C_BaseCombatCharacter, DT_BaseCombatCharacter, CBaseCombatCharacter);
// Only send active weapon index to local player
BEGIN_RECV_TABLE_NOBASE( C_BaseCombatCharacter, DT_BCCLocalPlayerExclusive )
RecvPropTime( RECVINFO( m_flNextAttack ) ),
RecvPropArray3( RECVINFO_ARRAY(m_hMyWeapons), RecvPropEHandle( RECVINFO( m_hMyWeapons[0] ) ) ),
END_RECV_TABLE();
BEGIN_RECV_TABLE(C_BaseCombatCharacter, DT_BaseCombatCharacter)
RecvPropDataTable( "bcc_localdata", 0, 0, &REFERENCE_RECV_TABLE(DT_BCCLocalPlayerExclusive) ),
RecvPropEHandle( RECVINFO( m_hActiveWeapon ) ),
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseCombatCharacter )
DEFINE_PRED_ARRAY( m_iAmmo, FIELD_INTEGER, MAX_AMMO_TYPES, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flNextAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_hActiveWeapon, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_ARRAY( m_hMyWeapons, FIELD_EHANDLE, MAX_WEAPONS, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()

View File

@ -0,0 +1,140 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines the client-side representation of CBaseCombatCharacter.
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_BASECOMBATCHARACTER_H
#define C_BASECOMBATCHARACTER_H
#ifdef _WIN32
#pragma once
#endif
#include "shareddefs.h"
#include "c_baseflex.h"
#define BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE 0.9f
class C_BaseCombatWeapon;
class C_WeaponCombatShield;
class C_BaseCombatCharacter : public C_BaseFlex
{
DECLARE_CLASS( C_BaseCombatCharacter, C_BaseFlex );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_BaseCombatCharacter( void );
virtual ~C_BaseCombatCharacter( void );
virtual bool IsBaseCombatCharacter( void ) { return true; };
virtual C_BaseCombatCharacter *MyCombatCharacterPointer( void ) { return this; }
// -----------------------
// Vision
// -----------------------
enum FieldOfViewCheckType { USE_FOV, DISREGARD_FOV };
bool IsAbleToSee( const CBaseEntity *entity, FieldOfViewCheckType checkFOV ); // Visible starts with line of sight, and adds all the extra game checks like fog, smoke, camo...
bool IsAbleToSee( C_BaseCombatCharacter *pBCC, FieldOfViewCheckType checkFOV ); // Visible starts with line of sight, and adds all the extra game checks like fog, smoke, camo...
virtual bool IsLookingTowards( const CBaseEntity *target, float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
virtual bool IsLookingTowards( const Vector &target, float cosTolerance = BCC_DEFAULT_LOOK_TOWARDS_TOLERANCE ) const; // return true if our view direction is pointing at the given target, within the cosine of the angular tolerance. LINE OF SIGHT IS NOT CHECKED.
virtual bool IsInFieldOfView( CBaseEntity *entity ) const; // Calls IsLookingAt with the current field of view.
virtual bool IsInFieldOfView( const Vector &pos ) const;
enum LineOfSightCheckType
{
IGNORE_NOTHING,
IGNORE_ACTORS
};
virtual bool IsLineOfSightClear( CBaseEntity *entity, LineOfSightCheckType checkType = IGNORE_NOTHING ) const;// strictly LOS check with no other considerations
virtual bool IsLineOfSightClear( const Vector &pos, LineOfSightCheckType checkType = IGNORE_NOTHING, CBaseEntity *entityToIgnore = NULL ) const;
// -----------------------
// Ammo
// -----------------------
void RemoveAmmo( int iCount, int iAmmoIndex );
void RemoveAmmo( int iCount, const char *szName );
void RemoveAllAmmo( );
int GetAmmoCount( int iAmmoIndex ) const;
int GetAmmoCount( char *szName ) const;
virtual C_BaseCombatWeapon* Weapon_OwnsThisType( const char *pszWeapon, int iSubType = 0 ) const; // True if already owns a weapon of this class
virtual int Weapon_GetSlot( const char *pszWeapon, int iSubType = 0 ) const; // Returns -1 if they don't have one
virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 );
virtual bool Weapon_CanSwitchTo(C_BaseCombatWeapon *pWeapon);
// I can't use my current weapon anymore. Switch me to the next best weapon.
bool SwitchToNextBestWeapon(C_BaseCombatWeapon *pCurrent);
virtual C_BaseCombatWeapon *GetActiveWeapon( void ) const;
int WeaponCount() const;
virtual C_BaseCombatWeapon *GetWeapon( int i ) const;
// This is a sort of hack back-door only used by physgun!
void SetAmmoCount( int iCount, int iAmmoIndex );
float GetNextAttack() const { return m_flNextAttack; }
void SetNextAttack( float flWait ) { m_flNextAttack = flWait; }
virtual int BloodColor();
// Blood color (see BLOOD_COLOR_* macros in baseentity.h)
void SetBloodColor( int nBloodColor );
virtual void DoMuzzleFlash();
public:
// BEGIN PREDICTION DATA COMPACTION (these fields are together to allow for faster copying in prediction system)
float m_flNextAttack;
private:
bool ComputeLOS( const Vector &vecEyePosition, const Vector &vecTarget ) const;
private:
CNetworkArray( int, m_iAmmo, MAX_AMMO_TYPES );
CHandle<C_BaseCombatWeapon> m_hMyWeapons[MAX_WEAPONS];
CHandle< C_BaseCombatWeapon > m_hActiveWeapon;
// END PREDICTION DATA COMPACTION
protected:
int m_bloodColor; // color of blood particless
private:
private:
C_BaseCombatCharacter( const C_BaseCombatCharacter & ); // not defined, not accessible
//-----------------------
};
inline C_BaseCombatCharacter *ToBaseCombatCharacter( C_BaseEntity *pEntity )
{
return pEntity ? pEntity->MyCombatCharacterPointer() : NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
inline int C_BaseCombatCharacter::WeaponCount() const
{
return MAX_WEAPONS;
}
EXTERN_RECV_TABLE(DT_BaseCombatCharacter);
#endif // C_BASECOMBATCHARACTER_H

View File

@ -0,0 +1,545 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side implementation of CBaseCombatWeapon.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "history_resource.h"
#include "iclientmode.h"
#include "iinput.h"
#include "weapon_selection.h"
#include "hud_crosshair.h"
#include "engine/ivmodelinfo.h"
#include "tier0/vprof.h"
#include "hltvcamera.h"
#include "tier1/KeyValues.h"
#include "toolframework/itoolframework.h"
#include "toolframework_client.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::SetDormant( bool bDormant )
{
// If I'm going from active to dormant and I'm carried by another player, holster me.
if ( !IsDormant() && bDormant && !IsCarriedByLocalPlayer() )
{
Holster( NULL );
}
BaseClass::SetDormant( bDormant );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::NotifyShouldTransmit( ShouldTransmitState_t state )
{
BaseClass::NotifyShouldTransmit(state);
if (state == SHOULDTRANSMIT_END)
{
if (m_iState == WEAPON_IS_ACTIVE)
{
m_iState = WEAPON_IS_CARRIED_BY_PLAYER;
}
}
else if( state == SHOULDTRANSMIT_START )
{
if( m_iState == WEAPON_IS_CARRIED_BY_PLAYER )
{
if( GetOwner() && GetOwner()->GetActiveWeapon() == this )
{
// Restore the Activeness of the weapon if we client-twiddled it off in the first case above.
m_iState = WEAPON_IS_ACTIVE;
}
}
}
}
static inline bool ShouldDrawLocalPlayer( C_BasePlayer *pl )
{
Assert( pl );
return pl->ShouldDrawLocalPlayer();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnRestore()
{
BaseClass::OnRestore();
// if the player is holding this weapon,
// mark it as just restored so it won't show as a new pickup
if ( C_BasePlayer::IsLocalPlayer( GetOwner() ) )
{
m_bJustRestored = true;
}
}
int C_BaseCombatWeapon::GetWorldModelIndex( void )
{
return m_iWorldModelIndex;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
// If it's being carried by the *local* player, on the first update,
// find the registered weapon for this ID
C_BaseCombatCharacter *pOwner = GetOwner();
C_BasePlayer *pPlayer = ToBasePlayer( pOwner );
// check if weapon is carried by local player
bool bIsLocalPlayer = C_BasePlayer::IsLocalPlayer( pPlayer );
if ( bIsLocalPlayer )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD( C_BasePlayer::GetSplitScreenSlotForPlayer( pPlayer ) );
// If I was just picked up, or created & immediately carried, add myself to this client's list of weapons
if ( ( m_iState != WEAPON_NOT_CARRIED ) &&
( m_iOldState == WEAPON_NOT_CARRIED ) )
{
// Tell the HUD this weapon's been picked up
if ( ShouldDrawPickup() )
{
CBaseHudWeaponSelection *pHudSelection = GetHudWeaponSelection();
if ( pHudSelection )
{
pHudSelection->OnWeaponPickup( this );
}
pPlayer->EmitSound( "Player.PickupWeapon" );
}
}
}
UpdateVisibility();
m_iOldState = m_iState;
m_bJustRestored = false;
}
//-----------------------------------------------------------------------------
// Is anyone carrying it?
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsBeingCarried() const
{
return ( m_hOwner.Get() != NULL );
}
//-----------------------------------------------------------------------------
// Is the carrier alive?
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsCarrierAlive() const
{
if ( !m_hOwner.Get() )
return false;
return m_hOwner.Get()->GetHealth() > 0;
}
//-----------------------------------------------------------------------------
// Should this object cast shadows?
//-----------------------------------------------------------------------------
ShadowType_t C_BaseCombatWeapon::ShadowCastType()
{
if ( IsEffectActive( /*EF_NODRAW |*/ EF_NOSHADOW ) )
return SHADOWS_NONE;
if (!IsBeingCarried())
return SHADOWS_RENDER_TO_TEXTURE;
if (IsCarriedByLocalPlayer())
return SHADOWS_NONE;
return (m_iState != WEAPON_IS_CARRIED_BY_PLAYER) ? SHADOWS_RENDER_TO_TEXTURE : SHADOWS_NONE;
}
//-----------------------------------------------------------------------------
// Purpose: This weapon is the active weapon, and it should now draw anything
// it wants to. This gets called every frame.
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::Redraw()
{
if ( GetClientMode()->ShouldDrawCrosshair() )
{
DrawCrosshair();
}
// ammo drawing has been moved into hud_ammo.cpp
}
//-----------------------------------------------------------------------------
// Purpose: Draw the weapon's crosshair
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::DrawCrosshair()
{
#ifndef INFESTED_DLL
C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
if ( !player )
return;
Color clr = GetHud().m_clrNormal;
/*
// TEST: if the thing under your crosshair is on a different team, light the crosshair with a different color.
Vector vShootPos, vShootAngles;
GetShootPosition( vShootPos, vShootAngles );
Vector vForward;
AngleVectors( vShootAngles, &vForward );
// Change the color depending on if we're looking at a friend or an enemy.
CPartitionFilterListMask filter( PARTITION_ALL_CLIENT_EDICTS );
trace_t tr;
traceline->TraceLine( vShootPos, vShootPos + vForward * 10000, COLLISION_GROUP_NONE, MASK_SHOT, &tr, true, ~0, &filter );
if ( tr.index != 0 && tr.index != INVALID_CLIENTENTITY_HANDLE )
{
C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( tr.index );
if ( pEnt )
{
if ( pEnt->GetTeamNumber() != player->GetTeamNumber() )
{
g = b = 0;
}
}
}
*/
CHudCrosshair *crosshair = GET_HUDELEMENT( CHudCrosshair );
if ( !crosshair )
return;
// Find out if this weapon's auto-aimed onto a target
bool bOnTarget = ( m_iState == WEAPON_IS_ACTIVE ) && player->m_fOnTarget;
if ( player->GetFOV() >= 90 )
{
// normal crosshairs
if ( bOnTarget && GetWpnData().iconAutoaim )
{
clr[3] = 255;
crosshair->SetCrosshair( GetWpnData().iconAutoaim, clr );
}
else if ( GetWpnData().iconCrosshair )
{
clr[3] = 255;
crosshair->SetCrosshair( GetWpnData().iconCrosshair, clr );
}
else
{
crosshair->ResetCrosshair();
}
}
else
{
Color white( 255, 255, 255, 255 );
// zoomed crosshairs
if (bOnTarget && GetWpnData().iconZoomedAutoaim)
crosshair->SetCrosshair(GetWpnData().iconZoomedAutoaim, white);
else if ( GetWpnData().iconZoomedCrosshair )
crosshair->SetCrosshair( GetWpnData().iconZoomedCrosshair, white );
else
crosshair->ResetCrosshair();
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: This weapon is the active weapon, and the viewmodel for it was just drawn.
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::ViewModelDrawn( C_BaseViewModel *pViewModel )
{
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this client's carrying this weapon
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsCarriedByLocalPlayer( void )
{
if ( !GetOwner() )
return false;
return ( C_BasePlayer::IsLocalPlayer( GetOwner() ) );
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this weapon is the local client's currently wielded weapon
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::IsActiveByLocalPlayer( void )
{
if ( IsCarriedByLocalPlayer() )
{
return (m_iState == WEAPON_IS_ACTIVE);
}
return false;
}
bool C_BaseCombatWeapon::GetShootPosition( Vector &vOrigin, QAngle &vAngles )
{
// Get the entity because the weapon doesn't have the right angles.
C_BaseCombatCharacter *pEnt = ToBaseCombatCharacter( GetOwner() );
if ( pEnt )
{
if ( pEnt == C_BasePlayer::GetLocalPlayer() )
{
vAngles = pEnt->EyeAngles();
}
else
{
vAngles = pEnt->GetRenderAngles();
}
}
else
{
vAngles.Init();
}
C_BasePlayer *player = ToBasePlayer( pEnt );
bool bUseViewModel = false;
if ( C_BasePlayer::IsLocalPlayer( pEnt ) )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( pEnt );
bUseViewModel = !player->ShouldDrawLocalPlayer();
}
QAngle vDummy;
if ( IsActiveByLocalPlayer() && bUseViewModel )
{
C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL;
if ( vm )
{
int iAttachment = vm->LookupAttachment( "muzzle" );
if ( vm->GetAttachment( iAttachment, vOrigin, vDummy ) )
{
return true;
}
}
}
else
{
// Thirdperson
int iAttachment = LookupAttachment( "muzzle" );
if ( GetAttachment( iAttachment, vOrigin, vDummy ) )
{
return true;
}
}
vOrigin = GetRenderOrigin();
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::ShouldDraw( void )
{
if ( m_iWorldModelIndex == 0 )
return false;
// FIXME: All weapons with owners are set to transmit in CBaseCombatWeapon::UpdateTransmitState,
// even if they have EF_NODRAW set, so we have to check this here. Ideally they would never
// transmit except for the weapons owned by the local player.
if ( IsEffectActive( EF_NODRAW ) )
return false;
C_BaseCombatCharacter *pOwner = GetOwner();
// weapon has no owner, always draw it
if ( !pOwner )
return true;
bool bIsActive = ( m_iState == WEAPON_IS_ACTIVE );
C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
// carried by local player?
if ( pOwner == pLocalPlayer )
{
// Only ever show the active weapon
if ( !bIsActive )
return false;
// 3rd person mode
if ( pLocalPlayer->ShouldDrawLocalPlayer() )
return true;
// don't draw active weapon if not in some kind of 3rd person mode, the viewmodel will do that
return false;
}
// If it's a player, then only show active weapons
if ( pOwner->IsPlayer() )
{
// Show it if it's active...
return bIsActive;
}
// FIXME: We may want to only show active weapons on NPCs
// These are carried by AIs; always show them
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Return true if a weapon-pickup icon should be displayed when this weapon is received
//-----------------------------------------------------------------------------
bool C_BaseCombatWeapon::ShouldDrawPickup( void )
{
if ( GetWeaponFlags() & ITEM_FLAG_NOITEMPICKUP )
return false;
if ( m_bJustRestored )
return false;
return true;
}
//----------------------------------------------------------------------------
// Hooks into the fast path render system
//----------------------------------------------------------------------------
IClientModelRenderable* C_BaseCombatWeapon::GetClientModelRenderable()
{
if ( !m_bReadyToDraw )
return 0;
// check if local player chases owner of this weapon in first person
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer && localplayer->IsObserver() && GetOwner() )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return NULL;
}
if ( !BaseClass::GetClientModelRenderable() )
return NULL;
EnsureCorrectRenderingModel();
return this;
}
//-----------------------------------------------------------------------------
// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried
// by this player, otherwise draw the worldmodel.
//-----------------------------------------------------------------------------
int C_BaseCombatWeapon::DrawModel( int flags, const RenderableInstance_t &instance )
{
VPROF_BUDGET( "C_BaseCombatWeapon::DrawModel", VPROF_BUDGETGROUP_MODEL_RENDERING );
if ( !m_bReadyToDraw )
return 0;
if ( !IsVisible() )
return 0;
// check if local player chases owner of this weapon in first person
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer && localplayer->IsObserver() && GetOwner() )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return false;
}
// See comment below
EnsureCorrectRenderingModel();
return BaseClass::DrawModel( flags, instance );
}
// If the local player is visible (thirdperson mode, tf2 taunts, etc., then make sure that we are using the
// w_ (world) model not the v_ (view) model or else the model can flicker, etc.
// Otherwise, if we're not the local player, always use the world model
void C_BaseCombatWeapon::EnsureCorrectRenderingModel()
{
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer &&
localplayer == GetOwner() &&
!localplayer->ShouldDrawLocalPlayer() )
{
return;
}
// BRJ 10/14/02
// FIXME: Remove when Yahn's client-side prediction is done
// It's a hacky workaround for the model indices fighting
// (GetRenderBounds uses the model index, which is for the view model)
SetModelIndex( GetWorldModelIndex() );
// Validate our current sequence just in case ( in theory the view and weapon models should have the same sequences for sequences that overlap at least )
CStudioHdr *pStudioHdr = GetModelPtr();
if ( pStudioHdr &&
GetSequence() >= pStudioHdr->GetNumSeq() )
{
SetSequence( 0 );
}
}
//-----------------------------------------------------------------------------
// tool recording
//-----------------------------------------------------------------------------
void C_BaseCombatWeapon::GetToolRecordingState( KeyValues *msg )
{
if ( !ToolsEnabled() )
return;
int nModelIndex = GetModelIndex();
int nWorldModelIndex = GetWorldModelIndex();
if ( nModelIndex != nWorldModelIndex )
{
SetModelIndex( nWorldModelIndex );
}
BaseClass::GetToolRecordingState( msg );
if ( m_iState == WEAPON_NOT_CARRIED )
{
BaseEntityRecordingState_t *pBaseEntity = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );
pBaseEntity->m_nOwner = -1;
}
else
{
msg->SetInt( "worldmodel", 1 );
if ( m_iState == WEAPON_IS_ACTIVE )
{
BaseEntityRecordingState_t *pBaseEntity = (BaseEntityRecordingState_t*)msg->GetPtr( "baseentity" );
pBaseEntity->m_bVisible = true;
}
}
if ( nModelIndex != nWorldModelIndex )
{
SetModelIndex( nModelIndex );
}
}

View File

@ -0,0 +1,22 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client's CBaseCombatWeapon entity
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASECOMBATWEAPON_H
#define C_BASECOMBATWEAPON_H
#ifdef _WIN32
#pragma once
#endif
#include "basecombatweapon_shared.h"
#include "weapons_resource.h"
class CViewSetup;
class C_BaseViewModel;
#endif // C_BASECOMBATWEAPON

View File

@ -0,0 +1,28 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basedoor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef CBaseDoor
#undef CBaseDoor
#endif
IMPLEMENT_CLIENTCLASS_DT(C_BaseDoor, DT_BaseDoor, CBaseDoor)
RecvPropFloat(RECVINFO(m_flWaveHeight)),
END_RECV_TABLE()
C_BaseDoor::C_BaseDoor( void )
{
m_flWaveHeight = 0.0f;
}
C_BaseDoor::~C_BaseDoor( void )
{
}

33
game/client/c_basedoor.h Normal file
View File

@ -0,0 +1,33 @@
//========= Copyright Š 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#if !defined( C_BASEDOOR_H )
#define C_BASEDOOR_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
#include "c_basetoggle.h"
#if defined( CLIENT_DLL )
#define CBaseDoor C_BaseDoor
#endif
class C_BaseDoor : public C_BaseToggle
{
public:
DECLARE_CLASS( C_BaseDoor, C_BaseToggle );
DECLARE_CLIENTCLASS();
C_BaseDoor( void );
~C_BaseDoor( void );
public:
float m_flWaveHeight;
};
#endif // C_BASEDOOR_H

6436
game/client/c_baseentity.cpp Normal file

File diff suppressed because it is too large Load Diff

2508
game/client/c_baseentity.h Normal file

File diff suppressed because it is too large Load Diff

2144
game/client/c_baseflex.cpp Normal file

File diff suppressed because it is too large Load Diff

309
game/client/c_baseflex.h Normal file
View File

@ -0,0 +1,309 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
// Client-side CBasePlayer
#ifndef C_STUDIOFLEX_H
#define C_STUDIOFLEX_H
#pragma once
#include "c_baseanimating.h"
#include "c_baseanimatingoverlay.h"
#include "sceneentity_shared.h"
#include "UtlVector.h"
//-----------------------------------------------------------------------------
// Purpose: Item in list of loaded scene files
//-----------------------------------------------------------------------------
class CFlexSceneFile
{
public:
enum
{
MAX_FLEX_FILENAME = 128,
};
char filename[ MAX_FLEX_FILENAME ];
void *buffer;
};
// For phoneme emphasis track
struct Emphasized_Phoneme;
class CSentence;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BaseFlex : public C_BaseAnimatingOverlay
{
DECLARE_CLASS( C_BaseFlex, C_BaseAnimatingOverlay );
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_BaseFlex();
virtual ~C_BaseFlex();
virtual void Spawn();
virtual IClientModelRenderable* GetClientModelRenderable();
virtual void InitPhonemeMappings();
void SetupMappings( char const *pchFileRoot );
virtual CStudioHdr *OnNewModel( void );
virtual void StandardBlendingRules( CStudioHdr *hdr, Vector pos[], QuaternionAligned q[], float currentTime, int boneMask );
virtual void OnThreadedDrawSetup();
// model specific
virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed );
virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights );
virtual bool UsesFlexDelayedWeights();
virtual bool GetSoundSpatialization( SpatializationInfo_t& info );
virtual void GetToolRecordingState( KeyValues *msg );
// Called at the lowest level to actually apply a flex animation
void AddFlexAnimation( CSceneEventInfo *info );
void SetFlexWeight( LocalFlexController_t index, float value );
float GetFlexWeight( LocalFlexController_t index );
// Look up flex controller index by global name
LocalFlexController_t FindFlexController( const char *szName );
public:
Vector m_viewtarget;
CInterpolatedVar< Vector > m_iv_viewtarget;
// indexed by model local flexcontroller
float m_flexWeight[MAXSTUDIOFLEXCTRL];
CInterpolatedVarArray< float, MAXSTUDIOFLEXCTRL > m_iv_flexWeight;
int m_blinktoggle;
static int AddGlobalFlexController( char *szName );
static char const *GetGlobalFlexControllerName( int idx );
// bah, this should be unified with all prev/current stuff.
public:
// Keep track of what scenes are being played
void StartChoreoScene( CChoreoScene *scene );
void RemoveChoreoScene( CChoreoScene *scene );
// Start the specifics of an scene event
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, C_BaseEntity *pTarget );
virtual bool ProcessSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
// Remove all playing events
void ClearSceneEvents( CChoreoScene *scene, bool canceled );
// Stop specifics of event
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
// Add the event to the queue for this actor
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false, C_SceneEntity *pSceneEntity = NULL );
// Remove the event from the queue for this actor
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );
// Checks to see if the event should be considered "completed"
bool CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event );
// Checks to see if a event should be considered "completed"
virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event );
int FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key );
void EnsureTranslations( const flexsettinghdr_t *pSettinghdr );
// For handling scene files
const void *FindSceneFile( const char *filename );
static void InvalidateFlexCaches();
bool IsFlexCacheValid() const;
private:
Vector SetViewTarget( CStudioHdr *pStudioHdr, const float *pGlobalFlexWeight );
void RunFlexRules( CStudioHdr *pStudioHdr, const float *pGlobalFlexWeight, float *dest );
// Manipulation of events for the object
// Should be called by think function to process all scene events
// The default implementation resets m_flexWeight array and calls
// AddSceneEvents
void ProcessSceneEvents( bool bFlexEvents, float *pGlobalFlexWeight );
// Assumes m_flexWeight array has been set up, this adds the actual currently playing
// expressions to the flex weights and adds other scene events as needed
bool ProcessSceneEvent( float *pGlobalFlexWeight, bool bFlexEvents, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool RequestStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
bool ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool ProcessFlexSettingSceneEvent( float *pGlobalFlexWeight, CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
void AddFlexSetting( float *pGlobalFlexWeight, const char *expr, float scale,
const flexsettinghdr_t *pSettinghdr, bool newexpression );
// Array of active SceneEvents, in order oldest to newest
CUtlVector < CSceneEventInfo > m_SceneEvents;
CUtlVector < CChoreoScene * > m_ActiveChoreoScenes;
bool HasSceneEvents() const;
private:
// Mapping for each loaded scene file used by this actor
struct FS_LocalToGlobal_t
{
explicit FS_LocalToGlobal_t() :
m_Key( 0 ),
m_nCount( 0 ),
m_Mapping( 0 )
{
}
explicit FS_LocalToGlobal_t( const flexsettinghdr_t *key ) :
m_Key( key ),
m_nCount( 0 ),
m_Mapping( 0 )
{
}
void SetCount( int count )
{
Assert( !m_Mapping );
Assert( count > 0 );
m_nCount = count;
m_Mapping = new int[ m_nCount ];
Q_memset( m_Mapping, 0, m_nCount * sizeof( int ) );
}
FS_LocalToGlobal_t( const FS_LocalToGlobal_t& src )
{
m_Key = src.m_Key;
delete m_Mapping;
m_Mapping = new int[ src.m_nCount ];
Q_memcpy( m_Mapping, src.m_Mapping, src.m_nCount * sizeof( int ) );
m_nCount = src.m_nCount;
}
~FS_LocalToGlobal_t()
{
delete m_Mapping;
m_nCount = 0;
m_Mapping = 0;
}
const flexsettinghdr_t *m_Key;
int m_nCount;
int *m_Mapping;
};
static bool FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs );
CUtlRBTree< FS_LocalToGlobal_t, unsigned short > m_LocalToGlobal;
float m_blinktime;
int m_prevblinktoggle;
int m_iBlink;
LocalFlexController_t m_iEyeUpdown;
LocalFlexController_t m_iEyeRightleft;
int m_iMouthAttachment;
float *m_flFlexDelayedWeight;
int m_iMostRecentFlexCounter;
Vector m_CachedViewTarget;
CUtlVector< float > m_CachedFlexWeights;
CUtlVector< float > m_CachedDelayedFlexWeights;
// shared flex controllers
static int g_numflexcontrollers;
static char *g_flexcontroller[MAXSTUDIOFLEXCTRL*4]; // room for global set of flexcontrollers
static float s_pGlobalFlexWeight[MAXSTUDIOFLEXCTRL*4];
protected:
enum
{
PHONEME_CLASS_WEAK = 0,
PHONEME_CLASS_NORMAL,
PHONEME_CLASS_STRONG,
NUM_PHONEME_CLASSES
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
struct Emphasized_Phoneme
{
// Global fields, setup at start
char classname[ 64 ];
bool required;
// Global fields setup first time tracks played
bool basechecked;
const flexsettinghdr_t *base;
const flexsetting_t *exp;
// Local fields, processed for each sentence
bool valid;
float amount;
};
Emphasized_Phoneme m_PhonemeClasses[ NUM_PHONEME_CLASSES ];
private:
C_BaseFlex( const C_BaseFlex & ); // not defined, not accessible
const flexsetting_t *FindNamedSetting( const flexsettinghdr_t *pSettinghdr, const char *expr );
void ProcessVisemes( Emphasized_Phoneme *classes, float *pGlobalFlexWeight );
void AddVisemesForSentence( float *pGlobalFlexWeight, Emphasized_Phoneme *classes, float emphasis_intensity, CSentence *sentence, float t, float dt, bool juststarted );
void AddViseme( float *pGlobalFlexWeight, Emphasized_Phoneme *classes, float emphasis_intensity, int phoneme, float scale, bool newexpression );
bool SetupEmphasisBlend( Emphasized_Phoneme *classes, int phoneme );
void ComputeBlendedSetting( Emphasized_Phoneme *classes, float emphasis_intensity );
#ifdef HL2_CLIENT_DLL
public:
Vector m_vecLean;
CInterpolatedVar< Vector > m_iv_vecLean;
Vector m_vecShift;
CInterpolatedVar< Vector > m_iv_vecShift;
#endif
};
//-----------------------------------------------------------------------------
// Do we have active expressions?
//-----------------------------------------------------------------------------
inline bool C_BaseFlex::HasSceneEvents() const
{
return m_SceneEvents.Count() != 0;
}
EXTERN_RECV_TABLE(DT_BaseFlex);
float *GetVisemeWeights( int phoneme );
#endif // C_STUDIOFLEX_H

3820
game/client/c_baselesson.cpp Normal file

File diff suppressed because it is too large Load Diff

446
game/client/c_baselesson.h Normal file
View File

@ -0,0 +1,446 @@
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client handler for instruction players how to play
//
//=============================================================================//
#ifndef _C_BASELESSON_H_
#define _C_BASELESSON_H_
#include "GameEventListener.h"
#include "hud_locator_target.h"
#define DECLARE_LESSON( _lessonClassName, _baseLessonClassName ) \
typedef _baseLessonClassName BaseClass;\
typedef _lessonClassName ThisClass;\
_lessonClassName( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity, int nSplitScreenSlot )\
: _baseLessonClassName( pchName, bIsDefaultHolder, bIsOpenOpportunity, nSplitScreenSlot )\
{\
Init();\
}
enum LessonInstanceType
{
LESSON_INSTANCE_MULTIPLE,
LESSON_INSTANCE_SINGLE_OPEN,
LESSON_INSTANCE_FIXED_REPLACE,
LESSON_INSTANCE_SINGLE_ACTIVE,
LESSON_INSTANCE_TYPE_TOTAL
};
// This is used to solve a problem where bots can take the place of a player, where on or the other don't have valid entities on the client at the same time
#define MAX_DELAYED_PLAYER_SWAPS 8
struct delayed_player_swap_t
{
CHandle<C_BaseEntity> *phHandleToChange;
int iNewUserID;
delayed_player_swap_t( void )
{
phHandleToChange = NULL;
iNewUserID = -1;
}
};
abstract_class CBaseLesson : public CGameEventListener
{
public:
CBaseLesson( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity, int nSplitScreenSlot );
virtual ~CBaseLesson( void );
void AddPrerequisite( const char *pchLessonName );
const CGameInstructorSymbol& GetNameSymbol( void ) const { return m_stringName; }
const char * GetName( void ) const { return m_stringName.String(); }
int GetPriority( void ) const { return m_iPriority; }
const char * GetCloseReason( void ) const { return m_stringCloseReason.String(); }
void SetCloseReason( const char *pchReason ) { m_stringCloseReason = pchReason; }
CBaseLesson* GetRoot( void ) const { return m_pRoot; }
void SetRoot( CBaseLesson *pRoot );
const CUtlVector < CBaseLesson * >* GetChildren( void ) const { return &m_OpenOpportunities; }
float GetInitTime( void ) { return m_fInitTime; }
void SetStartTime( void ) { m_fStartTime = gpGlobals->curtime; }
void ResetStartTime( void ) { m_fStartTime = 0.0f; m_bHasPlayedSound = false; }
bool ShouldShowSpew( void );
bool NoPriority( void ) const;
bool IsDefaultHolder( void ) const { return m_bIsDefaultHolder; }
bool IsOpenOpportunity( void ) const { return m_bIsOpenOpportunity; }
bool IsLocked( void ) const;
bool CanOpenWhenDead( void ) const { return m_bCanOpenWhenDead; }
bool IsInstructing( void ) const { return ( m_fStartTime > 0.0f ); }
bool IsLearned( void ) const;
bool PrerequisitesHaveBeenMet( void ) const;
bool IsTimedOut( void );
int InstanceType( void ) const { return m_iInstanceType; }
const CGameInstructorSymbol& GetReplaceKeySymbol( void ) const { return m_stringReplaceKey; }
const char* GetReplaceKey( void ) const { return m_stringReplaceKey.String(); }
int GetFixedInstancesMax( void ) const { return m_iFixedInstancesMax; }
bool ShouldReplaceOnlyWhenStopped( void ) const { return m_bReplaceOnlyWhenStopped; }
void SetInstanceActive( bool bInstanceActive ) { m_bInstanceActive = bInstanceActive; }
bool IsInstanceActive( void ) const { return m_bInstanceActive; }
void ResetDisplaysAndSuccesses( void );
bool IncDisplayCount( void );
bool IncSuccessCount( void );
void SetDisplayCount( int iDisplayCount ) { m_iDisplayCount = iDisplayCount; }
void SetSuccessCount( int iSuccessCount ) { m_iSuccessCount = iSuccessCount; }
int GetDisplayCount( void ) const { return m_iDisplayCount; }
int GetSuccessCount( void ) const { return m_iSuccessCount; }
int GetDisplayLimit( void ) const { return m_iDisplayLimit; }
int GetSuccessLimit( void ) const { return m_iSuccessLimit; }
void Init( void ); // NOT virtual, each constructor calls their own
virtual void InitPrerequisites( void ) {};
virtual void Start( void ) = 0;
virtual void Stop( void ) = 0;
virtual void OnOpen( void ) {};
virtual void Update( void ) {};
virtual void UpdateInactive( void ) {};
virtual bool ShouldDisplay( void ) const { return true; }
virtual bool IsVisible( void ) const { return true; }
virtual bool WasDisplayed( void ) const { return m_bWasDisplayed ? true : false; }
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID ) {}
virtual void TakePlaceOf( CBaseLesson *pLesson );
int GetSplitScreenSlot() const { return m_nSplitScreenSlot; }
const char *GetGroup() { return m_szLessonGroup.String(); }
void SetEnabled( bool bEnabled ) { m_bDisabled = !bEnabled; }
protected:
void MarkSucceeded( void );
void CloseOpportunity( const char *pchReason );
bool DoDelayedPlayerSwaps( void ) const;
private:
CBaseLesson *m_pRoot;
CUtlVector < CBaseLesson * > m_OpenOpportunities;
CUtlVector < const CBaseLesson * > m_Prerequisites;
CGameInstructorSymbol m_stringCloseReason;
CGameInstructorSymbol m_stringName;
bool m_bInstanceActive : 1;
bool m_bSuccessCounted : 1;
bool m_bIsDefaultHolder : 1;
bool m_bIsOpenOpportunity : 1;
protected:
LessonInstanceType m_iInstanceType;
int m_iPriority;
CGameInstructorSymbol m_stringReplaceKey;
int m_iFixedInstancesMax;
bool m_bReplaceOnlyWhenStopped;
int m_iTeam;
bool m_bOnlyKeyboard;
bool m_bOnlyGamepad;
int m_iDisplayLimit;
int m_iDisplayCount;
bool m_bWasDisplayed;
int m_iSuccessLimit;
int m_iSuccessCount;
int m_nSplitScreenSlot;
float m_fLockDuration;
float m_fTimeout;
float m_fInitTime;
float m_fStartTime;
float m_fLockTime;
float m_fUpdateInterval;
bool m_bHasPlayedSound;
CGameInstructorSymbol m_szStartSound;
CGameInstructorSymbol m_szLessonGroup;
bool m_bCanOpenWhenDead;
bool m_bBumpWithTimeoutWhenLearned;
bool m_bCanTimeoutWhileInactive;
bool m_bDisabled;
// Right now we can only queue up 4 swaps...
// this number can be increased if more entity handle scripted variables are added
mutable delayed_player_swap_t m_pDelayedPlayerSwap[ MAX_DELAYED_PLAYER_SWAPS ];
mutable int m_iNumDelayedPlayerSwaps;
public:
// Colors for console spew in verbose mode
static Color m_rgbaVerboseHeader;
static Color m_rgbaVerbosePlain;
static Color m_rgbaVerboseName;
static Color m_rgbaVerboseOpen;
static Color m_rgbaVerboseClose;
static Color m_rgbaVerboseSuccess;
static Color m_rgbaVerboseUpdate;
};
class CTextLesson : public CBaseLesson
{
public:
DECLARE_LESSON( CTextLesson, CBaseLesson );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void Start( void );
virtual void Stop( void );
protected:
CGameInstructorSymbol m_szDisplayText;
CGameInstructorSymbol m_szDisplayParamText;
CGameInstructorSymbol m_szBinding;
CGameInstructorSymbol m_szGamepadBinding;
};
class CIconLesson : public CTextLesson
{
public:
DECLARE_LESSON( CIconLesson, CTextLesson );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void Start( void );
virtual void Stop( void );
virtual void Update( void );
virtual void UpdateInactive( void );
virtual bool ShouldDisplay( void ) const;
virtual bool IsVisible( void ) const;
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID );
virtual void TakePlaceOf( CBaseLesson *pLesson );
void SetLocatorBinding( CLocatorTarget * pLocatorTarget );
const char *GetCaptionColorString() { return m_szCaptionColor.String(); }
bool IsPresentComplete( void );
void PresentStart( void );
void PresentEnd( void );
private:
virtual void UpdateLocatorTarget( CLocatorTarget *pLocatorTarget, C_BaseEntity *pIconTarget );
protected:
CHandle<C_BaseEntity> m_hIconTarget;
CGameInstructorSymbol m_szVguiTargetName;
CGameInstructorSymbol m_szVguiTargetLookup;
int m_nVguiTargetEdge;
float m_flUpOffset;
float m_flRelativeUpOffset;
float m_fFixedPositionX;
float m_fFixedPositionY;
int m_hLocatorTarget;
int m_iFlags;
float m_fRange;
float m_fCurrentDistance;
float m_fOnScreenStartTime;
float m_fUpdateDistanceTime;
CGameInstructorSymbol m_szOnscreenIcon;
CGameInstructorSymbol m_szOffscreenIcon;
CGameInstructorSymbol m_szCaptionColor;
bool m_bFixedPosition;
bool m_bNoIconTarget;
bool m_bAllowNodrawTarget;
bool m_bVisible;
bool m_bShowWhenOccluded;
bool m_bNoOffscreen;
bool m_bForceCaption;
};
enum LessonAction
{
LESSON_ACTION_NONE,
LESSON_ACTION_SCOPE_IN,
LESSON_ACTION_SCOPE_OUT,
LESSON_ACTION_CLOSE,
LESSON_ACTION_SUCCESS,
LESSON_ACTION_LOCK,
LESSON_ACTION_PRESENT_COMPLETE,
LESSON_ACTION_PRESENT_START,
LESSON_ACTION_PRESENT_END,
LESSON_ACTION_REFERENCE_OPEN,
LESSON_ACTION_SET,
LESSON_ACTION_ADD,
LESSON_ACTION_SUBTRACT,
LESSON_ACTION_MULTIPLY,
LESSON_ACTION_IS,
LESSON_ACTION_LESS_THAN,
LESSON_ACTION_HAS_PREFIX,
LESSON_ACTION_HAS_BIT,
LESSON_ACTION_BIT_COUNT_IS,
LESSON_ACTION_BIT_COUNT_LESS_THAN,
LESSON_ACTION_GET_DISTANCE,
LESSON_ACTION_GET_ANGULAR_DISTANCE,
LESSON_ACTION_GET_PLAYER_DISPLAY_NAME,
LESSON_ACTION_CLASSNAME_IS,
LESSON_ACTION_MODELNAME_IS,
LESSON_ACTION_TEAM_IS,
LESSON_ACTION_HEALTH_LESS_THAN,
LESSON_ACTION_HEALTH_PERCENTAGE_LESS_THAN,
LESSON_ACTION_GET_ACTIVE_WEAPON,
LESSON_ACTION_WEAPON_IS,
LESSON_ACTION_WEAPON_HAS,
LESSON_ACTION_GET_ACTIVE_WEAPON_SLOT,
LESSON_ACTION_GET_WEAPON_SLOT,
LESSON_ACTION_GET_WEAPON_IN_SLOT,
LESSON_ACTION_CLIP_PERCENTAGE_LESS_THAN,
LESSON_ACTION_WEAPON_AMMO_LOW,
LESSON_ACTION_WEAPON_AMMO_FULL,
LESSON_ACTION_WEAPON_AMMO_EMPTY,
LESSON_ACTION_WEAPON_CAN_USE,
LESSON_ACTION_USE_TARGET_IS,
LESSON_ACTION_GET_USE_TARGET,
LESSON_ACTION_GET_POTENTIAL_USE_TARGET,
// Enum continued in Mod_LessonAction
LESSON_ACTION_MOD_START,
};
struct LessonElement_t
{
int iVariable;
int iParamVarIndex;
int iAction;
_fieldtypes paramType;
CGameInstructorSymbol szParam;
bool bNot : 1;
bool bOptionalParam : 1;
LessonElement_t( int p_iVariable, int p_iAction, bool p_bNot, bool p_bOptionalParam, const char *pchParam, int p_iParamVarIndex, _fieldtypes p_paramType )
{
iVariable = p_iVariable;
iAction = p_iAction;
bNot = p_bNot;
bOptionalParam = p_bOptionalParam;
szParam = pchParam;
iParamVarIndex = p_iParamVarIndex;
paramType = p_paramType;
}
LessonElement_t( const LessonElement_t &p_LessonElement )
{
iVariable = p_LessonElement.iVariable;
iAction = p_LessonElement.iAction;
bNot = p_LessonElement.bNot;
bOptionalParam = p_LessonElement.bOptionalParam;
szParam = p_LessonElement.szParam;
iParamVarIndex = p_LessonElement.iParamVarIndex;
paramType = p_LessonElement.paramType;
}
};
struct LessonEvent_t
{
CUtlVector< LessonElement_t > elements;
CGameInstructorSymbol szEventName;
};
class CScriptedIconLesson : public CIconLesson
{
public:
DECLARE_LESSON( CScriptedIconLesson, CIconLesson )
virtual ~CScriptedIconLesson( void );
static void PreReadLessonsFromFile( void );
static void Mod_PreReadLessonsFromFile( void );
void Init( void ); // NOT virtual, each constructor calls their own
virtual void InitPrerequisites( void );
virtual void OnOpen( void );
virtual void Update( void );
virtual void SwapOutPlayers( int iOldUserID, int iNewUserID );
virtual void FireGameEvent( IGameEvent *event );
virtual void ProcessOpenGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
virtual void ProcessCloseGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
virtual void ProcessSuccessGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event );
CUtlVector< LessonEvent_t >& GetOpenEvents( void ) { return m_OpenEvents; }
CUtlVector< LessonEvent_t >& GetCloseEvents( void ) { return m_CloseEvents; }
CUtlVector< LessonEvent_t >& GetSuccessEvents( void ) { return m_SuccessEvents; }
CUtlVector< LessonEvent_t >& GetOnOpenEvents( void ) { return m_OnOpenEvents; }
CUtlVector< LessonEvent_t >& GetUpdateEvents( void ) { return m_UpdateEvents; }
bool ProcessElements( IGameEvent *event, const CUtlVector< LessonElement_t > *pElements );
private:
void InitElementsFromKeys( CUtlVector< LessonElement_t > *pLessonElements, KeyValues *pKey );
void InitElementsFromElements( CUtlVector< LessonElement_t > *pLessonElements, const CUtlVector< LessonElement_t > *pLessonElements2 );
void InitFromKeys( KeyValues *pKey );
bool ProcessElement( IGameEvent *event, const LessonElement_t *pLessonElement, bool bInFailedScope );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, float &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, int &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, bool &bVar, const CGameInstructorSymbol *pchParamName, float fParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam );
bool ProcessElementAction( int iAction, bool bNot, const char *pchVarName, CGameInstructorSymbol *pchVar, const CGameInstructorSymbol *pchParamName, const char *pchParam );
// Implemented per mod so they can have custom actions
bool Mod_ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam, bool &bModHandled );
LessonEvent_t * AddOpenEvent( void );
LessonEvent_t * AddCloseEvent( void );
LessonEvent_t * AddSuccessEvent( void );
LessonEvent_t * AddOnOpenEvent( void );
LessonEvent_t * AddUpdateEvent( void );
private:
static CUtlDict< int, int > CScriptedIconLesson::LessonActionMap;
EHANDLE m_hLocalPlayer;
float m_fOutput;
CHandle<C_BaseEntity> m_hEntity1;
CHandle<C_BaseEntity> m_hEntity2;
CGameInstructorSymbol m_szString1;
CGameInstructorSymbol m_szString2;
int m_iInteger1;
int m_iInteger2;
float m_fFloat1;
float m_fFloat2;
CUtlVector< CGameInstructorSymbol > m_PrerequisiteNames;
CUtlVector< LessonEvent_t > m_OpenEvents;
CUtlVector< LessonEvent_t > m_CloseEvents;
CUtlVector< LessonEvent_t > m_SuccessEvents;
CUtlVector< LessonEvent_t > m_OnOpenEvents;
CUtlVector< LessonEvent_t > m_UpdateEvents;
float m_fUpdateEventTime;
CScriptedIconLesson *m_pDefaultHolder;
int m_iScopeDepth;
// Need this to get offsets to scripted variables
friend class LessonVariableInfo;
friend int LessonActionFromString( const char *pchName );
};
#endif // _C_BASELESSON_H_

2899
game/client/c_baseplayer.cpp Normal file

File diff suppressed because it is too large Load Diff

793
game/client/c_baseplayer.h Normal file
View File

@ -0,0 +1,793 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Client-side CBasePlayer.
//
// - Manages the player's flashlight effect.
//
//===========================================================================//
#ifndef C_BASEPLAYER_H
#define C_BASEPLAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "c_playerlocaldata.h"
#include "c_basecombatcharacter.h"
#include "playerstate.h"
#include "usercmd.h"
#include "shareddefs.h"
#include "timedevent.h"
#include "smartptr.h"
#include "fx_water.h"
#include "hintsystem.h"
#include "soundemittersystem/isoundemittersystembase.h"
#include "c_env_fog_controller.h"
#include "C_PostProcessController.h"
#include "C_ColorCorrection.h"
class C_BaseCombatWeapon;
class C_BaseViewModel;
class C_FuncLadder;
extern int g_nKillCamMode;
extern int g_nKillCamTarget1;
extern int g_nKillCamTarget2;
class C_CommandContext
{
public:
bool needsprocessing;
CUserCmd cmd;
int command_number;
};
class C_PredictionError
{
public:
float time;
Vector error;
};
#define CHASE_CAM_DISTANCE 96.0f
#define WALL_OFFSET 6.0f
enum PlayerRenderMode_t
{
PLAYER_RENDER_NONE = 0,
PLAYER_RENDER_FIRSTPERSON,
PLAYER_RENDER_THIRDPERSON,
};
bool IsInFreezeCam( void );
//-----------------------------------------------------------------------------
// Purpose: Base Player class
//-----------------------------------------------------------------------------
class C_BasePlayer : public C_BaseCombatCharacter
{
public:
DECLARE_CLASS( C_BasePlayer, C_BaseCombatCharacter );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
DECLARE_INTERPOLATION();
C_BasePlayer();
virtual ~C_BasePlayer();
virtual void Spawn( void );
virtual void SharedSpawn(); // Shared between client and server.
Class_T Classify( void ) { return CLASS_PLAYER; }
// IClientEntity overrides.
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void OnRestore();
virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
virtual void GetToolRecordingState( KeyValues *msg );
void SetAnimationExtension( const char *pExtension );
C_BaseViewModel *GetViewModel( int viewmodelindex = 0 );
C_BaseCombatWeapon *GetActiveWeapon( void ) const;
const char *GetTracerType( void );
// View model prediction setup
virtual void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
virtual void CalcViewModelView( const Vector& eyeOrigin, const QAngle& eyeAngles);
// Handle view smoothing when going up stairs
void SmoothViewOnStairs( Vector& eyeOrigin );
virtual float CalcRoll (const QAngle& angles, const Vector& velocity, float rollangle, float rollspeed);
void CalcViewRoll( QAngle& eyeAngles );
virtual void CalcViewBob( Vector& eyeOrigin );
void CreateWaterEffects( void );
virtual void SetPlayerUnderwater( bool state );
void UpdateUnderwaterState( void );
bool IsPlayerUnderwater( void ) { return m_bPlayerUnderwater; }
virtual C_BaseCombatCharacter *ActivePlayerCombatCharacter( void ) { return this; }
virtual Vector Weapon_ShootPosition();
virtual bool Weapon_CanUse( C_BaseCombatWeapon *pWeapon );
virtual void Weapon_DropPrimary( void ) {}
virtual Vector GetAutoaimVector( float flScale );
void SetSuitUpdate(char *name, int fgroup, int iNoRepeat);
// Input handling
virtual bool CreateMove( float flInputSampleTime, CUserCmd *pCmd );
virtual void AvoidPhysicsProps( CUserCmd *pCmd );
virtual void PlayerUse( void );
CBaseEntity *FindUseEntity( void );
virtual bool IsUseableEntity( CBaseEntity *pEntity, unsigned int requiredCaps );
// Data handlers
virtual bool IsPlayer( void ) const { return true; }
virtual int GetHealth() const { return m_iHealth; }
int GetBonusProgress() const { return m_iBonusProgress; }
int GetBonusChallenge() const { return m_iBonusChallenge; }
// observer mode
virtual int GetObserverMode() const;
virtual CBaseEntity *GetObserverTarget() const;
void SetObserverTarget( EHANDLE hObserverTarget );
bool AudioStateIsUnderwater( Vector vecMainViewOrigin );
bool IsObserver() const;
bool IsHLTV() const;
bool IsReplay() const;
void ResetObserverMode();
bool IsBot( void ) const { return false; }
// Eye position..
virtual Vector EyePosition();
virtual const QAngle &EyeAngles(); // Direction of eyes
void EyePositionAndVectors( Vector *pPosition, Vector *pForward, Vector *pRight, Vector *pUp );
virtual const QAngle &LocalEyeAngles(); // Direction of eyes
// This can be overridden to return something other than m_pRagdoll if the mod uses separate
// entities for ragdolls.
virtual IRagdoll* GetRepresentativeRagdoll() const;
// override the initial bone position for ragdolls
virtual void GetRagdollInitBoneArrays( matrix3x4a_t *pDeltaBones0, matrix3x4a_t *pDeltaBones1, matrix3x4a_t *pCurrentBones, float boneDt );
// Returns eye vectors
void EyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL );
void CacheVehicleView( void ); // Calculate and cache the position of the player in the vehicle
bool IsSuitEquipped( void ) { return m_Local.m_bWearingSuit; };
// Team handlers
virtual void TeamChange( int iNewTeam );
// Flashlight
void Flashlight( void );
void UpdateFlashlight( void );
void TurnOffFlashlight( void ); // TERROR
virtual const char *GetFlashlightTextureName( void ) const { return NULL; } // TERROR
virtual float GetFlashlightFOV( void ) const { return 0.0f; } // TERROR
virtual float GetFlashlightFarZ( void ) const { return 0.0f; } // TERROR
virtual float GetFlashlightLinearAtten( void ) const { return 0.0f; } // TERROR
virtual bool CastsFlashlightShadows( void ) const { return true; } // TERROR
virtual void GetFlashlightOffset( const Vector &vecForward, const Vector &vecRight, const Vector &vecUp, Vector *pVecOffset ) const;
Vector m_vecFlashlightOrigin;
Vector m_vecFlashlightForward;
Vector m_vecFlashlightUp;
Vector m_vecFlashlightRight;
// Weapon selection code
virtual bool IsAllowedToSwitchWeapons( void ) { return !IsObserver(); }
virtual C_BaseCombatWeapon *GetActiveWeaponForSelection( void );
// Returns the view model if this is the local player. If you're in third person or
// this is a remote player, it returns the active weapon
// (and its appropriate left/right weapon if this is TF2).
virtual C_BaseAnimating* GetRenderedWeaponModel();
virtual bool IsOverridingViewmodel( void ) { return false; };
virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags, const RenderableInstance_t &instance ) { return 0; };
virtual float GetDefaultAnimSpeed( void ) { return 1.0; }
void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; }
float MaxSpeed() const { return m_flMaxspeed; }
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }
virtual bool ShouldReceiveProjectedTextures( int flags )
{
return false;
}
// Makes sure s_pLocalPlayer is properly initialized
void CheckForLocalPlayer( int nSplitScreenSlot );
/// Is the passed in player one of the split screen users
static bool IsLocalPlayer( const C_BaseEntity *pl );
/// is this player a local player ( call when you have already verified that your pointer really is a C_BasePlayer )
inline bool IsLocalPlayer( void ) const;
// Global/static methods
virtual void ThirdPersonSwitch( bool bThirdperson );
bool ShouldDrawLocalPlayer();
static C_BasePlayer *GetLocalPlayer( int nSlot = -1 );
static void SetRemoteSplitScreenPlayerViewsAreLocalPlayer( bool bSet ); //if true, calls to GetLocalPlayer() will return a remote splitscreen player when applicable.
static bool HasAnyLocalPlayer();
static int GetSplitScreenSlotForPlayer( C_BaseEntity *pl );
void AddSplitScreenPlayer( C_BasePlayer *pOther );
void RemoveSplitScreenPlayer( C_BasePlayer *pOther );
CUtlVector< CHandle< C_BasePlayer > > &GetSplitScreenPlayers();
bool IsSplitScreenPartner( C_BasePlayer *pPlayer );
bool IsSplitScreenPlayer() const;
int GetSplitScreenPlayerSlot();
virtual IClientModelRenderable* GetClientModelRenderable();
virtual bool PreRender( int nSplitScreenPlayerSlot );
int GetUserID( void ) const;
virtual bool CanSetSoundMixer( void );
// return the entity used for soundscape radius checks
virtual C_BaseEntity *GetSoundscapeListener();
#if !defined( NO_ENTITY_PREDICTION )
void AddToPlayerSimulationList( C_BaseEntity *other );
void SimulatePlayerSimulatedEntities( void );
void RemoveFromPlayerSimulationList( C_BaseEntity *ent );
void ClearPlayerSimulationList( void );
#endif
virtual void PhysicsSimulate( void );
virtual unsigned int PhysicsSolidMaskForEntity( void ) const { return MASK_PLAYERSOLID; }
// Prediction stuff
virtual bool ShouldPredict( void );
virtual C_BasePlayer *GetPredictionOwner( void );
virtual void PreThink( void );
virtual void PostThink( void );
virtual void ItemPreFrame( void );
virtual void ItemPostFrame( void );
virtual void AbortReload( void );
virtual void SelectLastItem(void);
virtual void Weapon_SetLast( C_BaseCombatWeapon *pWeapon );
virtual bool Weapon_ShouldSetLast( C_BaseCombatWeapon *pOldWeapon, C_BaseCombatWeapon *pNewWeapon ) { return true; }
virtual bool Weapon_ShouldSelectItem( C_BaseCombatWeapon *pWeapon );
virtual bool Weapon_Switch( C_BaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed)
virtual C_BaseCombatWeapon *GetLastWeapon( void ) { return m_hLastWeapon.Get(); }
void ResetAutoaim( void );
virtual void SelectItem( const char *pstr, int iSubType = 0 );
virtual void UpdateClientData( void );
virtual float GetFOV( void ) const;
virtual int GetDefaultFOV( void ) const;
virtual bool IsZoomed( void ) { return false; }
bool SetFOV( CBaseEntity *pRequester, int FOV, float zoomRate, int iZoomStart = 0 );
void ClearZoomOwner( void );
float GetFOVDistanceAdjustFactor();
virtual void ViewPunch( const QAngle &angleOffset );
void ViewPunchReset( float tolerance = 0 );
void UpdateButtonState( int nUserCmdButtonMask );
int GetImpulse( void ) const;
virtual bool Simulate();
virtual bool ShouldInterpolate();
virtual bool ShouldDraw();
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
// Called when not in tactical mode. Allows view to be overriden for things like driving a tank.
virtual void OverrideView( CViewSetup *pSetup );
C_BaseEntity *GetViewEntity( void ) const { return m_hViewEntity; }
// returns the player name
const char * GetPlayerName();
virtual const Vector GetPlayerMins( void ) const; // uses local player
virtual const Vector GetPlayerMaxs( void ) const; // uses local player
virtual void UpdateCollisionBounds( void );
// Is the player dead?
bool IsPlayerDead();
bool IsPoisoned( void ) { return m_Local.m_bPoisoned; }
virtual C_BaseEntity* GetUseEntity( void ) const;
virtual C_BaseEntity* GetPotentialUseEntity( void ) const;
// Vehicles...
IClientVehicle *GetVehicle();
const IClientVehicle *GetVehicle() const;
bool IsInAVehicle() const { return ( NULL != m_hVehicle.Get() ) ? true : false; }
virtual void SetVehicleRole( int nRole );
void LeaveVehicle( void );
bool UsingStandardWeaponsInVehicle( void );
virtual void SetAnimation( PLAYER_ANIM playerAnim );
float GetTimeBase( void ) const;
float GetFinalPredictedTime() const;
bool IsInVGuiInputMode() const;
bool IsInViewModelVGuiInputMode() const;
C_CommandContext *GetCommandContext();
// Get the command number associated with the current usercmd we're running (if in predicted code).
int CurrentCommandNumber() const;
const CUserCmd *GetCurrentUserCommand() const;
virtual const QAngle& GetPunchAngle();
void SetPunchAngle( const QAngle &angle );
float GetWaterJumpTime() const;
void SetWaterJumpTime( float flWaterJumpTime );
float GetSwimSoundTime( void ) const;
void SetSwimSoundTime( float flSwimSoundTime );
float GetDeathTime( void ) { return m_flDeathTime; }
void SetPreviouslyPredictedOrigin( const Vector &vecAbsOrigin );
const Vector &GetPreviouslyPredictedOrigin() const;
// CS wants to allow small FOVs for zoomed-in AWPs.
virtual float GetMinFOV() const;
virtual void DoMuzzleFlash();
virtual void PlayPlayerJingle();
virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity );
virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force );
virtual surfacedata_t * GetFootstepSurface( const Vector &origin, const char *surfaceName );
virtual void GetStepSoundVelocities( float *velwalk, float *velrun );
virtual void SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking );
// Called by prediction when it detects a prediction correction.
// vDelta is the line from where the client had predicted the player to at the usercmd in question,
// to where the server says the client should be at said usercmd.
void NotePredictionError( const Vector &vDelta );
// Called by the renderer to apply the prediction error smoothing.
void GetPredictionErrorSmoothingVector( Vector &vOffset );
virtual void ExitLadder() {}
surfacedata_t *GetLadderSurface( const Vector &origin );
void ForceButtons( int nButtons );
void UnforceButtons( int nButtons );
void SetLadderNormal( Vector vecLadderNormal ) { m_vecLadderNormal = vecLadderNormal; }
const Vector &GetLadderNormal( void ) const { return m_vecLadderNormal; }
int GetLadderSurfaceProps( void ) const { return m_ladderSurfaceProps; }
// Hints
virtual CHintSystem *Hints( void ) { return NULL; }
bool ShouldShowHints( void ) { return Hints() ? Hints()->ShouldShowHints() : false; }
bool HintMessage( int hint, bool bForce = false, bool bOnlyIfClear = false ) { return Hints() ? Hints()->HintMessage( hint, bForce, bOnlyIfClear ) : false; }
void HintMessage( const char *pMessage ) { if (Hints()) Hints()->HintMessage( pMessage ); }
virtual IMaterial *GetHeadLabelMaterial( void );
// Fog
virtual fogparams_t *GetFogParams( void ) { return &m_CurrentFog; }
void FogControllerChanged( bool bSnap );
void UpdateFogController( void );
void UpdateFogBlend( void );
C_PostProcessController* GetActivePostProcessController() const;
C_ColorCorrection* GetActiveColorCorrection() const;
void IncrementEFNoInterpParity();
int GetEFNoInterpParity() const;
float GetFOVTime( void ){ return m_flFOVTime; }
PlayerRenderMode_t GetPlayerRenderMode( int nSlot );
virtual void OnAchievementAchieved( int iAchievement ) {}
protected:
fogparams_t m_CurrentFog;
EHANDLE m_hOldFogController;
public:
// RecvProxies
static void RecvProxy_LocalVelocityX( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_LocalVelocityY( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_LocalVelocityZ( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_ObserverTarget( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_ObserverMode( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_LocalOriginXY( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_LocalOriginZ( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_NonLocalOriginXY( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_NonLocalOriginZ( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_NonLocalCellOriginXY( const CRecvProxyData *pData, void *pStruct, void *pOut );
static void RecvProxy_NonLocalCellOriginZ( const CRecvProxyData *pData, void *pStruct, void *pOut );
virtual bool ShouldRegenerateOriginFromCellBits() const;
public:
int m_StuckLast;
// Data for only the local player
CNetworkVarEmbedded( CPlayerLocalData, m_Local );
EHANDLE m_hTonemapController;
// Data common to all other players, too
CPlayerState pl;
public:
// BEGIN PREDICTION DATA COMPACTION (these fields are together to allow for faster copying in prediction system)
// FTYPEDESC_INSENDTABLE STUFF
// Player FOV values
int m_iFOV; // field of view
int m_iFOVStart; // starting value of the FOV changing over time (client only)
int m_afButtonLast;
int m_afButtonPressed;
int m_afButtonReleased;
int m_nButtons;
protected:
int m_nImpulse;
CNetworkVar( int, m_ladderSurfaceProps );
int m_flPhysics;
public:
float m_flFOVTime; // starting time of the FOV zoom
private:
float m_flWaterJumpTime; // used to be called teleport_time
float m_flSwimSoundTime;
protected:
float m_flStepSoundTime;
float m_surfaceFriction;
private:
CNetworkVector( m_vecLadderNormal );
// FTYPEDESC_INSENDTABLE STUFF (end)
public:
char m_szAnimExtension[32];
private:
int m_nOldTickBase;
private:
int m_iBonusProgress;
int m_iBonusChallenge;
private:
float m_flMaxspeed;
public:
EHANDLE m_hZoomOwner; // This is a pointer to the entity currently controlling the player's zoom
private:
EHANDLE m_hVehicle;
typedef CHandle<C_BaseCombatWeapon> CBaseCombatWeaponHandle;
CBaseCombatWeaponHandle m_hLastWeapon;
// players own view models, left & right hand
CHandle< C_BaseViewModel > m_hViewModel[ MAX_VIEWMODELS ];
public:
// For weapon prediction
bool m_fOnTarget; //Is the crosshair on a target?
// END PREDICTION DATA COMPACTION
public:
int m_iDefaultFOV; // default FOV if no other zooms are occurring
// Only this entity can change the zoom state once it has ownership
int m_afButtonForced; // These are forced onto the player's inputs
CUserCmd *m_pCurrentCommand;
EHANDLE m_hViewEntity;
// Movement constraints
EHANDLE m_hConstraintEntity;
Vector m_vecConstraintCenter;
float m_flConstraintRadius;
float m_flConstraintWidth;
float m_flConstraintSpeedFactor;
bool m_bConstraintPastRadius;
protected:
virtual void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcVehicleView(IClientVehicle *pVehicle, Vector& eyeOrigin, QAngle& eyeAngles,
float& zNear, float& zFar, float& fov );
virtual void CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual Vector GetChaseCamViewOffset( CBaseEntity *target );
void CalcChaseCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
void CalcInEyeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual void CalcDeathCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
virtual void CalcRoamingView(Vector& eyeOrigin, QAngle& eyeAngles, float& fov);
virtual void CalcFreezeCamView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
// Check to see if we're in vgui input mode...
void DetermineVguiInputMode( CUserCmd *pCmd );
// Used by prediction, sets the view angles for the player
virtual void SetLocalViewAngles( const QAngle &viewAngles );
virtual void SetViewAngles( const QAngle& ang );
// used by client side player footsteps
surfacedata_t* GetGroundSurface();
protected:
// Did we just enter a vehicle this frame?
bool JustEnteredVehicle();
// DATA
int m_iObserverMode; // if in spectator mode != 0
EHANDLE m_hObserverTarget; // current observer target
float m_flObserverChaseDistance; // last distance to observer traget
Vector m_vecFreezeFrameStart;
float m_flFreezeFrameStartTime; // Time at which we entered freeze frame observer mode
float m_flFreezeFrameDistance;
bool m_bWasFreezeFraming;
float m_flDeathTime; // last time player died
private:
// Make sure no one calls this...
C_BasePlayer& operator=( const C_BasePlayer& src );
C_BasePlayer( const C_BasePlayer & ); // not defined, not accessible
// Vehicle stuff.
EHANDLE m_hOldVehicle;
EHANDLE m_hUseEntity;
CInterpolatedVar< Vector > m_iv_vecViewOffset;
// Not replicated
Vector m_vecWaterJumpVel;
protected:
QAngle m_vecOldViewAngles;
private:
bool m_bWasFrozen;
int m_nTickBase;
int m_nFinalPredictedTick;
EHANDLE m_pCurrentVguiScreen;
// Player flashlight dynamic light pointers
bool m_bFlashlightEnabled[ MAX_SPLITSCREEN_PLAYERS ];
#if !defined( NO_ENTITY_PREDICTION )
CUtlVector< CHandle< C_BaseEntity > > m_SimulatedByThisPlayer;
#endif
float m_flOldPlayerZ;
float m_flOldPlayerViewOffsetZ;
Vector m_vecVehicleViewOrigin; // Used to store the calculated view of the player while riding in a vehicle
QAngle m_vecVehicleViewAngles; // Vehicle angles
float m_flVehicleViewFOV;
int m_nVehicleViewSavedFrame; // Used to mark which frame was the last one the view was calculated for
// For UI purposes...
int m_iOldAmmo[ MAX_AMMO_TYPES ];
C_CommandContext m_CommandContext;
// For underwater effects
float m_flWaterSurfaceZ;
bool m_bResampleWaterSurface;
TimedEvent m_tWaterParticleTimer;
CSmartPtr<WaterDebrisEffect> m_pWaterEmitter;
bool m_bPlayerUnderwater;
friend class CPrediction;
friend class CASW_Prediction;
// HACK FOR TF2 Prediction
friend class CTFGameMovementRecon;
friend class CGameMovement;
friend class CTFGameMovement;
friend class CCSGameMovement;
friend class CHL2GameMovement;
friend class CPortalGameMovement;
friend class CASW_MarineGameMovement;
friend class CPaintGameMovement;
// Accessors for gamemovement
float GetStepSize( void ) const { return m_Local.m_flStepSize; }
float m_flNextAvoidanceTime;
float m_flAvoidanceRight;
float m_flAvoidanceForward;
float m_flAvoidanceDotForward;
float m_flAvoidanceDotRight;
protected:
virtual bool IsDucked( void ) const { return m_Local.m_bDucked; }
virtual bool IsDucking( void ) const { return m_Local.m_bDucking; }
virtual float GetFallVelocity( void ) { return m_Local.m_flFallVelocity; }
void ForceSetupBonesAtTimeFakeInterpolation( matrix3x4a_t *pBonesOut, float curtimeOffset );
float m_flLaggedMovementValue;
// These are used to smooth out prediction corrections. They're most useful when colliding with
// vphysics objects. The server will be sending constant prediction corrections, and these can help
// the errors not be so jerky.
Vector m_vecPredictionError;
float m_flPredictionErrorTime;
Vector m_vecPreviouslyPredictedOrigin; // Used to determine if non-gamemovement game code has teleported, or tweaked the player's origin
char m_szLastPlaceName[MAX_PLACE_NAME_LENGTH]; // received from the server
// Texture names and surface data, used by CGameMovement
int m_surfaceProps;
surfacedata_t* m_pSurfaceData;
char m_chTextureType;
bool m_bSentFreezeFrame;
float m_flFreezeZOffset;
byte m_ubEFNoInterpParity;
byte m_ubOldEFNoInterpParity;
// If we have any attached split users, this is the list of them
CUtlVector< CHandle< CBasePlayer > > m_hSplitScreenPlayers;
int m_nSplitScreenSlot; //-1 == not a split player
CHandle< CBasePlayer > m_hSplitOwner;
bool m_bIsLocalPlayer;
private:
struct StepSoundCache_t
{
StepSoundCache_t() : m_usSoundNameIndex( 0 ) {}
CSoundParameters m_SoundParameters;
unsigned short m_usSoundNameIndex;
};
// One for left and one for right side of step
StepSoundCache_t m_StepSoundCache[ 2 ];
public:
const char *GetLastKnownPlaceName( void ) const { return m_szLastPlaceName; } // return the last nav place name the player occupied
float GetLaggedMovementValue( void ){ return m_flLaggedMovementValue; }
bool ShouldGoSouth( Vector vNPCForward, Vector vNPCRight ); //Such a bad name.
void SetOldPlayerZ( float flOld ) { m_flOldPlayerZ = flOld; }
const fogplayerparams_t& GetPlayerFog() const { return m_PlayerFog; }
private:
friend class CMoveHelperClient;
CNetworkHandle( CPostProcessController, m_hPostProcessCtrl ); // active postprocessing controller
CNetworkHandle( CColorCorrection, m_hColorCorrectionCtrl ); // active FXVolume color correction
// fog params
fogplayerparams_t m_PlayerFog;
};
EXTERN_RECV_TABLE(DT_BasePlayer);
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline C_BasePlayer *ToBasePlayer( C_BaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsPlayer() )
return NULL;
#if _DEBUG
Assert( dynamic_cast<C_BasePlayer *>( pEntity ) != NULL );
#endif
return static_cast<C_BasePlayer *>( pEntity );
}
inline const C_BasePlayer *ToBasePlayer( const C_BaseEntity *pEntity )
{
if ( !pEntity || !pEntity->IsPlayer() )
return NULL;
#if _DEBUG
Assert( dynamic_cast<const C_BasePlayer *>( pEntity ) != NULL );
#endif
return static_cast<const C_BasePlayer *>( pEntity );
}
inline IClientVehicle *C_BasePlayer::GetVehicle()
{
C_BaseEntity *pVehicleEnt = m_hVehicle.Get();
return pVehicleEnt ? pVehicleEnt->GetClientVehicle() : NULL;
}
inline bool C_BasePlayer::IsObserver() const
{
return (GetObserverMode() != OBS_MODE_NONE);
}
inline int C_BasePlayer::GetImpulse( void ) const
{
return m_nImpulse;
}
inline C_CommandContext* C_BasePlayer::GetCommandContext()
{
return &m_CommandContext;
}
inline int CBasePlayer::CurrentCommandNumber() const
{
Assert( m_pCurrentCommand );
if ( !m_pCurrentCommand )
return 0;
return m_pCurrentCommand->command_number;
}
inline const CUserCmd *CBasePlayer::GetCurrentUserCommand() const
{
Assert( m_pCurrentCommand );
return m_pCurrentCommand;
}
extern bool g_bEngineIsHLTV;
inline bool C_BasePlayer::IsHLTV() const
{
return m_bIsLocalPlayer && g_bEngineIsHLTV;
}
inline bool C_BasePlayer::IsLocalPlayer( void ) const
{
return m_bIsLocalPlayer;
}
#endif // C_BASEPLAYER_H

View File

@ -0,0 +1,201 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Core Temp Entity client implementation.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "c_basetempentity.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS(C_BaseTempEntity, DT_BaseTempEntity, CBaseTempEntity);
BEGIN_RECV_TABLE_NOBASE(C_BaseTempEntity, DT_BaseTempEntity)
END_RECV_TABLE()
// Global list of temp entity classes
C_BaseTempEntity *C_BaseTempEntity::s_pTempEntities = NULL;
// Global list of dynamic temp entities
C_BaseTempEntity *C_BaseTempEntity::s_pDynamicEntities = NULL;
//-----------------------------------------------------------------------------
// Purpose: Returns head of list
// Output : CBaseTempEntity * -- head of list
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetDynamicList( void )
{
return s_pDynamicEntities;
}
//-----------------------------------------------------------------------------
// Purpose: Returns head of list
// Output : CBaseTempEntity * -- head of list
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetList( void )
{
return s_pTempEntities;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
C_BaseTempEntity::C_BaseTempEntity( void )
{
// Add to list
m_pNext = s_pTempEntities;
s_pTempEntities = this;
m_pNextDynamic = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output :
//-----------------------------------------------------------------------------
C_BaseTempEntity::~C_BaseTempEntity( void )
{
}
//-----------------------------------------------------------------------------
// Purpose: Get next temp ent in chain
// Output : CBaseTempEntity *
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetNext( void )
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Purpose: Get next temp ent in chain
// Output : CBaseTempEntity *
//-----------------------------------------------------------------------------
C_BaseTempEntity *C_BaseTempEntity::GetNextDynamic( void )
{
return m_pNextDynamic;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseTempEntity::Precache( void )
{
// Nothing...
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup to allow temp entities to precache any models/sounds that they need
//-----------------------------------------------------------------------------
void C_BaseTempEntity::PrecacheTempEnts( void )
{
C_BaseTempEntity *te = GetList();
while ( te )
{
te->Precache();
te = te->GetNext();
}
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup and level load to clear out leftover temp entities
//-----------------------------------------------------------------------------
void C_BaseTempEntity::ClearDynamicTempEnts( void )
{
C_BaseTempEntity *next;
C_BaseTempEntity *te = s_pDynamicEntities;
while ( te )
{
next = te->GetNextDynamic();
delete te;
te = next;
}
s_pDynamicEntities = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Called at startup and level load to clear out leftover temp entities
//-----------------------------------------------------------------------------
void C_BaseTempEntity::CheckDynamicTempEnts( void )
{
C_BaseTempEntity *next, *newlist = NULL;
C_BaseTempEntity *te = s_pDynamicEntities;
while ( te )
{
next = te->GetNextDynamic();
if ( te->ShouldDestroy() )
{
delete te;
}
else
{
te->m_pNextDynamic = newlist;
newlist = te;
}
te = next;
}
s_pDynamicEntities = newlist;
}
//-----------------------------------------------------------------------------
// Purpose: Dynamic/non-singleton temp entities are initialized by
// calling into here. They should be added to a list of C_BaseTempEntities so
// that their memory can be deallocated appropriately.
// Input : *pEnt -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_BaseTempEntity::Init( int entnum, int iSerialNum )
{
if ( entnum != -1 )
{
Assert( 0 );
}
// Link into dynamic entity list
m_pNextDynamic = s_pDynamicEntities;
s_pDynamicEntities = this;
return true;
}
void C_BaseTempEntity::Release()
{
Assert( !"C_BaseTempEntity::Release should never be called" );
}
void C_BaseTempEntity::NotifyShouldTransmit( ShouldTransmitState_t state )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bool -
//-----------------------------------------------------------------------------
void C_BaseTempEntity::PreDataUpdate( DataUpdateType_t updateType )
{
// TE's may or may not implement this
}
int C_BaseTempEntity::entindex( void ) const { Assert( 0 ); return 0; }
void C_BaseTempEntity::PostDataUpdate( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::OnPreDataChanged( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::OnDataChanged( DataUpdateType_t updateType ) { Assert( 0 ); }
void C_BaseTempEntity::SetDormant( bool bDormant ) { Assert( 0 ); }
bool C_BaseTempEntity::IsDormant( void ) { Assert( 0 ); return false; };
void C_BaseTempEntity::ReceiveMessage( int classID, bf_read &msg ) { Assert( 0 ); }
void C_BaseTempEntity::SetDestroyedOnRecreateEntities( void ) { Assert(0); }
void* C_BaseTempEntity::GetDataTableBasePtr()
{
return this;
}

View File

@ -0,0 +1,122 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_BASETEMPENTITY_H
#define C_BASETEMPENTITY_H
#ifdef _WIN32
#pragma once
#endif
#include "client_class.h"
#include "iclientnetworkable.h"
#include "c_recipientfilter.h"
//-----------------------------------------------------------------------------
// Purpose: Base class for TEs. All TEs should derive from this and at
// least implement OnDataChanged to be notified when the TE has been received
// from the server
//-----------------------------------------------------------------------------
class C_BaseTempEntity : public IClientUnknown, public IClientNetworkable
{
public:
DECLARE_CLASS_NOBASE( C_BaseTempEntity );
DECLARE_CLIENTCLASS();
C_BaseTempEntity( void );
virtual ~C_BaseTempEntity( void );
// IClientUnknown implementation.
public:
virtual void SetRefEHandle( const CBaseHandle &handle ) { Assert( false ); }
virtual const CBaseHandle& GetRefEHandle() const { return *((CBaseHandle*)0); }
virtual IClientUnknown* GetIClientUnknown() { return this; }
virtual ICollideable* GetCollideable() { return 0; }
virtual IClientNetworkable* GetClientNetworkable() { return this; }
virtual IClientRenderable* GetClientRenderable() { return 0; }
virtual IClientEntity* GetIClientEntity() { return 0; }
virtual C_BaseEntity* GetBaseEntity() { return 0; }
virtual IClientThinkable* GetClientThinkable() { return 0; }
virtual IClientModelRenderable* GetClientModelRenderable() { return 0; }
virtual IClientAlphaProperty* GetClientAlphaProperty() { return 0; }
// IClientNetworkable overrides.
public:
virtual void Release();
virtual void NotifyShouldTransmit( ShouldTransmitState_t state );
virtual void PreDataUpdate( DataUpdateType_t updateType );
virtual void PostDataUpdate( DataUpdateType_t updateType );
virtual void OnPreDataChanged( DataUpdateType_t updateType );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void SetDormant( bool bDormant );
virtual bool IsDormant( void );
virtual int entindex( void ) const;
virtual void ReceiveMessage( int classID, bf_read &msg );
virtual void* GetDataTableBasePtr();
virtual void SetDestroyedOnRecreateEntities( void );
public:
// Dummy for CNetworkVars.
void NetworkStateChanged() {}
void NetworkStateChanged( void *pVar ) {}
virtual bool Init(int entnum, int iSerialNum);
virtual void Precache( void );
// For dynamic entities, return true to allow destruction
virtual bool ShouldDestroy( void ) { return false; };
C_BaseTempEntity *GetNext( void );
// Get list of tempentities
static C_BaseTempEntity *GetList( void );
C_BaseTempEntity *GetNextDynamic( void );
// Determine the color modulation amount
void GetColorModulation( float* color )
{
assert(color);
color[0] = color[1] = color[2] = 1.0f;
}
// Should this object be able to have shadows cast onto it?
virtual bool ShouldReceiveProjectedTextures( int flags ) { return false; }
// Static members
public:
// List of dynamically allocated temp entis
static C_BaseTempEntity *GetDynamicList();
// Called at startup to allow temp entities to precache any models/sounds that they need
static void PrecacheTempEnts( void );
static void ClearDynamicTempEnts( void );
static void CheckDynamicTempEnts( void );
private:
// Next in chain
C_BaseTempEntity *m_pNext;
C_BaseTempEntity *m_pNextDynamic;
// TEs add themselves to this list for the executable.
static C_BaseTempEntity *s_pTempEntities;
static C_BaseTempEntity *s_pDynamicEntities;
};
#endif // C_BASETEMPENTITY_H

View File

@ -0,0 +1,33 @@
//--------------------------------------------------------------------------------------------------------
// Copyright (c) 2007 Turtle Rock Studios, Inc.
#include "cbase.h"
#include "c_basetoggle.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_BaseToggle, DT_BaseToggle, CBaseToggle )
END_RECV_TABLE()
//--------------------------------------------------------------------------------------------------------
// Returns the velocity imparted to players standing on us.
void C_BaseToggle::GetGroundVelocityToApply( Vector &vecGroundVel )
{
vecGroundVel = GetLocalVelocity();
vecGroundVel.z = 0.0f; // don't give upward velocity, or it could predict players into the air.
}
//--------------------------------------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_BaseButton, DT_BaseButton, CBaseButton )
RecvPropBool( RECVINFO( m_usable ) ),
END_RECV_TABLE()
//--------------------------------------------------------------------------------------------------------
bool C_BaseButton::IsPotentiallyUsable( void )
{
return true;
}

View File

@ -0,0 +1,42 @@
//--------------------------------------------------------------------------------------------------------
// Copyright (c) 2007 Turtle Rock Studios, Inc.
#if !defined( C_BASETOGGLE_H )
#define C_BASETOGGLE_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseentity.h"
//--------------------------------------------------------------------------------------------------------
class C_BaseToggle: public C_BaseEntity
{
public:
DECLARE_CLASS( C_BaseToggle, C_BaseEntity );
DECLARE_CLIENTCLASS();
virtual void GetGroundVelocityToApply( Vector &vecGroundVel );
};
//--------------------------------------------------------------------------------------------------------
class C_BaseButton: public C_BaseToggle
{
public:
DECLARE_CLASS( C_BaseButton, C_BaseToggle );
DECLARE_CLIENTCLASS();
C_BaseButton()
{
}
virtual bool IsPotentiallyUsable( void );
private:
bool m_usable;
};
#endif // C_BASETOGGLE_H

View File

@ -0,0 +1,509 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side view model implementation. Responsible for drawing
// the view model.
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_baseviewmodel.h"
#include "model_types.h"
#include "hud.h"
#include "view_shared.h"
#include "iviewrender.h"
#include "view.h"
#include "mathlib/vmatrix.h"
#include "cl_animevent.h"
#include "eventlist.h"
#include "tools/bonelist.h"
#include <KeyValues.h>
#include "hltvcamera.h"
#include "r_efx.h"
#include "dlight.h"
#include "clientalphaproperty.h"
#include "iinput.h"
#if defined( REPLAY_ENABLED )
#include "replaycamera.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar vm_debug( "vm_debug", "0", FCVAR_CHEAT );
ConVar vm_draw_always( "vm_draw_always", "0" );
void PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg );
extern float g_flMuzzleFlashScale;
void FormatViewModelAttachment( C_BasePlayer *pPlayer, Vector &vOrigin, bool bInverse )
{
int nSlot = 0;
if ( pPlayer )
{
int nPlayerSlot = C_BasePlayer::GetSplitScreenSlotForPlayer( pPlayer );
if ( nPlayerSlot == -1 )
{
nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
}
else
{
nSlot = nPlayerSlot;
}
}
Assert( nSlot != -1 );
// Presumably, SetUpView has been called so we know our FOV and render origin.
const CViewSetup *pViewSetup = view->GetPlayerViewSetup( nSlot );
float worldx = tan( pViewSetup->fov * M_PI/360.0 );
float viewx = tan( pViewSetup->fovViewmodel * M_PI/360.0 );
// aspect ratio cancels out, so only need one factor
// the difference between the screen coordinates of the 2 systems is the ratio
// of the coefficients of the projection matrices (tan (fov/2) is that coefficient)
float factorX = worldx / viewx;
float factorY = factorX;
// Get the coordinates in the viewer's space.
Vector tmp = vOrigin - pViewSetup->origin;
Vector vTransformed( MainViewRight(nSlot).Dot( tmp ), MainViewUp(nSlot).Dot( tmp ), MainViewForward(nSlot).Dot( tmp ) );
// Now squash X and Y.
if ( bInverse )
{
if ( factorX != 0 && factorY != 0 )
{
vTransformed.x /= factorX;
vTransformed.y /= factorY;
}
else
{
vTransformed.x = 0.0f;
vTransformed.y = 0.0f;
}
}
else
{
vTransformed.x *= factorX;
vTransformed.y *= factorY;
}
// Transform back to world space.
Vector vOut = (MainViewRight(nSlot) * vTransformed.x) + (MainViewUp(nSlot) * vTransformed.y) + (MainViewForward(nSlot) * vTransformed.z);
vOrigin = pViewSetup->origin + vOut;
}
void C_BaseViewModel::FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld )
{
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
Vector vecOrigin;
MatrixPosition( attachmentToWorld, vecOrigin );
::FormatViewModelAttachment( pPlayer, vecOrigin, false );
PositionMatrix( vecOrigin, attachmentToWorld );
}
void C_BaseViewModel::UncorrectViewModelAttachment( Vector &vOrigin )
{
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
// Unformat the attachment.
::FormatViewModelAttachment( pPlayer, vOrigin, true );
}
//-----------------------------------------------------------------------------
// Purpose
//-----------------------------------------------------------------------------
void C_BaseViewModel::FireEvent( const Vector& origin, const QAngle& angles, int eventNum, const char *options )
{
// We override sound requests so that we can play them locally on the owning player
if ( ( eventNum == AE_CL_PLAYSOUND ) || ( eventNum == CL_EVENT_SOUND ) )
{
// Only do this if we're owned by someone
if ( GetOwner() != NULL )
{
CLocalPlayerFilter filter;
EmitSound( filter, GetOwner()->GetSoundSourceIndex(), options, &GetAbsOrigin() );
return;
}
}
C_BasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( !pOwner )
return;
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( pOwner );
// Otherwise pass the event to our associated weapon
C_BaseCombatWeapon *pWeapon = pOwner->GetActiveWeapon();
if ( pWeapon )
{
bool bResult = pWeapon->OnFireEvent( this, origin, angles, eventNum, options );
if ( !bResult )
{
if ( eventNum == AE_CLIENT_EFFECT_ATTACH && ::input->CAM_IsThirdPerson() )
return;
BaseClass::FireEvent( origin, angles, eventNum, options );
}
}
}
bool C_BaseViewModel::Interpolate( float currentTime )
{
CStudioHdr *pStudioHdr = GetModelPtr();
// Make sure we reset our animation information if we've switch sequences
UpdateAnimationParity();
bool bret = BaseClass::Interpolate( currentTime );
// Hack to extrapolate cycle counter for view model
float elapsed_time = currentTime - m_flAnimTime;
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
// Predicted viewmodels have fixed up interval
if ( GetPredictable() || IsClientCreated() )
{
Assert( pPlayer );
float curtime = pPlayer ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime;
elapsed_time = curtime - m_flAnimTime;
// Adjust for interpolated partial frame
elapsed_time += ( gpGlobals->interpolation_amount * TICK_INTERVAL );
}
// Prediction errors?
if ( elapsed_time < 0 )
{
elapsed_time = 0;
}
float dt = elapsed_time * GetSequenceCycleRate( pStudioHdr, GetSequence() );
if ( dt >= 1.0f )
{
if ( !IsSequenceLooping( GetSequence() ) )
{
dt = 0.999f;
}
else
{
dt = fmod( dt, 1.0f );
}
}
SetCycle( dt );
return bret;
}
inline bool C_BaseViewModel::ShouldFlipViewModel()
{
return false;
}
void C_BaseViewModel::ApplyBoneMatrixTransform( matrix3x4_t& transform )
{
if ( ShouldFlipViewModel() )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( GetOwner() );
matrix3x4_t viewMatrix, viewMatrixInverse;
// We could get MATERIAL_VIEW here, but this is called sometimes before the renderer
// has set that matrix. Luckily, this is called AFTER the CViewSetup has been initialized.
const CViewSetup *pSetup = view->GetPlayerViewSetup();
AngleMatrix( pSetup->angles, pSetup->origin, viewMatrixInverse );
MatrixInvert( viewMatrixInverse, viewMatrix );
// Transform into view space.
matrix3x4_t temp, temp2;
ConcatTransforms( viewMatrix, transform, temp );
// Flip it along X.
// (This is the slower way to do it, and it equates to negating the top row).
//matrix3x4_t mScale;
//SetIdentityMatrix( mScale );
//mScale[0][0] = 1;
//mScale[1][1] = -1;
//mScale[2][2] = 1;
//ConcatTransforms( mScale, temp, temp2 );
temp[1][0] = -temp[1][0];
temp[1][1] = -temp[1][1];
temp[1][2] = -temp[1][2];
temp[1][3] = -temp[1][3];
// Transform back out of view space.
ConcatTransforms( viewMatrixInverse, temp, transform );
}
}
//-----------------------------------------------------------------------------
// Purpose: check if weapon viewmodel should be drawn
//-----------------------------------------------------------------------------
bool C_BaseViewModel::ShouldDraw()
{
if ( g_bEngineIsHLTV )
{
return ( HLTVCamera()->GetMode() == OBS_MODE_IN_EYE &&
HLTVCamera()->GetPrimaryTarget() == GetOwner() );
}
#if defined( REPLAY_ENABLED )
else if ( engine->IsReplay() )
{
return ( ReplayCamera()->GetMode() == OBS_MODE_IN_EYE &&
ReplayCamera()->GetPrimaryTarget() == GetOwner() );
}
#endif
else
{
Assert( !IsEffectActive( EF_NODRAW ) );
Assert( GetRenderMode() != kRenderNone );
if ( vm_draw_always.GetBool() )
return true;
if ( GetOwner() != C_BasePlayer::GetLocalPlayer() )
return false;
return BaseClass::ShouldDraw();
}
}
//-----------------------------------------------------------------------------
// Purpose: Render the weapon. Draw the Viewmodel if the weapon's being carried
// by this player, otherwise draw the worldmodel.
//-----------------------------------------------------------------------------
int C_BaseViewModel::DrawModel( int flags, const RenderableInstance_t &instance )
{
if ( !m_bReadyToDraw )
return 0;
if ( flags & STUDIO_RENDER )
{
// Determine blending amount and tell engine
float blend = (float)( instance.m_nAlpha / 255.0f );
// Totally gone
if ( blend <= 0.0f )
return 0;
// Tell engine
render->SetBlend( blend );
float color[3];
GetColorModulation( color );
render->SetColorModulation( color );
}
CMatRenderContextPtr pRenderContext( materials );
if ( ShouldFlipViewModel() )
pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
int ret = 0;
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
// If the local player's overriding the viewmodel rendering, let him do it
if ( pPlayer && pPlayer->IsOverridingViewmodel() )
{
ret = pPlayer->DrawOverriddenViewmodel( this, flags, instance );
}
else if ( pWeapon && pWeapon->IsOverridingViewmodel() )
{
ret = pWeapon->DrawOverriddenViewmodel( this, flags, instance );
}
else
{
ret = BaseClass::DrawModel( flags, instance );
}
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
// Now that we've rendered, reset the animation restart flag
if ( flags & STUDIO_RENDER )
{
if ( m_nOldAnimationParity != m_nAnimationParity )
{
m_nOldAnimationParity = m_nAnimationParity;
}
// Tell the weapon itself that we've rendered, in case it wants to do something
if ( pWeapon )
{
pWeapon->ViewModelDrawn( this );
}
if ( vm_debug.GetBool() )
{
MDLCACHE_CRITICAL_SECTION();
int line = 16;
CStudioHdr *hdr = GetModelPtr();
engine->Con_NPrintf( line++, "%s: %s(%d), cycle: %.2f cyclerate: %.2f playbackrate: %.2f\n",
(hdr)?hdr->pszName():"(null)",
GetSequenceName( GetSequence() ),
GetSequence(),
GetCycle(),
GetSequenceCycleRate( hdr, GetSequence() ),
GetPlaybackRate()
);
if ( hdr )
{
for( int i=0; i < hdr->GetNumPoseParameters(); ++i )
{
const mstudioposeparamdesc_t &Pose = hdr->pPoseParameter( i );
engine->Con_NPrintf( line++, "pose_param %s: %f",
Pose.pszName(), GetPoseParameter( i ) );
}
}
// Determine blending amount and tell engine
float blend = (float)( instance.m_nAlpha / 255.0f );
float color[3];
GetColorModulation( color );
engine->Con_NPrintf( line++, "blend=%f, color=%f,%f,%f", blend, color[0], color[1], color[2] );
engine->Con_NPrintf( line++, "GetRenderMode()=%d", GetRenderMode() );
engine->Con_NPrintf( line++, "m_nRenderFX=0x%8.8X", GetRenderFX() );
color24 c = GetRenderColor();
unsigned char a = GetRenderAlpha();
engine->Con_NPrintf( line++, "rendercolor=%d,%d,%d,%d", c.r, c.g, c.b, a );
engine->Con_NPrintf( line++, "origin=%f, %f, %f", GetRenderOrigin().x, GetRenderOrigin().y, GetRenderOrigin().z );
engine->Con_NPrintf( line++, "angles=%f, %f, %f", GetRenderAngles()[0], GetRenderAngles()[1], GetRenderAngles()[2] );
if ( IsEffectActive( EF_NODRAW ) )
{
engine->Con_NPrintf( line++, "EF_NODRAW" );
}
}
}
return ret;
}
//-----------------------------------------------------------------------------
// Purpose: Called by the player when the player's overriding the viewmodel drawing. Avoids infinite recursion.
//-----------------------------------------------------------------------------
int C_BaseViewModel::DrawOverriddenViewmodel( int flags, const RenderableInstance_t &instance )
{
return BaseClass::DrawModel( flags, instance );
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
uint8 C_BaseViewModel::OverrideAlphaModulation( uint8 nAlpha )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( GetOwner() );
// See if the local player wants to override the viewmodel's rendering
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer && pPlayer->IsOverridingViewmodel() )
return pPlayer->AlphaProp()->ComputeRenderAlpha();
C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
if ( pWeapon && pWeapon->IsOverridingViewmodel() )
return pWeapon->AlphaProp()->ComputeRenderAlpha();
return nAlpha;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
RenderableTranslucencyType_t C_BaseViewModel::ComputeTranslucencyType( void )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD_ENT( GetOwner() );
// See if the local player wants to override the viewmodel's rendering
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer && pPlayer->IsOverridingViewmodel() )
return pPlayer->ComputeTranslucencyType();
C_BaseCombatWeapon *pWeapon = GetOwningWeapon();
if ( pWeapon && pWeapon->IsOverridingViewmodel() )
return pWeapon->ComputeTranslucencyType();
return BaseClass::ComputeTranslucencyType();
}
//-----------------------------------------------------------------------------
// Purpose: If the animation parity of the weapon has changed, we reset cycle to avoid popping
//-----------------------------------------------------------------------------
void C_BaseViewModel::UpdateAnimationParity( void )
{
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
// If we're predicting, then we don't use animation parity because we change the animations on the clientside
// while predicting. When not predicting, only the server changes the animations, so a parity mismatch
// tells us if we need to reset the animation.
if ( m_nOldAnimationParity != m_nAnimationParity && !GetPredictable() )
{
float curtime = (pPlayer && IsIntermediateDataAllocated()) ? pPlayer->GetFinalPredictedTime() : gpGlobals->curtime;
// FIXME: this is bad
// Simulate a networked m_flAnimTime and m_flCycle
// FIXME: Do we need the magic 0.1?
SetCycle( 0.0f ); // GetSequenceCycleRate( GetSequence() ) * 0.1;
m_flAnimTime = curtime;
}
}
//-----------------------------------------------------------------------------
// Purpose: Update global map state based on data received
// Input : bnewentity -
//-----------------------------------------------------------------------------
void C_BaseViewModel::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
AlphaProp()->EnableAlphaModulationOverride( true );
}
SetPredictionEligible( true );
BaseClass::OnDataChanged(updateType);
}
void C_BaseViewModel::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate(updateType);
OnLatchInterpolatedVariables( LATCH_ANIMATION_VAR );
}
//-----------------------------------------------------------------------------
// Purpose: Return the player who will predict this entity
//-----------------------------------------------------------------------------
CBasePlayer *C_BaseViewModel::GetPredictionOwner()
{
return ToBasePlayer( GetOwner() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_BaseViewModel::GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS])
{
BaseClass::GetBoneControllers( controllers );
// Tell the weapon itself that we've rendered, in case it wants to do something
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
return;
C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
if ( pWeapon )
{
pWeapon->GetViewmodelBoneControllers( this, controllers );
}
}

View File

@ -0,0 +1,20 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Client side view model implementation. Responsible for drawing
// the view model.
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_BASEVIEWMODEL_H
#define C_BASEVIEWMODEL_H
#ifdef _WIN32
#pragma once
#endif
#include "c_baseanimating.h"
#include "UtlVector.h"
#include "baseviewmodel_shared.h"
#endif // C_BASEVIEWMODEL_H

View File

@ -0,0 +1,354 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#include "cbase.h"
#include "dlight.h"
#include "iefx.h"
#include "beam_shared.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CSpotlightTraceCacheEntry
{
public:
CSpotlightTraceCacheEntry()
{
m_origin.Init();
m_radius = -1.0f;
}
bool IsValidFor( const Vector &origin )
{
if ( m_radius > 0 && m_origin.DistToSqr(origin) < 1.0f )
return true;
return false;
}
void Cache( const Vector &origin, const trace_t &tr )
{
m_radius = (tr.endpos - origin).Length();
m_origin = origin;
}
Vector m_origin;
float m_radius;
};
static const int NUM_CACHE_ENTRIES = 64;
class C_BeamSpotLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_BeamSpotLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_BeamSpotLight();
~C_BeamSpotLight();
bool ShouldDraw();
void ClientThink( void );
void OnDataChanged( DataUpdateType_t updateType );
void Release( void );
private:
Vector SpotlightCurrentPos(void);
void SpotlightCreate(void);
void SpotlightDestroy(void);
// Computes render info for a spotlight
void ComputeRenderInfo();
private:
int m_nHaloIndex;
int m_nRotationAxis;
float m_flRotationSpeed;
bool m_bSpotlightOn;
bool m_bHasDynamicLight;
float m_flSpotlightMaxLength;
float m_flSpotlightGoalWidth;
float m_flHDRColorScale;
Vector m_vSpotlightTargetPos;
Vector m_vSpotlightCurrentPos;
Vector m_vSpotlightDir;
CHandle<C_Beam> m_hSpotlight;
float m_flSpotlightCurLength;
float m_flLightScale;
dlight_t* m_pDynamicLight;
float m_lastTime;
CSpotlightTraceCacheEntry *m_pCache;
};
LINK_ENTITY_TO_CLASS( beam_spotlight, C_BeamSpotLight );
IMPLEMENT_CLIENTCLASS_DT( C_BeamSpotLight, DT_BeamSpotlight, CBeamSpotlight )
RecvPropInt( RECVINFO(m_nHaloIndex) ),
RecvPropBool( RECVINFO(m_bSpotlightOn) ),
RecvPropBool( RECVINFO(m_bHasDynamicLight) ),
RecvPropFloat( RECVINFO(m_flSpotlightMaxLength) ),
RecvPropFloat( RECVINFO(m_flSpotlightGoalWidth) ),
RecvPropFloat( RECVINFO(m_flHDRColorScale) ),
RecvPropInt( RECVINFO(m_nRotationAxis) ),
RecvPropFloat( RECVINFO(m_flRotationSpeed) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
C_BeamSpotLight::C_BeamSpotLight()
: m_vSpotlightTargetPos( vec3_origin )
, m_vSpotlightCurrentPos( vec3_origin )
, m_vSpotlightDir( vec3_origin )
, m_flSpotlightCurLength( 0.0f )
, m_flLightScale( 100.0f )
, m_pDynamicLight( NULL )
, m_lastTime( 0.0f )
, m_pCache(NULL)
{
}
C_BeamSpotLight::~C_BeamSpotLight()
{
delete[] m_pCache;
}
//-----------------------------------------------------------------------------
bool C_BeamSpotLight::ShouldDraw()
{
return false;
}
//-----------------------------------------------------------------------------
void C_BeamSpotLight::ClientThink( void )
{
float dt = gpGlobals->curtime - m_lastTime;
if ( !m_lastTime )
{
dt = 0.0f;
}
m_lastTime = gpGlobals->curtime;
// ---------------------------------------------------
// If I don't have a spotlight attempt to create one
// ---------------------------------------------------
if ( !m_hSpotlight )
{
if ( m_bSpotlightOn )
{
// Make the spotlight
SpotlightCreate();
}
else
{
SetNextClientThink( CLIENT_THINK_NEVER );
return;
}
}
else if ( !m_bSpotlightOn )
{
SpotlightDestroy();
SetNextClientThink( CLIENT_THINK_NEVER );
return;
}
// update rotation
if ( m_flRotationSpeed != 0.0f )
{
QAngle angles = GetAbsAngles();
angles[m_nRotationAxis] += m_flRotationSpeed * dt;
angles[m_nRotationAxis] = anglemod(angles[m_nRotationAxis]);
if ( !m_pCache )
{
m_pCache = new CSpotlightTraceCacheEntry[NUM_CACHE_ENTRIES];
}
SetAbsAngles( angles );
}
m_vSpotlightCurrentPos = SpotlightCurrentPos();
Assert( m_hSpotlight );
m_hSpotlight->SetStartPos( GetAbsOrigin() );
m_hSpotlight->SetEndPos( m_vSpotlightCurrentPos );
// Avoid sudden change in where beam fades out when cross disconinuities
Vector dir = m_vSpotlightCurrentPos - GetAbsOrigin();
float flBeamLength = VectorNormalize( dir );
m_flSpotlightCurLength = (0.60*m_flSpotlightCurLength) + (0.4*flBeamLength);
ComputeRenderInfo();
m_hSpotlight->RelinkBeam();
//NDebugOverlay::Cross3D(GetAbsOrigin(),Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
//NDebugOverlay::Cross3D(m_vSpotlightCurrentPos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1);
//NDebugOverlay::Cross3D(m_vSpotlightTargetPos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1);
// Do we need to keep updating?
if ( !GetMoveParent() && m_flRotationSpeed == 0 )
{
// No reason to think again, we're not going to move unless there's a data change
SetNextClientThink( CLIENT_THINK_NEVER );
}
}
//-----------------------------------------------------------------------------
void C_BeamSpotLight::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
m_flSpotlightCurLength = m_flSpotlightMaxLength;
}
// On a data change always think again
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
//------------------------------------------------------------------------------
void C_BeamSpotLight::Release()
{
SpotlightDestroy();
BaseClass::Release();
}
//------------------------------------------------------------------------------
void C_BeamSpotLight::SpotlightCreate(void)
{
m_vSpotlightTargetPos = SpotlightCurrentPos();
{
//C_Beam *beam = CBeam::BeamCreate( "sprites/spotlight.vmt", m_flSpotlightGoalWidth );
C_Beam *beam = C_Beam::BeamCreate( "sprites/glow_test02.vmt", m_flSpotlightGoalWidth );
// Beam only exists client side
ClientEntityList().AddNonNetworkableEntity( beam );
m_hSpotlight = beam;
}
// Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore)
m_hSpotlight->SetHDRColorScale( m_flHDRColorScale );
const color24 c = GetRenderColor();
m_hSpotlight->SetColor( c.r, c.g, c.b );
m_hSpotlight->SetHaloTexture(m_nHaloIndex);
m_hSpotlight->SetHaloScale(60);
m_hSpotlight->SetEndWidth(m_flSpotlightGoalWidth);
m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) );
m_hSpotlight->SetBrightness( 64 );
m_hSpotlight->SetNoise( 0 );
m_hSpotlight->PointsInit( GetAbsOrigin(), m_vSpotlightTargetPos );
}
//------------------------------------------------------------------------------
void C_BeamSpotLight::SpotlightDestroy(void)
{
if ( m_hSpotlight )
{
UTIL_Remove( m_hSpotlight );
m_hSpotlight.Term();
}
}
//------------------------------------------------------------------------------
Vector C_BeamSpotLight::SpotlightCurrentPos(void)
{
QAngle angles = GetAbsAngles();
GetVectors( &m_vSpotlightDir, NULL, NULL );
Vector position = GetAbsOrigin();
int cacheIndex = -1;
if ( m_pCache )
{
cacheIndex = int( angles[m_nRotationAxis] * float(NUM_CACHE_ENTRIES) * (1.0f / 360.0f)) & (NUM_CACHE_ENTRIES - 1);
if ( m_pCache[cacheIndex].IsValidFor(GetAbsOrigin()) )
{
return position + m_vSpotlightDir * m_pCache[cacheIndex].m_radius;
}
}
// Get beam end point. Only collide with solid objects, not npcs
trace_t tr;
UTIL_TraceLine( position, position + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
if ( cacheIndex >= 0 )
{
m_pCache[cacheIndex].Cache(position, tr);
}
return tr.endpos;
}
//-----------------------------------------------------------------------------
// Computes render info for a spotlight
//-----------------------------------------------------------------------------
void C_BeamSpotLight::ComputeRenderInfo()
{
// Fade out spotlight end if past max length.
if ( m_flSpotlightCurLength > 2*m_flSpotlightMaxLength )
{
SetRenderAlpha( 0 );
m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
}
else if ( m_flSpotlightCurLength > m_flSpotlightMaxLength )
{
SetRenderAlpha( (1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)) );
m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength );
}
else
{
SetRenderAlpha( 1.0 );
m_hSpotlight->SetFadeLength( m_flSpotlightCurLength );
}
// Adjust end width to keep beam width constant
float flNewWidth = m_flSpotlightGoalWidth * (m_flSpotlightCurLength / m_flSpotlightMaxLength);
flNewWidth = clamp(flNewWidth, 0, MAX_BEAM_WIDTH );
m_hSpotlight->SetEndWidth(flNewWidth);
if ( m_bHasDynamicLight )
{
// <<TODO>> - magic number 1.8 depends on sprite size
m_flLightScale = 1.8*flNewWidth;
if ( m_flLightScale > 0 )
{
const color24 c = GetRenderColor();
float a = GetRenderAlpha() / 255.0f;
ColorRGBExp32 color;
color.r = c.r * a;
color.g = c.g * a;
color.b = c.b * a;
color.exponent = 0;
if ( color.r == 0 && color.g == 0 && color.b == 0 )
return;
// Deal with the environment light
if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
{
m_pDynamicLight = effects->CL_AllocDlight( index );
assert (m_pDynamicLight);
}
//m_pDynamicLight->flags = DLIGHT_NO_MODEL_ILLUMINATION;
m_pDynamicLight->radius = m_flLightScale*3.0f;
m_pDynamicLight->origin = GetAbsOrigin() + Vector(0,0,5);
m_pDynamicLight->die = gpGlobals->curtime + 0.05f;
m_pDynamicLight->color = color;
}
}
}

View File

@ -0,0 +1,51 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "model_types.h"
#include "vcollide.h"
#include "vcollide_parse.h"
#include "solidsetdefaults.h"
#include "bone_setup.h"
#include "engine/ivmodelinfo.h"
#include "physics.h"
#include "c_breakableprop.h"
#include "view.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT(C_BreakableProp, DT_BreakableProp, CBreakableProp)
RecvPropBool( RECVINFO( m_bClientPhysics ) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_BreakableProp::C_BreakableProp( void )
{
m_takedamage = DAMAGE_YES;
}
//-----------------------------------------------------------------------------
// Copy fade from another breakable prop
//-----------------------------------------------------------------------------
void C_BreakableProp::CopyFadeFrom( C_BreakableProp *pSource )
{
SetGlobalFadeScale( pSource->GetGlobalFadeScale() );
SetDistanceFade( pSource->GetMinFadeDist(), pSource->GetMaxFadeDist() );
}
void C_BreakableProp::OnDataChanged( DataUpdateType_t type )
{
BaseClass::OnDataChanged( type );
if ( m_bClientPhysics )
{
bool bCreate = (type == DATA_UPDATE_CREATED) ? true : false;
VPhysicsShadowDataChanged(bCreate, this);
}
}

View File

@ -0,0 +1,37 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_BREAKABLEPROP_H
#define C_BREAKABLEPROP_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_BreakableProp : public C_BaseAnimating
{
typedef C_BaseAnimating BaseClass;
public:
DECLARE_CLIENTCLASS();
C_BreakableProp();
virtual bool IsProp( void ) const
{
return true;
};
// Copy fade from another breakable prop
void CopyFadeFrom( C_BreakableProp *pSource );
virtual void OnDataChanged( DataUpdateType_t type );
private:
bool m_bClientPhysics;
};
#endif // C_BREAKABLEPROP_H

View File

@ -0,0 +1,247 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Color correction entity with simple radial falloff
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_colorcorrection.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "colorcorrectionmgr.h"
#include "materialsystem/materialsystemutil.h"
#include "iclientmode.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar mat_colcorrection_disableentities( "mat_colcorrection_disableentities", "0", FCVAR_NONE, "Disable map color-correction entities" );
static ConVar mat_colcorrection_forceentitiesclientside( "mat_colcorrection_forceentitiesclientside", "0", FCVAR_CHEAT, "Forces color correction entities to be updated on the client" );
#ifdef CColorCorrection
#undef CColorCorrection
#endif
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrection, DT_ColorCorrection, CColorCorrection)
RecvPropVector( RECVINFO(m_vecOrigin) ),
RecvPropFloat( RECVINFO(m_minFalloff) ),
RecvPropFloat( RECVINFO(m_maxFalloff) ),
RecvPropFloat( RECVINFO(m_flCurWeight) ),
RecvPropFloat( RECVINFO(m_flMaxWeight) ),
RecvPropFloat( RECVINFO(m_flFadeInDuration) ),
RecvPropFloat( RECVINFO(m_flFadeOutDuration) ),
RecvPropString( RECVINFO(m_netLookupFilename) ),
RecvPropBool( RECVINFO(m_bEnabled) ),
RecvPropBool( RECVINFO(m_bMaster) ),
RecvPropBool( RECVINFO(m_bClientSide) ),
RecvPropBool( RECVINFO(m_bExclusive) )
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Constructor, destructor
//------------------------------------------------------------------------------
C_ColorCorrection::C_ColorCorrection()
{
m_minFalloff = -1.0f;
m_maxFalloff = -1.0f;
m_flFadeInDuration = 0.0f;
m_flFadeOutDuration = 0.0f;
m_flCurWeight = 0.0f;
m_flMaxWeight = 1.0f;
m_netLookupFilename[0] = '\0';
m_bEnabled = false;
m_bMaster = false;
m_bExclusive = false;
m_CCHandle = INVALID_CLIENT_CCHANDLE;
for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; i++ )
{
m_bEnabledOnClient[i] = false;
m_flCurWeightOnClient[i] = 0.0f;
m_bFadingIn[i] = false;
m_flFadeStartWeight[i] = 0.0f;
m_flFadeStartTime[i] = 0.0f;
m_flFadeDuration[i] = 0.0f;
}
}
C_ColorCorrection::~C_ColorCorrection()
{
g_pColorCorrectionMgr->RemoveColorCorrectionEntity( this, m_CCHandle );
}
bool C_ColorCorrection::IsClientSide() const
{
return m_bClientSide || mat_colcorrection_forceentitiesclientside.GetBool();
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_ColorCorrection::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_netLookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionEntity( this, name, m_netLookupFilename );
}
}
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_ColorCorrection::ShouldDraw()
{
return false;
}
void C_ColorCorrection::Update( C_BasePlayer *pPlayer, float ccScale )
{
Assert( m_CCHandle != INVALID_CLIENT_CCHANDLE );
if ( mat_colcorrection_disableentities.GetInt() )
{
// Allow the colorcorrectionui panel (or user) to turn off color-correction entities
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
bool bEnabled = IsClientSide() ? m_bEnabledOnClient[nSlot] : m_bEnabled;
// fade weight on client
if ( IsClientSide() )
{
m_flCurWeightOnClient[nSlot] = Lerp( GetFadeRatio( nSlot ), m_flFadeStartWeight[nSlot], m_bFadingIn[nSlot] ? m_flMaxWeight : 0.0f );
}
float flCurWeight = IsClientSide() ? m_flCurWeightOnClient[nSlot] : m_flCurWeight;
if( !bEnabled && flCurWeight == 0.0f )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
Vector playerOrigin = pPlayer->GetAbsOrigin();
float weight = 0;
if ( ( m_minFalloff != -1 ) && ( m_maxFalloff != -1 ) && m_minFalloff != m_maxFalloff )
{
float dist = (playerOrigin - m_vecOrigin).Length();
weight = (dist-m_minFalloff) / (m_maxFalloff-m_minFalloff);
if ( weight<0.0f ) weight = 0.0f;
if ( weight>1.0f ) weight = 1.0f;
}
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, flCurWeight * ( 1.0 - weight ) * ccScale, m_bExclusive );
}
void C_ColorCorrection::EnableOnClient( bool bEnable, bool bSkipFade )
{
if ( !IsClientSide() )
{
return;
}
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
if( m_bEnabledOnClient[nSlot] == bEnable )
{
return;
}
m_bFadingIn[nSlot] = bEnable;
m_bEnabledOnClient[nSlot] = bEnable;
// initialize countdown timer
m_flFadeStartWeight[nSlot] = m_flCurWeightOnClient[nSlot];
float flFadeTimeScale = 1.0f;
if ( m_flMaxWeight != 0.0f )
{
flFadeTimeScale = m_flCurWeightOnClient[nSlot] / m_flMaxWeight;
}
if ( m_bFadingIn[nSlot] )
{
flFadeTimeScale = 1.0f - flFadeTimeScale;
}
if ( bSkipFade )
{
flFadeTimeScale = 0.0f;
}
StartFade( nSlot, flFadeTimeScale * ( m_bFadingIn[nSlot] ? m_flFadeInDuration : m_flFadeOutDuration ) );
// update the clientside weight once here, in case the fade duration is 0
m_flCurWeightOnClient[nSlot] = Lerp( GetFadeRatio( nSlot ), m_flFadeStartWeight[nSlot], m_bFadingIn[nSlot] ? m_flMaxWeight : 0.0f );
}
Vector C_ColorCorrection::GetOrigin()
{
return m_vecOrigin;
}
float C_ColorCorrection::GetMinFalloff()
{
return m_minFalloff;
}
float C_ColorCorrection::GetMaxFalloff()
{
return m_maxFalloff;
}
void C_ColorCorrection::SetWeight( float fWeight )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, fWeight, false );
}
void C_ColorCorrection::StartFade( int nSplitScreenSlot, float flDuration )
{
m_flFadeStartTime[nSplitScreenSlot] = gpGlobals->curtime;
m_flFadeDuration[nSplitScreenSlot] = MAX( flDuration, 0.0f );
}
float C_ColorCorrection::GetFadeRatio( int nSplitScreenSlot ) const
{
float flRatio = 1.0f;
if ( m_flFadeDuration[nSplitScreenSlot] != 0.0f )
{
flRatio = ( gpGlobals->curtime - m_flFadeStartTime[nSplitScreenSlot] ) / m_flFadeDuration[nSplitScreenSlot];
flRatio = clamp( flRatio, 0.0f, 1.0f );
}
return flRatio;
}
bool C_ColorCorrection::IsFadeTimeElapsed( int nSplitScreenSlot ) const
{
return ( ( gpGlobals->curtime - m_flFadeStartTime[nSplitScreenSlot] ) > m_flFadeDuration[nSplitScreenSlot] ) ||
( ( gpGlobals->curtime - m_flFadeStartTime[nSplitScreenSlot] ) < 0.0f );
}
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}

View File

@ -0,0 +1,76 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Color correction entity with simple radial falloff
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_COLORCORRECTION_H
#define C_COLORCORRECTION_H
#ifdef _WIN32
#pragma once
#endif
#include "colorcorrectionmgr.h"
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ColorCorrection();
virtual ~C_ColorCorrection();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
virtual void Update(C_BasePlayer *pPlayer, float ccScale);
bool IsMaster() const { return m_bMaster; }
bool IsClientSide() const;
bool IsExclusive() const { return m_bExclusive; }
void EnableOnClient( bool bEnable, bool bSkipFade = false );
Vector GetOrigin();
float GetMinFalloff();
float GetMaxFalloff();
void SetWeight( float fWeight );
protected:
void StartFade( int nSplitScreenSlot, float flDuration );
float GetFadeRatio( int nSplitScreenSlot ) const;
bool IsFadeTimeElapsed( int nSplitScreenSlot ) const;
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_flFadeInDuration;
float m_flFadeOutDuration;
float m_flMaxWeight;
float m_flCurWeight; // networked from server
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled; // networked from server
bool m_bMaster;
bool m_bClientSide;
bool m_bExclusive;
bool m_bEnabledOnClient[MAX_SPLITSCREEN_PLAYERS];
float m_flCurWeightOnClient[MAX_SPLITSCREEN_PLAYERS];
bool m_bFadingIn[MAX_SPLITSCREEN_PLAYERS];
float m_flFadeStartWeight[MAX_SPLITSCREEN_PLAYERS];
float m_flFadeStartTime[MAX_SPLITSCREEN_PLAYERS];
float m_flFadeDuration[MAX_SPLITSCREEN_PLAYERS];
ClientCCHandle_t m_CCHandle;
};
#endif

View File

@ -0,0 +1,204 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Color correction entity.
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "materialsystem/materialsystemutil.h"
#include "colorcorrectionmgr.h"
#include "c_triggers.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//------------------------------------------------------------------------------
// FIXME: This really should inherit from something more lightweight
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Purpose : Shadow control entity
//------------------------------------------------------------------------------
class C_ColorCorrectionVolume : public C_BaseTrigger
{
public:
DECLARE_CLASS( C_ColorCorrectionVolume, C_BaseTrigger );
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
C_ColorCorrectionVolume();
virtual ~C_ColorCorrectionVolume();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void Update( C_BasePlayer *pPlayer, float ccScale );
void StartTouch( C_BaseEntity *pOther );
void EndTouch( C_BaseEntity *pOther );
private:
float m_LastEnterWeight;
float m_LastEnterTime;
float m_LastExitWeight;
float m_LastExitTime;
bool m_bEnabled;
float m_MaxWeight;
float m_FadeDuration;
float m_Weight;
char m_lookupFilename[MAX_PATH];
ClientCCHandle_t m_CCHandle;
};
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrectionVolume, DT_ColorCorrectionVolume, CColorCorrectionVolume)
RecvPropBool( RECVINFO(m_bEnabled) ),
RecvPropFloat( RECVINFO(m_MaxWeight) ),
RecvPropFloat( RECVINFO(m_FadeDuration) ),
RecvPropFloat( RECVINFO(m_Weight) ),
RecvPropString( RECVINFO(m_lookupFilename) ),
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_ColorCorrectionVolume )
DEFINE_PRED_FIELD( m_Weight, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
//------------------------------------------------------------------------------
// Constructor, destructor
//------------------------------------------------------------------------------
C_ColorCorrectionVolume::C_ColorCorrectionVolume()
{
m_CCHandle = INVALID_CLIENT_CCHANDLE;
}
C_ColorCorrectionVolume::~C_ColorCorrectionVolume()
{
g_pColorCorrectionMgr->RemoveColorCorrectionVolume( this, m_CCHandle );
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void C_ColorCorrectionVolume::OnDataChanged(DataUpdateType_t updateType)
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_lookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionVolume( this, name, m_lookupFilename );
SetSolid( SOLID_BSP );
SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID );
}
}
}
//------------------------------------------------------------------------------
// We don't draw...
//------------------------------------------------------------------------------
bool C_ColorCorrectionVolume::ShouldDraw()
{
return false;
}
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::StartTouch( CBaseEntity *pEntity )
{
m_LastEnterTime = gpGlobals->curtime;
m_LastEnterWeight = m_Weight;
}
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::EndTouch( CBaseEntity *pEntity )
{
m_LastExitTime = gpGlobals->curtime;
m_LastExitWeight = m_Weight;
}
void C_ColorCorrectionVolume::Update( C_BasePlayer *pPlayer, float ccScale )
{
if ( pPlayer )
{
bool isTouching = CollisionProp()->IsPointInBounds( pPlayer->EyePosition() );
bool wasTouching = m_LastEnterTime > m_LastExitTime;
if ( isTouching && !wasTouching )
{
StartTouch( pPlayer );
}
else if ( !isTouching && wasTouching )
{
EndTouch( pPlayer );
}
}
if( !m_bEnabled )
{
m_Weight = 0.0f;
}
else
{
if( m_LastEnterTime > m_LastExitTime )
{
// we most recently entered the volume
if( m_Weight < 1.0f )
{
float dt = gpGlobals->curtime - m_LastEnterTime;
float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = weight;
}
}
else
{
// we most recently exitted the volume
if( m_Weight > 0.0f )
{
float dt = gpGlobals->curtime - m_LastExitTime;
float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = 1.0f - weight;
}
}
}
// Vector entityPosition = GetAbsOrigin();
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight * ccScale );
}
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}

View File

@ -0,0 +1,239 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Dynamic light
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "dlight.h"
#include "iefx.h"
#include "IViewRender.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if HL2_EPISODIC
// In Episodic we unify the NO_WORLD_ILLUMINATION lights to use
// the more efficient elight structure instead. This should theoretically
// be extended to other projects but may have unintended consequences
// and bears more thorough testing.
//
// For an earlier iteration on this technique see changelist 214433,
// which had a specific flag for use of elights.
#define DLIGHT_NO_WORLD_USES_ELIGHT 1
#endif
//-----------------------------------------------------------------------------
// A dynamic light, with the goofy hack needed for spotlights
//-----------------------------------------------------------------------------
class C_DynamicLight : public C_BaseEntity
{
public:
DECLARE_CLASS( C_DynamicLight, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_DynamicLight();
public:
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink( void );
void Release( void );
unsigned char m_Flags;
unsigned char m_LightStyle;
float m_Radius;
int m_Exponent;
float m_InnerAngle;
float m_OuterAngle;
float m_SpotRadius;
private:
dlight_t* m_pDynamicLight;
dlight_t* m_pSpotlightEnd;
inline bool ShouldBeElight() { return (m_Flags & DLIGHT_NO_WORLD_ILLUMINATION); }
};
IMPLEMENT_CLIENTCLASS_DT(C_DynamicLight, DT_DynamicLight, CDynamicLight)
RecvPropInt (RECVINFO(m_Flags)),
RecvPropInt (RECVINFO(m_LightStyle)),
RecvPropFloat (RECVINFO(m_Radius)),
RecvPropInt (RECVINFO(m_Exponent)),
RecvPropFloat (RECVINFO(m_InnerAngle)),
RecvPropFloat (RECVINFO(m_OuterAngle)),
RecvPropFloat (RECVINFO(m_SpotRadius)),
END_RECV_TABLE()
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
C_DynamicLight::C_DynamicLight(void) : m_pSpotlightEnd(0), m_pDynamicLight(0)
{
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void C_DynamicLight::OnDataChanged(DataUpdateType_t updateType)
{
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink(gpGlobals->curtime + 0.05);
}
BaseClass::OnDataChanged( updateType );
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
bool C_DynamicLight::ShouldDraw()
{
return false;
}
//------------------------------------------------------------------------------
// Purpose : Disable drawing of this light when entity perishes
//------------------------------------------------------------------------------
void C_DynamicLight::Release()
{
if (m_pDynamicLight)
{
m_pDynamicLight->die = gpGlobals->curtime;
m_pDynamicLight = 0;
}
if (m_pSpotlightEnd)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
BaseClass::Release();
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void C_DynamicLight::ClientThink(void)
{
Vector forward;
AngleVectors( GetAbsAngles(), &forward );
if ( (m_Flags & DLIGHT_NO_MODEL_ILLUMINATION) == 0 )
{
// Deal with the model light
if ( !m_pDynamicLight || (m_pDynamicLight->key != index) )
{
#if DLIGHT_NO_WORLD_USES_ELIGHT
m_pDynamicLight = ShouldBeElight() != 0
? effects->CL_AllocElight( index )
: effects->CL_AllocDlight( index );
#else
m_pDynamicLight = effects->CL_AllocDlight( index );
#endif
Assert (m_pDynamicLight);
m_pDynamicLight->minlight = 0;
}
m_pDynamicLight->style = m_LightStyle;
m_pDynamicLight->radius = m_Radius;
m_pDynamicLight->flags = m_Flags;
if ( m_OuterAngle > 0 )
m_pDynamicLight->flags |= DLIGHT_NO_WORLD_ILLUMINATION;
color24 c = GetRenderColor();
m_pDynamicLight->color.r = c.r;
m_pDynamicLight->color.g = c.g;
m_pDynamicLight->color.b = c.b;
m_pDynamicLight->color.exponent = m_Exponent; // this makes it match the world
m_pDynamicLight->origin = GetAbsOrigin();
m_pDynamicLight->m_InnerAngle = m_InnerAngle;
m_pDynamicLight->m_OuterAngle = m_OuterAngle;
m_pDynamicLight->die = gpGlobals->curtime + 1e6;
m_pDynamicLight->m_Direction = forward;
}
else
{
// In this case, the m_Flags could have changed; which is how we turn the light off
if (m_pDynamicLight)
{
m_pDynamicLight->die = gpGlobals->curtime;
m_pDynamicLight = 0;
}
}
#if DLIGHT_NO_WORLD_USES_ELIGHT
if (( m_OuterAngle > 0 ) && !ShouldBeElight())
#else
if (( m_OuterAngle > 0 ) && ((m_Flags & DLIGHT_NO_WORLD_ILLUMINATION) == 0))
#endif
{
// Raycast to where the endpoint goes
// Deal with the environment light
if ( !m_pSpotlightEnd || (m_pSpotlightEnd->key != -index) )
{
m_pSpotlightEnd = effects->CL_AllocDlight( -index );
Assert (m_pSpotlightEnd);
}
// Trace a line outward, don't use hitboxes (too slow)
Vector end;
VectorMA( GetAbsOrigin(), m_Radius, forward, end );
trace_t pm;
C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace
UTIL_TraceLine( GetAbsOrigin(), end, MASK_NPCWORLDSTATIC, NULL, COLLISION_GROUP_NONE, &pm );
C_BaseEntity::PopEnableAbsRecomputations();
VectorCopy( pm.endpos, m_pSpotlightEnd->origin );
if (pm.fraction == 1.0f)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
else
{
float falloff = 1.0 - pm.fraction;
falloff *= falloff;
m_pSpotlightEnd->style = m_LightStyle;
m_pSpotlightEnd->flags = DLIGHT_NO_MODEL_ILLUMINATION | (m_Flags & DLIGHT_DISPLACEMENT_MASK);
m_pSpotlightEnd->radius = m_SpotRadius; // * falloff;
m_pSpotlightEnd->die = gpGlobals->curtime + 1e6;
color24 c = GetRenderColor();
m_pSpotlightEnd->color.r = c.r * falloff;
m_pSpotlightEnd->color.g = c.g * falloff;
m_pSpotlightEnd->color.b = c.b * falloff;
m_pSpotlightEnd->color.exponent = m_Exponent;
// For bumped lighting
m_pSpotlightEnd->m_Direction = forward;
// Update list of surfaces we influence
render->TouchLight( m_pSpotlightEnd );
}
}
else
{
// In this case, the m_Flags could have changed; which is how we turn the light off
if (m_pSpotlightEnd)
{
m_pSpotlightEnd->die = gpGlobals->curtime;
m_pSpotlightEnd = 0;
}
}
SetNextClientThink(gpGlobals->curtime + 0.001);
}

2657
game/client/c_effects.cpp Normal file

File diff suppressed because it is too large Load Diff

210
game/client/c_effects.h Normal file
View File

@ -0,0 +1,210 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef C_EFFECTS_H
#define C_EFFECTS_H
#ifdef _WIN32
#pragma once
#endif
#include "cbase.h"
#include "precipitation_shared.h"
// Draw rain effects.
void DrawPrecipitation();
//-----------------------------------------------------------------------------
// Precipitation particle type
//-----------------------------------------------------------------------------
class CPrecipitationParticle
{
public:
Vector m_Pos;
Vector m_Velocity;
float m_SpawnTime; // Note: Tweak with this to change lifetime
float m_Mass;
float m_Ramp;
float m_flMaxLifetime;
int m_nSplitScreenPlayerSlot;
};
class CClient_Precipitation;
static CUtlVector<CClient_Precipitation*> g_Precipitations;
//===========
// Snow fall
//===========
class CSnowFallManager;
static CSnowFallManager *s_pSnowFallMgr[ MAX_SPLITSCREEN_PLAYERS ];
bool SnowFallManagerCreate( CClient_Precipitation *pSnowEntity );
void SnowFallManagerDestroy( void );
class AshDebrisEffect : public CSimpleEmitter
{
public:
AshDebrisEffect( const char *pDebugName ) : CSimpleEmitter( pDebugName ) {}
static AshDebrisEffect* Create( const char *pDebugName );
virtual float UpdateAlpha( const SimpleParticle *pParticle );
virtual float UpdateRoll( SimpleParticle *pParticle, float timeDelta );
private:
AshDebrisEffect( const AshDebrisEffect & );
};
//-----------------------------------------------------------------------------
// Precipitation blocker entity
//-----------------------------------------------------------------------------
class C_PrecipitationBlocker : public C_BaseEntity
{
public:
DECLARE_CLASS( C_PrecipitationBlocker, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_PrecipitationBlocker();
virtual ~C_PrecipitationBlocker();
};
//-----------------------------------------------------------------------------
// Precipitation base entity
//-----------------------------------------------------------------------------
class CClient_Precipitation : public C_BaseEntity
{
class CPrecipitationEffect;
friend class CClient_Precipitation::CPrecipitationEffect;
public:
DECLARE_CLASS( CClient_Precipitation, C_BaseEntity );
DECLARE_CLIENTCLASS();
CClient_Precipitation();
virtual ~CClient_Precipitation();
// Inherited from C_BaseEntity
virtual void Precache( );
virtual RenderableTranslucencyType_t ComputeTranslucencyType() { return RENDERABLE_IS_TRANSLUCENT; }
void Render();
// Computes where we're gonna emit
bool ComputeEmissionArea( Vector& origin, Vector2D& size, C_BaseCombatCharacter *pCharacter );
private:
// Creates a single particle
CPrecipitationParticle* CreateParticle();
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink();
void Simulate( float dt );
// Renders the particle
void RenderParticle( CPrecipitationParticle* pParticle, CMeshBuilder &mb );
void CreateWaterSplashes();
// Emits the actual particles
void EmitParticles( float fTimeDelta );
// Gets the tracer width and speed
float GetWidth() const;
float GetLength() const;
float GetSpeed() const;
// Gets the remaining lifetime of the particle
float GetRemainingLifetime( CPrecipitationParticle* pParticle ) const;
// Computes the wind vector
static void ComputeWindVector( );
// simulation methods
bool SimulateRain( CPrecipitationParticle* pParticle, float dt );
bool SimulateSnow( CPrecipitationParticle* pParticle, float dt );
void CreateParticlePrecip( void );
void InitializeParticlePrecip( void );
void DispatchOuterParticlePrecip( int nSlot, C_BasePlayer *pPlayer, Vector vForward );
void DispatchInnerParticlePrecip( int nSlot, C_BasePlayer *pPlayer, Vector vForward );
void DestroyOuterParticlePrecip( int nSlot );
void DestroyInnerParticlePrecip( int nSlot );
void UpdateParticlePrecip( C_BasePlayer *pPlayer, int nSlot );
float GetDensity() { return m_flDensity; }
private:
void CreateAshParticle( void );
void CreateRainOrSnowParticle( const Vector &vSpawnPosition, const Vector &vEndPosition, const Vector &vVelocity ); // TERROR: adding end pos for lifetime calcs
// Information helpful in creating and rendering particles
IMaterial *m_MatHandle; // material used
float m_Color[4]; // precip color
float m_Lifetime; // Precip lifetime
float m_InitialRamp; // Initial ramp value
float m_Speed; // Precip speed
float m_Width; // Tracer width
float m_Remainder; // particles we should render next time
PrecipitationType_t m_nPrecipType; // Precip type
float m_flHalfScreenWidth; // Precalculated each frame.
float m_flDensity;
#ifdef INFESTED_DLL
int m_nSnowDustAmount;
#endif
// Some state used in rendering and simulation
// Used to modify the rain density and wind from the console
static ConVar s_raindensity;
static ConVar s_rainwidth;
static ConVar s_rainlength;
static ConVar s_rainspeed;
static Vector s_WindVector; // Stores the wind speed vector
CUtlLinkedList<CPrecipitationParticle> m_Particles;
CUtlVector<Vector> m_Splashes;
struct AshSplit_t
{
AshSplit_t() : m_bActiveAshEmitter( false ), m_vAshSpawnOrigin( 0, 0, 0 ), m_iAshCount( 0 )
{
}
CSmartPtr<AshDebrisEffect> m_pAshEmitter;
TimedEvent m_tAshParticleTimer;
TimedEvent m_tAshParticleTraceTimer;
bool m_bActiveAshEmitter;
Vector m_vAshSpawnOrigin;
int m_iAshCount;
};
protected:
AshSplit_t m_Ash[ MAX_SPLITSCREEN_PLAYERS ];
float m_flParticleInnerDist; //The distance at which to start drawing the inner system
char *m_pParticleInnerNearDef; //Name of the first inner system
char *m_pParticleInnerFarDef; //Name of the second inner system
char *m_pParticleOuterDef; //Name of the outer system
HPARTICLEFFECT m_pParticlePrecipInnerNear[ MAX_SPLITSCREEN_PLAYERS ];
HPARTICLEFFECT m_pParticlePrecipInnerFar[ MAX_SPLITSCREEN_PLAYERS ];
HPARTICLEFFECT m_pParticlePrecipOuter[ MAX_SPLITSCREEN_PLAYERS ];
TimedEvent m_tParticlePrecipTraceTimer[ MAX_SPLITSCREEN_PLAYERS ];
bool m_bActiveParticlePrecipEmitter[ MAX_SPLITSCREEN_PLAYERS ];
bool m_bParticlePrecipInitialized;
private:
CClient_Precipitation( const CClient_Precipitation & ); // not defined, not accessible
};
#endif // C_EFFECTS_H

View File

@ -0,0 +1,776 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "IViewRender.h"
#include "view.h"
#include "studio.h"
#include "bone_setup.h"
#include "model_types.h"
#include "beamdraw.h"
#include "engine/ivdebugoverlay.h"
#include "iviewrender_beams.h"
#include "fx.h"
#include "IEffects.h"
#include "c_entitydissolve.h"
#include "movevars_shared.h"
#include "precache_register.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectBuild )
PRECACHE( MATERIAL,"effects/tesla_glow_noz" )
PRECACHE( MATERIAL,"effects/spark" )
PRECACHE( MATERIAL,"effects/combinemuzzle2" )
PRECACHE_REGISTER_END()
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityDissolve, DT_EntityDissolve, CEntityDissolve )
RecvPropTime(RECVINFO(m_flStartTime)),
RecvPropFloat(RECVINFO(m_flFadeOutStart)),
RecvPropFloat(RECVINFO(m_flFadeOutLength)),
RecvPropFloat(RECVINFO(m_flFadeOutModelStart)),
RecvPropFloat(RECVINFO(m_flFadeOutModelLength)),
RecvPropFloat(RECVINFO(m_flFadeInStart)),
RecvPropFloat(RECVINFO(m_flFadeInLength)),
RecvPropInt(RECVINFO(m_nDissolveType)),
RecvPropVector( RECVINFO( m_vDissolverOrigin) ),
RecvPropInt( RECVINFO( m_nMagnitude ) ),
END_RECV_TABLE()
extern PMaterialHandle g_Material_Spark;
PMaterialHandle g_Material_AR2Glow = NULL;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityDissolve::C_EntityDissolve( void )
{
m_bLinkedToServerEnt = true;
m_pController = false;
m_bCoreExplode = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
if ( GetMoveParent() )
{
GetMoveParent()->GetRenderBounds( theMins, theMaxs );
}
else
{
theMins = GetAbsOrigin();
theMaxs = theMaxs;
}
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityDissolve::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
m_flNextSparkTime = m_flStartTime;
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Cleanup
//-----------------------------------------------------------------------------
void C_EntityDissolve::UpdateOnRemove( void )
{
if ( m_pController )
{
physenv->DestroyMotionController( m_pController );
m_pController = NULL;
}
BaseClass::UpdateOnRemove();
}
//------------------------------------------------------------------------------
// Apply the forces to the entity
//------------------------------------------------------------------------------
IMotionEvent::simresult_e C_EntityDissolve::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular )
{
linear.Init();
angular.Init();
// Make it zero g
linear.z -= -1.02 * sv_gravity.GetFloat();
Vector vel;
AngularImpulse angVel;
pObject->GetVelocity( &vel, &angVel );
vel += linear * deltaTime; // account for gravity scale
Vector unitVel = vel;
Vector unitAngVel = angVel;
float speed = VectorNormalize( unitVel );
// float angSpeed = VectorNormalize( unitAngVel );
// float speedScale = 0.0;
// float angSpeedScale = 0.0;
float flLinearLimit = 50;
float flLinearLimitDelta = 40;
if ( speed > flLinearLimit )
{
float flDeltaVel = (flLinearLimit - speed) / deltaTime;
if ( flLinearLimitDelta != 0.0f )
{
float flMaxDeltaVel = -flLinearLimitDelta / deltaTime;
if ( flDeltaVel < flMaxDeltaVel )
{
flDeltaVel = flMaxDeltaVel;
}
}
VectorMA( linear, flDeltaVel, unitVel, linear );
}
return SIM_GLOBAL_ACCELERATION;
}
//-----------------------------------------------------------------------------
// Tesla effect
//-----------------------------------------------------------------------------
static void FX_BuildTesla( C_BaseEntity *pEntity, Vector &vecOrigin, Vector &vecEnd )
{
BeamInfo_t beamInfo;
beamInfo.m_pStartEnt = pEntity;
beamInfo.m_nStartAttachment = 0;
beamInfo.m_pEndEnt = NULL;
beamInfo.m_nEndAttachment = 0;
beamInfo.m_nType = TE_BEAMTESLA;
beamInfo.m_vecStart = vecOrigin;
beamInfo.m_vecEnd = vecEnd;
beamInfo.m_pszModelName = "sprites/lgtning.vmt";
beamInfo.m_flHaloScale = 0.0;
beamInfo.m_flLife = random->RandomFloat( 0.25f, 1.0f );
beamInfo.m_flWidth = random->RandomFloat( 8.0f, 14.0f );
beamInfo.m_flEndWidth = 1.0f;
beamInfo.m_flFadeLength = 0.5f;
beamInfo.m_flAmplitude = 24;
beamInfo.m_flBrightness = 255.0;
beamInfo.m_flSpeed = 150.0f;
beamInfo.m_nStartFrame = 0.0;
beamInfo.m_flFrameRate = 30.0;
beamInfo.m_flRed = 255.0;
beamInfo.m_flGreen = 255.0;
beamInfo.m_flBlue = 255.0;
beamInfo.m_nSegments = 18;
beamInfo.m_bRenderable = true;
beamInfo.m_nFlags = 0; //FBEAM_ONLYNOISEONCE;
beams->CreateBeamEntPoint( beamInfo );
}
//-----------------------------------------------------------------------------
// Purpose: Tesla effect
//-----------------------------------------------------------------------------
void C_EntityDissolve::BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset )
{
Vector vecOrigin;
QAngle vecAngles;
MatrixGetColumn( hitboxToWorld, 3, vecOrigin );
MatrixAngles( hitboxToWorld, vecAngles.Base() );
C_BaseEntity *pEntity = GetMoveParent();
// Make a couple of tries at it
int iTries = -1;
Vector vecForward;
trace_t tr;
do
{
iTries++;
// Some beams are deliberatly aimed around the point, the rest are random.
if ( !bRandom )
{
QAngle vecTemp = vecAngles;
vecTemp[YAW] += flYawOffset;
AngleVectors( vecTemp, &vecForward );
// Randomly angle it up or down
vecForward.z = RandomFloat( -1, 1 );
}
else
{
vecForward = RandomVector( -1, 1 );
}
UTIL_TraceLine( vecOrigin, vecOrigin + (vecForward * 192), MASK_SHOT, pEntity, COLLISION_GROUP_NONE, &tr );
} while ( tr.fraction >= 1.0 && iTries < 3 );
Vector vecEnd = tr.endpos - (vecForward * 8);
// Only spark & glow if we hit something
if ( tr.fraction < 1.0 )
{
if ( !EffectOccluded( tr.endpos ) )
{
int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
// Move it towards the camera
Vector vecFlash = tr.endpos;
Vector vecForward;
AngleVectors( MainViewAngles(nSlot), &vecForward );
vecFlash -= (vecForward * 8);
g_pEffects->EnergySplash( vecFlash, -vecForward, false );
// End glow
CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "dust" );
pSimple->SetSortOrigin( vecFlash );
SimpleParticle *pParticle;
pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), pSimple->GetPMaterial( "effects/tesla_glow_noz" ), vecFlash );
if ( pParticle != NULL )
{
pParticle->m_flLifetime = 0.0f;
pParticle->m_flDieTime = RandomFloat( 0.5, 1 );
pParticle->m_vecVelocity = vec3_origin;
Vector color( 1,1,1 );
float colorRamp = RandomFloat( 0.75f, 1.25f );
pParticle->m_uchColor[0] = MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
pParticle->m_uchColor[1] = MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
pParticle->m_uchColor[2] = MIN( 1.0f, color[2] * colorRamp ) * 255.0f;
pParticle->m_uchStartSize = RandomFloat( 6,13 );
pParticle->m_uchEndSize = pParticle->m_uchStartSize - 2;
pParticle->m_uchStartAlpha = 255;
pParticle->m_uchEndAlpha = 10;
pParticle->m_flRoll = RandomFloat( 0,360 );
pParticle->m_flRollDelta = 0;
}
}
}
// Build the tesla
FX_BuildTesla( pEntity, vecOrigin, tr.endpos );
}
//-----------------------------------------------------------------------------
// Sorts the components of a vector
//-----------------------------------------------------------------------------
static inline void SortAbsVectorComponents( const Vector& src, int* pVecIdx )
{
Vector absVec( fabs(src[0]), fabs(src[1]), fabs(src[2]) );
int maxIdx = (absVec[0] > absVec[1]) ? 0 : 1;
if (absVec[2] > absVec[maxIdx])
{
maxIdx = 2;
}
// always choose something right-handed....
switch( maxIdx )
{
case 0:
pVecIdx[0] = 1;
pVecIdx[1] = 2;
pVecIdx[2] = 0;
break;
case 1:
pVecIdx[0] = 2;
pVecIdx[1] = 0;
pVecIdx[2] = 1;
break;
case 2:
pVecIdx[0] = 0;
pVecIdx[1] = 1;
pVecIdx[2] = 2;
break;
}
}
//-----------------------------------------------------------------------------
// Compute the bounding box's center, size, and basis
//-----------------------------------------------------------------------------
void C_EntityDissolve::ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec )
{
// Compute the center of the hitbox in worldspace
Vector vecHitboxCenter;
VectorAdd( pHitBox->bbmin, pHitBox->bbmax, vecHitboxCenter );
vecHitboxCenter *= 0.5f;
VectorTransform( vecHitboxCenter, hitboxToWorld, *pVecAbsOrigin );
// Get the object's basis
Vector vec[3];
MatrixGetColumn( hitboxToWorld, 0, vec[0] );
MatrixGetColumn( hitboxToWorld, 1, vec[1] );
MatrixGetColumn( hitboxToWorld, 2, vec[2] );
// vec[1] *= -1.0f;
Vector vecViewDir;
VectorSubtract( CurrentViewOrigin(), *pVecAbsOrigin, vecViewDir );
VectorNormalize( vecViewDir );
// Project the shadow casting direction into the space of the hitbox
Vector localViewDir;
localViewDir[0] = DotProduct( vec[0], vecViewDir );
localViewDir[1] = DotProduct( vec[1], vecViewDir );
localViewDir[2] = DotProduct( vec[2], vecViewDir );
// Figure out which vector has the largest component perpendicular
// to the view direction...
// Sort by how perpendicular it is
int vecIdx[3];
SortAbsVectorComponents( localViewDir, vecIdx );
// Here's our hitbox basis vectors; namely the ones that are
// most perpendicular to the view direction
*pXVec = vec[vecIdx[0]];
*pYVec = vec[vecIdx[1]];
// Project them into a plane perpendicular to the view direction
*pXVec -= vecViewDir * DotProduct( vecViewDir, *pXVec );
*pYVec -= vecViewDir * DotProduct( vecViewDir, *pYVec );
VectorNormalize( *pXVec );
VectorNormalize( *pYVec );
// Compute the hitbox size
Vector boxSize;
VectorSubtract( pHitBox->bbmax, pHitBox->bbmin, boxSize );
// We project the two longest sides into the vectors perpendicular
// to the projection direction, then add in the projection of the perp direction
Vector2D size( boxSize[vecIdx[0]], boxSize[vecIdx[1]] );
size.x *= fabs( DotProduct( vec[vecIdx[0]], *pXVec ) );
size.y *= fabs( DotProduct( vec[vecIdx[1]], *pYVec ) );
// Add the third component into x and y
size.x += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pXVec ) );
size.y += boxSize[vecIdx[2]] * fabs( DotProduct( vec[vecIdx[2]], *pYVec ) );
// Bloat a bit, since the shadow wants to extend outside the model a bit
size *= 2.0f;
// Clamp the minimum size
Vector2DMax( size, Vector2D(10.0f, 10.0f), size );
// Factor the size into the xvec + yvec
(*pXVec) *= size.x * 0.5f;
(*pYVec) *= size.y * 0.5f;
}
//-----------------------------------------------------------------------------
// Sparks!
//-----------------------------------------------------------------------------
void C_EntityDissolve::DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] )
{
if ( m_flNextSparkTime > gpGlobals->curtime )
return;
float dt = m_flStartTime + m_flFadeOutStart - gpGlobals->curtime;
dt = clamp( dt, 0.0f, m_flFadeOutStart );
float flNextTime;
if (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL)
{
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 2.0f * TICK_INTERVAL, 0.4f );
}
else
{
// m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT);
flNextTime = SimpleSplineRemapVal( dt, 0.0f, m_flFadeOutStart, 0.3f, 1.0f );
}
m_flNextSparkTime = gpGlobals->curtime + flNextTime;
// Send out beams around us
int iNumBeamsAround = 2;
int iNumRandomBeams = 1;
int iTotalBeams = iNumBeamsAround + iNumRandomBeams;
float flYawOffset = RandomFloat(0,360);
for ( int i = 0; i < iTotalBeams; i++ )
{
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
float flActualYawOffset = 0;
bool bRandom = ( i >= iNumBeamsAround );
if ( !bRandom )
{
flActualYawOffset = anglemod( flYawOffset + ((360 / iTotalBeams) * i) );
}
BuildTeslaEffect( pBox, *hitboxbones[pBox->bone], bRandom, flActualYawOffset );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::SetupEmitter( void )
{
if ( !m_pEmitter )
{
m_pEmitter = CSimpleEmitter::Create( "C_EntityDissolve" );
m_pEmitter->SetSortOrigin( GetAbsOrigin() );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetFadeInPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt > m_flFadeOutStart )
return 1.0f;
if ( dt < m_flFadeInStart )
return 0.0f;
if ( (dt > m_flFadeInStart) && (dt < m_flFadeInStart + m_flFadeInLength) )
{
dt -= m_flFadeInStart;
return ( dt / m_flFadeInLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetFadeOutPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt < m_flFadeInStart )
return 1.0f;
if ( dt > m_flFadeOutStart )
{
dt -= m_flFadeOutStart;
if ( dt > m_flFadeOutLength )
return 0.0f;
return 1.0f - ( dt / m_flFadeOutLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : float
//-----------------------------------------------------------------------------
float C_EntityDissolve::GetModelFadeOutPercentage( void )
{
float dt = gpGlobals->curtime - m_flStartTime;
if ( dt < m_flFadeOutModelStart )
return 1.0f;
if ( dt > m_flFadeOutModelStart )
{
dt -= m_flFadeOutModelStart;
if ( dt > m_flFadeOutModelLength )
return 0.0f;
return 1.0f - ( dt / m_flFadeOutModelLength );
}
return 1.0f;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityDissolve::ClientThink( void )
{
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if (!pAnimating)
return;
// NOTE: IsRagdoll means *client-side* ragdoll. We shouldn't be trying to fight
// the server ragdoll (or any server physics) on the client
if (( !m_pController ) && ( m_nDissolveType == ENTITY_DISSOLVE_NORMAL ) && pAnimating->IsRagdoll())
{
IPhysicsObject *ppList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
int nCount = pAnimating->VPhysicsGetObjectList( ppList, ARRAYSIZE(ppList) );
if ( nCount > 0 )
{
m_pController = physenv->CreateMotionController( this );
for ( int i = 0; i < nCount; ++i )
{
m_pController->AttachObject( ppList[i], true );
}
}
}
color32 color;
color.r = color.g = color.b = ( 1.0f - GetFadeInPercentage() ) * 255.0f;
color.a = GetModelFadeOutPercentage() * 255.0f;
// Setup the entity fade
pAnimating->SetRenderMode( kRenderTransColor );
pAnimating->SetRenderColor( color.r, color.g, color.b );
pAnimating->SetRenderAlpha( color.a );
if ( GetModelFadeOutPercentage() <= 0.2f )
{
m_bCoreExplode = true;
}
// If we're dead, fade out
if ( GetFadeOutPercentage() <= 0.0f )
{
// Do NOT remove from the client entity list. It'll confuse the local network backdoor, and the entity will never get destroyed
// because when the server says to destroy it, the client won't be able to find it.
// ClientEntityList().RemoveEntity( GetClientHandle() );
partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() );
RemoveFromLeafSystem();
//FIXME: Ick!
//Adrian: I'll assume we don't need the ragdoll either so I'll remove that too.
if ( m_bLinkedToServerEnt == false )
{
Release();
C_ClientRagdoll *pRagdoll = dynamic_cast <C_ClientRagdoll *> ( pAnimating );
if ( pRagdoll )
{
pRagdoll->ReleaseRagdoll();
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_EntityDissolve::DrawModel( int flags, const RenderableInstance_t &instance )
{
// See if we should draw
if ( gpGlobals->frametime == 0 || m_bReadyToDraw == false )
return 0;
C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
if ( pAnimating == NULL )
return 0;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) == false )
return 0;
studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if ( pStudioHdr == NULL )
return false;
mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
if ( set == NULL )
return false;
// Make sure the emitter is setup properly
SetupEmitter();
// Get fade percentages for the effect
float fadeInPerc = GetFadeInPercentage();
float fadeOutPerc = GetFadeOutPercentage();
float fadePerc = ( fadeInPerc >= 1.0f ) ? fadeOutPerc : fadeInPerc;
Vector vecSkew = vec3_origin;
// Do extra effects under certain circumstances
if ( ( fadePerc < 0.99f ) && ( (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) )
{
DoSparks( set, hitboxbones );
}
// Skew the particles in front or in back of their targets
vecSkew = CurrentViewForward() * ( 8.0f - ( ( 1.0f - fadePerc ) * 32.0f ) );
float spriteScale = ( ( gpGlobals->curtime - m_flStartTime ) / m_flFadeOutLength );
spriteScale = clamp( spriteScale, 0.75f, 1.0f );
// Cache off this material reference
if ( g_Material_Spark == NULL )
{
g_Material_Spark = ParticleMgr()->GetPMaterial( "effects/spark" );
}
if ( g_Material_AR2Glow == NULL )
{
g_Material_AR2Glow = ParticleMgr()->GetPMaterial( "effects/combinemuzzle2" );
}
SimpleParticle *sParticle;
for ( int i = 0; i < set->numhitboxes; ++i )
{
Vector vecAbsOrigin, xvec, yvec;
mstudiobbox_t *pBox = set->pHitbox(i);
ComputeRenderInfo( pBox, *hitboxbones[pBox->bone], &vecAbsOrigin, &xvec, &yvec );
Vector offset;
Vector xDir, yDir;
xDir = xvec;
float xScale = VectorNormalize( xDir ) * 0.75f;
yDir = yvec;
float yScale = VectorNormalize( yDir ) * 0.75f;
int numParticles = clamp( 3.0f * fadePerc, 0, 3 );
int iTempParts = 2;
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
numParticles = 15;
iTempParts = 20;
}
}
for ( int j = 0; j < iTempParts; j++ )
{
// Skew the origin
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
offset += vecSkew;
if ( random->RandomInt( 0, 2 ) != 0 )
continue;
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), g_Material_Spark, vecAbsOrigin + offset );
if ( sParticle == NULL )
return 1;
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( 16.0f, 64.0f ) );
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
Vector vDirection = (vecAbsOrigin + offset) - m_vDissolverOrigin;
VectorNormalize( vDirection );
sParticle->m_vecVelocity = vDirection * m_nMagnitude;
}
}
if ( sParticle->m_vecVelocity.z > 0 )
{
sParticle->m_uchStartSize = random->RandomFloat( 4, 6 ) * spriteScale;
}
else
{
sParticle->m_uchStartSize = 2 * spriteScale;
}
sParticle->m_flDieTime = random->RandomFloat( 0.4f, 0.5f );
// If we're the last particles, last longer
if ( numParticles == 0 )
{
sParticle->m_flDieTime *= 2.0f;
sParticle->m_uchStartSize = 2 * spriteScale;
sParticle->m_flRollDelta = Helper_RandomFloat( -4.0f, 4.0f );
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
sParticle->m_flDieTime *= 2.0f;
sParticle->m_flRollDelta = Helper_RandomFloat( -1.0f, 1.0f );
}
}
}
else
{
sParticle->m_flRollDelta = Helper_RandomFloat( -8.0f, 8.0f );
}
sParticle->m_flLifetime = 0.0f;
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
float alpha = 255;
sParticle->m_uchColor[0] = alpha;
sParticle->m_uchColor[1] = alpha;
sParticle->m_uchColor[2] = alpha;
sParticle->m_uchStartAlpha = alpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
}
for ( int j = 0; j < numParticles; j++ )
{
offset = xDir * Helper_RandomFloat( -xScale*0.5f, xScale*0.5f ) + yDir * Helper_RandomFloat( -yScale*0.5f, yScale*0.5f );
offset += vecSkew;
sParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), g_Material_AR2Glow, vecAbsOrigin + offset );
if ( sParticle == NULL )
return 1;
sParticle->m_vecVelocity = Vector( Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -4.0f, 4.0f ), Helper_RandomFloat( -64.0f, 128.0f ) );
sParticle->m_uchStartSize = random->RandomFloat( 8, 12 ) * spriteScale;
sParticle->m_flDieTime = 0.1f;
sParticle->m_flLifetime = 0.0f;
sParticle->m_flRoll = Helper_RandomInt( 0, 360 );
sParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
float alpha = 255;
sParticle->m_uchColor[0] = alpha;
sParticle->m_uchColor[1] = alpha;
sParticle->m_uchColor[2] = alpha;
sParticle->m_uchStartAlpha = alpha;
sParticle->m_uchEndAlpha = 0;
sParticle->m_uchEndSize = 0;
if ( m_nDissolveType == ENTITY_DISSOLVE_CORE )
{
if ( m_bCoreExplode == true )
{
Vector vDirection = (vecAbsOrigin + offset) - m_vDissolverOrigin;
VectorNormalize( vDirection );
sParticle->m_vecVelocity = vDirection * m_nMagnitude;
sParticle->m_flDieTime = 0.5f;
}
}
}
}
return 1;
}

View File

@ -0,0 +1,77 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef C_ENTITY_DISSOLVE_H
#define C_ENTITY_DISSOLVE_H
#include "cbase.h"
//-----------------------------------------------------------------------------
// Entity Dissolve, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityDissolve : public C_BaseEntity, public IMotionEvent
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityDissolve, C_BaseEntity );
C_EntityDissolve( void );
// Inherited from C_BaseEntity
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual bool ShouldDraw() { return true; }
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void UpdateOnRemove( void );
// Inherited from IMotionEvent
virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular );
void SetupEmitter( void );
void ClientThink( void );
void SetServerLinkState( bool state ) { m_bLinkedToServerEnt = state; }
float m_flStartTime;
float m_flFadeOutStart;
float m_flFadeOutLength;
float m_flFadeOutModelStart;
float m_flFadeOutModelLength;
float m_flFadeInStart;
float m_flFadeInLength;
int m_nDissolveType;
float m_flNextSparkTime;
Vector m_vDissolverOrigin;
int m_nMagnitude;
bool m_bCoreExplode;
protected:
float GetFadeInPercentage( void ); // Fade in amount (entity fading to black)
float GetFadeOutPercentage( void ); // Fade out amount (particles fading away)
float GetModelFadeOutPercentage( void );// Mode fade out amount
// Compute the bounding box's center, size, and basis
void ComputeRenderInfo( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld,
Vector *pVecAbsOrigin, Vector *pXVec, Vector *pYVec );
void BuildTeslaEffect( mstudiobbox_t *pHitBox, const matrix3x4_t &hitboxToWorld, bool bRandom, float flYawOffset );
void DoSparks( mstudiohitboxset_t *set, matrix3x4_t *hitboxbones[MAXSTUDIOBONES] );
private:
CSmartPtr<CSimpleEmitter> m_pEmitter;
bool m_bLinkedToServerEnt;
IPhysicsMotionController *m_pController;
};
#endif // C_ENTITY_DISSOLVE_H

View File

@ -0,0 +1,156 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_entityflame.h"
#include "particle_property.h"
#include "iefx.h"
#include "dlight.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Datadesc
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityFlame, DT_EntityFlame, CEntityFlame )
RecvPropEHandle(RECVINFO(m_hEntAttached)),
RecvPropBool(RECVINFO(m_bCheapEffect)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityFlame::C_EntityFlame( void ) : m_hEffect( NULL )
{
m_hOldAttached = NULL;
AddToEntityList( ENTITY_LIST_SIMULATE );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityFlame::~C_EntityFlame( void )
{
StopEffect();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::StopEffect( void )
{
if ( m_hEffect )
{
ParticleProp()->StopEmission( m_hEffect, true );
m_hEffect = NULL;
}
if ( m_hEntAttached )
{
m_hEntAttached->RemoveFlag( FL_ONFIRE );
m_hEntAttached->SetEffectEntity( NULL );
m_hEntAttached->StopSound( "General.BurningFlesh" );
m_hEntAttached->StopSound( "General.BurningObject" );
m_hEntAttached = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::UpdateOnRemove( void )
{
StopEffect();
BaseClass::UpdateOnRemove();
}
void C_EntityFlame::CreateEffect( void )
{
if ( m_hEffect )
{
m_hOldAttached = m_hEntAttached;
ParticleProp()->StopEmission( m_hEffect, true );
m_hEffect = NULL;
}
C_BaseEntity *pEntity = m_hEntAttached;
if ( pEntity && !pEntity->IsAbleToHaveFireEffect() )
return;
m_hEffect = ParticleProp()->Create( m_bCheapEffect ? "burning_gib_01" : "burning_character", PATTACH_ABSORIGIN_FOLLOW );
if ( m_hEffect )
{
m_hOldAttached = m_hEntAttached;
ParticleProp()->AddControlPoint( m_hEffect, 1, pEntity, PATTACH_ABSORIGIN_FOLLOW );
m_hEffect->SetControlPoint( 0, GetAbsOrigin() );
m_hEffect->SetControlPoint( 1, GetAbsOrigin() );
m_hEffect->SetControlPointEntity( 0, pEntity );
m_hEffect->SetControlPointEntity( 1, pEntity );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::OnDataChanged( DataUpdateType_t updateType )
{
if ( updateType == DATA_UPDATE_CREATED )
{
CreateEffect();
}
// FIXME: This is a bit of a shady path
if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
{
// If our owner changed, then recreate the effect
if ( m_hEntAttached != m_hOldAttached )
{
CreateEffect();
}
}
BaseClass::OnDataChanged( updateType );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_EntityFlame::Simulate( void )
{
if ( gpGlobals->frametime <= 0.0f )
return true;
#ifdef HL2_EPISODIC
if ( IsEffectActive(EF_BRIGHTLIGHT) || IsEffectActive(EF_DIMLIGHT) )
{
dlight_t *dl = effects->CL_AllocDlight( index );
dl->origin = GetAbsOrigin();
dl->origin[2] += 16;
dl->color.r = 254;
dl->color.g = 174;
dl->color.b = 10;
dl->radius = random->RandomFloat(400,431);
dl->die = gpGlobals->curtime + 0.001;
}
#endif // HL2_EPISODIC
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFlame::ClientThink( void )
{
StopEffect();
Release();
}

View File

@ -0,0 +1,43 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef C_ENTITY_FLAME_H
#define C_ENTITY_FLAME_H
#include "c_baseentity.h"
//
// Entity flame, client-side implementation
//
class C_EntityFlame : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityFlame, C_BaseEntity );
C_EntityFlame( void );
virtual ~C_EntityFlame( void );
virtual bool Simulate( void );
virtual void UpdateOnRemove( void );
virtual void OnDataChanged( DataUpdateType_t updateType );
virtual void ClientThink( void );
EHANDLE m_hEntAttached; // The entity that we are burning (attached to).
private:
void CreateEffect( void );
void StopEffect( void );
CUtlReference<CNewParticleEffect> m_hEffect;
EHANDLE m_hOldAttached;
bool m_bCheapEffect;
};
#endif // C_ENTITY_FLAME_H

View File

@ -0,0 +1,116 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_entityfreezing.h"
#include "studio.h"
#include "bone_setup.h"
#include "c_surfacerender.h"
#include "engine/ivdebugoverlay.h"
#include "dt_utlvector_recv.h"
#include "debugoverlay_shared.h"
#include "animation.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar cl_blobulator_freezing_max_metaball_radius( "cl_blobulator_freezing_max_metaball_radius",
#ifdef INFESTED_DLL
"25.0", // Don't need as much precision in Alien swarm because everything is zoomed out
#else
"12.0",
#endif
FCVAR_NONE, "Setting this can create more complex surfaces on large hitboxes at the cost of performance.", true, 12.0f, true, 100.0f );
//PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheEffectFreezing )
// PRECACHE( MATERIAL,"effects/tesla_glow_noz" )
// PRECACHE( MATERIAL,"effects/spark" )
// PRECACHE( MATERIAL,"effects/combinemuzzle2" )
//PRECACHE_REGISTER_END()
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityFreezing, DT_EntityFreezing, CEntityFreezing )
RecvPropVector( RECVINFO(m_vFreezingOrigin) ),
RecvPropArray3( RECVINFO_ARRAY(m_flFrozenPerHitbox), RecvPropFloat( RECVINFO( m_flFrozenPerHitbox[0] ) ) ),
RecvPropFloat( RECVINFO(m_flFrozen) ),
RecvPropBool( RECVINFO(m_bFinishFreezing) ),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFreezing::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
if ( GetMoveParent() )
{
GetMoveParent()->GetRenderBounds( theMins, theMaxs );
}
else
{
theMins = GetAbsOrigin();
theMaxs = theMaxs;
}
}
//-----------------------------------------------------------------------------
// Yes we bloody are
//-----------------------------------------------------------------------------
RenderableTranslucencyType_t C_EntityFreezing::ComputeTranslucencyType( )
{
return RENDERABLE_IS_TRANSLUCENT;
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityFreezing::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityFreezing::ClientThink( void )
{
__asm nop;
//C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL;
//if (!pAnimating)
// return;
//color32 color = pAnimating->GetRenderColor();
//color.r = color.g = ( 1.0f - m_flFrozen ) * 255.0f;
//// Setup the entity fade
//pAnimating->SetRenderMode( kRenderTransColor );
//pAnimating->SetRenderColor( color.r, color.g, color.b, color.a );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
// Output : int
//-----------------------------------------------------------------------------
int C_EntityFreezing::DrawModel( int flags, const RenderableInstance_t &instance )
{
return 1;
}

View File

@ -0,0 +1,47 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef C_ENTITY_FREEZING_H
#define C_ENTITY_FREEZING_H
#include "cbase.h"
struct EntityFreezingHitboxBlobData_t
{
CUtlVector<Vector> m_vPoints;
};
//-----------------------------------------------------------------------------
// Entity Dissolve, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityFreezing : public C_BaseEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityFreezing, C_BaseEntity );
virtual void GetRenderBounds( Vector& theMins, Vector& theMaxs );
virtual RenderableTranslucencyType_t ComputeTranslucencyType( );
virtual int DrawModel( int flags, const RenderableInstance_t &instance );
virtual bool ShouldDraw() { return true; }
virtual void OnDataChanged( DataUpdateType_t updateType );
void ClientThink( void );
private:
Vector m_vFreezingOrigin;
float m_flFrozenPerHitbox[ 50 ];
float m_flFrozen;
bool m_bFinishFreezing;
CUtlVector<EntityFreezingHitboxBlobData_t> m_HitboxBlobData;
};
#endif // C_ENTITY_FREEZING_H

View File

@ -0,0 +1,250 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "baseparticleentity.h"
#include "entityparticletrail_shared.h"
#include "particlemgr.h"
#include "particle_util.h"
#include "particles_simple.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Entity particle trail, client-side implementation
//-----------------------------------------------------------------------------
class C_EntityParticleTrail : public C_BaseParticleEntity
{
public:
DECLARE_CLIENTCLASS();
DECLARE_CLASS( C_EntityParticleTrail, C_BaseParticleEntity );
C_EntityParticleTrail( );
~C_EntityParticleTrail( );
// C_BaseEntity
virtual void OnDataChanged( DataUpdateType_t updateType );
// IParticleEffect
void Update( float fTimeDelta );
virtual void RenderParticles( CParticleRenderIterator *pIterator );
virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
private:
C_EntityParticleTrail( const C_EntityParticleTrail & ); // not defined, not accessible
void Start( );
void AddParticle( float flInitialDeltaTime, const Vector &vecMins, const Vector &vecMaxs, const matrix3x4_t &boxToWorld );
int m_iMaterialName;
EntityParticleTrailInfo_t m_Info;
EHANDLE m_hConstraintEntity;
PMaterialHandle m_hMaterial;
TimedEvent m_teParticleSpawn;
};
//-----------------------------------------------------------------------------
// Networking
//-----------------------------------------------------------------------------
IMPLEMENT_CLIENTCLASS_DT( C_EntityParticleTrail, DT_EntityParticleTrail, CEntityParticleTrail )
RecvPropInt(RECVINFO(m_iMaterialName)),
RecvPropDataTable( RECVINFO_DT( m_Info ), 0, &REFERENCE_RECV_TABLE(DT_EntityParticleTrailInfo) ),
RecvPropEHandle(RECVINFO(m_hConstraintEntity)),
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EntityParticleTrail::C_EntityParticleTrail( void )
{
}
C_EntityParticleTrail::~C_EntityParticleTrail()
{
ParticleMgr()->RemoveEffect( &m_ParticleEffect );
}
//-----------------------------------------------------------------------------
// On data changed
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
if ( updateType == DATA_UPDATE_CREATED )
{
Start( );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pParticleMgr -
// *pArgs -
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::Start( )
{
if( ParticleMgr()->AddEffect( &m_ParticleEffect, this ) == false )
return;
const char *pMaterialName = GetMaterialNameFromIndex( m_iMaterialName );
if ( !pMaterialName )
return;
m_hMaterial = ParticleMgr()->GetPMaterial( pMaterialName );
m_teParticleSpawn.Init( 150 );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::AddParticle( float flInitialDeltaTime, const Vector &vecMins, const Vector &vecMaxs, const matrix3x4_t &boxToWorld )
{
// Select a random point somewhere in the hitboxes of the entity.
Vector vecLocalPosition, vecWorldPosition;
vecLocalPosition.x = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.x, vecMaxs.x );
vecLocalPosition.y = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.y, vecMaxs.y );
vecLocalPosition.z = Lerp( random->RandomFloat( 0.0f, 1.0f ), vecMins.z, vecMaxs.z );
VectorTransform( vecLocalPosition, boxToWorld, vecWorldPosition );
// Don't emit the particle unless it's inside the model
if ( m_hConstraintEntity.Get() )
{
Ray_t ray;
trace_t tr;
ray.Init( vecWorldPosition, vecWorldPosition );
enginetrace->ClipRayToEntity( ray, MASK_ALL, m_hConstraintEntity, &tr );
if ( !tr.startsolid )
return;
}
// Make a new particle
SimpleParticle *pParticle = (SimpleParticle *)m_ParticleEffect.AddParticle( sizeof(SimpleParticle), m_hMaterial );
if ( pParticle == NULL )
return;
pParticle->m_Pos = vecWorldPosition;
pParticle->m_flRoll = Helper_RandomInt( 0, 360 );
pParticle->m_flRollDelta = Helper_RandomFloat( -2.0f, 2.0f );
pParticle->m_flLifetime = flInitialDeltaTime;
pParticle->m_flDieTime = m_Info.m_flLifetime;
pParticle->m_uchColor[0] = 64;
pParticle->m_uchColor[1] = 140;
pParticle->m_uchColor[2] = 225;
pParticle->m_uchStartAlpha = Helper_RandomInt( 64, 64 );
pParticle->m_uchEndAlpha = 0;
pParticle->m_uchStartSize = m_Info.m_flStartSize;
pParticle->m_uchEndSize = m_Info.m_flEndSize;
pParticle->m_vecVelocity = vec3_origin;
VectorMA( pParticle->m_Pos, flInitialDeltaTime, pParticle->m_vecVelocity, pParticle->m_Pos );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : fTimeDelta -
//-----------------------------------------------------------------------------
void C_EntityParticleTrail::Update( float fTimeDelta )
{
float tempDelta = fTimeDelta;
studiohdr_t *pStudioHdr;
mstudiohitboxset_t *set;
matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
C_BaseEntity *pMoveParent = GetMoveParent();
if ( !pMoveParent )
return;
C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating();
if (!pAnimating)
goto trailNoHitboxes;
if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) )
goto trailNoHitboxes;
pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() );
if (!pStudioHdr)
goto trailNoHitboxes;
set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() );
if ( !set )
goto trailNoHitboxes;
//Add new particles
while ( m_teParticleSpawn.NextEvent( tempDelta ) )
{
int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 );
mstudiobbox_t *pBox = set->pHitbox(nHitbox);
AddParticle( tempDelta, pBox->bbmin, pBox->bbmax, *hitboxbones[pBox->bone] );
}
return;
trailNoHitboxes:
while ( m_teParticleSpawn.NextEvent( tempDelta ) )
{
AddParticle( tempDelta, pMoveParent->CollisionProp()->OBBMins(), pMoveParent->CollisionProp()->OBBMaxs(), pMoveParent->EntityToWorldTransform() );
}
}
inline void C_EntityParticleTrail::RenderParticles( CParticleRenderIterator *pIterator )
{
const SimpleParticle *pParticle = (const SimpleParticle*)pIterator->GetFirst();
while ( pParticle )
{
float t = pParticle->m_flLifetime / pParticle->m_flDieTime;
// Render
Vector tPos;
TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
float sortKey = tPos.z;
Vector color = Vector( pParticle->m_uchColor[0] / 255.0f, pParticle->m_uchColor[1] / 255.0f, pParticle->m_uchColor[2] / 255.0f );
float alpha = Lerp( t, pParticle->m_uchStartAlpha / 255.0f, pParticle->m_uchEndAlpha / 255.0f );
float flSize = Lerp( t, pParticle->m_uchStartSize, pParticle->m_uchEndSize );
// Render it
RenderParticle_ColorSize( pIterator->GetParticleDraw(), tPos, color, alpha, flSize );
pParticle = (const SimpleParticle*)pIterator->GetNext( sortKey );
}
}
inline void C_EntityParticleTrail::SimulateParticles( CParticleSimulateIterator *pIterator )
{
SimpleParticle *pParticle = (SimpleParticle*)pIterator->GetFirst();
while ( pParticle )
{
// Update position
float flTimeDelta = pIterator->GetTimeDelta();
pParticle->m_Pos += pParticle->m_vecVelocity * flTimeDelta;
// NOTE: I'm overloading "die time" to be the actual start time.
pParticle->m_flLifetime += flTimeDelta;
if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
pIterator->RemoveParticle( pParticle );
pParticle = (SimpleParticle*)pIterator->GetNext();
}
}

View File

@ -0,0 +1,95 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Ambient light controller entity with simple radial falloff
//
// $NoKeywords: $
//===========================================================================//
#include "cbase.h"
#include "c_spatialentity.h"
#include "spatialentitymgr.h"
#include "c_env_ambient_light.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static ConVar cl_ambient_light_disableentities( "cl_ambient_light_disableentities", "0", FCVAR_NONE, "Disable map ambient light entities." );
static CSpatialEntityMgr s_EnvAmbientLightMgr;
IMPLEMENT_CLIENTCLASS_DT( C_EnvAmbientLight, DT_EnvAmbientLight, CEnvAmbientLight )
RecvPropVector( RECVINFO_NAME( m_Value, m_vecColor ) ),
END_RECV_TABLE()
void C_EnvAmbientLight::ApplyAccumulation( void )
{
Vector rgbVal = BlendedValue();
static ConVarRef mat_ambient_light_r( "mat_ambient_light_r" );
static ConVarRef mat_ambient_light_g( "mat_ambient_light_g" );
static ConVarRef mat_ambient_light_b( "mat_ambient_light_b" );
if ( mat_ambient_light_r.IsValid() )
{
mat_ambient_light_r.SetValue( rgbVal.x );
}
if ( mat_ambient_light_g.IsValid() )
{
mat_ambient_light_g.SetValue( rgbVal.y );
}
if ( mat_ambient_light_b.IsValid() )
{
mat_ambient_light_b.SetValue( rgbVal.z );
}
}
void C_EnvAmbientLight::AddToPersonalSpatialEntityMgr( void )
{
s_EnvAmbientLightMgr.AddSpatialEntity( this );
}
void C_EnvAmbientLight::RemoveFromPersonalSpatialEntityMgr( void )
{
s_EnvAmbientLightMgr.RemoveSpatialEntity( this );
}
void C_EnvAmbientLight::SetColor( const Vector &vecColor, float flLerpTime )
{
if ( flLerpTime <= 0 )
{
m_Value = vecColor / 255.0f;
m_colorTimer.Invalidate();
return;
}
m_vecStartColor = m_Value;
m_vecTargetColor = vecColor / 255.0f;
m_colorTimer.Start( flLerpTime );
}
void C_EnvAmbientLight::ClientThink( void )
{
BaseClass::ClientThink();
if ( m_colorTimer.HasStarted() )
{
if ( m_colorTimer.IsElapsed() )
{
m_Value = m_vecTargetColor;
m_colorTimer.Invalidate();
}
else
{
m_Value = m_vecTargetColor - ( m_vecTargetColor - m_vecStartColor ) * m_colorTimer.GetRemainingRatio();
}
}
}

View File

@ -0,0 +1,30 @@
#ifndef _INCLUDED_C_ENV_AMBIENT_LIGHT_H
#define _INCLUDED_C_ENV_AMBIENT_LIGHT_H
#include "c_spatialentity.h"
//------------------------------------------------------------------------------
// Purpose : Ambient light controller entity with radial falloff
//------------------------------------------------------------------------------
class C_EnvAmbientLight : public C_SpatialEntityTemplate<Vector>
{
public:
DECLARE_CLASS( C_EnvAmbientLight, C_SpatialEntityTemplate<Vector> );
DECLARE_CLIENTCLASS();
virtual void ApplyAccumulation( void );
virtual void ClientThink( void );
void SetColor( const Vector &vecColor, float flLerpTime = 0 );
Vector GetTargetColor() { return m_vecTargetColor * 255.0f; }
protected:
virtual void AddToPersonalSpatialEntityMgr( void );
virtual void RemoveFromPersonalSpatialEntityMgr( void );
Vector m_vecStartColor;
Vector m_vecTargetColor;
CountdownTimer m_colorTimer;
};
#endif // _INCLUDED_C_ENV_AMBIENT_LIGHT_H

View File

@ -0,0 +1,100 @@
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "cbase.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
extern bool g_bDOFEnabled;
extern float g_flDOFNearBlurDepth;
extern float g_flDOFNearFocusDepth;
extern float g_flDOFFarFocusDepth;
extern float g_flDOFFarBlurDepth;
extern float g_flDOFNearBlurRadius;
extern float g_flDOFFarBlurRadius;
EHANDLE g_hDOFControllerInUse = NULL;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class C_EnvDOFController : public C_BaseEntity
{
DECLARE_CLASS( C_EnvDOFController, C_BaseEntity );
public:
DECLARE_CLIENTCLASS();
C_EnvDOFController();
~C_EnvDOFController();
virtual void OnDataChanged( DataUpdateType_t updateType );
private:
bool m_bDOFEnabled;
float m_flNearBlurDepth;
float m_flNearFocusDepth;
float m_flFarFocusDepth;
float m_flFarBlurDepth;
float m_flNearBlurRadius;
float m_flFarBlurRadius;
private:
C_EnvDOFController( const C_EnvDOFController & );
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvDOFController, DT_EnvDOFController, CEnvDOFController )
RecvPropInt( RECVINFO(m_bDOFEnabled) ),
RecvPropFloat( RECVINFO(m_flNearBlurDepth) ),
RecvPropFloat( RECVINFO(m_flNearFocusDepth) ),
RecvPropFloat( RECVINFO(m_flFarFocusDepth) ),
RecvPropFloat( RECVINFO(m_flFarBlurDepth) ),
RecvPropFloat( RECVINFO(m_flNearBlurRadius) ),
RecvPropFloat( RECVINFO(m_flFarBlurRadius) )
END_RECV_TABLE()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvDOFController::C_EnvDOFController( void )
: m_bDOFEnabled( true ),
m_flNearBlurDepth( 50.0f ),
m_flNearFocusDepth( 100.0f ),
m_flFarFocusDepth( 250.0f ),
m_flFarBlurDepth( 1000.0f ),
m_flNearBlurRadius( 0.0f ), // no near blur by default
m_flFarBlurRadius( 5.0f )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
C_EnvDOFController::~C_EnvDOFController( void )
{
if ( g_hDOFControllerInUse == this )
{
g_bDOFEnabled = false;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_EnvDOFController::OnDataChanged( DataUpdateType_t updateType )
{
BaseClass::OnDataChanged( updateType );
g_bDOFEnabled = m_bDOFEnabled && ( ( m_flNearBlurRadius > 0.0f ) || ( m_flFarBlurRadius > 0.0f ) );
g_flDOFNearBlurDepth = m_flNearBlurDepth;
g_flDOFNearFocusDepth = m_flNearFocusDepth;
g_flDOFFarFocusDepth = m_flFarFocusDepth;
g_flDOFFarBlurDepth = m_flFarBlurDepth;
g_flDOFNearBlurRadius = m_flNearBlurRadius;
g_flDOFFarBlurRadius = m_flFarBlurRadius;
g_hDOFControllerInUse = this;
}

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