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

617 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Base combat character with no AI
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //=============================================================================//
  9. #include "cbase.h"
  10. #include "convar.h"
  11. #include "ai_basenpc.h"
  12. #include "tier1/strtools.h"
  13. #include "ai_activity.h"
  14. #include "ai_schedule.h"
  15. #include "ai_default.h"
  16. #include "ai_hint.h"
  17. #include "bitstring.h"
  18. #include "stringregistry.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. //-----------------------------------------------------------------------------
  22. // Init static variables
  23. //-----------------------------------------------------------------------------
  24. CAI_SchedulesManager g_AI_SchedulesManager;
  25. //-----------------------------------------------------------------------------
  26. // Purpose: Delete all the string registries
  27. // Input :
  28. // Output :
  29. //-----------------------------------------------------------------------------
  30. void CAI_SchedulesManager::DestroyStringRegistries(void)
  31. {
  32. CAI_BaseNPC::GetSchedulingSymbols()->Clear();
  33. CAI_BaseNPC::gm_SquadSlotNamespace.Clear();
  34. delete CAI_BaseNPC::m_pActivitySR;
  35. CAI_BaseNPC::m_pActivitySR = NULL;
  36. CAI_BaseNPC::m_iNumActivities = 0;
  37. }
  38. void CAI_SchedulesManager::CreateStringRegistries( void )
  39. {
  40. CAI_BaseNPC::GetSchedulingSymbols()->Clear();
  41. CAI_BaseNPC::gm_SquadSlotNamespace.Clear();
  42. CAI_BaseNPC::m_pActivitySR = new CStringRegistry();
  43. CAI_BaseNPC::m_pEventSR = new CStringRegistry();
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose: Load all the schedules
  47. // Input :
  48. // Output :
  49. //-----------------------------------------------------------------------------
  50. void CAI_BaseNPC::InitSchedulingTables()
  51. {
  52. CAI_BaseNPC::gm_ClassScheduleIdSpace.Init( "CAI_BaseNPC", CAI_BaseNPC::GetSchedulingSymbols() );
  53. CAI_BaseNPC::InitDefaultScheduleSR();
  54. CAI_BaseNPC::InitDefaultConditionSR();
  55. CAI_BaseNPC::InitDefaultTaskSR();
  56. CAI_BaseNPC::InitDefaultActivitySR();
  57. CAI_BaseNPC::InitDefaultSquadSlotSR();
  58. }
  59. bool CAI_SchedulesManager::LoadAllSchedules(void)
  60. {
  61. // If I haven't loaded schedules yet
  62. if (!CAI_SchedulesManager::allSchedules)
  63. {
  64. // Init defaults
  65. CAI_BaseNPC::InitSchedulingTables();
  66. if (!CAI_BaseNPC::LoadDefaultSchedules())
  67. {
  68. CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI;
  69. DevMsg("ERROR: Mistake in default schedule definitions, AI Disabled.\n");
  70. }
  71. // UNDONE: enable this after the schedules are all loaded (right now some load in monster spawns)
  72. #if 0
  73. // If not in developer mode, free the string memory. Otherwise
  74. // keep it around for debugging information
  75. if (!g_pDeveloper->GetInt())
  76. {
  77. ClearStringRegistries();
  78. }
  79. #endif
  80. }
  81. return true;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose: Creates and returns schedule of the given name
  85. // This should eventually be replaced when we convert to
  86. // non-hard coded schedules
  87. // Input :
  88. // Output :
  89. //-----------------------------------------------------------------------------
  90. CAI_Schedule *CAI_SchedulesManager::CreateSchedule(char *name, int schedule_id)
  91. {
  92. // Allocate schedule
  93. CAI_Schedule *pSched = new CAI_Schedule(name,schedule_id,CAI_SchedulesManager::allSchedules);
  94. CAI_SchedulesManager::allSchedules = pSched;
  95. // Return schedule
  96. return pSched;
  97. }
  98. //-----------------------------------------------------------------------------
  99. // Purpose: Given text name of a NPC state returns its ID number
  100. // Input :
  101. // Output :
  102. //-----------------------------------------------------------------------------
  103. int CAI_SchedulesManager::GetStateID(const char *state_name)
  104. {
  105. if (!stricmp(state_name,"NONE")) { return NPC_STATE_NONE; }
  106. else if (!stricmp(state_name,"IDLE")) { return NPC_STATE_IDLE; }
  107. else if (!stricmp(state_name,"COMBAT")) { return NPC_STATE_COMBAT; }
  108. else if (!stricmp(state_name,"PRONE")) { return NPC_STATE_PRONE; }
  109. else if (!stricmp(state_name,"ALERT")) { return NPC_STATE_ALERT; }
  110. else if (!stricmp(state_name,"SCRIPT")) { return NPC_STATE_SCRIPT; }
  111. else if (!stricmp(state_name,"PLAYDEAD")) { return NPC_STATE_PLAYDEAD; }
  112. else if (!stricmp(state_name,"DEAD")) { return NPC_STATE_DEAD; }
  113. else return -1;
  114. }
  115. //-----------------------------------------------------------------------------
  116. // Purpose: Given text name of a memory bit returns its ID number
  117. // Input :
  118. // Output :
  119. //-----------------------------------------------------------------------------
  120. int CAI_SchedulesManager::GetMemoryID(const char *state_name)
  121. {
  122. if (!stricmp(state_name,"PROVOKED")) { return bits_MEMORY_PROVOKED; }
  123. else if (!stricmp(state_name,"INCOVER")) { return bits_MEMORY_INCOVER; }
  124. else if (!stricmp(state_name,"SUSPICIOUS")) { return bits_MEMORY_SUSPICIOUS; }
  125. else if (!stricmp(state_name,"PATH_FAILED")) { return bits_MEMORY_PATH_FAILED; }
  126. else if (!stricmp(state_name,"FLINCHED")) { return bits_MEMORY_FLINCHED; }
  127. else if (!stricmp(state_name,"TOURGUIDE")) { return bits_MEMORY_TOURGUIDE; }
  128. else if (!stricmp(state_name,"LOCKED_HINT")) { return bits_MEMORY_LOCKED_HINT; }
  129. else if (!stricmp(state_name,"TURNING")) { return bits_MEMORY_TURNING; }
  130. else if (!stricmp(state_name,"TURNHACK")) { return bits_MEMORY_TURNHACK; }
  131. else if (!stricmp(state_name,"CUSTOM4")) { return bits_MEMORY_CUSTOM4; }
  132. else if (!stricmp(state_name,"CUSTOM3")) { return bits_MEMORY_CUSTOM3; }
  133. else if (!stricmp(state_name,"CUSTOM2")) { return bits_MEMORY_CUSTOM2; }
  134. else if (!stricmp(state_name,"CUSTOM1")) { return bits_MEMORY_CUSTOM1; }
  135. else return -1;
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. // Input : *token -
  140. // Output : int
  141. //-----------------------------------------------------------------------------
  142. int CAI_SchedulesManager::GetPathID( const char *token )
  143. {
  144. if ( !stricmp( token, "TRAVEL" ) ) { return PATH_TRAVEL; }
  145. else if ( !stricmp( token, "LOS" ) ) { return PATH_LOS; }
  146. // else if ( !stricmp( token, "FLANK" ) ) { return PATH_FLANK; }
  147. // else if ( !stricmp( token, "FLANK_LOS" ) ) { return PATH_FLANK_LOS; }
  148. else if ( !stricmp( token, "COVER" ) ) { return PATH_COVER; }
  149. // else if ( !stricmp( token, "COVER_LOS" ) ) { return PATH_COVER_LOS; }
  150. return -1;
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Purpose:
  154. // Input : *token -
  155. // Output : int
  156. //-----------------------------------------------------------------------------
  157. int CAI_SchedulesManager::GetGoalID( const char *token )
  158. {
  159. if ( !stricmp( token, "ENEMY" ) ) { return GOAL_ENEMY; }
  160. else if ( !stricmp( token, "ENEMY_LKP" ) ) { return GOAL_ENEMY_LKP; }
  161. else if ( !stricmp( token, "TARGET" ) ) { return GOAL_TARGET; }
  162. else if ( !stricmp( token, "SAVED_POSITION" ) ) { return GOAL_SAVED_POSITION; }
  163. return -1;
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Purpose: Read data on schedules
  167. // As I'm parsing a human generated file, give a lot of error output
  168. // Output: true - if data successfully read
  169. // false - if data load fails
  170. //-----------------------------------------------------------------------------
  171. bool CAI_SchedulesManager::LoadSchedulesFromBuffer( const char *prefix, const char *pStartFile, CAI_ClassScheduleIdSpace *pIdSpace )
  172. {
  173. char token[1024];
  174. char save_token[1024];
  175. const char *pfile = engine->ParseFile(pStartFile, token, sizeof( token ) );
  176. while (!stricmp("Schedule",token))
  177. {
  178. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  179. // -----------------------------
  180. // Check for duplicate schedule
  181. // -----------------------------
  182. if (GetScheduleByName(token))
  183. {
  184. DevMsg("ERROR: file contains a schedule (%s) that has already been defined!\n",token);
  185. DevMsg(" Aborting schedule load.\n");
  186. Assert(0);
  187. return false;
  188. }
  189. int scheduleID = CAI_BaseNPC::GetScheduleID(token);
  190. if (scheduleID == -1)
  191. {
  192. DevMsg( "ERROR: LoadSchd (%s): Unknown schedule type (%s)\n", prefix, token);
  193. // FIXME: .sch's not being in code/perforce makes it hard to share branches between developers
  194. // for now, just stop processing this entities schedules if one is found that isn't in the schedule registry
  195. break;
  196. // return false;
  197. }
  198. CAI_Schedule *new_schedule = CreateSchedule(token,scheduleID);
  199. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  200. if (stricmp(token,"Tasks"))
  201. {
  202. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting 'Tasks' keyword.\n",prefix,new_schedule->GetName());
  203. Assert(0);
  204. return false;
  205. }
  206. // ==========================
  207. // Now read in the tasks
  208. // ==========================
  209. // Store in temp array until number of tasks is known
  210. Task_t tempTask[50];
  211. int taskNum = 0;
  212. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  213. while ((token[0]!='\0') && (stricmp("Interrupts",token)))
  214. {
  215. // Convert generic ID to sub-class specific enum
  216. int taskID = CAI_BaseNPC::GetTaskID(token);
  217. tempTask[taskNum].iTask = (pIdSpace) ? pIdSpace->TaskGlobalToLocal(taskID) : AI_RemapFromGlobal( taskID );
  218. // If not a valid condition, send a warning message
  219. if (tempTask[taskNum].iTask == -1)
  220. {
  221. DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown task %s!\n", prefix,new_schedule->GetName(), token);
  222. Assert(0);
  223. return false;
  224. }
  225. Assert( AI_IdIsLocal( tempTask[taskNum].iTask ) );
  226. // Read in the task argument
  227. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  228. if (!stricmp("Activity",token))
  229. {
  230. // Skip the ";", but make sure it's present
  231. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  232. if (stricmp(token,":"))
  233. {
  234. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'ACTIVITY.\n",prefix,new_schedule->GetName());
  235. Assert(0);
  236. return false;
  237. }
  238. // Load the activity and make sure its valid
  239. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  240. tempTask[taskNum].flTaskData = CAI_BaseNPC::GetActivityID(token);
  241. if (tempTask[taskNum].flTaskData == -1)
  242. {
  243. DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown activity %s!\n", prefix,new_schedule->GetName(), token);
  244. Assert(0);
  245. return false;
  246. }
  247. }
  248. else if (!stricmp("Task",token))
  249. {
  250. // Skip the ";", but make sure it's present
  251. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  252. if (stricmp(token,":"))
  253. {
  254. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'ACTIVITY.\n",prefix,new_schedule->GetName());
  255. Assert(0);
  256. return false;
  257. }
  258. // Load the activity and make sure its valid
  259. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  260. // Convert generic ID to sub-class specific enum
  261. int taskID = CAI_BaseNPC::GetTaskID(token);
  262. tempTask[taskNum].flTaskData = (pIdSpace) ? pIdSpace->TaskGlobalToLocal(taskID) : AI_RemapFromGlobal( taskID );
  263. if (tempTask[taskNum].flTaskData == -1)
  264. {
  265. DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown task %s!\n", prefix,new_schedule->GetName(), token);
  266. Assert(0);
  267. return false;
  268. }
  269. }
  270. else if (!stricmp("Schedule",token))
  271. {
  272. // Skip the ";", but make sure it's present
  273. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  274. if (stricmp(token,":"))
  275. {
  276. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'ACTIVITY.\n",prefix,new_schedule->GetName());
  277. Assert(0);
  278. return false;
  279. }
  280. // Load the schedule and make sure its valid
  281. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  282. // Convert generic ID to sub-class specific enum
  283. int schedID = CAI_BaseNPC::GetScheduleID(token);
  284. tempTask[taskNum].flTaskData = (pIdSpace) ? pIdSpace->ScheduleGlobalToLocal(schedID) : AI_RemapFromGlobal( schedID );
  285. if (tempTask[taskNum].flTaskData == -1)
  286. {
  287. DevMsg( "ERROR: LoadSchd %d (%s): (%s) Unknown shedule %s!\n", __LINE__, prefix,new_schedule->GetName(), token);
  288. Assert(0);
  289. return false;
  290. }
  291. }
  292. else if (!stricmp("State",token))
  293. {
  294. // Skip the ";", but make sure it's present
  295. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  296. if (stricmp(token,":"))
  297. {
  298. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'STATE.\n",prefix,new_schedule->GetName());
  299. Assert(0);
  300. return false;
  301. }
  302. // Load the activity and make sure its valid
  303. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  304. tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetStateID(token);
  305. if (tempTask[taskNum].flTaskData == -1)
  306. {
  307. DevMsg( "ERROR: LoadSchd %d (%s): (%s) Unknown shedule %s!\n", __LINE__, prefix,new_schedule->GetName(), token);
  308. Assert(0);
  309. return false;
  310. }
  311. }
  312. else if (!stricmp("Memory",token))
  313. {
  314. // Skip the ";", but make sure it's present
  315. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  316. if (stricmp(token,":"))
  317. {
  318. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'STATE.\n",prefix,new_schedule->GetName());
  319. Assert(0);
  320. return false;
  321. }
  322. // Load the activity and make sure its valid
  323. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  324. tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetMemoryID(token);
  325. if (tempTask[taskNum].flTaskData == -1)
  326. {
  327. DevMsg( "ERROR: LoadSchd %d (%s): (%s) Unknown shedule %s!\n", __LINE__, prefix,new_schedule->GetName(), token);
  328. Assert(0);
  329. return false;
  330. }
  331. }
  332. else if (!stricmp("Path",token))
  333. {
  334. // Skip the ";", but make sure it's present
  335. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  336. if (stricmp(token,":"))
  337. {
  338. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'PATH.\n",prefix,new_schedule->GetName());
  339. Assert(0);
  340. return false;
  341. }
  342. // Load the activity and make sure its valid
  343. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  344. tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetPathID( token );
  345. if (tempTask[taskNum].flTaskData == -1)
  346. {
  347. DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown path type %s!\n", prefix,new_schedule->GetName(), token);
  348. Assert(0);
  349. return false;
  350. }
  351. }
  352. else if (!stricmp("Goal",token))
  353. {
  354. // Skip the ";", but make sure it's present
  355. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  356. if (stricmp(token,":"))
  357. {
  358. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'GOAL.\n",prefix,new_schedule->GetName());
  359. Assert(0);
  360. return false;
  361. }
  362. // Load the activity and make sure its valid
  363. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  364. tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetGoalID( token );
  365. if (tempTask[taskNum].flTaskData == -1)
  366. {
  367. DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown goal type %s!\n", prefix,new_schedule->GetName(), token);
  368. Assert(0);
  369. return false;
  370. }
  371. }
  372. else if ( !stricmp( "HintFlags",token ) )
  373. {
  374. // Skip the ":", but make sure it's present
  375. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  376. if (stricmp(token,":"))
  377. {
  378. DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'HINTFLAG'\n",prefix,new_schedule->GetName());
  379. Assert(0);
  380. return false;
  381. }
  382. // Load the flags and make sure they are valid
  383. pfile = engine->ParseFile( pfile, token, sizeof( token ) );
  384. tempTask[taskNum].flTaskData = CAI_HintManager::GetFlags( token );
  385. if (tempTask[taskNum].flTaskData == -1)
  386. {
  387. DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown hint flag type %s!\n", prefix,new_schedule->GetName(), token);
  388. Assert(0);
  389. return false;
  390. }
  391. }
  392. else if (!stricmp("Interrupts",token) || !strnicmp("TASK_",token,5) )
  393. {
  394. // a parse error. Interrupts is the next section, TASK_ is probably the next task, missing task argument?
  395. Warning( "ERROR: LoadSchd (%s): (%s) Bad syntax at task #%d (wasn't expecting %s)\n", prefix, new_schedule->GetName(), taskNum, token);
  396. Assert(0);
  397. return false;
  398. }
  399. else
  400. {
  401. tempTask[taskNum].flTaskData = atof(token);
  402. }
  403. taskNum++;
  404. // Read the next token
  405. Q_strncpy(save_token,token,sizeof(save_token));
  406. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  407. // Check for malformed task argument type
  408. if (!stricmp(token,":"))
  409. {
  410. DevMsg( "ERROR: LoadSchd (%s): Schedule (%s),\n Task (%d), has a malformed AI Task Argument = (%s)\n",
  411. prefix,new_schedule->GetName(),taskID,save_token);
  412. Assert(0);
  413. return false;
  414. }
  415. }
  416. // Now copy the tasks into the new schedule
  417. new_schedule->m_iNumTasks = taskNum;
  418. new_schedule->m_pTaskList = new Task_t[taskNum];
  419. for (int i=0;i<taskNum;i++)
  420. {
  421. new_schedule->m_pTaskList[i].iTask = tempTask[i].iTask;
  422. new_schedule->m_pTaskList[i].flTaskData = tempTask[i].flTaskData;
  423. Assert( AI_IdIsLocal( new_schedule->m_pTaskList[i].iTask ) );
  424. }
  425. // ==========================
  426. // Now read in the interrupts
  427. // ==========================
  428. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  429. while ((token[0]!='\0') && (stricmp("Schedule",token)))
  430. {
  431. // Convert generic ID to sub-class specific enum
  432. int condID = CAI_BaseNPC::GetConditionID(token);
  433. // If not a valid condition, send a warning message
  434. if (condID == -1)
  435. {
  436. DevMsg( "ERROR: LoadSchd (%s): Schedule (%s), Unknown condition %s!\n", prefix,new_schedule->GetName(),token);
  437. Assert(0);
  438. }
  439. // Otherwise, add to this schedules list of conditions
  440. else
  441. {
  442. int interrupt = AI_RemapFromGlobal(condID);
  443. Assert( AI_IdIsGlobal( condID ) && interrupt >= 0 && interrupt < MAX_CONDITIONS );
  444. new_schedule->m_InterruptMask.Set(interrupt);
  445. }
  446. // Read the next token
  447. pfile = engine->ParseFile(pfile, token, sizeof( token ) );
  448. }
  449. }
  450. return true;
  451. }
  452. bool CAI_SchedulesManager::LoadSchedules( const char *prefix, CAI_ClassScheduleIdSpace *pIdSpace )
  453. {
  454. char sz[128];
  455. // Open the weapon's data file and read the weaponry details
  456. Q_snprintf(sz,sizeof(sz), "scripts/%s.sch",prefix);
  457. char *pfile = (char*)UTIL_LoadFileForMe(sz, NULL);
  458. if (!pfile)
  459. {
  460. DevMsg( "Unable to open AI Schedule data file for: %s\n", sz);
  461. return false;
  462. }
  463. if (!LoadSchedulesFromBuffer( prefix, pfile, pIdSpace))
  464. {
  465. DevMsg( " Schedule file: %s\n", sz );
  466. UTIL_FreeFile( (byte*)pfile );
  467. return false;
  468. }
  469. UTIL_FreeFile( (byte*)pfile );
  470. return true;
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose: Given a schedule ID, returns a schedule of the given type
  474. //-----------------------------------------------------------------------------
  475. CAI_Schedule *CAI_SchedulesManager::GetScheduleFromID( int schedID )
  476. {
  477. for ( CAI_Schedule *schedule = CAI_SchedulesManager::allSchedules; schedule != NULL; schedule = schedule->nextSchedule )
  478. {
  479. if (schedule->m_iScheduleID == schedID)
  480. return schedule;
  481. }
  482. DevMsg( "Couldn't find schedule (%s)\n", CAI_BaseNPC::GetSchedulingSymbols()->ScheduleIdToSymbol(schedID) );
  483. return NULL;
  484. }
  485. //-----------------------------------------------------------------------------
  486. // Purpose: Given a schedule name, returns a schedule of the given type
  487. //-----------------------------------------------------------------------------
  488. CAI_Schedule *CAI_SchedulesManager::GetScheduleByName( const char *name )
  489. {
  490. for ( CAI_Schedule *schedule = CAI_SchedulesManager::allSchedules; schedule != NULL; schedule = schedule->nextSchedule )
  491. {
  492. if (FStrEq(schedule->GetName(),name))
  493. return schedule;
  494. }
  495. return NULL;
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose: Delete all the schedules
  499. // Input :
  500. // Output :
  501. //-----------------------------------------------------------------------------
  502. void CAI_SchedulesManager::DeleteAllSchedules(void)
  503. {
  504. m_CurLoadSig++;
  505. if ( m_CurLoadSig < 0 )
  506. m_CurLoadSig = 0;
  507. CAI_Schedule *schedule = CAI_SchedulesManager::allSchedules;
  508. CAI_Schedule *next;
  509. while (schedule)
  510. {
  511. next = schedule->nextSchedule;
  512. delete schedule;
  513. schedule = next;
  514. }
  515. CAI_SchedulesManager::allSchedules = NULL;
  516. }
  517. //-----------------------------------------------------------------------------
  518. // Purpose:
  519. // Input :
  520. // Output :
  521. //-----------------------------------------------------------------------------
  522. CAI_Schedule::CAI_Schedule(char *name, int schedule_id, CAI_Schedule *pNext)
  523. {
  524. m_iScheduleID = schedule_id;
  525. int len = strlen(name);
  526. m_pName = new char[len+1];
  527. Q_strncpy(m_pName,name,len+1);
  528. m_pTaskList = NULL;
  529. m_iNumTasks = 0;
  530. // ---------------------------------
  531. // Add to linked list of schedules
  532. // ---------------------------------
  533. nextSchedule = pNext;
  534. }
  535. //-----------------------------------------------------------------------------
  536. // Purpose:
  537. //-----------------------------------------------------------------------------
  538. CAI_Schedule::~CAI_Schedule( void )
  539. {
  540. delete[] m_pName;
  541. delete[] m_pTaskList;
  542. }