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

外挂编程

开发平台:

Visual C++

  1. #include <stdafx.h>
  2. #include "ROA.h"
  3. #include "ROAUtils.h"
  4. #include "ROAView.h"
  5. #include "math.h"
  6. CString utlParseString(CString& str)
  7. {
  8. CString strRtn = _T("");
  9. int nIndex;
  10. nIndex = str.Find((","));
  11. if(nIndex == -1)
  12. {
  13. strRtn = str;
  14. str.Empty();
  15. }
  16. else
  17. {
  18. strRtn = str.Left(nIndex);
  19. str = str.Mid(nIndex+1);
  20. }
  21. return(strRtn);
  22. }
  23. int sendSyncInject()
  24. {
  25. char lpBuffer[3];
  26. memset(lpBuffer, 0, 3);
  27. lpBuffer[0] = 'K';
  28. sockInject.Send(lpBuffer, 3);
  29. return(0);
  30. }
  31. DWORD getROProcessId()
  32. {
  33. HANDLE hSnapshot = INVALID_HANDLE_VALUE;
  34. DWORD dwIdRo = 0;
  35. HANDLE toolhelp;
  36. PROCESSENTRY32 pe;
  37. CString strTemp;
  38. pe.dwSize = sizeof(PROCESSENTRY32);
  39. toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  40. if (Process32First(toolhelp,&pe)) {
  41. do {
  42. strTemp = pe.szExeFile;
  43. int nIndex = strTemp.ReverseFind(_T('\'));
  44. if(nIndex != -1)
  45. strTemp = strTemp.Right(strTemp.GetLength() - nIndex - 1);
  46. if (!stricmp("ragexe.exe", strTemp) || !stricmp("sakexe.exe", strTemp))
  47. {
  48. dwIdRo = pe.th32ProcessID;
  49. break;
  50. }
  51. } while (Process32Next(toolhelp,&pe));
  52. }
  53. CloseHandle(toolhelp);
  54. return(dwIdRo);
  55. }
  56. int sendToServerByInject(char *lpBuffer, WORD sSize)
  57. {
  58. ASSERT(sSize > 0);
  59. static char pBufNew[MAX_BUFFER_LEN];
  60. WORD sSizeNew = sSize + 3;
  61. memset(pBufNew, 0, MAX_BUFFER_LEN);
  62. pBufNew[0] = 'S';
  63. *((WORD*)(pBufNew+1)) = sSize;
  64. int cntMax = strlen(cSendKey);
  65. if(cntMax > 0)
  66. {
  67. int cnt = 0;
  68. for(int i=0; i<sSize; i++)
  69. {
  70. *(lpBuffer+i) = (*(lpBuffer+i)) + cSendKey[cnt];
  71. if(++cnt >= cntMax)
  72. cnt = 0;
  73. }
  74. }
  75. memcpy(pBufNew+3, lpBuffer, sSize);
  76. sockInject.Send(pBufNew, sSizeNew);
  77. return(0);
  78. }
  79. int sendToClientByInject(char *lpBuffer, WORD sSize)
  80. {
  81. ASSERT(sSize > 0);
  82. static char pBufNew[MAX_BUFFER_LEN];
  83. WORD sSizeNew = sSize + 3;
  84. memset(pBufNew, 0, sSizeNew);
  85. pBufNew[0] = 'R';
  86. *((WORD*)(pBufNew+1)) = sSize;
  87. memcpy(pBufNew+3, lpBuffer, sSize);
  88. sockInject.Send(pBufNew, sSizeNew);
  89. return(0);
  90. }
  91. int injectAdminMessage(LPCTSTR lpMsg)
  92. {
  93. ASSERT(lpMsg != NULL);
  94. if(nConnState < 5)
  95. return(-1);
  96. utlLogout(lpMsg, eLogError, false);
  97. char *pBufNew = NULL;
  98. char *p = NULL;
  99. WORD sSizeNew = strlen(lpMsg) + 5 + strlen(ROA_HEADER);
  100. pBufNew = new char [sSizeNew];
  101. memset(pBufNew, 0, sSizeNew);
  102. p = pBufNew;
  103. *((WORD*)p) = 0x009A; p += 2;
  104. *((WORD*)p) = sSizeNew; p += 2;
  105. strcpy(p, ROA_HEADER); p += strlen(ROA_HEADER);
  106. strcpy(p, lpMsg);               p += strlen(lpMsg);
  107. *p = 0;
  108. // encrypt($msg, $msg);
  109. sendToClientByInject(pBufNew, sSizeNew);
  110. delete pBufNew;
  111. return(0);
  112. }
  113. int injectMessage(LPCTSTR lpMsg)
  114. {
  115. ASSERT(lpMsg != NULL);
  116. if(nConnState < 5)
  117. return(-1);
  118. utlLogout(lpMsg, eLogCommon, false);
  119. static char cBufferMsg[1024];
  120. char *p = cBufferMsg;
  121. WORD sSizeNew = strlen(lpMsg) + 9 + strlen(ROA_HEADER);
  122. *((WORD*)p) = 0x0109; p += 2;
  123. *((WORD*)p) = sSizeNew; p += 2;
  124. *((DWORD*)p) = 0; p += 4;
  125. strcpy(p, ROA_HEADER); p += strlen(ROA_HEADER);
  126. strcpy(p, lpMsg); p += strlen(lpMsg);
  127. *p = 0;
  128. // encrypt($msg, $msg);
  129. sendToClientByInject(cBufferMsg, sSizeNew);
  130. // EnterCriticalSection(&criticalSection);
  131. return(0);
  132. }
  133. char* utlPrintHex(char *lpBuffer, WORD wLen)
  134. {
  135. static char cPrintBuf[1024];
  136. // memset(cPrinted, 0, 1024);
  137. char *p = cPrintBuf;
  138. int nPrintlen = (wLen>100) ? 100 : wLen;
  139. for(int i=0; i<nPrintlen; i++)
  140. {
  141. if(i % 5 == 0)
  142. sprintf(p++, "|");
  143. else
  144. sprintf(p++, " ");
  145. BYTE temp = lpBuffer[i];
  146. sprintf(p, "%02X", temp);
  147. p += 2;
  148. }
  149. if(wLen>100)
  150. {
  151. sprintf(p, "...");
  152. p += 3;
  153. }
  154. p = '';
  155. return(cPrintBuf);
  156. }
  157. int sendWelcomeMessage()
  158. {
  159. CString strOutput;
  160. int i;
  161. for(i=0; i<sizeof(strWelcome)/sizeof(strWelcome[0]); i++)
  162. {
  163. injectAdminMessage(strWelcome[i]);
  164. }
  165. if(dwAccountId == 0)
  166. {
  167. injectAdminMessage("无法获取人物信息,请重新登录帐号!");
  168. }
  169. else
  170. {
  171. if(bProfileLoaded)
  172. injectAdminMessage(_T("已读入用户设定文件"));
  173. else
  174. injectAdminMessage(_T("无法读入用户设定文件,请按END键或选择ROA菜单进行战斗设置"));
  175. }
  176. if(hHook == NULL)
  177. {
  178. injectAdminMessage(_T("快捷键无效或已关闭!"));
  179. }
  180. bWelcomeSent = true;
  181. return(0);
  182. }
  183. void utlLogout(LPCTSTR lpszMsg, LOG_LEVEL level, BOOL bAi)
  184. {
  185. #ifndef VIPMODE
  186. return;
  187. #endif
  188. if(llFile == eLogNone && llDlg == eLogNone)
  189. return;
  190. CString strLog;
  191. CTime time = CTime::GetCurrentTime();
  192. CString strTime;
  193. strTime.Format( _T("[%02d/%02d %02d:%02d:%02d] "), time.GetMonth(), time.GetDay(),
  194. time.GetHour(), time.GetMinute(), time.GetSecond() );
  195. switch(level)
  196. {
  197. case eLogError:
  198. strLog = "(E) ";
  199. break;
  200. case eLogCommon:
  201. strLog = "(C) ";
  202. break;
  203. case eLogInfo:
  204. strLog = "(I) ";
  205. break;
  206. default:
  207. strLog = "(D) ";
  208. break;
  209. }
  210. if(bAi)
  211. strLog += "****AI****";
  212. strLog = strTime + strLog + lpszMsg;
  213. if(level <= llFile)
  214. {
  215. fLog.Write(strLog, strlen(strLog));
  216. fLog.Write("rn", 2);
  217. }
  218. if(level <= llDlg)
  219. {
  220. ((CROAView*)AfxGetMainWnd())->AddMessage(lpszMsg, level, bAi);
  221. }
  222. if(level <= llRo && nConnState == 5)
  223. {
  224. injectMessage(strLog);
  225. }
  226. }
  227. void utlLogout2(LPCTSTR lpszMsg, LOG_LEVEL level, BOOL bAi)
  228. {
  229. #ifndef VIPMODE
  230. return;
  231. #endif
  232. CString strLog;
  233. CTime time = CTime::GetCurrentTime();
  234. CString strTime;
  235. strTime.Format( _T("[%02d/%02d %02d:%02d:%02d] "), time.GetMonth(), time.GetDay(),
  236. time.GetHour(), time.GetMinute(), time.GetSecond() );
  237. switch(level)
  238. {
  239. case eLogError:
  240. strLog = "(E) ";
  241. break;
  242. case eLogCommon:
  243. strLog = "(C) ";
  244. break;
  245. case eLogInfo:
  246. strLog = "(I) ";
  247. break;
  248. default:
  249. strLog = "(D) ";
  250. break;
  251. }
  252. if(bAi)
  253. strLog += "****AI****";
  254. strLog = strTime + strLog + lpszMsg;
  255. if(level <= llFile)
  256. {
  257. fLog.Write(strLog, strlen(strLog));
  258. }
  259. if(level <= llDlg)
  260. {
  261. ((CROAView*)AfxGetMainWnd())->AddMessage2(lpszMsg, level, bAi);
  262. }
  263. if(level <= llRo && nConnState == 5)
  264. {
  265. injectMessage(strLog);
  266. }
  267. }
  268. void utlLogout3(LPCTSTR lpszMsg, LOG_LEVEL level, BOOL bAi)
  269. {
  270. #ifndef VIPMODE
  271. return;
  272. #endif
  273. if(level <= llFile)
  274. {
  275. fLog.Write(lpszMsg, strlen(lpszMsg));
  276. fLog.Write("rn", 2);
  277. }
  278. if(level <= llDlg)
  279. {
  280. ((CROAView*)AfxGetMainWnd())->AddMessage3(lpszMsg, level, bAi);
  281. }
  282. if(level <= llRo && nConnState == 5)
  283. {
  284. injectMessage(lpszMsg);
  285. }
  286. }
  287. void utlLogout4(LPCTSTR lpszMsg)
  288. {
  289. injectMessage(lpszMsg);
  290. return;
  291. }
  292. void utlChangeState(int nState1, int nState2)
  293. {
  294. CString strLog;
  295. int nStateOld = nConnState;
  296. if(nState1 == -1 || nConnState == nState1)
  297. nConnState = nState2;
  298. if(nStateOld != nConnState)
  299. {
  300. strLog.Format("切换连换状态: %d -> %d", nStateOld, nConnState);
  301. utlLogout(strLog, eLogInfo, false);
  302. }
  303. if(nConnState == 5)
  304. {
  305. ;
  306. }
  307. }
  308. void utlInitMapChangeVars()
  309. {
  310. inventory.RemoveAll();
  311. monsters.RemoveAll();
  312. players.RemoveAll();
  313. portals.RemoveAll();
  314. items.RemoveAll();
  315. cart.RemoveAll();
  316. damages.RemoveAll();
  317. spells.RemoveAll();
  318. you.init();
  319. if(nCharSelected >= 0 && nCharSelected <= 2)
  320. you = youTemp[nCharSelected];
  321. utlChangeMode(eModeNormal, 0);
  322. bAiEnabled = true;
  323. ufAutoSaClassChange(0);
  324. dwAttackTick = 0;
  325. dwUseItemTick = 0;
  326. }
  327. POINT utlMakeCoords(BYTE *pCoords)
  328. {
  329. POINT pntRtn;
  330. pntRtn.x = pCoords[0] * 4 + (pCoords[1] & 0xC0) / 64;
  331. pntRtn.y = (pCoords[1] & 0x3F) * 16 + (pCoords[2] & 0xF0) / 16;
  332. return(pntRtn);
  333. }
  334. POINT utlMakeCoords2(BYTE *pCoords)
  335. {
  336. POINT pntRtn;
  337. pntRtn.x = (pCoords[1] & 0xFC) / 4 + (pCoords[0] & 0x0F) * 64;
  338. pntRtn.y = (pCoords[1] & 0x03) * 256 + pCoords[2];
  339. return(pntRtn);
  340. }
  341. double utlDistanceFrom(POINT pnt1, POINT pnt2)
  342. {
  343. return(sqrt((pnt1.x-pnt2.x)*(pnt1.x-pnt2.x)+(pnt1.y-pnt2.y)*(pnt1.y-pnt2.y)));
  344. }
  345. CString utlFindTarget(DWORD dwId)
  346. {
  347. CString strRtn = "未知人物";
  348. do
  349. {
  350. if(dwId == dwAccountId)
  351. {
  352. strRtn = _T("你");
  353. break;
  354. }
  355. if(-1 != monsters.FindId(dwId))
  356. {
  357. strRtn.Format("%s(%X)@(%d, %d)", monsters[monsters.FindId(dwId)].cName, dwId, monsters[monsters.FindId(dwId)].pntTo.x, monsters[monsters.FindId(dwId)].pntTo.y);
  358. break;
  359. }
  360. if(-1 != players.FindId(dwId))
  361. {
  362. strRtn.Format("%s(%X)", players[players.FindId(dwId)].cName, dwId);
  363. break;
  364. }
  365. }while(0);
  366. return(strRtn);
  367. }
  368. CString utlFindTargetItem(DWORD dwId)
  369. {
  370. CString strRtn = "未知物品";
  371. int nIdx = items.FindId(dwId);
  372. if(-1 != nIdx)
  373. {
  374. strRtn.Format("%s(%X)@(%d, %d)", mapItem.FindValue(items[nIdx].wType, eItemName), dwId, items[nIdx].pntPos.x, items[nIdx].pntPos.y);
  375. }
  376. return(strRtn);
  377. }
  378. CString utlFindTargetInventory(int nIndex)
  379. {
  380. CString strRtn = "未知物品/装备";
  381. int nIdx = inventory.FindIndex(nIndex);
  382. if(-1 != nIdx)
  383. {
  384. strRtn = utlGetInventoryName(&inventory[nIdx]);
  385. }
  386. return(strRtn);
  387. }
  388. void utlUpdateDamage(DWORD dwSource, DWORD dwTarget, WORD wDamage, int nType)
  389. {
  390. DAMAGE damage;
  391. int nIndex;
  392. CString strTemp, strOutput;
  393. strOutput = "Unknown damage!";
  394. if(dwSource == dwAccountId || dwTarget == dwAccountId)
  395. {
  396. if((dwSource == dwAccountId &&
  397. -1 != monsters.FindId(dwTarget)) ||
  398. (dwTarget == dwAccountId &&
  399. -1 != monsters.FindId(dwSource)))
  400. {
  401. // Attack
  402. nIndex = damages.FindDamage(dwSource, dwTarget);
  403. if(-1 != nIndex)
  404. {
  405. damage = damages.GetAt(nIndex);
  406. }
  407. else
  408. {
  409. damage.dwId1 = dwSource;
  410. damage.dwId2 = dwTarget;
  411. damage.dwDamage = 0;
  412. damage.dwStart = GetTickCount();
  413. nIndex = damages.Add(damage);
  414. }
  415. // if(dwSource == dwAccountId && wDamage == 0)
  416. // wDamage = 1;
  417. damage.dwDamage += wDamage;
  418. damage.dwDamage2[nType] += wDamage;
  419. if(wDamage != 0)
  420. {
  421. damage.dwHits[nType]++;
  422. if(wDamage > damage.dwDamageMax[nType])
  423. {
  424. damage.dwDamageMax[nType] = wDamage;
  425. }
  426. if(wDamage < damage.dwDamageMin[nType])
  427. {
  428. damage.dwDamageMin[nType] = wDamage;
  429. }
  430. }
  431. else
  432. damage.dwMiss[nType]++;
  433. damages.SetAt(nIndex, damage);
  434. }
  435. /*
  436. if(-1 != monsters.FindId(dwTarget))
  437. {
  438. // Attack
  439. monsters[monsters.FindId(dwTarget)].bClean = false;
  440. }
  441. */
  442. return;
  443. }
  444. CString utlCalculateHits(WORD wDamage)
  445. {
  446. CString strRtn;
  447. if(0 == wDamage)
  448. strRtn = "Miss!";
  449. else
  450. strRtn.Format("%d hits!", wDamage);
  451. return(strRtn);
  452. }
  453. BYTE* utlGetCoord(POINT pnt)
  454. {
  455. static BYTE coord[3];
  456. coord[0] = pnt.x / 4;
  457. coord[1] = (pnt.x % 4) * 64 + int(pnt.y / 16);
  458. coord[2] = (pnt.y % 16) * 16;
  459. return(coord);
  460. }
  461. int sendTeleport(LPCTSTR pLocation)
  462. {
  463. ASSERT(pLocation != NULL);
  464. char *pBufNew = NULL;
  465. char *p = NULL;
  466. WORD sSizeNew = 16+4;
  467. CString strOutput;
  468. pBufNew = new char [sSizeNew];
  469. memset(pBufNew, 0, sSizeNew);
  470. p = pBufNew;
  471. *((DWORD*)p) = 0x001A011B; p += 4;
  472. strncpy(p, pLocation, 15);
  473. // encrypt($msg, $msg);
  474. parseSendData(pBufNew, sSizeNew, true);
  475. delete pBufNew;
  476. return(0);
  477. }
  478. int utlUseTeleport(int nLevel)
  479. {
  480. int nItem = -1, nSkill = -1;
  481. BOOL bDone = false;
  482. if(nConnState < 5)
  483. return(-1);
  484. nItem = inventory.FindId((DWORD)(600 + nLevel));
  485. nSkill = utlFindSkillByAlias(_T("瞬间移动"));
  486. if(nLevel == 2)
  487. {
  488. if(nItem != -1)
  489. {
  490. sendUseItem((WORD)inventory[nItem].dwIndex, dwAccountId);
  491. bDone = true;
  492. }
  493. }
  494. else
  495. {
  496. if(nSkill != -1)
  497. {
  498. if(bFlyUsed)
  499. {
  500. sendTeleport(_T("Random"));
  501. }
  502. else
  503. {
  504. sendUseSkill(1, (WORD)skills[nSkill].dwId, dwAccountId);
  505. Sleep(100);
  506. bFlyUsed = true;
  507. sendTeleport(_T("Random"));
  508. }
  509. bDone = true;
  510. }
  511. else
  512. {
  513. if(nItem != -1)
  514. {
  515. sendUseItem((WORD)inventory[nItem].dwIndex, dwAccountId);
  516. bDone = true;
  517. }
  518. }
  519. }
  520. if(!bDone)
  521. {
  522. injectAdminMessage(_T("无法使用技能[瞬移]"));
  523. }
  524. return(0);
  525. }
  526. int sendMove(POINT pntTo)
  527. {
  528. char buffer[5];
  529. *(WORD*)buffer = 0x0085;
  530. memcpy(buffer+2, utlGetCoord(pntTo), 3);
  531. parseSendData(buffer, 5, true);
  532. return(0);
  533. }
  534. int sendEmotion(BYTE bEmotion)
  535. {
  536. char buffer[3];
  537. *(WORD*)buffer = 0x00BF;
  538. buffer[2] = bEmotion;
  539. parseSendData(buffer, 3, true);
  540. return(0);
  541. }
  542. int sendTake(DWORD dwItemId)
  543. {
  544. char buffer[6];
  545. *(WORD*)(buffer+0) = 0x009f;
  546. *(DWORD*)(buffer+2) = dwItemId;
  547. if(!you.bSit)
  548. parseSendData(buffer, 6, true);
  549. return(0);
  550. }
  551. int sendAttack(DWORD dwMonster, BYTE byMode)
  552. {
  553. char buffer[7];
  554. *(WORD*)(buffer+0) = 0x0089;
  555. *(DWORD*)(buffer+2) = dwMonster;
  556. *(BYTE*)(buffer+6) = byMode;
  557. parseSendData(buffer, 7, true);
  558. return(0);
  559. }
  560. int sendUseSkill(WORD wLevel, WORD wSkillId, DWORD dwTarget)
  561. {
  562. char buffer[10];
  563. *(WORD*)(buffer+0) = 0x0113;
  564. *(WORD*)(buffer+2) = wLevel;
  565. *(WORD*)(buffer+4) = wSkillId;
  566. *(DWORD*)(buffer+6) = dwTarget;
  567. parseSendData(buffer, 10, true);
  568. return(0);
  569. }
  570. int sendUseSkillOnLoc(WORD wLevel, WORD wSkillId, POINT pnt)
  571. {
  572. char buffer[10];
  573. *(WORD*)(buffer+0) = 0x0116;
  574. *(WORD*)(buffer+2) = wLevel;
  575. *(WORD*)(buffer+4) = wSkillId;
  576. *(WORD*)(buffer+6) = (WORD)pnt.x;
  577. *(WORD*)(buffer+8) = (WORD)pnt.y;
  578. parseSendData(buffer, 10, true);
  579. return(0);
  580. }
  581. int sendStand()
  582. {
  583. char buffer[7];
  584. memset(buffer, 0, 7);
  585. *(WORD*)(buffer+0) = 0x0089;
  586. *(BYTE*)(buffer+6) = 3;
  587. parseSendData(buffer, 7, true);
  588. return(0);
  589. }
  590. int sendSit()
  591. {
  592. char buffer[7];
  593. memset(buffer, 0, 7);
  594. *(WORD*)(buffer+0) = 0x0089;
  595. *(BYTE*)(buffer+6) = 2;
  596. parseSendData(buffer, 7, true);
  597. return(0);
  598. }
  599. int sendRespawn()
  600. {
  601. char buffer[3];
  602. *(BYTE*)(buffer+0) = 0xB2;
  603. *(BYTE*)(buffer+1) = 0;
  604. *(BYTE*)(buffer+2) = 1;
  605. parseSendData(buffer, 3, true);
  606. return(0);
  607. }
  608. int sendUseItem(WORD wIndex, DWORD dwTarget)
  609. {
  610. char buffer[8];
  611. *(WORD*)(buffer+0) = 0x00A7;
  612. *(WORD*)(buffer+2) = wIndex;
  613. *(DWORD*)(buffer+4) = dwTarget;
  614. parseSendData(buffer, 8, true);
  615. return(0);
  616. }
  617. int sendDealCancel()
  618. {
  619. char buffer[3];
  620. *(BYTE*)(buffer+0) = 0xE6;
  621. *(BYTE*)(buffer+1) = 0x00;
  622. *(BYTE*)(buffer+2) = 0x04;
  623. parseSendData(buffer, 3, true);
  624. return(0);
  625. }
  626. int sendAttackStop()
  627. {
  628. char buffer[2];
  629. *(WORD*)(buffer+0) = 0x0118;
  630. parseSendData(buffer, 2, true);
  631. return(0);
  632. }
  633. int sendGetPlayerInfo(DWORD dwId)
  634. {
  635. char buffer[6];
  636. *(WORD*)(buffer+0) = 0x0094;
  637. *(DWORD*)(buffer+2) = dwId;
  638. parseSendData(buffer, 6, true);
  639. return(0);
  640. }
  641. int sendChatParty(LPCTSTR lpszMsg)
  642. {
  643. if(!option.bUsePartyChat)
  644. {
  645. injectMessage(lpszMsg);
  646. return(0);
  647. }
  648. char *pBufNew = NULL;
  649. char *p = NULL;
  650. WORD sSizeNew = strlen(lpszMsg) + 8 + strlen(you.cName);
  651. pBufNew = new char [sSizeNew];
  652. memset(pBufNew, 0, sSizeNew);
  653. p = pBufNew;
  654. *((WORD*)p) = 0x0108; p += 2;
  655. *((WORD*)p) = sSizeNew; p += 2;
  656. strcpy(p, you.cName); p += strlen(you.cName);
  657. strcpy(p, _T(" : ")); p += 3;
  658. strcpy(p, lpszMsg);
  659. parseSendData(pBufNew, sSizeNew, true);
  660. delete pBufNew;
  661. return(0);
  662. }
  663. int sendChatPublic(LPCTSTR lpszMsg)
  664. {
  665. char *pBufNew = NULL;
  666. char *p = NULL;
  667. WORD sSizeNew = strlen(lpszMsg) + 8 + strlen(you.cName);
  668. pBufNew = new char [sSizeNew];
  669. memset(pBufNew, 0, sSizeNew);
  670. p = pBufNew;
  671. *((WORD*)p) = 0x008C; p += 2;
  672. *((WORD*)p) = sSizeNew; p += 2;
  673. strcpy(p, you.cName); p += strlen(you.cName);
  674. strcpy(p, _T(" : ")); p += 3;
  675. strcpy(p, lpszMsg);
  676. parseSendData(pBufNew, sSizeNew, true);
  677. delete pBufNew;
  678. return(0);
  679. }
  680. BOOL utlCheckForGmByName(PLAYER player)
  681. {
  682. BOOL bRtn = false;
  683. if(0 == strcmp(player.cName, _T("gm01")) ||
  684. 0 == strcmp(player.cName, _T("gm02")) ||
  685. 0 == strcmp(player.cName, _T("gm03")) ||
  686. 0 == strcmp(player.cName, _T("gm04")) ||
  687. 0 == strcmp(player.cName, _T("gm05")) ||
  688. 0 == strcmp(player.cName, _T("gm06")))
  689. bRtn = true;
  690. return(bRtn);
  691. }
  692. BOOL utlCheckForWanzi(LPCTSTR lpszGuild)
  693. {
  694. BOOL bRtn = false;
  695. BOOL bFound = false;
  696. int i;
  697. if(strlen(lpszGuild) > 1)
  698. {
  699. for(i=0; i<(int)strlen(lpszGuild)-1; i++)
  700. {
  701. if(lpszGuild[i] == (char)0xCD && lpszGuild[i+1] == (char)0xE8)
  702. {
  703. bFound = true;
  704. break;
  705. }
  706. }
  707. if(bFound)
  708. {
  709. bFound = false;
  710. for(i=0; i<(int)strlen(lpszGuild)-1; i++)
  711. {
  712. if(lpszGuild[i] == (char)0xD7 && lpszGuild[i+1] == (char)0xD3)
  713. {
  714. bFound = true;
  715. break;
  716. }
  717. }
  718. }
  719. if(bFound)
  720. {
  721. bFound = false;
  722. for(i=0; i<(int)strlen(lpszGuild)-1; i++)
  723. {
  724. if(lpszGuild[i] == (char)0xBC && lpszGuild[i+1] == (char)0xD2)
  725. {
  726. bFound = true;
  727. break;
  728. }
  729. }
  730. }
  731. if(bFound)
  732. {
  733. bFound = false;
  734. for(i=0; i<(int)strlen(lpszGuild)-1; i++)
  735. {
  736. if(lpszGuild[i] == (char)0xD7 && lpszGuild[i+1] == (char)0xE5)
  737. {
  738. bFound = true;
  739. break;
  740. }
  741. }
  742. }
  743. if(bFound)
  744. bRtn = true;
  745. }
  746. return(bRtn);
  747. }
  748. BOOL utlCheckForGm(PLAYER player)
  749. {
  750. BOOL bRtn = false;
  751. CString strAid, strDummy;
  752. if(0 != serverip[0][0])
  753. {
  754. strAid.Format(_T("%d.%d.%d.%d#%d"),
  755. serverip[0][2],
  756. serverip[0][3],
  757. serverip[0][4],
  758. serverip[0][5],
  759. player.dwId);
  760. bRtn = mapAvoidAid.Lookup(strAid, strDummy);
  761. }
  762. return(bRtn);
  763. }
  764. int utlFindItemInInventory(LPCTSTR lpszItemName)
  765. {
  766. int nRtn = -1;
  767. CString strTemp;
  768. CString strItemName = lpszItemName;
  769. for(int i=0; i<inventory.GetSize(); i++)
  770. {
  771. strTemp = mapItem.FindValue(inventory[i].dwId, eItemName);
  772. if(strTemp == strItemName)
  773. {
  774. nRtn = inventory[i].dwIndex;
  775. break;
  776. }
  777. }
  778. return(nRtn);
  779. }
  780. #define USE_ITEM(ITEM)
  781. for(i=0; i<ITEM.GetSize(); i++) {
  782. nIndex = utlFindItemInInventory(ITEM[i]);
  783. if(-1 != nIndex){
  784. sendUseItem(nIndex, dwAccountId);
  785. bHealed = true;}}
  786. void utlCheckForAutoHeal()
  787. {
  788. if(dwUseItemTick != 0 && dwUseItemTick > GetTickCount())
  789. return;
  790. if(you.wHp <= 1 || you.bDied || nConnState < 5)
  791. return;
  792. AUTOHEAL2 *pHeal;
  793. BOOL bHealNeed = false;
  794. BOOL bHealed = false;
  795. int nIndex, i;
  796. static BOOL bTeleported = false;
  797. switch(mode)
  798. {
  799. case eModeNormal:
  800. case eModePvp:
  801. case eModeGvg:
  802. pHeal = &settingcmn.autoheal;
  803. break;
  804. case eModeMvp:
  805. pHeal = &settingmvp.autoheal;
  806. break;
  807. }
  808. if(pHeal->bHP)
  809. {
  810. if(you.wHp > pHeal->nHP1Lower && you.wHp < pHeal->nHP1Upper && pHeal->nHP1Upper <= you.wHpMax)
  811. {
  812. bHealNeed = true;
  813. nIndex = utlFindItemInInventory(pHeal->strHP1Item);
  814. if(-1 != nIndex)
  815. {
  816. sendUseItem(nIndex, dwAccountId);
  817. you.wHp = pHeal->nHP1Upper;
  818. bHealed = true;
  819. }
  820. else
  821. {
  822. USE_ITEM(HPITEMS);
  823. you.wHp = pHeal->nHP1Upper;
  824. }
  825. }
  826. if(!bHealed && ((you.wHp > pHeal->nHP2Lower && you.wHp < pHeal->nHP2Upper && pHeal->nHP2Upper <= you.wHpMax) ||
  827. (you.wHp > pHeal->nHP1Lower && you.wHp < pHeal->nHP1Upper && pHeal->nHP1Upper <= you.wHpMax)) &&
  828. you.wSp >= 40)
  829. {
  830. nIndex = utlFindSkillByAlias(_T("治愈术"));
  831. if(nIndex != -1)
  832. {
  833. sendUseSkill(skills[nIndex].wLevel, (unsigned short)skills[nIndex].dwId, dwAccountId);
  834. bHealed = true;
  835. }
  836. }
  837. }
  838. if(bHealNeed && !bHealed)
  839. {
  840. injectAdminMessage(_T("无法自动回复HP,回动回复HP已关闭,请检查物品或技能后手动打开"));
  841. pHeal->bHP = false;
  842. }
  843. if(bHealNeed && bHealed)
  844. {
  845. dwUseItemTick = GetTickCount() + option.nItemUseInterval;
  846. return;
  847. }
  848. bHealNeed = bHealed = false;
  849. if(pHeal->bSP && you.wSp < pHeal->nSPUpper && pHeal->nSPUpper <= you.wSpMax)
  850. {
  851. bHealNeed = true;
  852. nIndex = utlFindItemInInventory(pHeal->strSPItem);
  853. if(-1 != nIndex)
  854. {
  855. sendUseItem(nIndex, dwAccountId);
  856. you.wSp = pHeal->nSPUpper;
  857. bHealed = true;
  858. }
  859. else
  860. {
  861. USE_ITEM(SPITEMS);
  862. you.wSp = pHeal->nSPUpper;
  863. }
  864. }
  865. if(bHealNeed && !bHealed)
  866. {
  867. injectAdminMessage(_T("无法自动回复SP,回动回复SP已关闭,请检查物品后手动打开"));
  868. pHeal->bSP = false;
  869. }
  870. if(bHealNeed && bHealed)
  871. dwUseItemTick = GetTickCount() + option.nItemUseInterval;
  872. if(pHeal->bHPTele && you.wHp < pHeal->nHPTeleUpper && pHeal->nHPTeleUpper <= you.wHpMax)
  873. {
  874. CDWordArray dwTargetArray, dwDamageArray;
  875. if(damages.FindDamageFrom(dwAccountId, dwTargetArray, dwDamageArray))
  876. {
  877. if(dwTargetArray.GetSize() > 0)
  878. {
  879. utlUseTeleport(1);
  880. }
  881. }
  882. }
  883. return;
  884. }
  885. void utlReportMonsterToParty(DWORD dwId)
  886. {
  887. CString strMsg, strTemp;
  888. CString strArraw[] = {"↑", "↗", "→", "↘", "↓", "↙", "←", "↖"};
  889. int nIndex = monsters.FindId(dwId);
  890. if(-1 != nIndex)
  891. {
  892. int tempX, tempY;
  893. tempX = monsters[nIndex].pntPos.x - field.m_szField.cx / 2;
  894. tempY = monsters[nIndex].pntPos.y - field.m_szField.cy / 2;
  895. double dRadio, dRadio1;
  896. dRadio1 = dRadio = atan2(tempY, tempX);
  897. dRadio = dRadio * 180 / 3.1415926;
  898. if(dRadio < 0)
  899. dRadio += 360;
  900. dRadio -= 90;
  901. if(dRadio < 0)
  902. dRadio += 360;
  903. dRadio = 360 - dRadio;
  904. double dDist;
  905. // if(cos(dRadio1) != 0)
  906. // {
  907. // dDist1 = double(field.m_szField.cx)/2/cos(dRadio1);
  908. // }
  909. dDist = sqrt(tempX*tempX + tempY*tempY);
  910. strMsg.Format(_T("发现%s(%d,%d), %d点%d分方向, 距离中心点%d "),
  911. monsters[nIndex].cName, monsters[nIndex].pntPos.x, monsters[nIndex].pntPos.y,
  912. (int)dRadio / 30, ((int)dRadio % 30)*2, (int)dDist);
  913. if(dDist < 50)
  914. {
  915. strTemp = _T("⊙");
  916. }
  917. else
  918. {
  919. if(dRadio <= 22.5 || dRadio >= 337.5)
  920. strTemp = strArraw[0];
  921. else
  922. {
  923. dRadio -= 22.5;
  924. strTemp = strArraw[(int)dRadio/45+1];
  925. }
  926. }
  927. strMsg += strTemp;
  928. sendChatParty(strMsg);
  929. }
  930. }
  931. void utlSetAutoSearchMvp(BOOL bOn)
  932. {
  933. if(bAutoSearch == bOn)
  934. return;
  935. CString strOutput;
  936. bAutoSearch = bOn;
  937. if(bOn)
  938. {
  939. strOutput.Format(_T("开始自动寻找"));
  940. injectAdminMessage(strOutput);
  941. dwAutoSearchTick = GetTickCount() + option.nAutoSearchDelay;
  942. strAutoSearchMap = field.m_strFieldname;
  943. }
  944. else
  945. {
  946. strOutput.Format(_T("结束自动寻找"));
  947. injectAdminMessage(strOutput);
  948. dwAutoSearchTick = 0;
  949. strAutoSearchMap.Empty();
  950. }
  951. return;
  952. }
  953. int utlFindSkillByAlias(LPCTSTR lpszSkillName)
  954. {
  955. CString strTemp;
  956. int nRtn = -1;
  957. for(int i=0; i<mapSkill.GetCount(); i++)
  958. {
  959. strTemp = mapSkill.FindValue(i, eSkillAlias);
  960. if(strTemp.CompareNoCase(lpszSkillName) == 0)
  961. {
  962. for(int j=0; j<skills.GetSize(); j++)
  963. {
  964. int temp = skills[j].dwId;
  965. if(skills[j].dwId == (DWORD)i)
  966. {
  967. nRtn = j;
  968. break;
  969. }
  970. }
  971. }
  972. }
  973. return(nRtn);
  974. }
  975. int utlFindSkillIdByAlias(LPCTSTR lpszSkillName)
  976. {
  977. CString strTemp;
  978. int nRtn = -1;
  979. for(int i=0; i<mapSkill.GetCount(); i++)
  980. {
  981. strTemp = mapSkill.FindValue(i, eSkillAlias);
  982. if(strTemp.CompareNoCase(lpszSkillName) == 0)
  983. {
  984. nRtn = i;
  985. break;
  986. }
  987. }
  988. return(nRtn);
  989. }
  990. int utlLoadBossInfo()
  991. {
  992. CString strProfile, strTemp, strTemp1;
  993. char buffer[1024];
  994. int i;
  995. DWORD dwRtn;
  996. BOSSINFO boss;
  997. int nBossNumber;
  998. bossinfo.RemoveAll();
  999. dwRtn = GetPrivateProfileString(ROA_INI2_BOSSINFO, _T("BossNumber"), _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1000. nBossNumber = atoi(buffer);
  1001. for(i=0; i<nBossNumber; i++)
  1002. {
  1003. int y, m, d, h, min, s;
  1004. y=m=d=h=min=s=0;
  1005. strTemp.Format(_T("Boss%d"), i+1);
  1006. dwRtn = GetPrivateProfileString(ROA_INI2_BOSSINFO, strTemp, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1007. strProfile = buffer;
  1008. strTemp = utlParseString(strProfile);
  1009. boss.strBossName = strTemp;
  1010. strTemp = utlParseString(strProfile);
  1011. y = atoi(strTemp);
  1012. strTemp = utlParseString(strProfile);
  1013. m = atoi(strTemp);
  1014. strTemp = utlParseString(strProfile);
  1015. d = atoi(strTemp);
  1016. strTemp = utlParseString(strProfile);
  1017. h = atoi(strTemp);
  1018. strTemp = utlParseString(strProfile);
  1019. min = atoi(strTemp);
  1020. strTemp = utlParseString(strProfile);
  1021. s = atoi(strTemp);
  1022. CTime time(y, m, d, h, min, s);
  1023. boss.tmBossTime = time;
  1024. CTime tmNow = CTime::GetCurrentTime();
  1025. CTimeSpan ts = tmNow - boss.tmBossTime;
  1026. if(ts.GetTotalHours() <= 24)
  1027. {
  1028. bossinfo.Add(boss);
  1029. }
  1030. }
  1031. utlSortBossInfo();
  1032. return(0);
  1033. }
  1034. int utlWriteBossInfo()
  1035. {
  1036. CString strProfile, strTemp, strTemp1;
  1037. int i;
  1038. strProfile.Format(_T("%d"), bossinfo.GetSize());
  1039. WritePrivateProfileString(ROA_INI2_BOSSINFO, _T("BossNumber"), strProfile, ROA_INI2_FILENAME);
  1040. for(i=0; i<bossinfo.GetSize(); i++)
  1041. {
  1042. strProfile.Format(_T("%s,%d,%d,%d,%d,%d,%d"), bossinfo[i].strBossName,
  1043. bossinfo[i].tmBossTime.GetYear(),
  1044. bossinfo[i].tmBossTime.GetMonth(),
  1045. bossinfo[i].tmBossTime.GetDay(),
  1046. bossinfo[i].tmBossTime.GetHour(),
  1047. bossinfo[i].tmBossTime.GetMinute(),
  1048. bossinfo[i].tmBossTime.GetSecond());
  1049. strTemp.Format(_T("Boss%d"), i+1);
  1050. WritePrivateProfileString(ROA_INI2_BOSSINFO, strTemp, strProfile, ROA_INI2_FILENAME);
  1051. }
  1052. return(0);
  1053. }
  1054. int utlSetMonsterDiedTime(LPCTSTR lpszMonsterName)
  1055. {
  1056. int i, nIndex = -1;
  1057. BOSSINFO boss;
  1058. CString bossfullname;
  1059. bossfullname.Format(_T("%s(%s)"), lpszMonsterName, field.m_strAlias);
  1060. for(i=0; i<bossinfo.GetSize(); i++)
  1061. {
  1062. if(bossinfo[i].strBossName.CompareNoCase(bossfullname) == 0)
  1063. {
  1064. boss = bossinfo[i];
  1065. nIndex = i;
  1066. break;
  1067. }
  1068. }
  1069. CTime tm = CTime::GetCurrentTime();
  1070. boss.tmBossTime = tm;
  1071. boss.reset();
  1072. if(-1 == nIndex)
  1073. {
  1074. boss.strBossName = bossfullname;
  1075. bossinfo.Add(boss);
  1076. }
  1077. else
  1078. {
  1079. bossinfo.SetAt(nIndex, boss);
  1080. }
  1081. utlWriteBossInfo();
  1082. return(0);
  1083. }
  1084. BOOL utlCheckSpellLoc(POINT pnt, WORD wSkill)
  1085. {
  1086. BOOL bRtn = false;
  1087. for(int i=0; i<spells.GetSize(); i++)
  1088. {
  1089. if(spells[i].pntPos.x == pnt.x && spells[i].pntPos.y == pnt.y && spells[i].wSkill == wSkill)
  1090. {
  1091. bRtn = true;
  1092. break;
  1093. }
  1094. }
  1095. return(bRtn);
  1096. }
  1097. int utlSortBossInfo()
  1098. {
  1099. BOSSINFO boss;
  1100. for(int i=0; i<bossinfo.GetSize(); i++)
  1101. {
  1102. for(int j=i+1; j<bossinfo.GetSize(); j++)
  1103. {
  1104. CTimeSpan ts = bossinfo[i].tmBossTime - bossinfo[j].tmBossTime;
  1105. if(ts.GetTotalSeconds() > 0)
  1106. {
  1107. boss = bossinfo[i];
  1108. bossinfo[i] = bossinfo[j];
  1109. bossinfo[j] = boss;
  1110. }
  1111. }
  1112. }
  1113. return(0);
  1114. }
  1115. int utlGMAppeared(PLAYER player)
  1116. {
  1117. CString strOutput;
  1118. strOutput.Format("发现GM帐号[%08X:%s]", player.dwId, player.cName);
  1119. sendChatParty(strOutput);
  1120. injectAdminMessage(strOutput);
  1121. bAiEnabled = false;
  1122. return(0);
  1123. }
  1124. int utlGMDisappeared(PLAYER player)
  1125. {
  1126. CString strOutput;
  1127. strOutput.Format("GM帐号[%08X:%s]消失了", player.dwId, player.cName);
  1128. sendChatParty(strOutput);
  1129. injectAdminMessage(strOutput);
  1130. bAiEnabled = true;
  1131. return(0);
  1132. }
  1133. int utlShowAttackResult(DWORD nMonIndex)
  1134. {
  1135. int nIndex;
  1136. CString strOutput;
  1137. DWORD dwTick;
  1138. int i;
  1139. double dSecond;
  1140. nIndex = damages.FindDamage(dwAccountId, monsters[nMonIndex].dwId);
  1141. if(nIndex != -1)
  1142. {
  1143. dwTick = GetTickCount() - damages[nIndex].dwStart;
  1144. dSecond = (double)dwTick/1000;
  1145. strOutput.Format(_T("攻击 %s : 持续时间: %2.2f秒,DMG: %d"), utlFindTarget(monsters[nMonIndex].dwId), dSecond, damages[nIndex].dwDamage);
  1146. injectMessage(strOutput);
  1147. for(i=0; i<MAX_SKILL; i++)
  1148. {
  1149. if( damages[nIndex].dwHits[i] == 0 &&
  1150. damages[nIndex].dwDamage2[i] == 0 &&
  1151. damages[nIndex].dwMiss[i] == 0)
  1152. continue;
  1153. strOutput.Format(_T(" -- %s %dHits %dMiss %dDMG [MAX:%d MIN:%d %2.2fHits/s %2.2fDMG/s]"),
  1154. mapSkill.FindValue(i, eSkillAlias),
  1155. damages[nIndex].dwHits[i],
  1156. damages[nIndex].dwMiss[i],
  1157. damages[nIndex].dwDamage2[i],
  1158. damages[nIndex].dwDamageMax[i],
  1159. damages[nIndex].dwDamageMin[i],
  1160. dSecond < 0.01 ? 0 : (double)damages[nIndex].dwHits[i]/dSecond,
  1161. dSecond < 0.01 ? 0 : (double)damages[nIndex].dwDamage2[i]/dSecond
  1162. );
  1163. injectMessage(strOutput);
  1164. }
  1165. }
  1166. return(0);
  1167. }
  1168. int utlParseInventory(char *pBuffer, INVENTORY* pInv, DWORD dwParseId)
  1169. {
  1170. switch(dwParseId)
  1171. {
  1172. case 0x00A0: //00a0 <index>.w <amount>.w <item ID>.w <identify flag>.B <attribute?>.B <refine>.B <card>.4w <equip type>.w <type>.B <fail>.B
  1173. pInv->dwIndex = *((WORD*)(pBuffer));
  1174. pInv->wAmount = *((WORD*)(pBuffer+2));
  1175. pInv->dwId = *((WORD*)(pBuffer+4));
  1176. pInv->bIdentified = *(pBuffer+6);
  1177. pInv->byAttrib = *(pBuffer+7);
  1178. pInv->byRefine = *(pBuffer+8);
  1179. pInv->wCard[0] = *((WORD*)(pBuffer+9));
  1180. if(pInv->wCard[0] == 0x00FF)
  1181. {
  1182. pInv->byElement = *(pBuffer+11);
  1183. pInv->byStar = *(pBuffer+12) / 5;
  1184. }
  1185. else
  1186. {
  1187. pInv->wCard[1] = *((WORD*)(pBuffer+11));
  1188. pInv->wCard[2] = *((WORD*)(pBuffer+13));
  1189. pInv->wCard[3] = *((WORD*)(pBuffer+15));
  1190. }
  1191. pInv->wEquipType = *((WORD*)(pBuffer+17));
  1192. pInv->wType = *(pBuffer+19);
  1193. break;
  1194. case 0x00A4:
  1195. case 0x0122:
  1196. pInv->dwIndex = *((WORD*)(pBuffer));
  1197. pInv->dwId = *((WORD*)(pBuffer+2));
  1198. pInv->wAmount = 1;
  1199. pInv->wType = *(pBuffer+4);
  1200. pInv->bIdentified = *(pBuffer+5);
  1201. pInv->wEquipType = *((WORD*)(pBuffer+6));
  1202. pInv->wEquipped = *((WORD*)(pBuffer+8));
  1203. pInv->byRefine = *(pBuffer+11);
  1204. pInv->wCard[0] = *((WORD*)(pBuffer+12));
  1205. if(pInv->wCard[0] == 0x00FF)
  1206. {
  1207. pInv->byElement = *(pBuffer+14);
  1208. pInv->byStar = *(pBuffer+15) / 5;
  1209. }
  1210. else
  1211. {
  1212. pInv->wCard[1] = *((WORD*)(pBuffer+14));
  1213. pInv->wCard[2] = *((WORD*)(pBuffer+16));
  1214. pInv->wCard[3] = *((WORD*)(pBuffer+18));
  1215. }
  1216. break;
  1217. }
  1218. return(0);
  1219. }
  1220. CString utlGetInventoryName(INVENTORY *pInv)
  1221. {
  1222. CString strRtn, strTemp;
  1223. strRtn.Empty();
  1224. if(pInv->wEquipType)
  1225. {
  1226. if(pInv->byRefine)
  1227. {
  1228. strRtn.Format(_T("+%d"), pInv->byRefine);
  1229. }
  1230. strRtn += mapItem.FindValue(pInv->dwId, eItemName);
  1231. if(pInv->wCard[0] == 0x00FF)
  1232. {
  1233. if(pInv->byStar != 0)
  1234. {
  1235. strTemp.Format(_T("[%d级强悍]"), pInv->byStar);
  1236. strRtn += strTemp;
  1237. }
  1238. if(pInv->byElement != 0)
  1239. {
  1240. strTemp.Format(_T("[%s属性]"), mapElements.FindValue(pInv->byElement));
  1241. strRtn += strTemp;
  1242. }
  1243. }
  1244. else
  1245. {
  1246. CString strTemp1[4];
  1247. int nTemp1[4];
  1248. for(int i=0; i<4; i++)
  1249. {
  1250. nTemp1[i] = 0;
  1251. if(pInv->wCard[i] != 0)
  1252. {
  1253. strTemp1[i].Format(_T("%s"), mapItem.FindValue(pInv->wCard[i], eItemName));
  1254. nTemp1[i] = 1;
  1255. }
  1256. }
  1257. for(i=3; i>0; i--)
  1258. {
  1259. if(!strTemp1[1].IsEmpty() && strTemp1[i] == strTemp1[i-1])
  1260. {
  1261. nTemp1[i-1] += nTemp1[i];
  1262. strTemp1[i].Empty();
  1263. nTemp1[i] = 0;
  1264. }
  1265. }
  1266. for(i=0; i<4; i++)
  1267. {
  1268. if(nTemp1[i] == 0 || strTemp1[i].IsEmpty())
  1269. continue;
  1270. if(nTemp1[i] == 1)
  1271. {
  1272. strTemp.Format(_T("[%s]"), strTemp1[i]);
  1273. }
  1274. else
  1275. {
  1276. strTemp.Format(_T("[%d倍%s]"), nTemp1[i], strTemp1[i]);
  1277. }
  1278. strRtn += strTemp;
  1279. }
  1280. }
  1281. }
  1282. else
  1283. {
  1284. strRtn = mapItem.FindValue(pInv->dwId, eItemName);
  1285. }
  1286. return(strRtn);
  1287. }
  1288. BOOL utlPlayerInParty(DWORD dwId)
  1289. {
  1290. // return(false);
  1291. return(partners.FindId(dwId) != -1);
  1292. }
  1293. BOOL utlIsMvpMonster(MONSTER monster)
  1294. {
  1295. CString strId, strName;
  1296. BOOL bFound = false;
  1297. mapMvpMonster.FindValue(monster.wType, 0, &bFound);
  1298. if(!bFound)
  1299. {
  1300. POSITION pos = mapMvpMonster.GetStartPosition();
  1301. while (pos)
  1302. {
  1303. mapMvpMonster.GetNextAssoc(pos, strId, strName);
  1304. if (strName == monster.cName)
  1305. {
  1306. bFound = true;
  1307. break;
  1308. }
  1309. }
  1310. }
  1311. return(bFound);
  1312. }
  1313. int sendUnequip(int nIndex)
  1314. {
  1315. char buffer[4];
  1316. *(WORD*)buffer = 0x00AB;
  1317. *(WORD*)(buffer+2) = (WORD)nIndex;
  1318. parseSendData(buffer, 4, true);
  1319. return(0);
  1320. }
  1321. int sendEquip(int nIndex, WORD wType)
  1322. {
  1323. char buffer[6];
  1324. *(WORD*)buffer = 0x00A9;
  1325. *(WORD*)(buffer+2) = (WORD)nIndex;
  1326. *(WORD*)(buffer+4) = (WORD)wType;
  1327. parseSendData(buffer, 6, true);
  1328. return(0);
  1329. }
  1330. int utlPopupBossWarning()
  1331. {
  1332. CTimeSpan timespan;
  1333. CTime tmNow;
  1334. long dwSecond;
  1335. tmNow = CTime::GetCurrentTime();
  1336. tmNow -= CTimeSpan( 0, 1, 0, 0 ); // 1 hour exactly
  1337. CString strTemp;
  1338. for(int i=0; i<bossinfo.GetSize(); i++)
  1339. {
  1340. timespan = bossinfo[i].tmBossTime - tmNow;
  1341. dwSecond = timespan.GetTotalSeconds();
  1342. if(dwSecond > 10*60 || dwSecond < -60)
  1343. continue;
  1344. if(dwSecond < 10*60 && dwSecond >= 5*60 && !bossinfo[i].bWaring[0])
  1345. {
  1346. strTemp.Format(_T("%s还有%d分%d秒重生"), bossinfo[i].strBossName, dwSecond / 60, dwSecond%60);
  1347. sendChatParty(strTemp);
  1348. injectAdminMessage(strTemp);
  1349. bossinfo[i].bWaring[0] = true;
  1350. }
  1351. if(dwSecond < 5*60 && dwSecond >= 3*60 && !bossinfo[i].bWaring[1])
  1352. {
  1353. strTemp.Format(_T("%s还有%d分%d秒重生"), bossinfo[i].strBossName, dwSecond / 60, dwSecond%60);
  1354. sendChatParty(strTemp);
  1355. injectAdminMessage(strTemp);
  1356. bossinfo[i].bWaring[0] = true;
  1357. bossinfo[i].bWaring[1] = true;
  1358. }
  1359. if(dwSecond < 3*60 && dwSecond >= 30 && !bossinfo[i].bWaring[2])
  1360. {
  1361. strTemp.Format(_T("%s还有%d分%d秒重生"), bossinfo[i].strBossName, dwSecond / 60, dwSecond%60);
  1362. sendChatParty(strTemp);
  1363. injectAdminMessage(strTemp);
  1364. bossinfo[i].bWaring[0] = true;
  1365. bossinfo[i].bWaring[1] = true;
  1366. bossinfo[i].bWaring[2] = true;
  1367. }
  1368. if(dwSecond < 30 && dwSecond >= 1 && !bossinfo[i].bWaring[3])
  1369. {
  1370. strTemp.Format(_T("%s还有%d秒重生"), bossinfo[i].strBossName, dwSecond);
  1371. sendChatParty(strTemp);
  1372. injectAdminMessage(strTemp);
  1373. bossinfo[i].bWaring[0] = true;
  1374. bossinfo[i].bWaring[1] = true;
  1375. bossinfo[i].bWaring[2] = true;
  1376. bossinfo[i].bWaring[3] = true;
  1377. }
  1378. if(dwSecond < 1 && !bossinfo[i].bWaring[4])
  1379. {
  1380. strTemp.Format(_T("%s重生了"), bossinfo[i].strBossName);
  1381. sendChatParty(strTemp);
  1382. injectAdminMessage(strTemp);
  1383. bossinfo[i].bWaring[0] = true;
  1384. bossinfo[i].bWaring[1] = true;
  1385. bossinfo[i].bWaring[2] = true;
  1386. bossinfo[i].bWaring[3] = true;
  1387. bossinfo[i].bWaring[4] = true;
  1388. }
  1389. }
  1390. return(0);
  1391. }
  1392. int utlLoadOption(OPTION& option)
  1393. {
  1394. char buffer[1024];
  1395. DWORD dwRtn;
  1396. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_TESTSVR, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1397. if(buffer[0] != 0)
  1398. option.bTestServer = atoi(buffer);
  1399. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_PARTYCHAT, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1400. if(buffer[0] != 0)
  1401. option.bUsePartyChat = atoi(buffer);
  1402. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_AUTOPICKUP, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1403. if(buffer[0] != 0)
  1404. option.bAutoPickup = atoi(buffer);
  1405. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_BOSSINFO, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1406. if(buffer[0] != 0)
  1407. option.bBossInfo = atoi(buffer);
  1408. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_MOVEPICKUP, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1409. if(buffer[0] != 0)
  1410. option.bMovePickup = atoi(buffer);
  1411. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_LAUNCHER, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1412. if(buffer[0] != 0)
  1413. option.strLauncher = buffer;
  1414. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_LAUNCHERPAPRAM, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1415. if(buffer[0] != 0)
  1416. option.strLaunchParam = buffer;
  1417. for(int i=0; i<10; i++)
  1418. {
  1419. CString strProfile;
  1420. strProfile.Format(_T("%s%d"), ROA_INI2_OPT_EMOTION, i);
  1421. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, strProfile, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1422. if(buffer[0] != 0)
  1423. emotions[i] = buffer;
  1424. }
  1425. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_AUTOCONT, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1426. if(buffer[0] != 0)
  1427. option.bNpcTalkContinue = atoi(buffer);
  1428. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_WELCOMEDELAY, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1429. if(buffer[0] != 0)
  1430. option.nWelcomeDelay = atoi(buffer);
  1431. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_SEARCHDELAY, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1432. if(buffer[0] != 0)
  1433. option.nAutoSearchDelay = atoi(buffer);
  1434. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_PICKUPDISTANCE, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1435. if(buffer[0] != 0)
  1436. option.nPickupDistance = atoi(buffer);
  1437. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_ATTACKPERS, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1438. if(buffer[0] != 0)
  1439. option.nAttackPerSecond = atoi(buffer);
  1440. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_HPITEMS, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1441. if(buffer[0] != 0)
  1442. option.strHPRecoverItems = buffer;
  1443. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_SPITEMS, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1444. if(buffer[0] != 0)
  1445. option.strSPRecoverItems = buffer;
  1446. dwRtn = GetPrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_ITEMUSEINT, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1447. if(buffer[0] != 0)
  1448. option.nItemUseInterval = atoi(buffer);
  1449. return(0);
  1450. }
  1451. int utlSaveOption(OPTION option)
  1452. {
  1453. CString strProfile;
  1454. strProfile.Format(_T("%d"), option.bTestServer);
  1455. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_TESTSVR, strProfile, ROA_INI2_FILENAME);
  1456. strProfile.Format(_T("%d"), option.bUsePartyChat);
  1457. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_PARTYCHAT, strProfile, ROA_INI2_FILENAME);
  1458. strProfile.Format(_T("%d"), option.bAutoPickup);
  1459. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_AUTOPICKUP, strProfile, ROA_INI2_FILENAME);
  1460. strProfile.Format(_T("%d"), option.bBossInfo);
  1461. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_BOSSINFO, strProfile, ROA_INI2_FILENAME);
  1462. strProfile.Format(_T("%d"), option.bMovePickup);
  1463. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_MOVEPICKUP, strProfile, ROA_INI2_FILENAME);
  1464. strProfile.Format(_T("%s"), option.strLauncher);
  1465. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_LAUNCHER, strProfile, ROA_INI2_FILENAME);
  1466. strProfile.Format(_T("%s"), option.strLaunchParam);
  1467. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_LAUNCHERPAPRAM, strProfile, ROA_INI2_FILENAME);
  1468. for(int i=0; i<10; i++)
  1469. {
  1470. strProfile.Format(_T("%s%d"), ROA_INI2_OPT_EMOTION, i);
  1471. WritePrivateProfileString(ROA_INI2_OPTION, strProfile, emotions[i], ROA_INI2_FILENAME);
  1472. }
  1473. strProfile.Format(_T("%d"), option.bNpcTalkContinue);
  1474. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_AUTOCONT, strProfile, ROA_INI2_FILENAME);
  1475. strProfile.Format(_T("%d"), option.nWelcomeDelay);
  1476. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_WELCOMEDELAY, strProfile, ROA_INI2_FILENAME);
  1477. strProfile.Format(_T("%d"), option.nAutoSearchDelay);
  1478. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_SEARCHDELAY, strProfile, ROA_INI2_FILENAME);
  1479. strProfile.Format(_T("%d"), option.nPickupDistance);
  1480. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_PICKUPDISTANCE, strProfile, ROA_INI2_FILENAME);
  1481. strProfile.Format(_T("%d"), option.nAttackPerSecond);
  1482. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_ATTACKPERS, strProfile, ROA_INI2_FILENAME);
  1483. strProfile.Format(_T("%s"), option.strHPRecoverItems);
  1484. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_HPITEMS, strProfile, ROA_INI2_FILENAME);
  1485. strProfile.Format(_T("%s"), option.strSPRecoverItems);
  1486. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_SPITEMS, strProfile, ROA_INI2_FILENAME);
  1487. strProfile.Format(_T("%d"), option.nItemUseInterval);
  1488. WritePrivateProfileString(ROA_INI2_OPTION, ROA_INI2_OPT_ITEMUSEINT, strProfile, ROA_INI2_FILENAME);
  1489. return(0);
  1490. }
  1491. void utlWriteUserProfile()
  1492. {
  1493. CString strProfile;
  1494. CString strName, strTemp;
  1495. strName = utlProcessUserName(you.cName);
  1496. strProfile = settingcmn.GetProfileString();
  1497. WritePrivateProfileString(strName, ROA_INI2_SETTING_CMN, strProfile, ROA_INI2_FILENAME);
  1498. strProfile = settingmvp.GetProfileString();
  1499. WritePrivateProfileString(strName, ROA_INI2_SETTING_MVP, strProfile, ROA_INI2_FILENAME);
  1500. strProfile.Format(_T("%d"), userfuncs[0]);
  1501. for(int i=1; i<12; i++)
  1502. {
  1503. strTemp.Format(_T(",%d"), userfuncs[i]);
  1504. strProfile += strTemp;
  1505. }
  1506. WritePrivateProfileString(strName, ROA_INI2_SETTING_KEY, strProfile, ROA_INI2_FILENAME);
  1507. return;
  1508. }
  1509. CString utlProcessUserName(LPCTSTR lpszName)
  1510. {
  1511. CString strRet, strName;
  1512. BOOL bWide = false;
  1513. if(0 == strlen(lpszName))
  1514. strName = _T("[未知人物]");
  1515. else
  1516. strName = lpszName;
  1517. strName += _T("_V3");
  1518. strRet.Empty();
  1519. for(int i=0; i<(int)strlen(strName); i++)
  1520. {
  1521. if(bWide)
  1522. {
  1523. strRet += strName[i];
  1524. bWide = false;
  1525. continue;
  1526. }
  1527. if(strName[i] & 0x80)
  1528. {
  1529. bWide = true;
  1530. strRet += strName[i];
  1531. continue;
  1532. }
  1533. if(strName[i] != _T('[') && strName[i] != _T(']') && strName[i] >= 32)
  1534. {
  1535. strRet += strName[i];
  1536. }
  1537. }
  1538. return(strRet);
  1539. }
  1540. void utlReadUserProfile()
  1541. {
  1542. char buffer[1024];
  1543. DWORD dwRtn;
  1544. CString strProfile;
  1545. CString strName, strTemp;
  1546. bProfileLoaded = false;
  1547. strName = utlProcessUserName(you.cName);
  1548. dwRtn = GetPrivateProfileString(strName, ROA_INI2_SETTING_CMN, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1549. if(dwRtn > 0)
  1550. {
  1551. strProfile = buffer;
  1552. settingcmn.ParseProfileString(strProfile);
  1553. bProfileLoaded = true;
  1554. }
  1555. dwRtn = GetPrivateProfileString(strName, ROA_INI2_SETTING_MVP, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1556. if(dwRtn > 0)
  1557. {
  1558. strProfile = buffer;
  1559. settingmvp.ParseProfileString(strProfile);
  1560. bProfileLoaded = true;
  1561. }
  1562. dwRtn = GetPrivateProfileString(strName, ROA_INI2_SETTING_KEY, _T(""), buffer, 1024, ROA_INI2_FILENAME);
  1563. if(dwRtn > 0)
  1564. {
  1565. strProfile = buffer;
  1566. for(int i=0; i<12; i++)
  1567. {
  1568. strTemp = utlParseString(strProfile);
  1569. userfuncs[i] = (USERFUNCTION)atoi(strTemp);
  1570. }
  1571. bProfileLoaded = true;
  1572. }
  1573. return;
  1574. }
  1575. int utlAddComboHPItem(CComboBox *pCombo)
  1576. {
  1577. for(int i=0; i<HPITEMS.GetSize(); i++)
  1578. {
  1579. pCombo->AddString(HPITEMS[i]);
  1580. }
  1581. return(0);
  1582. }
  1583. int utlAddComboSPItem(CComboBox *pCombo)
  1584. {
  1585. for(int i=0; i<SPITEMS.GetSize(); i++)
  1586. {
  1587. pCombo->AddString(SPITEMS[i]);
  1588. }
  1589. return(0);
  1590. }
  1591. int utlAddComboAttackSkill(CComboBox *pCombo)
  1592. {
  1593. for(int i=0; i<ATTACKSKILLNUM; i++)
  1594. {
  1595. pCombo->AddString(ATTACKSKILL[i]);
  1596. }
  1597. return(0);
  1598. }
  1599. int utlAddComboProtectState(CComboBox *pCombo)
  1600. {
  1601. for(int i=0; i<PROTECTSTATENUM; i++)
  1602. {
  1603. pCombo->AddString(PROTECTSTATE[i]);
  1604. }
  1605. return(0);
  1606. }
  1607. int utlAddComboProtectSkill(CComboBox *pCombo)
  1608. {
  1609. for(int i=0; i<PROTECTSKILLNUM; i++)
  1610. {
  1611. pCombo->AddString(PROTECTSKILL[i]);
  1612. }
  1613. return(0);
  1614. }
  1615. BOOL CheckForRegionAttack(CString& strSkillName, int& nMonIndex)
  1616. {
  1617. CDWordArray dwTargetArray, dwDamageArray;
  1618. BOOL bRet = false;
  1619. if(damages.FindDamageFrom(dwAccountId, dwTargetArray, dwDamageArray))
  1620. {
  1621. if(dwTargetArray.GetSize() > settingmvp.nRegionAtkNum)
  1622. {
  1623. bRet = true;
  1624. int nMonsters = dwTargetArray.GetSize();
  1625. int x=0, y=0, nCount = 0;
  1626. POINT pntCenter;
  1627. double dDist = 999;
  1628. int nIndex;
  1629. for(int i=0; i<nMonsters; i++)
  1630. {
  1631. nIndex = monsters.FindId(dwTargetArray[i]);
  1632. if(nIndex != -1)
  1633. {
  1634. x += monsters[nIndex].pntTo.x;
  1635. y += monsters[nIndex].pntTo.y;
  1636. nCount++;
  1637. }
  1638. }
  1639. pntCenter.x = (int)((double)x/nCount);
  1640. pntCenter.y = (int)((double)y/nCount);
  1641. for(i=0; i<nMonsters; i++)
  1642. {
  1643. nIndex = monsters.FindId(dwTargetArray[i]);
  1644. if(nIndex != -1)
  1645. {
  1646. if(utlDistanceFrom(pntCenter, monsters[nIndex].pntPos) < dDist)
  1647. {
  1648. dDist = utlDistanceFrom(pntCenter, monsters[nIndex].pntPos);
  1649. strSkillName = settingmvp.strRegionAtkSkill;
  1650. nMonIndex = nIndex;
  1651. }
  1652. }
  1653. }
  1654. }
  1655. }
  1656. return(bRet);
  1657. }
  1658. int utlChangeMode(BYTE eMode, DWORD dwId)
  1659. {
  1660. CString strOutput;
  1661. BYTE eModeOld = mode;
  1662. if(mode != eMode)
  1663. {
  1664. mode = eMode;
  1665. switch(mode)
  1666. {
  1667. case eModeNormal:
  1668. dwMvpId = 0;
  1669. break;
  1670. case eModeMvp:
  1671. dwMvpId = dwId;
  1672. if(bAutoSearch)
  1673. {
  1674. ufAutoSearchMvp(false);
  1675. }
  1676. break;
  1677. }
  1678. }
  1679. if(mode != eModeNormal && !utlCheckForWanzi(you.cGuild))
  1680. {
  1681. for(int i=0; i<players.GetSize(); i++)
  1682. {
  1683. if(utlCheckForWanzi(players[i].cGuild) && !utlPlayerInParty(players[i].dwId))
  1684. {
  1685. mode = eModeNormal;
  1686. break;
  1687. }
  1688. }
  1689. }
  1690. if(eModeOld != mode)
  1691. {
  1692. switch(mode)
  1693. {
  1694. case eModeNormal:
  1695. strOutput = _T("进入正常模式");
  1696. break;
  1697. case eModeMvp:
  1698. strOutput = _T("进入MVP模式");
  1699. break;
  1700. }
  1701. injectAdminMessage(strOutput);
  1702. }
  1703. return(0);
  1704. }
  1705. int sendTalkContinue(DWORD dwNpcId)
  1706. {
  1707. char buffer[6];
  1708. *(WORD*)(buffer+0) = 0x00B9;
  1709. *(DWORD*)(buffer+2) = dwNpcId;
  1710. parseSendData(buffer, 6, true);
  1711. return(0);
  1712. }
  1713. int sendTalkCancel(DWORD dwNpcId)
  1714. {
  1715. char buffer[6];
  1716. *(WORD*)(buffer+0) = 0x0146;
  1717. *(DWORD*)(buffer+2) = dwNpcId;
  1718. parseSendData(buffer, 6, true);
  1719. return(0);
  1720. }
  1721. void utlParseHpSpItems()
  1722. {
  1723. CString strTemp;
  1724. int nIndex = -1;
  1725. CString strHpItems, strSpItems;
  1726. HPITEMS.RemoveAll();
  1727. SPITEMS.RemoveAll();
  1728. strHpItems = option.strHPRecoverItems;
  1729. strSpItems = option.strSPRecoverItems;
  1730. while(-1 != (nIndex = strHpItems.Find(_T("|"))))
  1731. {
  1732. strTemp = strHpItems.Left(nIndex);
  1733. if(!strTemp.IsEmpty())
  1734. HPITEMS.Add(strTemp);
  1735. strHpItems = strHpItems.Mid(nIndex+1);
  1736. }
  1737. if(!strHpItems.IsEmpty())
  1738. HPITEMS.Add(strHpItems);
  1739. while(-1 != (nIndex = strSpItems.Find(_T("|"))))
  1740. {
  1741. strTemp = strSpItems.Left(nIndex);
  1742. if(!strTemp.IsEmpty())
  1743. SPITEMS.Add(strTemp);
  1744. strSpItems = strSpItems.Mid(nIndex+1);
  1745. }
  1746. if(!strSpItems.IsEmpty())
  1747. SPITEMS.Add(strSpItems);
  1748. return;
  1749. }
  1750. DWORD utlGetFileSize(LPCTSTR lpszFilename)
  1751. {
  1752. HANDLE hFile;
  1753. DWORD dwRet = 0;
  1754. hFile = CreateFile(lpszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
  1755. if(hFile != INVALID_HANDLE_VALUE)
  1756. {
  1757. dwRet = GetFileSize(hFile, NULL);
  1758. CloseHandle(hFile);
  1759. }
  1760. return(dwRet);
  1761. }
  1762. int utlGetAttackPerSecond()
  1763. {
  1764. int nRet = option.nAttackPerSecond;
  1765. if(option.bTestServer)
  1766. {
  1767. if(nRet >= 10)
  1768. nRet = 10;
  1769. }
  1770. else
  1771. {
  1772. if(nRet >= 3)
  1773. nRet = 3;
  1774. }
  1775. return(nRet);
  1776. }