KNpcAI.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:51k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "KCore.h"
  2. #include "KNpc.h"
  3. #include "KNpcSet.h"
  4. #include "KSubWorld.h"
  5. #include "KMath.h"
  6. #include "KObj.h"
  7. #include "KPlayer.h"
  8. #include "KNpcAI.h"
  9. // flying add here, to use math lib
  10. #include <math.h>
  11. extern int GetRandomNumber(int nMin, int nMax);
  12. #define MAX_FOLLOW_DISTANCE 48
  13. #define FOLLOW_WALK_DISTANCE 100
  14. KNpcAI NpcAI;
  15. KNpcAI::KNpcAI()
  16. {
  17. m_nIndex = 0;
  18. m_bActivate = TRUE;
  19. }
  20. // flying modified this function.
  21. // Jun.4.2003
  22. void KNpcAI::Activate(int nIndex)
  23. {
  24. m_nIndex = nIndex;
  25. if (Npc[m_nIndex].IsPlayer())
  26. {
  27. // 新增的Player AI在这里调用实现。
  28. ProcessPlayer();
  29. return;
  30. }
  31. #ifdef _SERVER
  32. if (Npc[m_nIndex].m_CurrentLifeMax == 0)
  33. return;
  34. int nCurTime = SubWorld[Npc[m_nIndex].m_SubWorldIndex].m_dwCurrentTime;
  35. if (/*Npc[m_nIndex].m_nPeopleIdx ||*/Npc[m_nIndex].m_NextAITime <= nCurTime)
  36. {
  37. Npc[m_nIndex].m_NextAITime = nCurTime + Npc[m_nIndex].m_AIMAXTime;
  38. switch(Npc[m_nIndex].m_AiMode)
  39. {
  40. case 1:
  41. ProcessAIType01();
  42. break;
  43. case 2:
  44. ProcessAIType02();
  45. break;
  46. case 3:
  47. ProcessAIType03();
  48. break;
  49. case 4:
  50. ProcessAIType04();
  51. break;
  52. case 5:
  53. ProcessAIType05();
  54. break;
  55. case 6:
  56. ProcessAIType06();
  57. break;
  58. /* case 7:
  59. ProcessAIType7();
  60. break;
  61. case 8:
  62. ProcessAIType8();
  63. break;
  64. case 9:
  65. ProcessAIType9();
  66. break;
  67. case 10:
  68. ProcessAIType10();
  69. break;*/
  70. default:
  71. break;
  72. }
  73. }
  74. // flying add the code for the macro such as "_CLIENT".
  75. // because this code only run at client.
  76. #else
  77. if (Npc[m_nIndex].m_Kind > 3 && Npc[m_nIndex].m_AiMode > 10)
  78. {
  79. if (CanShowNpc())
  80. {
  81. // 让NPC随机休息一下,是个好建议。
  82. if (GetRandomNumber(0, 1))
  83. {
  84. Npc[m_nIndex].m_AiParam[5] = 0;
  85. Npc[m_nIndex].m_AiParam[4] = 5;
  86. return;
  87. }
  88. if (!KeepActiveRange())
  89. ProcessShowNpc();
  90. }
  91. }
  92. #endif
  93. }
  94. //---------------------------------------------------------------------
  95. // flying add these functions
  96. // Run at client.
  97. #ifndef _SERVER
  98. // 仅仅有画面效果的NPC
  99. int KNpcAI::ProcessShowNpc()
  100. {
  101.     int nResult  = false;
  102.     int nRetCode = false;
  103. switch (Npc[m_nIndex].m_AiMode)
  104. {
  105. // 飞鸟型
  106. case 11:
  107. nRetCode = ShowNpcType11();
  108.         if (!nRetCode)
  109.             goto Exit0;
  110. break;
  111. // 蜻蜓型
  112. case 12:
  113. nRetCode = ShowNpcType12();
  114.         if (!nRetCode)
  115.             goto Exit0;
  116. break;
  117. // 鱼类型
  118. case 13:
  119. nRetCode = ShowNpcType13();
  120.         if (!nRetCode)
  121.             goto Exit0;
  122. break;
  123. // 老鼠型
  124. case 14:
  125. nRetCode = ShowNpcType14();
  126.         if (!nRetCode)
  127.             goto Exit0;
  128. break;
  129. // 鸡犬型
  130. case 15:
  131. nRetCode = ShowNpcType15();
  132.         if (!nRetCode)
  133.             goto Exit0;
  134. break;
  135. // 兔子型
  136. case 16:
  137. nRetCode = ShowNpcType16();
  138.         if (!nRetCode)
  139.             goto Exit0;
  140. break;
  141. // 蝴蝶型
  142. case 17:
  143. nRetCode = ShowNpcType17();
  144.         if (!nRetCode)
  145.             goto Exit0;
  146. break;
  147. default:
  148. break;
  149. }
  150.     nResult = true;
  151. Exit0:
  152. return nResult;
  153. }
  154. // 飞鸟型
  155. int KNpcAI::ShowNpcType11()
  156. {
  157.     int nResult = false;
  158.     int nRetCode = false;
  159. KNpc& aNpc = Npc[m_nIndex];
  160. // Go the distance between P1 to P2
  161. int nDistance = 0;
  162. int nDesX = 0;
  163. int nDesY = 0;
  164. int nCurX = 0;
  165. int nCurY = 0;
  166. int nOffX = 0;
  167. int nOffY = 0;
  168. int nOffsetDir = 0;
  169. // 效果加强 随机调整高度
  170. aNpc.m_Height = GetRandomNumber(aNpc.m_AiParam[6] - 4, aNpc.m_AiParam[6]);
  171. aNpc.GetMpsPos(&nCurX, &nCurY);
  172. // 计算新角度 和 距离
  173. if (aNpc.m_AiParam[3] > 0)
  174. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  175. else
  176. nOffsetDir = aNpc.m_AiParam[2];
  177.     if (GetRandomNumber(0, 1))
  178. nOffsetDir = -nOffsetDir;
  179.     nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  180. // 取得运动所需的时间,保存在参数表中
  181. if (aNpc.m_CurrentWalkSpeed > 0)
  182. {
  183. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  184. aNpc.m_AiParam[5] = 0;
  185. }
  186. //if (KeepActiveShowRange())
  187. // aNpc.m_Dir += 32;
  188. aNpc.m_Dir += nOffsetDir;
  189. if (aNpc.m_Dir < 0)
  190. aNpc.m_Dir += 64;
  191. else
  192. aNpc.m_Dir %= 64;
  193.     // 根据三角函数计算偏移的X、Y数值
  194. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  195.     if (!nRetCode)
  196.         goto Exit0;
  197. // 获取目标坐标
  198. nDesX = nCurX + nOffX;
  199. nDesY = nCurY + nOffY;
  200. aNpc.SendCommand(do_walk, nDesX, nDesY);
  201.     nResult = true;
  202. Exit0:
  203. return nResult;
  204. }
  205. // 蜻蜓型
  206. // done
  207. int KNpcAI::ShowNpcType12()
  208. {
  209.     int nResult = false;
  210.     int nRetCode = false;
  211. // Go the distance between P1 to P2
  212. int nDistance = 0;
  213. int nDesX = 0;
  214. int nDesY = 0;
  215. int nCurX = 0;
  216. int nCurY = 0;
  217. int nOffX = 0;
  218. int nOffY = 0;
  219. int nOffsetDir = 0;
  220. KNpc& aNpc = Npc[m_nIndex];
  221. // 效果加强 随机调整高度
  222. aNpc.m_Height = GetRandomNumber(aNpc.m_AiParam[6] - 4, aNpc.m_AiParam[6]);
  223. aNpc.GetMpsPos(&nCurX, &nCurY);
  224. // 计算新角度 和 距离
  225. if (aNpc.m_AiParam[3] > 0)
  226. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  227. else
  228. nOffsetDir = aNpc.m_AiParam[2];
  229. if (GetRandomNumber(0, 1))
  230. nOffsetDir = -nOffsetDir;
  231. nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  232. // 取得运动所需的时间,保存在参数表中
  233. if (aNpc.m_CurrentWalkSpeed > 0)
  234. {
  235. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  236. aNpc.m_AiParam[5] = 0;
  237. }
  238. else
  239. {
  240. aNpc.m_AiParam[4] = 0;
  241. aNpc.m_AiParam[5] = 0;
  242. }
  243. aNpc.m_Dir += nOffsetDir;
  244. if (aNpc.m_Dir < 0)
  245. aNpc.m_Dir += 64;
  246. else
  247. aNpc.m_Dir %= 64;
  248. // 根据三角函数计算偏移的X、Y数值
  249. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  250. if (!nRetCode)
  251. goto Exit0;
  252. // 获取目标坐标
  253. nDesX = nCurX + nOffX;
  254. nDesY = nCurY + nOffY;
  255. aNpc.SendCommand(do_walk, nDesX, nDesY);
  256. nResult = true;
  257. Exit0:
  258. return nResult;
  259. }
  260. // 鱼类型
  261. // done
  262. int KNpcAI::ShowNpcType13()
  263. {
  264. int nResult  = false;
  265. int nRetCode = false;
  266. // Go the distance between P1 to P2
  267. int nDistance = 0;
  268. int nDesX = 0;
  269. int nDesY = 0;
  270. int nCurX = 0;
  271. int nCurY = 0;
  272. int nOffX = 0;
  273. int nOffY = 0;
  274. int nOffsetDir = 0;
  275. int nIndex = 0;
  276. KNpc& aNpc = Npc[m_nIndex];
  277. aNpc.GetMpsPos(&nCurX, &nCurY);
  278. // 计算新角度 和 距离
  279. if (aNpc.m_AiParam[3] > 0)
  280. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  281. else
  282. nOffsetDir = aNpc.m_AiParam[2];
  283. if (GetRandomNumber(0, 1))
  284. nOffsetDir = -nOffsetDir;
  285. nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  286. // 取得运动所需的时间,保存在参数表中
  287. if (aNpc.m_CurrentWalkSpeed > 0)
  288. {
  289. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  290. aNpc.m_AiParam[5] = 0;
  291. }
  292. else
  293. {
  294. aNpc.m_AiParam[4] = 0;
  295. aNpc.m_AiParam[5] = 0;
  296. }
  297. //if (KeepActiveShowRange())
  298. // aNpc.m_Dir += 32;
  299. // 附近有玩家
  300. nIndex = IsPlayerCome();
  301. if (nIndex > 0)
  302. {
  303. // do flee
  304. DoShowFlee(nIndex);
  305. goto Exit0;
  306. }
  307. // 根据三角函数计算偏移的X、Y数值
  308. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  309. // 获取目标坐标
  310. nDesX = nCurX + nOffX;
  311. nDesY = nCurY + nOffY;
  312. aNpc.SendCommand(do_walk, nDesX, nDesY);
  313. nResult = true;
  314. Exit0:
  315. return nResult;
  316. }
  317. // 老鼠型
  318. // done
  319. int KNpcAI::ShowNpcType14()
  320. {
  321. int nResult  = false;
  322. int nRetCode = false;
  323. int nDistance = 0;
  324. int nDesX = 0;
  325. int nDesY = 0;
  326. int nCurX = 0;
  327. int nCurY = 0;
  328. int nOffX = 0;
  329. int nOffY = 0;
  330. int nRandom = 0;
  331. int nOffsetDir = 0;
  332. KNpc& aNpc = Npc[m_nIndex];
  333. nRandom = GetRandomNumber(1, 10);
  334. // 掉头就跑
  335. if (nRandom < 4)
  336. nDistance = -nDistance;
  337. // 嗷嗷发呆
  338. else if (nRandom < 7)
  339. {
  340. aNpc.SendCommand(do_stand);
  341. goto Exit0;
  342. }
  343. aNpc.GetMpsPos(&nCurX, &nCurY);
  344. // 计算新角度 和 距离
  345. if (aNpc.m_AiParam[3] > 0)
  346. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  347. else
  348. nOffsetDir = aNpc.m_AiParam[2];
  349. if (GetRandomNumber(0, 1))
  350. nOffsetDir = -nOffsetDir;
  351. nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  352. // 取得运动所需的时间,保存在参数表中
  353. if (aNpc.m_CurrentWalkSpeed > 0)
  354. {
  355. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  356. aNpc.m_AiParam[5] = 0;
  357. }
  358. else
  359. {
  360. aNpc.m_AiParam[4] = 0;
  361. aNpc.m_AiParam[5] = 0;
  362. }
  363. aNpc.m_Dir += nOffsetDir;
  364. if (aNpc.m_Dir < 0)
  365. aNpc.m_Dir += 64;
  366. else
  367. aNpc.m_Dir %= 64;
  368. // 根据三角函数计算偏移的X、Y数值
  369. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  370. if (!nRetCode)
  371. goto Exit0;
  372. // 获取目标坐标
  373. nDesX = nCurX + nOffX;
  374. nDesY = nCurY + nOffY;
  375. aNpc.SendCommand(do_walk, nDesX, nDesY);
  376. nResult = true;
  377. Exit0:
  378. return nResult;
  379. }
  380. // 鸡犬型
  381. int KNpcAI::ShowNpcType15()
  382. {
  383. int nResult  = false;
  384. int nRetCode = false;
  385. // Go the distance between P1 to P2
  386. int nDistance = 0;
  387. int nDesX = 0;
  388. int nDesY = 0;
  389. int nCurX = 0;
  390. int nCurY = 0;
  391. int nOffX = 0;
  392. int nOffY = 0;
  393. int nOffsetDir = 0;
  394. int nIndex = 0;
  395. KNpc& aNpc = Npc[m_nIndex];
  396. aNpc.GetMpsPos(&nCurX, &nCurY);
  397. // 计算新角度 和 距离
  398. if (aNpc.m_AiParam[3] > 0)
  399. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  400. else
  401. nOffsetDir = aNpc.m_AiParam[2];
  402. if (GetRandomNumber(0, 1))
  403. nOffsetDir = -nOffsetDir;
  404. nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  405. // 取得运动所需的时间,保存在参数表中
  406. if (aNpc.m_CurrentWalkSpeed > 0)
  407. {
  408. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  409. aNpc.m_AiParam[5] = 0;
  410. }
  411. else
  412. {
  413. aNpc.m_AiParam[4] = 0;
  414. aNpc.m_AiParam[5] = 0;
  415. }
  416. //if (KeepActiveShowRange())
  417. // aNpc.m_Dir += 32;
  418. // 附近有玩家
  419. nIndex = IsPlayerCome();
  420. if (nIndex > 0)
  421. {
  422. // do flee
  423. DoShowFlee(nIndex);
  424. goto Exit0;
  425. }
  426. // 根据三角函数计算偏移的X、Y数值
  427. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  428. // 获取目标坐标
  429. nDesX = nCurX + nOffX;
  430. nDesY = nCurY + nOffY;
  431. aNpc.SendCommand(do_walk, nDesX, nDesY);
  432. nResult = true;
  433. Exit0:
  434. return nResult;
  435. }
  436. // 兔子型
  437. int KNpcAI::ShowNpcType16()
  438. {
  439. int nResult  = false;
  440. int nRetCode = false;
  441. // Go the distance between P1 to P2
  442. register int nDistance = 0;
  443. int nDesX = 0;
  444. int nDesY = 0;
  445. int nCurX = 0;
  446. int nCurY = 0;
  447. int nOffX = 0;
  448. int nOffY = 0;
  449. int nOffsetDir = 0;
  450. int nIndex = 0;
  451. KNpc& aNpc = Npc[m_nIndex];
  452. aNpc.GetMpsPos(&nCurX, &nCurY);
  453. // 计算新角度 和 距离
  454. if (aNpc.m_AiParam[3] > 0)
  455. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  456. else
  457. nOffsetDir = aNpc.m_AiParam[2];
  458. if (GetRandomNumber(0, 1))
  459. nOffsetDir = -nOffsetDir;
  460. nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  461. // 附近有玩家
  462. nIndex = IsPlayerCome();
  463. if (nIndex > 0)
  464. {
  465. // do flee
  466. nRetCode = DoShowFlee(nIndex);
  467. if (!nRetCode)
  468. goto Exit0;
  469. goto Exit1;
  470. }
  471. // 计算距离
  472. if (aNpc.m_CurrentWalkSpeed > 0)
  473. {
  474. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  475. aNpc.m_AiParam[5] = 0;
  476. }
  477. else
  478. {
  479. aNpc.m_AiParam[4] = 0;
  480. aNpc.m_AiParam[5] = 0;
  481. }
  482. // 计算新角度
  483. //if (KeepActiveShowRange())
  484. // aNpc.m_Dir += 32;
  485. aNpc.m_Dir += GetRandomNumber(0, 6);
  486. aNpc.m_Dir %= 64;
  487. // 根据三角函数计算偏移的X、Y数值
  488. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  489. if (!nRetCode)
  490. goto Exit0;
  491. // 获取目标坐标
  492. nDesX = nCurX + nOffX;
  493. nDesY = nCurY + nOffY;
  494. aNpc.SendCommand(do_walk, nDesX, nDesY);
  495. Exit1:
  496. nResult = true;
  497. Exit0:
  498. return nResult;
  499. }
  500. // 蝴蝶型
  501. int KNpcAI::ShowNpcType17()
  502. {
  503. int nResult  = false;
  504. int nRetCode = false;
  505. // Go the distance between P1 to P2
  506. int nDistance = 0;
  507. int nDesX = 0;
  508. int nDesY = 0;
  509. int nCurX = 0;
  510. int nCurY = 0;
  511. int nOffX = 0;
  512. int nOffY = 0;
  513. int nOffsetDir = 0;
  514. KNpc& aNpc = Npc[m_nIndex];
  515. // 效果加强 随机调整高度
  516. aNpc.m_Height = GetRandomNumber(aNpc.m_AiParam[6] - 4, aNpc.m_AiParam[6]);
  517. aNpc.GetMpsPos(&nCurX, &nCurY);
  518. // 计算新角度 和 距离
  519. if (aNpc.m_AiParam[3] > 0)
  520. nOffsetDir = GetRandomNumber(aNpc.m_AiParam[3], aNpc.m_AiParam[2]);
  521. else
  522. nOffsetDir = aNpc.m_AiParam[2];
  523. if (GetRandomNumber(0, 1))
  524. nOffsetDir = -nOffsetDir;
  525. nDistance = GetRandomNumber(aNpc.m_AiParam[0] - aNpc.m_AiParam[1], aNpc.m_AiParam[0]);
  526. // 取得运动所需的时间,保存在参数表中
  527. if (aNpc.m_CurrentWalkSpeed > 0)
  528. {
  529. aNpc.m_AiParam[4] = (int) nDistance / aNpc.m_CurrentWalkSpeed;
  530. aNpc.m_AiParam[5] = 0;
  531. }
  532. else
  533. {
  534. aNpc.m_AiParam[4] = 0;
  535. aNpc.m_AiParam[5] = 0;
  536. }
  537. if (KeepActiveRange())
  538. {
  539. //aNpc.SendCommand(do_walk, aNpc.m_OriginX, aNpc.m_OriginY);
  540. goto Exit0;
  541. //aNpc.m_Dir += 32;
  542. }
  543. aNpc.m_Dir += nOffsetDir;
  544. //aNpc.m_Dir += GetRandomNumber(32, 64);
  545. if (aNpc.m_Dir < 0)
  546. aNpc.m_Dir += 64;
  547. else
  548. aNpc.m_Dir %= 64;
  549. // 根据三角函数计算偏移的X、Y数值
  550. nRetCode = GetNpcMoveOffset(aNpc.m_Dir, nDistance, &nOffX, &nOffY);
  551. if (!nRetCode)
  552. goto Exit0;
  553. // 获取目标坐标
  554. nDesX = nCurX + nOffX;
  555. nDesY = nCurY + nOffY;
  556. aNpc.SendCommand(do_walk, nDesX, nDesY);
  557. nResult = true;
  558. Exit0:
  559. return nResult;
  560. }
  561. #endif
  562. //---------------------------------------------------------------------
  563. // Player AI add here.
  564. // flying comment
  565. void KNpcAI::ProcessPlayer()
  566. {
  567. #ifdef _SERVER
  568. TriggerObjectTrap();
  569. TriggerMapTrap();
  570. #else
  571. int i = Npc[m_nIndex].m_nPeopleIdx;
  572. if (i > 0)
  573. {
  574. FollowPeople(i);
  575. }
  576. i = Npc[m_nIndex].m_nObjectIdx;
  577. if (i > 0)
  578. {
  579. FollowObject(i);
  580. }
  581. #endif
  582. }
  583. #ifndef _SERVER
  584. void KNpcAI::FollowObject(int nIdx)
  585. {
  586. int nX1, nY1, nX2, nY2;
  587. Npc[m_nIndex].GetMpsPos(&nX1, &nY1);
  588. Object[nIdx].GetMpsPos(&nX2, &nY2);
  589. if ((nX1 - nX2) * (nX1 - nX2) + (nY1 - nY2) * (nY1 - nY2) < PLAYER_PICKUP_CLIENT_DISTANCE * PLAYER_PICKUP_CLIENT_DISTANCE)
  590. {
  591. //#ifndef _SERVER
  592. Player[CLIENT_PLAYER_INDEX].CheckObject(nIdx);
  593. //#endif
  594. }
  595. }
  596. #endif
  597. #ifndef _SERVER
  598. void KNpcAI::FollowPeople(int nIdx)
  599. {
  600. if (Npc[nIdx].m_Doing == do_death || Npc[nIdx].m_Doing == do_revive)
  601. {
  602. Npc[m_nIndex].m_nPeopleIdx = 0;
  603. return;
  604. }
  605. // 取得到目标的距离
  606. int distance = NpcSet.GetDistance(nIdx, m_nIndex);
  607. int nRelation = NpcSet.GetRelation(m_nIndex, nIdx);
  608. // 小于对话半径就开始对话
  609. if ((Npc[nIdx].m_Kind == kind_dialoger))
  610. {
  611. if (distance <= Npc[nIdx].m_DialogRadius)
  612. {
  613. int x, y;
  614. SubWorld[Npc[m_nIndex].m_SubWorldIndex].Map2Mps(Npc[m_nIndex].m_RegionIndex, Npc[m_nIndex].m_MapX, Npc[m_nIndex].m_MapY, Npc[m_nIndex].m_OffX, Npc[m_nIndex].m_OffY, &x, &y);
  615. Npc[m_nIndex].SendCommand(do_walk, x,y);
  616. // Send Command to Server
  617. SendClientCmdWalk(x, y);
  618. Player[CLIENT_PLAYER_INDEX].DialogNpc(nIdx);
  619. Npc[Player[CLIENT_PLAYER_INDEX].m_nIndex].m_nPeopleIdx = 0;
  620. Npc[nIdx].TurnTo(Player[CLIENT_PLAYER_INDEX].m_nIndex);
  621. return;
  622. }
  623. }
  624. // 距离小于攻击范围就开始攻击
  625. if (nRelation == relation_enemy)
  626. {
  627. if (distance <= Npc[m_nIndex].m_CurrentAttackRadius)
  628. {
  629. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, nIdx);
  630. // Send to Server
  631. SendClientCmdSkill(Npc[m_nIndex].m_ActiveSkillID, -1, Npc[nIdx].m_dwID);
  632. }
  633. // 嗷嗷追
  634. else
  635. {
  636. int nDesX, nDesY;
  637. Npc[nIdx].GetMpsPos(&nDesX, &nDesY);
  638. // modify by spe 2003/06/13
  639. if (Player[CLIENT_PLAYER_INDEX].m_RunStatus)
  640. {
  641. Npc[m_nIndex].SendCommand(do_run, nDesX, nDesY);
  642. SendClientCmdRun(nDesX, nDesY);
  643. }
  644. else
  645. {
  646. Npc[m_nIndex].SendCommand(do_walk, nDesX, nDesY);
  647. SendClientCmdWalk(nDesX, nDesY);
  648. }
  649. }
  650. return;
  651. }
  652. // 跟随
  653. if (Npc[nIdx].m_Kind == kind_player)
  654. {
  655. // flow
  656. int nDesX, nDesY;
  657. if (distance < MAX_FOLLOW_DISTANCE)
  658. {
  659. Npc[this->m_nIndex].GetMpsPos(&nDesX, &nDesY);
  660. Npc[m_nIndex].SendCommand(do_walk, nDesX, nDesY);
  661. SendClientCmdWalk(nDesX, nDesY);
  662. }
  663. else
  664. {
  665. Npc[nIdx].GetMpsPos(&nDesX, &nDesY);
  666. if (distance < FOLLOW_WALK_DISTANCE ||
  667. !Player[CLIENT_PLAYER_INDEX].m_RunStatus)
  668. {
  669. Npc[m_nIndex].SendCommand(do_walk, nDesX, nDesY);
  670. SendClientCmdWalk(nDesX, nDesY);
  671. }
  672. else
  673. {
  674. Npc[m_nIndex].SendCommand(do_run, nDesX, nDesY);
  675. SendClientCmdRun(nDesX, nDesY);
  676. }
  677. }
  678. }
  679. return;
  680. }
  681. #endif
  682. void KNpcAI::TriggerMapTrap()
  683. {
  684. Npc[m_nIndex].CheckTrap();
  685. }
  686. void KNpcAI::TriggerObjectTrap()
  687. {
  688. return;
  689. }
  690. int KNpcAI::GetNearestNpc(int nRelation)
  691. {
  692. int nRangeX = Npc[m_nIndex].m_VisionRadius;
  693. int nRangeY = nRangeX;
  694. int nSubWorld = Npc[m_nIndex].m_SubWorldIndex;
  695. int nRegion = Npc[m_nIndex].m_RegionIndex;
  696. int nMapX = Npc[m_nIndex].m_MapX;
  697. int nMapY = Npc[m_nIndex].m_MapY;
  698. int nRet;
  699. int nRMx, nRMy, nSearchRegion;
  700. nRangeX = nRangeX / SubWorld[nSubWorld].m_nCellWidth;
  701. nRangeY = nRangeY / SubWorld[nSubWorld].m_nCellHeight;
  702. // 检查视野范围内的格子里的NPC
  703. for (int i = 0; i < nRangeX; i++) // i, j由0开始而不是从-range开始是要保证Nearest
  704. {
  705. for (int j = 0; j < nRangeY; j++)
  706. {
  707. // 去掉边角几个格子,保证视野是椭圆形
  708. if ((i * i + j * j) > nRangeX * nRangeX)
  709. continue;
  710. // 确定目标格子实际的REGION和坐标确定
  711. nRMx = nMapX + i;
  712. nRMy = nMapY + j;
  713. nSearchRegion = nRegion;
  714. if (nRMx < 0)
  715. {
  716. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[2];
  717. nRMx += SubWorld[nSubWorld].m_nRegionWidth;
  718. }
  719. else if (nRMx >= SubWorld[nSubWorld].m_nRegionWidth)
  720. {
  721. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[6];
  722. nRMx -= SubWorld[nSubWorld].m_nRegionWidth;
  723. }
  724. if (nSearchRegion == -1)
  725. continue;
  726. if (nRMy < 0)
  727. {
  728. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[4];
  729. nRMy += SubWorld[nSubWorld].m_nRegionHeight;
  730. }
  731. else if (nRMy >= SubWorld[nSubWorld].m_nRegionHeight)
  732. {
  733. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[0];
  734. nRMy -= SubWorld[nSubWorld].m_nRegionHeight;
  735. }
  736. if (nSearchRegion == -1)
  737. continue;
  738. // 从REGION的NPC列表中查找满足条件的NPC
  739. nRet = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nIndex, nRelation);
  740. if (nRet > 0)
  741. return nRet;
  742. // 确定目标格子实际的REGION和坐标确定
  743. nRMx = nMapX - i;
  744. nRMy = nMapY + j;
  745. nSearchRegion = nRegion;
  746. if (nRMx < 0)
  747. {
  748. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[2];
  749. nRMx += SubWorld[nSubWorld].m_nRegionWidth;
  750. }
  751. else if (nRMx >= SubWorld[nSubWorld].m_nRegionWidth)
  752. {
  753. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[6];
  754. nRMx -= SubWorld[nSubWorld].m_nRegionWidth;
  755. }
  756. if (nSearchRegion == -1)
  757. continue;
  758. if (nRMy < 0)
  759. {
  760. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[4];
  761. nRMy += SubWorld[nSubWorld].m_nRegionHeight;
  762. }
  763. else if (nRMy >= SubWorld[nSubWorld].m_nRegionHeight)
  764. {
  765. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[0];
  766. nRMy -= SubWorld[nSubWorld].m_nRegionHeight;
  767. }
  768. if (nSearchRegion == -1)
  769. continue;
  770. // 从REGION的NPC列表中查找满足条件的NPC
  771. nRet = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nIndex, nRelation);
  772. if (nRet > 0)
  773. return nRet;
  774. // 确定目标格子实际的REGION和坐标确定
  775. nRMx = nMapX - i;
  776. nRMy = nMapY - j;
  777. nSearchRegion = nRegion;
  778. if (nRMx < 0)
  779. {
  780. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[2];
  781. nRMx += SubWorld[nSubWorld].m_nRegionWidth;
  782. }
  783. else if (nRMx >= SubWorld[nSubWorld].m_nRegionWidth)
  784. {
  785. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[6];
  786. nRMx -= SubWorld[nSubWorld].m_nRegionWidth;
  787. }
  788. if (nSearchRegion == -1)
  789. continue;
  790. if (nRMy < 0)
  791. {
  792. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[4];
  793. nRMy += SubWorld[nSubWorld].m_nRegionHeight;
  794. }
  795. else if (nRMy >= SubWorld[nSubWorld].m_nRegionHeight)
  796. {
  797. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[0];
  798. nRMy -= SubWorld[nSubWorld].m_nRegionHeight;
  799. }
  800. if (nSearchRegion == -1)
  801. continue;
  802. // 从REGION的NPC列表中查找满足条件的NPC
  803. nRet = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nIndex, nRelation);
  804. if (nRet > 0)
  805. return nRet;
  806. // 确定目标格子实际的REGION和坐标确定
  807. nRMx = nMapX + i;
  808. nRMy = nMapY - j;
  809. nSearchRegion = nRegion;
  810. if (nRMx < 0)
  811. {
  812. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[2];
  813. nRMx += SubWorld[nSubWorld].m_nRegionWidth;
  814. }
  815. else if (nRMx >= SubWorld[nSubWorld].m_nRegionWidth)
  816. {
  817. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[6];
  818. nRMx -= SubWorld[nSubWorld].m_nRegionWidth;
  819. }
  820. if (nSearchRegion == -1)
  821. continue;
  822. if (nRMy < 0)
  823. {
  824. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[4];
  825. nRMy += SubWorld[nSubWorld].m_nRegionHeight;
  826. }
  827. else if (nRMy >= SubWorld[nSubWorld].m_nRegionHeight)
  828. {
  829. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[0];
  830. nRMy -= SubWorld[nSubWorld].m_nRegionHeight;
  831. }
  832. if (nSearchRegion == -1)
  833. continue;
  834. // 从REGION的NPC列表中查找满足条件的NPC
  835. nRet = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nIndex, nRelation);
  836. if (nRet > 0)
  837. return nRet;
  838. }
  839. }
  840. return 0;
  841. }
  842. #ifndef _SERVER
  843. // flying add this
  844. // 查找离某个NPC最近的玩家
  845. int KNpcAI::IsPlayerCome()
  846. {
  847. int nResult = 0;
  848. int nPlayer = 0;
  849. int X1 = 0;
  850. int Y1 = 0;
  851. int X2 = 0;
  852. int Y2 = 0;
  853. int nDistance = 0;
  854. nPlayer = Player[CLIENT_PLAYER_INDEX].m_nIndex;
  855. nDistance = NpcSet.GetDistance(nPlayer, m_nIndex);
  856. // 鸡看的到的玩家
  857. if (nDistance < Npc[m_nIndex].m_VisionRadius)
  858. {
  859. // 分别处理走和跑
  860. if (Player[CLIENT_PLAYER_INDEX].m_RunStatus ||
  861. Npc[m_nIndex].m_CurrentVisionRadius > nDistance * 4)
  862. {
  863. nResult = nPlayer;
  864. }
  865. }
  866. return nResult;
  867. }
  868. #endif
  869. int KNpcAI::GetNpcNumber(int nRelation)
  870. {
  871. int nRangeX = Npc[m_nIndex].m_VisionRadius;
  872. int nRangeY = nRangeX;
  873. int nSubWorld = Npc[m_nIndex].m_SubWorldIndex;
  874. int nRegion = Npc[m_nIndex].m_RegionIndex;
  875. int nMapX = Npc[m_nIndex].m_MapX;
  876. int nMapY = Npc[m_nIndex].m_MapY;
  877. int nRet = 0;
  878. int nRMx, nRMy, nSearchRegion;
  879. nRangeX = nRangeX / SubWorld[nSubWorld].m_nCellWidth;
  880. nRangeY = nRangeY / SubWorld[nSubWorld].m_nCellHeight;
  881. // 检查视野范围内的格子里的NPC
  882. for (int i = -nRangeX; i < nRangeX; i++)
  883. {
  884. for (int j = -nRangeY; j < nRangeY; j++)
  885. {
  886. // 去掉边角几个格子,保证视野是椭圆形
  887. if ((i * i + j * j) > nRangeX * nRangeX)
  888. continue;
  889. // 确定目标格子实际的REGION和坐标确定
  890. nRMx = nMapX + i;
  891. nRMy = nMapY + j;
  892. nSearchRegion = nRegion;
  893. if (nRMx < 0)
  894. {
  895. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[2];
  896. nRMx += SubWorld[nSubWorld].m_nRegionWidth;
  897. }
  898. else if (nRMx >= SubWorld[nSubWorld].m_nRegionWidth)
  899. {
  900. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[6];
  901. nRMx -= SubWorld[nSubWorld].m_nRegionWidth;
  902. }
  903. if (nSearchRegion == -1)
  904. continue;
  905. if (nRMy < 0)
  906. {
  907. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[4];
  908. nRMy += SubWorld[nSubWorld].m_nRegionHeight;
  909. }
  910. else if (nRMy >= SubWorld[nSubWorld].m_nRegionHeight)
  911. {
  912. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[0];
  913. nRMy -= SubWorld[nSubWorld].m_nRegionHeight;
  914. }
  915. if (nSearchRegion == -1)
  916. continue;
  917. // 从REGION的NPC列表中查找满足条件的NPC
  918. int nNpcIdx = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nIndex, nRelation);
  919. if (nNpcIdx > 0)
  920. nRet++;
  921. }
  922. }
  923. return nRet;
  924. }
  925. void KNpcAI::KeepAttackRange(int nEnemy, int nRange)
  926. {
  927. int nX1, nY1, nX2, nY2, nDir, nWantX, nWantY;
  928. Npc[m_nIndex].GetMpsPos(&nX1, &nY1);
  929. Npc[nEnemy].GetMpsPos(&nX2, &nY2);
  930. nDir = g_GetDirIndex(nX1, nY1, nX2, nY2);
  931. nWantX = nX2 - ((nRange * g_DirCos(nDir, 64)) >> 10);
  932. nWantY = nY2 - ((nRange * g_DirSin(nDir, 64)) >> 10);
  933. Npc[m_nIndex].SendCommand(do_walk, nWantX, nWantY);
  934. }
  935. void KNpcAI::FollowAttack(int i)
  936. {
  937. if ( Npc[i].m_RegionIndex < 0 )
  938. return;
  939. int distance = NpcSet.GetDistance(m_nIndex, i);
  940. #define MINI_ATTACK_RANGE 32
  941. if (distance <= MINI_ATTACK_RANGE)
  942. {
  943. KeepAttackRange(i, MINI_ATTACK_RANGE);
  944. return;
  945. }
  946. // Attack Enemy
  947. if (distance <= Npc[m_nIndex].m_CurrentAttackRadius && InEyeshot(i))
  948. {
  949. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, i);
  950. return;
  951. }
  952. // Move to Enemy
  953. int x, y;
  954. Npc[i].GetMpsPos(&x, &y);
  955. Npc[m_nIndex].SendCommand(do_walk, x, y);
  956. }
  957. BOOL KNpcAI::InEyeshot(int nIdx)
  958. {
  959. int distance = NpcSet.GetDistance(nIdx, m_nIndex);
  960. return (Npc[m_nIndex].m_VisionRadius > distance);
  961. }
  962. void KNpcAI::CommonAction()
  963. {
  964. // 如果是对话类的NPC,就原地不动
  965. if (Npc[m_nIndex].m_Kind == kind_dialoger)
  966. {
  967. Npc[m_nIndex].SendCommand(do_stand);
  968. return;
  969. }
  970. int nOffX, nOffY;
  971. if (g_RandPercent(80))
  972. {
  973. nOffX = 0;
  974. nOffY = 0;
  975. }
  976. else
  977. {
  978. nOffX = g_Random(Npc[m_nIndex].m_CurrentActiveRadius / 2);
  979. nOffY = g_Random(Npc[m_nIndex].m_CurrentActiveRadius / 2);
  980. if (nOffX & 1)
  981. {
  982. nOffX = - nOffX;
  983. }
  984. if (nOffY & 1)
  985. {
  986. nOffY = - nOffY;
  987. }
  988. }
  989. Npc[m_nIndex].SendCommand(do_walk, Npc[m_nIndex].m_OriginX + nOffX, Npc[m_nIndex].m_OriginY + nOffY);
  990. }
  991. BOOL KNpcAI::KeepActiveRange()
  992. {
  993. int x, y;
  994. Npc[m_nIndex].GetMpsPos(&x, &y);
  995. int nRange = g_GetDistance(Npc[m_nIndex].m_OriginX, Npc[m_nIndex].m_OriginY, x, y);
  996. // 发现超出活动范围,把当前活动范围缩小,避免在活动范围边缘来回晃。
  997. if (Npc[m_nIndex].m_ActiveRadius < nRange)
  998. {
  999. Npc[m_nIndex].m_CurrentActiveRadius = Npc[m_nIndex].m_ActiveRadius / 2;
  1000. }
  1001. // 发现超出当前活动范围,往回走
  1002. if (Npc[m_nIndex].m_CurrentActiveRadius < nRange)
  1003. {
  1004. Npc[m_nIndex].SendCommand(do_walk, Npc[m_nIndex].m_OriginX, Npc[m_nIndex].m_OriginY);
  1005. return TRUE;
  1006. }
  1007. else // 在当前活动范围内,恢复当前活动范围大小。
  1008. {
  1009. Npc[m_nIndex].m_CurrentActiveRadius = Npc[m_nIndex].m_ActiveRadius;
  1010. return FALSE;
  1011. }
  1012. }
  1013. #ifndef _SERVER
  1014. // 15/16 AiMode NPC的逃逸动作
  1015. int KNpcAI::DoShowFlee(int nIdx)
  1016. {
  1017. int nResult  = false;
  1018. int nRetCode = false;
  1019. int x1, y1, x2, y2;
  1020. int nDistance = Npc[m_nIndex].m_AiParam[6];
  1021. Npc[m_nIndex].GetMpsPos(&x1, &y1);
  1022. //Npc[nIdx].GetMpsPos(&x2, &y2);
  1023. Npc[m_nIndex].m_Dir = Npc[nIdx].m_Dir;
  1024. nRetCode = GetNpcMoveOffset(Npc[m_nIndex].m_Dir, nDistance, &x2, &y2);
  1025. if (!nRetCode)
  1026. goto Exit0;
  1027. Npc[m_nIndex].m_AiParam[4] = (int) nDistance / Npc[m_nIndex].m_WalkSpeed;
  1028. Npc[m_nIndex].m_AiParam[5] = 0;
  1029. Npc[m_nIndex].SendCommand(do_walk, x1 + x2, y1 + y2);
  1030. nResult = true;
  1031. Exit0:
  1032. return nResult;
  1033. }
  1034. #endif
  1035. // 逃离Npc[nIdx]
  1036. void KNpcAI::Flee(int nIdx)
  1037. {
  1038. int x1, y1, x2, y2;
  1039. Npc[m_nIndex].GetMpsPos(&x1, &y1);
  1040. Npc[nIdx].GetMpsPos(&x2, &y2);
  1041. x1 = x1 * 2 - x2;
  1042. y1 = y1 * 2 - y2;
  1043. Npc[m_nIndex].SendCommand(do_walk, x1, y1);
  1044. }
  1045. //------------------------------------------------------------------------------
  1046. // 功能:普通主动类1
  1047. // m_AiParam[0] 无敌人时候的巡逻概率
  1048. // m_AiParam[1、2、3、4] 四种技能的使用概率,分别对应SkillList里的技能1 2 3 4
  1049. // m_AiParam[5、6] 看见敌人但比较远时,待机、巡逻的概率
  1050. //------------------------------------------------------------------------------
  1051. void KNpcAI::ProcessAIType01()
  1052. {
  1053. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1054. // 是否已超过活动半径
  1055. if (KeepActiveRange())
  1056. return;
  1057. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1058. // 如果原本没有锁定敌人或者这个敌人跑太远,重新锁定敌人
  1059. if (nEnemyIdx <= 0 || Npc[nEnemyIdx].m_dwID <= 0 || !InEyeshot(nEnemyIdx) )
  1060. {
  1061. nEnemyIdx = GetNearestNpc(relation_enemy);
  1062. Npc[m_nIndex].m_nPeopleIdx = nEnemyIdx;
  1063. }
  1064. // 周围没有敌人,一定概率待机/巡逻
  1065. if (nEnemyIdx <= 0)
  1066. {
  1067. // pAIParam[0]:巡逻概率
  1068. if (pAIParam[0] > 0 && g_RandPercent(pAIParam[0]))
  1069. { // 巡逻
  1070. CommonAction();
  1071. }
  1072. return;
  1073. }
  1074. // 如果敌人在所有技能攻击范围之外,一定概率选择待机/巡逻/向敌人靠近
  1075. if (KNpcSet::GetDistanceSquare(m_nIndex, nEnemyIdx) > pAIParam[MAX_AI_PARAM - 1])
  1076. {
  1077. int nRand;
  1078. nRand = g_Random(100);
  1079. if (nRand < pAIParam[5]) // 待机
  1080. return;
  1081. if (nRand < pAIParam[5] + pAIParam[6]) // 巡逻
  1082. {
  1083. CommonAction();
  1084. return;
  1085. }
  1086. FollowAttack(nEnemyIdx); // 向敌人靠近
  1087. return;
  1088. }
  1089. // 敌人在最大技能攻击范围之内,选择一种技能攻击
  1090. int nRand;
  1091. nRand = g_Random(100);
  1092. if (nRand < pAIParam[1])
  1093. {
  1094. if (!Npc[m_nIndex].SetActiveSkill(1))
  1095. {
  1096. CommonAction();
  1097. return;
  1098. }
  1099. }
  1100. else if (nRand < pAIParam[1] + pAIParam[2])
  1101. {
  1102. if (!Npc[m_nIndex].SetActiveSkill(2))
  1103. {
  1104. CommonAction();
  1105. return;
  1106. }
  1107. }
  1108. else if (nRand < pAIParam[1] + pAIParam[2] + pAIParam[3])
  1109. {
  1110. if (!Npc[m_nIndex].SetActiveSkill(3))
  1111. {
  1112. CommonAction();
  1113. return;
  1114. }
  1115. }
  1116. else if (nRand < pAIParam[1] + pAIParam[2] + pAIParam[3] + pAIParam[4])
  1117. {
  1118. if (!Npc[m_nIndex].SetActiveSkill(4))
  1119. {
  1120. CommonAction();
  1121. return;
  1122. }
  1123. }
  1124. else // 待机
  1125. {
  1126. return;
  1127. }
  1128. FollowAttack(nEnemyIdx);
  1129. }
  1130. //------------------------------------------------------------------------------
  1131. // 功能:普通主动类2
  1132. // m_AiParam[0] 无敌人时候的巡逻概率
  1133. // m_AiParam[1] 剩余生命低于这个百分比的时候执行相应处理
  1134. // m_AiParam[2] 在m_AiParam[1]的情况出现的时候是否执行相应处理的概率
  1135. // m_AiParam[3] 在m_AiParam[1]的情况出现并决定要执行相应处理,使用回复技能的概率 对应SkillList里面的技能 1
  1136. // m_AiParam[4、5、6] 三种攻击技能的使用概率,分别对应SkillList里的技能 2 3 4
  1137. // m_AiParam[7、8] 看见敌人但比较远时,待机、巡逻的概率
  1138. //------------------------------------------------------------------------------
  1139. void KNpcAI::ProcessAIType02()
  1140. {
  1141. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1142. // 是否已超过活动半径
  1143. if (KeepActiveRange())
  1144. return;
  1145. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1146. // 如果原本没有锁定敌人或者这个敌人跑太远,重新锁定敌人
  1147. if (nEnemyIdx <= 0 || Npc[nEnemyIdx].m_dwID <= 0 || !InEyeshot(nEnemyIdx) )
  1148. {
  1149. nEnemyIdx = GetNearestNpc(relation_enemy);
  1150. Npc[m_nIndex].m_nPeopleIdx = nEnemyIdx;
  1151. }
  1152. // 周围没有敌人,一定概率待机/巡逻
  1153. if (nEnemyIdx <= 0)
  1154. {
  1155. // pAIParam[0]:巡逻概率
  1156. if (pAIParam[0] > 0 && g_RandPercent(pAIParam[0]))
  1157. { // 巡逻
  1158. CommonAction();
  1159. }
  1160. return;
  1161. }
  1162. // 检测剩余生命是否符合条件,生命太少一定概率使用补血技能或逃跑
  1163. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[1])
  1164. {
  1165. if (g_RandPercent(pAIParam[2])) // 是否使用补血技能或逃跑
  1166. {
  1167. if (Npc[m_nIndex].m_AiAddLifeTime < pAIParam[9] && g_RandPercent(pAIParam[3])) // 使用补血技能
  1168. {
  1169. Npc[m_nIndex].SetActiveSkill(1);
  1170. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, m_nIndex);
  1171. Npc[m_nIndex].m_AiAddLifeTime++;
  1172. return;
  1173. }
  1174. else // 逃跑
  1175. {
  1176. Flee(nEnemyIdx);
  1177. return;
  1178. }
  1179. }
  1180. }
  1181. // 如果敌人在所有技能攻击范围之外,一定概率选择待机/巡逻/向敌人靠近
  1182. if (KNpcSet::GetDistanceSquare(m_nIndex, nEnemyIdx) > pAIParam[MAX_AI_PARAM - 1])
  1183. {
  1184. int nRand;
  1185. nRand = g_Random(100);
  1186. if (nRand < pAIParam[7]) // 待机
  1187. return;
  1188. if (nRand < pAIParam[7] + pAIParam[8]) // 巡逻
  1189. {
  1190. CommonAction();
  1191. return;
  1192. }
  1193. FollowAttack(nEnemyIdx); // 向敌人靠近
  1194. return;
  1195. }
  1196. // 敌人在最大技能攻击范围之内,选择一种技能攻击
  1197. int nRand;
  1198. nRand = g_Random(100);
  1199. if (nRand < pAIParam[4])
  1200. {
  1201. if (!Npc[m_nIndex].SetActiveSkill(2))
  1202. {
  1203. CommonAction();
  1204. return;
  1205. }
  1206. }
  1207. else if (nRand < pAIParam[4] + pAIParam[5])
  1208. {
  1209. if (!Npc[m_nIndex].SetActiveSkill(3))
  1210. {
  1211. CommonAction();
  1212. return;
  1213. }
  1214. }
  1215. else if (nRand < pAIParam[4] + pAIParam[5] + pAIParam[6])
  1216. {
  1217. if (!Npc[m_nIndex].SetActiveSkill(4))
  1218. {
  1219. CommonAction();
  1220. return;
  1221. }
  1222. }
  1223. else // 待机
  1224. {
  1225. return;
  1226. }
  1227. FollowAttack(nEnemyIdx);
  1228. }
  1229. //------------------------------------------------------------------------------
  1230. // 功能:普通主动类3
  1231. // m_AiParam[0] 无敌人时候的巡逻概率
  1232. // m_AiParam[1] 剩余生命低于这个百分比的时候执行相应处理
  1233. // m_AiParam[2] 在m_AiParam[1]的情况出现的时候是否执行相应处理的概率
  1234. // m_AiParam[3] 在m_AiParam[1]的情况出现并决定要执行相应处理,使用攻击技能的概率 对应SkillList里面的技能 1
  1235. // m_AiParam[4、5、6] 三种攻击技能的使用概率,分别对应SkillList里的技能 2 3 4
  1236. // m_AiParam[7、8] 看见敌人但比较远时,待机、巡逻的概率
  1237. //------------------------------------------------------------------------------
  1238. void KNpcAI::ProcessAIType03()
  1239. {
  1240. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1241. // 是否已超过活动半径
  1242. if (KeepActiveRange())
  1243. return;
  1244. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1245. // 如果原本没有锁定敌人或者这个敌人跑太远,重新锁定敌人
  1246. if (nEnemyIdx <= 0 || Npc[nEnemyIdx].m_dwID <= 0 || !InEyeshot(nEnemyIdx) )
  1247. {
  1248. nEnemyIdx = GetNearestNpc(relation_enemy);
  1249. Npc[m_nIndex].m_nPeopleIdx = nEnemyIdx;
  1250. }
  1251. // 周围没有敌人,一定概率待机/巡逻
  1252. if (nEnemyIdx <= 0)
  1253. {
  1254. // pAIParam[0]:巡逻概率
  1255. if (pAIParam[0] > 0 && g_RandPercent(pAIParam[0]))
  1256. { // 巡逻
  1257. CommonAction();
  1258. }
  1259. return;
  1260. }
  1261. // 检测剩余生命是否符合条件,生命太少一定概率使用攻击技能或逃跑
  1262. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[1])
  1263. {
  1264. if (g_RandPercent(pAIParam[2])) // 是否使用攻击技能或逃跑
  1265. {
  1266. if (g_RandPercent(pAIParam[3])) // 使用攻击技能
  1267. {
  1268. Npc[m_nIndex].SetActiveSkill(1);
  1269. FollowAttack(nEnemyIdx);
  1270. return;
  1271. }
  1272. else // 逃跑
  1273. {
  1274. Flee(nEnemyIdx);
  1275. return;
  1276. }
  1277. }
  1278. }
  1279. // 如果敌人在所有技能攻击范围之外,一定概率选择待机/巡逻/向敌人靠近
  1280. if (KNpcSet::GetDistanceSquare(m_nIndex, nEnemyIdx) > pAIParam[MAX_AI_PARAM - 1])
  1281. {
  1282. int nRand;
  1283. nRand = g_Random(100);
  1284. if (nRand < pAIParam[7]) // 待机
  1285. return;
  1286. if (nRand < pAIParam[7] + pAIParam[8]) // 巡逻
  1287. {
  1288. CommonAction();
  1289. return;
  1290. }
  1291. FollowAttack(nEnemyIdx); // 向敌人靠近
  1292. return;
  1293. }
  1294. // 敌人在最大技能攻击范围之内,选择一种技能攻击
  1295. int nRand;
  1296. nRand = g_Random(100);
  1297. if (nRand < pAIParam[4])
  1298. {
  1299. if (!Npc[m_nIndex].SetActiveSkill(2))
  1300. {
  1301. CommonAction();
  1302. return;
  1303. }
  1304. }
  1305. else if (nRand < pAIParam[4] + pAIParam[5])
  1306. {
  1307. if (!Npc[m_nIndex].SetActiveSkill(3))
  1308. {
  1309. CommonAction();
  1310. return;
  1311. }
  1312. }
  1313. else if (nRand < pAIParam[4] + pAIParam[5] + pAIParam[6])
  1314. {
  1315. if (!Npc[m_nIndex].SetActiveSkill(4))
  1316. {
  1317. CommonAction();
  1318. return;
  1319. }
  1320. }
  1321. else // 待机
  1322. {
  1323. return;
  1324. }
  1325. FollowAttack(nEnemyIdx);
  1326. }
  1327. //------------------------------------------------------------------------------
  1328. // 功能:普通被动类1
  1329. // m_AiParam[0] 无敌人时候的巡逻概率
  1330. // m_AiParam[1、2、3、4] 四种攻击技能的使用概率,分别对应SkillList里的技能 1 2 3 4
  1331. // m_AiParam[5、6] 看见敌人但比较远时,待机、巡逻的概率
  1332. //------------------------------------------------------------------------------
  1333. void KNpcAI::ProcessAIType04()
  1334. {
  1335. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1336. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1337. // 是否受到攻击,否,一定概率选择待机/巡逻
  1338. if (nEnemyIdx <= 0)
  1339. {
  1340. // pAIParam[0]:巡逻概率
  1341. if (pAIParam[0] > 0 && g_RandPercent(pAIParam[0]))
  1342. { // 巡逻
  1343. CommonAction();
  1344. }
  1345. return;
  1346. }
  1347. // 是否已超过活动半径
  1348. if (KeepActiveRange())
  1349. return;
  1350. // 如果敌人在所有技能攻击范围之外,一定概率选择待机/巡逻/向敌人靠近
  1351. if (KNpcSet::GetDistanceSquare(m_nIndex, nEnemyIdx) > pAIParam[MAX_AI_PARAM - 1])
  1352. {
  1353. int nRand;
  1354. nRand = g_Random(100);
  1355. if (nRand < pAIParam[5]) // 待机
  1356. return;
  1357. if (nRand < pAIParam[5] + pAIParam[6]) // 巡逻
  1358. {
  1359. CommonAction();
  1360. return;
  1361. }
  1362. FollowAttack(nEnemyIdx); // 向敌人靠近
  1363. return;
  1364. }
  1365. // 敌人在最大技能攻击范围之内,选择一种技能攻击
  1366. int nRand;
  1367. nRand = g_Random(100);
  1368. if (nRand < pAIParam[1])
  1369. {
  1370. if (!Npc[m_nIndex].SetActiveSkill(1))
  1371. {
  1372. CommonAction();
  1373. return;
  1374. }
  1375. }
  1376. else if (nRand < pAIParam[1] + pAIParam[2])
  1377. {
  1378. if (!Npc[m_nIndex].SetActiveSkill(2))
  1379. {
  1380. CommonAction();
  1381. return;
  1382. }
  1383. }
  1384. else if (nRand < pAIParam[1] + pAIParam[2] + pAIParam[3])
  1385. {
  1386. if (!Npc[m_nIndex].SetActiveSkill(3))
  1387. {
  1388. CommonAction();
  1389. return;
  1390. }
  1391. }
  1392. else if (nRand < pAIParam[1] + pAIParam[2] + pAIParam[3] + pAIParam[4])
  1393. {
  1394. if (!Npc[m_nIndex].SetActiveSkill(4))
  1395. {
  1396. CommonAction();
  1397. return;
  1398. }
  1399. }
  1400. else // 待机
  1401. {
  1402. return;
  1403. }
  1404. FollowAttack(nEnemyIdx);
  1405. }
  1406. //------------------------------------------------------------------------------
  1407. // 功能:普通被动类2
  1408. // m_AiParam[0] 无敌人时候的巡逻概率
  1409. // m_AiParam[1] 剩余生命低于这个百分比的时候执行相应处理
  1410. // m_AiParam[2] 在m_AiParam[1]的情况出现的时候是否执行相应处理的概率
  1411. // m_AiParam[3] 在m_AiParam[1]的情况出现并决定要执行相应处理,使用回复技能的概率 对应SkillList里面的技能 1
  1412. // m_AiParam[4、5、6] 三种攻击技能的使用概率,分别对应SkillList里的技能 2 3 4
  1413. // m_AiParam[7、8] 看见敌人但比较远时,待机、巡逻的概率
  1414. //------------------------------------------------------------------------------
  1415. void KNpcAI::ProcessAIType05()
  1416. {
  1417. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1418. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1419. // 是否受到攻击,否,一定概率选择待机/巡逻
  1420. if (nEnemyIdx <= 0)
  1421. {
  1422. // pAIParam[0]:巡逻概率
  1423. if (pAIParam[0] > 0 && g_RandPercent(pAIParam[0]))
  1424. { // 巡逻
  1425. CommonAction();
  1426. }
  1427. return;
  1428. }
  1429. // 是否已超过活动半径
  1430. if (KeepActiveRange())
  1431. return;
  1432. // 检测剩余生命是否符合条件,生命太少一定概率使用补血技能或逃跑
  1433. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[1])
  1434. {
  1435. if (g_RandPercent(pAIParam[2])) // 是否使用补血技能或逃跑
  1436. {
  1437. if (Npc[m_nIndex].m_AiAddLifeTime < pAIParam[9] && g_RandPercent(pAIParam[3])) // 使用补血技能
  1438. {
  1439. Npc[m_nIndex].m_AiAddLifeTime++;
  1440. Npc[m_nIndex].SetActiveSkill(1);
  1441. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, m_nIndex);
  1442. return;
  1443. }
  1444. else // 逃跑
  1445. {
  1446. Flee(nEnemyIdx);
  1447. return;
  1448. }
  1449. }
  1450. }
  1451. // 如果敌人在所有技能攻击范围之外,一定概率选择待机/巡逻/向敌人靠近
  1452. if (KNpcSet::GetDistanceSquare(m_nIndex, nEnemyIdx) > pAIParam[MAX_AI_PARAM - 1])
  1453. {
  1454. int nRand;
  1455. nRand = g_Random(100);
  1456. if (nRand < pAIParam[7]) // 待机
  1457. return;
  1458. if (nRand < pAIParam[7] + pAIParam[8]) // 巡逻
  1459. {
  1460. CommonAction();
  1461. return;
  1462. }
  1463. FollowAttack(nEnemyIdx); // 向敌人靠近
  1464. return;
  1465. }
  1466. // 敌人在最大技能攻击范围之内,选择一种技能攻击
  1467. int nRand;
  1468. nRand = g_Random(100);
  1469. if (nRand < pAIParam[4])
  1470. {
  1471. if (!Npc[m_nIndex].SetActiveSkill(2))
  1472. {
  1473. CommonAction();
  1474. return;
  1475. }
  1476. }
  1477. else if (nRand < pAIParam[4] + pAIParam[5])
  1478. {
  1479. if (!Npc[m_nIndex].SetActiveSkill(3))
  1480. {
  1481. CommonAction();
  1482. return;
  1483. }
  1484. }
  1485. else if (nRand < pAIParam[4] + pAIParam[5] + pAIParam[6])
  1486. {
  1487. if (!Npc[m_nIndex].SetActiveSkill(4))
  1488. {
  1489. CommonAction();
  1490. return;
  1491. }
  1492. }
  1493. else // 待机
  1494. {
  1495. return;
  1496. }
  1497. FollowAttack(nEnemyIdx);
  1498. }
  1499. //------------------------------------------------------------------------------
  1500. // 功能:普通被动类3
  1501. // m_AiParam[0] 无敌人时候的巡逻概率
  1502. // m_AiParam[1] 剩余生命低于这个百分比的时候执行相应处理
  1503. // m_AiParam[2] 在m_AiParam[1]的情况出现的时候是否执行相应处理的概率
  1504. // m_AiParam[3] 在m_AiParam[1]的情况出现并决定要执行相应处理,使用攻击技能的概率 对应SkillList里面的技能 1
  1505. // m_AiParam[4、5、6] 三种攻击技能的使用概率,分别对应SkillList里的技能 2 3 4
  1506. // m_AiParam[7、8] 看见敌人但比较远时,待机、巡逻的概率
  1507. //------------------------------------------------------------------------------
  1508. void KNpcAI::ProcessAIType06()
  1509. {
  1510. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1511. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1512. // 是否受到攻击,否,一定概率选择待机/巡逻
  1513. if (nEnemyIdx <= 0)
  1514. {
  1515. // pAIParam[0]:巡逻概率
  1516. if (pAIParam[0] > 0 && g_RandPercent(pAIParam[0]))
  1517. { // 巡逻
  1518. CommonAction();
  1519. }
  1520. return;
  1521. }
  1522. // 是否已超过活动半径
  1523. if (KeepActiveRange())
  1524. return;
  1525. // 检测剩余生命是否符合条件,生命太少一定概率使用攻击技能或逃跑
  1526. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[1])
  1527. {
  1528. if (g_RandPercent(pAIParam[2])) // 是否使用攻击技能或逃跑
  1529. {
  1530. if (g_RandPercent(pAIParam[3])) // 使用攻击技能
  1531. {
  1532. Npc[m_nIndex].SetActiveSkill(1);
  1533. FollowAttack(nEnemyIdx); // 向敌人靠近
  1534. return;
  1535. }
  1536. else // 逃跑
  1537. {
  1538. Flee(nEnemyIdx);
  1539. return;
  1540. }
  1541. }
  1542. }
  1543. // 如果敌人在所有技能攻击范围之外,一定概率选择待机/巡逻/向敌人靠近
  1544. if (KNpcSet::GetDistanceSquare(m_nIndex, nEnemyIdx) > pAIParam[MAX_AI_PARAM - 1])
  1545. {
  1546. int nRand;
  1547. nRand = g_Random(100);
  1548. if (nRand < pAIParam[7]) // 待机
  1549. return;
  1550. if (nRand < pAIParam[7] + pAIParam[8]) // 巡逻
  1551. {
  1552. CommonAction();
  1553. return;
  1554. }
  1555. FollowAttack(nEnemyIdx); // 向敌人靠近
  1556. return;
  1557. }
  1558. // 敌人在最大技能攻击范围之内,选择一种技能攻击
  1559. int nRand;
  1560. nRand = g_Random(100);
  1561. if (nRand < pAIParam[4])
  1562. {
  1563. if (!Npc[m_nIndex].SetActiveSkill(2))
  1564. {
  1565. CommonAction();
  1566. return;
  1567. }
  1568. }
  1569. else if (nRand < pAIParam[4] + pAIParam[5])
  1570. {
  1571. if (!Npc[m_nIndex].SetActiveSkill(3))
  1572. {
  1573. CommonAction();
  1574. return;
  1575. }
  1576. }
  1577. else if (nRand < pAIParam[4] + pAIParam[5] + pAIParam[6])
  1578. {
  1579. if (!Npc[m_nIndex].SetActiveSkill(4))
  1580. {
  1581. CommonAction();
  1582. return;
  1583. }
  1584. }
  1585. else // 待机
  1586. {
  1587. return;
  1588. }
  1589. FollowAttack(nEnemyIdx);
  1590. }
  1591. /*
  1592. // 一般主动型
  1593. void KNpcAI::ProcessAIType1()
  1594. {
  1595. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1596. // 是否已超过活动半径
  1597. if (KeepActiveRange())
  1598. return;
  1599. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[0])
  1600. {
  1601. if (g_RandPercent(pAIParam[1]))
  1602. {
  1603. Npc[m_nIndex].SetActiveSkill(1);
  1604. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, m_nIndex);
  1605. return;
  1606. }
  1607. }
  1608. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1609. if (nEnemyIdx <= 0 || Npc[nEnemyIdx].m_dwID <= 0 || !InEyeshot(nEnemyIdx) )
  1610. {
  1611. nEnemyIdx = GetNearestNpc(relation_enemy);
  1612. Npc[m_nIndex].m_nPeopleIdx = nEnemyIdx;
  1613. }
  1614. if (nEnemyIdx > 0)
  1615. {
  1616. int nRand;
  1617. nRand = g_Random(100);
  1618. if (nRand < pAIParam[2])
  1619. {
  1620. if (!Npc[m_nIndex].SetActiveSkill(2))
  1621. {
  1622. CommonAction();
  1623. return;
  1624. }
  1625. }
  1626. else if (nRand < pAIParam[2] + pAIParam[3])
  1627. {
  1628. if (!Npc[m_nIndex].SetActiveSkill(3))
  1629. {
  1630. CommonAction();
  1631. return;
  1632. }
  1633. }
  1634. else if (nRand < pAIParam[2] + pAIParam[3] + pAIParam[4])
  1635. {
  1636. if (!Npc[m_nIndex].SetActiveSkill(4))
  1637. {
  1638. CommonAction();
  1639. return;
  1640. }
  1641. }
  1642. // if (g_RandPercent(pAIParam[2]))
  1643. // {
  1644. // Npc[m_nIndex].SetActiveSkill(2);
  1645. // }
  1646. // else if (g_RandPercent(pAIParam[3]))
  1647. // {
  1648. // Npc[m_nIndex].SetActiveSkill(3);
  1649. // }
  1650. // else if (g_RandPercent(pAIParam[4]))
  1651. // {
  1652. // Npc[m_nIndex].SetActiveSkill(4);
  1653. // }
  1654. else
  1655. {
  1656. CommonAction();
  1657. return;
  1658. }
  1659. FollowAttack(nEnemyIdx);
  1660. return;
  1661. }
  1662. CommonAction();
  1663. }
  1664. */
  1665. /*
  1666. // 一般被动型
  1667. void KNpcAI::ProcessAIType2()
  1668. {
  1669. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1670. if (KeepActiveRange())
  1671. return;
  1672. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[0])
  1673. {
  1674. if (g_RandPercent(pAIParam[1]))
  1675. {
  1676. Npc[m_nIndex].SetActiveSkill(1);
  1677. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, m_nIndex);
  1678. return;
  1679. }
  1680. }
  1681. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1682. if (nEnemyIdx <= 0 || !InEyeshot(nEnemyIdx))
  1683. return;
  1684. int nRand;
  1685. nRand = g_Random(100);
  1686. if (nRand < pAIParam[2])
  1687. {
  1688. if (!Npc[m_nIndex].SetActiveSkill(2))
  1689. {
  1690. CommonAction();
  1691. return;
  1692. }
  1693. }
  1694. else if (nRand < pAIParam[2] + pAIParam[3])
  1695. {
  1696. if (!Npc[m_nIndex].SetActiveSkill(3))
  1697. {
  1698. CommonAction();
  1699. return;
  1700. }
  1701. }
  1702. else if (nRand < pAIParam[2] + pAIParam[3] + pAIParam[4])
  1703. {
  1704. if (!Npc[m_nIndex].SetActiveSkill(4))
  1705. {
  1706. CommonAction();
  1707. return;
  1708. }
  1709. }
  1710. // if (g_RandPercent(pAIParam[2]))
  1711. // {
  1712. // Npc[m_nIndex].SetActiveSkill(2);
  1713. // }
  1714. // else if (g_RandPercent(pAIParam[3]))
  1715. // {
  1716. // Npc[m_nIndex].SetActiveSkill(3);
  1717. // }
  1718. // else if (g_RandPercent(pAIParam[4]))
  1719. // {
  1720. // Npc[m_nIndex].SetActiveSkill(4);
  1721. // }
  1722. else
  1723. {
  1724. CommonAction();
  1725. return;
  1726. }
  1727. FollowAttack(nEnemyIdx);
  1728. return;
  1729. }
  1730. */
  1731. /*
  1732. // 一般逃跑型
  1733. void KNpcAI::ProcessAIType3()
  1734. {
  1735. int* pAIParam = Npc[m_nIndex].m_AiParam;
  1736. if (KeepActiveRange())
  1737. return;
  1738. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1739. if (nEnemyIdx <= 0 || !InEyeshot(nEnemyIdx))
  1740. {
  1741. nEnemyIdx = GetNearestNpc(relation_enemy);
  1742. Npc[m_nIndex].m_nPeopleIdx = nEnemyIdx;
  1743. }
  1744. if (nEnemyIdx <= 0)
  1745. {
  1746. CommonAction();
  1747. return;
  1748. }
  1749. if (Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[0])
  1750. {
  1751. if (g_RandPercent(pAIParam[1]))
  1752. {
  1753. Flee(nEnemyIdx);
  1754. return;
  1755. }
  1756. }
  1757. int nRand;
  1758. nRand = g_Random(100);
  1759. if (nRand < pAIParam[2])
  1760. {
  1761. if (!Npc[m_nIndex].SetActiveSkill(1))
  1762. {
  1763. CommonAction();
  1764. return;
  1765. }
  1766. }
  1767. else if (nRand < pAIParam[2] + pAIParam[3])
  1768. {
  1769. if (!Npc[m_nIndex].SetActiveSkill(2))
  1770. {
  1771. CommonAction();
  1772. return;
  1773. }
  1774. }
  1775. else if (nRand < pAIParam[2] + pAIParam[3] + pAIParam[4])
  1776. {
  1777. if (!Npc[m_nIndex].SetActiveSkill(3))
  1778. {
  1779. CommonAction();
  1780. return;
  1781. }
  1782. }
  1783. // if (g_RandPercent(pAIParam[2]))
  1784. /// {
  1785. // Npc[m_nIndex].SetActiveSkill(1);
  1786. // }
  1787. // else if (g_RandPercent(pAIParam[3]))
  1788. // {
  1789. // Npc[m_nIndex].SetActiveSkill(2);
  1790. // }
  1791. // else if (g_RandPercent(pAIParam[4]))
  1792. // {
  1793. // Npc[m_nIndex].SetActiveSkill(3);
  1794. // }
  1795. else
  1796. {
  1797. CommonAction();
  1798. return;
  1799. }
  1800. FollowAttack(nEnemyIdx);
  1801. return;
  1802. }
  1803. */
  1804. /*
  1805. // 逃跑加强型
  1806. void KNpcAI::ProcessAIType4()
  1807. {
  1808. int* pAIParam = Npc[m_nIndex].m_AiParam;
  1809. if (KeepActiveRange())
  1810. return;
  1811. int nEnemyIdx = Npc[m_nIndex].m_nPeopleIdx;
  1812. if (nEnemyIdx <= 0 || !InEyeshot(nEnemyIdx))
  1813. {
  1814. nEnemyIdx = GetNearestNpc(relation_enemy);
  1815. Npc[m_nIndex].m_nPeopleIdx = nEnemyIdx;
  1816. }
  1817. if (nEnemyIdx <= 0)
  1818. {
  1819. CommonAction();
  1820. return;
  1821. }
  1822. int nLifePercent = Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax;
  1823. if (nLifePercent < pAIParam[0])
  1824. {
  1825. if (g_RandPercent(pAIParam[1]))
  1826. {
  1827. Flee(nEnemyIdx);
  1828. return;
  1829. }
  1830. }
  1831. if (nLifePercent < pAIParam[2])
  1832. {
  1833. if (g_RandPercent(pAIParam[3]))
  1834. {
  1835. Npc[m_nIndex].SetActiveSkill(1);
  1836. Npc[m_nIndex].SendCommand(do_skill, Npc[m_nIndex].m_ActiveSkillID, -1, m_nIndex);
  1837. return;
  1838. }
  1839. }
  1840. if (g_RandPercent(pAIParam[4]))
  1841. {
  1842. Npc[m_nIndex].SetActiveSkill(2);
  1843. }
  1844. else if (g_RandPercent(pAIParam[5]))
  1845. {
  1846. Npc[m_nIndex].SetActiveSkill(3);
  1847. }
  1848. else
  1849. {
  1850. CommonAction();
  1851. return;
  1852. }
  1853. FollowAttack(nEnemyIdx);
  1854. return;
  1855. }
  1856. */
  1857. /*
  1858. // 人多就跑型
  1859. void KNpcAI::ProcessAIType5()
  1860. {
  1861. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1862. if (KeepActiveRange())
  1863. return;
  1864. int i = Npc[m_nIndex].m_nPeopleIdx;
  1865. if (!i || !InEyeshot(i))
  1866. {
  1867. i = GetNearestNpc(relation_enemy);
  1868. Npc[m_nIndex].m_nPeopleIdx = i;
  1869. }
  1870. if (!i)
  1871. {
  1872. CommonAction();
  1873. return;
  1874. }
  1875. int nEnemyNumber = GetNpcNumber(relation_enemy);
  1876. if (nEnemyNumber > pAIParam[0])
  1877. {
  1878. if (g_RandPercent(pAIParam[1]))
  1879. {
  1880. Flee(i);
  1881. return;
  1882. }
  1883. }
  1884. if (g_RandPercent(pAIParam[2]))
  1885. {
  1886. Npc[m_nIndex].SetActiveSkill(1);
  1887. }
  1888. else if (nEnemyNumber <= pAIParam[3] && g_RandPercent(pAIParam[4]))
  1889. {
  1890. Npc[m_nIndex].SetActiveSkill(2);
  1891. }
  1892. else
  1893. {
  1894. CommonAction();
  1895. return;
  1896. }
  1897. FollowAttack(i);
  1898. return;
  1899. }
  1900. */
  1901. /*
  1902. // 成群结队型
  1903. void KNpcAI::ProcessAIType6()
  1904. {
  1905. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1906. if (KeepActiveRange())
  1907. return;
  1908. int i = Npc[m_nIndex].m_nPeopleIdx;
  1909. if (!i || !InEyeshot(i))
  1910. {
  1911. i = GetNearestNpc(relation_enemy);
  1912. Npc[m_nIndex].m_nPeopleIdx = i;
  1913. }
  1914. if (!i)
  1915. {
  1916. CommonAction();
  1917. return;
  1918. }
  1919. int nAllyNumber = GetNpcNumber(relation_none);
  1920. if (nAllyNumber <= pAIParam[0])
  1921. {
  1922. if (g_RandPercent(pAIParam[1]))
  1923. {
  1924. Flee(i);
  1925. return;
  1926. }
  1927. }
  1928. if (g_RandPercent(pAIParam[2]))
  1929. {
  1930. Npc[m_nIndex].SetActiveSkill(1);
  1931. }
  1932. else if (nAllyNumber > pAIParam[3] && g_RandPercent(pAIParam[4]))
  1933. {
  1934. Npc[m_nIndex].SetActiveSkill(2);
  1935. }
  1936. else
  1937. {
  1938. CommonAction();
  1939. return;
  1940. }
  1941. FollowAttack(i);
  1942. return;
  1943. }
  1944. */
  1945. /*
  1946. // 挨打聚堆型
  1947. void KNpcAI::ProcessAIType7()
  1948. {
  1949. int *pAIParam = Npc[m_nIndex].m_AiParam;
  1950. if (KeepActiveRange())
  1951. return;
  1952. int i = Npc[m_nIndex].m_nPeopleIdx;
  1953. if (!i || !InEyeshot(i))
  1954. {
  1955. i = GetNearestNpc(relation_enemy);
  1956. Npc[m_nIndex].m_nPeopleIdx = i;
  1957. }
  1958. if (!i)
  1959. {
  1960. CommonAction();
  1961. return;
  1962. }
  1963. int j = GetNearestNpc(relation_ally);
  1964. if (j && Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax < pAIParam[0])
  1965. {
  1966. if (g_RandPercent(pAIParam[1]))
  1967. {
  1968. int x, y;
  1969. Npc[j].GetMpsPos(&x, &y);
  1970. Npc[m_nIndex].SendCommand(do_walk, x, y);
  1971. return;
  1972. }
  1973. }
  1974. if (g_RandPercent(pAIParam[2]))
  1975. {
  1976. Npc[m_nIndex].SetActiveSkill(1);
  1977. }
  1978. else if (g_RandPercent(pAIParam[3]))
  1979. {
  1980. Npc[m_nIndex].SetActiveSkill(2);
  1981. }
  1982. else if (g_RandPercent(pAIParam[4]))
  1983. {
  1984. Npc[m_nIndex].SetActiveSkill(3);
  1985. }
  1986. else
  1987. {
  1988. CommonAction();
  1989. return;
  1990. }
  1991. FollowAttack(i);
  1992. return;
  1993. }
  1994. */
  1995. /*
  1996. // 主动送死型
  1997. void KNpcAI::ProcessAIType8()
  1998. {
  1999. int *pAIParam = Npc[m_nIndex].m_AiParam;
  2000. if (KeepActiveRange())
  2001. return;
  2002. int i = Npc[m_nIndex].m_nPeopleIdx;
  2003. if (!i || !InEyeshot(i))
  2004. {
  2005. i = GetNearestNpc(relation_enemy);
  2006. Npc[m_nIndex].m_nPeopleIdx = i;
  2007. }
  2008. if (!i)
  2009. {
  2010. CommonAction();
  2011. return;
  2012. }
  2013. if (g_RandPercent(pAIParam[0]))
  2014. {
  2015. int x, y;
  2016. Npc[i].GetMpsPos(&x, &y);
  2017. Npc[m_nIndex].SendCommand(do_walk, x, y);
  2018. }
  2019. else if (g_RandPercent(pAIParam[1]))
  2020. {
  2021. Npc[m_nIndex].SetActiveSkill(1);
  2022. }
  2023. else if (g_RandPercent(pAIParam[2]))
  2024. {
  2025. Npc[m_nIndex].SetActiveSkill(2);
  2026. }
  2027. else if (g_RandPercent(pAIParam[3]))
  2028. {
  2029. Npc[m_nIndex].SetActiveSkill(3);
  2030. }
  2031. else
  2032. {
  2033. CommonAction();
  2034. return;
  2035. }
  2036. FollowAttack(i);
  2037. return;
  2038. }
  2039. */
  2040. /*
  2041. // 越战越勇型
  2042. void KNpcAI::ProcessAIType9()
  2043. {
  2044. int *pAIParam = Npc[m_nIndex].m_AiParam;
  2045. if (KeepActiveRange())
  2046. return;
  2047. int i = Npc[m_nIndex].m_nPeopleIdx;
  2048. if (!i || !InEyeshot(i))
  2049. {
  2050. i = GetNearestNpc(relation_enemy);
  2051. Npc[m_nIndex].m_nPeopleIdx = i;
  2052. }
  2053. if (!i)
  2054. {
  2055. CommonAction();
  2056. return;
  2057. }
  2058. int nLifePercent = Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax;
  2059. if (g_RandPercent(pAIParam[0]))
  2060. {
  2061. Npc[m_nIndex].SetActiveSkill(1);
  2062. }
  2063. else if (nLifePercent < pAIParam[1] && g_RandPercent(pAIParam[2]))
  2064. {
  2065. Npc[m_nIndex].SetActiveSkill(2);
  2066. }
  2067. else if (nLifePercent < pAIParam[3] && g_RandPercent(pAIParam[4]))
  2068. {
  2069. Npc[m_nIndex].SetActiveSkill(3);
  2070. }
  2071. else
  2072. {
  2073. CommonAction();
  2074. return;
  2075. }
  2076. FollowAttack(i);
  2077. return;
  2078. }
  2079. */
  2080. /*
  2081. // 逃跑不掉型
  2082. void KNpcAI::ProcessAIType10()
  2083. {
  2084. int *pAIParam = Npc[m_nIndex].m_AiParam;
  2085. if (KeepActiveRange())
  2086. return;
  2087. int i = Npc[m_nIndex].m_nPeopleIdx;
  2088. if (!i || !InEyeshot(i))
  2089. {
  2090. i = GetNearestNpc(relation_enemy);
  2091. Npc[m_nIndex].m_nPeopleIdx = i;
  2092. }
  2093. if (!i)
  2094. {
  2095. CommonAction();
  2096. return;
  2097. }
  2098. int nLifePercent = Npc[m_nIndex].m_CurrentLife * 100 / Npc[m_nIndex].m_CurrentLifeMax;
  2099. if (nLifePercent < pAIParam[0] && g_RandPercent(pAIParam[1]))
  2100. {
  2101. Npc[m_nIndex].SetActiveSkill(1);
  2102. }
  2103. else if (nLifePercent < pAIParam[2] && g_RandPercent(pAIParam[3]))
  2104. {
  2105. Npc[m_nIndex].SetActiveSkill(2);
  2106. }
  2107. else if (nLifePercent < pAIParam[4] && g_RandPercent(pAIParam[5]))
  2108. {
  2109. Flee(i);
  2110. return;
  2111. }
  2112. else
  2113. {
  2114. CommonAction();
  2115. return;
  2116. }
  2117. FollowAttack(i);
  2118. return;
  2119. }
  2120. */