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.

3953 lines
127 KiB

  1. //========= Copyright (c) Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Client handler implementations for instruction players how to play
  4. //
  5. //============================================================================//
  6. #include "cbase.h"
  7. #include "c_baselesson.h"
  8. #include "c_gameinstructor.h"
  9. #include "hud_locator_target.h"
  10. #include "c_world.h"
  11. #include "iinput.h"
  12. #include "ammodef.h"
  13. #include "vprof.h"
  14. #include "view.h"
  15. #include "vstdlib/ikeyvaluessystem.h"
  16. #ifdef INFESTED_DLL
  17. #include "c_asw_marine.h"
  18. #include "c_asw_marine_resource.h"
  19. #endif
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. #define LESSON_PRIORITY_MAX 1000
  23. #define LESSON_PRIORITY_NONE 0
  24. #define LESSON_MIN_TIME_ON_SCREEN_TO_MARK_DISPLAYED 1.5f
  25. #define LESSON_MIN_TIME_BEFORE_LOCK_ALLOWED 0.1f
  26. #define LESSON_DISTANCE_UPDATE_RATE 0.25f
  27. // See comments in UtlSymbol on why this is useful and how it works
  28. IMPLEMENT_PRIVATE_SYMBOLTYPE( CGameInstructorSymbol );
  29. extern ConVar gameinstructor_verbose;
  30. extern ConVar gameinstructor_verbose_lesson;
  31. extern ConVar gameinstructor_find_errors;
  32. //
  33. // CGameInstructorLesson
  34. //
  35. Color CBaseLesson::m_rgbaVerboseHeader = Color( 255, 128, 64, 255 );
  36. Color CBaseLesson::m_rgbaVerbosePlain = Color( 64, 128, 255, 255 );
  37. Color CBaseLesson::m_rgbaVerboseName = Color( 255, 255, 255, 255 );
  38. Color CBaseLesson::m_rgbaVerboseOpen = Color( 0, 255, 0, 255 );
  39. Color CBaseLesson::m_rgbaVerboseClose = Color( 255, 0, 0, 255 );
  40. Color CBaseLesson::m_rgbaVerboseSuccess = Color( 255, 255, 0, 255 );
  41. Color CBaseLesson::m_rgbaVerboseUpdate = Color( 255, 0, 255, 255 );
  42. CBaseLesson::CBaseLesson( const char *pchName, bool bIsDefaultHolder, bool bIsOpenOpportunity, int nSplitScreenSlot )
  43. {
  44. COMPILE_TIME_ASSERT( sizeof( CGameInstructorSymbol ) == sizeof( CUtlSymbol ) );
  45. m_nSplitScreenSlot = nSplitScreenSlot;
  46. m_stringName = pchName;
  47. m_stringReplaceKey = "";
  48. m_bIsDefaultHolder = bIsDefaultHolder;
  49. m_bIsOpenOpportunity = bIsOpenOpportunity;
  50. Init();
  51. }
  52. CBaseLesson::~CBaseLesson( void )
  53. {
  54. if ( m_pRoot )
  55. {
  56. // Remove from root's children list
  57. m_pRoot->m_OpenOpportunities.FindAndRemove( this );
  58. }
  59. else
  60. {
  61. for ( int i = 0; i < m_OpenOpportunities.Count(); ++i )
  62. {
  63. // Remove from children if they are still around
  64. CBaseLesson *pLesson = m_OpenOpportunities[ i ];
  65. pLesson->m_pRoot = NULL;
  66. }
  67. }
  68. }
  69. void CBaseLesson::AddPrerequisite( const char *pchLessonName )
  70. {
  71. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  72. {
  73. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "\t%s: ", GetName() );
  74. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Adding prereq " );
  75. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\"", pchLessonName );
  76. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ".\n" );
  77. }
  78. const CBaseLesson *pPrerequisite = GetGameInstructor().GetLesson( pchLessonName );
  79. if ( !pPrerequisite )
  80. {
  81. DevWarning( "Prerequisite %s added by lesson %s doesn't exist!\n", pchLessonName, GetName() );
  82. return;
  83. }
  84. m_Prerequisites.AddToTail( pPrerequisite );
  85. }
  86. void CBaseLesson::SetRoot( CBaseLesson *pRoot )
  87. {
  88. m_pRoot = pRoot;
  89. if ( m_pRoot && m_pRoot->m_OpenOpportunities.Find( this ) == -1 )
  90. {
  91. m_pRoot->m_OpenOpportunities.AddToTail( this );
  92. }
  93. }
  94. bool CBaseLesson::ShouldShowSpew( void )
  95. {
  96. if ( gameinstructor_verbose_lesson.GetString()[ 0 ] == '\0' )
  97. return false;
  98. return ( Q_stristr( GetName(), gameinstructor_verbose_lesson.GetString() ) != NULL );
  99. }
  100. bool CBaseLesson::NoPriority( void ) const
  101. {
  102. return ( m_iPriority == LESSON_PRIORITY_NONE );
  103. }
  104. bool CBaseLesson::IsLocked( void ) const
  105. {
  106. if ( m_fLockDuration == 0.0f )
  107. return false;
  108. if ( !IsInstructing() || !IsVisible() )
  109. return false;
  110. float fLockTime = m_fLockTime;
  111. if ( fLockTime == 0.0f )
  112. {
  113. fLockTime = m_fStartTime;
  114. }
  115. return ( gpGlobals->curtime > m_fStartTime + LESSON_MIN_TIME_BEFORE_LOCK_ALLOWED && gpGlobals->curtime < fLockTime + m_fLockDuration );
  116. }
  117. bool CBaseLesson::IsLearned( void ) const
  118. {
  119. if ( m_iDisplayLimit > 0 && m_iDisplayCount >= m_iDisplayLimit )
  120. return true;
  121. if ( m_iSuccessLimit > 0 && m_iSuccessCount >= m_iSuccessLimit )
  122. return true;
  123. return false;
  124. }
  125. bool CBaseLesson::PrerequisitesHaveBeenMet( void ) const
  126. {
  127. for ( int i = 0; i < m_Prerequisites.Count(); ++i )
  128. {
  129. if ( !m_Prerequisites[ i ]->IsLearned() )
  130. {
  131. // Failed a prereq
  132. return false;
  133. }
  134. }
  135. // All prereqs passed
  136. return true;
  137. }
  138. bool CBaseLesson::IsTimedOut( void )
  139. {
  140. VPROF_BUDGET( "CBaseLesson::IsTimedOut", "GameInstructor" );
  141. // Check for no timeout
  142. if ( m_fTimeout == 0.0f )
  143. return false;
  144. float fStartTime = m_fStartTime;
  145. if ( GetRoot()->IsLearned() )
  146. {
  147. if ( !m_bBumpWithTimeoutWhenLearned )
  148. {
  149. // Time out instantly if we've learned this and don't want to keep it open for priority bumping
  150. return true;
  151. }
  152. else
  153. {
  154. // It'll never be active, so lets use timeout based on when it was initialized
  155. fStartTime = m_fInitTime;
  156. }
  157. }
  158. if ( !fStartTime )
  159. {
  160. if ( !m_bCanTimeoutWhileInactive )
  161. {
  162. return false;
  163. }
  164. // Not active, so lets use timeout based on when it was initialized
  165. fStartTime = m_fInitTime;
  166. }
  167. bool bTimedOut = ( fStartTime + m_fTimeout < gpGlobals->curtime );
  168. if ( bTimedOut )
  169. {
  170. SetCloseReason( "Timed out." );
  171. }
  172. return bTimedOut;
  173. }
  174. void CBaseLesson::ResetDisplaysAndSuccesses( void )
  175. {
  176. m_iDisplayCount = 0;
  177. m_bSuccessCounted = false;
  178. m_iSuccessCount = 0;
  179. }
  180. bool CBaseLesson::IncDisplayCount( void )
  181. {
  182. if ( m_iDisplayCount < m_iDisplayLimit )
  183. {
  184. m_iDisplayCount++;
  185. return true;
  186. }
  187. return false;
  188. }
  189. bool CBaseLesson::IncSuccessCount( void )
  190. {
  191. if ( m_iSuccessCount < m_iSuccessLimit )
  192. {
  193. m_iSuccessCount++;
  194. return true;
  195. }
  196. return false;
  197. }
  198. void CBaseLesson::Init( void )
  199. {
  200. m_pRoot = NULL;
  201. m_bSuccessCounted = false;
  202. SetCloseReason( "None given." );
  203. m_iPriority = LESSON_PRIORITY_MAX; // Set to invalid value to ensure that it is actually set later on
  204. m_iInstanceType = LESSON_INSTANCE_MULTIPLE;
  205. m_iFixedInstancesMax = 1;
  206. m_bReplaceOnlyWhenStopped = false;
  207. m_iTeam = TEAM_ANY;
  208. m_bOnlyKeyboard = false;
  209. m_bOnlyGamepad = false;
  210. m_bNoSplitscreen = false;
  211. m_iDisplayLimit = 0;
  212. m_iDisplayCount = 0;
  213. m_bWasDisplayed = false;
  214. m_iSuccessLimit = 0;
  215. m_iSuccessCount = 0;
  216. m_fLockDuration = 0.0f;
  217. m_bCanOpenWhenDead = false;
  218. m_bBumpWithTimeoutWhenLearned = false;
  219. m_bOnceLearnedNeverOpen = false;
  220. m_bCanTimeoutWhileInactive = false;
  221. m_bUsableInMidair = false;
  222. m_fTimeout = 0.0f;
  223. m_fInitTime = gpGlobals->curtime;
  224. m_fStartTime = 0.0f;
  225. m_fLockTime = 0.0f;
  226. m_fUpdateInterval = 0.5;
  227. m_bHasPlayedSound = false;
  228. m_szStartSound = "Instructor.LessonStart";
  229. m_szLessonGroup = "";
  230. m_iNumDelayedPlayerSwaps = 0;
  231. }
  232. void CBaseLesson::TakePlaceOf( CBaseLesson *pLesson )
  233. {
  234. // Transfer over marked as displayed so a replaced lesson won't count as an extra display
  235. m_bWasDisplayed = pLesson->m_bWasDisplayed;
  236. pLesson->m_bWasDisplayed = false;
  237. }
  238. void CBaseLesson::MarkSucceeded( void )
  239. {
  240. if ( !m_bSuccessCounted )
  241. {
  242. GetGameInstructor().MarkSucceeded( GetName() );
  243. m_bSuccessCounted = true;
  244. }
  245. }
  246. void CBaseLesson::CloseOpportunity( const char *pchReason )
  247. {
  248. SetCloseReason( pchReason );
  249. m_bIsOpenOpportunity = false;
  250. }
  251. bool CBaseLesson::DoDelayedPlayerSwaps( void ) const
  252. {
  253. // A bot has swapped places with a player or player with a bot...
  254. // At the time of the actual swap there was no client representation for the new player...
  255. // So that swap was queued up and now we're going to make things right!
  256. while ( m_iNumDelayedPlayerSwaps )
  257. {
  258. C_BasePlayer *pNewPlayer = UTIL_PlayerByUserId( m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps - 1 ].iNewUserID );
  259. if ( !pNewPlayer )
  260. {
  261. // There is still no client representation of the new player, we'll have to try again later
  262. if ( gameinstructor_verbose.GetInt() > 1 )
  263. {
  264. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tFailed delayed player swap!" );
  265. }
  266. return false;
  267. }
  268. if ( gameinstructor_verbose.GetInt() > 1 )
  269. {
  270. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tSuccessful delayed player swap!" );
  271. }
  272. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps - 1 ].phHandleToChange->Set( pNewPlayer );
  273. m_iNumDelayedPlayerSwaps--;
  274. }
  275. return true;
  276. }
  277. //
  278. // CTextLesson
  279. //
  280. void CTextLesson::Init( void )
  281. {
  282. m_szDisplayText = "";
  283. m_szDisplayParamText = "";
  284. m_szBinding = "";
  285. m_szGamepadBinding = "";
  286. }
  287. void CTextLesson::Start( void )
  288. {
  289. // TODO: Display some text
  290. //m_szDisplayText
  291. }
  292. void CTextLesson::Stop( void )
  293. {
  294. // TODO: Clean up text
  295. }
  296. //
  297. // CIconLesson
  298. //
  299. void CIconLesson::Init( void )
  300. {
  301. m_hIconTarget = NULL;
  302. m_szVguiTargetName = "";
  303. m_szVguiTargetLookup = "";
  304. m_nVguiTargetEdge = 0;
  305. m_hLocatorTarget = -1;
  306. m_bFixedPosition = false;
  307. m_bNoIconTarget = false;
  308. m_bAllowNodrawTarget = false;
  309. m_bVisible = true;
  310. m_bShowWhenOccluded = true;
  311. m_bNoOffscreen = false;
  312. m_bForceCaption = false;
  313. m_szOnscreenIcon = "";
  314. m_szOffscreenIcon = "";
  315. m_flUpOffset = 0.0f;
  316. m_flRelativeUpOffset = 0.0f;
  317. m_fFixedPositionX = 0.0f;
  318. m_fFixedPositionY = 0.0f;
  319. m_fRange = 0.0f;
  320. m_fCurrentDistance = 0.0f;
  321. m_fOnScreenStartTime = 0.0f;
  322. m_fUpdateDistanceTime = 0.0f;
  323. m_iFlags = LOCATOR_ICON_FX_NONE;
  324. m_szCaptionColor = "255,255,255";// Default to white
  325. }
  326. void CIconLesson::Start( void )
  327. {
  328. if ( !DoDelayedPlayerSwaps() )
  329. {
  330. return;
  331. }
  332. // Display some text
  333. C_BaseEntity *pIconTarget = m_hIconTarget.Get();
  334. if ( !pIconTarget )
  335. {
  336. if ( !m_bNoIconTarget )
  337. {
  338. // Wanted one, but couldn't get it
  339. CloseOpportunity( "Icon Target handle went invalid before the lesson started!" );
  340. }
  341. return;
  342. }
  343. else
  344. {
  345. if ( ( pIconTarget->IsEffectActive( EF_NODRAW ) || pIconTarget->IsDormant() ) && !m_bAllowNodrawTarget )
  346. {
  347. // We don't allow no draw entities
  348. CloseOpportunity( "Icon Target is using effect NODRAW and allow_nodraw_target is false!" );
  349. return;
  350. }
  351. }
  352. CLocatorTarget *pLocatorTarget = NULL;
  353. if( m_hLocatorTarget != -1 )
  354. {
  355. // Lets try the handle that we've held on to
  356. pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  357. if ( !pLocatorTarget )
  358. {
  359. // It's gone stale, get a new target
  360. m_hLocatorTarget = Locator_AddTarget();
  361. pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  362. }
  363. }
  364. else
  365. {
  366. // Get a new target
  367. m_hLocatorTarget = Locator_AddTarget();
  368. pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  369. }
  370. if( m_hLocatorTarget == -1 || !pLocatorTarget )
  371. {
  372. CloseOpportunity( "Could not get a handle for new locator target. Too many targets in use!" );
  373. return;
  374. }
  375. pLocatorTarget->AddIconEffects( m_iFlags );
  376. pLocatorTarget->SetCaptionColor( GetCaptionColorString() );
  377. pLocatorTarget->SetIconNoTarget( m_bNoIconTarget );
  378. UpdateLocatorTarget( pLocatorTarget, pIconTarget );
  379. // Update occlusion data
  380. Locator_ComputeTargetIconPositionFromHandle( m_hLocatorTarget );
  381. }
  382. void CIconLesson::Stop( void )
  383. {
  384. if ( !DoDelayedPlayerSwaps() )
  385. {
  386. return;
  387. }
  388. if ( m_hLocatorTarget != -1 )
  389. {
  390. Locator_RemoveTarget( m_hLocatorTarget );
  391. }
  392. m_fOnScreenStartTime = 0.0f;
  393. }
  394. void CIconLesson::Update( void )
  395. {
  396. if ( !DoDelayedPlayerSwaps() )
  397. {
  398. return;
  399. }
  400. C_BaseEntity *pIconTarget = m_hIconTarget.Get();
  401. if ( !pIconTarget )
  402. {
  403. if ( !m_bNoIconTarget )
  404. {
  405. CloseOpportunity( "Lost our icon target handle returned NULL." );
  406. }
  407. return;
  408. }
  409. else
  410. {
  411. if ( ( pIconTarget->IsEffectActive( EF_NODRAW ) || pIconTarget->IsDormant() ) && !m_bAllowNodrawTarget )
  412. {
  413. // We don't allow no draw entities
  414. CloseOpportunity( "Icon Target is using effect NODRAW and allow_nodraw_target is false!" );
  415. return;
  416. }
  417. }
  418. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  419. if ( !pLocatorTarget )
  420. {
  421. // Temp instrumentation to catch a bug - possibly calling Update without having called Start?
  422. Warning( "Problem in lesson %s: Locator_GetTargetFromHandle returned null for handle %d.\n IsInstanceActive: %s. IsInstructing: %s. IsLearned: %s\n",
  423. GetName(), m_hLocatorTarget,
  424. (IsInstanceActive() ? "yes" : "no"),
  425. (IsInstructing() ? "yes" : "no"),
  426. (IsLearned() ? "yes" : "no") );
  427. CloseOpportunity( "Lost locator target handle." );
  428. return;
  429. }
  430. UpdateLocatorTarget( pLocatorTarget, pIconTarget );
  431. C_BasePlayer *pLocalPlayer = GetGameInstructor().GetLocalPlayer();
  432. // Check if it has been onscreen long enough to count as being displayed
  433. if ( m_fOnScreenStartTime == 0.0f )
  434. {
  435. if ( pLocatorTarget->IsOnScreen() && ( IsPresentComplete() || ( pLocatorTarget->GetIconEffectsFlags() & LOCATOR_ICON_FX_STATIC ) ) )
  436. {
  437. // Is either static or has finished presenting and is on screen
  438. m_fOnScreenStartTime = gpGlobals->curtime;
  439. }
  440. }
  441. else
  442. {
  443. if ( !pLocatorTarget->IsOnScreen() )
  444. {
  445. // Was visible before, but it isn't now
  446. m_fOnScreenStartTime = 0.0f;
  447. }
  448. else if ( gpGlobals->curtime - m_fOnScreenStartTime >= LESSON_MIN_TIME_ON_SCREEN_TO_MARK_DISPLAYED )
  449. {
  450. // Lesson on screen long enough to be counted as displayed
  451. m_bWasDisplayed = true;
  452. }
  453. }
  454. if ( m_fUpdateDistanceTime < gpGlobals->curtime )
  455. {
  456. // Update it's distance from the local player
  457. C_BaseEntity *pTarget = m_hIconTarget.Get();
  458. if ( !pLocalPlayer || !pTarget || pLocalPlayer == pTarget )
  459. {
  460. m_fCurrentDistance = 0.0f;
  461. }
  462. else
  463. {
  464. m_fCurrentDistance = pLocalPlayer->ActivePlayerCombatCharacter()->EyePosition().DistTo( pTarget->WorldSpaceCenter() );
  465. }
  466. m_fUpdateDistanceTime = gpGlobals->curtime + LESSON_DISTANCE_UPDATE_RATE;
  467. }
  468. }
  469. void CIconLesson::UpdateInactive( void )
  470. {
  471. if ( m_fUpdateDistanceTime < gpGlobals->curtime )
  472. {
  473. if ( !DoDelayedPlayerSwaps() )
  474. {
  475. return;
  476. }
  477. C_BaseEntity *pIconTarget = m_hIconTarget.Get();
  478. if ( !pIconTarget )
  479. {
  480. if ( !m_bNoIconTarget )
  481. {
  482. CloseOpportunity( "Lost our icon target handle returned NULL." );
  483. }
  484. m_fCurrentDistance = 0.0f;
  485. return;
  486. }
  487. else
  488. {
  489. if ( ( pIconTarget->IsEffectActive( EF_NODRAW ) || pIconTarget->IsDormant() ) && !m_bAllowNodrawTarget )
  490. {
  491. // We don't allow no draw entities
  492. CloseOpportunity( "Icon Target is using effect NODRAW and allow_nodraw_target is false!" );
  493. return;
  494. }
  495. }
  496. // Update it's distance from the local player
  497. C_BasePlayer *pLocalPlayer = GetGameInstructor().GetLocalPlayer();
  498. if ( !pLocalPlayer || pLocalPlayer == pIconTarget )
  499. {
  500. m_fCurrentDistance = 0.0f;
  501. }
  502. else
  503. {
  504. m_fCurrentDistance = pLocalPlayer->ActivePlayerCombatCharacter()->EyePosition().DistTo( pIconTarget->WorldSpaceCenter() );
  505. }
  506. m_fUpdateDistanceTime = gpGlobals->curtime + LESSON_DISTANCE_UPDATE_RATE;
  507. }
  508. }
  509. bool CIconLesson::ShouldDisplay( void ) const
  510. {
  511. VPROF_BUDGET( "CIconLesson::ShouldDisplay", "GameInstructor" );
  512. if ( !DoDelayedPlayerSwaps() )
  513. {
  514. return false;
  515. }
  516. if ( m_fRange > 0.0f && m_fCurrentDistance > m_fRange )
  517. {
  518. // Distance to target is more than the max range
  519. return false;
  520. }
  521. if ( !m_bShowWhenOccluded && m_hLocatorTarget >= 0 )
  522. {
  523. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  524. if ( pLocatorTarget && pLocatorTarget->IsOccluded() )
  525. {
  526. // Target is occluded and doesn't want to be shown when occluded
  527. return false;
  528. }
  529. }
  530. C_BasePlayer *pLocalPlayer = GetGameInstructor().GetLocalPlayer();
  531. if ( !IsUsableInMidair() )
  532. {
  533. if ( !pLocalPlayer )
  534. {
  535. return false;
  536. }
  537. else
  538. {
  539. float flAirTime = pLocalPlayer->GetAirTime();
  540. if ( flAirTime > 0.75f )
  541. {
  542. return false;
  543. }
  544. }
  545. }
  546. // Ok to display
  547. return true;
  548. }
  549. bool CIconLesson::IsVisible( void ) const
  550. {
  551. VPROF_BUDGET( "CIconLesson::IsVisible", "GameInstructor" );
  552. if( m_hLocatorTarget == -1 )
  553. {
  554. // If it doesn't want a target, it's "visible" otherwise we'll have to call it invisible
  555. return m_bNoIconTarget;
  556. }
  557. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  558. if ( !pLocatorTarget )
  559. {
  560. return false;
  561. }
  562. return pLocatorTarget->IsVisible();
  563. }
  564. void CIconLesson::SwapOutPlayers( int iOldUserID, int iNewUserID )
  565. {
  566. BaseClass::SwapOutPlayers( iOldUserID, iNewUserID );
  567. if ( m_bNoIconTarget )
  568. return;
  569. // Get the player pointers from the user IDs
  570. C_BasePlayer *pOldPlayer = UTIL_PlayerByUserId( iOldUserID );
  571. C_BasePlayer *pNewPlayer = UTIL_PlayerByUserId( iNewUserID );
  572. if ( pOldPlayer == m_hIconTarget.Get() )
  573. {
  574. if ( pNewPlayer )
  575. {
  576. m_hIconTarget = pNewPlayer;
  577. }
  578. else
  579. {
  580. if ( m_iNumDelayedPlayerSwaps < MAX_DELAYED_PLAYER_SWAPS )
  581. {
  582. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps ].phHandleToChange = &m_hIconTarget;
  583. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps ].iNewUserID = iNewUserID;
  584. ++m_iNumDelayedPlayerSwaps;
  585. }
  586. }
  587. }
  588. }
  589. void CIconLesson::TakePlaceOf( CBaseLesson *pLesson )
  590. {
  591. BaseClass::TakePlaceOf( pLesson );
  592. const CIconLesson *pIconLesson = dynamic_cast<const CIconLesson*>( pLesson );
  593. if ( pIconLesson )
  594. {
  595. if ( pIconLesson->m_hLocatorTarget != -1 )
  596. {
  597. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( pIconLesson->m_hLocatorTarget );
  598. if ( pLocatorTarget )
  599. {
  600. // This one draw right to the hud... use it's icon target handle
  601. m_hLocatorTarget = pIconLesson->m_hLocatorTarget;
  602. }
  603. }
  604. m_fOnScreenStartTime = pIconLesson->m_fOnScreenStartTime;
  605. }
  606. }
  607. void CIconLesson::SetLocatorBinding( CLocatorTarget * pLocatorTarget )
  608. {
  609. if ( IsGameConsole() || input->ControllerModeActive() )
  610. {
  611. // Try to use gamepad bindings first
  612. if ( m_szGamepadBinding.String()[ 0 ] != '\0' )
  613. {
  614. // Found gamepad binds!
  615. pLocatorTarget->SetBinding( m_szGamepadBinding.String() );
  616. }
  617. else
  618. {
  619. // No gamepad binding, so fallback to the regular binding
  620. pLocatorTarget->SetBinding( m_szBinding.String() );
  621. }
  622. }
  623. else
  624. {
  625. // Always use the regular binding when the gamepad is disabled
  626. pLocatorTarget->SetBinding( m_szBinding.String() );
  627. }
  628. }
  629. bool CIconLesson::IsPresentComplete( void )
  630. {
  631. if ( m_hLocatorTarget == -1 )
  632. return false;
  633. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  634. if ( !pLocatorTarget )
  635. return false;
  636. return !pLocatorTarget->IsPresenting();
  637. }
  638. void CIconLesson::PresentStart( void )
  639. {
  640. if ( m_hLocatorTarget == -1 )
  641. return;
  642. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  643. if ( !pLocatorTarget )
  644. return;
  645. pLocatorTarget->StartPresent();
  646. }
  647. void CIconLesson::PresentEnd( void )
  648. {
  649. if ( m_hLocatorTarget == -1 )
  650. return;
  651. CLocatorTarget *pLocatorTarget = Locator_GetTargetFromHandle( m_hLocatorTarget );
  652. if ( !pLocatorTarget )
  653. return;
  654. pLocatorTarget->EndPresent();
  655. }
  656. void CIconLesson::UpdateLocatorTarget( CLocatorTarget *pLocatorTarget, C_BaseEntity *pIconTarget )
  657. {
  658. if ( m_bFixedPosition )
  659. {
  660. pLocatorTarget->m_bOriginInScreenspace = true;
  661. pLocatorTarget->m_vecOrigin.x = m_fFixedPositionX;
  662. pLocatorTarget->m_vecOrigin.y = m_fFixedPositionY;
  663. pLocatorTarget->SetVguiTargetName( m_szVguiTargetName.String() );
  664. pLocatorTarget->SetVguiTargetLookup( m_szVguiTargetLookup.String() );
  665. pLocatorTarget->SetVguiTargetEdge( m_nVguiTargetEdge );
  666. }
  667. else
  668. {
  669. pLocatorTarget->m_bOriginInScreenspace = false;
  670. pLocatorTarget->m_vecOrigin = pIconTarget->EyePosition() + MainViewUp( 0 ) * m_flRelativeUpOffset + Vector( 0.0f, 0.0f, m_flUpOffset );
  671. pLocatorTarget->SetVguiTargetName( "" );
  672. }
  673. const char *pchDisplayParamText = m_szDisplayParamText.String();
  674. #ifdef INFESTED_DLL
  675. char szCustomName[ 256 ];
  676. #endif
  677. // Check if the parameter is the be the player display name
  678. if ( Q_stricmp( pchDisplayParamText, "use_name" ) == 0 )
  679. {
  680. // Fix up the player display name
  681. C_BasePlayer *pPlayer = ToBasePlayer( pIconTarget );
  682. if ( pPlayer )
  683. {
  684. pchDisplayParamText = pPlayer->GetPlayerName();
  685. }
  686. else
  687. {
  688. bool bNoName = true;
  689. #ifdef INFESTED_DLL
  690. C_ASW_Marine *pMarine = dynamic_cast< C_ASW_Marine* >( pIconTarget );
  691. if ( pMarine )
  692. {
  693. C_ASW_Marine_Resource *pMR = pMarine->GetMarineResource();
  694. if ( pMR )
  695. {
  696. pMR->GetDisplayName( szCustomName, sizeof( szCustomName ) );
  697. pchDisplayParamText = szCustomName;
  698. bNoName = false;
  699. }
  700. }
  701. #endif
  702. if ( bNoName )
  703. {
  704. // It's not a player!
  705. pchDisplayParamText = "";
  706. }
  707. }
  708. }
  709. pLocatorTarget->SetCaptionText( m_szDisplayText.String(), pchDisplayParamText );
  710. SetLocatorBinding( pLocatorTarget );
  711. pLocatorTarget->SetOnscreenIconTextureName( m_szOnscreenIcon.String() );
  712. pLocatorTarget->SetOffscreenIconTextureName( m_szOffscreenIcon.String() );
  713. pLocatorTarget->SetVisible( m_bVisible );
  714. C_BasePlayer *pLocalPlayer = GetGameInstructor().GetLocalPlayer();
  715. if( !m_bFixedPosition &&
  716. ( ( pLocalPlayer != NULL && pLocalPlayer == m_hIconTarget ) ||
  717. GetClientWorldEntity() == m_hIconTarget ) )
  718. {
  719. // Mark this icon as a static icon that draws in a fixed
  720. // location on the hud rather than tracking an object
  721. // in 3D space.
  722. pLocatorTarget->AddIconEffects( LOCATOR_ICON_FX_STATIC );
  723. }
  724. else
  725. {
  726. pLocatorTarget->AddIconEffects( LOCATOR_ICON_FX_NONE );
  727. }
  728. if ( m_bNoOffscreen )
  729. {
  730. pLocatorTarget->AddIconEffects( LOCATOR_ICON_FX_NO_OFFSCREEN );
  731. }
  732. else
  733. {
  734. pLocatorTarget->RemoveIconEffects( LOCATOR_ICON_FX_NO_OFFSCREEN );
  735. }
  736. if( m_bForceCaption || IsLocked() )
  737. {
  738. pLocatorTarget->AddIconEffects( LOCATOR_ICON_FX_FORCE_CAPTION );
  739. }
  740. else
  741. {
  742. pLocatorTarget->RemoveIconEffects( LOCATOR_ICON_FX_FORCE_CAPTION );
  743. }
  744. pLocatorTarget->Update();
  745. if ( pLocatorTarget->m_bIsDrawing )
  746. {
  747. if ( !m_bHasPlayedSound )
  748. {
  749. GetGameInstructor().PlaySound( m_szStartSound.String() );
  750. m_bHasPlayedSound = true;
  751. }
  752. }
  753. }
  754. //
  755. // CScriptedIconLesson
  756. //
  757. // Linking variables to scriptable entries is done here!
  758. // The first parameter correlates to the case insensitive string name read from scripts.
  759. // This macro generates code that passes this consistent variable data in to other macros
  760. #define LESSON_VARIABLE_FACTORY \
  761. LESSON_VARIABLE_MACRO_EHANDLE( VOID, m_hLocalPlayer, EHANDLE ) \
  762. \
  763. LESSON_VARIABLE_MACRO_EHANDLE( LOCAL_PLAYER, m_hLocalPlayer, EHANDLE ) \
  764. LESSON_VARIABLE_MACRO( OUTPUT, m_fOutput, float ) \
  765. \
  766. LESSON_VARIABLE_MACRO_EHANDLE( ENTITY1, m_hEntity1, EHANDLE ) \
  767. LESSON_VARIABLE_MACRO_EHANDLE( ENTITY2, m_hEntity2, EHANDLE ) \
  768. LESSON_VARIABLE_MACRO_STRING( STRING1, m_szString1, CGameInstructorSymbol ) \
  769. LESSON_VARIABLE_MACRO_STRING( STRING2, m_szString2, CGameInstructorSymbol ) \
  770. LESSON_VARIABLE_MACRO( INTEGER1, m_iInteger1, int ) \
  771. LESSON_VARIABLE_MACRO( INTEGER2, m_iInteger2, int ) \
  772. LESSON_VARIABLE_MACRO( FLOAT1, m_fFloat1, float ) \
  773. LESSON_VARIABLE_MACRO( FLOAT2, m_fFloat2, float ) \
  774. \
  775. LESSON_VARIABLE_MACRO_EHANDLE( ICON_TARGET, m_hIconTarget, EHANDLE ) \
  776. LESSON_VARIABLE_MACRO_STRING( VGUI_TARGET_NAME, m_szVguiTargetName, CGameInstructorSymbol ) \
  777. LESSON_VARIABLE_MACRO_STRING( VGUI_TARGET_LOOKUP, m_szVguiTargetLookup, CGameInstructorSymbol ) \
  778. LESSON_VARIABLE_MACRO( VGUI_TARGET_EDGE, m_nVguiTargetEdge, int ) \
  779. LESSON_VARIABLE_MACRO( FIXED_POSITION_X, m_fFixedPositionX, float ) \
  780. LESSON_VARIABLE_MACRO( FIXED_POSITION_Y, m_fFixedPositionY, float ) \
  781. LESSON_VARIABLE_MACRO_BOOL( FIXED_POSITION, m_bFixedPosition, bool ) \
  782. LESSON_VARIABLE_MACRO_BOOL( NO_ICON_TARGET, m_bNoIconTarget, bool ) \
  783. LESSON_VARIABLE_MACRO_BOOL( ALLOW_NODRAW_TARGET, m_bAllowNodrawTarget, bool ) \
  784. LESSON_VARIABLE_MACRO_BOOL( VISIBLE, m_bVisible, bool ) \
  785. LESSON_VARIABLE_MACRO_BOOL( SHOW_WHEN_OCCLUDED, m_bShowWhenOccluded, bool ) \
  786. LESSON_VARIABLE_MACRO_BOOL( NO_OFFSCREEN, m_bNoOffscreen, bool ) \
  787. LESSON_VARIABLE_MACRO_BOOL( FORCE_CAPTION, m_bForceCaption, bool ) \
  788. LESSON_VARIABLE_MACRO_STRING( ONSCREEN_ICON, m_szOnscreenIcon, CGameInstructorSymbol ) \
  789. LESSON_VARIABLE_MACRO_STRING( OFFSCREEN_ICON, m_szOffscreenIcon, CGameInstructorSymbol ) \
  790. LESSON_VARIABLE_MACRO( ICON_OFFSET, m_flUpOffset, float ) \
  791. LESSON_VARIABLE_MACRO( ICON_RELATIVE_OFFSET, m_flRelativeUpOffset, float ) \
  792. LESSON_VARIABLE_MACRO( RANGE, m_fRange, float ) \
  793. \
  794. LESSON_VARIABLE_MACRO( FLAGS, m_iFlags, int ) \
  795. LESSON_VARIABLE_MACRO_STRING( CAPTION_COLOR, m_szCaptionColor, CGameInstructorSymbol ) \
  796. LESSON_VARIABLE_MACRO_STRING( GROUP, m_szLessonGroup, CGameInstructorSymbol ) \
  797. \
  798. LESSON_VARIABLE_MACRO_STRING( CAPTION, m_szDisplayText, CGameInstructorSymbol ) \
  799. LESSON_VARIABLE_MACRO_STRING( CAPTION_PARAM, m_szDisplayParamText, CGameInstructorSymbol ) \
  800. LESSON_VARIABLE_MACRO_STRING( BINDING, m_szBinding, CGameInstructorSymbol ) \
  801. LESSON_VARIABLE_MACRO_STRING( GAMEPAD_BINDING, m_szGamepadBinding, CGameInstructorSymbol ) \
  802. \
  803. LESSON_VARIABLE_MACRO( PRIORITY, m_iPriority, int ) \
  804. LESSON_VARIABLE_MACRO_STRING( REPLACE_KEY, m_stringReplaceKey, CGameInstructorSymbol ) \
  805. \
  806. LESSON_VARIABLE_MACRO( LOCK_DURATION, m_fLockDuration, float ) \
  807. LESSON_VARIABLE_MACRO_BOOL( CAN_OPEN_WHEN_DEAD, m_bCanOpenWhenDead, bool ) \
  808. LESSON_VARIABLE_MACRO_BOOL( BUMP_WITH_TIMEOUT_WHEN_LEARNED, m_bBumpWithTimeoutWhenLearned, bool ) \
  809. LESSON_VARIABLE_MACRO_BOOL( ONCE_LEARNED_NEVER_OPEN, m_bOnceLearnedNeverOpen, bool ) \
  810. LESSON_VARIABLE_MACRO_BOOL( CAN_TIMEOUT_WHILE_INACTIVE, m_bCanTimeoutWhileInactive, bool ) \
  811. LESSON_VARIABLE_MACRO_BOOL( USABLE_IN_MIDAIR, m_bUsableInMidair, bool) \
  812. LESSON_VARIABLE_MACRO( TIMEOUT, m_fTimeout, float ) \
  813. LESSON_VARIABLE_MACRO( UPDATE_INTERVAL, m_fUpdateInterval, float ) \
  814. LESSON_VARIABLE_MACRO_STRING( START_SOUND, m_szStartSound, CGameInstructorSymbol ) \
  815. // Create keyvalues name symbol
  816. #define LESSON_VARIABLE_SYMBOL( _varEnum, _varName, _varType ) static int g_n##_varEnum##Symbol;
  817. #define LESSON_VARIABLE_INIT_SYMBOL( _varEnum, _varName, _varType ) g_n##_varEnum##Symbol = KeyValuesSystem()->GetSymbolForString( #_varEnum );
  818. #define LESSON_SCRIPT_STRING_ADD_TO_MAP( _varEnum, _varName, _varType ) g_NameToTypeMap.Insert( #_varEnum, LESSON_VARIABLE_##_varEnum );
  819. // Create enum value
  820. #define LESSON_VARIABLE_ENUM( _varEnum, _varName, _varType ) LESSON_VARIABLE_##_varEnum,
  821. // Init info call
  822. #define LESSON_VARIABLE_INIT_INFO_CALL( _varEnum, _varName, _varType ) g_pLessonVariableInfo[ LESSON_VARIABLE_##_varEnum ].Init_##_varEnum();
  823. // Init info
  824. #define LESSON_VARIABLE_INIT_INFO( _varEnum, _varName, _varType ) \
  825. void Init_##_varEnum( void ) \
  826. { \
  827. iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
  828. varType = LessonParamTypeFromString( #_varType ); \
  829. }
  830. #define LESSON_VARIABLE_INIT_INFO_BOOL( _varEnum, _varName, _varType ) \
  831. void Init_##_varEnum( void ) \
  832. { \
  833. iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
  834. varType = FIELD_BOOLEAN; \
  835. }
  836. #define LESSON_VARIABLE_INIT_INFO_EHANDLE( _varEnum, _varName, _varType ) \
  837. void Init_##_varEnum( void ) \
  838. { \
  839. iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
  840. varType = FIELD_EHANDLE; \
  841. }
  842. #define LESSON_VARIABLE_INIT_INFO_STRING( _varEnum, _varName, _varType ) \
  843. void Init_##_varEnum( void ) \
  844. { \
  845. iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
  846. varType = FIELD_STRING; \
  847. }
  848. // Data desc
  849. #define DEFINE_GAMEINSTRUCTOR_SYMBOL(name) \
  850. { FIELD_CUSTOM, #name, offsetof(classNameTypedef,name), 1, FTYPEDESC_SAVE, NULL, GetGameInstructorSymbolSaveRestoreOps( ), NULL }
  851. #define LESSON_VARIABLE_DATADESC_INFO( _varEnum, _varName, _varType ) \
  852. DEFINE_FIELD( _varName, LessonParamTypeFromString( #_varType ) ),
  853. #define LESSON_VARIABLE_DATADESC_INFO_EHANDLE( _varEnum, _varName, _varType ) \
  854. DEFINE_FIELD( _varName, FIELD_EHANDLE ),
  855. #define LESSON_VARIABLE_DATADESC_INFO_STRING( _varEnum, _varName, _varType ) \
  856. DEFINE_GAMEINSTRUCTOR_SYMBOL(_varName),
  857. // Copy defaults into this scripted lesson into a new one
  858. #define LESSON_VARIABLE_DEFAULT( _varEnum, _varName, _varType ) ( _varName = m_pDefaultHolder->_varName );
  859. // Copy a variable from this scripted lesson into a new one
  860. #define LESSON_VARIABLE_COPY( _varEnum, _varName, _varType ) ( pOpenLesson->_varName = _varName );
  861. // Return the first param if pchName is the same as the second param
  862. #define LESSON_SCRIPT_STRING( _type, _string ) \
  863. if ( Q_stricmp( pchName, _string ) == 0 )\
  864. {\
  865. return _type;\
  866. }
  867. // Wrapper for using this macro in the factory
  868. #define LESSON_SCRIPT_STRING_GENERAL( _varEnum, _varName, _varType ) LESSON_SCRIPT_STRING( LESSON_VARIABLE_##_varEnum, #_varEnum )
  869. // Process the element action on this variable
  870. #define PROCESS_LESSON_ACTION( _varEnum, _varName, _varType ) \
  871. case LESSON_VARIABLE_##_varEnum:\
  872. return ProcessElementAction( pLessonElement->iAction, pLessonElement->bNot, #_varName, _varName, &pLessonElement->szParam, eventParam_float );
  873. #define PROCESS_LESSON_ACTION_EHANDLE( _varEnum, _varName, _varType ) \
  874. case LESSON_VARIABLE_##_varEnum:\
  875. return ProcessElementAction( pLessonElement->iAction, pLessonElement->bNot, #_varName, _varName, &pLessonElement->szParam, eventParam_float, eventParam_BaseEntity, eventParam_string );
  876. #define PROCESS_LESSON_ACTION_STRING( _varEnum, _varName, _varType ) \
  877. case LESSON_VARIABLE_##_varEnum:\
  878. return ProcessElementAction( pLessonElement->iAction, pLessonElement->bNot, #_varName, &_varName, &pLessonElement->szParam, eventParam_string );
  879. // Init the variable from the script (or a convar)
  880. #define LESSON_VARIABLE_INIT( _varEnum, _varName, _varType ) \
  881. else if ( g_n##_varEnum##Symbol == pSubKey->GetNameSymbol() ) \
  882. { \
  883. const char *pchParam = pSubKey->GetString(); \
  884. if ( pchParam && StringHasPrefix( pchParam, "convar " ) ) \
  885. { \
  886. ConVarRef tempCVar( pchParam + Q_strlen( "convar " ) ); \
  887. if ( tempCVar.IsValid() ) \
  888. { \
  889. _varName = static_cast<_varType>( tempCVar.GetFloat() ); \
  890. } \
  891. else \
  892. { \
  893. _varName = static_cast<_varType>( 0.0f ); \
  894. } \
  895. } \
  896. else \
  897. { \
  898. _varName = static_cast<_varType>( pSubKey->GetFloat() ); \
  899. } \
  900. }
  901. #define LESSON_VARIABLE_INIT_BOOL( _varEnum, _varName, _varType ) \
  902. else if ( Q_stricmp( #_varEnum, pSubKey->GetName() ) == 0 ) \
  903. { \
  904. _varName = pSubKey->GetBool(); \
  905. }
  906. #define LESSON_VARIABLE_INIT_EHANDLE( _varEnum, _varName, _varType ) \
  907. else if ( g_n##_varEnum##Symbol == pSubKey->GetNameSymbol() ) \
  908. { \
  909. DevWarning( "Can't initialize an EHANDLE from the instructor lesson script." ); \
  910. }
  911. #define LESSON_VARIABLE_INIT_STRING( _varEnum, _varName, _varType ) \
  912. else if ( g_n##_varEnum##Symbol == pSubKey->GetNameSymbol() ) \
  913. { \
  914. const char *pchParam = pSubKey->GetString(); \
  915. if ( pchParam && StringHasPrefix( pchParam, "convar " ) ) \
  916. { \
  917. ConVarRef tempCVar( pchParam + Q_strlen( "convar " ) ); \
  918. if ( tempCVar.IsValid() ) \
  919. { \
  920. _varName = tempCVar.GetString(); \
  921. } \
  922. else \
  923. { \
  924. _varName = ""; \
  925. } \
  926. } \
  927. else \
  928. { \
  929. _varName = pSubKey->GetString(); \
  930. } \
  931. }
  932. // Gets a scripted variable by offset and casts it to the proper type
  933. #define LESSON_VARIABLE_GET_FROM_OFFSET( _type, _offset ) *static_cast<_type*>( static_cast<void*>( static_cast<byte*>( static_cast<void*>( this ) ) + _offset ) )
  934. // Enum of scripted variables
  935. enum LessonVariable
  936. {
  937. // Run enum macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  938. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_ENUM
  939. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_ENUM
  940. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_ENUM
  941. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_ENUM
  942. LESSON_VARIABLE_FACTORY
  943. #undef LESSON_VARIABLE_MACRO
  944. #undef LESSON_VARIABLE_MACRO_BOOL
  945. #undef LESSON_VARIABLE_MACRO_EHANDLE
  946. #undef LESSON_VARIABLE_MACRO_STRING
  947. LESSON_VARIABLE_TOTAL
  948. };
  949. // Declare the keyvalues symbols for the keynames
  950. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_SYMBOL
  951. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_SYMBOL
  952. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_SYMBOL
  953. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_SYMBOL
  954. LESSON_VARIABLE_FACTORY
  955. #undef LESSON_VARIABLE_MACRO
  956. #undef LESSON_VARIABLE_MACRO_BOOL
  957. #undef LESSON_VARIABLE_MACRO_EHANDLE
  958. #undef LESSON_VARIABLE_MACRO_STRING
  959. // String lookup prototypes
  960. LessonVariable LessonVariableFromString( const char *pchName, bool bWarnOnInvalidNames = true );
  961. _fieldtypes LessonParamTypeFromString( const char *pchName );
  962. int LessonActionFromString( const char *pchName );
  963. // This is used to get type info an variable offsets from the variable enumerated value
  964. class LessonVariableInfo
  965. {
  966. public:
  967. LessonVariableInfo( void )
  968. : iOffset( 0 ), varType( FIELD_VOID )
  969. {
  970. }
  971. // Run init info macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  972. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_INIT_INFO
  973. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_INIT_INFO_BOOL
  974. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_INIT_INFO_EHANDLE
  975. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_INIT_INFO_STRING
  976. LESSON_VARIABLE_FACTORY
  977. #undef LESSON_VARIABLE_MACRO
  978. #undef LESSON_VARIABLE_MACRO_BOOL
  979. #undef LESSON_VARIABLE_MACRO_EHANDLE
  980. #undef LESSON_VARIABLE_MACRO_STRING
  981. public:
  982. int iOffset;
  983. _fieldtypes varType;
  984. };
  985. LessonVariableInfo g_pLessonVariableInfo[ LESSON_VARIABLE_TOTAL ];
  986. const LessonVariableInfo *GetLessonVariableInfo( int iLessonVariable )
  987. {
  988. Assert( iLessonVariable >= 0 && iLessonVariable < LESSON_VARIABLE_TOTAL );
  989. if ( g_pLessonVariableInfo[ 0 ].varType == FIELD_VOID )
  990. {
  991. // Run init info call macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  992. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_INIT_INFO_CALL
  993. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_INIT_INFO_CALL
  994. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_INIT_INFO_CALL
  995. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_INIT_INFO_CALL
  996. LESSON_VARIABLE_FACTORY
  997. #undef LESSON_VARIABLE_MACRO
  998. #undef LESSON_VARIABLE_MACRO_BOOL
  999. #undef LESSON_VARIABLE_MACRO_EHANDLE
  1000. #undef LESSON_VARIABLE_MACRO_STRING
  1001. }
  1002. return &(g_pLessonVariableInfo[ iLessonVariable ]);
  1003. }
  1004. static CUtlDict< LessonVariable, int > g_NameToTypeMap;
  1005. static CUtlDict< fieldtype_t, int > g_TypeToParamTypeMap;
  1006. CUtlDict< int, int > CScriptedIconLesson::LessonActionMap;
  1007. //-----------------------------------------------------------------------------
  1008. // Queues up game instructor symbols to save/load
  1009. //-----------------------------------------------------------------------------
  1010. class CGameInstructorSymbolSaveRestoreOps : public CDefSaveRestoreOps
  1011. {
  1012. public:
  1013. virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave )
  1014. {
  1015. pSave->StartBlock();
  1016. CGameInstructorSymbol *pSymbol = (CGameInstructorSymbol*)fieldInfo.pField;
  1017. int nNumChars = pSymbol->String() != NULL ? V_strlen( pSymbol->String() ) + 1 : 0;
  1018. pSave->WriteInt( &nNumChars );
  1019. if ( nNumChars > 0 )
  1020. {
  1021. pSave->WriteData( pSymbol->String(), nNumChars );
  1022. }
  1023. pSave->EndBlock();
  1024. }
  1025. virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore )
  1026. {
  1027. pRestore->StartBlock();
  1028. int nNumChars;
  1029. pRestore->ReadInt( &nNumChars );
  1030. if ( nNumChars > 0 )
  1031. {
  1032. char *pchTemp = ((char*)stackalloc(nNumChars));
  1033. pRestore->ReadData( pchTemp, nNumChars, nNumChars );
  1034. CGameInstructorSymbol *pSymbol = (CGameInstructorSymbol*)fieldInfo.pField;
  1035. *pSymbol = pchTemp;
  1036. }
  1037. pRestore->EndBlock();
  1038. }
  1039. };
  1040. static CGameInstructorSymbolSaveRestoreOps s_GameInstructorSymbolSaveRestoreOps;
  1041. ISaveRestoreOps *GetGameInstructorSymbolSaveRestoreOps( )
  1042. {
  1043. return &s_GameInstructorSymbolSaveRestoreOps;
  1044. }
  1045. BEGIN_SIMPLE_DATADESC( CScriptedIconLesson )
  1046. DEFINE_GAMEINSTRUCTOR_SYMBOL( m_stringName ),
  1047. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_DATADESC_INFO
  1048. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_DATADESC_INFO
  1049. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_DATADESC_INFO_EHANDLE
  1050. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_DATADESC_INFO_STRING
  1051. LESSON_VARIABLE_FACTORY
  1052. #undef LESSON_VARIABLE_MACRO
  1053. #undef LESSON_VARIABLE_MACRO_BOOL
  1054. #undef LESSON_VARIABLE_MACRO_EHANDLE
  1055. #undef LESSON_VARIABLE_MACRO_STRING
  1056. END_DATADESC()
  1057. CScriptedIconLesson::~CScriptedIconLesson( void )
  1058. {
  1059. if ( m_pDefaultHolder )
  1060. {
  1061. delete m_pDefaultHolder;
  1062. m_pDefaultHolder = NULL;
  1063. }
  1064. }
  1065. void CScriptedIconLesson::Init( void )
  1066. {
  1067. m_hLocalPlayer.Set( NULL );
  1068. m_fOutput = 0.0f;
  1069. m_hEntity1.Set( NULL );
  1070. m_hEntity2.Set( NULL );
  1071. m_szString1 = "";
  1072. m_szString2 = "";
  1073. m_iInteger1 = 0;
  1074. m_iInteger2 = 0;
  1075. m_fFloat1 = 0.0f;
  1076. m_fFloat2 = 0.0f;
  1077. m_fUpdateEventTime = 0.0f;
  1078. m_pDefaultHolder = NULL;
  1079. m_iScopeDepth = 0;
  1080. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1081. {
  1082. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1083. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Initializing scripted lesson " );
  1084. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", GetName() );
  1085. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1086. }
  1087. if ( !IsDefaultHolder() )
  1088. {
  1089. if ( !IsOpenOpportunity() )
  1090. {
  1091. // Initialize from the key value file
  1092. InitFromKeys( GetGameInstructor().GetScriptKeys() );
  1093. if ( m_iPriority >= LESSON_PRIORITY_MAX )
  1094. {
  1095. DevWarning( "Priority level not set for lesson: %s\n", GetName() );
  1096. }
  1097. // We use this to remember variable defaults to be reset before each open attempt
  1098. m_pDefaultHolder = new CScriptedIconLesson( GetName(), true, false, m_nSplitScreenSlot );
  1099. CScriptedIconLesson *pOpenLesson = m_pDefaultHolder;
  1100. // Run copy macros on all default scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  1101. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_COPY
  1102. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_COPY
  1103. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_COPY
  1104. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_COPY
  1105. LESSON_VARIABLE_FACTORY
  1106. #undef LESSON_VARIABLE_MACRO
  1107. #undef LESSON_VARIABLE_MACRO_BOOL
  1108. #undef LESSON_VARIABLE_MACRO_EHANDLE
  1109. #undef LESSON_VARIABLE_MACRO_STRING
  1110. // Listen for open events
  1111. for ( int iLessonEvent = 0; iLessonEvent < m_OpenEvents.Count(); ++iLessonEvent )
  1112. {
  1113. const LessonEvent_t *pLessonEvent = &(m_OpenEvents[ iLessonEvent ]);
  1114. ListenForGameEvent( pLessonEvent->szEventName.String() );
  1115. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1116. {
  1117. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tListen for open event " );
  1118. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\"", pLessonEvent->szEventName.String());
  1119. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ".\n" );
  1120. }
  1121. }
  1122. // Listen for close events
  1123. for ( int iLessonEvent = 0; iLessonEvent < m_CloseEvents.Count(); ++iLessonEvent )
  1124. {
  1125. const LessonEvent_t *pLessonEvent = &(m_CloseEvents[ iLessonEvent ]);
  1126. ListenForGameEvent( pLessonEvent->szEventName.String() );
  1127. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1128. {
  1129. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tListen for close event " );
  1130. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\"", pLessonEvent->szEventName.String());
  1131. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ".\n" );
  1132. }
  1133. }
  1134. // Listen for success events
  1135. for ( int iLessonEvent = 0; iLessonEvent < m_SuccessEvents.Count(); ++iLessonEvent )
  1136. {
  1137. const LessonEvent_t *pLessonEvent = &(m_SuccessEvents[ iLessonEvent ]);
  1138. ListenForGameEvent( pLessonEvent->szEventName.String());
  1139. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1140. {
  1141. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tListen for success event " );
  1142. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "\"%s\"", pLessonEvent->szEventName.String());
  1143. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ".\n" );
  1144. }
  1145. }
  1146. }
  1147. else
  1148. {
  1149. // This is an open lesson! Get the root for reference
  1150. const CScriptedIconLesson *pLesson = static_cast<const CScriptedIconLesson *>( GetGameInstructor().GetLesson( GetName() ) );
  1151. SetRoot( const_cast<CScriptedIconLesson *>( pLesson ) );
  1152. }
  1153. }
  1154. }
  1155. void CScriptedIconLesson::InitPrerequisites( void )
  1156. {
  1157. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1158. {
  1159. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1160. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Initializing prereqs for scripted lesson " );
  1161. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\"", GetName() );
  1162. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1163. }
  1164. for ( int iPrerequisit = 0; iPrerequisit < m_PrerequisiteNames.Count(); ++iPrerequisit )
  1165. {
  1166. const char *pPrerequisiteName = m_PrerequisiteNames[ iPrerequisit ].String();
  1167. AddPrerequisite( pPrerequisiteName );
  1168. }
  1169. }
  1170. void CScriptedIconLesson::OnOpen( void )
  1171. {
  1172. VPROF_BUDGET( "CScriptedIconLesson::OnOpen", "GameInstructor" );
  1173. if ( !DoDelayedPlayerSwaps() )
  1174. {
  1175. return;
  1176. }
  1177. const CScriptedIconLesson *pLesson = static_cast<const CScriptedIconLesson *>( GetRoot() );
  1178. // Process all update events
  1179. for ( int iLessonEvent = 0; iLessonEvent < pLesson->m_OnOpenEvents.Count(); ++iLessonEvent )
  1180. {
  1181. const LessonEvent_t *pLessonEvent = &(pLesson->m_OnOpenEvents[ iLessonEvent ]);
  1182. if ( gameinstructor_verbose.GetInt() > 1 && ShouldShowSpew() )
  1183. {
  1184. ConColorMsg( Color( 255, 128, 64, 255 ), "GAME INSTRUCTOR: " );
  1185. ConColorMsg( Color( 64, 128, 255, 255 ), "OnOpen event " );
  1186. ConColorMsg( Color( 0, 255, 0, 255 ), "\"%s\"", pLessonEvent->szEventName.String());
  1187. ConColorMsg( Color( 64, 128, 255, 255 ), "received for lesson \"%s\"...\n", GetName() );
  1188. }
  1189. ProcessElements( NULL, &(pLessonEvent->elements) );
  1190. }
  1191. BaseClass::OnOpen();
  1192. }
  1193. void CScriptedIconLesson::Update( void )
  1194. {
  1195. VPROF_BUDGET( "CScriptedIconLesson::Update", "GameInstructor" );
  1196. if ( !DoDelayedPlayerSwaps() )
  1197. {
  1198. return;
  1199. }
  1200. const CScriptedIconLesson *pLesson = static_cast<const CScriptedIconLesson *>( GetRoot() );
  1201. if ( gpGlobals->curtime >= m_fUpdateEventTime )
  1202. {
  1203. bool bShowSpew = ( gameinstructor_verbose.GetInt() > 1 && ShouldShowSpew() );
  1204. int iVerbose = gameinstructor_verbose.GetInt();
  1205. if ( gameinstructor_verbose.GetInt() == 1 )
  1206. {
  1207. // Force the verbose level from 1 to 0 for update events
  1208. gameinstructor_verbose.SetValue( 0 );
  1209. }
  1210. // Process all update events
  1211. for ( int iLessonEvent = 0; iLessonEvent < pLesson->m_UpdateEvents.Count(); ++iLessonEvent )
  1212. {
  1213. const LessonEvent_t *pLessonEvent = &(pLesson->m_UpdateEvents[ iLessonEvent ]);
  1214. if ( bShowSpew )
  1215. {
  1216. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1217. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Update event " );
  1218. ConColorMsg( CBaseLesson::m_rgbaVerboseUpdate, "\"%s\"", pLessonEvent->szEventName.String());
  1219. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "received for lesson \"%s\"...\n", GetName() );
  1220. }
  1221. ProcessElements( NULL, &(pLessonEvent->elements) );
  1222. }
  1223. gameinstructor_verbose.SetValue( iVerbose );
  1224. // Wait before doing update events again
  1225. m_fUpdateEventTime = gpGlobals->curtime + m_fUpdateInterval;
  1226. }
  1227. BaseClass::Update();
  1228. }
  1229. void CScriptedIconLesson::SwapOutPlayers( int iOldUserID, int iNewUserID )
  1230. {
  1231. BaseClass::SwapOutPlayers( iOldUserID, iNewUserID );
  1232. // Get the player pointers from the user IDs
  1233. C_BasePlayer *pOldPlayer = UTIL_PlayerByUserId( iOldUserID );
  1234. C_BasePlayer *pNewPlayer = UTIL_PlayerByUserId( iNewUserID );
  1235. if ( pOldPlayer == m_hEntity1.Get() )
  1236. {
  1237. if ( pNewPlayer )
  1238. {
  1239. m_hEntity1 = pNewPlayer;
  1240. }
  1241. else
  1242. {
  1243. if ( m_iNumDelayedPlayerSwaps < MAX_DELAYED_PLAYER_SWAPS )
  1244. {
  1245. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps ].phHandleToChange = &m_hEntity1;
  1246. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps ].iNewUserID = iNewUserID;
  1247. ++m_iNumDelayedPlayerSwaps;
  1248. }
  1249. }
  1250. }
  1251. if ( pOldPlayer == m_hEntity2.Get() )
  1252. {
  1253. if ( pNewPlayer )
  1254. {
  1255. m_hEntity2 = pNewPlayer;
  1256. }
  1257. else
  1258. {
  1259. if ( m_iNumDelayedPlayerSwaps < MAX_DELAYED_PLAYER_SWAPS )
  1260. {
  1261. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps ].phHandleToChange = &m_hEntity2;
  1262. m_pDelayedPlayerSwap[ m_iNumDelayedPlayerSwaps ].iNewUserID = iNewUserID;
  1263. ++m_iNumDelayedPlayerSwaps;
  1264. }
  1265. }
  1266. }
  1267. }
  1268. void CScriptedIconLesson::FireGameEvent( IGameEvent *event )
  1269. {
  1270. VPROF_BUDGET( "CScriptedIconLesson::FireGameEvent", "GameInstructor" );
  1271. ACTIVE_SPLITSCREEN_PLAYER_GUARD( GetSplitScreenSlot() );
  1272. if ( m_bDisabled )
  1273. return;
  1274. if ( !DoDelayedPlayerSwaps() )
  1275. {
  1276. return;
  1277. }
  1278. if ( !C_BasePlayer::GetLocalPlayer() )
  1279. return;
  1280. // Check that this lesson is allowed for the current input device
  1281. if( m_bOnlyKeyboard && input->ControllerModeActive() )
  1282. return;
  1283. if( m_bOnlyGamepad && !input->ControllerModeActive() )
  1284. return;
  1285. if( m_bNoSplitscreen && XBX_GetNumGameUsers() > 1 )
  1286. return;
  1287. // Check that this lesson is for the proper team
  1288. CBasePlayer *pLocalPlayer = GetGameInstructor().GetLocalPlayer();
  1289. if ( m_iTeam != TEAM_ANY && pLocalPlayer && pLocalPlayer->GetTeamNumber() != m_iTeam )
  1290. {
  1291. // This lesson is intended for a different team
  1292. return;
  1293. }
  1294. const char *name = event->GetName();
  1295. // Open events run on the root
  1296. ProcessOpenGameEvents( this, name, event );
  1297. // Close and success events run on the children
  1298. const CUtlVector < CBaseLesson * > *pChildren = GetChildren();
  1299. for ( int iChild = 0; iChild < pChildren->Count(); ++iChild )
  1300. {
  1301. CScriptedIconLesson *pScriptedChild = dynamic_cast<CScriptedIconLesson*>( (*pChildren)[ iChild ] );
  1302. pScriptedChild->ProcessCloseGameEvents( this, name, event );
  1303. pScriptedChild->ProcessSuccessGameEvents( this, name, event );
  1304. }
  1305. }
  1306. void CScriptedIconLesson::ProcessOpenGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event )
  1307. {
  1308. if ( pRootLesson->InstanceType() == LESSON_INSTANCE_SINGLE_OPEN && GetGameInstructor().IsLessonOfSameTypeOpen( this ) )
  1309. {
  1310. // We don't want more than one of this type, and there is already one open
  1311. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1312. {
  1313. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1314. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Opportunity " );
  1315. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\" ", pRootLesson->GetName() );
  1316. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "open events NOT processed (there is already an open lesson of this type).\n" );
  1317. }
  1318. return;
  1319. }
  1320. for ( int iLessonEvent = 0; iLessonEvent < pRootLesson->m_OpenEvents.Count(); ++iLessonEvent )
  1321. {
  1322. const LessonEvent_t *pLessonEvent = &(pRootLesson->m_OpenEvents[ iLessonEvent ]);
  1323. if ( Q_strcmp( name, pLessonEvent->szEventName.String()) == 0 )
  1324. {
  1325. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1326. {
  1327. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1328. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Open event " );
  1329. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\"", pLessonEvent->szEventName.String());
  1330. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "received for lesson \"%s\"...\n", GetName() );
  1331. }
  1332. if ( m_pDefaultHolder )
  1333. {
  1334. // Run copy from default macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  1335. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_DEFAULT
  1336. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_DEFAULT
  1337. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_DEFAULT
  1338. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_DEFAULT
  1339. LESSON_VARIABLE_FACTORY
  1340. #undef LESSON_VARIABLE_MACRO
  1341. #undef LESSON_VARIABLE_MACRO_BOOL
  1342. #undef LESSON_VARIABLE_MACRO_EHANDLE
  1343. #undef LESSON_VARIABLE_MACRO_STRING
  1344. }
  1345. if ( ProcessElements( event, &(pLessonEvent->elements) ) )
  1346. {
  1347. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1348. {
  1349. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\tAll elements returned true. Opening!\n" );
  1350. }
  1351. MEM_ALLOC_CREDIT();
  1352. CScriptedIconLesson *pOpenLesson = new CScriptedIconLesson( GetName(), false, true, GetSplitScreenSlot() );
  1353. // Run copy macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  1354. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_COPY
  1355. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_COPY
  1356. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_COPY
  1357. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_COPY
  1358. LESSON_VARIABLE_FACTORY
  1359. #undef LESSON_VARIABLE_MACRO
  1360. #undef LESSON_VARIABLE_MACRO_BOOL
  1361. #undef LESSON_VARIABLE_MACRO_EHANDLE
  1362. #undef LESSON_VARIABLE_MACRO_STRING
  1363. if ( GetGameInstructor().OpenOpportunity( pOpenLesson ) )
  1364. {
  1365. pOpenLesson->OnOpen();
  1366. if ( pRootLesson->InstanceType() == LESSON_INSTANCE_SINGLE_OPEN )
  1367. {
  1368. // This one is open and we only want one! So, we're done.
  1369. // Other open events may be listening for the same events... skip them!
  1370. return;
  1371. }
  1372. }
  1373. }
  1374. }
  1375. }
  1376. }
  1377. void CScriptedIconLesson::ProcessCloseGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event )
  1378. {
  1379. for ( int iLessonEvent = 0; iLessonEvent < pRootLesson->m_CloseEvents.Count() && IsOpenOpportunity(); ++iLessonEvent )
  1380. {
  1381. const LessonEvent_t *pLessonEvent = &(pRootLesson->m_CloseEvents[ iLessonEvent ]);
  1382. if ( Q_strcmp( name, pLessonEvent->szEventName.String()) == 0 )
  1383. {
  1384. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1385. {
  1386. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1387. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Close event " );
  1388. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\"", pLessonEvent->szEventName.String());
  1389. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "received for lesson \"%s\"...\n", GetName() );
  1390. }
  1391. if ( ProcessElements( event, &(pLessonEvent->elements) ) )
  1392. {
  1393. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1394. {
  1395. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tAll elements returned true. Closing!\n" );
  1396. }
  1397. CloseOpportunity( "Close event elements completed." );
  1398. }
  1399. }
  1400. }
  1401. }
  1402. void CScriptedIconLesson::ProcessSuccessGameEvents( const CScriptedIconLesson *pRootLesson, const char *name, IGameEvent *event )
  1403. {
  1404. for ( int iLessonEvent = 0; iLessonEvent < pRootLesson->m_SuccessEvents.Count(); ++iLessonEvent )
  1405. {
  1406. const LessonEvent_t *pLessonEvent = &(pRootLesson->m_SuccessEvents[ iLessonEvent ]);
  1407. if ( Q_strcmp( name, pLessonEvent->szEventName.String()) == 0 )
  1408. {
  1409. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1410. {
  1411. ConColorMsg( CBaseLesson::m_rgbaVerboseHeader, "GAME INSTRUCTOR: " );
  1412. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "Success event " );
  1413. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "\"%s\"", pLessonEvent->szEventName.String());
  1414. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "received for lesson \"%s\"...\n", GetName() );
  1415. }
  1416. if ( ProcessElements( event, &(pLessonEvent->elements) ) )
  1417. {
  1418. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1419. {
  1420. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "\tAll elements returned true. Succeeding!\n" );
  1421. }
  1422. MarkSucceeded();
  1423. }
  1424. }
  1425. }
  1426. }
  1427. LessonVariable LessonVariableFromString( const char *pchName, bool bWarnOnInvalidNames )
  1428. {
  1429. int slot = g_NameToTypeMap.Find( pchName );
  1430. if ( slot != g_NameToTypeMap.InvalidIndex() )
  1431. return g_NameToTypeMap[ slot ];
  1432. if ( bWarnOnInvalidNames )
  1433. {
  1434. AssertMsg( 0, "Invalid scripted lesson variable!" );
  1435. DevWarning( "Invalid scripted lesson variable: %s\n", pchName );
  1436. }
  1437. return LESSON_VARIABLE_TOTAL;
  1438. }
  1439. _fieldtypes LessonParamTypeFromString( const char *pchName )
  1440. {
  1441. if ( g_TypeToParamTypeMap.Count() == 0 )
  1442. {
  1443. CScriptedIconLesson::PreReadLessonsFromFile();
  1444. }
  1445. int slot = g_TypeToParamTypeMap.Find( pchName );
  1446. if ( slot != g_TypeToParamTypeMap.InvalidIndex() )
  1447. return g_TypeToParamTypeMap[ slot ];
  1448. DevWarning( "Invalid scripted lesson variable/param type: %s\n", pchName );
  1449. return FIELD_VOID;
  1450. }
  1451. int LessonActionFromString( const char *pchName )
  1452. {
  1453. int slot = CScriptedIconLesson::LessonActionMap.Find( pchName );
  1454. if ( slot != CScriptedIconLesson::LessonActionMap.InvalidIndex() )
  1455. return CScriptedIconLesson::LessonActionMap[ slot ];
  1456. DevWarning( "Invalid scripted lesson action: %s\n", pchName );
  1457. return LESSON_ACTION_NONE;
  1458. }
  1459. void CScriptedIconLesson::InitElementsFromKeys( CUtlVector< LessonElement_t > *pLessonElements, KeyValues *pKey )
  1460. {
  1461. KeyValues *pSubKey = NULL;
  1462. for ( pSubKey = pKey->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
  1463. {
  1464. char szSubKeyName[ 256 ];
  1465. V_strcpy_safe( szSubKeyName, pSubKey->GetName() );
  1466. char *pchToken = strtok( szSubKeyName, " " );
  1467. LessonVariable iVariable = LessonVariableFromString( pchToken );
  1468. pchToken = strtok ( NULL, "" );
  1469. int iAction = LESSON_ACTION_NONE;
  1470. bool bNot = false;
  1471. bool bOptionalParam = false;
  1472. if ( !pchToken || pchToken[ 0 ] == '\0' )
  1473. {
  1474. DevWarning( "No action specified for variable: \"%s\"\n", pSubKey->GetName() );
  1475. }
  1476. else
  1477. {
  1478. if ( pchToken[ 0 ] == '?' )
  1479. {
  1480. pchToken++;
  1481. bOptionalParam = true;
  1482. }
  1483. if ( pchToken[ 0 ] == '!' )
  1484. {
  1485. pchToken++;
  1486. bNot = true;
  1487. }
  1488. iAction = LessonActionFromString( pchToken );
  1489. }
  1490. V_strcpy_safe( szSubKeyName, pSubKey->GetString() );
  1491. pchToken = strtok( szSubKeyName, " " );
  1492. _fieldtypes paramType = LessonParamTypeFromString( pchToken );
  1493. char *pchParam = "";
  1494. if ( paramType != FIELD_VOID )
  1495. {
  1496. pchToken = strtok ( NULL, "" );
  1497. pchParam = pchToken;
  1498. }
  1499. if ( !pchParam )
  1500. {
  1501. DevWarning( "No parameter specified for action: \"%s\"\n", pSubKey->GetName() );
  1502. }
  1503. else
  1504. {
  1505. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1506. {
  1507. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t\tElement \"%s %s\" added.\n", pSubKey->GetName(), pSubKey->GetString() );
  1508. }
  1509. // See if our param is a scripted var
  1510. LessonVariable iParamVarIndex = LessonVariableFromString( pchParam, false );
  1511. pLessonElements->AddToTail( LessonElement_t( iVariable, iAction, bNot, bOptionalParam, pchParam, iParamVarIndex, paramType ) );
  1512. }
  1513. }
  1514. }
  1515. void CScriptedIconLesson::InitElementsFromElements( CUtlVector< LessonElement_t > *pLessonElements, const CUtlVector< LessonElement_t > *pLessonElements2 )
  1516. {
  1517. for ( int i = 0; i < pLessonElements2->Count(); ++i )
  1518. {
  1519. pLessonElements->AddToTail( LessonElement_t( (*pLessonElements2)[ i ] ) );
  1520. }
  1521. }
  1522. void CScriptedIconLesson::InitFromKeys( KeyValues *pKey )
  1523. {
  1524. if ( !pKey )
  1525. return;
  1526. static int s_nInstanceTypeSymbol = KeyValuesSystem()->GetSymbolForString( "instance_type" );
  1527. static int s_nReplaceKeySymbol = KeyValuesSystem()->GetSymbolForString( "replace_key" );
  1528. static int s_nFixedInstancesMaxSymbol = KeyValuesSystem()->GetSymbolForString( "fixed_instances_max" );
  1529. static int s_nReplaceOnlyWhenStopped = KeyValuesSystem()->GetSymbolForString( "replace_only_when_stopped" );
  1530. static int s_nTeamSymbol = KeyValuesSystem()->GetSymbolForString( "team" );
  1531. static int s_nOnlyKeyboardSymbol = KeyValuesSystem()->GetSymbolForString( "only_keyboard" );
  1532. static int s_nOnlyGamepadSymbol = KeyValuesSystem()->GetSymbolForString( "only_gamepad" );
  1533. static int s_nNoSplitscreenSymbol = KeyValuesSystem()->GetSymbolForString( "no_splitscreen" );
  1534. static int s_nDisplayLimitSymbol = KeyValuesSystem()->GetSymbolForString( "display_limit" );
  1535. static int s_nSuccessLimitSymbol = KeyValuesSystem()->GetSymbolForString( "success_limit" );
  1536. static int s_nPreReqSymbol = KeyValuesSystem()->GetSymbolForString( "prereq" );
  1537. static int s_nOpenSymbol = KeyValuesSystem()->GetSymbolForString( "open" );
  1538. static int s_nCloseSymbol = KeyValuesSystem()->GetSymbolForString( "close" );
  1539. static int s_nSuccessSymbol = KeyValuesSystem()->GetSymbolForString( "success" );
  1540. static int s_nOnOpenSymbol = KeyValuesSystem()->GetSymbolForString( "onopen" );
  1541. static int s_nUpdateSymbol = KeyValuesSystem()->GetSymbolForString( "update" );
  1542. KeyValues *pSubKey = NULL;
  1543. for ( pSubKey = pKey->GetFirstSubKey(); pSubKey; pSubKey = pSubKey->GetNextKey() )
  1544. {
  1545. if ( pSubKey->GetNameSymbol() == s_nInstanceTypeSymbol )
  1546. {
  1547. m_iInstanceType = LessonInstanceType( pSubKey->GetInt() );
  1548. }
  1549. else if ( pSubKey->GetNameSymbol() == s_nReplaceKeySymbol )
  1550. {
  1551. m_stringReplaceKey = pSubKey->GetString();
  1552. }
  1553. else if ( pSubKey->GetNameSymbol() == s_nFixedInstancesMaxSymbol )
  1554. {
  1555. m_iFixedInstancesMax = pSubKey->GetInt();
  1556. }
  1557. else if ( pSubKey->GetNameSymbol() == s_nReplaceOnlyWhenStopped )
  1558. {
  1559. m_bReplaceOnlyWhenStopped = pSubKey->GetBool();
  1560. }
  1561. else if ( pSubKey->GetNameSymbol() == s_nTeamSymbol )
  1562. {
  1563. m_iTeam = pSubKey->GetInt();
  1564. }
  1565. else if ( pSubKey->GetNameSymbol() == s_nOnlyKeyboardSymbol )
  1566. {
  1567. m_bOnlyKeyboard = pSubKey->GetBool();
  1568. }
  1569. else if ( pSubKey->GetNameSymbol() == s_nOnlyGamepadSymbol )
  1570. {
  1571. m_bOnlyGamepad = pSubKey->GetBool();
  1572. }
  1573. else if ( pSubKey->GetNameSymbol() == s_nNoSplitscreenSymbol )
  1574. {
  1575. m_bNoSplitscreen = pSubKey->GetBool();
  1576. }
  1577. else if ( pSubKey->GetNameSymbol() == s_nDisplayLimitSymbol )
  1578. {
  1579. m_iDisplayLimit = pSubKey->GetInt();
  1580. }
  1581. else if ( pSubKey->GetNameSymbol() == s_nSuccessLimitSymbol )
  1582. {
  1583. m_iSuccessLimit = pSubKey->GetInt();
  1584. }
  1585. else if ( pSubKey->GetNameSymbol() == s_nPreReqSymbol )
  1586. {
  1587. CGameInstructorSymbol pName;
  1588. pName = pSubKey->GetString();
  1589. m_PrerequisiteNames.AddToTail( pName );
  1590. }
  1591. else if ( pSubKey->GetNameSymbol() == s_nOpenSymbol )
  1592. {
  1593. KeyValues *pEventKey = NULL;
  1594. for ( pEventKey = pSubKey->GetFirstTrueSubKey(); pEventKey; pEventKey = pEventKey->GetNextTrueSubKey() )
  1595. {
  1596. LessonEvent_t *pLessonEvent = AddOpenEvent();
  1597. pLessonEvent->szEventName = pEventKey->GetName();
  1598. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1599. {
  1600. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tAdding open event " );
  1601. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\" ", pLessonEvent->szEventName.String());
  1602. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1603. }
  1604. InitElementsFromKeys( &(pLessonEvent->elements), pEventKey );
  1605. }
  1606. }
  1607. else if ( pSubKey->GetNameSymbol() == s_nCloseSymbol )
  1608. {
  1609. KeyValues *pEventKey = NULL;
  1610. for ( pEventKey = pSubKey->GetFirstTrueSubKey(); pEventKey; pEventKey = pEventKey->GetNextTrueSubKey() )
  1611. {
  1612. LessonEvent_t *pLessonEvent = AddCloseEvent();
  1613. pLessonEvent->szEventName = pEventKey->GetName();
  1614. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1615. {
  1616. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tAdding close event " );
  1617. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\"%s\" ", pLessonEvent->szEventName.String());
  1618. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1619. }
  1620. InitElementsFromKeys( &(pLessonEvent->elements), pEventKey );
  1621. }
  1622. }
  1623. else if ( pSubKey->GetNameSymbol() == s_nSuccessSymbol )
  1624. {
  1625. KeyValues *pEventKey = NULL;
  1626. for ( pEventKey = pSubKey->GetFirstTrueSubKey(); pEventKey; pEventKey = pEventKey->GetNextTrueSubKey() )
  1627. {
  1628. LessonEvent_t *pLessonEvent = AddSuccessEvent();
  1629. pLessonEvent->szEventName = pEventKey->GetName();
  1630. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1631. {
  1632. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tAdding success event " );
  1633. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "\"%s\" ", pLessonEvent->szEventName.String());
  1634. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1635. }
  1636. InitElementsFromKeys( &(pLessonEvent->elements), pEventKey );
  1637. }
  1638. }
  1639. else if ( pSubKey->GetNameSymbol() == s_nOnOpenSymbol )
  1640. {
  1641. KeyValues *pEventKey = NULL;
  1642. for ( pEventKey = pSubKey->GetFirstTrueSubKey(); pEventKey; pEventKey = pEventKey->GetNextTrueSubKey() )
  1643. {
  1644. LessonEvent_t *pLessonEvent = AddOnOpenEvent();
  1645. pLessonEvent->szEventName = pEventKey->GetName();
  1646. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1647. {
  1648. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tAdding onopen event " );
  1649. ConColorMsg( CBaseLesson::m_rgbaVerboseOpen, "\"%s\" ", pLessonEvent->szEventName.String());
  1650. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1651. }
  1652. InitElementsFromKeys( &(pLessonEvent->elements), pEventKey );
  1653. }
  1654. }
  1655. else if ( pSubKey->GetNameSymbol() == s_nUpdateSymbol )
  1656. {
  1657. KeyValues *pEventKey = NULL;
  1658. for ( pEventKey = pSubKey->GetFirstTrueSubKey(); pEventKey; pEventKey = pEventKey->GetNextTrueSubKey() )
  1659. {
  1660. LessonEvent_t *pLessonEvent = AddUpdateEvent();
  1661. pLessonEvent->szEventName = pEventKey->GetName();
  1662. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1663. {
  1664. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tAdding update event " );
  1665. ConColorMsg( CBaseLesson::m_rgbaVerboseUpdate, "\"%s\" ", pLessonEvent->szEventName.String());
  1666. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "...\n" );
  1667. }
  1668. InitElementsFromKeys( &(pLessonEvent->elements), pEventKey );
  1669. }
  1670. }
  1671. // Run intialize from key macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  1672. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_INIT
  1673. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_INIT_BOOL
  1674. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_INIT_EHANDLE
  1675. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_INIT_STRING
  1676. LESSON_VARIABLE_FACTORY
  1677. #undef LESSON_VARIABLE_MACRO
  1678. #undef LESSON_VARIABLE_MACRO_BOOL
  1679. #undef LESSON_VARIABLE_MACRO_EHANDLE
  1680. #undef LESSON_VARIABLE_MACRO_STRING
  1681. }
  1682. }
  1683. bool CScriptedIconLesson::ProcessElements( IGameEvent *event, const CUtlVector< LessonElement_t > *pElements )
  1684. {
  1685. VPROF_BUDGET( "CScriptedIconLesson::ProcessElements", "GameInstructor" );
  1686. m_hLocalPlayer = GetGameInstructor().GetLocalPlayer();
  1687. bool bSuccess = true;
  1688. int nContinueScope = -1;
  1689. m_iScopeDepth = 0;
  1690. if ( gameinstructor_find_errors.GetBool() )
  1691. {
  1692. // Just run them all to check for errors!
  1693. for ( int iElement = 0; iElement < pElements->Count(); ++iElement )
  1694. {
  1695. ProcessElement( event, &((*pElements)[ iElement ] ), false );
  1696. }
  1697. return false;
  1698. }
  1699. // Process each element until a step fails
  1700. for ( int iElement = 0; iElement < pElements->Count(); ++iElement )
  1701. {
  1702. if ( nContinueScope == m_iScopeDepth )
  1703. {
  1704. nContinueScope = -1;
  1705. }
  1706. if ( !ProcessElement( event, &((*pElements)[ iElement ]), nContinueScope != -1 ) )
  1707. {
  1708. // This element failed
  1709. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1710. {
  1711. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tPrevious element returned false.\n" );
  1712. }
  1713. nContinueScope = m_iScopeDepth - 1;
  1714. if ( nContinueScope < 0 )
  1715. {
  1716. // No outer scope to worry about, we're done
  1717. bSuccess = false;
  1718. break;
  1719. }
  1720. }
  1721. }
  1722. return bSuccess;
  1723. }
  1724. bool CScriptedIconLesson::ProcessElement( IGameEvent *event, const LessonElement_t *pLessonElement, bool bInFailedScope )
  1725. {
  1726. ACTIVE_SPLITSCREEN_PLAYER_GUARD( GetSplitScreenSlot() );
  1727. VPROF_BUDGET( "CScriptedIconLesson::ProcessElement", "GameInstructor" );
  1728. if ( pLessonElement->iAction == LESSON_ACTION_SCOPE_IN )
  1729. {
  1730. // Special case for closing (we don't need variables for this)
  1731. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1732. {
  1733. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tScopeIn()\n" );
  1734. }
  1735. m_iScopeDepth++;
  1736. return true;
  1737. }
  1738. else if ( pLessonElement->iAction == LESSON_ACTION_SCOPE_OUT )
  1739. {
  1740. // Special case for closing (we don't need variables for this)
  1741. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1742. {
  1743. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tScopeOut()\n" );
  1744. }
  1745. m_iScopeDepth--;
  1746. return true;
  1747. }
  1748. if ( bInFailedScope )
  1749. {
  1750. // Only scope upkeep is done when we're in a failing scope... bail!
  1751. return true;
  1752. }
  1753. if ( pLessonElement->iAction == LESSON_ACTION_CLOSE )
  1754. {
  1755. // Special case for closing (we don't need variables for this)
  1756. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1757. {
  1758. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tCloseOpportunity()\n" );
  1759. }
  1760. CloseOpportunity( "Close action." );
  1761. return true;
  1762. }
  1763. else if ( pLessonElement->iAction == LESSON_ACTION_SUCCESS )
  1764. {
  1765. // Special case for succeeding (we don't need variables for this)
  1766. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1767. {
  1768. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tMarkSucceeded()\n" );
  1769. }
  1770. MarkSucceeded();
  1771. return true;
  1772. }
  1773. else if ( pLessonElement->iAction == LESSON_ACTION_LOCK )
  1774. {
  1775. // Special case for setting the starting point for the lesson to stay locked from (we don't need variables for this)
  1776. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1777. {
  1778. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tm_fLockTime = gpGlobals->curtime\n" );
  1779. }
  1780. m_fLockTime = gpGlobals->curtime;
  1781. return true;
  1782. }
  1783. else if ( pLessonElement->iAction == LESSON_ACTION_PRESENT_COMPLETE )
  1784. {
  1785. // Special case for checking presentation status (we don't need variables for this)
  1786. bool bPresentComplete = IsPresentComplete();
  1787. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1788. {
  1789. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tIsPresentComplete() " );
  1790. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%s ", ( bPresentComplete ) ? ( "true" ) : ( "false" ) );
  1791. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( pLessonElement->bNot ) ? ( "!= true\n" ) : ( "== true\n" ) );
  1792. }
  1793. return ( pLessonElement->bNot ) ? ( !bPresentComplete ) : ( bPresentComplete );
  1794. }
  1795. else if ( pLessonElement->iAction == LESSON_ACTION_PRESENT_START )
  1796. {
  1797. // Special case for setting presentation status (we don't need variables for this)
  1798. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1799. {
  1800. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tPresentStart()\n" );
  1801. }
  1802. PresentStart();
  1803. return true;
  1804. }
  1805. else if ( pLessonElement->iAction == LESSON_ACTION_PRESENT_END )
  1806. {
  1807. // Special case for setting presentation status (we don't need variables for this)
  1808. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1809. {
  1810. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tPresentEnd()\n" );
  1811. }
  1812. PresentEnd();
  1813. return true;
  1814. }
  1815. else if ( pLessonElement->iAction == LESSON_ACTION_IS_MULTIPLAYER )
  1816. {
  1817. // Special case for checking if the gamerules are multiplayer
  1818. bool bIsMultiplayer = ( GameRules() && GameRules()->IsMultiplayer() );
  1819. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  1820. {
  1821. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tGameRules()->IsMultiplayer() " );
  1822. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%s ", ( bIsMultiplayer ) ? ( "true" ) : ( "false" ) );
  1823. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( pLessonElement->bNot ) ? ( "!= true\n" ) : ( "== true\n" ) );
  1824. }
  1825. return ( pLessonElement->bNot ) ? ( !bIsMultiplayer ) : ( bIsMultiplayer );
  1826. }
  1827. // These values temporarily hold the parameter's value
  1828. const char *pParamName = pLessonElement->szParam.String();
  1829. float eventParam_float = 0.0f;
  1830. char eventParam_string[ 256 ];
  1831. eventParam_string[ 0 ] = '\0';
  1832. C_BaseEntity *eventParam_BaseEntity = NULL;
  1833. // Get the value from the event parameter based on its type
  1834. switch ( pLessonElement->paramType )
  1835. {
  1836. case FIELD_FLOAT:
  1837. if ( pLessonElement->iParamVarIndex < LESSON_VARIABLE_TOTAL )
  1838. {
  1839. // The parameter is a scripted var
  1840. const LessonVariableInfo *pInfo = GetLessonVariableInfo( pLessonElement->iParamVarIndex );
  1841. switch ( pInfo->varType )
  1842. {
  1843. case FIELD_FLOAT:
  1844. eventParam_float = LESSON_VARIABLE_GET_FROM_OFFSET( float, pInfo->iOffset );
  1845. break;
  1846. case FIELD_INTEGER:
  1847. eventParam_float = static_cast<float>( LESSON_VARIABLE_GET_FROM_OFFSET( int, pInfo->iOffset ) );
  1848. break;
  1849. case FIELD_BOOLEAN:
  1850. eventParam_float = static_cast<float>( LESSON_VARIABLE_GET_FROM_OFFSET( bool, pInfo->iOffset ) );
  1851. break;
  1852. case FIELD_STRING:
  1853. eventParam_float = static_cast<float>( atoi( &LESSON_VARIABLE_GET_FROM_OFFSET( CGameInstructorSymbol, pInfo->iOffset )->String() ) );
  1854. break;
  1855. case FIELD_EHANDLE:
  1856. case FIELD_FUNCTION:
  1857. DevWarning( "Can't use this variable type with this parameter type in lesson script.\n" );
  1858. break;
  1859. }
  1860. }
  1861. else if ( event && !(event->IsEmpty( pParamName )) )
  1862. {
  1863. eventParam_float = event->GetFloat( pParamName );
  1864. }
  1865. else if ( pLessonElement->bOptionalParam )
  1866. {
  1867. // We don't want to interpret this and not finding the param is still ok
  1868. return true;
  1869. }
  1870. else if ( ( pParamName[ 0 ] >= '0' && pParamName[ 0 ] <= '9' ) || pParamName[ 0 ] == '-' || pParamName[ 0 ] == '.' )
  1871. {
  1872. // This param doesn't exist, try parsing the string
  1873. eventParam_float = Q_atof( pParamName );
  1874. }
  1875. else
  1876. {
  1877. DevWarning( "Invalid event field name and not a float \"%s\".\n", pParamName );
  1878. return false;
  1879. }
  1880. break;
  1881. case FIELD_INTEGER:
  1882. if ( pLessonElement->iParamVarIndex < LESSON_VARIABLE_TOTAL )
  1883. {
  1884. // The parameter is a scripted var
  1885. const LessonVariableInfo *pInfo = GetLessonVariableInfo( pLessonElement->iParamVarIndex );
  1886. switch ( pInfo->varType )
  1887. {
  1888. case FIELD_FLOAT:
  1889. eventParam_float = static_cast<int>( LESSON_VARIABLE_GET_FROM_OFFSET( float, pInfo->iOffset ) );
  1890. break;
  1891. case FIELD_INTEGER:
  1892. eventParam_float = LESSON_VARIABLE_GET_FROM_OFFSET( int, pInfo->iOffset );
  1893. break;
  1894. case FIELD_BOOLEAN:
  1895. eventParam_float = static_cast<int>( LESSON_VARIABLE_GET_FROM_OFFSET( bool, pInfo->iOffset ) );
  1896. break;
  1897. case FIELD_STRING:
  1898. eventParam_float = atof( &LESSON_VARIABLE_GET_FROM_OFFSET( CGameInstructorSymbol, pInfo->iOffset )->String() );
  1899. break;
  1900. case FIELD_EHANDLE:
  1901. case FIELD_FUNCTION:
  1902. DevWarning( "Can't use this variable type with this parameter type in lesson script.\n" );
  1903. break;
  1904. }
  1905. }
  1906. else if ( event && !(event->IsEmpty( pParamName )) )
  1907. {
  1908. eventParam_float = static_cast<float>( event->GetInt( pParamName ) );
  1909. }
  1910. else if ( pLessonElement->bOptionalParam )
  1911. {
  1912. // We don't want to interpret this and not finding the param is still ok
  1913. return true;
  1914. }
  1915. else if ( ( pParamName[ 0 ] >= '0' && pParamName[ 0 ] <= '9' ) || pParamName[ 0 ] == '-' )
  1916. {
  1917. // This param doesn't exist, try parsing the string
  1918. eventParam_float = static_cast<float>( Q_atoi( pParamName ) );
  1919. }
  1920. else
  1921. {
  1922. DevWarning( "Invalid event field name and not an integer \"%s\".\n", pParamName );
  1923. return false;
  1924. }
  1925. break;
  1926. case FIELD_STRING:
  1927. if ( pLessonElement->iParamVarIndex < LESSON_VARIABLE_TOTAL )
  1928. {
  1929. // The parameter is a scripted var
  1930. const LessonVariableInfo *pInfo = GetLessonVariableInfo( pLessonElement->iParamVarIndex );
  1931. switch ( pInfo->varType )
  1932. {
  1933. case FIELD_STRING:
  1934. Q_strncpy( eventParam_string, &LESSON_VARIABLE_GET_FROM_OFFSET( CGameInstructorSymbol, pInfo->iOffset )->String(), sizeof( eventParam_string ) );
  1935. break;
  1936. case FIELD_FLOAT:
  1937. Q_snprintf( eventParam_string, sizeof( eventParam_string ), "%f", LESSON_VARIABLE_GET_FROM_OFFSET( float, pInfo->iOffset ) );
  1938. break;
  1939. case FIELD_INTEGER:
  1940. Q_snprintf( eventParam_string, sizeof( eventParam_string ), "%i", LESSON_VARIABLE_GET_FROM_OFFSET( int, pInfo->iOffset ) );
  1941. break;
  1942. case FIELD_BOOLEAN:
  1943. case FIELD_EHANDLE:
  1944. case FIELD_FUNCTION:
  1945. DevWarning( "Can't use this variable type with this parameter type in lesson script.\n" );
  1946. break;
  1947. }
  1948. }
  1949. else
  1950. {
  1951. const char *pchEventString = NULL;
  1952. if ( event && !(event->IsEmpty( pParamName )) )
  1953. {
  1954. pchEventString = event->GetString( pParamName );
  1955. }
  1956. if ( pchEventString && pchEventString[0] )
  1957. {
  1958. V_strcpy_safe( eventParam_string, pchEventString );
  1959. }
  1960. else if ( pLessonElement->bOptionalParam )
  1961. {
  1962. // We don't want to interpret this and not finding the param is still ok
  1963. return true;
  1964. }
  1965. else
  1966. {
  1967. // This param doesn't exist, try parsing the string
  1968. Q_strncpy( eventParam_string, pParamName, sizeof( eventParam_string ) );
  1969. }
  1970. }
  1971. break;
  1972. case FIELD_BOOLEAN:
  1973. if ( pLessonElement->iParamVarIndex < LESSON_VARIABLE_TOTAL )
  1974. {
  1975. // The parameter is a scripted var
  1976. const LessonVariableInfo *pInfo = GetLessonVariableInfo( pLessonElement->iParamVarIndex );
  1977. switch ( pInfo->varType )
  1978. {
  1979. case FIELD_FLOAT:
  1980. eventParam_float = ( ( LESSON_VARIABLE_GET_FROM_OFFSET( float, pInfo->iOffset ) ) ? ( 1.0f ) : ( 0.0f ) );
  1981. break;
  1982. case FIELD_INTEGER:
  1983. eventParam_float = ( ( LESSON_VARIABLE_GET_FROM_OFFSET( int, pInfo->iOffset ) ) ? ( 1.0f ) : ( 0.0f ) );
  1984. break;
  1985. case FIELD_BOOLEAN:
  1986. eventParam_float = ( ( LESSON_VARIABLE_GET_FROM_OFFSET( bool, pInfo->iOffset ) ) ? ( 1.0f ) : ( 0.0f ) );
  1987. break;
  1988. case FIELD_EHANDLE:
  1989. case FIELD_STRING:
  1990. case FIELD_FUNCTION:
  1991. DevWarning( "Can't use this variable type with this parameter type in lesson script.\n" );
  1992. break;
  1993. }
  1994. }
  1995. else if ( event && !(event->IsEmpty( pParamName )) )
  1996. {
  1997. eventParam_float = ( event->GetBool( pParamName ) ) ? ( 1.0f ) : ( 0.0f );
  1998. }
  1999. else if ( pLessonElement->bOptionalParam )
  2000. {
  2001. // We don't want to interpret this and not finding the param is still ok
  2002. return true;
  2003. }
  2004. else if ( pParamName[ 0 ] == '0' || pParamName[ 0 ] == '1' )
  2005. {
  2006. // This param doesn't exist, try parsing the string
  2007. eventParam_float = ( Q_atof( pParamName ) != 0.0f ) ? 1.0f : 0.0f;
  2008. }
  2009. else
  2010. {
  2011. DevWarning( "Invalid event field name and not an boolean \"%s\".\n", pParamName );
  2012. return false;
  2013. }
  2014. break;
  2015. case FIELD_CUSTOM:
  2016. if ( pLessonElement->iParamVarIndex < LESSON_VARIABLE_TOTAL )
  2017. {
  2018. // The parameter is a scripted var
  2019. const LessonVariableInfo *pInfo = GetLessonVariableInfo( pLessonElement->iParamVarIndex );
  2020. switch ( pInfo->varType )
  2021. {
  2022. case FIELD_EHANDLE:
  2023. eventParam_BaseEntity = ( LESSON_VARIABLE_GET_FROM_OFFSET( EHANDLE, pInfo->iOffset ) ).Get();
  2024. if ( !eventParam_BaseEntity )
  2025. {
  2026. if ( pLessonElement->bOptionalParam )
  2027. {
  2028. // Not having an entity is fine
  2029. return true;
  2030. }
  2031. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2032. {
  2033. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tPlayer param \"%s\" returned NULL.\n", pParamName );
  2034. }
  2035. return false;
  2036. }
  2037. break;
  2038. case FIELD_FLOAT:
  2039. case FIELD_INTEGER:
  2040. case FIELD_BOOLEAN:
  2041. case FIELD_STRING:
  2042. case FIELD_FUNCTION:
  2043. DevWarning( "Can't use this variable type with this parameter type in lesson script.\n" );
  2044. break;
  2045. }
  2046. }
  2047. else if ( event && !(event->IsEmpty( pParamName )) )
  2048. {
  2049. eventParam_BaseEntity = UTIL_PlayerByUserId( event->GetInt( pParamName ) );
  2050. if ( !eventParam_BaseEntity )
  2051. {
  2052. if ( pLessonElement->bOptionalParam )
  2053. {
  2054. // Not having an entity is fine
  2055. return true;
  2056. }
  2057. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2058. {
  2059. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tPlayer param \"%s\" returned NULL.\n", pParamName );
  2060. }
  2061. return false;
  2062. }
  2063. }
  2064. else if ( pLessonElement->bOptionalParam )
  2065. {
  2066. // We don't want to interpret this and not finding the param is still ok
  2067. return true;
  2068. }
  2069. else if ( Q_stricmp( pParamName, "null" ) == 0 )
  2070. {
  2071. // They explicitly want a null pointer
  2072. eventParam_BaseEntity = NULL;
  2073. }
  2074. else
  2075. {
  2076. DevWarning( "Invalid event field name \"%s\".\n", pParamName );
  2077. return false;
  2078. }
  2079. break;
  2080. case FIELD_EHANDLE:
  2081. if ( pLessonElement->iParamVarIndex < LESSON_VARIABLE_TOTAL )
  2082. {
  2083. // The parameter is a scripted var
  2084. const LessonVariableInfo *pInfo = GetLessonVariableInfo( pLessonElement->iParamVarIndex );
  2085. switch ( pInfo->varType )
  2086. {
  2087. case FIELD_EHANDLE:
  2088. eventParam_BaseEntity = ( LESSON_VARIABLE_GET_FROM_OFFSET( EHANDLE, pInfo->iOffset ) ).Get();
  2089. if ( !eventParam_BaseEntity )
  2090. {
  2091. if ( pLessonElement->bOptionalParam )
  2092. {
  2093. // Not having an entity is fine
  2094. return true;
  2095. }
  2096. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2097. {
  2098. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tEntity param \"%s\" returned NULL.\n", pParamName );
  2099. }
  2100. return false;
  2101. }
  2102. break;
  2103. case FIELD_FLOAT:
  2104. case FIELD_INTEGER:
  2105. case FIELD_BOOLEAN:
  2106. case FIELD_STRING:
  2107. case FIELD_FUNCTION:
  2108. DevWarning( "Can't use this variable type with this parameter type in lesson script.\n" );
  2109. break;
  2110. }
  2111. }
  2112. else if ( event && !(event->IsEmpty( pParamName )) )
  2113. {
  2114. int iEntID = event->GetInt( pParamName );
  2115. if ( iEntID >= NUM_ENT_ENTRIES )
  2116. {
  2117. AssertMsg( 0, "Invalid entity ID used in game event field!" );
  2118. DevWarning( "Invalid entity ID used in game event (%s) for param (%s).", event->GetName(), pParamName );
  2119. return false;
  2120. }
  2121. eventParam_BaseEntity = C_BaseEntity::Instance( iEntID );
  2122. if ( !eventParam_BaseEntity )
  2123. {
  2124. if ( pLessonElement->bOptionalParam )
  2125. {
  2126. // Not having an entity is fine
  2127. return true;
  2128. }
  2129. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2130. {
  2131. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tEntity param \"%s\" returned NULL.\n", pParamName );
  2132. }
  2133. return false;
  2134. }
  2135. }
  2136. else if ( pLessonElement->bOptionalParam )
  2137. {
  2138. // We don't want to interpret this and not finding the param is still ok
  2139. return true;
  2140. }
  2141. else if ( Q_stricmp( pParamName, "null" ) == 0 )
  2142. {
  2143. // They explicitly want a null pointer
  2144. eventParam_BaseEntity = NULL;
  2145. }
  2146. else if ( Q_stricmp( pParamName, "world" ) == 0 )
  2147. {
  2148. // They explicitly want the world
  2149. eventParam_BaseEntity = GetClientWorldEntity();
  2150. }
  2151. else
  2152. {
  2153. DevWarning( "Invalid event field name \"%s\".\n", pParamName );
  2154. return false;
  2155. }
  2156. break;
  2157. case FIELD_EMBEDDED:
  2158. {
  2159. // The parameter is a convar
  2160. ConVarRef tempCVar( pParamName );
  2161. if ( tempCVar.IsValid() )
  2162. {
  2163. eventParam_float = tempCVar.GetFloat();
  2164. Q_strncpy( eventParam_string, tempCVar.GetString(), sizeof( eventParam_string ) );
  2165. }
  2166. else
  2167. {
  2168. DevWarning( "Invalid convar name \"%s\".\n", pParamName );
  2169. return false;
  2170. }
  2171. }
  2172. break;
  2173. }
  2174. // Do the action to the specified variable
  2175. switch ( pLessonElement->iVariable )
  2176. {
  2177. // Run process action macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  2178. #define LESSON_VARIABLE_MACRO PROCESS_LESSON_ACTION
  2179. #define LESSON_VARIABLE_MACRO_BOOL PROCESS_LESSON_ACTION
  2180. #define LESSON_VARIABLE_MACRO_EHANDLE PROCESS_LESSON_ACTION_EHANDLE
  2181. #define LESSON_VARIABLE_MACRO_STRING PROCESS_LESSON_ACTION_STRING
  2182. LESSON_VARIABLE_FACTORY;
  2183. #undef LESSON_VARIABLE_MACRO
  2184. #undef LESSON_VARIABLE_MACRO_BOOL
  2185. #undef LESSON_VARIABLE_MACRO_EHANDLE
  2186. #undef LESSON_VARIABLE_MACRO_STRING
  2187. }
  2188. return true;
  2189. }
  2190. bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const char *pchVarName, float &fVar, const CGameInstructorSymbol *pchParamName, float fParam )
  2191. {
  2192. switch ( iAction )
  2193. {
  2194. case LESSON_ACTION_SET:
  2195. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2196. {
  2197. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = [%s] ", pchVarName, pchParamName->String() );
  2198. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2199. }
  2200. fVar = fParam;
  2201. return true;
  2202. case LESSON_ACTION_ADD:
  2203. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2204. {
  2205. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] += [%s] ", pchVarName, pchParamName->String() );
  2206. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2207. }
  2208. fVar += fParam;
  2209. return true;
  2210. case LESSON_ACTION_SUBTRACT:
  2211. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2212. {
  2213. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] -= [%s] ", pchVarName, pchParamName->String() );
  2214. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2215. }
  2216. fVar -= fParam;
  2217. return true;
  2218. case LESSON_ACTION_MULTIPLY:
  2219. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2220. {
  2221. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] *= [%s] ", pchVarName, pchParamName->String() );
  2222. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2223. }
  2224. fVar *= fParam;
  2225. return true;
  2226. case LESSON_ACTION_IS:
  2227. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2228. {
  2229. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] ", pchVarName );
  2230. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f ", fVar );
  2231. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "!= [%s] " ) : ( "== [%s] " ), pchParamName->String() );
  2232. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2233. }
  2234. return ( bNot ) ? ( fVar != fParam ) : ( fVar == fParam );
  2235. case LESSON_ACTION_LESS_THAN:
  2236. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2237. {
  2238. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] ", pchVarName );
  2239. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f ", fVar );
  2240. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2241. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2242. }
  2243. return ( bNot ) ? ( fVar >= fParam ) : ( fVar < fParam );
  2244. case LESSON_ACTION_HAS_BIT:
  2245. {
  2246. int iTemp1 = static_cast<int>( fVar );
  2247. int iTemp2 = ( 1 << static_cast<int>( fParam ) );
  2248. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2249. {
  2250. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t([%s] ", pchVarName );
  2251. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "0x%X ", iTemp1 );
  2252. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "& [%s] ", pchParamName->String() );
  2253. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "0x%X", iTemp2 );
  2254. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ") == 0\n" ) : ( ") != 0\n" ) );
  2255. }
  2256. return ( bNot ) ? ( ( iTemp1 & iTemp2 ) == 0 ) : ( ( iTemp1 & iTemp2 ) != 0 );
  2257. }
  2258. case LESSON_ACTION_BIT_COUNT_IS:
  2259. {
  2260. int iTemp1 = UTIL_CountNumBitsSet( static_cast<unsigned int>( fVar ) );
  2261. int iTemp2 = static_cast<int>( fParam );
  2262. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2263. {
  2264. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tUTIL_CountNumBitsSet([%s]) ", pchVarName );
  2265. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", iTemp1 );
  2266. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( " != [%s] " ) : ( " == [%s] " ), pchParamName->String() );
  2267. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i\n", iTemp2 );
  2268. }
  2269. return ( bNot ) ? ( iTemp1 != iTemp2 ) : ( iTemp1 == iTemp2 );
  2270. }
  2271. case LESSON_ACTION_BIT_COUNT_LESS_THAN:
  2272. {
  2273. int iTemp1 = UTIL_CountNumBitsSet( static_cast<unsigned int>( fVar ) );
  2274. int iTemp2 = static_cast<int>( fParam );
  2275. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2276. {
  2277. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tUTIL_CountNumBitsSet([%s]) ", pchVarName );
  2278. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", iTemp1 );
  2279. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( " >= [%s] " ) : ( " < [%s] " ), pchParamName->String() );
  2280. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i\n", iTemp2 );
  2281. }
  2282. return ( bNot ) ? ( iTemp1 >= iTemp2 ) : ( iTemp1 < iTemp2 );
  2283. }
  2284. }
  2285. DevWarning( "Invalid lesson action type used with \"%s\" variable type.\n", pchVarName );
  2286. return false;
  2287. }
  2288. bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const char *pchVarName, int &iVar, const CGameInstructorSymbol *pchParamName, float fParam )
  2289. {
  2290. float fTemp = static_cast<float>( iVar );
  2291. bool bRetVal = ProcessElementAction( iAction, bNot, pchVarName, fTemp, pchParamName, fParam );
  2292. iVar = static_cast<int>( fTemp );
  2293. return bRetVal;
  2294. }
  2295. bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const char *pchVarName, bool &bVar, const CGameInstructorSymbol *pchParamName, float fParam )
  2296. {
  2297. float fTemp = ( bVar ) ? ( 1.0f ) : ( 0.0f );
  2298. bool bRetVal = ProcessElementAction( iAction, bNot, pchVarName, fTemp, pchParamName, fParam );
  2299. bVar = ( fTemp != 0.0f );
  2300. return bRetVal;
  2301. }
  2302. bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const char *pchVarName, EHANDLE &hVar, const CGameInstructorSymbol *pchParamName, float fParam, C_BaseEntity *pParam, const char *pchParam )
  2303. {
  2304. // First try to let the mod act on the action
  2305. bool bModHandled = false;
  2306. bool bModReturn = Mod_ProcessElementAction( iAction, bNot, pchVarName, hVar, pchParamName, fParam, pParam, pchParam, bModHandled );
  2307. if ( bModHandled )
  2308. {
  2309. return bModReturn;
  2310. }
  2311. C_BaseEntity *pVar = hVar.Get();
  2312. switch ( iAction )
  2313. {
  2314. case LESSON_ACTION_SET:
  2315. {
  2316. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2317. {
  2318. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = [%s]\n", pchVarName, pchParamName->String() );
  2319. }
  2320. hVar = pParam;
  2321. return true;
  2322. }
  2323. case LESSON_ACTION_IS:
  2324. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2325. {
  2326. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t[%s] != [%s]\n" ) : ( "\t[%s] == [%s]\n" ), pchVarName, pchParamName->String() );
  2327. }
  2328. return ( bNot ) ? ( pVar != pParam ) : ( pVar == pParam );
  2329. case LESSON_ACTION_GET_DISTANCE:
  2330. {
  2331. if ( !pVar || !pParam )
  2332. {
  2333. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2334. {
  2335. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->DistTo( [%s] )", pchVarName, pchParamName->String() );
  2336. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "...\n" );
  2337. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle or Param handle returned NULL!\n" );
  2338. }
  2339. return false;
  2340. }
  2341. C_BasePlayer *pVarPlayer = ( pVar->IsPlayer() ? static_cast< C_BasePlayer* >( pVar ) : NULL );
  2342. C_BasePlayer *pParamPlayer = ( pParam->IsPlayer() ? static_cast< C_BasePlayer* >( pParam ) : NULL );
  2343. Vector vVarPos = ( pVarPlayer ? pVarPlayer->ActivePlayerCombatCharacter()->EyePosition() : pVar->WorldSpaceCenter() );
  2344. Vector vParamPos = ( pParamPlayer ? pParamPlayer->ActivePlayerCombatCharacter()->EyePosition() : pParam->WorldSpaceCenter() );
  2345. m_fOutput = vVarPos.DistTo( vParamPos );
  2346. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2347. {
  2348. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->DistTo( [%s] ) ", pchVarName, pchParamName->String() );
  2349. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", m_fOutput );
  2350. }
  2351. return true;
  2352. }
  2353. case LESSON_ACTION_GET_ANGULAR_DISTANCE:
  2354. {
  2355. if ( !pVar || !pParam )
  2356. {
  2357. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2358. {
  2359. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->AngularDistTo( [%s] )", pchVarName, pchParamName->String() );
  2360. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "...\n" );
  2361. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle or Param handle returned NULL!\n" );
  2362. }
  2363. return false;
  2364. }
  2365. C_BasePlayer *pVarPlayer = ( pVar->IsPlayer() ? static_cast< C_BasePlayer* >( pVar ) : NULL );
  2366. C_BasePlayer *pParamPlayer = ( pParam->IsPlayer() ? static_cast< C_BasePlayer* >( pParam ) : NULL );
  2367. Vector vVarPos = ( pVarPlayer ? pVarPlayer->ActivePlayerCombatCharacter()->EyePosition() : pVar->WorldSpaceCenter() );
  2368. Vector vParamPos = ( pParamPlayer ? pParamPlayer->ActivePlayerCombatCharacter()->EyePosition() : pParam->WorldSpaceCenter() );
  2369. Vector vVarToParam = vParamPos - vVarPos;
  2370. VectorNormalize( vVarToParam );
  2371. Vector vVarForward;
  2372. if ( pVar->IsPlayer() )
  2373. {
  2374. AngleVectors( static_cast< C_BasePlayer* >( pVar )->ActivePlayerCombatCharacter()->EyeAngles(), &vVarForward, NULL, NULL );
  2375. }
  2376. else
  2377. {
  2378. pVar->GetVectors( &vVarForward, NULL, NULL );
  2379. }
  2380. // Set the distance in degrees
  2381. m_fOutput = ( vVarToParam.Dot( vVarForward ) - 1.0f ) * -90.0f;
  2382. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2383. {
  2384. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->AngularDistTo( [%s] ) ", pchVarName, pchParamName->String() );
  2385. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", m_fOutput );
  2386. }
  2387. return true;
  2388. }
  2389. case LESSON_ACTION_GET_PLAYER_DISPLAY_NAME:
  2390. {
  2391. int iTemp = static_cast<int>( fParam );
  2392. if ( iTemp <= 0 || iTemp > 2 )
  2393. {
  2394. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2395. {
  2396. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcpy( [stringINVALID], [%s]->GetPlayerName() ", pchVarName );
  2397. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2398. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2399. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tParam selecting string is out of range!\n" );
  2400. }
  2401. return false;
  2402. }
  2403. // Use string2 if it was specified, otherwise, use string1
  2404. CGameInstructorSymbol *pString;
  2405. char const *pchParamNameTemp = NULL;
  2406. if ( iTemp == 2 )
  2407. {
  2408. pString = &m_szString2;
  2409. pchParamNameTemp = "string2";
  2410. }
  2411. else
  2412. {
  2413. pString = &m_szString1;
  2414. pchParamNameTemp = "string1";
  2415. }
  2416. if ( !pVar )
  2417. {
  2418. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2419. {
  2420. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcpy( [%s], [%s]->GetPlayerName() ", pchParamNameTemp, pchVarName );
  2421. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2422. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2423. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle returned NULL!\n" );
  2424. }
  2425. return false;
  2426. }
  2427. *pString = pVar->GetPlayerName();
  2428. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2429. {
  2430. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcpy( [%s], [%s]->GetPlayerName() ", pchParamNameTemp, pchVarName );
  2431. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\" ", pString->String() );
  2432. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2433. }
  2434. return true;
  2435. }
  2436. case LESSON_ACTION_CLASSNAME_IS:
  2437. {
  2438. if ( !pVar )
  2439. {
  2440. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2441. {
  2442. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t!FClassnameIs( [%s] " ) : ( "\tFClassnameIs( [%s] " ), pchVarName );
  2443. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "..." );
  2444. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  2445. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\" ", pchParam );
  2446. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2447. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle returned NULL!\n" );
  2448. }
  2449. return false;
  2450. }
  2451. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2452. {
  2453. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t!FClassnameIs( [%s] " ) : ( "\tFClassnameIs( [%s] " ), pchVarName );
  2454. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%s", pVar->GetClassname() );
  2455. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  2456. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\" ", pchParam );
  2457. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2458. }
  2459. return ( bNot ) ? ( !FClassnameIs( pVar, pchParam ) ) : ( FClassnameIs( pVar, pchParam ) );
  2460. }
  2461. case LESSON_ACTION_TEAM_IS:
  2462. {
  2463. int iTemp = static_cast<int>( fParam );
  2464. if ( !pVar )
  2465. {
  2466. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2467. {
  2468. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetTeamNumber() ", pchVarName );
  2469. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2470. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "!= [%s] " ) : ( "== [%s] " ), pchParamName->String() );
  2471. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i\n", iTemp );
  2472. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle returned NULL!\n" );
  2473. }
  2474. return false;
  2475. }
  2476. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2477. {
  2478. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetTeamNumber() ", pchVarName );
  2479. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", pVar->GetTeamNumber() );
  2480. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "!= [%s] " ) : ( "== [%s] " ), pchParamName->String() );
  2481. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i\n", iTemp );
  2482. }
  2483. return ( bNot ) ? ( pVar->GetTeamNumber() != iTemp ) : ( pVar->GetTeamNumber() == iTemp );
  2484. }
  2485. case LESSON_ACTION_MODELNAME_IS:
  2486. {
  2487. C_BaseAnimating *pBaseAnimating = dynamic_cast<C_BaseAnimating *>( pVar );
  2488. if ( !pBaseAnimating )
  2489. {
  2490. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2491. {
  2492. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_stricmp( [%s]->ModelName() ", pchVarName );
  2493. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "..." );
  2494. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  2495. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\" ", pchParam );
  2496. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ") != 0\n" ) : ( ") == 0\n" ) );
  2497. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseAnimating returned NULL!\n" );
  2498. }
  2499. return false;
  2500. }
  2501. const char *pchModelName = "-no model-";
  2502. CStudioHdr *pModel = pBaseAnimating->GetModelPtr();
  2503. if ( pModel )
  2504. {
  2505. const studiohdr_t *pRenderHDR = pModel->GetRenderHdr();
  2506. if ( pRenderHDR )
  2507. {
  2508. pchModelName = pRenderHDR->name;
  2509. }
  2510. }
  2511. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2512. {
  2513. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_stricmp( [%s]->ModelName() ", pchVarName );
  2514. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%s", pchModelName );
  2515. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  2516. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\" ", pchParam );
  2517. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ") != 0\n" ) : ( ") == 0\n" ) );
  2518. }
  2519. return ( bNot ) ? ( Q_stricmp( pchModelName, pchParam ) != 0 ) : ( Q_stricmp( pchModelName, pchParam ) == 0 );
  2520. }
  2521. case LESSON_ACTION_HEALTH_LESS_THAN:
  2522. {
  2523. int iTemp = static_cast<int>( fParam );
  2524. if ( !pVar )
  2525. {
  2526. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2527. {
  2528. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetHealth() ", pchVarName );
  2529. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2530. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2531. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i\n", iTemp );
  2532. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle returned NULL!\n" );
  2533. }
  2534. return false;
  2535. }
  2536. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2537. {
  2538. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetHealth() ", pchVarName );
  2539. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", pVar->GetHealth() );
  2540. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2541. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i\n", iTemp );
  2542. }
  2543. return ( bNot ) ? ( pVar->GetHealth() >= iTemp ) : ( pVar->GetHealth() < iTemp );
  2544. }
  2545. case LESSON_ACTION_HEALTH_PERCENTAGE_LESS_THAN:
  2546. {
  2547. if ( !pVar )
  2548. {
  2549. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2550. {
  2551. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->HealthFraction() ", pchVarName );
  2552. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2553. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2554. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2555. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle returned NULL!\n" );
  2556. }
  2557. return false;
  2558. }
  2559. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2560. {
  2561. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->HealthFraction() ", pchVarName );
  2562. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f ", pVar->HealthFraction() );
  2563. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2564. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
  2565. }
  2566. float fHealthPercentage = 1.0f;
  2567. if ( pVar->GetMaxHealth() != 0.0f )
  2568. {
  2569. fHealthPercentage = pVar->HealthFraction();
  2570. }
  2571. return ( bNot ) ? ( fHealthPercentage >= fParam ) : ( fHealthPercentage < fParam );
  2572. }
  2573. case LESSON_ACTION_GET_ACTIVE_WEAPON:
  2574. {
  2575. int iTemp = static_cast<int>( fParam );
  2576. if ( iTemp <= 0 || iTemp > 2 )
  2577. {
  2578. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2579. {
  2580. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[entityINVALID] = [%s]->GetActiveWeapon()\n", pchVarName );
  2581. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tParam selecting string is out of range!\n" );
  2582. }
  2583. return false;
  2584. }
  2585. // Use entity2 if it was specified, otherwise, use entity1
  2586. CHandle<C_BaseEntity> *pHandle;
  2587. char const *pchParamNameTemp = NULL;
  2588. if ( iTemp == 2 )
  2589. {
  2590. pHandle = &m_hEntity2;
  2591. pchParamNameTemp = "entity2";
  2592. }
  2593. else
  2594. {
  2595. pHandle = &m_hEntity1;
  2596. pchParamNameTemp = "entity1";
  2597. }
  2598. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2599. if ( pVar )
  2600. {
  2601. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2602. }
  2603. if ( !pBaseCombatCharacter )
  2604. {
  2605. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2606. {
  2607. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = [%s]->GetActiveWeapon()", pchParamNameTemp, pchVarName );
  2608. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2609. }
  2610. return false;
  2611. }
  2612. pHandle->Set( pBaseCombatCharacter->GetActiveWeapon() );
  2613. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2614. {
  2615. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = [%s]->GetActiveWeapon()", pchParamNameTemp, pchVarName );
  2616. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"\n", pchParam );
  2617. }
  2618. return true;
  2619. }
  2620. case LESSON_ACTION_WEAPON_IS:
  2621. {
  2622. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2623. if ( pVar )
  2624. {
  2625. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2626. }
  2627. if ( !pBaseCombatCharacter )
  2628. {
  2629. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2630. {
  2631. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetActiveWeapon()->GetName() ", pchVarName );
  2632. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2633. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "!= [%s] " ) : ( "== [%s] " ), pchParamName->String() );
  2634. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"\n", pchParam );
  2635. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2636. }
  2637. return false;
  2638. }
  2639. CBaseCombatWeapon *pBaseCombatWeapon = pBaseCombatCharacter->GetActiveWeapon();
  2640. if ( !pBaseCombatWeapon )
  2641. {
  2642. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2643. {
  2644. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetActiveWeapon()->GetName() ", pchVarName );
  2645. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2646. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "!= [%s] " ) : ( "== [%s] " ), pchParamName->String() );
  2647. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"\n", pchParam );
  2648. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar GetActiveWeapon returned NULL!\n" );
  2649. }
  2650. return false;
  2651. }
  2652. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2653. {
  2654. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetActiveWeapon()->GetName() ", pchVarName );
  2655. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\" ", pBaseCombatWeapon->GetName() );
  2656. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "!= [%s] " ) : ( "== [%s] " ), pchParamName->String() );
  2657. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"\n", pchParam );
  2658. }
  2659. return ( bNot ) ? ( Q_stricmp( pBaseCombatWeapon->GetName(), pchParam ) != 0 ) : ( Q_stricmp( pBaseCombatWeapon->GetName(), pchParam ) == 0 );
  2660. }
  2661. case LESSON_ACTION_WEAPON_HAS:
  2662. {
  2663. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2664. if ( pVar )
  2665. {
  2666. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2667. }
  2668. if ( !pBaseCombatCharacter )
  2669. {
  2670. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2671. {
  2672. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->Weapon_OwnsThisType([%s] " ) : ( "\t[%s]->Weapon_OwnsThisType([%s] " ), pchVarName, pchParamName->String() );
  2673. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  2674. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2675. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2676. }
  2677. return false;
  2678. }
  2679. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2680. {
  2681. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->Weapon_OwnsThisType([%s] " ) : ( "\t[%s]->Weapon_OwnsThisType([%s] " ), pchVarName, pchParamName->String() );
  2682. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  2683. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2684. }
  2685. return ( bNot ) ? ( pBaseCombatCharacter->Weapon_OwnsThisType( pchParam ) == NULL ) : ( pBaseCombatCharacter->Weapon_OwnsThisType( pchParam ) != NULL );
  2686. }
  2687. case LESSON_ACTION_GET_ACTIVE_WEAPON_SLOT:
  2688. {
  2689. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2690. if ( pVar )
  2691. {
  2692. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2693. }
  2694. if ( !pBaseCombatCharacter )
  2695. {
  2696. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2697. {
  2698. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->Weapon_GetActiveSlot() ...\n", pchVarName );
  2699. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2700. }
  2701. return false;
  2702. }
  2703. C_BaseCombatWeapon *pWeapon = pBaseCombatCharacter->GetActiveWeapon();
  2704. if ( !pWeapon )
  2705. {
  2706. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2707. {
  2708. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->Weapon_GetActiveSlot() ...\n", pchVarName );
  2709. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar GetActiveWeapon returned NULL!\n" );
  2710. }
  2711. return false;
  2712. }
  2713. m_fOutput = pWeapon->GetSlot();
  2714. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2715. {
  2716. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->Weapon_GetSlot() ", pchVarName );
  2717. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", m_fOutput );
  2718. }
  2719. return true;
  2720. }
  2721. case LESSON_ACTION_GET_WEAPON_SLOT:
  2722. {
  2723. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2724. if ( pVar )
  2725. {
  2726. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2727. }
  2728. if ( !pBaseCombatCharacter )
  2729. {
  2730. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2731. {
  2732. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->Weapon_GetSlot([%s] ", pchVarName, pchParamName->String() );
  2733. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  2734. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ") ...\n" );
  2735. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2736. }
  2737. return false;
  2738. }
  2739. C_BaseCombatWeapon *pWeapon = pBaseCombatCharacter->Weapon_OwnsThisType( pchParam );
  2740. m_fOutput = (pWeapon != NULL) ? pWeapon->GetSlot() : 0.0f;
  2741. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2742. {
  2743. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[output] = [%s]->Weapon_GetSlot([%s] ", pchVarName, pchParamName->String() );
  2744. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  2745. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ") " );
  2746. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", m_fOutput );
  2747. }
  2748. return true;
  2749. }
  2750. case LESSON_ACTION_GET_WEAPON_IN_SLOT:
  2751. {
  2752. int nTemp = static_cast<int>( fParam );
  2753. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2754. if ( pVar )
  2755. {
  2756. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2757. }
  2758. if ( !pBaseCombatCharacter )
  2759. {
  2760. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2761. {
  2762. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[entity1] = [%s]->GetWeapon([%s] ", pchVarName, pchParamName->String() );
  2763. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%i\"", nTemp );
  2764. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2765. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2766. }
  2767. return false;
  2768. }
  2769. m_hEntity1 = pBaseCombatCharacter->GetWeapon( nTemp );
  2770. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2771. {
  2772. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[entity1] = [%s]->GetWeapon([%s] ", pchVarName, pchParamName->String() );
  2773. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%i\"", nTemp );
  2774. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  2775. }
  2776. return true;
  2777. }
  2778. case LESSON_ACTION_CLIP_PERCENTAGE_LESS_THAN:
  2779. {
  2780. C_BaseCombatCharacter *pBaseCombatCharacter = NULL;
  2781. if ( pVar )
  2782. {
  2783. pBaseCombatCharacter = pVar->MyCombatCharacterPointer();
  2784. }
  2785. if ( !pBaseCombatCharacter )
  2786. {
  2787. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2788. {
  2789. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetActiveWeapon()->Clip1Percentage() ", pchVarName );
  2790. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2791. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2792. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%.1f\n", fParam );
  2793. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BaseCombatCharacter returned NULL!\n" );
  2794. }
  2795. return false;
  2796. }
  2797. CBaseCombatWeapon *pBaseCombatWeapon = pBaseCombatCharacter->GetActiveWeapon();
  2798. if ( !pBaseCombatWeapon )
  2799. {
  2800. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2801. {
  2802. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetActiveWeapon()->Clip1Percentage() ", pchVarName );
  2803. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
  2804. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2805. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%.1f\n", fParam );
  2806. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar GetActiveWeapon returned NULL!\n" );
  2807. }
  2808. return false;
  2809. }
  2810. float fClip1Percentage = 100.0f;
  2811. if ( pBaseCombatWeapon->UsesClipsForAmmo1() )
  2812. {
  2813. fClip1Percentage = 100.0f * ( static_cast<float>( pBaseCombatWeapon->Clip1() ) / static_cast<float>( pBaseCombatWeapon->GetMaxClip1() ) );
  2814. }
  2815. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2816. {
  2817. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetActiveWeapon()->Clip1Percentage() ", pchVarName );
  2818. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%.1f ", fClip1Percentage );
  2819. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
  2820. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%.1f\n", fParam );
  2821. }
  2822. return ( bNot ) ? ( fClip1Percentage >= fParam ) : ( fClip1Percentage < fParam );
  2823. }
  2824. case LESSON_ACTION_WEAPON_AMMO_LOW:
  2825. {
  2826. int iTemp = static_cast<int>( fParam );
  2827. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  2828. if ( !pBasePlayer )
  2829. {
  2830. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2831. {
  2832. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetWeaponInSlot( ", pchVarName );
  2833. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", iTemp );
  2834. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ")->AmmoPercentage() >= 30\n" ) : ( ")->AmmoPercentage() < 30\n" ) );
  2835. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BasePlayer returned NULL!\n" );
  2836. }
  2837. return false;
  2838. }
  2839. CBaseCombatWeapon *pBaseCombatWeapon = NULL;
  2840. // Get the weapon in variable slot
  2841. for ( int iWeapon = 0; iWeapon < MAX_WEAPONS; iWeapon++ )
  2842. {
  2843. CBaseCombatWeapon *pBaseCombatWeaponTemp = pBasePlayer->ActivePlayerCombatCharacter()->GetWeapon( iWeapon );
  2844. if ( pBaseCombatWeaponTemp )
  2845. {
  2846. if ( pBaseCombatWeaponTemp->GetSlot() == iTemp )
  2847. {
  2848. pBaseCombatWeapon = pBaseCombatWeaponTemp;
  2849. break;
  2850. }
  2851. }
  2852. }
  2853. if ( !pBaseCombatWeapon )
  2854. {
  2855. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2856. {
  2857. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetWeaponInSlot( ", pchVarName );
  2858. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", iTemp );
  2859. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ")->AmmoPercentage() >= 30\n" ) : ( ")->AmmoPercentage() < 30\n" ) );
  2860. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar GetActiveWeapon returned NULL!\n" );
  2861. }
  2862. return false;
  2863. }
  2864. // Check if the ammo is full
  2865. int iMaxAmmo = pBaseCombatWeapon->GetReserveAmmoMax( AMMO_POSITION_PRIMARY );
  2866. int iPlayerAmmo = pBaseCombatWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  2867. bool bAmmoLow = ( iPlayerAmmo < ( iMaxAmmo / 3 ) );
  2868. if ( bNot )
  2869. {
  2870. bAmmoLow = !bAmmoLow;
  2871. }
  2872. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2873. {
  2874. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->GetWeaponInSlot( ", pchVarName );
  2875. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%i ", iTemp );
  2876. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ")->AmmoPercentage() >= 30 " ) : ( ")->AmmoPercentage() < 30 " ) );
  2877. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bAmmoLow ) ? ( "true\n" ) : ( "false\n" ) );
  2878. }
  2879. return bAmmoLow;
  2880. }
  2881. case LESSON_ACTION_WEAPON_AMMO_FULL:
  2882. {
  2883. int iTemp = static_cast<int>( fParam );
  2884. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  2885. if ( !pBasePlayer )
  2886. {
  2887. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2888. {
  2889. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->GetWeaponInSlot( " ) : ( "\t[%s]->GetWeaponInSlot( " ), pchVarName );
  2890. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "%i ", iTemp );
  2891. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")->AmmoFull()\n" );
  2892. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BasePlayer returned NULL!\n" );
  2893. }
  2894. return false;
  2895. }
  2896. CBaseCombatWeapon *pBaseCombatWeapon = NULL;
  2897. // Get the weapon in variable slot
  2898. for ( int iWeapon = 0; iWeapon < MAX_WEAPONS; iWeapon++ )
  2899. {
  2900. CBaseCombatWeapon *pBaseCombatWeaponTemp = pBasePlayer->ActivePlayerCombatCharacter()->GetWeapon( iWeapon );
  2901. if ( pBaseCombatWeaponTemp )
  2902. {
  2903. if ( pBaseCombatWeaponTemp->GetSlot() == iTemp )
  2904. {
  2905. pBaseCombatWeapon = pBaseCombatWeaponTemp;
  2906. break;
  2907. }
  2908. }
  2909. }
  2910. if ( !pBaseCombatWeapon )
  2911. {
  2912. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2913. {
  2914. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->GetWeaponInSlot( " ) : ( "\t[%s]->GetWeaponInSlot( " ), pchVarName );
  2915. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "%i ", iTemp );
  2916. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")->AmmoFull()\n" );
  2917. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar GetWeaponInSlot returned NULL!\n" );
  2918. }
  2919. return false;
  2920. }
  2921. // Check if the ammo is full
  2922. int iMaxAmmo = pBaseCombatWeapon->GetReserveAmmoMax( AMMO_POSITION_PRIMARY );
  2923. int iPlayerAmmo = pBaseCombatWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  2924. bool bAmmoFull = ( iPlayerAmmo >= iMaxAmmo );
  2925. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2926. {
  2927. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->GetWeaponInSlot( " ) : ( "\t[%s]->GetWeaponInSlot( " ), pchVarName );
  2928. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "%i ", iTemp );
  2929. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")->AmmoFull() " );
  2930. ConColorMsg( CBaseLesson::m_rgbaVerboseName, ( bAmmoFull ) ? ( "true\n" ) : ( "false\n" ) );
  2931. }
  2932. return ( bNot ) ? ( !bAmmoFull ) : ( bAmmoFull );
  2933. }
  2934. case LESSON_ACTION_WEAPON_AMMO_EMPTY:
  2935. {
  2936. int iTemp = static_cast<int>( fParam );
  2937. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  2938. if ( !pBasePlayer )
  2939. {
  2940. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2941. {
  2942. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->GetWeaponInSlot( " ) : ( "\t[%s]->GetWeaponInSlot( " ), pchVarName );
  2943. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "%i ", iTemp );
  2944. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")->AmmoEmpty()\n" );
  2945. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BasePlayer returned NULL!\n" );
  2946. }
  2947. return false;
  2948. }
  2949. CBaseCombatWeapon *pBaseCombatWeapon = NULL;
  2950. // Get the weapon in variable slot
  2951. for ( int iWeapon = 0; iWeapon < MAX_WEAPONS; iWeapon++ )
  2952. {
  2953. CBaseCombatWeapon *pBaseCombatWeaponTemp = pBasePlayer->ActivePlayerCombatCharacter()->GetWeapon( iWeapon );
  2954. if ( pBaseCombatWeaponTemp )
  2955. {
  2956. if ( pBaseCombatWeaponTemp->GetSlot() == iTemp )
  2957. {
  2958. pBaseCombatWeapon = pBaseCombatWeaponTemp;
  2959. break;
  2960. }
  2961. }
  2962. }
  2963. if ( !pBaseCombatWeapon )
  2964. {
  2965. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2966. {
  2967. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->GetWeaponInSlot( " ) : ( "\t[%s]->GetWeaponInSlot( " ), pchVarName );
  2968. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "%i ", iTemp );
  2969. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")->AmmoEmpty()\n" );
  2970. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar GetWeaponInSlot returned NULL!\n" );
  2971. }
  2972. return false;
  2973. }
  2974. // Check if the ammo is empty
  2975. int iPlayerAmmo = pBaseCombatWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  2976. bool bAmmoEmpty = ( iPlayerAmmo <= 0 );
  2977. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2978. {
  2979. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->GetWeaponInSlot( " ) : ( "\t[%s]->GetWeaponInSlot( " ), pchVarName );
  2980. ConColorMsg( CBaseLesson::m_rgbaVerboseSuccess, "%i ", iTemp );
  2981. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")->AmmoEmpty() " );
  2982. ConColorMsg( CBaseLesson::m_rgbaVerboseName, ( bAmmoEmpty ) ? ( "true" ) : ( "false" ) );
  2983. ConColorMsg(CBaseLesson::m_rgbaVerbosePlain, " )\n" );
  2984. }
  2985. return ( bNot ) ? ( !bAmmoEmpty ) : ( bAmmoEmpty );
  2986. }
  2987. case LESSON_ACTION_WEAPON_CAN_USE:
  2988. {
  2989. C_BaseCombatWeapon *pBaseCombatWeapon = dynamic_cast<C_BaseCombatWeapon*>( pParam );
  2990. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  2991. if ( !pBasePlayer )
  2992. {
  2993. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  2994. {
  2995. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->Weapon_CanUse([%s])\n" ) : ( "\t[%s]->Weapon_CanUse([%s])\n" ), pchVarName, pchParamName->String() );
  2996. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as BasePlayer returned NULL!\n" );
  2997. }
  2998. return false;
  2999. }
  3000. if ( !pBaseCombatWeapon )
  3001. {
  3002. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3003. {
  3004. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->Weapon_CanUse([%s])\n" ) : ( "\t[%s]->Weapon_CanUse([%s])\n" ), pchVarName, pchParamName->String() );
  3005. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tParam BaseCombatWeapon returned NULL!\n" );
  3006. }
  3007. return false;
  3008. }
  3009. bool bCanEquip = pBasePlayer->Weapon_CanUse( pBaseCombatWeapon );
  3010. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3011. {
  3012. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\t![%s]->Weapon_CanUse([%s]) " ) : ( "\t[%s]->Weapon_CanUse([%s]) " ), pchVarName, pchParamName->String() );
  3013. ConColorMsg( CBaseLesson::m_rgbaVerboseName, ( bCanEquip ) ? ( "true\n" ) : ( "false\n" ) );
  3014. }
  3015. return ( bNot ) ? ( !bCanEquip ) : ( bCanEquip );
  3016. }
  3017. case LESSON_ACTION_USE_TARGET_IS:
  3018. {
  3019. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  3020. if ( !pBasePlayer )
  3021. {
  3022. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3023. {
  3024. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\tC_BaseEntity::Instance([%s]->GetUseEntity()) != [%s]\n" ) : ( "\tC_BaseEntity::Instance([%s]->GetUseEntity()) == [%s]\n" ), pchVarName, pchParamName->String() );
  3025. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as Player returned NULL!\n" );
  3026. }
  3027. return false;
  3028. }
  3029. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3030. {
  3031. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( "\tC_BaseEntity::Instance([%s]->GetUseEntity()) != [%s]\n" ) : ( "\tC_BaseEntity::Instance([%s]->GetUseEntity()) == [%s]\n" ), pchVarName, pchParamName->String() );
  3032. }
  3033. return ( bNot ) ? ( C_BaseEntity::Instance( pBasePlayer->GetUseEntity() ) != pParam ) : ( C_BaseEntity::Instance( pBasePlayer->GetUseEntity() ) == pParam );
  3034. }
  3035. case LESSON_ACTION_GET_USE_TARGET:
  3036. {
  3037. int iTemp = static_cast<int>( fParam );
  3038. if ( iTemp <= 0 || iTemp > 2 )
  3039. {
  3040. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3041. {
  3042. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[entityINVALID] = C_BaseEntity::Instance([%s]->GetUseEntity())\n", pchVarName );
  3043. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tParam selecting string is out of range!\n" );
  3044. }
  3045. return false;
  3046. }
  3047. // Use entity2 if it was specified, otherwise, use entity1
  3048. CHandle<C_BaseEntity> *pHandle;
  3049. char const *pchParamNameTemp = NULL;
  3050. if ( iTemp == 2 )
  3051. {
  3052. pHandle = &m_hEntity2;
  3053. pchParamNameTemp = "entity2";
  3054. }
  3055. else
  3056. {
  3057. pHandle = &m_hEntity1;
  3058. pchParamNameTemp = "entity1";
  3059. }
  3060. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  3061. if ( !pBasePlayer )
  3062. {
  3063. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3064. {
  3065. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = C_BaseEntity::Instance([%s]->GetUseEntity())\n", pchParamNameTemp, pchVarName );
  3066. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as Player returned NULL!\n" );
  3067. }
  3068. return false;
  3069. }
  3070. pHandle->Set( C_BaseEntity::Instance( pBasePlayer->GetUseEntity() ) );
  3071. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3072. {
  3073. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = C_BaseEntity::Instance([%s]->GetUseEntity())\n", pchParamNameTemp, pchVarName );
  3074. }
  3075. return true;
  3076. }
  3077. case LESSON_ACTION_GET_POTENTIAL_USE_TARGET:
  3078. {
  3079. int iTemp = static_cast<int>( fParam );
  3080. if ( iTemp <= 0 || iTemp > 2 )
  3081. {
  3082. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3083. {
  3084. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[entityINVALID] = C_BaseEntity::Instance([%s]->GetPotentialUseEntity())\n", pchVarName );
  3085. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tParam selecting string is out of range!\n" );
  3086. }
  3087. return false;
  3088. }
  3089. // Use entity2 if it was specified, otherwise, use entity1
  3090. CHandle<C_BaseEntity> *pHandle;
  3091. char const *pchParamNameTemp = NULL;
  3092. if ( iTemp == 2 )
  3093. {
  3094. pHandle = &m_hEntity2;
  3095. pchParamNameTemp = "entity2";
  3096. }
  3097. else
  3098. {
  3099. pHandle = &m_hEntity1;
  3100. pchParamNameTemp = "entity1";
  3101. }
  3102. C_BasePlayer *pBasePlayer = ToBasePlayer( pVar );
  3103. if ( !pBasePlayer )
  3104. {
  3105. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3106. {
  3107. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = C_BaseEntity::Instance([%s]->GetPotentialUseEntity())\n", pchParamNameTemp, pchVarName );
  3108. ConColorMsg( CBaseLesson::m_rgbaVerboseClose, "\tVar handle as Player returned NULL!\n" );
  3109. }
  3110. return false;
  3111. }
  3112. pHandle->Set( C_BaseEntity::Instance( pBasePlayer->GetPotentialUseEntity() ) );
  3113. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3114. {
  3115. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s] = C_BaseEntity::Instance([%s]->GetPotentialUseEntity())\n", pchParamNameTemp, pchVarName );
  3116. }
  3117. return true;
  3118. }
  3119. }
  3120. DevWarning( "Invalid lesson action type used with \"%s\" variable type.\n", pchVarName );
  3121. return false;
  3122. }
  3123. bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const char *pchVarName, CGameInstructorSymbol *pchVar, const CGameInstructorSymbol *pchParamName, const char *pchParam )
  3124. {
  3125. switch ( iAction )
  3126. {
  3127. case LESSON_ACTION_REFERENCE_OPEN:
  3128. {
  3129. const CBaseLesson *pLesson = GetGameInstructor().GetLesson( pchParamName->String() );
  3130. if ( !pLesson )
  3131. {
  3132. DevWarning( "Invalid lesson specified: \"%s\".", pchParamName->String() );
  3133. return false;
  3134. }
  3135. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3136. {
  3137. ConColorMsg( Color( 64, 128, 255, 255 ), ( bNot ) ? ( "\t!( [\"%s\"]->IsInstanceActive() " ) : ( "\t( [\"%s\"]->IsInstanceActive() " ), pchParamName->String() );
  3138. ConColorMsg( Color( 255, 255, 255, 255 ), "\"%s\"", (pLesson->IsInstanceActive() ? "true" : "false") );
  3139. ConColorMsg( Color( 64, 128, 255, 255 ), " )\n" );
  3140. }
  3141. return ( bNot ) ? ( !pLesson->IsInstanceActive() ) : ( pLesson->IsInstanceActive() );
  3142. }
  3143. case LESSON_ACTION_SET:
  3144. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3145. {
  3146. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcpy([%s], [%s] ", pchVarName, pchParamName->String() );
  3147. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  3148. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  3149. }
  3150. *pchVar = pchParam;
  3151. return true;
  3152. case LESSON_ACTION_ADD:
  3153. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3154. {
  3155. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcat([%s], [%s] ", pchVarName, pchParamName->String() );
  3156. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  3157. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ")\n" );
  3158. }
  3159. char szTemp[ 256 ];
  3160. Q_strncpy( szTemp, pchVar->String(), sizeof( szTemp ) );
  3161. Q_strncat( szTemp, pchParam, sizeof( szTemp ) );
  3162. *pchVar = szTemp;
  3163. return true;
  3164. case LESSON_ACTION_IS:
  3165. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3166. {
  3167. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcmp([%s] ", pchVarName );
  3168. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchVar->String() );
  3169. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  3170. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  3171. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ") != 0\n" ) : ( ") == 0\n" ) );
  3172. }
  3173. return ( bNot ) ? ( Q_strcmp( pchVar->String(), pchParam ) != 0 ) : ( Q_strcmp( pchVar->String(), pchParam ) == 0 );
  3174. case LESSON_ACTION_HAS_PREFIX:
  3175. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3176. {
  3177. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tStringHasPrefix([%s] ", pchVarName );
  3178. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchVar->String() );
  3179. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  3180. ConColorMsg( CBaseLesson::m_rgbaVerboseName, "\"%s\"", pchParam );
  3181. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ") == false\n" ) : ( ") == true\n" ) );
  3182. }
  3183. return ( bNot ) ? ( !StringHasPrefix( pchVar->String(), pchParam ) ) : ( StringHasPrefix( pchVar->String(), pchParam ) );
  3184. case LESSON_ACTION_LESS_THAN:
  3185. if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
  3186. {
  3187. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\tQ_strcmp([%s] ", pchVarName );
  3188. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\"%s\"", pchVar->String() );
  3189. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ", [%s] ", pchParamName->String() );
  3190. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\"%s\"", pchParam );
  3191. ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ") >= 0\n" ) : ( ") < 0\n" ) );
  3192. }
  3193. return ( bNot ) ? ( Q_strcmp( pchVar->String(), pchParam ) >= 0 ) : ( Q_strcmp( pchVar->String(), pchParam ) < 0 );
  3194. }
  3195. DevWarning( "Invalid lesson action type used with \"%s\" variable type.\n", pchVarName );
  3196. return false;
  3197. }
  3198. LessonEvent_t * CScriptedIconLesson::AddOpenEvent( void )
  3199. {
  3200. int iNewLessonEvent = m_OpenEvents.AddToTail();
  3201. return &(m_OpenEvents[ iNewLessonEvent ]);
  3202. }
  3203. LessonEvent_t * CScriptedIconLesson::AddCloseEvent( void )
  3204. {
  3205. int iNewLessonEvent = m_CloseEvents.AddToTail();
  3206. return &(m_CloseEvents[ iNewLessonEvent ]);
  3207. }
  3208. LessonEvent_t * CScriptedIconLesson::AddSuccessEvent( void )
  3209. {
  3210. int iNewLessonEvent = m_SuccessEvents.AddToTail();
  3211. return &(m_SuccessEvents[ iNewLessonEvent ]);
  3212. }
  3213. LessonEvent_t * CScriptedIconLesson::AddOnOpenEvent( void )
  3214. {
  3215. int iNewLessonEvent = m_OnOpenEvents.AddToTail();
  3216. return &(m_OnOpenEvents[ iNewLessonEvent ]);
  3217. }
  3218. LessonEvent_t * CScriptedIconLesson::AddUpdateEvent( void )
  3219. {
  3220. int iNewLessonEvent = m_UpdateEvents.AddToTail();
  3221. return &(m_UpdateEvents[ iNewLessonEvent ]);
  3222. }
  3223. // Static method to init the keyvalues symbols used for comparisons
  3224. void CScriptedIconLesson::PreReadLessonsFromFile()
  3225. {
  3226. static bool bFirstTime = true;
  3227. if ( !bFirstTime )
  3228. return;
  3229. bFirstTime = false;
  3230. // Run init info call macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  3231. #define LESSON_VARIABLE_MACRO LESSON_VARIABLE_INIT_SYMBOL
  3232. #define LESSON_VARIABLE_MACRO_BOOL LESSON_VARIABLE_INIT_SYMBOL
  3233. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_VARIABLE_INIT_SYMBOL
  3234. #define LESSON_VARIABLE_MACRO_STRING LESSON_VARIABLE_INIT_SYMBOL
  3235. LESSON_VARIABLE_FACTORY
  3236. #undef LESSON_VARIABLE_MACRO
  3237. #undef LESSON_VARIABLE_MACRO_BOOL
  3238. #undef LESSON_VARIABLE_MACRO_EHANDLE
  3239. #undef LESSON_VARIABLE_MACRO_STRING
  3240. // And build the map of variable name to enum
  3241. // Run string to int macros on all scriptable variables (see: LESSON_VARIABLE_FACTORY definition)
  3242. #define LESSON_VARIABLE_MACRO LESSON_SCRIPT_STRING_ADD_TO_MAP
  3243. #define LESSON_VARIABLE_MACRO_BOOL LESSON_SCRIPT_STRING_ADD_TO_MAP
  3244. #define LESSON_VARIABLE_MACRO_EHANDLE LESSON_SCRIPT_STRING_ADD_TO_MAP
  3245. #define LESSON_VARIABLE_MACRO_STRING LESSON_SCRIPT_STRING_ADD_TO_MAP
  3246. LESSON_VARIABLE_FACTORY
  3247. #undef LESSON_VARIABLE_MACRO
  3248. #undef LESSON_VARIABLE_MACRO_BOOL
  3249. #undef LESSON_VARIABLE_MACRO_EHANDLE
  3250. #undef LESSON_VARIABLE_MACRO_STRING
  3251. // Set up mapping of field types
  3252. g_TypeToParamTypeMap.Insert( "float", FIELD_FLOAT );
  3253. g_TypeToParamTypeMap.Insert( "string", FIELD_STRING );
  3254. g_TypeToParamTypeMap.Insert( "int", FIELD_INTEGER );
  3255. g_TypeToParamTypeMap.Insert( "integer", FIELD_INTEGER );
  3256. g_TypeToParamTypeMap.Insert( "short", FIELD_INTEGER );
  3257. g_TypeToParamTypeMap.Insert( "long", FIELD_INTEGER );
  3258. g_TypeToParamTypeMap.Insert( "bool", FIELD_BOOLEAN );
  3259. g_TypeToParamTypeMap.Insert( "player", FIELD_CUSTOM );
  3260. g_TypeToParamTypeMap.Insert( "entity", FIELD_EHANDLE );
  3261. g_TypeToParamTypeMap.Insert( "convar", FIELD_EMBEDDED );
  3262. g_TypeToParamTypeMap.Insert( "void", FIELD_VOID );
  3263. // Set up the lesson action map
  3264. CScriptedIconLesson::LessonActionMap.Insert( "scope in", LESSON_ACTION_SCOPE_IN );
  3265. CScriptedIconLesson::LessonActionMap.Insert( "scope out", LESSON_ACTION_SCOPE_OUT );
  3266. CScriptedIconLesson::LessonActionMap.Insert( "close", LESSON_ACTION_CLOSE );
  3267. CScriptedIconLesson::LessonActionMap.Insert( "success", LESSON_ACTION_SUCCESS );
  3268. CScriptedIconLesson::LessonActionMap.Insert( "lock", LESSON_ACTION_LOCK );
  3269. CScriptedIconLesson::LessonActionMap.Insert( "present complete", LESSON_ACTION_PRESENT_COMPLETE );
  3270. CScriptedIconLesson::LessonActionMap.Insert( "present start", LESSON_ACTION_PRESENT_START );
  3271. CScriptedIconLesson::LessonActionMap.Insert( "present end", LESSON_ACTION_PRESENT_END );
  3272. CScriptedIconLesson::LessonActionMap.Insert( "reference open", LESSON_ACTION_REFERENCE_OPEN );
  3273. CScriptedIconLesson::LessonActionMap.Insert( "is multiplayer", LESSON_ACTION_IS_MULTIPLAYER );
  3274. CScriptedIconLesson::LessonActionMap.Insert( "set", LESSON_ACTION_SET );
  3275. CScriptedIconLesson::LessonActionMap.Insert( "add", LESSON_ACTION_ADD );
  3276. CScriptedIconLesson::LessonActionMap.Insert( "subtract", LESSON_ACTION_SUBTRACT );
  3277. CScriptedIconLesson::LessonActionMap.Insert( "multiply", LESSON_ACTION_MULTIPLY );
  3278. CScriptedIconLesson::LessonActionMap.Insert( "is", LESSON_ACTION_IS );
  3279. CScriptedIconLesson::LessonActionMap.Insert( "less than", LESSON_ACTION_LESS_THAN );
  3280. CScriptedIconLesson::LessonActionMap.Insert( "has prefix", LESSON_ACTION_HAS_PREFIX );
  3281. CScriptedIconLesson::LessonActionMap.Insert( "has bit", LESSON_ACTION_HAS_BIT );
  3282. CScriptedIconLesson::LessonActionMap.Insert( "bit count is", LESSON_ACTION_BIT_COUNT_IS );
  3283. CScriptedIconLesson::LessonActionMap.Insert( "bit count less than", LESSON_ACTION_BIT_COUNT_LESS_THAN );
  3284. CScriptedIconLesson::LessonActionMap.Insert( "get distance", LESSON_ACTION_GET_DISTANCE );
  3285. CScriptedIconLesson::LessonActionMap.Insert( "get angular distance", LESSON_ACTION_GET_ANGULAR_DISTANCE );
  3286. CScriptedIconLesson::LessonActionMap.Insert( "get player display name", LESSON_ACTION_GET_PLAYER_DISPLAY_NAME );
  3287. CScriptedIconLesson::LessonActionMap.Insert( "classname is", LESSON_ACTION_CLASSNAME_IS );
  3288. CScriptedIconLesson::LessonActionMap.Insert( "modelname is", LESSON_ACTION_MODELNAME_IS );
  3289. CScriptedIconLesson::LessonActionMap.Insert( "team is", LESSON_ACTION_TEAM_IS );
  3290. CScriptedIconLesson::LessonActionMap.Insert( "health less than", LESSON_ACTION_HEALTH_LESS_THAN );
  3291. CScriptedIconLesson::LessonActionMap.Insert( "health percentage less than", LESSON_ACTION_HEALTH_PERCENTAGE_LESS_THAN );
  3292. CScriptedIconLesson::LessonActionMap.Insert( "get active weapon", LESSON_ACTION_GET_ACTIVE_WEAPON );
  3293. CScriptedIconLesson::LessonActionMap.Insert( "weapon is", LESSON_ACTION_WEAPON_IS );
  3294. CScriptedIconLesson::LessonActionMap.Insert( "weapon has", LESSON_ACTION_WEAPON_HAS );
  3295. CScriptedIconLesson::LessonActionMap.Insert( "get active weapon slot", LESSON_ACTION_GET_ACTIVE_WEAPON_SLOT );
  3296. CScriptedIconLesson::LessonActionMap.Insert( "get weapon slot", LESSON_ACTION_GET_WEAPON_SLOT );
  3297. CScriptedIconLesson::LessonActionMap.Insert( "get weapon in slot", LESSON_ACTION_GET_WEAPON_IN_SLOT );
  3298. CScriptedIconLesson::LessonActionMap.Insert( "clip percentage less than", LESSON_ACTION_CLIP_PERCENTAGE_LESS_THAN);
  3299. CScriptedIconLesson::LessonActionMap.Insert( "weapon ammo low", LESSON_ACTION_WEAPON_AMMO_LOW );
  3300. CScriptedIconLesson::LessonActionMap.Insert( "weapon ammo full", LESSON_ACTION_WEAPON_AMMO_FULL );
  3301. CScriptedIconLesson::LessonActionMap.Insert( "weapon ammo empty", LESSON_ACTION_WEAPON_AMMO_EMPTY );
  3302. CScriptedIconLesson::LessonActionMap.Insert( "weapon can use", LESSON_ACTION_WEAPON_CAN_USE );
  3303. CScriptedIconLesson::LessonActionMap.Insert( "use target is", LESSON_ACTION_USE_TARGET_IS );
  3304. CScriptedIconLesson::LessonActionMap.Insert( "get use target", LESSON_ACTION_GET_USE_TARGET );
  3305. CScriptedIconLesson::LessonActionMap.Insert( "get potential use target", LESSON_ACTION_GET_POTENTIAL_USE_TARGET );
  3306. // Add mod actions to the map
  3307. Mod_PreReadLessonsFromFile();
  3308. }