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.

513 lines
15 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "func_ladder.h"
  8. // memdbgon must be the last include file in a .cpp file!!!
  9. #include "tier0/memdbgon.h"
  10. #if !defined( CLIENT_DLL )
  11. ConVar sv_showladders( "sv_showladders", "0", 0, "Show bbox and dismount points for all ladders (must be set before level load.)\n" );
  12. #endif
  13. CUtlVector< CFuncLadder * > CFuncLadder::s_Ladders;
  14. //-----------------------------------------------------------------------------
  15. // Purpose:
  16. //-----------------------------------------------------------------------------
  17. CFuncLadder::CFuncLadder() :
  18. m_bDisabled( false )
  19. {
  20. s_Ladders.AddToTail( this );
  21. }
  22. //-----------------------------------------------------------------------------
  23. // Purpose:
  24. //-----------------------------------------------------------------------------
  25. CFuncLadder::~CFuncLadder()
  26. {
  27. s_Ladders.FindAndRemove( this );
  28. }
  29. int CFuncLadder::GetLadderCount()
  30. {
  31. return s_Ladders.Count();
  32. }
  33. CFuncLadder *CFuncLadder::GetLadder( int index )
  34. {
  35. if ( index < 0 || index >= s_Ladders.Count() )
  36. return NULL;
  37. return s_Ladders[ index ];
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Purpose:
  41. //-----------------------------------------------------------------------------
  42. void CFuncLadder::Spawn()
  43. {
  44. BaseClass::Spawn();
  45. // Entity is symbolid
  46. SetSolid( SOLID_NONE );
  47. SetMoveType( MOVETYPE_NONE );
  48. SetCollisionGroup( COLLISION_GROUP_NONE );
  49. //AddFlag( FL_WORLDBRUSH );
  50. SetModelName( NULL_STRING );
  51. // Make entity invisible
  52. AddEffects( EF_NODRAW );
  53. // No model but should still network
  54. AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
  55. Vector playerMins = VEC_HULL_MIN;
  56. Vector playerMaxs = VEC_HULL_MAX;
  57. // This will swap them if they are inverted
  58. SetEndPoints( m_vecPlayerMountPositionTop, m_vecPlayerMountPositionBottom );
  59. #if !defined( CLIENT_DLL )
  60. trace_t bottomtrace, toptrace;
  61. UTIL_TraceHull( m_vecPlayerMountPositionBottom, m_vecPlayerMountPositionBottom,
  62. playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &bottomtrace );
  63. UTIL_TraceHull( m_vecPlayerMountPositionTop, m_vecPlayerMountPositionTop,
  64. playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &toptrace );
  65. if ( bottomtrace.startsolid || toptrace.startsolid )
  66. {
  67. if ( bottomtrace.startsolid )
  68. {
  69. DevMsg( 1, "Warning, funcladder with blocked bottom point (%.2f %.2f %.2f) stuck in (%s)\n",
  70. m_vecPlayerMountPositionBottom.GetX(),
  71. m_vecPlayerMountPositionBottom.GetY(),
  72. m_vecPlayerMountPositionBottom.GetZ(),
  73. bottomtrace.m_pEnt
  74. ?
  75. UTIL_VarArgs( "%s/%s", bottomtrace.m_pEnt->GetClassname(), bottomtrace.m_pEnt->GetEntityName().ToCStr() )
  76. :
  77. "NULL" );
  78. }
  79. if ( toptrace.startsolid )
  80. {
  81. DevMsg( 1, "Warning, funcladder with blocked top point (%.2f %.2f %.2f) stuck in (%s)\n",
  82. m_vecPlayerMountPositionTop.GetX(),
  83. m_vecPlayerMountPositionTop.GetY(),
  84. m_vecPlayerMountPositionTop.GetZ(),
  85. toptrace.m_pEnt
  86. ?
  87. UTIL_VarArgs( "%s/%s", toptrace.m_pEnt->GetClassname(), toptrace.m_pEnt->GetEntityName().ToCStr() )
  88. :
  89. "NULL" );
  90. }
  91. // Force geometry overlays on, but only if developer 2 is set...
  92. if ( developer.GetInt() > 1 )
  93. {
  94. m_debugOverlays |= OVERLAY_TEXT_BIT;
  95. }
  96. }
  97. m_vecPlayerMountPositionTop -= GetAbsOrigin();
  98. m_vecPlayerMountPositionBottom -= GetAbsOrigin();
  99. // Compute mins, maxs of points
  100. //
  101. Vector mins( MAX_COORD_INTEGER, MAX_COORD_INTEGER, MAX_COORD_INTEGER );
  102. Vector maxs( -MAX_COORD_INTEGER, -MAX_COORD_INTEGER, -MAX_COORD_INTEGER );
  103. int i;
  104. for ( i = 0; i < 3; i++ )
  105. {
  106. if ( m_vecPlayerMountPositionBottom.m_Value[ i ] < mins[ i ] )
  107. {
  108. mins[ i ] = m_vecPlayerMountPositionBottom.m_Value[ i ];
  109. }
  110. if ( m_vecPlayerMountPositionBottom.m_Value[ i ] > maxs[ i ] )
  111. {
  112. maxs[ i ] = m_vecPlayerMountPositionBottom.m_Value[ i ];
  113. }
  114. if ( m_vecPlayerMountPositionTop.m_Value[ i ] < mins[ i ] )
  115. {
  116. mins[ i ] = m_vecPlayerMountPositionTop.m_Value[ i ];
  117. }
  118. if ( m_vecPlayerMountPositionTop.m_Value[ i ] > maxs[ i ] )
  119. {
  120. maxs[ i ] = m_vecPlayerMountPositionTop.m_Value[ i ];
  121. }
  122. }
  123. // Expand mins/maxs by player hull size
  124. mins += playerMins;
  125. maxs += playerMaxs;
  126. UTIL_SetSize( this, mins, maxs );
  127. m_bFakeLadder = HasSpawnFlags(SF_LADDER_DONTGETON);
  128. #endif
  129. }
  130. //-----------------------------------------------------------------------------
  131. // Purpose: Called after all entities have spawned or after reload from .sav file
  132. //-----------------------------------------------------------------------------
  133. void CFuncLadder::Activate()
  134. {
  135. // Chain to base class
  136. BaseClass::Activate();
  137. #if !defined( CLIENT_DLL )
  138. // Re-hook up ladder dismount points
  139. SearchForDismountPoints();
  140. // Show debugging UI if it's active
  141. if ( sv_showladders.GetBool() )
  142. {
  143. m_debugOverlays |= OVERLAY_TEXT_BIT;
  144. }
  145. #endif
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose:
  149. //-----------------------------------------------------------------------------
  150. void CFuncLadder::SearchForDismountPoints()
  151. {
  152. #if !defined( CLIENT_DLL )
  153. CUtlVector< CInfoLadderDismountHandle > allNodes;
  154. Vector topPos;
  155. Vector bottomPos;
  156. GetTopPosition( topPos );
  157. GetBottomPosition( bottomPos );
  158. float dismount_radius = 100.0f;
  159. Vector vecBottomToTop = topPos - bottomPos;
  160. float ladderLength = VectorNormalize( vecBottomToTop );
  161. float recheck = 40.0f;
  162. // add both sets of nodes
  163. FindNearbyDismountPoints( topPos, dismount_radius, m_Dismounts );
  164. FindNearbyDismountPoints( bottomPos, dismount_radius, m_Dismounts );
  165. while ( 1 )
  166. {
  167. ladderLength -= recheck;
  168. if ( ladderLength <= 0.0f )
  169. break;
  170. bottomPos += recheck * vecBottomToTop;
  171. FindNearbyDismountPoints( bottomPos, dismount_radius, m_Dismounts );
  172. }
  173. #endif
  174. }
  175. void CFuncLadder::SetEndPoints( const Vector& p1, const Vector& p2 )
  176. {
  177. m_vecPlayerMountPositionTop = p1;
  178. m_vecPlayerMountPositionBottom = p2;
  179. if ( m_vecPlayerMountPositionBottom.GetZ() > m_vecPlayerMountPositionTop.GetZ() )
  180. {
  181. Vector temp = m_vecPlayerMountPositionBottom;
  182. m_vecPlayerMountPositionBottom = m_vecPlayerMountPositionTop;
  183. m_vecPlayerMountPositionTop = temp;
  184. }
  185. #if !defined( CLIENT_DLL)
  186. Vector playerMins = VEC_HULL_MIN;
  187. Vector playerMaxs = VEC_HULL_MAX;
  188. trace_t result;
  189. UTIL_TraceHull( m_vecPlayerMountPositionTop + Vector( 0, 0, 4 ), m_vecPlayerMountPositionTop,
  190. playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &result );
  191. if ( !result.startsolid )
  192. {
  193. m_vecPlayerMountPositionTop = result.endpos;
  194. }
  195. UTIL_TraceHull( m_vecPlayerMountPositionBottom + Vector( 0, 0, 4 ), m_vecPlayerMountPositionBottom,
  196. playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &result );
  197. if ( !result.startsolid )
  198. {
  199. m_vecPlayerMountPositionBottom = result.endpos;
  200. }
  201. #endif
  202. }
  203. //-----------------------------------------------------------------------------
  204. // Purpose:
  205. //-----------------------------------------------------------------------------
  206. void CFuncLadder::DrawDebugGeometryOverlays()
  207. {
  208. #if !defined( CLIENT_DLL )
  209. BaseClass::DrawDebugGeometryOverlays();
  210. Vector playerMins = VEC_HULL_MIN;
  211. Vector playerMaxs = VEC_HULL_MAX;
  212. Vector topPosition;
  213. Vector bottomPosition;
  214. GetTopPosition( topPosition );
  215. GetBottomPosition( bottomPosition );
  216. NDebugOverlay::Box( topPosition, playerMins, playerMaxs, 255,0,0,127, 0 );
  217. NDebugOverlay::Box( bottomPosition, playerMins, playerMaxs, 0,0,255,127, 0 );
  218. NDebugOverlay::EntityBounds(this, 200, 180, 63, 63, 0);
  219. trace_t bottomtrace;
  220. UTIL_TraceHull( m_vecPlayerMountPositionBottom, m_vecPlayerMountPositionBottom,
  221. playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &bottomtrace );
  222. int c = m_Dismounts.Count();
  223. for ( int i = 0 ; i < c ; i++ )
  224. {
  225. CInfoLadderDismount *pt = m_Dismounts[ i ];
  226. if ( !pt )
  227. continue;
  228. NDebugOverlay::Box(pt->GetAbsOrigin(),Vector( -16, -16, 0 ), Vector( 16, 16, 8 ), 150,0,0, 63, 0);
  229. }
  230. #endif
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Purpose:
  234. // Input : org -
  235. //-----------------------------------------------------------------------------
  236. void CFuncLadder::GetTopPosition( Vector& org )
  237. {
  238. ComputeAbsPosition( m_vecPlayerMountPositionTop + GetLocalOrigin(), &org );
  239. }
  240. //-----------------------------------------------------------------------------
  241. // Purpose:
  242. // Input : org -
  243. //-----------------------------------------------------------------------------
  244. void CFuncLadder::GetBottomPosition( Vector& org )
  245. {
  246. ComputeAbsPosition( m_vecPlayerMountPositionBottom + GetLocalOrigin(), &org );
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Purpose:
  250. // Input : bottomToTopVec -
  251. //-----------------------------------------------------------------------------
  252. void CFuncLadder::ComputeLadderDir( Vector& bottomToTopVec )
  253. {
  254. Vector top;
  255. Vector bottom;
  256. GetTopPosition( top );
  257. GetBottomPosition( bottom );
  258. bottomToTopVec = top - bottom;
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Purpose:
  262. // Output : int
  263. //-----------------------------------------------------------------------------
  264. int CFuncLadder::GetDismountCount() const
  265. {
  266. return m_Dismounts.Count();
  267. }
  268. //-----------------------------------------------------------------------------
  269. // Purpose:
  270. // Input : index -
  271. // Output : CInfoLadderDismountHandle
  272. //-----------------------------------------------------------------------------
  273. CInfoLadderDismount *CFuncLadder::GetDismount( int index )
  274. {
  275. if ( index < 0 || index >= m_Dismounts.Count() )
  276. return NULL;
  277. return m_Dismounts[ index ];
  278. }
  279. //-----------------------------------------------------------------------------
  280. // Purpose:
  281. // Input : origin -
  282. // radius -
  283. // list -
  284. //-----------------------------------------------------------------------------
  285. void CFuncLadder::FindNearbyDismountPoints( const Vector& origin, float radius, CUtlVector< CInfoLadderDismountHandle >& list )
  286. {
  287. #if !defined( CLIENT_DLL )
  288. CBaseEntity *pEntity = NULL;
  289. while ( (pEntity = gEntList.FindEntityByClassnameWithin( pEntity, "info_ladder_dismount", origin, radius)) != NULL )
  290. {
  291. CInfoLadderDismount *landingspot = static_cast< CInfoLadderDismount * >( pEntity );
  292. Assert( landingspot );
  293. // If spot has a target, then if the target is not this ladder, don't add to our list.
  294. if ( landingspot->m_target != NULL_STRING )
  295. {
  296. if ( landingspot->GetNextTarget() != this )
  297. {
  298. continue;
  299. }
  300. }
  301. CInfoLadderDismountHandle handle;
  302. handle = landingspot;
  303. if ( list.Find( handle ) == list.InvalidIndex() )
  304. {
  305. list.AddToTail( handle );
  306. }
  307. }
  308. #endif
  309. }
  310. //-----------------------------------------------------------------------------
  311. // Purpose:
  312. // Input : &inputdata -
  313. //-----------------------------------------------------------------------------
  314. void CFuncLadder::InputEnable( inputdata_t &inputdata )
  315. {
  316. m_bDisabled = false;
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Purpose:
  320. // Input : &inputdata -
  321. //-----------------------------------------------------------------------------
  322. void CFuncLadder::InputDisable( inputdata_t &inputdata )
  323. {
  324. m_bDisabled = true;
  325. }
  326. //-----------------------------------------------------------------------------
  327. // Purpose:
  328. // Input : *pPlayer -
  329. //-----------------------------------------------------------------------------
  330. void CFuncLadder::PlayerGotOn( CBasePlayer *pPlayer )
  331. {
  332. #if !defined( CLIENT_DLL )
  333. m_OnPlayerGotOnLadder.FireOutput(this, pPlayer);
  334. pPlayer->EmitSound( "Ladder.StepRight" );
  335. #endif
  336. }
  337. //-----------------------------------------------------------------------------
  338. // Purpose:
  339. // Input : *pPlayer -
  340. //-----------------------------------------------------------------------------
  341. void CFuncLadder::PlayerGotOff( CBasePlayer *pPlayer )
  342. {
  343. #if !defined( CLIENT_DLL )
  344. m_OnPlayerGotOffLadder.FireOutput(this, pPlayer);
  345. #endif
  346. }
  347. //-----------------------------------------------------------------------------
  348. // Purpose:
  349. // Output : Returns true on success, false on failure.
  350. //-----------------------------------------------------------------------------
  351. bool CFuncLadder::DontGetOnLadder( void ) const
  352. {
  353. return m_bFakeLadder;
  354. }
  355. #if !defined(CLIENT_DLL)
  356. const char *CFuncLadder::GetSurfacePropName()
  357. {
  358. if ( !m_surfacePropName )
  359. return NULL;
  360. return m_surfacePropName.ToCStr();
  361. }
  362. #endif
  363. IMPLEMENT_NETWORKCLASS_ALIASED( FuncLadder, DT_FuncLadder );
  364. BEGIN_NETWORK_TABLE( CFuncLadder, DT_FuncLadder )
  365. #if !defined( CLIENT_DLL )
  366. SendPropVector( SENDINFO( m_vecPlayerMountPositionTop ), SPROP_COORD ),
  367. SendPropVector( SENDINFO( m_vecPlayerMountPositionBottom ), SPROP_COORD ),
  368. SendPropVector( SENDINFO( m_vecLadderDir ), SPROP_COORD ),
  369. SendPropBool( SENDINFO( m_bFakeLadder ) ),
  370. // SendPropStringT( SENDINFO(m_surfacePropName) ),
  371. #else
  372. RecvPropVector( RECVINFO( m_vecPlayerMountPositionTop ) ),
  373. RecvPropVector( RECVINFO( m_vecPlayerMountPositionBottom )),
  374. RecvPropVector( RECVINFO( m_vecLadderDir )),
  375. RecvPropBool( RECVINFO( m_bFakeLadder ) ),
  376. #endif
  377. END_NETWORK_TABLE()
  378. LINK_ENTITY_TO_CLASS_ALIASED( func_useableladder, FuncLadder );
  379. //---------------------------------------------------------
  380. // Save/Restore
  381. //---------------------------------------------------------
  382. BEGIN_DATADESC( CFuncLadder )
  383. DEFINE_KEYFIELD( m_vecPlayerMountPositionTop, FIELD_VECTOR, "point0" ),
  384. DEFINE_KEYFIELD( m_vecPlayerMountPositionBottom, FIELD_VECTOR, "point1" ),
  385. DEFINE_FIELD( m_vecLadderDir, FIELD_VECTOR ),
  386. // DEFINE_FIELD( m_Dismounts, FIELD_UTLVECTOR ),
  387. DEFINE_FIELD( m_bFakeLadder, FIELD_BOOLEAN ),
  388. DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
  389. #if !defined( CLIENT_DLL )
  390. DEFINE_KEYFIELD( m_surfacePropName,FIELD_STRING, "ladderSurfaceProperties" ),
  391. DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
  392. DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
  393. DEFINE_OUTPUT( m_OnPlayerGotOnLadder, "OnPlayerGotOnLadder" ),
  394. DEFINE_OUTPUT( m_OnPlayerGotOffLadder, "OnPlayerGotOffLadder" ),
  395. #endif
  396. END_DATADESC()
  397. //-----------------------------------------------------------------------------
  398. // Purpose:
  399. //-----------------------------------------------------------------------------
  400. void CInfoLadderDismount::DrawDebugGeometryOverlays()
  401. {
  402. #if !defined( CLIENT_DLL )
  403. BaseClass::DrawDebugGeometryOverlays();
  404. if ( developer.GetBool() )
  405. {
  406. NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, 0 ), Vector( 16, 16, 8 ), 127, 127, 127, 127, 0 );
  407. }
  408. #endif
  409. }
  410. #if defined( GAME_DLL )
  411. int CFuncLadder::UpdateTransmitState()
  412. {
  413. // transmit if in PVS for clientside prediction
  414. return SetTransmitState( FL_EDICT_PVSCHECK );
  415. }
  416. #endif
  417. IMPLEMENT_NETWORKCLASS_ALIASED( InfoLadderDismount, DT_InfoLadderDismount );
  418. BEGIN_NETWORK_TABLE( CInfoLadderDismount, DT_InfoLadderDismount )
  419. END_NETWORK_TABLE()
  420. LINK_ENTITY_TO_CLASS_ALIASED( info_ladder_dismount, InfoLadderDismount );
  421. #if defined(GAME_DLL)
  422. const char *FuncLadder_GetSurfaceprops(CBaseEntity *pLadderEntity)
  423. {
  424. CFuncLadder *pLadder = dynamic_cast<CFuncLadder *>(pLadderEntity);
  425. if ( pLadder )
  426. {
  427. if ( pLadder->GetSurfacePropName() )
  428. return pLadder->GetSurfacePropName();
  429. }
  430. return "ladder";
  431. }
  432. #endif