Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
7.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //=============================================================================
  4. #include "cbase.h"
  5. #include "KeyValues.h"
  6. #include "tf_playerclass_shared.h"
  7. #include "materialsystem/imaterialsystemhardwareconfig.h"
  8. #include "filesystem.h"
  9. #include "tier2/tier2.h"
  10. //=============================================================================
  11. //
  12. // Shared player class data.
  13. //
  14. //=============================================================================
  15. //
  16. // Tables.
  17. //
  18. #define CLASSMODEL_PARITY_BITS 3
  19. #define CLASSMODEL_PARITY_MASK ((1<<CLASSMODEL_PARITY_BITS)-1)
  20. // Client specific.
  21. #ifdef CLIENT_DLL
  22. BEGIN_RECV_TABLE_NOBASE( CTFPlayerClassShared, DT_TFPlayerClassShared )
  23. RecvPropInt( RECVINFO( m_iClass ) ),
  24. RecvPropString( RECVINFO( m_iszClassIcon ) ),
  25. RecvPropString( RECVINFO( m_iszCustomModel ) ),
  26. RecvPropVector( RECVINFO( m_vecCustomModelOffset ) ),
  27. RecvPropQAngles( RECVINFO( m_angCustomModelRotation ) ),
  28. RecvPropBool( RECVINFO( m_bCustomModelRotates ) ),
  29. RecvPropBool( RECVINFO( m_bCustomModelRotationSet ) ),
  30. RecvPropBool( RECVINFO( m_bCustomModelVisibleToSelf ) ),
  31. RecvPropBool( RECVINFO( m_bUseClassAnimations ) ),
  32. RecvPropInt( RECVINFO(m_iClassModelParity) ),
  33. END_RECV_TABLE()
  34. // Server specific.
  35. #else
  36. BEGIN_SEND_TABLE_NOBASE( CTFPlayerClassShared, DT_TFPlayerClassShared )
  37. SendPropInt( SENDINFO( m_iClass ), Q_log2( TF_CLASS_COUNT_ALL )+1, SPROP_UNSIGNED ),
  38. SendPropStringT( SENDINFO( m_iszClassIcon ) ),
  39. SendPropStringT( SENDINFO( m_iszCustomModel ) ),
  40. SendPropVector( SENDINFO( m_vecCustomModelOffset ) ),
  41. SendPropQAngles( SENDINFO( m_angCustomModelRotation ) ),
  42. SendPropBool( SENDINFO( m_bCustomModelRotates ) ),
  43. SendPropBool( SENDINFO( m_bCustomModelRotationSet ) ),
  44. SendPropBool( SENDINFO( m_bCustomModelVisibleToSelf ) ),
  45. SendPropBool( SENDINFO( m_bUseClassAnimations ) ),
  46. SendPropInt( SENDINFO(m_iClassModelParity), CLASSMODEL_PARITY_BITS, SPROP_UNSIGNED ),
  47. END_SEND_TABLE()
  48. #endif
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Constructor
  51. //-----------------------------------------------------------------------------
  52. CTFPlayerClassShared::CTFPlayerClassShared()
  53. {
  54. Reset();
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose:
  58. //-----------------------------------------------------------------------------
  59. void CTFPlayerClassShared::Reset( void )
  60. {
  61. m_iClass.Set( TF_CLASS_UNDEFINED );
  62. #ifdef CLIENT_DLL
  63. m_iszClassIcon[0] = '\0';
  64. m_iszCustomModel[0] = '\0';
  65. #else
  66. m_iszClassIcon.Set( NULL_STRING );
  67. m_iszCustomModel.Set( NULL_STRING );
  68. #endif
  69. m_vecCustomModelOffset = vec3_origin;
  70. m_angCustomModelRotation = vec3_angle;
  71. m_bCustomModelRotates = true;
  72. m_bCustomModelRotationSet = false;
  73. m_bCustomModelVisibleToSelf = true;
  74. m_bUseClassAnimations = false;
  75. m_iClassModelParity = 0;
  76. }
  77. #ifndef CLIENT_DLL
  78. //-----------------------------------------------------------------------------
  79. // Purpose:
  80. //-----------------------------------------------------------------------------
  81. void CTFPlayerClassShared::SetCustomModel( const char *pszModelName, bool isUsingClassAnimations )
  82. {
  83. if ( pszModelName && pszModelName[0] )
  84. {
  85. bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed();
  86. CBaseEntity::SetAllowPrecache( true );
  87. CBaseEntity::PrecacheModel( pszModelName );
  88. CBaseEntity::SetAllowPrecache( bAllowPrecache );
  89. m_iszCustomModel.Set( AllocPooledString( pszModelName ) );
  90. m_bUseClassAnimations = isUsingClassAnimations;
  91. }
  92. else
  93. {
  94. m_iszCustomModel.Set( NULL_STRING );
  95. m_vecCustomModelOffset = vec3_origin;
  96. m_angCustomModelRotation = vec3_angle;
  97. }
  98. m_iClassModelParity = (m_iClassModelParity + 1) & CLASSMODEL_PARITY_MASK;
  99. }
  100. #endif // #ifndef CLIENT_DLL
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. //-----------------------------------------------------------------------------
  104. bool CTFPlayerClassShared::CustomModelHasChanged( void )
  105. {
  106. if ( m_iClassModelParity != m_iOldClassModelParity )
  107. {
  108. m_iOldClassModelParity = m_iClassModelParity.Get();
  109. return true;
  110. }
  111. return false;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // Purpose:
  115. //-----------------------------------------------------------------------------
  116. #ifdef STAGING_ONLY
  117. ConVar tf_player_use_female_models( "tf_player_use_female_models", "0", FCVAR_CHEAT | FCVAR_REPLICATED, "For testing. Appends '_female' to the model filename loaded" );
  118. #endif
  119. const char *CTFPlayerClassShared::GetModelName( void ) const
  120. {
  121. // Does this play have an overridden model?
  122. #ifdef CLIENT_DLL
  123. if ( m_iszCustomModel[0] )
  124. return m_iszCustomModel;
  125. #else
  126. if ( m_iszCustomModel.Get() != NULL_STRING )
  127. return ( STRING( m_iszCustomModel.Get() ) );
  128. #endif
  129. #define MAX_MODEL_FILENAME_LENGTH 256
  130. static char modelFilename[ MAX_MODEL_FILENAME_LENGTH ];
  131. Q_strncpy( modelFilename, GetPlayerClassData( m_iClass )->GetModelName(), sizeof( modelFilename ) );
  132. #ifdef STAGING_ONLY
  133. if ( tf_player_use_female_models.GetBool() )
  134. {
  135. // find the ".mdl" part
  136. char *ext;
  137. for( ext = modelFilename; *ext != '\000'; ++ext )
  138. {
  139. if ( *ext == '.' )
  140. {
  141. V_strncpy( ext, "_female.mdl", sizeof( modelFilename ) - ( ext - modelFilename ) );
  142. break;
  143. }
  144. }
  145. // make sure the test model is precached
  146. bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed();
  147. CBaseEntity::SetAllowPrecache( true );
  148. CBaseEntity::PrecacheModel( modelFilename );
  149. CBaseEntity::SetAllowPrecache( bAllowPrecache );
  150. }
  151. #endif
  152. return modelFilename;
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Purpose: Initialize the player class.
  156. //-----------------------------------------------------------------------------
  157. const char *g_HACK_GunslingerEngineerArmsOverride = "models\\weapons\\c_models\\c_engineer_gunslinger.mdl";
  158. const char *CTFPlayerClassShared::GetHandModelName( int iHandIndex = 0 ) const
  159. {
  160. return iHandIndex == 0
  161. ? GetPlayerClassData( m_iClass )->m_szHandModelName
  162. :g_HACK_GunslingerEngineerArmsOverride; // this is precached in the CTFRobotArm class
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Purpose: Initialize the player class.
  166. //-----------------------------------------------------------------------------
  167. bool CTFPlayerClassShared::Init( int iClass )
  168. {
  169. Assert ( ( iClass >= TF_FIRST_NORMAL_CLASS ) && ( iClass <= TF_LAST_NORMAL_CLASS ) );
  170. Reset();
  171. m_iClass = iClass;
  172. #ifdef CLIENT_DLL
  173. V_strncpy( m_iszCustomModel, g_aRawPlayerClassNamesShort[ m_iClass ], sizeof( m_iszCustomModel ) );
  174. #else
  175. m_iszClassIcon.Set( AllocPooledString( g_aRawPlayerClassNamesShort[ m_iClass ] ) );
  176. #endif
  177. return true;
  178. }
  179. // If needed, put this into playerclass scripts
  180. bool CTFPlayerClassShared::CanBuildObject( int iObjectType )
  181. {
  182. bool bFound = false;
  183. TFPlayerClassData_t *pData = GetData();
  184. int i;
  185. for ( i=0;i<TF_PLAYER_BLUEPRINT_COUNT;i++ )
  186. {
  187. if ( iObjectType == pData->m_aBuildable[i] )
  188. {
  189. bFound = true;
  190. break;
  191. }
  192. }
  193. return bFound;
  194. }