Merge branch 'ValveSoftware:master' into master

This commit is contained in:
CookieCat 2025-05-14 00:26:44 -04:00 committed by GitHub
commit d64a531377
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
122 changed files with 12286 additions and 295 deletions

13
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,13 @@
<!--
Thanks for your interest in Source SDK 2013! When you make a contribution to the Source SDK 2013, either by creating an Issue or submitting a Pull Request (a "Contribution"), Valve wants to be able to use your Contribution to improve the Source 2013 SDK and other Valve products.
1. Contributions: When you provide a Contribution, please ensure it is your original creation. You agree to the following license and warranty for any Contributions you provide:
1.1 You grant Valve a non-exclusive, perpetual, irrevocable, royalty-free, sublicensable, and worldwide license to make, use, sell, reproduce, modify, create derivate works, directly and indirectly distribute, publicly display, publish, transmit and perform the Contribution, and any derivative works thereof. .
1.2 You represent and warrant that you are either the owner or authorized licensee of the Contribution, that you have all necessary consents to grant this license to the Contribution to Valve, and that the Contribution does not violate any third-party intellectual property rights.
1.3 Except as set forth in (2) above, you provide your Contribution "as is" without warranties of any kind.
2. Other Materials or Suggestions: If you want to submit any materials or suggestions that are not your original work, you agree to do the following:
2.1 You may submit other materials or suggestions to Valve separate from any Contributions;
2.2 You will explicitly identify them as sourced from a third party and state the details of its origin; and
2.3 You will include Valve with any third party licenses, terms, or other restrictions that apply, if you are aware of any.
-->
# Description

View File

@ -1,38 +1,9 @@
Thanks for your interest in the Source SDK 2013 project. When you make a
contribution to the project (e.g. create an Issue or submit a Pull Request)
(a "Contribution"), Valve wants to be able to use your Contribution to improve
the SDK and other Valve products.
As a condition of providing a Contribution, you agree that:
- You grant Valve a non-exclusive, irrevocable, royalty-free, worldwide license
to make, use, sell, reproduce, modify, distribute (directly and indirectly),
and publicly display and perform the Contribution, and any derivative works
that Valve may make from the Contribution, under any intellectual property you
own or have the right to license.
- You warrant and represent that the Contribution is your original creation,
that you have the authority to grant this license to Valve, and that this
license does not require the permission of any third party. Otherwise, you
provide your Contribution "as is" without warranties.
Should you wish to submit a suggestion or work that is not your original
creation, you may submit it to Valve separate from any Contribution,
explicitly identifying it as sourced from a third party, stating the details
of its origin, and informing Valve of any license or other restriction of
which you are personally aware.
Valve is happy to accept pull requests and issues in the source-sdk-2013
repository in these cases:
* Changes that fix bugs in the SDK deployment process itself. The repository
should build out of the box, and anything that prevents that is a pull
request we want.
* High priority bugs in HL2, the Episodes, or HL2MP that can be fixed in
client.dll or server.dll.
For other changes we suggest that you issue a pull request to one of these
fine community-maintained repositories instead:
https://developer.valvesoftware.com/wiki/Source-sdk-2013-community-repos
If you are going to make a pull request, please keep them as granular as
possible. Pull requests with 3-4 unrelated changes in them aren't going to
be accepted.
Thanks for your interest in Source SDK 2013! When you make a contribution to the Source SDK 2013, either by creating an Issue or submitting a Pull Request (a "Contribution"), Valve wants to be able to use your Contribution to improve the Source 2013 SDK and other Valve products.
1. Contributions: When you provide a Contribution, please ensure it is your original creation. You agree to the following license and warranty for any Contributions you provide:
1.1 You grant Valve a non-exclusive, perpetual, irrevocable, royalty-free, sublicensable, and worldwide license to make, use, sell, reproduce, modify, create derivate works, directly and indirectly distribute, publicly display, publish, transmit and perform the Contribution, and any derivative works thereof. .
1.2 You represent and warrant that you are either the owner or authorized licensee of the Contribution, that you have all necessary consents to grant this license to the Contribution to Valve, and that the Contribution does not violate any third-party intellectual property rights.
1.3 Except as set forth in (2) above, you provide your Contribution "as is" without warranties of any kind.
2. Other Materials or Suggestions: If you want to submit any materials or suggestions that are not your original work, you agree to do the following:
2.1 You may submit other materials or suggestions to Valve separate from any Contributions;
2.2 You will explicitly identify them as sourced from a third party and state the details of its origin; and
2.3 You will include Valve with any third party licenses, terms, or other restrictions that apply, if you are aware of any.

View File

@ -18,6 +18,6 @@ WARRANTY OF ANY KIND. VALVE EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS O
INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, TITLE AND FITNESS FOR A PARTICULAR PURPOSE.
LIMITATION OF LIABILITY. VALVE AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES WHATSOEVER ) THAT MAY BE INCURRED BY YOU EVEN IF VALVE HAS BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
OR CONSEQUENTIAL DAMAGES WHATSOEVER THAT MAY BE INCURRED BY YOU EVEN IF VALVE HAS BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF SUCH DAMAGES.

View File

