ROAAi.cpp
上传用户:tianheyiqi
上传日期:2010-04-16
资源大小:282k
文件大小:21k
源码类别:

外挂编程

开发平台:

Visual C++

  1. #include <stdafx.h>
  2. #include "ROA.h"
  3. #include "ROAUtils.h"
  4. AICOMMANDQUEUE::AICOMMANDQUEUE()
  5. {
  6. priority = eAiPriMax;
  7. dwTarget = 0xFFFFFFFF;
  8. }
  9. AICOMMANDQUEUE::~AICOMMANDQUEUE()
  10. {
  11. }
  12. BOOL AICOMMANDQUEUE::update(AICOMMAND command)
  13. {
  14. // CString strOutput;
  15. // strOutput.Format("------ Update %s(%X)", utlGetStatusDescription(command.eAction), command.dwTarget);
  16. // utlLogout(strOutput, eLogInfo, true);
  17. SetAt(0, command);
  18. return(true);
  19. }
  20. BOOL AICOMMANDQUEUE::cancelAll()
  21. {
  22. if(GetSize() <= 0)
  23. return(false);
  24. int nSize = GetSize();
  25. for(int i=0; i<nSize; i++)
  26. cancel();
  27. return(TRUE);
  28. }
  29. BOOL AICOMMANDQUEUE::cancel()
  30. {
  31. CString strOutput;
  32. if(GetSize() <= 0)
  33. return(false);
  34. AICOMMAND command;
  35. int nIndex;
  36. command = GetAt(0);
  37. strOutput.Format("------ Cancel %s(%X)", utlGetStatusDescription(command.eAction), command.dwTarget);
  38. utlLogout(strOutput, eLogCommon, true);
  39. nIndex = monsters.FindId(command.dwTarget);
  40. if(-1 != nIndex)
  41. {
  42. monsters[nIndex].bAiIgnore = true;
  43. } else
  44. {
  45. nIndex = items.FindId(command.dwTarget);
  46. if(-1 != nIndex)
  47. {
  48. items[nIndex].bAiIgnore = true;
  49. }
  50. }
  51. finish();
  52. return(TRUE);
  53. }
  54. BOOL AICOMMANDQUEUE::finishAll()
  55. {
  56. int nSize = GetSize();
  57. if(nSize <= 0)
  58. return(false);
  59. for(int i=0; i<nSize; i++)
  60. finish();
  61. return(true);
  62. }
  63. BOOL AICOMMANDQUEUE::finish()
  64. {
  65. CString strOutput;
  66. if(GetSize() <= 0)
  67. return(false);
  68. AICOMMAND command;
  69. command = GetAt(0);
  70. strOutput.Format("------ Removing %s(%X)", utlGetStatusDescription(command.eAction), command.dwTarget);
  71. utlLogout(strOutput, eLogInfo, true);
  72. RemoveAt(0);
  73. if(0 == GetSize())
  74. {
  75. priority = eAiPriMax;
  76. dwTarget = 0xFFFFFFFF;
  77. utlChangeGlobalAction(eAiIdle);
  78. }
  79. return(true);
  80. }
  81. BOOL AICOMMANDQUEUE::extend(AICOMMAND command)
  82. {
  83. BOOL bRtn = false;
  84. CString strOutput;
  85. if(GetSize() > 0)
  86. {
  87. strOutput.Format("------ Extend  %s(%X)", utlGetStatusDescription(command.eAction), command.dwTarget);
  88. utlLogout(strOutput, eLogInfo, true);
  89. InsertAt(0, command);
  90. bRtn = true;
  91. }
  92. else
  93. {
  94. ASSERT(false);
  95. }
  96. return(bRtn);
  97. }
  98. BOOL AICOMMANDQUEUE::push(AICOMMAND command, AIPRIORITY ePri)
  99. {
  100. ASSERT(GetSize() == 0);
  101. BOOL bRtn = false;
  102. CString strOutput;
  103. if(ePri < priority)
  104. {
  105. Add(command);
  106. priority = ePri;
  107. dwTarget = command.dwTarget;
  108. bRtn = true;
  109. strOutput.Format("------ Add  %s(%X)", utlGetStatusDescription(command.eAction), command.dwTarget);
  110. utlLogout(strOutput, eLogInfo, true);
  111. }
  112. return(bRtn);
  113. }
  114. BOOL AICOMMANDQUEUE::pop(AICOMMAND &command)
  115. {
  116. BOOL bFound = false;
  117. if(GetSize() > 0)
  118. {
  119. command = GetAt(0);
  120. bFound = true;
  121. }
  122. return(bFound);
  123. }
  124. int doAi()
  125. {
  126. //check for status
  127. AICOMMAND command;
  128. DWORD dwTarget;
  129. CString strOutput, strTemp;
  130. DWORD dwDamage;
  131. int nMinDist, nDist;
  132. BOOL bFound = false;
  133. int i;
  134. pos pos1, pos2;
  135. pos_list *poslist = (pos_list*)&route.size;
  136. DWORD dwDamage1;
  137. int nMinLevel, nLevel;
  138. CDWordArray dwTargetArray;
  139. CDWordArray dwDamageArray;
  140. // Check for eAiPriItem0
  141. if(aiQueue.priority <= eAiPriItem0)
  142. {
  143. // already in eAiPriItem0, no compare
  144. goto DONE;
  145. }
  146. if(aiGetItemToPickup(eIpGrab, dwTarget))
  147. {
  148. // ignore weight
  149. if(aiQueue.dwTarget != dwTarget)
  150. {
  151. aiQueue.finishAll();
  152. command.eAction = eAiPickup;
  153. command.ePhase = ePhaseNone;
  154. command.dwTarget = dwTarget;
  155. strOutput.Format("------ Prepare to pickup %s", utlFindTargetItem(dwTarget));
  156. utlLogout(strOutput, eLogCommon, true);
  157. aiQueue.push(command, eAiPriItem0);
  158. }
  159. goto DONE;
  160. }
  161. // Check for eAiPriFlee
  162. /*
  163. if(aiCheckTeleportCondition())
  164. {
  165. BOOL bFound = false;
  166. for(int i=0; i<inventory.GetSize(); i++)
  167. {
  168. if(inventory[i].dwId == 601)
  169. {
  170. bFound = true;
  171. break;
  172. }
  173. }
  174. if(bUseFlywing && bFound)
  175. {
  176. aiQueue.finishAll();
  177. sendUseItem((WORD)inventory[i].dwIndex, dwAccountId);
  178. }
  179. else
  180. {
  181. if(bFlyUsed)
  182. {
  183. aiQueue.finishAll();
  184. sendTeleport("Random");
  185. }
  186. else
  187. {
  188. if(bFound)
  189. {
  190. aiQueue.finishAll();
  191. sendUseItem(i, dwAccountId);
  192. sendTeleport("Random");
  193. }
  194. else
  195. {
  196. // .... 
  197. }
  198. }
  199. }
  200. goto DONE;
  201. }
  202. */
  203. // Check for eAiPriCounter
  204. if(aiQueue.priority < eAiPriCounter)
  205. {
  206. goto DONE;
  207. }
  208. bFound = false;
  209. dwTarget = 0;
  210. dwDamage = 0;
  211. nMinDist = 999;
  212. if(damages.FindDamageFrom(dwAccountId, dwTargetArray, dwDamageArray))
  213. {
  214. // Choose a monster by distance and damage
  215. for(i=0; i<dwTargetArray.GetSize(); i++)
  216. {
  217. nDist = (int)utlDistanceFrom(you.pntTo, monsters[monsters.FindId(dwTargetArray[i])].pntTo);
  218. dwDamage1 = dwDamageArray[i];
  219. if(nMinDist - nDist > 2)
  220. {
  221. dwTarget = dwTargetArray[i];
  222. dwDamage = dwDamage1;
  223. nMinDist = nDist;
  224. continue;
  225. }
  226. if(dwDamage1 > dwDamage)
  227. {
  228. dwTarget = dwTargetArray[i];
  229. dwDamage = dwDamage1;
  230. nMinDist = nDist;
  231. continue;
  232. }
  233. }
  234. if(dwTarget != aiQueue.dwTarget)
  235. {
  236. aiQueue.finishAll();
  237. command.eAction = eAiAttack;
  238. command.ePhase = ePhaseNone;
  239. command.dwTarget = dwTarget;
  240. strOutput.Format("------ Prepare to counter-attack %s", utlFindTarget(dwTarget));
  241. utlLogout(strOutput, eLogCommon, true);
  242. aiQueue.push(command, eAiPriCounter);
  243. }
  244. goto DONE;
  245. }
  246. //Aggresive monster
  247. if(action == eAtkPhaseAttacking)
  248. {
  249. // Attacking
  250. goto DONE;
  251. }
  252. // Check for eAiPriRecess
  253. if(aiQueue.priority < eAiPriRecess)
  254. {
  255. goto DONE;
  256. }
  257. if(you.bSit && you.wHp < you.wHpMax * 0.6)
  258. {
  259. goto DONE;
  260. }
  261. if(you.wHp < you.wHpMax * 0.3 && !you.bSit && aiQueue.priority != eAiPriRecess)
  262. {
  263. command.eAction = eAiSit;
  264. command.ePhase = ePhaseNone;
  265. aiQueue.finishAll();
  266. aiQueue.push(command, eAiPriRecess);
  267. goto DONE;
  268. }
  269. // Check for eAiPriItem1
  270. if(aiQueue.priority <= eAiPriItem1)
  271. {
  272. goto DONE;
  273. }
  274. if(aiGetItemToPickup(eIpGather, dwTarget) && ((double)you.dwWeight / you.dwWeightMax)< 0.48)
  275. {
  276. // weight
  277. if(aiQueue.dwTarget != dwTarget)
  278. {
  279. aiQueue.finishAll();
  280. command.eAction = eAiPickup;
  281. command.ePhase = ePhaseNone;
  282. command.dwTarget = dwTarget;
  283. strOutput.Format("------ Prepare to pickup %s", utlFindTargetItem(dwTarget));
  284. utlLogout(strOutput, eLogCommon, true);
  285. aiQueue.push(command, eAiPriItem1);
  286. }
  287. goto DONE;
  288. }
  289. // Check for eAiPriMonster
  290. if(aiQueue.priority <= eAiPriMonster)
  291. {
  292. goto DONE;
  293. }
  294. bFound = false;
  295. nMinLevel = 0;
  296. nMinDist = 999;
  297. nLevel = -1;
  298. dwTarget = 0;
  299. for(i=0; i<monsters.GetSize(); i++)
  300. {
  301. if(!monsters[i].bClean)
  302. {
  303. // no kill steal
  304. continue;
  305. }
  306. if(monsters[i].bAiIgnore)
  307. {
  308. // Ignore
  309. continue;
  310. }
  311. nDist = (int)utlDistanceFrom(you.pntTo, monsters[i].pntTo);
  312. // nLevel = atoi(mapMonsterInfo.FindValue(monsters[i].wType, eMonsterLev));
  313. if(nMinDist - nDist > 2)
  314. {
  315. dwTarget = monsters[i].dwId;
  316. nMinDist = nDist;
  317. nMinLevel = nLevel;
  318. bFound = true;
  319. continue;
  320. }
  321. if(nLevel > nMinLevel)
  322. {
  323. dwTarget = monsters[i].dwId;
  324. nMinDist = nDist;
  325. nMinLevel = nLevel;
  326. bFound = true;
  327. }
  328. }
  329. if(bFound)
  330. {
  331. if(dwTarget != aiQueue.dwTarget)
  332. {
  333. aiQueue.finishAll();
  334. command.eAction = eAiAttack;
  335. command.ePhase = ePhaseNone;
  336. command.dwTarget = dwTarget;
  337. strOutput.Format("------ Prepare to attack %s", utlFindTarget(dwTarget));
  338. utlLogout(strOutput, eLogCommon, true);
  339. aiQueue.push(command, eAiPriMonster);
  340. }
  341. goto DONE;
  342. }
  343. // Check for eAiPriItem2
  344. if(aiQueue.priority <= eAiPriItem2)
  345. {
  346. goto DONE;
  347. }
  348. if(aiGetItemToPickup(eIpPickup, dwTarget) && ((double)you.dwWeight / you.dwWeightMax)< 0.40 )
  349. {
  350. // weight
  351. if(aiQueue.dwTarget != dwTarget)
  352. {
  353. aiQueue.finishAll();
  354. command.eAction = eAiPickup;
  355. command.ePhase = ePhaseNone;
  356. command.dwTarget = dwTarget;
  357. strOutput.Format("------ Prepare to pickup %s", utlFindTargetItem(dwTarget));
  358. utlLogout(strOutput, eLogCommon, true);
  359. aiQueue.push(command, eAiPriItem2);
  360. }
  361. goto DONE;
  362. }
  363. // Random walk
  364. if(aiQueue.priority <= eAiPriRandom)
  365. {
  366. goto DONE;
  367. }
  368. bFound = true;
  369. if( route.size == 0 ||
  370. route.curPoint > route.size-1 ||
  371. (you.pntTo.x != route.array[route.curPoint].x ||
  372.  you.pntTo.y != route.array[route.curPoint].y))
  373. {
  374. // need recalculate
  375. // if((you.wHp < you.wHpMax * 0.8 || you.wSp < you.wSpMax * 0.8) && !you.bSit)
  376. // {
  377. // // Take a rest while calculating, mmmm....
  378. // sendSit();
  379. // }
  380. pos1.x = (WORD)you.pntTo.x;
  381. pos1.y = (WORD)you.pntTo.y;
  382. while(true)
  383. {
  384. pos2.x = (int)((double)rand()/RAND_MAX * field.m_szField.cx);
  385. pos2.y = (int)((double)rand()/RAND_MAX * field.m_szField.cy);
  386. if(!field.m_byFields[pos2.x + field.m_szField.cx * pos2.y])
  387. {
  388. break;
  389. }
  390. }
  391. DWORD session = (*CalcPath_init)(poslist, (char*)field.m_byFields, field.m_szField.cx, field.m_szField.cy, 
  392. &pos2, &pos1, MAX_ROUTE_TIMEOUT);
  393. bFound = !((*CalcPath_pathStep)(session));
  394. (*CalcPath_destory)(session);
  395. route.curPoint = 0;
  396. }
  397. if(bFound && route.size > 0)
  398. {
  399. route.curPoint += (int)((double)rand()/RAND_MAX *MAX_ROUTE_STEPONCE + MAX_ROUTE_STEPONCE);
  400. if(route.curPoint > (int)route.size-1)
  401. route.curPoint = route.size-1;
  402. command.eAction = eAiMove;
  403. command.ePhase = ePhaseNone;
  404. command.dwTarget = 0;
  405. command.pntMoveTo.x = route.array[route.curPoint].x;
  406. command.pntMoveTo.y = route.array[route.curPoint].y;
  407. strOutput.Format("------ Prepare to walk to (%d, %d), step: %d/%d", command.pntMoveTo.x, command.pntMoveTo.y, route.curPoint, route.size-1);
  408. utlLogout(strOutput, eLogCommon, true);
  409. aiQueue.push(command, eAiPriRandom);
  410. if(route.curPoint >= (int)route.size-1)
  411. route.curPoint = 0;
  412. goto DONE;
  413. }
  414. DONE:
  415. processCommandQueue();
  416. return(0);
  417. }
  418. int processCommandQueue()
  419. {
  420. AICOMMAND command;
  421. CString strOutput;
  422. if(!aiQueue.pop(command))
  423. {
  424. return(-1);
  425. }
  426. switch(command.eAction)
  427. {
  428. case eAiAttack:
  429. aiProcessAttackCommand(&command);
  430. break;
  431. case eAiSit:
  432. aiProcessSitCommand(&command);
  433. break;
  434. case eAiStand:
  435. aiProcessStandCommand(&command);
  436. break;
  437. case eAiMove:
  438. aiProcessMoveCommand(&command);
  439. break;
  440. case eAiPickup:
  441. aiProcessPickupCommand(&command);
  442. break;
  443. }
  444. return(0);
  445. }
  446. int aiProcessAttackCommand(AICOMMAND *pCommand)
  447. {
  448. POINT pnt;
  449. int nIndex = monsters.FindId(pCommand->dwTarget);
  450. CString strOutput;
  451. AICOMMAND *pNewCommand = NULL;
  452. static DWORD dwQuiken = GetTickCount();
  453. MONSTER monster;
  454. // Check if finish
  455. if(-1 == nIndex)
  456. {
  457. aiQueue.finish();
  458. goto DONE;
  459. }
  460. monster = monsters[nIndex];
  461. while(true)
  462. {
  463. switch(pCommand->ePhase)
  464. {
  465. case ePhaseNone:
  466. if(utlDistanceFrom(monster.pntTo, you.pntTo) > 3)
  467. {
  468. // move needed
  469. if(field.FindNearestPoint(you.pntTo, monster.pntTo, &pnt))
  470. {
  471. pNewCommand = new AICOMMAND;
  472. pNewCommand->eAction = eAiMove;
  473. pNewCommand->pntMoveTo = pnt;
  474. pNewCommand->dwTarget = monster.dwId;
  475. }
  476. else
  477. {
  478. strOutput.Format("%s can not be reached.",
  479. utlFindTarget(monster.dwId));
  480. utlLogout(strOutput, eLogError, true);
  481. aiQueue.cancelAll();
  482. }
  483. goto DONE;
  484. }
  485. else
  486. {
  487. // Proceed
  488. utlChangeAttackPhase(pCommand, eAtkPhaseEquip);
  489. }
  490. break;
  491. case eAtkPhaseEquip:
  492. // Change equipment
  493. utlChangeAttackPhase(pCommand, eAtkPhaseSkillUse);
  494. break;
  495. case eAtkPhaseEquipping:
  496. //
  497. break;
  498. case eAtkPhaseSkillUse:
  499. // Use Skill
  500. utlChangeAttackPhase(pCommand, eAtkPhaseAttack);
  501. if(you.wSp > 30 && !you.bTwoHandsQuiken && GetTickCount() > dwQuiken + 300000)
  502. {
  503. // sendUseSkill(10, 60, dwAccountId);
  504. dwQuiken = GetTickCount();
  505. goto DONE;
  506. }
  507. break;
  508. case eAtkPhaseAttack:
  509. if(utlDistanceFrom(monster.pntTo, you.pntTo) > 3)
  510. {
  511. // Re-move
  512. utlChangeAttackPhase(pCommand, (AIATTACKPHASE)ePhaseNone);
  513. }
  514. else
  515. {
  516. // Attack
  517. nIndex = damages.FindDamage(dwAccountId, pCommand->dwTarget);
  518. if(-1 != nIndex)
  519. {
  520. pCommand->dwLastDamage = damages[nIndex].dwDamage;
  521. }
  522. else
  523. {
  524. pCommand->dwLastDamage =0;
  525. }
  526. pCommand->dwTimeout = GetTickCount() + TIMEOUT_ATTACK;
  527. utlChangeAttackPhase(pCommand, eAtkPhaseAttacking);
  528. sendAttack(pCommand->dwTarget, 7);
  529. goto DONE;
  530. }
  531. break;
  532. case eAtkPhaseAttacking:
  533. if(utlDistanceFrom(monster.pntTo, you.pntTo) > 3)
  534. {
  535. // Re-move
  536. utlChangeAttackPhase(pCommand, (AIATTACKPHASE)ePhaseNone);
  537. }
  538. else
  539. {
  540. if(GetTickCount() > pCommand->dwTimeout)
  541. {
  542. DWORD intCurDamage = 0;
  543. nIndex = damages.FindDamage(dwAccountId, pCommand->dwTarget);
  544. if(-1 != nIndex)
  545. {
  546. intCurDamage = damages[nIndex].dwDamage;
  547. }
  548. if(intCurDamage == pCommand->dwLastDamage)
  549. {
  550. strOutput.Format("%s can not be attacked!",
  551. utlFindTarget(monster.dwId));
  552. utlLogout(strOutput, eLogError, true);
  553. // Can not hurt target
  554. aiQueue.cancelAll();
  555. }
  556. else
  557. {
  558. // Keep on attacking
  559. pCommand->dwLastDamage = intCurDamage;
  560. pCommand->dwTimeout = GetTickCount() + TIMEOUT_ATTACK;
  561. utlChangeAttackPhase(pCommand, (AIATTACKPHASE)eAtkPhaseAttacking);
  562. }
  563. }
  564. goto DONE;
  565. }
  566. break;
  567. }
  568. }
  569. DONE:
  570. if(pNewCommand)
  571. {
  572. aiQueue.extend(*pNewCommand);
  573. delete pNewCommand;
  574. }
  575. return(0);
  576. }
  577. int aiProcessPickupCommand(AICOMMAND *pCommand)
  578. {
  579. POINT pnt;
  580. int nIndex = items.FindId(pCommand->dwTarget);
  581. CString strOutput;
  582. AICOMMAND *pNewCommand = NULL;
  583. ITEM item;
  584. // Check if finish
  585. if(-1 == nIndex)
  586. {
  587. aiQueue.finishAll();
  588. goto DONE;
  589. }
  590. item = items[nIndex];
  591. while(true)
  592. {
  593. switch(pCommand->ePhase)
  594. {
  595. case ePhaseNone:
  596. if(utlDistanceFrom(item.pntPos, you.pntTo) > 3)
  597. {
  598. // Calculate route
  599. if(field.FindNearestPoint(you.pntTo, item.pntPos, &pnt))
  600. {
  601. pNewCommand = new AICOMMAND;
  602. pNewCommand->eAction = eAiMove;
  603. pNewCommand->pntMoveTo = pnt;
  604. pNewCommand->dwTarget = item.dwId;
  605. }
  606. else
  607. {
  608. strOutput.Format("%s@ can not be reached!", utlFindTargetItem(item.dwId));
  609. utlLogout(strOutput, eLogError, true);
  610. aiQueue.cancelAll();
  611. }
  612. goto DONE;
  613. }
  614. else
  615. {
  616. // Proceed
  617. utlChangePickupPhase(pCommand, ePickupPhasePick);
  618. }
  619. break;
  620. case ePickupPhaseLook:
  621. utlChangePickupPhase(pCommand, ePickupPhasePick);
  622. break;
  623. case ePickupPhaseLooking:
  624. //
  625. break;
  626. case ePickupPhasePick:
  627. if(utlDistanceFrom(items[nIndex].pntPos, you.pntTo) > 3)
  628. {
  629. // Retry
  630. utlChangePickupPhase(pCommand, (AIPICKUPPHASE)ePhaseNone);
  631. }
  632. else
  633. {
  634. // Start pickup
  635. pCommand->dwTimeout = GetTickCount() + TIMEOUT_PICKUP;
  636. utlChangePickupPhase(pCommand, ePickupPhasePicking);
  637. sendTake(pCommand->dwTarget);
  638. goto DONE;
  639. }
  640. break;
  641. case ePickupPhasePicking:
  642. sendTake(pCommand->dwTarget);
  643. if(item.nPickupFailed)
  644. {
  645. // Retry
  646. utlChangePickupPhase(pCommand, (AIPICKUPPHASE)ePhaseNone);
  647. items[nIndex].nPickupFailed = 0;
  648. strOutput.Format("Failed to pickup %s, retry!", utlFindTargetItem(item.dwId));
  649. utlLogout(strOutput, eLogError, true);
  650. }
  651. else
  652. {
  653. if(GetTickCount() > pCommand->dwTimeout)
  654. {
  655. strOutput.Format("Pickup %s timeout!", utlFindTargetItem(item.dwId));
  656. utlLogout(strOutput, eLogError, true);
  657. aiQueue.cancelAll();
  658. }
  659. goto DONE;
  660. }
  661. break;
  662. }
  663. }
  664. DONE:
  665. if(pNewCommand)
  666. {
  667. aiQueue.extend(*pNewCommand);
  668. delete pNewCommand;
  669. }
  670. return(0);
  671. }
  672. int aiProcessSitCommand(AICOMMAND *pCommand)
  673. {
  674. if(you.bSit)
  675. {
  676. aiQueue.finish();
  677. }
  678. else
  679. {
  680. switch(pCommand->ePhase)
  681. {
  682. case ePhaseNone:
  683. pCommand->dwTimeout = GetTickCount() + TIMEOUT_SIT;
  684. utlChangeSitPhase(pCommand, eSitPhaseSitting);
  685. sendSit();
  686. break;
  687. case eSitPhaseSitting:
  688. if(GetTickCount() > pCommand->dwTimeout)
  689. aiQueue.cancelAll();
  690. break;
  691. }
  692. }
  693. return(0);
  694. }
  695. int aiProcessStandCommand(AICOMMAND *pCommand)
  696. {
  697. if(!you.bSit)
  698. {
  699. aiQueue.finish();
  700. }
  701. else
  702. {
  703. switch(pCommand->ePhase)
  704. {
  705. case ePhaseNone:
  706. pCommand->dwTimeout = GetTickCount() + TIMEOUT_STAND;
  707. utlChangeStandPhase(pCommand, eStandPhaseStanding);
  708. sendStand();
  709. break;
  710. case eStandPhaseStanding:
  711. if(GetTickCount() > pCommand->dwTimeout)
  712. aiQueue.cancelAll();
  713. break;
  714. }
  715. }
  716. return(0);
  717. }
  718. int aiProcessMoveCommand(AICOMMAND *pCommand)
  719. {
  720. CString strOutput;
  721. BOOL bFound = false;
  722. BOOL bNeedRemove = false;
  723. AICOMMAND *pNewCommand = NULL;
  724. // check for cancel
  725. do
  726. {
  727. if(pCommand->dwTarget != 0 &&
  728. -1 == monsters.FindId(pCommand->dwTarget) &&
  729. -1 == items.FindId(pCommand->dwTarget))
  730. {
  731. // lost target
  732. strOutput.Format("Lost target(%X), giveup!", pCommand->dwTarget);
  733. bNeedRemove = true;
  734. break;
  735. }
  736. if(pCommand->dwTarget != 0 && -1 != monsters.FindId(pCommand->dwTarget))
  737. {
  738. if(GetTickCount() - monsters[monsters.FindId(pCommand->dwTarget)].dwAppearTime > 120000)
  739. {
  740. // lost target
  741. strOutput.Format("Target(%X) timeout, giveup!", pCommand->dwTarget);
  742. bNeedRemove = true;
  743. break;
  744. }
  745. }
  746. if(pCommand->dwTarget != 0 && -1 != items.FindId(pCommand->dwTarget))
  747. {
  748. if(GetTickCount() - items[items.FindId(pCommand->dwTarget)].dwAppearTime > 120000)
  749. {
  750. // lost target
  751. strOutput.Format("Target(%X) timeout, giveup!", pCommand->dwTarget);
  752. bNeedRemove = true;
  753. break;
  754. }
  755. }
  756. if(utlDistanceFrom(you.pntTo, pCommand->pntMoveTo) > 30)
  757. {
  758. // Too far
  759. strOutput.Format("Target(%X) is too far from you, giveup!", pCommand->dwTarget);
  760. bNeedRemove = true;
  761. break;
  762. }
  763. // Check for portals
  764. for(int i=0; i<portals.GetSize(); i++)
  765. {
  766. if(utlDistanceFrom(portals[i].pntPos, pCommand->pntMoveTo) <= 10)
  767. {
  768. // lost target
  769. strOutput.Format("Portal found, giveup!", pCommand->dwTarget);
  770. bNeedRemove = true;
  771. break;
  772. }
  773. }
  774. }while(0);
  775. if(bNeedRemove)
  776. {
  777. utlLogout(strOutput, eLogError, true);
  778. aiQueue.cancelAll();
  779. goto DONE;
  780. }
  781. // Process phase change
  782. while(true)
  783. {
  784. switch(pCommand->ePhase)
  785. {
  786. case ePhaseNone:
  787. if(!you.bSit)
  788. {
  789. // Proceed
  790. utlChangeMovePhase(pCommand, (AIMOVEPHASE)eMovePhaseMove);
  791. }
  792. else
  793. {
  794. // Generate stand command
  795. pNewCommand = new AICOMMAND;
  796. pNewCommand->eAction = eAiStand;
  797. pNewCommand->ePhase = ePhaseNone;
  798. goto DONE;
  799. }
  800. break;
  801. case eMovePhaseMove:
  802. pCommand->pntMoveFrom = you.pntTo;
  803. pCommand->dwTimeout = GetTickCount()+(DWORD)(SECOND_PER_BLOCK*utlDistanceFrom(pCommand->pntMoveFrom, pCommand->pntMoveTo));
  804. utlChangeMovePhase(pCommand, eMovePhaseMoving);
  805. sendMove(pCommand->pntMoveTo);
  806. goto DONE;
  807. break;
  808. case eMovePhaseMoving:
  809. if(GetTickCount() > pCommand->dwTimeout)
  810. {
  811. if(you.pntTo.x == pCommand->pntMoveTo.x &&
  812. you.pntTo.y == pCommand->pntMoveTo.y)
  813. {
  814. aiQueue.finish();
  815. goto DONE;
  816. }
  817. if(you.pntTo.x == pCommand->pntMoveFrom.x &&
  818. you.pntTo.y == pCommand->pntMoveFrom.y)
  819. {
  820. // Timeup: not moved, maybe can not reach
  821. if(GetTickCount() > pCommand->dwTimeout + TIMEOUT_MOVE)
  822. {
  823. strOutput.Format("Move to %s@(%d, %d) timeout, giveup!", utlFindTarget(pCommand->dwTarget), pCommand->pntMoveTo.x, pCommand->pntMoveTo.y);
  824. utlLogout(strOutput, eLogError, true);
  825. aiQueue.cancelAll(); 
  826. }
  827. goto DONE;
  828. }
  829. // Timeup: moved but has not reached, try again
  830. utlChangeMovePhase(pCommand, eMovePhaseMove);
  831. }
  832. else
  833. {
  834. goto DONE;
  835. }
  836. break;
  837. }
  838. }
  839. DONE:
  840. if(pNewCommand)
  841. {
  842. aiQueue.extend(*pNewCommand);
  843. delete pNewCommand;
  844. }
  845. return(0);
  846. }
  847. BOOL aiGetUnderAttackFrom(DWORD &dwTarget)
  848. {
  849. BOOL bRtn = false;
  850. for(int i=0; i<monsters.GetSize(); i++)
  851. {
  852. if(-1 != damages.FindDamage(monsters[i].dwId, dwAccountId))
  853. {
  854. dwTarget = monsters[i].dwId;
  855. bRtn = true;
  856. break;
  857. }
  858. }
  859. return(bRtn);
  860. }
  861. BOOL aiGetItemToPickup(ITEMPRIORITY priority, DWORD &dwTarget)
  862. {
  863. BOOL bRtn = false;
  864. int nPriFound;
  865. for(int i=0; i<items.GetSize(); i++)
  866. {
  867. nPriFound = atoi(mapItem.FindValue(items[i].wType, eItemPriority));
  868. if(nPriFound <= priority && !items[i].bAiIgnore)
  869. {
  870. dwTarget = items[i].dwId;
  871. bRtn = true;
  872. break;
  873. }
  874. }
  875. return(bRtn);
  876. }
  877. BOOL aiCheckTeleportCondition()
  878. {
  879. BOOL bRtn = false;
  880. CDWordArray dwTargetArray, dwDamageArray;
  881. if(action == eAiAttack && you.wHp < you.wHpMax * 0.2)
  882. {
  883. bRtn = true;
  884. }
  885. if(damages.FindDamageFrom(dwAccountId, dwTargetArray, dwDamageArray))
  886. {
  887. if(dwTargetArray.GetSize() > 6)
  888. bRtn = true;
  889. }
  890. return(bRtn);
  891. }