Counter Strike : Global Offensive Source Code
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.

245 lines
6.0 KiB

  1. // C_NextBot.cpp
  2. // Client-side implementation of Next generation bot system
  3. // Author: Michael Booth, April 2005
  4. // Copyright (c) 2005 Turtle Rock Studios, Inc. - All Rights Reserved
  5. #include "cbase.h"
  6. #include "C_NextBot.h"
  7. #include "debugoverlay_shared.h"
  8. #include <bitbuf.h>
  9. #include "viewrender.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. #undef NextBot
  13. ConVar NextBotShadowDist( "nb_shadow_dist", "400" );
  14. //-----------------------------------------------------------------------------
  15. IMPLEMENT_CLIENTCLASS_DT( C_NextBotCombatCharacter, DT_NextBot, NextBotCombatCharacter )
  16. END_RECV_TABLE()
  17. //-----------------------------------------------------------------------------
  18. C_NextBotCombatCharacter::C_NextBotCombatCharacter()
  19. {
  20. // Left4Dead have surfaces too steep for IK to work properly
  21. m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
  22. m_shadowType = SHADOWS_SIMPLE;
  23. m_forcedShadowType = SHADOWS_NONE;
  24. m_bForceShadowType = false;
  25. TheClientNextBots().Register( this );
  26. }
  27. //-----------------------------------------------------------------------------
  28. C_NextBotCombatCharacter::~C_NextBotCombatCharacter()
  29. {
  30. TheClientNextBots().UnRegister( this );
  31. }
  32. //-----------------------------------------------------------------------------
  33. void C_NextBotCombatCharacter::Spawn( void )
  34. {
  35. BaseClass::Spawn();
  36. }
  37. //-----------------------------------------------------------------------------
  38. void C_NextBotCombatCharacter::UpdateClientSideAnimation()
  39. {
  40. if (IsDormant())
  41. {
  42. return;
  43. }
  44. BaseClass::UpdateClientSideAnimation();
  45. }
  46. //--------------------------------------------------------------------------------------------------------
  47. void C_NextBotCombatCharacter::UpdateShadowLOD( void )
  48. {
  49. ShadowType_t oldShadowType = m_shadowType;
  50. if ( m_bForceShadowType )
  51. {
  52. m_shadowType = m_forcedShadowType;
  53. }
  54. else
  55. {
  56. #ifdef NEED_SPLITSCREEN_INTEGRATION
  57. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  58. {
  59. C_BasePlayer *pl = C_BasePlayer::GetLocalPlayer(hh);
  60. if ( pl )
  61. {
  62. Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer(hh)->GetAbsOrigin();
  63. #else
  64. {
  65. if ( C_BasePlayer::GetLocalPlayer() )
  66. {
  67. Vector delta = GetAbsOrigin() - C_BasePlayer::GetLocalPlayer()->GetAbsOrigin();
  68. #endif
  69. if ( delta.IsLengthLessThan( NextBotShadowDist.GetFloat() ) )
  70. {
  71. m_shadowType = SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
  72. }
  73. else
  74. {
  75. m_shadowType = SHADOWS_SIMPLE;
  76. }
  77. }
  78. else
  79. {
  80. m_shadowType = SHADOWS_SIMPLE;
  81. }
  82. }
  83. }
  84. if ( oldShadowType != m_shadowType )
  85. {
  86. DestroyShadow();
  87. }
  88. }
  89. //--------------------------------------------------------------------------------------------------------
  90. ShadowType_t C_NextBotCombatCharacter::ShadowCastType( void )
  91. {
  92. if ( !IsVisible() )
  93. return SHADOWS_NONE;
  94. if ( m_shadowTimer.IsElapsed() )
  95. {
  96. m_shadowTimer.Start( 0.15f );
  97. UpdateShadowLOD();
  98. }
  99. return m_shadowType;
  100. }
  101. //--------------------------------------------------------------------------------------------------------
  102. bool C_NextBotCombatCharacter::GetForcedShadowCastType( ShadowType_t* pForcedShadowType ) const
  103. {
  104. if ( pForcedShadowType )
  105. {
  106. *pForcedShadowType = m_forcedShadowType;
  107. }
  108. return m_bForceShadowType;
  109. }
  110. //--------------------------------------------------------------------------------------------------------
  111. /**
  112. * Singleton accessor.
  113. * By returning a reference, we guarantee construction of the
  114. * instance before its first use.
  115. */
  116. C_NextBotManager &TheClientNextBots( void )
  117. {
  118. static C_NextBotManager manager;
  119. return manager;
  120. }
  121. //--------------------------------------------------------------------------------------------------------
  122. C_NextBotManager::C_NextBotManager( void )
  123. {
  124. }
  125. //--------------------------------------------------------------------------------------------------------
  126. C_NextBotManager::~C_NextBotManager()
  127. {
  128. }
  129. //--------------------------------------------------------------------------------------------------------
  130. void C_NextBotManager::Register( C_NextBotCombatCharacter *bot )
  131. {
  132. m_botList.AddToTail( bot );
  133. }
  134. //--------------------------------------------------------------------------------------------------------
  135. void C_NextBotManager::UnRegister( C_NextBotCombatCharacter *bot )
  136. {
  137. m_botList.FindAndRemove( bot );
  138. }
  139. //-----------------------------------------------------------------------------
  140. // Purpose:
  141. //-----------------------------------------------------------------------------
  142. bool C_NextBotManager::SetupInFrustumData( void )
  143. {
  144. #ifdef ENABLE_AFTER_INTEGRATION
  145. // Done already this frame.
  146. if ( IsInFrustumDataValid() )
  147. return true;
  148. // Can we use the view data yet?
  149. if ( !FrustumCache()->IsValid() )
  150. return false;
  151. // Get the number of active bots.
  152. int nBotCount = m_botList.Count();
  153. // Reset.
  154. for ( int iBot = 0; iBot < nBotCount; ++iBot )
  155. {
  156. // Get the current bot.
  157. C_NextBotCombatCharacter *pBot = m_botList[iBot];
  158. if ( !pBot )
  159. continue;
  160. pBot->InitFrustumData();
  161. }
  162. FOR_EACH_VALID_SPLITSCREEN_PLAYER( iSlot )
  163. {
  164. ACTIVE_SPLITSCREEN_PLAYER_GUARD( iSlot );
  165. // Get the active local player.
  166. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  167. if ( !pPlayer )
  168. continue;
  169. for ( int iBot = 0; iBot < nBotCount; ++iBot )
  170. {
  171. // Get the current bot.
  172. C_NextBotCombatCharacter *pBot = m_botList[iBot];
  173. if ( !pBot )
  174. continue;
  175. // Are we in the view frustum?
  176. Vector vecMin, vecMax;
  177. pBot->CollisionProp()->WorldSpaceAABB( &vecMin, &vecMax );
  178. bool bInFrustum = !FrustumCache()->m_Frustums[iSlot].CullBox( vecMin, vecMax );
  179. if ( bInFrustum )
  180. {
  181. Vector vecSegment;
  182. VectorSubtract( pBot->GetAbsOrigin(), pPlayer->GetAbsOrigin(), vecSegment );
  183. float flDistance = vecSegment.LengthSqr();
  184. if ( flDistance < pBot->GetInFrustumDistanceSqr() )
  185. {
  186. pBot->SetInFrustumDistanceSqr( flDistance );
  187. }
  188. pBot->SetInFrustum( true );
  189. }
  190. }
  191. }
  192. // Mark as setup this frame.
  193. m_nInFrustumFrame = gpGlobals->framecount;
  194. #endif
  195. return true;
  196. }
  197. //--------------------------------------------------------------------------------------------------------