@ -16,7 +16,11 @@ Clone the repository using the following command:
Requirements:
- Source SDK 2013 Multiplayer installed via Steam
- Visual Studio 2022
- Visual Studio 2022 with the following workload and components:
- Desktop development with C++:
- MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
- Windows 11 SDK (10.0.22621.0) or Windows 10 SDK (10.0.19041.1)
- Python 3.13 or later
Inside the cloned directory, navigate to `src`, run:
```bat

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -441,10 +441,10 @@ void CHudCommentary::Paint()
// Draw the speaker names
// Get our scheme and font information
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
vgui::HFont hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "CommentaryDefault" );
vgui::HFont hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "CommentaryDefault", true );
if ( !hFont )
{
hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "Default" );
hFont = vgui::scheme()->GetIScheme(scheme)->GetFont( "Default", true );
}
vgui::surface()->DrawSetTextFont( hFont );
vgui::surface()->DrawSetTextColor( clr );

View File

@ -267,7 +267,7 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void )
char szFullFileName[_MAX_PATH];
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory, szMatFileName );
KeyValues *pMaterialKeys = new KeyValues( "material" );
KeyValuesAD pMaterialKeys( "material" );
bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
if ( bLoaded )

View File

@ -121,7 +121,7 @@ inline ClientThinkHandle_t CClientThinkList::GetInvalidThinkHandle()
inline CClientThinkList::ThinkEntry_t* CClientThinkList::GetThinkEntry( ClientThinkHandle_t hThink )
{
return &m_ThinkEntries[ (unsigned long)hThink ];
return &m_ThinkEntries[ (uintp)hThink ];
}

View File

@ -837,23 +837,26 @@ void ClientModeShared::StartMessageMode( int iMessageModeType )
}
#if defined( TF_CLIENT_DLL )
bool bSuspensionInMatch = GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch();
if ( !cl_enable_text_chat.GetBool() || bSuspensionInMatch )
if ( iMessageModeType == MM_SAY || iMessageModeType == MM_SAY_TEAM )
{
CBaseHudChat *pHUDChat = ( CBaseHudChat * ) GET_HUDELEMENT( CHudChat );
if ( pHUDChat )
bool bSuspensionInMatch = GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch();
if ( !cl_enable_text_chat.GetBool() || bSuspensionInMatch )
{
const char *pszReason = "#TF_Chat_Disabled";
if ( bSuspensionInMatch )
CBaseHudChat *pHUDChat = ( CBaseHudChat * ) GET_HUDELEMENT( CHudChat );
if ( pHUDChat )
{
pszReason = "#TF_Chat_Unavailable";
}
const char *pszReason = "#TF_Chat_Disabled";
if ( bSuspensionInMatch )
{
pszReason = "#TF_Chat_Unavailable";
}
char szLocalized[100];
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pszReason ), szLocalized, sizeof( szLocalized ) );
pHUDChat->ChatPrintf( 0, CHAT_FILTER_NONE, "%s ", szLocalized );
char szLocalized[100];
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pszReason ), szLocalized, sizeof( szLocalized ) );
pHUDChat->ChatPrintf( 0, CHAT_FILTER_NONE, "%s ", szLocalized );
}
return;
}
return;
}
#endif // TF_CLIENT_DLL

View File

@ -1596,7 +1596,7 @@ void CHudCloseCaption::CreateFonts( void )
{
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
m_hFonts[CCFONT_NORMAL] = pScheme->GetFont( "CloseCaption_Normal", true );
m_hFonts[CCFONT_NORMAL] = pScheme->GetFont( "CloseCaption", true );
if ( IsPC() )
{

View File

@ -191,12 +191,12 @@ void CMoveHelperClient::ProcessImpacts( void )
}
// misyl: Debug
if ( vOldLocalVel != vOldAbsVel )
{
Msg( "%d\n", gpGlobals->tickcount );
Msg( "vOldLocalVel: %f %f %f\n", vOldLocalVel.x, vOldLocalVel.y, vOldLocalVel.z );
Msg( "vOldAbsVel: %f %f %f\n", vOldAbsVel.x, vOldAbsVel.y, vOldAbsVel.z );
}
// if ( vOldLocalVel != vOldAbsVel )
// {
// Msg( "%d\n", gpGlobals->tickcount );
// Msg( "vOldLocalVel: %f %f %f\n", vOldLocalVel.x, vOldLocalVel.y, vOldLocalVel.z );
// Msg( "vOldAbsVel: %f %f %f\n", vOldAbsVel.x, vOldAbsVel.y, vOldAbsVel.z );
// }
// Restore the velocity
m_pHost->SetAbsVelocity( vOldAbsVel );
//m_pHost->SetLocalVelocity( vOldLocalVel );

View File

@ -146,6 +146,7 @@ CParticleEffectBinding::CParticleEffectBinding()
m_LastMin = m_Min;
m_LastMax = m_Max;
m_flParticleCullRadius = -1.f; // dummy value, is overwritten below
SetParticleCullRadius( 0.0f );
m_nActiveParticles = 0;

View File

@ -6050,7 +6050,7 @@ void C_TFPlayer::ClientThink()
//
// Passtime ask for ball button
//
if ( m_nButtons & IN_ATTACK3 )
if ( m_afButtonPressed & IN_ATTACK3 )
{
engine->ClientCmd("voicemenu 1 8");
}

View File

@ -531,6 +531,7 @@ void ClientModeTFNormal::Shutdown()
{
RemoveFilesInPath( "materials/temp" );
RemoveFilesInPath( "download/user_custom" );
RemoveFilesInPath( "sound/temp" );
}
DestroyStatsSummaryPanel();

View File

@ -35,7 +35,7 @@ void CTFAutoRP::ParseDataFile( void )
Assert( !m_pDataFileKV );
// Load & parse the word files
KeyValues *pFileKV = new KeyValues( "AutoRPFile" );
KeyValuesAD pFileKV( "AutoRPFile" );
if ( pFileKV->LoadFromFile( filesystem, "scripts/autorp.txt", "MOD" ) == false )
return;
@ -547,7 +547,7 @@ void CTFAutoRP::ModifySpeech( const char *pszInText, char *pszOutText, int iOutL
{
szStoredWord[0] = toupper( szStoredWord[0] );
}
else if ( pszCurWord[0] >= 'a' && pszCurWord[0] <= 'a' )
else if ( pszCurWord[0] >= 'a' && pszCurWord[0] <= 'z' )
{
szStoredWord[0] = tolower( szStoredWord[0] );
}

View File

@ -777,7 +777,7 @@ void CHudMainMenuOverride::LoadCharacterImageFile( void )
//-----------------------------------------------------------------------------
void CHudMainMenuOverride::LoadMenuEntries( void )
{
KeyValues *datafile = new KeyValues("GameMenu");
KeyValuesAD datafile("GameMenu");
datafile->UsesEscapeSequences( true ); // VGUI uses escape sequences
bool bLoaded = datafile->LoadFromFile( g_pFullFileSystem, "Resource/GameMenu.res", "custom_mod" );
if ( !bLoaded )
@ -2274,7 +2274,7 @@ public:
//V_strcpy_safe( uilanguage, "german" );
KeyValues *pEntriesKV = new KeyValues( "motd_entries");
KeyValuesAD pEntriesKV( "motd_entries");
// Try and load the cache file. If we fail, we'll just create a new one.
if ( !pMMPanel->ReloadedAllMOTDs() )

View File

@ -851,7 +851,14 @@ void CWaveStatusPanel::UpdateEnemyCounts( void )
if ( pPanel->m_pEnemyCountImageBG )
{
pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
if ( support[i].iFlags & MVM_CLASS_FLAG_MINIBOSS )
{
pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrMiniBoss );
}
else
{
pPanel->m_pEnemyCountImageBG->SetBgColor( m_clrNormal );
}
}
if ( pPanel->m_pEnemyCountCritBG )

View File

@ -574,6 +574,23 @@ void CTFHudMatchStatus::FireGameEvent( IGameEvent * event )
}
const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
// FIX: Refresh versus doors so late-joiners do not see the wrong skin
int nSkin = 0;
int nSubModel = 0;
if (pMatchDesc->BGetRoundDoorParameters(nSkin, nSubModel))
{
// Is VS doors model not initialized yet?
if (m_pMatchStartModelPanel->m_hModel == NULL)
{
m_pMatchStartModelPanel->UpdateModel();
}
m_pMatchStartModelPanel->SetBodyGroup( "logos", nSubModel );
m_pMatchStartModelPanel->UpdateModel();
m_pMatchStartModelPanel->SetSkin( nSkin );
}
bool bForceDoors = false;
if ( bForceDoors || ( pMatchDesc && pMatchDesc->BUsesPostRoundDoors() ) )
{

View File

@ -242,6 +242,7 @@ protected:
virtual void ApplySchemeSettings(vgui::IScheme *scheme);
virtual void Paint( void );
virtual bool ShouldDraw( void );
virtual bool CanAnimate() const OVERRIDE { return false; }
private:
int m_iScopeTexture[4];

View File

@ -385,14 +385,6 @@ void CTFMapInfoMenu::LoadMapPage()
{
m_pMapInfo->SetText( wszMapDescription );
}
else if ( StringHasPrefix( m_szMapName, "vsh_" ) )
{
m_pMapInfo->SetText( "#default_vsh_description" );
}
else if ( StringHasPrefix( m_szMapName, "zi_" ) )
{
m_pMapInfo->SetText( "#default_zi_description" );
}
else
{
// try loading map descriptions from .txt files first
@ -497,7 +489,15 @@ void CTFMapInfoMenu::LoadMapPage()
if( !g_pVGuiLocalize->Find( mapInfoKey ) )
{
if ( TFGameRules() )
if ( StringHasPrefix( m_szMapName, "vsh_" ) )
{
pszDescription = "#default_vsh_description";
}
else if ( StringHasPrefix( m_szMapName, "zi_" ) )
{
pszDescription = "#default_zi_description";
}
else if ( TFGameRules() )
{
if ( TFGameRules()->IsMannVsMachineMode() )
{

View File

@ -17,6 +17,10 @@
static int g_ActiveVoiceMenu = 0;
#if defined( TF_CLIENT_DLL )
extern ConVar tf_voice_command_suspension_mode;
#endif
void OpenVoiceMenu( int index )
{
// do not show the menu if the player is dead or is an observer
@ -28,7 +32,7 @@ void OpenVoiceMenu( int index )
return;
#if defined ( TF_CLIENT_DLL )
if ( GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch() )
if ( GTFGCClientSystem() && GTFGCClientSystem()->BHaveChatSuspensionInCurrentMatch() && tf_voice_command_suspension_mode.GetInt() == 1 )
{
CBaseHudChat *pHUDChat = ( CBaseHudChat * ) GET_HUDELEMENT( CHudChat );
if ( pHUDChat )

View File

@ -40,6 +40,7 @@ public:
virtual Vector EyePosition( void );
virtual INextBot *MyNextBotPointer( void ) { return this; }
virtual bool IsNextBot(void) const { return true; }
// Event hooks into NextBot system ---------------------------------------
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );

View File

@ -146,4 +146,10 @@ void CSkyCamera::Activate( )
}
}
#endif
// matches the behavior of fog controller
if ( GameRules()->IsOfficialMap() )
{
m_skyboxData.fog.radial = true;
}
}

View File

@ -996,6 +996,9 @@ public:
void TraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType );
virtual bool IsTriggered( CBaseEntity *pActivator ) {return true;}
virtual bool IsNPC( void ) const { return false; }
#ifdef NEXT_BOT
virtual bool IsNextBot(void) const { return false; }
#endif
CAI_BaseNPC *MyNPCPointer( void );
virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return NULL; }
virtual INextBot *MyNextBotPointer( void ) { return NULL; }

View File

@ -95,9 +95,9 @@ ConVar spec_freeze_traveltime( "spec_freeze_traveltime", "0.4", FCVAR_CHEAT | FC
ConVar sv_bonus_challenge( "sv_bonus_challenge", "0", FCVAR_REPLICATED, "Set to values other than 0 to select a bonus map challenge type." );
ConVar sv_chat_bucket_size_tier1( "sv_chat_bucket_size_tier1", "4", FCVAR_NONE, "The maxmimum size of the short term chat msg bucket." );
ConVar sv_chat_bucket_size_tier1( "sv_chat_bucket_size_tier1", "4", FCVAR_NONE, "The maximum size of the short term chat msg bucket." );
ConVar sv_chat_seconds_per_msg_tier1( "sv_chat_seconds_per_msg_tier1", "3", FCVAR_NONE, "The number of seconds to accrue an additional short term chat msg." );
ConVar sv_chat_bucket_size_tier2( "sv_chat_bucket_size_tier2", "30", FCVAR_NONE, "The maxmimum size of the long term chat msg bucket." );
ConVar sv_chat_bucket_size_tier2( "sv_chat_bucket_size_tier2", "30", FCVAR_NONE, "The maximum size of the long term chat msg bucket." );
ConVar sv_chat_seconds_per_msg_tier2( "sv_chat_seconds_per_msg_tier2", "10", FCVAR_NONE, "The number of seconds to accrue an additional long term chat msg." );
static ConVar sv_maxusrcmdprocessticks( "sv_maxusrcmdprocessticks", "24", FCVAR_NOTIFY, "Maximum number of client-issued usrcmd ticks that can be replayed in packet loss conditions, 0 to allow no restrictions" );
@ -8102,13 +8102,6 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data)
}
void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID)
{
int mask = (1<<PLAYER_FLAG_BITS) - 1;
int data = *(int *)pVarData;
pOut->m_Int = ( data & mask );
}
// -------------------------------------------------------------------------------- //
// SendTable for CPlayerState.
// -------------------------------------------------------------------------------- //
@ -8187,7 +8180,7 @@ void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const voi
SendPropInt (SENDINFO(m_iBonusProgress), 15 ),
SendPropInt (SENDINFO(m_iBonusChallenge), 4 ),
SendPropFloat (SENDINFO(m_flMaxspeed), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), // CL
SendPropInt (SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN, SendProxy_CropFlagsToPlayerFlagBitsLength ),
SendPropInt (SENDINFO(m_fFlags), 0, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN ),
SendPropInt (SENDINFO(m_iObserverMode), 3, SPROP_UNSIGNED ),
SendPropEHandle (SENDINFO(m_hObserverTarget) ),
SendPropInt (SENDINFO(m_iFOV), 8, SPROP_UNSIGNED ),

View File

@ -523,7 +523,7 @@ void CSlideshowDisplay::BuildSlideShowImagesList( void )
char szFullFileName[_MAX_PATH];
Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory.Get(), szMatFileName );
KeyValues *pMaterialKeys = new KeyValues( "material" );
KeyValuesAD pMaterialKeys( "material" );
bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL );
if ( bLoaded )

View File

@ -1156,6 +1156,9 @@ int CTeamControlPointMaster::GetNumPointsOwnedByTeam( int iTeam )
//-----------------------------------------------------------------------------
int CTeamControlPointMaster::CalcNumRoundsRemaining( int iTeam )
{
if ( m_ControlPointRounds.IsEmpty() )
return 0;
// To determine how many rounds remain for a given team if it consistently wins mini-rounds, we have to
// simulate forward each mini-round and track the control point ownership that would result

View File

@ -29,7 +29,8 @@ ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::OnStart( CTFBot *me,
ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::Update( CTFBot *me, float interval )
{
CTeamControlPoint *point = me->GetMyControlPoint();
if ( !point )
CCaptureZone *zone = me->GetFlagCaptureZone();
if ( !point && !zone )
{
// wait until a control point becomes available
return Continue();
@ -64,7 +65,14 @@ ActionResult< CTFBot > CTFBotEngineerBuildTeleportEntrance::Update( CTFBot *me,
if ( !m_path.IsValid() )
{
CTFBotPathCost cost( me, FASTEST_ROUTE );
m_path.Compute( me, point->GetAbsOrigin(), cost );
if ( point )
{
m_path.Compute( me, point->GetAbsOrigin(), cost );
}
else if ( zone )
{
m_path.Compute( me, zone->WorldSpaceCenter(), cost );
}
}
m_path.Update( me );

View File

@ -243,7 +243,7 @@ ActionResult< CTFBot > CTFBotDeliverFlag::Update( CTFBot *me, float interval )
m_flTotalTravelDistance = NavAreaTravelDistance( me->GetLastKnownArea(), TheNavMesh->GetNavArea( zone->WorldSpaceCenter() ), cost );
if ( flOldTravelDistance != -1.0f && m_flTotalTravelDistance - flOldTravelDistance > 2000.0f )
if ( TFGameRules()->IsMannVsMachineMode() && flOldTravelDistance != -1.0f && m_flTotalTravelDistance - flOldTravelDistance > 2000.0f )
{
TFGameRules()->BroadcastSound( 255, "Announcer.MVM_Bomb_Reset" );

View File

@ -70,7 +70,14 @@ ActionResult< CTFBot > CTFBotSpyHide::Update( CTFBot *me, float interval )
if ( m_talkTimer.IsElapsed() )
{
m_talkTimer.Start( RandomFloat( 5.0f, 10.0f ) );
me->EmitSound( "Spy.TeaseVictim" );
if ( TFGameRules()->IsMannVsMachineMode() && me->GetTeamNumber() == TF_TEAM_PVE_INVADERS )
{
me->EmitSound( "Spy.MVM_TeaseVictim" );
}
else
{
me->EmitSound( "Spy.TeaseVictim" );
}
}
if ( m_isAtGoal )

View File

@ -704,9 +704,9 @@ DEFINE_SCRIPTFUNC( IsOnAnyMission, "Return true if this bot has a current missio
DEFINE_SCRIPTFUNC_WRAPPED( SetMissionTarget, "Set this bot's mission target to the given entity" )
DEFINE_SCRIPTFUNC_WRAPPED( GetMissionTarget, "Get this bot's current mission target" )
DEFINE_SCRIPTFUNC( SetBehaviorFlag, "Set the given behavior flag(s) for this bot" )
DEFINE_SCRIPTFUNC( ClearBehaviorFlag, "Clear the given behavior flag(s) for this bot" )
DEFINE_SCRIPTFUNC( IsBehaviorFlagSet, "Return true if the given behavior flag(s) are set for this bot" )
DEFINE_SCRIPTFUNC_WRAPPED( SetBehaviorFlag, "Set the given behavior flag(s) for this bot" )
DEFINE_SCRIPTFUNC_WRAPPED( ClearBehaviorFlag, "Clear the given behavior flag(s) for this bot" )
DEFINE_SCRIPTFUNC_WRAPPED( IsBehaviorFlagSet, "Return true if the given behavior flag(s) are set for this bot" )
DEFINE_SCRIPTFUNC_WRAPPED( SetActionPoint, "Set the given action point for this bot" )
DEFINE_SCRIPTFUNC_WRAPPED( GetActionPoint, "Get the given action point for this bot" )

View File

@ -331,6 +331,9 @@ public:
void SetBehaviorFlag( unsigned int flags );
void ClearBehaviorFlag( unsigned int flags );
bool IsBehaviorFlagSet( unsigned int flags ) const;
void ScriptSetBehaviorFlag( int flags ) { this->SetBehaviorFlag( (unsigned int)flags ); }
void ScriptClearBehaviorFlag( int flags ) { this->ClearBehaviorFlag( (unsigned int)flags ); }
bool ScriptIsBehaviorFlagSet( int flags ) const { return this->IsBehaviorFlagSet( (unsigned int)flags ); }
bool FindSplashTarget( CBaseEntity *target, float maxSplashRadius, Vector *splashTarget ) const;
@ -358,11 +361,11 @@ public:
CBaseEntity *GetMissionTarget( void ) const;
void SetMissionString( CUtlString string );
CUtlString *GetMissionString( void );
void ScriptSetMission( unsigned int mission, bool resetBehaviorSystem = true ) { this->SetMission( (MissionType)mission, resetBehaviorSystem ); }
void ScriptSetPrevMission( unsigned int mission ) { this->SetPrevMission( (MissionType)mission ); }
unsigned int ScriptGetMission( void ) const { return (unsigned int)this->GetMission(); }
unsigned int ScriptGetPrevMission( void ) const { return (unsigned int)this->GetPrevMission(); }
bool ScriptHasMission( unsigned int mission ) const { return this->HasMission( (MissionType)mission ); }
void ScriptSetMission( int mission, bool resetBehaviorSystem = true ) { this->SetMission( (MissionType)mission, resetBehaviorSystem ); }
void ScriptSetPrevMission( int mission ) { this->SetPrevMission( (MissionType)mission ); }
int ScriptGetMission( void ) const { return (int)this->GetMission(); }
int ScriptGetPrevMission( void ) const { return (int)this->GetPrevMission(); }
bool ScriptHasMission( int mission ) const { return this->HasMission( (MissionType)mission ); }
void ScriptSetMissionTarget( HSCRIPT hTarget ) { this->SetMissionTarget( ToEnt( hTarget ) ); }
HSCRIPT ScriptGetMissionTarget( void ) const { return ToHScript( this->GetMissionTarget() ); }

View File

@ -17,6 +17,7 @@
#include "particle_parse.h"
#include "player_vs_environment/tf_population_manager.h"
#include "collisionutils.h"
#include "func_respawnroom.h"
#include "tf_objective_resource.h"
//=============================================================================
@ -209,6 +210,21 @@ void CCurrencyPack::ComeToRest( void )
}
}
}
// Or a func_respawnroom (robots can drop money in their own spawn)
for ( int i = 0; i < IFuncRespawnRoomAutoList::AutoList().Count(); i++ )
{
CFuncRespawnRoom *pRespawnRoom = static_cast<CFuncRespawnRoom *>( IFuncRespawnRoomAutoList::AutoList()[ i ] );
Vector vecMins, vecMaxs;
pRespawnRoom->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs );
if ( IsPointInBox( GetCollideable()->GetCollisionOrigin(), vecMins, vecMaxs ) )
{
TFGameRules()->DistributeCurrencyAmount( m_nAmount );
m_bTouched = true;
UTIL_Remove( this );
}
}
}
//-----------------------------------------------------------------------------

View File

@ -2626,7 +2626,7 @@ void CPopulationManager::AllocateBots()
Warning( "%d bots were already allocated some how before CPopulationManager::AllocateBots was called\n", botVector.Count() );
}
for ( int i = nNumEnemyBots; i < MVM_INVADERS_TEAM_SIZE; ++i )
for ( int i = nNumEnemyBots; i < tf_mvm_max_invaders.GetInt(); ++i )
{
CTFBot* newBot = NextBotCreatePlayerBot< CTFBot >( "TFBot", false );
if ( newBot )

View File

@ -137,8 +137,6 @@ public:
bool IsBonusRound() const { return m_bBonusRound; }
CBaseCombatCharacter* GetBonusBoss() const { return m_hBonusBoss; }
enum { MVM_INVADERS_TEAM_SIZE = 22 };
static bool GetWavesUseReadyBetween() { return true; }
void SetDefaultEventChangeAttributesName( const char* pszDefaultEventChangeAttributesName ) { m_defaultEventChangeAttributesName = pszDefaultEventChangeAttributesName; }

View File

@ -1014,7 +1014,7 @@ bool CTFBotSpawner::Spawn( const Vector &rawHere, EntityHandleVector_t *result )
nNumEnemyBots = botVector.Count();
if ( nNumEnemyBots >= CPopulationManager::MVM_INVADERS_TEAM_SIZE )
if ( nNumEnemyBots >= tf_mvm_max_invaders.GetInt() )
{
// no room for more
if ( tf_populator_debug.GetBool() )
@ -1023,10 +1023,10 @@ bool CTFBotSpawner::Spawn( const Vector &rawHere, EntityHandleVector_t *result )
}
// extra guard if we're over full on bots
if ( nNumEnemyBots > CPopulationManager::MVM_INVADERS_TEAM_SIZE )
if ( nNumEnemyBots > tf_mvm_max_invaders.GetInt() )
{
// Kick bots until we are at the proper number starting with spectator bots
int iNumberToKick = nNumEnemyBots - CPopulationManager::MVM_INVADERS_TEAM_SIZE;
int iNumberToKick = nNumEnemyBots - tf_mvm_max_invaders.GetInt();
int iKickedBots = 0;
// loop through spectators and invaders in that order

View File

@ -741,7 +741,7 @@ bool CMissionPopulator::UpdateMission( CTFBot::MissionType mission )
// are there enough free slots?
int currentEnemyCount = GetGlobalTeam( TF_TEAM_PVE_INVADERS )->GetNumPlayers();
if ( currentEnemyCount + m_desiredCount > CPopulationManager::MVM_INVADERS_TEAM_SIZE )
if ( currentEnemyCount + m_desiredCount > tf_mvm_max_invaders.GetInt() )
{
// not enough slots yet
if ( tf_populator_debug.GetBool() )
@ -1578,7 +1578,7 @@ void CWaveSpawnPopulator::Update( void )
int currentEnemyCount = GetGlobalTeam( TF_TEAM_PVE_INVADERS )->GetNumPlayers();
if ( currentEnemyCount + m_spawnCount + m_reservedPlayerSlotCount > CPopulationManager::MVM_INVADERS_TEAM_SIZE )
if ( currentEnemyCount + m_spawnCount + m_reservedPlayerSlotCount > tf_mvm_max_invaders.GetInt() )
{
// no space right now
return;

View File

@ -126,7 +126,6 @@
#include "tf_revive.h"
#include "tf_logic_halloween_2014.h"
#include "tf_logic_player_destruction.h"
#include "tf_weapon_rocketpack.h"
#include "tf_weapon_slap.h"
#include "func_croc.h"
#include "tf_weapon_bonesaw.h"
@ -278,6 +277,7 @@ extern ConVar sv_vote_allow_spectators;
ConVar sv_vote_late_join_time( "sv_vote_late_join_time", "90", FCVAR_NONE, "Grace period after the match starts before players who join the match receive a vote-creation cooldown" );
ConVar sv_vote_late_join_cooldown( "sv_vote_late_join_cooldown", "300", FCVAR_NONE, "Length of the vote-creation cooldown when joining the server after the grace period has expired" );
extern ConVar tf_voice_command_suspension_mode;
extern ConVar tf_feign_death_duration;
extern ConVar spec_freeze_time;
extern ConVar spec_freeze_traveltime;
@ -997,7 +997,6 @@ CTFPlayer::CTFPlayer()
m_flNextChangeClassTime = 0.0f;
m_flNextChangeTeamTime = 0.0f;
m_bScattergunJump = false;
m_iOldStunFlags = 0;
m_iLastWeaponSlot = 1;
m_iNumberofDominations = 0;
@ -1453,35 +1452,6 @@ void CTFPlayer::TFPlayerThink()
else
{
m_iLeftGroundHealth = -1;
if ( GetFlags() & FL_ONGROUND )
{
// Airborne conditions end on ground contact
m_Shared.RemoveCond( TF_COND_KNOCKED_INTO_AIR );
m_Shared.RemoveCond( TF_COND_AIR_CURRENT );
if ( m_Shared.InCond( TF_COND_ROCKETPACK ) )
{
// Make sure we're still not dealing with launch, where it's possible
// to hit your head and fall to the ground before the second stage.
CTFWeaponBase *pRocketPack = Weapon_OwnsThisID( TF_WEAPON_ROCKETPACK );
if ( pRocketPack )
{
if ( gpGlobals->curtime > ( static_cast< CTFRocketPack* >( pRocketPack )->GetRefireTime() ) )
{
EmitSound( "Weapon_RocketPack.BoostersShutdown" );
EmitSound( "Weapon_RocketPack.Land" );
m_Shared.RemoveCond( TF_COND_ROCKETPACK );
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_landed" );
if ( pEvent )
{
pEvent->SetInt( "userid", GetUserID() );
gameeventmanager->FireEvent( pEvent );
}
}
}
}
}
if ( m_iBlastJumpState )
{
@ -2833,6 +2803,7 @@ void CTFPlayer::PrecacheMvM()
PrecacheScriptSound( "MVM.DeployBombGiant" );
PrecacheScriptSound( "Weapon_Upgrade.ExplosiveHeadshot" );
PrecacheScriptSound( "Spy.MVM_Chuckle" );
PrecacheScriptSound( "Spy.MVM_TeaseVictim" );
PrecacheScriptSound( "MVM.Robot_Engineer_Spawn" );
PrecacheScriptSound( "MVM.Robot_Teleporter_Deliver" );
PrecacheScriptSound( "MVM.MoneyPickup" );
@ -3781,7 +3752,6 @@ void CTFPlayer::Spawn()
m_Shared.SetFeignDeathReady( false );
m_bScattergunJump = false;
m_iOldStunFlags = 0;
m_flAccumulatedHealthRegen = 0;
@ -9127,44 +9097,40 @@ int CTFPlayer::OnTakeDamage( const CTakeDamageInfo &inputInfo )
}
}
if ( pTFAttacker && pTFAttacker->IsPlayerClass( TF_CLASS_MEDIC ) )
if ( pTFAttacker && pTFAttacker->IsPlayerClass( TF_CLASS_MEDIC ) && pWeapon && pWeapon->GetWeaponID() == TF_WEAPON_BONESAW )
{
CTFWeaponBase *pAttackerWeapon = pTFAttacker->GetActiveTFWeapon();
if ( pAttackerWeapon && pAttackerWeapon->GetWeaponID() == TF_WEAPON_BONESAW )
CTFBonesaw *pBoneSaw = static_cast< CTFBonesaw* >( pWeapon );
if ( pBoneSaw->GetBonesawType() == BONESAW_UBER_SAVEDONDEATH )
{
CTFBonesaw *pBoneSaw = static_cast< CTFBonesaw* >( pAttackerWeapon );
if ( pBoneSaw->GetBonesawType() == BONESAW_UBER_SAVEDONDEATH )
// Spawn their spleen
CPhysicsProp *pRandomInternalOrgan = dynamic_cast< CPhysicsProp* >( CreateEntityByName( "prop_physics_override" ) );
if ( pRandomInternalOrgan )
{
// Spawn their spleen
CPhysicsProp *pRandomInternalOrgan = dynamic_cast< CPhysicsProp* >( CreateEntityByName( "prop_physics_override" ) );
if ( pRandomInternalOrgan )
{
pRandomInternalOrgan->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
pRandomInternalOrgan->AddFlag( FL_GRENADE );
char buf[512];
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
pRandomInternalOrgan->KeyValue( "origin", buf );
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsAngles().x, GetAbsAngles().y, GetAbsAngles().z );
pRandomInternalOrgan->KeyValue( "angles", buf );
pRandomInternalOrgan->KeyValue( "model", "models/player/gibs/random_organ.mdl" );
pRandomInternalOrgan->KeyValue( "fademindist", "-1" );
pRandomInternalOrgan->KeyValue( "fademaxdist", "0" );
pRandomInternalOrgan->KeyValue( "fadescale", "1" );
pRandomInternalOrgan->KeyValue( "inertiaScale", "1.0" );
pRandomInternalOrgan->KeyValue( "physdamagescale", "0.1" );
DispatchSpawn( pRandomInternalOrgan );
pRandomInternalOrgan->m_takedamage = DAMAGE_YES; // Take damage, otherwise this can block trains
pRandomInternalOrgan->SetHealth( 100 );
pRandomInternalOrgan->Activate();
pRandomInternalOrgan->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
pRandomInternalOrgan->AddFlag( FL_GRENADE );
char buf[512];
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z );
pRandomInternalOrgan->KeyValue( "origin", buf );
Q_snprintf( buf, sizeof( buf ), "%.10f %.10f %.10f", GetAbsAngles().x, GetAbsAngles().y, GetAbsAngles().z );
pRandomInternalOrgan->KeyValue( "angles", buf );
pRandomInternalOrgan->KeyValue( "model", "models/player/gibs/random_organ.mdl" );
pRandomInternalOrgan->KeyValue( "fademindist", "-1" );
pRandomInternalOrgan->KeyValue( "fademaxdist", "0" );
pRandomInternalOrgan->KeyValue( "fadescale", "1" );
pRandomInternalOrgan->KeyValue( "inertiaScale", "1.0" );
pRandomInternalOrgan->KeyValue( "physdamagescale", "0.1" );
DispatchSpawn( pRandomInternalOrgan );
pRandomInternalOrgan->m_takedamage = DAMAGE_YES; // Take damage, otherwise this can block trains
pRandomInternalOrgan->SetHealth( 100 );
pRandomInternalOrgan->Activate();
Vector vecImpulse = RandomVector( -1.f, 1.f );
vecImpulse.z = 1.f;
VectorNormalize( vecImpulse );
Vector vecVelocity = vecImpulse * 250.0;
pRandomInternalOrgan->ApplyAbsVelocityImpulse( vecVelocity );
Vector vecImpulse = RandomVector( -1.f, 1.f );
vecImpulse.z = 1.f;
VectorNormalize( vecImpulse );
Vector vecVelocity = vecImpulse * 250.0;
pRandomInternalOrgan->ApplyAbsVelocityImpulse( vecVelocity );
pRandomInternalOrgan->ThinkSet( &CBaseEntity::SUB_Remove, gpGlobals->curtime + 5.f, "DieContext" );
}
pRandomInternalOrgan->ThinkSet( &CBaseEntity::SUB_Remove, gpGlobals->curtime + 5.f, "DieContext" );
}
}
}
@ -20028,7 +19994,20 @@ bool CTFPlayer::ShouldShowVoiceSubtitleToEnemy( void )
//-----------------------------------------------------------------------------
bool CTFPlayer::CanSpeakVoiceCommand( void )
{
return ( gpGlobals->curtime > m_flNextVoiceCommandTime );
if ( tf_voice_command_suspension_mode.GetInt() == 1 )
return false;
if ( gpGlobals->curtime <= m_flNextVoiceCommandTime )
return false;
// misyl: New F2P voice command rate-limiting path.
if ( BHaveChatSuspensionInCurrentMatch() && tf_voice_command_suspension_mode.GetInt() == 2 )
{
if ( !m_RateLimitedVoiceCommandTokenBucket.BTakeToken( gpGlobals->curtime ) )
return false;
}
return true;
}
//-----------------------------------------------------------------------------

View File

@ -66,6 +66,46 @@ enum EAmmoSource
kAmmoSource_ResourceMeter, // it regenerated after a cooldown
};
extern ConVar tf_voice_command_suspension_rate_limit_bucket_count;
extern ConVar tf_voice_command_suspension_rate_limit_bucket_refill_rate;
class CVoiceCommandBucketSizer
{
public:
int GetBucketSize() const { return tf_voice_command_suspension_rate_limit_bucket_count.GetInt(); }
float GetBucketRefillRate() const { return tf_voice_command_suspension_rate_limit_bucket_refill_rate.GetFloat(); }
};
template <typename TBucketSizer>
class CRateLimitingTokenBucket : public TBucketSizer
{
public:
CRateLimitingTokenBucket()
: m_nBucket( this->GetBucketSize() )
{
}
bool BTakeToken( float flNow )
{
// misyl: This token bucket doesn't go negative, so you don't ever dig yourself into a hole by spamming.
// You might want that if you use this class, feel free to add something to the BucketSizer.
int nNewBucket = MIN( m_nBucket + ( flNow - m_flLastTokenTaken ) / this->GetBucketRefillRate(), this->GetBucketSize() ) - 1;
if ( nNewBucket <= 0 )
{
return false;
}
m_nBucket = nNewBucket;
m_flLastTokenTaken = flNow;
return true;
}
private:
float m_flLastTokenTaken = 0.0f;
int m_nBucket = 0;
};
//=============================================================================
//
// TF Player
@ -483,6 +523,8 @@ public:
float m_flNextVoiceCommandTime;
int m_iVoiceSpamCounter;
CRateLimitingTokenBucket<CVoiceCommandBucketSizer> m_RateLimitedVoiceCommandTokenBucket;
float m_flNextSpeakWeaponFire;
virtual int CalculateTeamBalanceScore( void );
@ -938,7 +980,6 @@ public:
bool m_bSuicideExplode;
bool m_bScattergunJump;
int m_iOldStunFlags;
bool m_bFlipViewModels;

View File

@ -801,7 +801,7 @@ void CAchievementMgr::LoadGlobalState()
// HPE_END
//=============================================================================
KeyValues *pKV = new KeyValues("GameState" );
KeyValuesAD pKV("GameState" );
if ( pKV->LoadFromFile( filesystem, szFilename, "MOD" ) )
{
KeyValues *pNode = pKV->GetFirstSubKey();

View File

@ -2607,7 +2607,7 @@ void UTIL_LoadActivityRemapFile( const char *filename, const char *section, CUtl
return;
}
KeyValues *pkvFile = new KeyValues( section );
KeyValuesAD pkvFile( section );
if ( pkvFile->LoadFromFile( filesystem, filename, NULL ) )
{

View File

@ -54,8 +54,6 @@ BEGIN_DATADESC( CBaseGrenade )
END_DATADESC()
void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID);
#endif
IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenade, DT_BaseGrenade )
@ -70,7 +68,7 @@ BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade )
SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ),
// HACK: Use same flag bits as player for now
SendPropInt ( SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED, SendProxy_CropFlagsToPlayerFlagBitsLength ),
SendPropInt ( SENDINFO(m_fFlags), 0, SPROP_UNSIGNED ),
#else
RecvPropFloat( RECVINFO( m_flDamage ) ),
RecvPropFloat( RECVINFO( m_DmgRadius ) ),

View File

@ -177,10 +177,14 @@ void CEconItemSystem::ReloadWhitelist( void )
// If we didn't find a file, we're done.
if ( !bFoundWhitelist )
{
pWhitelistKV->deleteThis();
return;
}
// Otherwise, go through the KVs and turn on the matching items.
Msg("Parsing item whitelist (default: %s)\n", bDefault ? "allowed" : "disallowed" );
KeyValues* ownerWhitelistKV = pWhitelistKV;
pWhitelistKV = pWhitelistKV->GetFirstSubKey();
while ( pWhitelistKV )
{
@ -204,6 +208,8 @@ void CEconItemSystem::ReloadWhitelist( void )
pWhitelistKV = pWhitelistKV->GetNextKey();
}
Msg("Finished.\n");
ownerWhitelistKV->deleteThis();
}
#ifdef GAME_DLL

View File

@ -11,6 +11,7 @@
#ifdef CLIENT_DLL
#include "c_hl2mp_player.h"
#include <prediction.h>
#else
#include "hl2mp_player.h"
#endif
@ -133,16 +134,18 @@ void CWeapon357::PrimaryAttack( void )
// Fire the bullets, and force the first shot to be perfectly accuracy
pPlayer->FireBullets( info );
#ifdef CLIENT_DLL
//Disorient the player
QAngle angles = pPlayer->GetLocalAngles();
angles.x += random->RandomInt( -1, 1 );
angles.y += random->RandomInt( -1, 1 );
angles.z = 0;
#ifndef CLIENT_DLL
pPlayer->SnapEyeAngles( angles );
#endif
if ( prediction->IsFirstTimePredicted() )
{
QAngle angles;
engine->GetViewAngles( angles );
angles.x += random->RandomInt( -1, 1 );
angles.y += random->RandomInt( -1, 1 );
angles.z += 0.0f;
engine->SetViewAngles( angles );
}
#endif // CLIENT_DLL
pPlayer->ViewPunch( QAngle( -8, random->RandomFloat( -2, 2 ), 0 ) );

View File

@ -186,7 +186,7 @@ void ParseParticleEffectsMap( const char *pMapName, bool bLoadSheets )
V_snprintf( szMapManifestFilename, sizeof( szMapManifestFilename ), "maps/%s_particles.txt", pMapName );
}
KeyValues *manifest = new KeyValues( szMapManifestFilename );
KeyValuesAD manifest( szMapManifestFilename );
// In order:
// - particles.txt within the map BSP

View File

@ -325,6 +325,7 @@ void CSave::Log( const char *pName, fieldtype_t fieldType, void *value, int coun
char chValue = pValue[iCount];
Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%c", chValue );
Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
break;
}
case FIELD_COLOR32:
{
@ -332,6 +333,7 @@ void CSave::Log( const char *pName, fieldtype_t fieldType, void *value, int coun
byte *pColor = &pValue[iCount*4];
Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%d %d %d %d)", ( int )pColor[0], ( int )pColor[1], ( int )pColor[2], ( int )pColor[3] );
Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS );
break;
}
case FIELD_EMBEDDED:
case FIELD_CUSTOM:

View File

@ -53,7 +53,7 @@ ConVar tf_max_charge_speed( "tf_max_charge_speed", "750", FCVAR_NOTIFY | FCVAR_R
ConVar tf_parachute_gravity( "tf_parachute_gravity", "0.2f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Gravity while parachute is deployed" );
ConVar tf_parachute_maxspeed_xy( "tf_parachute_maxspeed_xy", "300.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max XY Speed while Parachute is deployed" );
ConVar tf_parachute_maxspeed_z( "tf_parachute_maxspeed_z", "-100.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max Z Speed while Parachute is deployed" );
ConVar tf_parachute_maxspeed_onfire_z( "tf_parachute_maxspeed_onfire_z", "10.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max Z Speed when on Fire and Parachute is deployed" );
ConVar tf_parachute_maxspeed_onfire_z( "tf_parachute_maxspeed_onfire_z", "-100.0f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Max Z Speed when on Fire and Parachute is deployed" );
ConVar tf_parachute_aircontrol( "tf_parachute_aircontrol", "2.5f", FCVAR_DEVELOPMENTONLY | FCVAR_REPLICATED, "Multiplier for how much air control players have when Parachute is deployed" );
ConVar tf_parachute_deploy_toggle_allowed( "tf_parachute_deploy_toggle_allowed", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY );
@ -1115,12 +1115,6 @@ void CTFGameMovement::PreventBunnyJumping()
//-----------------------------------------------------------------------------
void CTFGameMovement::ToggleParachute()
{
if ( ( m_pTFPlayer->GetFlags() & FL_ONGROUND ) )
{
m_pTFPlayer->m_Shared.RemoveCond( TF_COND_PARACHUTE_DEPLOYED );
return;
}
if ( mv->m_nOldButtons & IN_JUMP )
return;
@ -1147,9 +1141,10 @@ void CTFGameMovement::ToggleParachute()
}
else
{
bool bOnGround = ( m_pTFPlayer->GetFlags() & FL_ONGROUND );
int iParachuteDisabled = 0;
CALL_ATTRIB_HOOK_INT_ON_OTHER( m_pTFPlayer, iParachuteDisabled, parachute_disabled );
if ( !iParachuteDisabled && ( tf_parachute_deploy_toggle_allowed.GetBool() || !m_pTFPlayer->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) )
if ( !bOnGround && !iParachuteDisabled && ( tf_parachute_deploy_toggle_allowed.GetBool() || !m_pTFPlayer->m_Shared.InCond( TF_COND_PARACHUTE_DEPLOYED ) ) )
{
m_pTFPlayer->m_Shared.AddCond( TF_COND_PARACHUTE_ACTIVE );
m_pTFPlayer->m_Shared.AddCond( TF_COND_PARACHUTE_DEPLOYED );
@ -1381,7 +1376,7 @@ int CTFGameMovement::CheckStuck( void )
m_pTFPlayer->GetTeam()->GetName(),
m_pTFPlayer->GetAbsOrigin().x, m_pTFPlayer->GetAbsOrigin().y, m_pTFPlayer->GetAbsOrigin().z );
m_pTFPlayer->TakeDamage( CTakeDamageInfo( m_pTFPlayer, m_pTFPlayer, vec3_origin, m_pTFPlayer->WorldSpaceCenter(), 999999.9f, DMG_CRUSH ) );
m_pTFPlayer->CommitSuicide( false, true );
}
else
{
@ -2629,8 +2624,8 @@ void CTFGameMovement::FullWalkMove()
{
if ( m_pTFPlayer->m_Shared.InCond( TF_COND_PARACHUTE_ACTIVE ) && mv->m_vecVelocity[2] < 0 )
{
mv->m_vecVelocity[2] = Max( mv->m_vecVelocity[2], tf_parachute_maxspeed_z.GetFloat() );
mv->m_vecVelocity[2] = Max( mv->m_vecVelocity[2], m_pTFPlayer->m_Shared.InCond( TF_COND_BURNING ) ? tf_parachute_maxspeed_onfire_z.GetFloat() : tf_parachute_maxspeed_z.GetFloat() );
float flDrag = tf_parachute_maxspeed_xy.GetFloat();
// Instead of clamping, we'll dampen
float flSpeedX = abs( mv->m_vecVelocity[0] );
@ -2956,9 +2951,9 @@ void CTFGameMovement::SetGroundEntity( trace_t *pm )
{
m_pTFPlayer->SpeakConceptIfAllowed( MP_CONCEPT_DOUBLE_JUMP, "started_jumping:0" );
}
m_pTFPlayer->m_Shared.SetWeaponKnockbackID( -1 );
m_pTFPlayer->m_bScattergunJump = false;
#endif // GAME_DLL
m_pTFPlayer->m_Shared.SetWeaponKnockbackID( -1 );
m_pTFPlayer->m_Shared.m_bScattergunJump = false;
m_pTFPlayer->m_Shared.SetAirDash( 0 );
m_pTFPlayer->m_Shared.SetAirDucked( 0 );

View File

@ -875,6 +875,7 @@ ConVar tf_raid_allow_overtime( "tf_raid_allow_overtime", "0"/*, FCVAR_CHEAT*/ );
ConVar tf_mvm_defenders_team_size( "tf_mvm_defenders_team_size", "6", FCVAR_REPLICATED | FCVAR_NOTIFY, "Maximum number of defenders in MvM" );
ConVar tf_mvm_max_connected_players( "tf_mvm_max_connected_players", "10", FCVAR_GAMEDLL, "Maximum number of connected real players in MvM" );
ConVar tf_mvm_max_invaders( "tf_mvm_max_invaders", "22", FCVAR_GAMEDLL, "Maximum number of invaders in MvM" );
ConVar tf_mvm_min_players_to_start( "tf_mvm_min_players_to_start", "3", FCVAR_REPLICATED | FCVAR_NOTIFY, "Minimum number of players connected to start a countdown timer" );
ConVar tf_mvm_respec_enabled( "tf_mvm_respec_enabled", "1", FCVAR_CHEAT | FCVAR_REPLICATED, "Allow players to refund credits spent on player and item upgrades." );
@ -1106,7 +1107,13 @@ ConVar tf_competitive_required_late_join_confirm_timeout( "tf_competitive_requir
ConVar tf_gamemode_community ( "tf_gamemode_community", "0", FCVAR_REPLICATED | FCVAR_NOTIFY | FCVAR_DEVELOPMENTONLY );
ConVar tf_voice_command_suspension_mode( "tf_voice_command_suspension_mode", "2", FCVAR_REPLICATED, "0 = None | 1 = No Voice Commands | 2 = Rate Limited" );
#ifdef GAME_DLL
ConVar tf_voice_command_suspension_rate_limit_bucket_count( "tf_voice_command_suspension_rate_limit_bucket_count", "5" ); // Bucket size of 5.
ConVar tf_voice_command_suspension_rate_limit_bucket_refill_rate( "tf_voice_command_suspension_rate_limit_bucket_refill_rate", "6" ); // 6s
void cc_powerup_mode( IConVar *pConVar, const char *pOldString, float flOldValue )
{
ConVarRef var( pConVar );
@ -10126,7 +10133,12 @@ VoiceCommandMenuItem_t *CTFGameRules::VoiceCommand( CBaseMultiplayerPlayer *pPla
if ( pTFPlayer )
{
if ( pTFPlayer->BHaveChatSuspensionInCurrentMatch() )
return NULL;
{
if ( tf_voice_command_suspension_mode.GetInt() == 1 )
{
return NULL;
}
}
if ( pTFPlayer->m_Shared.InCond( TF_COND_HALLOWEEN_GHOST_MODE ) )
{
@ -16966,7 +16978,7 @@ int CTFGameRules::CalcPlayerScore( RoundStats_t *pRoundStats, CTFPlayer *pPlayer
( pRoundStats->m_iStat[TFSTAT_TELEPORTS] / TF_SCORE_TELEPORTS_PER_POINT ) +
( pRoundStats->m_iStat[TFSTAT_INVULNS] / TF_SCORE_INVULN ) +
( pRoundStats->m_iStat[TFSTAT_REVENGE] / TF_SCORE_REVENGE ) +
( pRoundStats->m_iStat[TFSTAT_BONUS_POINTS] / TF_SCORE_BONUS_POINT_DIVISOR );
( pRoundStats->m_iStat[TFSTAT_BONUS_POINTS] / TF_SCORE_BONUS_POINT_DIVISOR ) +
( pRoundStats->m_iStat[TFSTAT_CURRENCY_COLLECTED] / TF_SCORE_CURRENCY_COLLECTED );
if ( pPlayer )

View File

@ -97,6 +97,7 @@ class CMannVsMachineUpgrades;
//extern ConVar tf_populator_damage_multiplier;
extern ConVar tf_mvm_defenders_team_size;
extern ConVar tf_mvm_max_invaders;
const int kLadder_TeamSize_6v6 = 6;
const int kLadder_TeamSize_9v9 = 9;

View File

@ -279,7 +279,7 @@ void CTFPowerupBottle::ReapplyProvision( void )
// Refill weapon clips
for ( int i = 0; i < MAX_WEAPONS; i++ )
{
CBaseCombatWeapon *pWeapon = pTFPlayer->GetWeapon(i);
CTFWeaponBase *pWeapon = dynamic_cast<CTFWeaponBase *>( pTFPlayer->GetWeapon( i ) );
if ( !pWeapon )
continue;
@ -287,7 +287,8 @@ void CTFPowerupBottle::ReapplyProvision( void )
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
{
if ( ( pWeapon->UsesPrimaryAmmo() && !pWeapon->HasPrimaryAmmo() ) ||
( pWeapon->UsesSecondaryAmmo() && !pWeapon->HasSecondaryAmmo() ) )
( pWeapon->UsesSecondaryAmmo() && !pWeapon->HasSecondaryAmmo() ) ||
( pWeapon->IsEnergyWeapon() && !pWeapon->Energy_HasEnergy() ) )
{
pTFPlayer->AwardAchievement( ACHIEVEMENT_TF_MVM_USE_AMMO_BOTTLE );
}
@ -297,7 +298,7 @@ void CTFPowerupBottle::ReapplyProvision( void )
if ( iShareBottle && pHealTarget )
{
CBaseCombatWeapon *pPatientWeapon = pHealTarget->GetWeapon(i);
CTFWeaponBase *pPatientWeapon = dynamic_cast<CTFWeaponBase *>( pHealTarget->GetWeapon( i ) );
if ( !pPatientWeapon )
continue;

View File

@ -31,6 +31,7 @@
#include "tf_mapinfo.h"
#include "tf_dropped_weapon.h"
#include "tf_weapon_passtime_gun.h"
#include "tf_weapon_rocketpack.h"
#include <functional>
// Client specific.
@ -471,7 +472,10 @@ BEGIN_PREDICTION_DATA_NO_BASE( CTFPlayerShared )
DEFINE_PRED_FIELD( m_bHasPasstimeBall, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_bIsTargetedForPasstimePass, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), // does this belong here?
DEFINE_PRED_FIELD( m_askForBallTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flHolsterAnimTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_ARRAY( m_flItemChargeMeter, FIELD_FLOAT, LAST_LOADOUT_SLOT_WITH_CHARGE_METER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_iStunIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_bScattergunJump, FIELD_BOOLEAN, 0 ),
END_PREDICTION_DATA()
// Server specific.
@ -784,6 +788,8 @@ CTFPlayerShared::CTFPlayerShared()
m_flPrevInvisibility = 0.f;
m_flTmpDamageBonusAmount = 1.0f;
m_bScattergunJump = false;
m_bFeignDeathReady = false;
m_fCloakConsumeRate = tf_spy_cloak_consume_rate.GetFloat();
@ -1005,7 +1011,6 @@ void CTFPlayerShared::Spawn( void )
SetRevengeCrits( 0 );
m_PlayerStuns.RemoveAll();
m_iStunIndex = -1;
m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_NONE;
m_bHasPasstimeBall = false;
@ -1014,6 +1019,7 @@ void CTFPlayerShared::Spawn( void )
#else
m_bSyncingConditions = false;
#endif
m_iStunIndex = -1;
m_bKingRuneBuffActive = false;
// Reset our assist here incase something happens before we get killed
@ -3090,9 +3096,46 @@ void CTFPlayerShared::ConditionThink( void )
VehicleThink();
if ( m_pOuter->GetFlags() & FL_ONGROUND && InCond( TF_COND_PARACHUTE_ACTIVE ) )
if ( m_pOuter->GetFlags() & FL_ONGROUND )
{
// Airborne conditions end on ground contact
RemoveCond( TF_COND_KNOCKED_INTO_AIR );
RemoveCond( TF_COND_AIR_CURRENT );
RemoveCond( TF_COND_PARACHUTE_ACTIVE );
RemoveCond( TF_COND_PARACHUTE_DEPLOYED );
if ( InCond( TF_COND_ROCKETPACK ) )
{
// Make sure we're still not dealing with launch, where it's possible
// to hit your head and fall to the ground before the second stage.
CTFWeaponBase *pRocketPack = m_pOuter->Weapon_OwnsThisID( TF_WEAPON_ROCKETPACK );
if ( pRocketPack )
{
if ( gpGlobals->curtime > ( static_cast< CTFRocketPack* >( pRocketPack )->GetRefireTime() ) )
{
#ifdef CLIENT_DLL
if ( prediction->IsFirstTimePredicted() )
#endif
{
CPASAttenuationFilter filter( m_pOuter );
filter.UsePredictionRules();
m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Weapon_RocketPack.BoostersShutdown" );
m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Weapon_RocketPack.Land" );
}
RemoveCond( TF_COND_ROCKETPACK );
#ifdef GAME_DLL
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_landed" );
if ( pEvent )
{
pEvent->SetInt( "userid", m_pOuter->GetUserID() );
gameeventmanager->FireEvent( pEvent );
}
#endif
}
}
}
}
// See if we should be pulsing our radius heal
@ -7301,6 +7344,8 @@ void CTFPlayerShared::OnRemoveStunned( void )
m_iStunFlags = 0;
m_hStunner = NULL;
m_iStunIndex = -1;
#ifdef CLIENT_DLL
if ( m_pOuter->m_pStunnedEffect )
{
@ -7310,7 +7355,6 @@ void CTFPlayerShared::OnRemoveStunned( void )
m_pOuter->m_pStunnedEffect = NULL;
}
#else
m_iStunIndex = -1;
m_PlayerStuns.RemoveAll();
#endif
@ -9624,15 +9668,16 @@ bool CTFPlayerShared::AddToSpyCloakMeter( float val, bool bForce )
#endif
#ifdef GAME_DLL
//-----------------------------------------------------------------------------
// Purpose: Stun & Snare Application
//-----------------------------------------------------------------------------
void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iStunFlags, CTFPlayer* pAttacker )
{
#ifdef GAME_DLL
// Insanity prevention
if ( ( m_PlayerStuns.Count() + 1 ) >= 250 )
return;
#endif
if ( InCond( TF_COND_PHASE ) || InCond( TF_COND_PASSTIME_INTERCEPTION ) )
return;
@ -9643,15 +9688,19 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
if ( InCond( TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED ) && !InCond( TF_COND_MVM_BOT_STUN_RADIOWAVE ) )
return;
#ifdef GAME_DLL
if ( pAttacker && TFGameRules() && TFGameRules()->IsTruceActive() && pAttacker->IsTruceValidForEnt() )
{
if ( ( pAttacker->GetTeamNumber() == TF_TEAM_RED ) || ( pAttacker->GetTeamNumber() == TF_TEAM_BLUE ) )
return;
}
#endif
float flRemapAmount = RemapValClamped( flReductionAmount, 0.0, 1.0, 0, 255 );
#ifdef GAME_DLL
int iOldStunFlags = GetStunFlags();
#endif
// Already stunned
bool bStomp = false;
@ -9674,10 +9723,13 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
}
else if ( GetActiveStunInfo() )
{
#ifdef GAME_DLL
// Something yanked our TF_COND_STUNNED in an unexpected way
if ( !HushAsserts() )
Assert( !"Something yanked out TF_COND_STUNNED." );
m_PlayerStuns.RemoveAll();
#endif
m_iStunIndex = -1;
return;
}
@ -9699,7 +9751,16 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
// This can happen when stuns use TF_STUN_CONTROLS or TF_STUN_LOSER_STATE.
float flOldStun = GetActiveStunInfo() ? GetActiveStunInfo()->flStunAmount : 0.f;
#ifdef GAME_DLL
m_iStunIndex = m_PlayerStuns.AddToTail( stunEvent );
#else
m_iStunIndex = 0;
if ( prediction->IsFirstTimePredicted() )
{
m_ActiveStunInfo = stunEvent;
}
#endif
if ( flOldStun > flRemapAmount )
{
@ -9709,10 +9770,18 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
else
{
// Done for now
#ifdef GAME_DLL
m_PlayerStuns.AddToTail( stunEvent );
#else
if ( prediction->IsFirstTimePredicted() )
{
m_ActiveStunInfo = stunEvent;
}
#endif
return;
}
#ifdef GAME_DLL
// Add in extra time when TF_STUN_CONTROLS
if ( GetActiveStunInfo()->iStunFlags & TF_STUN_CONTROLS )
{
@ -9766,10 +9835,10 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt
m_pOuter->ClearExpression();
m_pOuter->ClearWeaponFireScene();
}
#endif
AddCond( TF_COND_STUNNED, -1.f, pAttacker );
}
#endif // GAME_DLL
//-----------------------------------------------------------------------------
// Purpose: Returns the intensity of the current stun effect, if we have the type of stun indicated.
@ -12110,6 +12179,13 @@ bool CTFPlayer::CanJump() const
if ( m_Shared.InCond( TF_COND_TAUNTING ) )
return false;
CTFWeaponBase *pActiveWeapon = m_Shared.GetActiveTFWeapon();
if ( pActiveWeapon )
{
if ( !pActiveWeapon->OwnerCanJump() )
return false;
}
int iNoJump = 0;
CALL_ATTRIB_HOOK_INT( iNoJump, no_jump );

View File

@ -560,9 +560,7 @@ public:
// Stuns
stun_struct_t *GetActiveStunInfo( void ) const;
#ifdef GAME_DLL
void StunPlayer( float flTime, float flReductionAmount, int iStunFlags = TF_STUN_MOVEMENT, CTFPlayer* pAttacker = NULL );
#endif // GAME_DLL
float GetAmountStunned( int iStunFlags );
bool IsLoserStateStunned( void ) const;
bool IsControlStunned( void );
@ -1218,6 +1216,8 @@ private:
#endif
public:
bool m_bScattergunJump;
float m_flStunFade;
float m_flStunEnd;
float m_flStunMid;

View File

@ -1144,7 +1144,7 @@ protected:
int nNumJumps = pNonConstPlayer->GetGroundEntity() == NULL ? 1 : 0;
nNumJumps += pPlayer->m_Shared.GetAirDash();
nNumJumps += pPlayer->m_bScattergunJump;
nNumJumps += pPlayer->m_Shared.m_bScattergunJump;
if ( m_eJumpingState == JUMPING_STATE_IS_NOT_JUMPING )
{
@ -3027,7 +3027,7 @@ bool CTFJumpStateQuestModifier::BPassesModifier( const CTFPlayer *pOwner, Invali
#else
int nNumJumps = const_cast< CTFPlayer* >( pOwner )->GetGroundEntity() == NULL ? 1 : 0;
nNumJumps += pOwner->m_Shared.GetAirDash();
nNumJumps += pOwner->m_bScattergunJump;
nNumJumps += pOwner->m_Shared.m_bScattergunJump;
// If we want them on the ground, make sure they're on the ground
if ( m_nJumpCount == 0 )

View File

@ -654,19 +654,7 @@ void CTFCompoundBow::SetArrowAlight( bool bAlight )
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFCompoundBow::SetInternalChargeBeginTime( float flChargeBeginTime )
bool CTFCompoundBow::OwnerCanJump( void )
{
#ifdef GAME_DLL
float flCurrentChargeBeginTime = GetInternalChargeBeginTime();
if ( flCurrentChargeBeginTime == 0.f && flChargeBeginTime > 0.f )
{
DisableJump();
}
else if ( flCurrentChargeBeginTime > 0.f && flChargeBeginTime == 0.f )
{
EnableJump();
}
#endif // GAME_DLL
BaseClass::SetInternalChargeBeginTime( flChargeBeginTime );
return GetInternalChargeBeginTime() == 0.f;
}

View File

@ -89,8 +89,7 @@ public:
void SetArrowAlight( bool bAlight );
protected:
virtual void SetInternalChargeBeginTime( float flChargeBeginTime ) OVERRIDE;
bool OwnerCanJump( void );
private:
#ifdef CLIENT_DLL

View File

@ -2110,7 +2110,7 @@ bool CTFFlameThrower::EffectMeterShouldFlash( void )
//-----------------------------------------------------------------------------
Vector CTFFlameThrower::GetMuzzlePosHelper( bool bVisualPos )
{
Vector vecMuzzlePos;
Vector vecMuzzlePos = vec3_origin;
CTFPlayer *pOwner = GetTFPlayerOwner();
if ( pOwner )
{

View File

@ -13,6 +13,7 @@
#ifdef CLIENT_DLL
#include "c_tf_player.h"
#include "c_rope.h"
#include "prediction.h"
// Server specific.
#else
#include "tf_player.h"
@ -47,7 +48,10 @@ END_NETWORK_TABLE()
#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CTFRocketPack )
DEFINE_PRED_FIELD( m_flInitLaunchTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flLaunchTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flToggleEndTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_flRefireTime, FIELD_FLOAT, 0 ),
DEFINE_PRED_FIELD( m_bLaunchedFromGround, FIELD_BOOLEAN, 0 ),
END_PREDICTION_DATA()
#endif // CLIENT_DLL
@ -211,10 +215,13 @@ bool CTFRocketPack::InitiateLaunch( void )
CTFPlayer *pOwner = GetTFPlayerOwner();
if ( !pOwner->m_Shared.IsRocketPackReady() )
{
#ifdef GAME_DLL
CPVSFilter filter( WorldSpaceCenter() );
pOwner->EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersNotReady" );
#endif // GAME_DLL
// note: this is never reached
#ifdef CLIENT_DLL
if ( prediction->IsFirstTimePredicted() )
{
pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" );
}
#endif
return false;
}
@ -224,16 +231,18 @@ bool CTFRocketPack::InitiateLaunch( void )
return false;
}
#ifdef GAME_DLL
if ( pOwner->m_Shared.IsLoser() )
#ifdef CLIENT_DLL
if ( prediction->IsFirstTimePredicted() )
#endif
{
pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" );
CPASAttenuationFilter filter( pOwner );
filter.UsePredictionRules();
pOwner->EmitSound(
filter,
entindex(),
pOwner->m_Shared.IsLoser() ? "Weapon_RocketPack.BoostersNotReady" : "Weapon_RocketPack.BoostersCharge"
);
}
else
{
pOwner->EmitSound( "Weapon_RocketPack.BoostersCharge" );
}
#endif // GAME_DLL
m_flInitLaunchTime = gpGlobals->curtime;
@ -369,7 +378,6 @@ bool CTFRocketPack::ShouldDraw()
#endif // CLIENT_DLL
#ifdef GAME_DLL
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -384,7 +392,7 @@ Vector CTFRocketPack::CalcRocketForceFromPlayer( CTFPlayer *pPlayer )
const float flVertPushScale = ( bOnGround ) ? 0.7f : 0.25f; // Less vertical force while airborne
Vector vecForward, vecRight;
QAngle angAim = ( bOnGround ) ? pPlayer->GetAbsAngles() : pPlayer->EyeAngles();
QAngle angAim = pPlayer->EyeAngles();
AngleVectors( angAim, &vecForward, &vecRight, NULL );
bool bNone = !( pPlayer->m_nButtons & IN_FORWARD ) &&
!( pPlayer->m_nButtons & IN_BACK ) /* &&
@ -468,7 +476,6 @@ void CTFRocketPack::RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecFor
pPlayer->ApplyAbsVelocityImpulse( vecForce );
}
#endif // GAME_DLL
//-----------------------------------------------------------------------------
// Purpose:
@ -482,7 +489,6 @@ bool CTFRocketPack::PreLaunch( void )
pOwner->DoAnimationEvent( PLAYERANIMEVENT_CUSTOM, ACT_MP_ATTACK_STAND_PRIMARYFIRE );
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
#ifdef GAME_DLL
// Negate any fall
Vector vecVel = pOwner->GetAbsVelocity();
if ( vecVel.z < 0.f )
@ -496,14 +502,15 @@ bool CTFRocketPack::PreLaunch( void )
pOwner->ApplyAbsVelocityImpulse( vForward );
pOwner->m_Shared.AddCond( TF_COND_PARACHUTE_ACTIVE );
#ifdef GAME_DLL
const Vector &vecOrigin = pOwner->GetAbsOrigin();
CPVSFilter filter( vecOrigin );
TE_TFParticleEffect( filter, 0.f, "heavy_ring_of_fire", vecOrigin, vec3_angle );
DispatchParticleEffect( "rocketjump_smoke", PATTACH_POINT_FOLLOW, pOwner, "foot_L" );
DispatchParticleEffect( "rocketjump_smoke", PATTACH_POINT_FOLLOW, pOwner, "foot_R" );
#endif // GAME_DLL
m_flLaunchTime = gpGlobals->curtime + tf_rocketpack_launch_delay.GetFloat();
#endif // GAME_DLL
return true;
}
@ -519,16 +526,20 @@ bool CTFRocketPack::Launch( void )
pOwner->StopSound( "Weapon_LooseCannon.Charge" );
#ifdef GAME_DLL
m_flLaunchTime = 0.f;
pOwner->m_Shared.RemoveCond( TF_COND_PARACHUTE_ACTIVE );
#ifdef CLIENT_DLL
Vector m_vecLaunchDir;
#endif
// Launch
m_vecLaunchDir = CalcRocketForceFromPlayer( pOwner );
RocketLaunchPlayer( pOwner, m_vecLaunchDir, false );
#ifdef GAME_DLL
SetContextThink( &CTFRocketPack::PassengerDelayLaunchThink, gpGlobals->curtime + TF_ROCKETPACK_PASSENGER_DELAY_LAUNCH, "PassengerDelayLaunchThink" );
#endif
m_flRefireTime = gpGlobals->curtime + 0.5f;
@ -536,6 +547,7 @@ bool CTFRocketPack::Launch( void )
pOwner->m_Shared.SetRocketPackCharge( pOwner->m_Shared.GetRocketPackCharge() - tf_rocketpack_cost.GetFloat() );
}
#ifdef GAME_DLL
// Knock-back nearby enemies
float flRadius = 150.f;
CUtlVector< CTFPlayer* > vecPushedPlayers;
@ -594,6 +606,7 @@ bool CTFRocketPack::Launch( void )
}
CPASAttenuationFilter filter( pOwner );
filter.UsePredictionRules();
pOwner->EmitSound( filter, pOwner->entindex(), "Weapon_RocketPack.BoostersFire" );
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_launch" );
@ -610,7 +623,12 @@ bool CTFRocketPack::Launch( void )
DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_LA" );
DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_RA" );
}
#endif // GAME_DLL
#else
if ( prediction->IsFirstTimePredicted() )
{
pOwner->EmitSound( "Weapon_RocketPack.BoostersFire" );
}
#endif // CLIENT_DLL
return true;
}
@ -748,7 +766,7 @@ void CTFRocketPack::ItemPostFrame( void )
{
ResetTransition();
#ifdef CLIENT_DLL
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() )
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() )
{
pOwner->EmitSound( "Weapon_RocketPack.BoostersReady" );
}
@ -757,7 +775,7 @@ void CTFRocketPack::ItemPostFrame( void )
else if ( pOwner->m_afButtonPressed & IN_ATTACK2 )
{
#ifdef CLIENT_DLL
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() )
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() )
{
pOwner->EmitSound( "Player.DenyWeaponSelection" );
}
@ -841,14 +859,21 @@ const CEconItemView *CTFRocketPack::GetTauntItem() const
//-----------------------------------------------------------------------------
bool CTFRocketPack::Deploy( void )
{
#ifdef GAME_DLL
CTFPlayer *pOwner = GetTFPlayerOwner();
if ( pOwner )
{
EmitSound( "Weapon_RocketPack.BoostersExtend" );
#ifdef CLIENT_DLL
if ( prediction->IsFirstTimePredicted() )
#endif
{
CPASAttenuationFilter filter( pOwner );
filter.UsePredictionRules();
EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersExtend" );
}
#ifdef GAME_DLL
SetEnabled( true );
#endif
}
#endif // GAME_DLL
return BaseClass::Deploy();
}
@ -861,14 +886,21 @@ void CTFRocketPack::StartHolsterAnim( void )
{
BaseClass::StartHolsterAnim();
#ifdef GAME_DLL
CTFPlayer *pOwner = GetTFPlayerOwner();
if ( pOwner )
{
EmitSound( "Weapon_RocketPack.BoostersRetract" );
#ifdef CLIENT_DLL
if ( prediction->IsFirstTimePredicted() )
#endif
{
CPASAttenuationFilter filter( pOwner );
filter.UsePredictionRules();
EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersRetract" );
}
#ifdef GAME_DLL
SetEnabled( false );
#endif
}
#endif // GAME_DLL
}
@ -890,7 +922,7 @@ void CTFRocketPack::OnResourceMeterFilled()
{
#ifdef CLIENT_DLL
CBasePlayer *pPlayer = GetPlayerOwner();
if ( pPlayer->IsLocalPlayer() )
if ( pPlayer->IsLocalPlayer() && prediction->IsFirstTimePredicted() )
{
pPlayer->EmitSound( "TFPlayer.ReCharged" );
}

View File

@ -71,14 +71,14 @@ private:
bool IsTransitionCompleted( void ) const;
void WaitToLaunch( void );
void RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger );
Vector CalcRocketForceFromPlayer( CTFPlayer *pPlayer );
#ifdef GAME_DLL
void SetEnabled( bool bEnabled );
void PassengerDelayLaunchThink( void );
void RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger );
Vector CalcRocketForceFromPlayer( CTFPlayer *pPlayer );
#else
void CleanupParticles( void );
#endif // GAME_DLL
#endif // CLIENT_DLL
CNetworkVar( float, m_flInitLaunchTime );
CNetworkVar( float, m_flLaunchTime );

View File

@ -316,7 +316,6 @@ extern float AirBurstDamageForce( const Vector &size, float damage, float scale
//-----------------------------------------------------------------------------
void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
{
#ifndef CLIENT_DLL
if ( HasKnockback() )
{
// Perform some knock back.
@ -329,9 +328,9 @@ void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
return;
// Knock the firer back!
if ( !(pOwner->GetFlags() & FL_ONGROUND) && !pPlayer->m_bScattergunJump )
if ( !(pOwner->GetFlags() & FL_ONGROUND) && !pPlayer->m_Shared.m_bScattergunJump )
{
pPlayer->m_bScattergunJump = true;
pPlayer->m_Shared.m_bScattergunJump = true;
pOwner->m_Shared.StunPlayer( 0.3f, 1.f, TF_STUN_MOVEMENT | TF_STUN_MOVEMENT_FORWARD_ONLY );
@ -341,15 +340,15 @@ void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
AngleVectors( pOwner->EyeAngles(), &vecForward );
Vector vecForce = vecForward * -flForce;
EntityMatrix mtxPlayer;
mtxPlayer.InitFromEntity( pOwner );
VMatrix mtxPlayer;
mtxPlayer.SetupMatrixOrgAngles( pOwner->GetAbsOrigin(), pOwner->EyeAngles() );
Vector vecAbsVelocity = pOwner->GetAbsVelocity();
Vector vecAbsVelocityAsPoint = vecAbsVelocity + pOwner->GetAbsOrigin();
Vector vecLocalVelocity = mtxPlayer.WorldToLocal( vecAbsVelocityAsPoint );
Vector vecLocalVelocity = mtxPlayer.VMul4x3Transpose( vecAbsVelocityAsPoint );
vecLocalVelocity.x = -300;
vecAbsVelocityAsPoint = mtxPlayer.LocalToWorld( vecLocalVelocity );
vecAbsVelocityAsPoint = mtxPlayer.VMul4x3( vecLocalVelocity );
vecAbsVelocity = vecAbsVelocityAsPoint - pOwner->GetAbsOrigin();
pOwner->SetAbsVelocity( vecAbsVelocity );
@ -360,7 +359,6 @@ void CTFScatterGun::FireBullet( CTFPlayer *pPlayer )
pOwner->RemoveFlag( FL_ONGROUND );
}
}
#endif
BaseClass::FireBullet( pPlayer );
}

View File

@ -424,6 +424,19 @@ void CTFWeaponBase::Activate( void )
GiveDefaultAmmo();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFWeaponBase::GiveDefaultAmmo( void )
{
BaseClass::GiveDefaultAmmo();
if ( IsEnergyWeapon() )
{
m_flEnergy = Energy_GetMaxEnergy();
}
}
// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------

View File

@ -282,6 +282,7 @@ class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner, public IHasGen
virtual void Spawn();
virtual void Activate( void );
virtual void GiveDefaultAmmo( void );
virtual void Precache();
virtual bool IsPredicted() const { return true; }
virtual void FallInit( void );
@ -335,6 +336,7 @@ class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner, public IHasGen
void EnableDuck();
void DisableDuck();
virtual bool OwnerCanJump( void ) { return true; }
virtual bool OwnerCanTaunt( void ) { return true; }
virtual bool CanBeCritBoosted( void );
bool CanHaveRevengeCrits( void );

View File

@ -7,7 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@ -43,7 +43,7 @@ END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""winres.h""\r\n"
"\0"
END

View File

@ -7,7 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@ -43,7 +43,7 @@ END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""winres.h""\r\n"
"\0"
END

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -155,7 +155,7 @@ float4 main( PS_INPUT i ) : COLOR
if( bFlashlight )
{
float3 worldSpaceNormal;
// Make the unbumped version not so fucking stupid and not need tangentSpaceTranspose you knob.
// Make the unbumped version not need tangentSpaceTranspose
worldSpaceNormal = mul( normal, i.tangentSpaceTranspose );
int nShadowSampleLevel = 0;

View File

@ -121,7 +121,7 @@
#define FL_INWATER (1<<9) // In water
// NOTE if you move things up, make sure to change this value
#define PLAYER_FLAG_BITS 10
#define PLAYER_FLAG_BITS 32
#define FL_FLY (1<<10) // Changes the SV_Movestep() behavior to not need to be on ground
#define FL_SWIM (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)
@ -163,7 +163,7 @@
#define FL_INWATER (1<<10) // In water
// NOTE if you move things up, make sure to change this value
#define PLAYER_FLAG_BITS 11
#define PLAYER_FLAG_BITS 32
#define FL_FLY (1<<11) // Changes the SV_Movestep() behavior to not need to be on ground
#define FL_SWIM (1<<12) // Changes the SV_Movestep() behavior to not need to be on ground (but stay in water)

View File

@ -101,6 +101,7 @@ public:
virtual ~CProtoBufMsgBase();
bool BIsInitialized() const;
bool InitFromPacket( IMsgNetPacket * pNetPacket );
bool BAsyncSend( IProtoBufSendHandler & pSender ) const;
bool BAsyncSendWithPreSerializedBody( IProtoBufSendHandler & pSender, const byte *pubBody, uint32 cubBody ) const;

View File

@ -41,7 +41,11 @@ protected:
virtual void PerformLayout();
virtual void Paint();
MESSAGE_FUNC( OnMenuClose, "MenuClose" );
MESSAGE_FUNC_INT( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel);
#ifdef PLATFORM_64BITS
MESSAGE_FUNC_PTR( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel );
#else
MESSAGE_FUNC_INT( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel );
#endif
private:
CUtlVector<MenuButton *> m_pMenuButtons;

View File

@ -347,6 +347,8 @@ public:
bool IsRightAligned(); // returns true if the settings are aligned to the right of the screen
bool IsBottomAligned(); // returns true if the settings are aligned to the bottom of the screen
virtual bool CanAnimate() const { return true; } // If the panel can animate
// scheme access functions
virtual HScheme GetScheme();
virtual void SetScheme(const char *tag);

View File

@ -0,0 +1,727 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#if defined(WIN32) && !defined( _X360 )
#include <windows.h>
#endif
#include "filesystem.h"
#include "filesystem_init.h"
#include "appframework/IAppSystemGroup.h"
#include "appframework/IAppSystem.h"
#include "appframework/AppFramework.h"
#include "filesystem_helpers.h"
#include "matsys_controls/QCGenerator.h"
#include "tier1/KeyValues.h"
#include "tier2/vconfig.h"
#include "vgui_controls/ListPanel.h"
#include "vgui_controls/TextEntry.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/FileOpenDialog.h"
#include "vgui_controls/DirectorySelectDialog.h"
#include "vgui_controls/ComboBox.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/MessageBox.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/Cursor.h"
#include "vgui_controls/KeyBoardEditorDialog.h"
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
using namespace vgui;
#define MAX_KEYVALUE 1024
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to the 'count' occurence of a character from the end of a string
// returns 0 of there aren't 'count' number of the character in the string
//-----------------------------------------------------------------------------
char *strrchrcount(char *string, int character, int count )
{
int j = count;
int numChars = V_strlen( string );
for( int i = numChars; i > 0; i-- )
{
if( string[i-1] == character )
{
j--;
}
if( j == 0 )
{
return string + i-1;
}
}
return 0;
}
class CModalPreserveMessageBox : public vgui::MessageBox
{
public:
CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
: vgui::MessageBox( title, text, parent )
{
m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
}
~CModalPreserveMessageBox()
{
vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
}
public:
vgui::VPANEL m_PrevAppFocusPanel;
};
void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... )
{
char msg[4096];
va_list marker;
va_start( marker, pMsg );
Q_vsnprintf( msg, sizeof( msg ), pMsg, marker );
va_end( marker );
vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent );
dlg->DoModal();
dlg->Activate();
dlg->RequestFocus();
}
//-----------------------------------------------------------------------------
// Purpose: Places all the info from the vgui controls into the QCInfo struct
//-----------------------------------------------------------------------------
void QCInfo::SyncFromControls()
{
char tempText[MAX_PATH];
vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
bStaticProp = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
bMostlyOpaque = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
bDisableCollision = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
bReferenceAsPhys = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
bConcave = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
bAutomass = ((CheckButton *)pTargetField)->IsSelected();
pTargetField = pQCGenerator->FindChildByName( "massField" );
((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
fMass = atof(tempText);
pTargetField = pQCGenerator->FindChildByName( "scaleField" );
((TextEntry *)pTargetField)->GetText(tempText, MAX_PATH);
fScale = atof(tempText);
pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
V_strcpy_safe( pszCollisionPath, tempText );
pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
((ComboBox *)pTargetField)->GetText( tempText, MAX_PATH );
V_strcpy_safe( pszSurfaceProperty, tempText );
pTargetField = pQCGenerator->FindChildByName( "materialsField" );
((TextEntry *)pTargetField)->GetText( tempText, MAX_PATH );
V_strcpy_safe( pszMaterialPath, tempText );
LODs.RemoveAll();
pTargetField = pQCGenerator->FindChildByName( "LODList" );
int numLOD = ((ListPanel *)pTargetField)->GetItemCount();
for ( int i = 0; i < numLOD; i++ )
{
KeyValues *key = ((ListPanel *)pTargetField)->GetItem( i );
LODInfo newLOD;
V_strcpy_safe( newLOD.pszFilename, key->GetString( "SMD" ) );
newLOD.iLOD = key->GetInt( "LOD" );
LODs.AddToTail( newLOD );
}
}
//-----------------------------------------------------------------------------
// Purpose: Called during intialization to setup the initial state of the VGUI controls
//-----------------------------------------------------------------------------
void QCInfo::SyncToControls()
{
char tempText[MAX_PATH];
vgui::Panel *pTargetField = pQCGenerator->FindChildByName( "staticPropCheck" );
((CheckButton *)pTargetField)->SetSelected( bStaticProp );
pTargetField = pQCGenerator->FindChildByName( "mostlyOpaqueCheck" );
((CheckButton *)pTargetField)->SetSelected( bMostlyOpaque );
pTargetField = pQCGenerator->FindChildByName( "disableCollisionsCheck" );
((CheckButton *)pTargetField)->SetSelected( bDisableCollision );
pTargetField = pQCGenerator->FindChildByName( "referencePhysicsCheck" );
((CheckButton *)pTargetField)->SetSelected( bReferenceAsPhys );
pTargetField = pQCGenerator->FindChildByName( "concaveCheck" );
((CheckButton *)pTargetField)->SetSelected( bConcave );
pTargetField = pQCGenerator->FindChildByName( "automassCheck" );
((CheckButton *)pTargetField)->SetSelected( bAutomass );
Q_snprintf( tempText, 10, "%d", (int)fMass );
pTargetField = pQCGenerator->FindChildByName( "massField" );
((TextEntry *)pTargetField)->SetText( tempText );
Q_snprintf( tempText, 10, "%d", (int)fScale );
pTargetField = pQCGenerator->FindChildByName( "scaleField" );
((TextEntry *)pTargetField)->SetText( tempText );
pTargetField = pQCGenerator->FindChildByName( "collisionSMDField" );
((TextEntry *)pTargetField)->SetText( pszCollisionPath );
pTargetField = pQCGenerator->FindChildByName( "materialsField" );
((TextEntry *)pTargetField)->SetText( pszMaterialPath );
pTargetField = pQCGenerator->FindChildByName( "surfacePropertyDropDown" );
int numItems = ((ComboBox *)pTargetField)->GetItemCount();
for( int i = 0; i < numItems; i++ )
{
((ComboBox *)pTargetField)->GetItemText( i, tempText, MAX_PATH );
if ( !Q_strcmp( tempText, pszSurfaceProperty ) )
{
((ComboBox *)pTargetField)->SetItemEnabled( i, true );
((ComboBox *)pTargetField)->SetText( tempText );
break;
}
}
}
CBrowseButton::CBrowseButton( vgui::Panel *pParent ) : BaseClass( pParent, "Browse Button", "...", pParent, "browse" )
{
SetParent( pParent );
pszStartingDirectory = NULL;
pszFileFilter = NULL;
pszTargetField = NULL;
}
CBrowseButton::~CBrowseButton()
{
}
void CBrowseButton::SetCharVar( char **pVar, const char *pszNewText )
{
if ( *pVar && pszNewText && !Q_strcmp( *pVar, pszNewText ) )
{
return;
}
if ( *pVar )
{
delete [] *pVar;
*pVar = NULL;
}
if ( pszNewText )
{
int len = Q_strlen( pszNewText ) + 1;
*pVar = new char[ len ];
Q_strncpy( *pVar, pszNewText, len );
}
}
void CBrowseButton::InitBrowseInfo( int x, int y, const char *pszName, const char *pszDir, const char *pszFilter, const char *pszField )
{
SetSize( 24, 24 );
SetPos( x, y );
SetName( pszName );
SetCharVar( GetStartingDirectory(), pszDir );
SetCharVar( GetFileFilter(), pszFilter );
SetCharVar( GetTargetField(), pszField );
SetActionMessage();
}
void CBrowseButton::SetActionMessage()
{
KeyValues *newActionMessage = new KeyValues( "browse", "directory", pszStartingDirectory, "filter", pszFileFilter);
newActionMessage->SetString( "targetField", pszTargetField );
SetCommand( newActionMessage );
}
const char *ParseKeyvalue( const char *pBuffer, char *key, char *value )
{
char com_token[1024];
pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
if ( Q_strlen( com_token ) < MAX_KEYVALUE )
{
Q_strncpy( key, com_token, MAX_KEYVALUE );
Q_strlower( key );
}
// no value on a close brace
if ( !Q_strcmp( key, "}" ) )
{
value[0] = 0;
return pBuffer;
}
pBuffer = (const char *)ParseFile( pBuffer, com_token, NULL );
if ( Q_strlen( com_token ) < MAX_KEYVALUE )
{
Q_strncpy( value, com_token, MAX_KEYVALUE );
Q_strlower( value );
}
return pBuffer;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CQCGenerator::CQCGenerator( vgui::Panel *pParent, const char *pszPath, const char *pszScene ) : BaseClass( pParent, "QCGenerator" )
{
m_szTargetField[0] = 0;
m_nSelectedSequence = 0;
m_nSelectedColumn = 0;
m_QCInfo_t.Init( this );
SetMinimumSize(846, 770);
m_pLODPanel = new ListPanel(this, "LODList");
m_pLODPanel->SetSelectIndividualCells( true );
m_pLODPanel->AddColumnHeader(0, "SMD", "LOD SMD", 450, 0);
m_pLODPanel->AddColumnHeader(1, "LOD", "LOD Distance", 50, 0);
m_pLODPanel->AddActionSignalTarget( this );
m_pLODPanel->SetMouseInputEnabled( true );
LoadControlSettings( "QCGenerator.res" );
m_pCollisionBrowseButton = new CBrowseButton( this );
m_pCollisionBrowseButton->InitBrowseInfo( 808, 158, "collisionBrowseButton", pszPath, "*.smd", "collisionSMDField" );
char szTerminatedPath[1024] = "\0";
sprintf( szTerminatedPath, "%s\\", pszPath );
InitializeSMDPaths( szTerminatedPath, pszScene );
char *pszMaterialsStart = strrchrcount( szTerminatedPath, '\\', 3 ) + 1;
char *pszMaterialsEnd = strrchr( szTerminatedPath, '\\');
Q_strncpy( m_QCInfo_t.pszMaterialPath, pszMaterialsStart, pszMaterialsEnd - pszMaterialsStart + 1 );
SetParent( pParent );
char szGamePath[1024] = "\0";
char szSearchPath[1024] = "\0";
// Get the currently set game configuration
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
static const char *pSurfacePropFilename = "\\scripts\\surfaceproperties.txt";
sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
FileHandle_t fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
if ( !fp )
{
//the set game configuration didn't have a surfaceproperties file; we are grabbing it from hl2
//TODO: This only works if they are in a subdirectory that is a peer to an hl2 directory
// that contains the file. It potentially needs to search the entire drive or prompt for the location
char *pszEndGamePath = Q_strrchr( szGamePath, '\\' );
pszEndGamePath[0] = 0;
V_strcat_safe( szGamePath, "\\hl2" );
sprintf( szSearchPath, "%s%s", szGamePath, pSurfacePropFilename );
fp = g_pFullFileSystem->Open( szSearchPath, "rb" );
}
int len = g_pFullFileSystem->Size( fp );
const char *szSurfacePropContents = new char[len+1];
g_pFullFileSystem->Read( (void *)szSurfacePropContents, len, fp );
char key[MAX_KEYVALUE], value[MAX_KEYVALUE];
vgui::Panel *pSurfacePropDropDown = FindChildByName( "surfacePropertyDropDown" );
//filling up the surface property dropdown
while ( szSurfacePropContents )
{
szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
((ComboBox *)pSurfacePropDropDown)->AddItem( key, NULL );
while ( szSurfacePropContents )
{
szSurfacePropContents = ParseKeyvalue( szSurfacePropContents, key, value );
if (!stricmp( key, "}" ) )
{
break;
}
}
}
m_QCInfo_t.SyncToControls();
m_pLODEdit = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CQCGenerator::~CQCGenerator()
{
}
void CQCGenerator::OnCommand( const char *command )
{
if ( Q_stricmp( command, "createQC" ) == 0 )
{
m_QCInfo_t.SyncFromControls();
GenerateQCFile();
}
if ( Q_stricmp( command, "deleteSeq" ) == 0 )
{
//delete it
DeleteLOD();
}
if ( Q_stricmp( command, "editSeq" ) == 0 )
{
//edit
EditLOD();
}
BaseClass::OnCommand( command );
}
void CQCGenerator::OnKeyCodeTyped( KeyCode code )
{
switch ( code )
{
case KEY_ENTER:
EditLOD();
}
}
void CQCGenerator::OnBrowse( KeyValues *data )
{
V_strcpy_safe( m_szTargetField, data->GetString( "targetField" ) );
const char *filter = data->GetString( "filter" );
if ( Q_strlen( filter ) == 0 )
{
// BrowseDirectory( data );
}
else
{
BrowseFile( data );
}
}
/*
//This function is no longer used in the current version of the program.
void CQCGenerator::BrowseDirectory( KeyValues *data )
{
DirectorySelectDialog *pDialog = new DirectorySelectDialog( this, "Select Directory" );
pDialog->AddActionSignalTarget( this );
pDialog->DoModal();
pDialog->SetStartDirectory( data->GetString( "directory" ) );
}
*/
void CQCGenerator::BrowseFile( KeyValues *data )
{
const char *filter = data->GetString( "filter" );
FileOpenDialog *pDialog = new FileOpenDialog( this, "Select File", true );
pDialog->AddFilter( filter, filter, true );
pDialog->AddActionSignalTarget(this);
pDialog->SetStartDirectory( data->GetString( "directory" ) );
pDialog->DoModal( true );
}
void CQCGenerator::OnFileSelected( KeyValues *data )
{
if ( *m_szTargetField )
{
vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
((TextEntry *)pTargetField)->SetText( data->GetString( "fullpath" ) );
Repaint();
}
}
void CQCGenerator::OnDirectorySelected( KeyValues *data )
{
if ( *m_szTargetField )
{
vgui::Panel *pTargetField = FindChildByName( m_szTargetField );
((TextEntry *)pTargetField)->SetText( data->GetString( "dir" ) );
Repaint();
}
}
bool CQCGenerator::GenerateQCFile()
{
//TODO: clean this up. Consider creating a datatype that includes the string to write out when the QC file is created
char *nameBegin = strrchr( m_QCInfo_t.pszSMDPath, '\\' );
char szPath[MAX_PATH];
char szName[MAX_PATH];
Q_strncpy( szPath, m_QCInfo_t.pszSMDPath, nameBegin - m_QCInfo_t.pszSMDPath + 2 );
V_strcpy_safe( szName, szPath);
V_strcat_safe( szName, m_QCInfo_t.pszSceneName);
V_strcat_safe( szName, ".qc" );
FileHandle_t pSaveFile = g_pFullFileSystem->Open( szName, "wt" );
if (!pSaveFile)
{
char szSaveError[1024] = "";
Q_snprintf( szSaveError, 1024, "Save failed: invalid file name '%s'\n\nDirectory '%s' must exist.", szName, szPath );
VGUIMessageBox( this, "QC Generator error", szSaveError );
return 0;
}
//write qc header
g_pFullFileSystem->FPrintf( pSaveFile, "//\n// .qc file version 1.0\n\n");
//write out modelname info
char szModelName[MAX_PATH];
char *modelStart = strrchrcount( szName, '\\', 2) + 1;
char *modelEnd = strrchr( szName, '.' );
Q_strncpy( szModelName, modelStart, modelEnd - modelStart + 1 );
V_strcat_safe( szModelName, ".mdl" );
g_pFullFileSystem->FPrintf( pSaveFile, "$modelname %s\n\n", szModelName );
//write out scale info
g_pFullFileSystem->FPrintf( pSaveFile, "$scale %f\n", m_QCInfo_t.fScale );
//write out body info
g_pFullFileSystem->FPrintf( pSaveFile, "$body \"Body\" \"%s\"\n", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
if ( m_QCInfo_t.bStaticProp == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$staticprop\n" );
}
if ( m_QCInfo_t.bMostlyOpaque == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$mostlyopaque\n" );
}
//write out surfaceprop info
g_pFullFileSystem->FPrintf( pSaveFile, "$surfaceprop \"%s\"\n\n", m_QCInfo_t.pszSurfaceProperty );
//write materials
g_pFullFileSystem->FPrintf( pSaveFile, "$cdmaterials %s\n\n", m_QCInfo_t.pszMaterialPath);
if ( m_QCInfo_t.bStaticProp || m_QCInfo_t.bNoAnimation )
{
g_pFullFileSystem->FPrintf( pSaveFile, "// --------- Animation sequences -------\n");
g_pFullFileSystem->FPrintf( pSaveFile, "$sequence \"idle\" \"%s\" fps 30\n\n", strrchr(m_QCInfo_t.pszSMDPath, '\\')+1);
}
//write out lod info
for( int i = 0; i < m_QCInfo_t.LODs.Count(); i++ )
{
LODInfo thisLOD = m_QCInfo_t.LODs.Element( i );
g_pFullFileSystem->FPrintf( pSaveFile, "$lod %d\n{\n\treplacemodel \"%s\" \"%s\"\n}\n\n", thisLOD.iLOD, strrchr(m_QCInfo_t.pszSMDPath, '\\')+1, thisLOD.pszFilename );
}
if ( m_QCInfo_t.bDisableCollision != true )
{
//write out collision header
g_pFullFileSystem->FPrintf( pSaveFile, "\n" );
//write out collision info
if ( m_QCInfo_t.bReferenceAsPhys == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszSMDPath, '\\' ) + 1 );
}
else
{
if( Q_strcmp( m_QCInfo_t.pszCollisionPath, "" ) )
{
g_pFullFileSystem->FPrintf( pSaveFile, "$collisionmodel \"%s\"", strrchr( m_QCInfo_t.pszCollisionPath, '\\' ) + 1 );
}
}
g_pFullFileSystem->FPrintf( pSaveFile, " {\n\t// Mass in kilograms\n ");
if ( m_QCInfo_t.bAutomass == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "\t$automass\n" );
}
else
{
g_pFullFileSystem->FPrintf( pSaveFile, "\t$mass %f\n", m_QCInfo_t.fMass );
}
if ( m_QCInfo_t.bConcave == true )
{
g_pFullFileSystem->FPrintf( pSaveFile, "\t$concave\n" );
}
g_pFullFileSystem->FPrintf( pSaveFile, "}\n\n");
}
g_pFullFileSystem->Close( pSaveFile );
char szCommand[MAX_PATH];
char szGamePath[MAX_PATH];
char studiomdlPath[512];
g_pFullFileSystem->RelativePathToFullPath( "studiomdl.bat", NULL, studiomdlPath, sizeof( studiomdlPath ));
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szGamePath, sizeof( szGamePath ) );
#ifdef WIN32
STARTUPINFO startup;
PROCESS_INFORMATION process;
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
sprintf( szCommand, "%s -game %s %s", studiomdlPath, szGamePath, szName);
bool bReturn = CreateProcess( NULL, szCommand, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &startup, &process);
#else
Assert( !"Implement me, why aren't we using a thread tool abstraction?" );
bool bReturn = false;
#endif
return bReturn;
}
void CQCGenerator::InitializeSMDPaths( const char *pszPath, const char *pszScene )
{
V_strcpy_safe( m_QCInfo_t.pszSceneName, pszScene );
FileFindHandle_t *pFileHandle = new FileFindHandle_t();
g_pFullFileSystem->AddSearchPath( pszPath, "SMD_DIR" );
const char *filename = g_pFullFileSystem->FindFirst( "*.smd", pFileHandle );
bool bFoundReference = false;
bool bFoundCollision = false;
bool bFoundLOD = false;
//iterate through .smd files
const char *startName = pszScene;
int nSearchLength = Q_strlen( pszScene );
int currentLOD = 1;
while( filename )
{
if ( !strncmp( startName, filename, nSearchLength ) )
{
const char *filenameEnd = filename + nSearchLength;
if ( !strncmp( filenameEnd, "_ref", 4 ) || !strncmp( filenameEnd, ".smd", 4 ) )
{
bFoundReference = true;
//we have found the reference smd.
V_strcpy_safe( m_QCInfo_t.pszSMDPath, pszPath );
V_strcat_safe( m_QCInfo_t.pszSMDPath, filename );
}
if ( !strncmp( filenameEnd, "_phy", 4) || !strncmp( filenameEnd, "_col", 4 ) )
{
bFoundCollision = true;
//we have found the collision smd.
V_strcpy_safe( m_QCInfo_t.pszCollisionPath, pszPath );
V_strcat_safe( m_QCInfo_t.pszCollisionPath, filename );
}
if ( !strncmp( filenameEnd, "_lod", 4) )
{
bFoundLOD = true;
//we found an LOD smd.
char lodName[255];
Q_snprintf( lodName, Q_strlen( lodName ), "lod%d", currentLOD );
//we found an LOD
KeyValues *newKv = new KeyValues( lodName, "SMD", filename, "LOD", "10" );
m_pLODPanel->AddItem( newKv, currentLOD, false, false );
currentLOD++;
}
}
filename = g_pFullFileSystem->FindNext( *pFileHandle );
}
char pszMessage[2048] = "";
char pszRefMessage[1024] = "";
char pszColMessage[1024] = "";
if (!bFoundReference )
{
V_strcat_safe( m_QCInfo_t.pszSMDPath, pszPath );
V_strcat_safe( m_QCInfo_t.pszSMDPath, pszScene );
V_strcat_safe( m_QCInfo_t.pszSMDPath, ".smd" );
Q_snprintf( pszRefMessage, 1024, "Reference SMD not found.\n\nValid default reference SMDs are %s%s_ref*.smd and %s%s.smd\nUsing default of %s. Model will not compile.\n\n", pszPath, pszScene, pszPath, pszScene, m_QCInfo_t.pszSMDPath );
}
if ( !bFoundCollision )
{
Q_snprintf( pszColMessage, 1024, "Collision SMD not found.\n\nThe valid default collision SMD is %s%s_phy*.smd.\nUsing reference SMD as default.\n", pszPath, pszScene );
V_strcpy_safe( m_QCInfo_t.pszCollisionPath, m_QCInfo_t.pszSMDPath );
m_QCInfo_t.bReferenceAsPhys = true;
}
if ( !bFoundReference || !bFoundCollision)
{
V_strcpy_safe( pszMessage, pszRefMessage );
V_strcat_safe( pszMessage, pszColMessage );
VGUIMessageBox( this, "Error Initializing Paths", pszMessage );
}
}
void CQCGenerator::DeleteLOD()
{
int numSelected = m_pLODPanel->GetSelectedItemsCount();
int selected;
for ( int i = numSelected-1; i >= 0; i-- )
{
selected = m_pLODPanel->GetSelectedItem( i );
m_pLODPanel->RemoveItem( selected );
}
}
void CQCGenerator::EditLOD()
{
int numSelected = m_pLODPanel->GetSelectedItemsCount();
if ( numSelected == 1 && !m_pLODPanel->IsInEditMode() )
{
if ( m_pLODEdit )
{
m_pLODEdit->MarkForDeletion();
m_pLODEdit = NULL;
}
m_pLODEdit = new vgui::TextEntry( this, "Edit" );
m_pLODEdit->SendNewLine( true );
m_nSelectedSequence = m_pLODPanel->GetSelectedItem( 0 );
m_nSelectedColumn = m_pLODPanel->GetSelectedColumn();
m_pLODPanel->EnterEditMode( m_nSelectedSequence, m_nSelectedColumn, m_pLODEdit );
}
}
void CQCGenerator::OnNewLODText()
{
KeyValues *pEditItem = m_pLODPanel->GetItem( m_nSelectedSequence );
KeyValues *pListItem = pEditItem;
wchar_t szEditText[MAX_PATH];
pEditItem = pEditItem->GetFirstValue();
const char *name = pEditItem->GetName();
for( int i = 0; i < m_nSelectedColumn; i++ )
{
pEditItem = pEditItem->GetNextValue();
name = pEditItem->GetName();
}
m_pLODEdit->GetText( szEditText, MAX_PATH );
pListItem->SetWString( name, szEditText );
m_pLODPanel->LeaveEditMode();
m_pLODPanel->InvalidateLayout();
return;
}

View File

@ -0,0 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "matsys_controls/assetpicker.h"
using namespace vgui;
//-----------------------------------------------------------------------------
//
// Asset Picker with no preview
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CAssetPicker::CAssetPicker( vgui::Panel *pParent, const char *pAssetType,
const char *pExt, const char *pSubDir, const char *pTextType ) :
BaseClass( pParent, pAssetType, pExt, pSubDir, pTextType )
{
CreateStandardControls( this );
LoadControlSettingsAndUserConfig( "resource/assetpicker.res" );
}
//-----------------------------------------------------------------------------
//
// Purpose: Modal picker frame
//
//-----------------------------------------------------------------------------
CAssetPickerFrame::CAssetPickerFrame( vgui::Panel *pParent, const char *pTitle,
const char *pAssetType, const char *pExt, const char *pSubDir, const char *pTextType ) :
BaseClass( pParent )
{
SetAssetPicker( new CAssetPicker( this, pAssetType, pExt, pSubDir, pTextType ) );
LoadControlSettingsAndUserConfig( "resource/assetpickerframe.res" );
SetTitle( pTitle, false );
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "matsys_controls/curveeditorpanel.h"
#include "matsys_controls/matsyscontrols.h"
#include "tier1/KeyValues.h"
#include "vgui/ISurface.h"
#include "vgui/IInput.h"
#include "vgui/MouseCode.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CCurveEditorPanel::CCurveEditorPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName )
{
m_nSelectedPoint = -1;
SetMouseInputEnabled( true );
SetKeyBoardInputEnabled( true );
m_nHighlightedPoint = -1;
}
CCurveEditorPanel::~CCurveEditorPanel()
{
}
//-----------------------------------------------------------------------------
// Converts screen location to normalized values
//-----------------------------------------------------------------------------
void CCurveEditorPanel::ScreenToValue( int x, int y, float *pIn, float *pOut )
{
int w, h;
GetSize( w, h );
*pIn = (float)x / (w-1);
*pOut = 1.0f - ((float)y / (h-1));
}
void CCurveEditorPanel::ValueToScreen( float flIn, float flOut, int *x, int *y )
{
int w, h;
GetSize( w, h );
*x = (int)(flIn * (w-1) + 0.5f);
*y = (h-1) - (int)(flOut * (h-1) + 0.5f);
}
//-----------------------------------------------------------------------------
// Handle input
//-----------------------------------------------------------------------------
void CCurveEditorPanel::OnMousePressed( vgui::MouseCode code )
{
BaseClass::OnMousePressed( code );
int x, y;
input()->GetCursorPos( x, y );
ScreenToLocal( x, y );
if ( code == MOUSE_LEFT )
{
int w, h;
GetSize( w, h );
float flIn, flOut;
ScreenToValue( x, y, &flIn, &flOut );
float flTolerance = 5.0f / (w-1); // +/- 3 pixels to select the point
m_nSelectedPoint = FindOrAddControlPoint( flIn, flTolerance, flOut );
}
}
void CCurveEditorPanel::OnMouseReleased( vgui::MouseCode code )
{
BaseClass::OnMouseReleased( code );
if ( code == MOUSE_LEFT )
{
m_nSelectedPoint = -1;
}
}
void CCurveEditorPanel::OnCursorMoved( int x, int y )
{
BaseClass::OnCursorMoved( x, y );
float flIn, flOut;
ScreenToValue( x, y, &flIn, &flOut );
int w, h;
GetSize( w, h );
float flTolerance = 5.0f / (w-1); // +/- 3 pixels to select the point
m_nHighlightedPoint = FindControlPoint( flIn, flTolerance );
if ( m_nSelectedPoint < 0 )
return;
m_nSelectedPoint = ModifyControlPoint( m_nSelectedPoint, flIn, flOut );
}
//-----------------------------------------------------------------------------
// Handles keypresses
//-----------------------------------------------------------------------------
void CCurveEditorPanel::OnKeyCodePressed( vgui::KeyCode code )
{
BaseClass::OnKeyCodePressed( code );
if ( m_nSelectedPoint >= 0 )
{
RemoveControlPoint( m_nSelectedPoint );
m_nSelectedPoint = -1;
}
}
//-----------------------------------------------------------------------------
// This paints the grid behind the curves
//-----------------------------------------------------------------------------
void CCurveEditorPanel::PaintBackground( void )
{
int w, h;
GetSize( w, h );
vgui::surface()->DrawSetColor( 255, 255, 255, 255 );
vgui::surface()->DrawFilledRect( 0, 0, w, h );
vgui::surface()->DrawSetColor( 128, 128, 128, 255 );
vgui::surface()->DrawLine( 0, h/4, w, h/4 );
vgui::surface()->DrawLine( 0, h/2, w, h/2 );
vgui::surface()->DrawLine( 0, 3*h/4, w, 3*h/4 );
vgui::surface()->DrawLine( w/4, 0, w/4, h );
vgui::surface()->DrawLine( w/2, 0, w/2, h );
vgui::surface()->DrawLine( 3*w/4, 0, 3*w/4, h );
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawLine( 0, 0, w, 0 );
vgui::surface()->DrawLine( w, 0, w, h );
vgui::surface()->DrawLine( w, h, 0, h );
vgui::surface()->DrawLine( 0, h, 0, 0 );
}
//-----------------------------------------------------------------------------
// Sets the color curves operation to edit
//-----------------------------------------------------------------------------
void CCurveEditorPanel::Paint( void )
{
int w, h;
GetSize( w, h );
int x0 = 0, y0 = 0;
// FIXME: Add method to draw multiple lines DrawPolyLine connects the 1st and last points... bleah
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
for ( int i = 0; i < w; ++i )
{
float flIn = (float)i / (w-1);
float flOut = GetValue( flIn );
int x = i;
int y = (h-1) - (int)(flOut * (h-1) + 0.5f);
y = clamp( y, 0, h-1 );
if ( i != 0 )
{
vgui::surface()->DrawLine( x0, y0, x, y );
}
x0 = x; y0 = y;
}
// This will paint the control points
// The currently selected one will be painted red and filled.
for ( int i = ControlPointCount(); --i >= 0; )
{
float flIn, flOut;
GetControlPoint( i, &flIn, &flOut );
int cx, cy;
ValueToScreen( flIn, flOut, &cx, &cy );
if ( (i == m_nSelectedPoint) || ((m_nSelectedPoint == -1) && (i == m_nHighlightedPoint)) )
{
vgui::surface()->DrawSetColor( 255, 0, 0, 255 );
vgui::surface()->DrawFilledRect( cx-3, cy-3, cx+3, cy+3 );
}
else
{
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawOutlinedRect( cx-3, cy-3, cx+3, cy+3 );
}
}
}

View File

@ -0,0 +1,301 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#if defined(WIN32) && !defined( _X360 )
#include <windows.h>
#endif
#undef PropertySheet
#include "matsys_controls/gamefiletreeview.h"
#include "filesystem.h"
#include "tier1/KeyValues.h"
#include "vgui/ISurface.h"
#include "vgui/Cursor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// list of all tree view icons
//-----------------------------------------------------------------------------
enum
{
IMAGE_FOLDER = 1,
IMAGE_OPENFOLDER,
IMAGE_FILE,
};
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameFileTreeView::CGameFileTreeView( Panel *parent, const char *name, const char *pRootFolderName, const char *pRootDir, const char *pExtension ) : BaseClass(parent, name), m_Images( false )
{
m_RootDir = pRootDir;
m_Ext = pExtension;
m_bUseExt = ( pExtension != NULL );
m_RootFolderName = pRootFolderName;
// build our list of images
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder", false ) );
m_Images.AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) );
m_Images.AddImage( scheme()->GetImage( "resource/icon_file", false ) );
SetImageList( &m_Images, false );
}
//-----------------------------------------------------------------------------
// Purpose: Refreshes the active file list
//-----------------------------------------------------------------------------
void CGameFileTreeView::RefreshFileList()
{
RemoveAll();
SetFgColor(Color(216, 222, 211, 255));
// add the base node
KeyValues *pkv = new KeyValues( "root" );
pkv->SetString( "text", m_RootFolderName );
pkv->SetInt( "root", 1 );
pkv->SetInt( "expand", 1 );
int iRoot = AddItem( pkv, GetRootItemIndex() );
pkv->deleteThis();
ExpandItem( iRoot, true );
}
//-----------------------------------------------------------------------------
// Selects the root folder
//-----------------------------------------------------------------------------
void CGameFileTreeView::SelectRoot()
{
AddSelectedItem( GetRootItemIndex(), true );
}
//-----------------------------------------------------------------------------
// Gets the number of root directories
//-----------------------------------------------------------------------------
int CGameFileTreeView::GetRootDirectoryCount()
{
return GetNumChildren( GetRootItemIndex() );
}
//-----------------------------------------------------------------------------
// Gets the ith root directory
//-----------------------------------------------------------------------------
const char *CGameFileTreeView::GetRootDirectory( int nIndex )
{
int nItemIndex = GetChild( GetRootItemIndex(), nIndex );
KeyValues *kv = GetItemData( nItemIndex );
if ( !kv )
return NULL;
return kv->GetString( "path", NULL );
}
//-----------------------------------------------------------------------------
// Populate the root node (necessary since tree view can't have multiple roots)
//-----------------------------------------------------------------------------
void CGameFileTreeView::PopulateRootNode( int itemIndex )
{
AddDirectoriesOfNode( itemIndex, m_RootDir );
if ( m_bUseExt )
{
AddFilesOfNode( itemIndex, m_RootDir, m_Ext );
}
}
//-----------------------------------------------------------------------------
// Populate the root node with directories
//-----------------------------------------------------------------------------
bool CGameFileTreeView::DoesDirectoryHaveSubdirectories( const char *pFilePath )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath );
// get the list of files
FileFindHandle_t findHandle;
// generate children
// add all the items
const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle );
while ( pszFileName )
{
bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle );
if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) )
return true;
pszFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
return false;
}
//-----------------------------------------------------------------------------
// Populate the root node with directories
//-----------------------------------------------------------------------------
void CGameFileTreeView::AddDirectoriesOfNode( int itemIndex, const char *pFilePath )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath );
// get the list of files
FileFindHandle_t findHandle;
// generate children
// add all the items
const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle );
while ( pszFileName )
{
bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle );
if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) )
{
KeyValues *kv = new KeyValues( "node", "text", pszFileName );
char pFullPath[MAX_PATH];
Q_snprintf( pFullPath, sizeof(pFullPath), "%s/%s", pFilePath, pszFileName );
Q_FixSlashes( pFullPath );
Q_strlower( pFullPath );
bool bHasSubdirectories = DoesDirectoryHaveSubdirectories( pFullPath );
kv->SetString( "path", pFullPath );
kv->SetInt( "expand", bHasSubdirectories );
kv->SetInt( "dir", 1 );
kv->SetInt( "image", IMAGE_FOLDER );
int itemID = AddItem(kv, itemIndex);
kv->deleteThis();
// mark directories in orange
SetItemColorForDirectories( itemID );
}
pszFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
}
//-----------------------------------------------------------------------------
// Populate the root node with files
//-----------------------------------------------------------------------------
void CGameFileTreeView::AddFilesOfNode( int itemIndex, const char *pFilePath, const char *pExt )
{
char pSearchString[MAX_PATH];
Q_snprintf( pSearchString, MAX_PATH, "%s\\*.%s", pFilePath, pExt );
// get the list of files
FileFindHandle_t findHandle;
// generate children
// add all the items
const char *pszFileName = g_pFullFileSystem->FindFirst( pSearchString, &findHandle );
while ( pszFileName )
{
if ( !g_pFullFileSystem->FindIsDirectory( findHandle ) )
{
KeyValues *kv = new KeyValues( "node", "text", pszFileName );
char pFullPath[MAX_PATH];
Q_snprintf( pFullPath, MAX_PATH, "%s\\%s", pFilePath, pszFileName );
kv->SetString( "path", pFullPath );
kv->SetInt( "image", IMAGE_FILE );
AddItem(kv, itemIndex);
kv->deleteThis();
}
pszFileName = g_pFullFileSystem->FindNext( findHandle );
}
g_pFullFileSystem->FindClose( findHandle );
}
//-----------------------------------------------------------------------------
// override to incremental request and show p4 directories
//-----------------------------------------------------------------------------
void CGameFileTreeView::GenerateChildrenOfNode(int itemIndex)
{
KeyValues *pkv = GetItemData(itemIndex);
if ( pkv->GetInt("root") )
{
PopulateRootNode( itemIndex );
return;
}
if (!pkv->GetInt("dir"))
return;
const char *pFilePath = pkv->GetString("path", "");
if (!pFilePath[0])
return;
surface()->SetCursor(dc_waitarrow);
AddDirectoriesOfNode( itemIndex, pFilePath );
if ( m_bUseExt )
{
AddFilesOfNode( itemIndex, pFilePath, m_Ext );
}
}
//-----------------------------------------------------------------------------
// setup a context menu whenever a directory is clicked on
//-----------------------------------------------------------------------------
void CGameFileTreeView::GenerateContextMenu( int itemIndex, int x, int y )
{
return;
/*
KeyValues *pkv = GetItemData(itemIndex);
const char *pFilePath = pkv->GetString("path", "");
if (!pFilePath[0])
return;
Menu *pContext = new Menu(this, "FileContext");
pContext->AddMenuItem("Cloak folder", new KeyValues("CloakFolder", "item", itemIndex), GetParent(), NULL);
// show the context menu
pContext->SetPos(x, y);
pContext->SetVisible(true);
*/
}
//-----------------------------------------------------------------------------
// Sets an item to be colored as if its a menu
//-----------------------------------------------------------------------------
void CGameFileTreeView::SetItemColorForDirectories( int itemID )
{
// mark directories in orange
SetItemFgColor( itemID, Color(224, 192, 0, 255) );
}
//-----------------------------------------------------------------------------
// setup a smaller font
//-----------------------------------------------------------------------------
void CGameFileTreeView::ApplySchemeSettings(IScheme *pScheme)
{
BaseClass::ApplySchemeSettings(pScheme);
SetFont( pScheme->GetFont("DefaultSmall") );
}

View File

@ -0,0 +1,201 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#include "matsys_controls/manipulator.h"
#include "materialsystem/imaterialsystem.h"
#include "vgui/IVGui.h"
#include "vgui/IInput.h"
#include "vgui/ISystem.h"
#include "vgui/MouseCode.h"
#include "mathlib/vector.h"
#include "mathlib/vmatrix.h"
#include "mathlib/mathlib.h"
#include <float.h>
using namespace vgui;
//-----------------------------------------------------------------------------
// local helper functions
//-----------------------------------------------------------------------------
static float UpdateTime( float &flLastTime )
{
float flTime = vgui::system()->GetFrameTime();
float dt = flTime - flLastTime;
flLastTime = flTime;
return dt;
}
//-----------------------------------------------------------------------------
// Base class for manipulators which operate on transforms
//-----------------------------------------------------------------------------
CTransformManipulator::CTransformManipulator( matrix3x4_t *pTransform ) :
m_pTransform( pTransform )
{
}
void CTransformManipulator::SetTransform( matrix3x4_t *pTransform )
{
m_pTransform = pTransform;
}
matrix3x4_t *CTransformManipulator::GetTransform( void )
{
return m_pTransform;
}
//-----------------------------------------------------------------------------
// CPotteryWheelManip - nendo-style camera manipulator
//-----------------------------------------------------------------------------
CPotteryWheelManip::CPotteryWheelManip( matrix3x4_t *pTransform ) :
CTransformManipulator( pTransform ),
m_lastx( -1 ), m_lasty( -1 ),
m_zoom( 100.0f ), m_altitude( 0.0f ), m_azimuth( 0.0f ),
m_prevZoom( 100.0f ), m_prevAltitude( 0.0f ), m_prevAzimuth( 0.0f ),
m_flLastMouseTime( 0.0f ), m_flLastTickTime( 0.0f ),
m_flSpin( 0.0f ), m_bSpin( false )
{
}
void CPotteryWheelManip::OnBeginManipulation( void )
{
m_prevZoom = m_zoom;
m_prevAltitude = m_altitude;
m_prevAzimuth = m_azimuth;
m_flLastMouseTime = m_flLastTickTime = vgui::system()->GetFrameTime();
m_flSpin = 0.0f;
m_bSpin = false;
}
// Sets the zoom level
void CPotteryWheelManip::SetZoom( float flZoom )
{
m_prevZoom = m_zoom = flZoom;
}
void CPotteryWheelManip::OnAcceptManipulation( void )
{
m_flSpin = 0.0f;
m_bSpin = false;
}
void CPotteryWheelManip::OnCancelManipulation( void )
{
m_zoom = m_prevZoom;
m_altitude = m_prevAltitude;
m_azimuth = m_prevAzimuth;
m_flSpin = 0.0f;
m_bSpin = false;
UpdateTransform();
}
void CPotteryWheelManip::OnTick( void )
{
float dt = UpdateTime( m_flLastTickTime );
if ( m_bSpin )
{
m_azimuth += dt * m_flSpin;
UpdateTransform();
}
}
void CPotteryWheelManip::OnCursorMoved( int x, int y )
{
float dt = UpdateTime( m_flLastMouseTime );
if ( m_bSpin )
{
m_lastx = x;
m_lasty = y;
return;
}
if ( input()->IsMouseDown( MOUSE_MIDDLE ) )
{
int dy = y - m_lasty;
int dx = x - m_lastx;
if ( abs( dx ) < 2 * abs( dy ) )
{
UpdateZoom( 0.2f * dy );
}
else
{
m_flSpin = (dt != 0.0f) ? 0.002f * dx / dt : 0.0f;
m_azimuth += 0.002f * dx;
}
}
else
{
m_azimuth += 0.002f * ( x - m_lastx );
m_altitude -= 0.002f * ( y - m_lasty );
m_altitude = max( (float)-M_PI/2, min( (float)M_PI/2, m_altitude ) );
}
m_lastx = x;
m_lasty = y;
UpdateTransform();
}
void CPotteryWheelManip::OnMousePressed( vgui::MouseCode code, int x, int y )
{
UpdateTime( m_flLastMouseTime );
m_lastx = x;
m_lasty = y;
m_bSpin = false;
m_flSpin = 0.0f;
}
void CPotteryWheelManip::OnMouseReleased( vgui::MouseCode code, int x, int y )
{
UpdateTime( m_flLastMouseTime );
if ( code == MOUSE_MIDDLE )
{
m_bSpin = ( fabs( m_flSpin ) > 1.0f );
}
m_lastx = x;
m_lasty = y;
}
void CPotteryWheelManip::OnMouseWheeled( int delta )
{
UpdateTime( m_flLastMouseTime );
UpdateZoom( -10.0f * delta );
UpdateTransform();
}
void CPotteryWheelManip::UpdateTransform()
{
if ( !m_pTransform )
return;
float y = m_zoom * sin( m_altitude );
float xz = m_zoom * cos( m_altitude );
float x = xz * sin( m_azimuth );
float z = xz * cos( m_azimuth );
Vector position(x, y, z);
AngleMatrix( RadianEuler( -m_altitude, m_azimuth, 0 ), position, *m_pTransform );
}
void CPotteryWheelManip::UpdateZoom( float delta )
{
m_zoom *= pow( 1.01f, delta );
}

View File

@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
// MATSYS_CONTROLS.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR "..\.."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Project "matsys_controls"
{
$Folder "Source Files"
{
$File "assetpicker.cpp"
$File "baseassetpicker.cpp"
$File "colorpickerpanel.cpp"
$File "curveeditorpanel.cpp"
$File "gamefiletreeview.cpp"
$File "manipulator.cpp"
$File "matsyscontrols.cpp"
$File "mdlpanel.cpp"
$File "mdlpicker.cpp"
$File "mdlsequencepicker.cpp"
$File "picker.cpp"
$File "potterywheelpanel.cpp"
$File "proceduraltexturepanel.cpp"
$File "QCGenerator.cpp"
$File "sequencepicker.cpp"
$File "tgapreviewpanel.cpp"
$File "vmtpicker.cpp"
$File "vmtpreviewpanel.cpp"
$File "vtfpicker.cpp"
$File "vtfpreviewpanel.cpp"
$File "vmtpanel.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\matsys_controls\assetpicker.h"
$File "$SRCDIR\public\matsys_controls\baseassetpicker.h"
$File "$SRCDIR\public\matsys_controls\colorpickerpanel.h"
$File "$SRCDIR\public\matsys_controls\gamefiletreeview.h"
$File "$SRCDIR\public\matsys_controls\manipulator.h"
$File "$SRCDIR\public\matsys_controls\matsyscontrols.h"
$File "$SRCDIR\public\matsys_controls\mdlpanel.h"
$File "$SRCDIR\public\matsys_controls\mdlpicker.h"
$File "$SRCDIR\public\matsys_controls\mdlsequencepicker.h"
$File "$SRCDIR\public\matsys_controls\picker.h"
$File "$SRCDIR\public\matsys_controls\potterywheelpanel.h"
$File "$SRCDIR\public\matsys_controls\proceduraltexturepanel.h"
$File "$SRCDIR\public\matsys_controls\QCGenerator.h"
$File "$SRCDIR\public\matsys_controls\sequencepicker.h"
$File "$SRCDIR\public\matsys_controls\tgapreviewpanel.h"
$File "$SRCDIR\public\matsys_controls\vmtpicker.h"
$File "$SRCDIR\public\matsys_controls\vmtpreviewpanel.h"
$File "$SRCDIR\public\matsys_controls\vtfpicker.h"
$File "$SRCDIR\public\matsys_controls\vtfpreviewpanel.h"
$File "$SRCDIR\public\matsys_controls\vmtpanel.h"
}
$Folder "Link Libraries"
{
$Lib bitmap [$WIN32]
}
}

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