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.

603 lines
21 KiB

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