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

模拟服务器

开发平台:

C/C++

  1. #include "KCore.h"
  2. #include <math.h>
  3. #include "KNpc.h"
  4. #include "KSubWorld.h"
  5. #include "KRegion.h"
  6. #include "GameDataDef.h"
  7. #include "KNpcSet.h"
  8. #include "KPlayer.h"
  9. #ifndef _SERVER
  10. #include "CoreShell.h"
  11. #include "SceneKScenePlaceC.h"
  12. #include "../../Represent/iRepresent/iRepresentshell.h"
  13. #include "KOption.h"
  14. #ifndef TOOLVERSION
  15. #include "../../Headers/IClient.h"
  16. #endif
  17. #endif
  18. #include "Scene/SceneDataDef.h"
  19. #include "KMath.h"
  20. //#define ENCHANT_SETTING_PATH "settings\npc"
  21. //#define ENCHANT_NORMAL_FILE "normalunique.txt"
  22. //#define ENCHANT_SPECIAL_FILE "speicalunique.txt"
  23. KNpcSet NpcSet;
  24. KNpcSet::KNpcSet()
  25. {
  26. m_dwIDCreator = 1000;
  27. }
  28. // 黄金怪物设定文件的初始化没有放在这里,直接放在 core 的初始化里面
  29. void KNpcSet::Init()
  30. {
  31.     // Add by Freeway Chen in 2003.6.29    
  32.     GenRelationTable();
  33. m_FreeIdx.Init(MAX_NPC);
  34. m_UseIdx.Init(MAX_NPC);
  35. // 开始时所有的数组元素都为空
  36. for (int i = MAX_NPC - 1; i > 0; i--)
  37. {
  38. m_FreeIdx.Insert(i);
  39. Npc[i].m_Node.m_nIndex = i;
  40. #ifdef _SERVER
  41. Npc[i].m_cDeathCalcExp.Init(i);
  42. #endif
  43. Npc[i].m_cGold.Init(i);
  44. }
  45. LoadPlayerBaseValue(PLAYER_BASE_VALUE);
  46. #ifdef _SERVER
  47. KIniFile cPKIni;
  48. // g_SetFilePath("\");
  49. if (cPKIni.Load(PLAYER_PK_RATE_FILE))
  50. {
  51. cPKIni.GetInteger("PK", "rate", 20, &m_nPKDamageRate);
  52. cPKIni.GetInteger("PK", "FactionPKFaction", 1, &m_nFactionPKFactionAddPKValue);
  53. cPKIni.GetInteger("PK", "KillerPKFaction", 1, &m_nKillerPKFactionAddPKValue);
  54. cPKIni.GetInteger("PK", "EnmityPK", 2, &m_nEnmityAddPKValue);
  55. cPKIni.GetInteger("PK", "BeKilled", -1, &m_nBeKilledAddPKValue);
  56. cPKIni.GetInteger("PK", "LevelDistance", 25, &m_nLevelDistance);
  57. }
  58. else
  59. {
  60. m_nPKDamageRate = 20;
  61. m_nFactionPKFactionAddPKValue = 1;
  62. m_nKillerPKFactionAddPKValue = 1;
  63. m_nEnmityAddPKValue = 2;
  64. m_nBeKilledAddPKValue = -1;
  65. m_nLevelDistance = 25;
  66. }
  67. #endif
  68. #ifndef _SERVER
  69. m_nShowPateFlag = PATE_CHAT;
  70. ZeroMemory(m_RequestNpc, sizeof(m_RequestNpc));
  71. m_RequestFreeIdx.Init(MAX_NPC_REQUEST);
  72. m_RequestUseIdx.Init(MAX_NPC_REQUEST);
  73. for (i = MAX_NPC_REQUEST - 1; i > 0; i--)
  74. {
  75. m_RequestFreeIdx.Insert(i);
  76. }
  77. #endif
  78. }
  79. void KNpcSet::LoadPlayerBaseValue(LPSTR szFile)
  80. {
  81. KIniFile File;
  82. File.Load(szFile);
  83. File.GetInteger("Common", "HurtFrame", 12, &m_cPlayerBaseValue.nHurtFrame);
  84. File.GetInteger("Common", "RunSpeed", 10, &m_cPlayerBaseValue.nRunSpeed);
  85. File.GetInteger("Common", "WalkSpeed", 5, &m_cPlayerBaseValue.nWalkSpeed);
  86. File.GetInteger("Common", "AttackFrame", 20, &m_cPlayerBaseValue.nAttackFrame);
  87. #ifndef _SERVER
  88. File.GetInteger("Male", "WalkFrame", 15, &m_cPlayerBaseValue.nWalkFrame[0]);
  89. File.GetInteger("Female", "WalkFrame", 15, &m_cPlayerBaseValue.nWalkFrame[1]);
  90. File.GetInteger("Male", "RunFrame", 15, &m_cPlayerBaseValue.nRunFrame[0]);
  91. File.GetInteger("Female", "RunFrame", 15, &m_cPlayerBaseValue.nRunFrame[1]);
  92. File.GetInteger("Male", "StandFrame", 15, &m_cPlayerBaseValue.nStandFrame[0]);
  93. File.GetInteger("Female", "StandFrame", 15, &m_cPlayerBaseValue.nStandFrame[1]);
  94. #endif
  95. File.Clear();
  96. }
  97. BOOL KNpcSet::IsNpcExist(int nIdx, DWORD dwId)
  98. {
  99. if (Npc[nIdx].m_dwID == dwId)
  100. return TRUE;
  101. else
  102. return FALSE;
  103. }
  104. // Add by Freeway Chen in 2003.6.29
  105. NPC_RELATION KNpcSet::GenOneRelation(NPCKIND Kind1, NPCKIND Kind2, NPCCAMP Camp1, NPCCAMP Camp2)
  106. {
  107. // 路人NPC没有战斗关系
  108. if (Kind1 == kind_dialoger || Kind2 == kind_dialoger)
  109. return relation_dialog;
  110. // 路人阵营没有战斗关系
  111. if (Camp1 == camp_event || Camp2 == camp_event)
  112. return relation_none;
  113. // 新手和动物还是战斗关系
  114. if ((Camp1 == camp_begin && Camp2 == camp_animal)
  115. ||(Camp1 == camp_animal && Camp2 == camp_begin))
  116. return relation_enemy;
  117. // 只要有一个新手,就不存在战斗关系(是同盟关系,大家帮新手)
  118. if (Camp1 == camp_begin || Camp2 == camp_begin)
  119. return relation_ally;
  120.     // 两个都是玩家
  121. if (Kind1 == kind_player && Kind2 == kind_player)
  122. {
  123. // 只要有一个玩家开了PK,就一定存在战斗关系
  124. if (Camp1 == camp_free || Camp2 == camp_free)
  125. {
  126. return relation_enemy;
  127. }
  128. }
  129. // 同阵营为伙伴关系
  130. if (Camp1 == Camp2)
  131. return relation_ally;
  132. // 其他情况为战斗关系
  133. return relation_enemy;
  134. }
  135. // Add by Freeway Chen in 2003.7.14
  136. int KNpcSet::GenRelationTable()
  137. {
  138.     int nKind1 = 0;
  139.     int nKind2 = 0;
  140.     int nCamp1 = 0;
  141.     int nCamp2 = 0;
  142.     for (nKind1 = 0; nKind1 < kind_num; nKind1++)
  143.     {
  144.         for (nKind2 = 0; nKind2 < kind_num; nKind2++)
  145.         {
  146.             for (nCamp1 = 0; nCamp1 < camp_num; nCamp1++)
  147.             {
  148.                 for (nCamp2 = 0; nCamp2 < camp_num; nCamp2++)
  149.                 {
  150.                     m_RelationTable[nKind1][nKind2][nCamp1][nCamp2] = GenOneRelation(
  151.                         (NPCKIND)nKind1, 
  152.                         (NPCKIND)nKind2, 
  153.                         (NPCCAMP)nCamp1, 
  154.                         (NPCCAMP)nCamp2
  155.                     );
  156.                 }
  157.             }
  158.         }
  159.     }
  160.     return true;
  161. }
  162. int KNpcSet::SearchID(DWORD dwID)
  163. {
  164. // int nMaxNpc = m_BinTree.GetCount();
  165. // for (int i = 0; i < MAX_NPC; i++)
  166. // {
  167. // if (Npc[i].m_dwID == dwID)
  168. // return Npc[i].m_Index;
  169. // }
  170. int nIdx = 0;
  171. while (1)
  172. {
  173. nIdx = m_UseIdx.GetNext(nIdx);
  174. if (nIdx == 0)
  175. break;
  176. if (Npc[nIdx].m_dwID == dwID)
  177. return nIdx;
  178. }
  179. return 0;
  180. }
  181. #ifndef _SERVER
  182. //---------------------------------------------------------------------------
  183. // 功能:查找某个ClientID的npc是否存在
  184. //---------------------------------------------------------------------------
  185. int KNpcSet::SearchClientID(KClientNpcID sClientID)
  186. {
  187. int nIdx = 0;
  188. while (1)
  189. {
  190. nIdx = m_UseIdx.GetNext(nIdx);
  191. if (nIdx == 0)
  192. break;
  193. if (Npc[nIdx].m_sClientNpcID.m_dwRegionID == sClientID.m_dwRegionID &&
  194. Npc[nIdx].m_sClientNpcID.m_nNo == sClientID.m_nNo)
  195. return nIdx;
  196. }
  197. return 0;
  198. }
  199. #endif
  200. int KNpcSet::SearchName(LPSTR szName)
  201. {
  202. // for (int i = 0; i < MAX_NPC; i ++)
  203. // {
  204. // if (!strcmp(Npc[i].Name, szName))
  205. // return i ;
  206. // }
  207. int nIdx = 0;
  208. while (1)
  209. {
  210. nIdx = m_UseIdx.GetNext(nIdx);
  211. if (nIdx == 0)
  212. break;
  213. if (g_StrCmp(Npc[nIdx].Name, szName))
  214. return nIdx;
  215. }
  216. return 0;
  217. }
  218. int KNpcSet::SearchNameID(DWORD dwID)
  219. {
  220. int nIdx = 0;
  221. DWORD dwNameID = 0;
  222. while(1)
  223. {
  224. nIdx = m_UseIdx.GetNext(nIdx);
  225. if (nIdx == 0)
  226. break;
  227. if (Npc[nIdx].m_Kind != kind_player)
  228. continue;
  229. dwNameID = g_FileName2Id(Npc[nIdx].Name);
  230. if (dwID == dwNameID)
  231. return nIdx;
  232. }
  233. return 0;
  234. }
  235. int KNpcSet::FindFree()
  236. {
  237. return m_FreeIdx.GetNext(0);
  238. }
  239. #ifndef _SERVER
  240. //---------------------------------------------------------------------------
  241. // 功能:添加一个客户端npc(需要设定ClientNpcID)
  242. //---------------------------------------------------------------------------
  243. int KNpcSet::AddClientNpc(int nTemplateID, int nRegionX, int nRegionY, int nMpsX, int nMpsY, int nNo)
  244. {
  245. int nNpcNo, nNpcSettingIdxInfo, nMapX, nMapY, nOffX, nOffY, nRegion;
  246. nNpcSettingIdxInfo = MAKELONG(1, nTemplateID);
  247. SubWorld[0].Mps2Map(nMpsX, nMpsY, &nRegion, &nMapX, &nMapY, &nOffX, &nOffY);
  248. if (nRegion < 0)
  249. return 0;
  250. nNpcNo = this->Add(nNpcSettingIdxInfo, 0, nRegion, nMapX, nMapY, nOffX, nOffY);
  251. if (nNpcNo > 0)
  252. {
  253. Npc[nNpcNo].m_sClientNpcID.m_dwRegionID = MAKELONG(nRegionX, nRegionY);
  254. Npc[nNpcNo].m_sClientNpcID.m_nNo = nNo;
  255. Npc[nNpcNo].m_RegionIndex = nRegion;
  256. Npc[nNpcNo].m_dwRegionID = SubWorld[0].m_Region[nRegion].m_RegionID;
  257. Npc[nNpcNo].m_bClientOnly = TRUE;
  258. Npc[nNpcNo].m_SyncSignal = SubWorld[0].m_dwCurrentTime;
  259. SubWorld[0].m_Region[nRegion].DecRef(Npc[nNpcNo].m_MapX, Npc[nNpcNo].m_MapY, obj_npc);
  260. }
  261. return nNpcNo;
  262. }
  263. #endif
  264. int KNpcSet::Add(int nSubWorld, void* pNpcInfo)
  265. {
  266. KSPNpc* pKSNpcInfo = (KSPNpc *)pNpcInfo;
  267. int nMpsX = pKSNpcInfo->nPositionX;
  268. int nMpsY = pKSNpcInfo->nPositionY;
  269. int nNpcSettingIdxInfo = MAKELONG(pKSNpcInfo->nLevel, pKSNpcInfo->nTemplateID);
  270. int nRet = Add(nNpcSettingIdxInfo, nSubWorld, nMpsX, nMpsY);
  271. if (nRet)
  272. {
  273. Npc[nRet].m_TrapScriptID = 0;
  274. g_StrCpyLen(Npc[nRet].Name, pKSNpcInfo->szName, sizeof(Npc[nRet].Name));
  275. Npc[nRet].m_Kind = pKSNpcInfo->shKind;
  276. Npc[nRet].m_Camp = pKSNpcInfo->cCamp;
  277. Npc[nRet].m_CurrentCamp = pKSNpcInfo->cCamp;
  278. Npc[nRet].m_Series = pKSNpcInfo->cSeries;
  279. // 如果是黄金怪物,备份数据
  280. if (pKSNpcInfo->bSpecialNpc)
  281. {
  282. Npc[nRet].m_cGold.SetGoldTypeAndBackData();
  283. }
  284. else
  285. {
  286. Npc[nRet].m_cGold.SetGoldType(FALSE);;
  287. }
  288. if (pKSNpcInfo->szScript[0])
  289. {
  290. if (pKSNpcInfo->szScript[0] == '.')
  291. g_StrCpyLen(Npc[nRet].ActionScript, &pKSNpcInfo->szScript[1], sizeof(Npc[nRet].ActionScript));
  292. else
  293. g_StrCpyLen(Npc[nRet].ActionScript, pKSNpcInfo->szScript, sizeof(Npc[nRet].ActionScript));
  294. // 保持小写,保证脚本对应关系
  295. g_StrLower(Npc[nRet].ActionScript);
  296. Npc[nRet].m_ActionScriptID = g_FileName2Id(Npc[nRet].ActionScript);
  297. g_DebugLog("[Script]Npc %s,%d", Npc[nRet].ActionScript, Npc[nRet].m_ActionScriptID);
  298. }
  299. else
  300. {
  301. Npc[nRet].m_ActionScriptID = 0;
  302. }
  303. }
  304. return nRet;
  305. }
  306. int KNpcSet::Add(int nNpcSettingIdxInfo, int nSubWorld, int nMpsX, int nMpsY)
  307. {
  308. int nRegion, nMapX, nMapY, nOffX, nOffY;
  309. if (nSubWorld < 0 || nSubWorld >= MAX_SUBWORLD)
  310. return 0;
  311. SubWorld[nSubWorld].Mps2Map(nMpsX, nMpsY, &nRegion, &nMapX, &nMapY, &nOffX, &nOffY);
  312. if (nRegion < 0)
  313. return 0;
  314. return Add(nNpcSettingIdxInfo, nSubWorld, nRegion, nMapX, nMapY, nOffX, nOffY);
  315. }
  316. int KNpcSet::Add(int nNpcSettingIdxInfo, int nSubWorld, int nRegion, int nMapX, int nMapY, int nOffX /* = 0 */, int nOffY /* = 0 */)
  317. {
  318. int i = FindFree();
  319. if (i == 0)
  320. return 0;
  321. #ifndef _SERVER
  322. Npc[i].m_sClientNpcID.m_dwRegionID = 0;
  323. Npc[i].m_sClientNpcID.m_nNo = -1;
  324. Npc[i].Remove();
  325. Npc[i].ClearBlood();
  326. #endif
  327. int nNpcSettingIdx = (short)HIWORD(nNpcSettingIdxInfo);// >> 7; //除于128
  328. int nLevel = LOWORD(nNpcSettingIdxInfo);// & 0x7f; 
  329. Npc[i].m_Index = i;
  330. Npc[i].m_SkillList.m_nNpcIndex = i;
  331. Npc[i].Load(nNpcSettingIdx, nLevel);
  332. Npc[i].m_SubWorldIndex = nSubWorld;
  333. Npc[i].m_RegionIndex = nRegion;
  334. #ifndef _SERVER
  335. if (nRegion >= 0 && nRegion < 9)
  336. Npc[i].m_dwRegionID = SubWorld[nSubWorld].m_Region[nRegion].m_RegionID;
  337. #endif
  338. Npc[i].m_MapX = nMapX;
  339. Npc[i].m_MapY = nMapY;
  340. Npc[i].m_OffX = nOffX;
  341. Npc[i].m_OffY = nOffY;
  342. SubWorld[nSubWorld].Map2Mps(nRegion, nMapX, nMapY, nOffX, nOffY, &Npc[i].m_OriginX, &Npc[i].m_OriginY);
  343. #ifdef _SERVER
  344. SetID(i);
  345. #endif
  346. // 修改可用与使用表
  347. m_FreeIdx.Remove(i);
  348. m_UseIdx.Insert(i);
  349. SubWorld[nSubWorld].m_Region[nRegion].AddNpc(i);//m_WorldMessage.Send(GWM_NPC_ADD, nRegion, i);
  350. SubWorld[nSubWorld].m_Region[nRegion].AddRef(nMapX, nMapY, obj_npc);
  351. #ifndef _SERVER
  352. Npc[i].m_dwRegionID = SubWorld[nSubWorld].m_Region[nRegion].m_RegionID;
  353. #endif
  354. return i;
  355. }
  356. void KNpcSet::Remove(int nIdx)
  357. {
  358. if (nIdx <= 0 || nIdx >= MAX_NPC)
  359. return;
  360. #ifdef _SERVER
  361. NPC_REMOVE_SYNC NetCommand;
  362. NetCommand.ProtocolType = (BYTE)s2c_npcremove;
  363. NetCommand.ID = Npc[nIdx].m_dwID;
  364. int nSubWorld = Npc[nIdx].m_SubWorldIndex;
  365. int nRegion = Npc[nIdx].m_RegionIndex;
  366. if (nSubWorld >= 0 && nSubWorld <= MAX_SUBWORLD && nRegion >= 0 && nRegion <= SubWorld[nSubWorld].m_nTotalRegion)
  367. {
  368. POINT POff[8] = 
  369. {
  370. {0, 32},
  371. {-16, 32},
  372. {-16, 0},
  373. {-16, -32},
  374. {0, -32},
  375. {16, -32},
  376. {16, 0},
  377. {16, 32},
  378. };
  379. int nMaxCount = MAX_BROADCAST_COUNT;
  380. SubWorld[nSubWorld].m_Region[nRegion].BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, Npc[nIdx].m_MapX, Npc[nIdx].m_MapY);
  381. int nConRegion;
  382. for (int i = 0; i < 8; i++)
  383. {
  384. nConRegion = SubWorld[nSubWorld].m_Region[nRegion].m_nConnectRegion[i];
  385. if (nConRegion == -1)
  386. continue;
  387. SubWorld[nSubWorld].m_Region[nConRegion].BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, Npc[nIdx].m_MapX - POff[i].x, Npc[nIdx].m_MapY - POff[i].y);
  388. }
  389. }
  390. #endif
  391. Npc[nIdx].ClearNpcState();
  392. Npc[nIdx].m_SkillList.Clear();
  393. Npc[nIdx].Remove();
  394. m_FreeIdx.Insert(nIdx);
  395. m_UseIdx.Remove(nIdx);
  396. }
  397. void KNpcSet::RemoveAll()
  398. {
  399. int nIdx = m_UseIdx.GetNext(0);
  400. int nIdx1 = 0;
  401. while(nIdx)
  402. {
  403. nIdx1 = m_UseIdx.GetNext(nIdx);
  404. Npc[nIdx].ClearNpcState();
  405. Npc[nIdx].m_SkillList.Clear();
  406. Npc[nIdx].Remove();
  407. m_FreeIdx.Insert(nIdx);
  408. m_UseIdx.Remove(nIdx);
  409. nIdx = nIdx1;
  410. }
  411. }
  412. #ifndef _SERVER
  413. //---------------------------------------------------------------------------
  414. // 功能:从npc数组中寻找属于某个region的 client npc ,添加进去
  415. //---------------------------------------------------------------------------
  416. void KNpcSet::InsertNpcToRegion(int nRegionIdx)
  417. {
  418. if (nRegionIdx < 0 || nRegionIdx >= MAX_REGION)
  419. return;
  420. int nIdx = 0;
  421. while (1)
  422. {
  423. nIdx = m_UseIdx.GetNext(nIdx);
  424. if (nIdx == 0)
  425. break;
  426. if (Npc[nIdx].m_sClientNpcID.m_dwRegionID > 0 && Npc[nIdx].m_dwRegionID == (DWORD)SubWorld[0].m_Region[nRegionIdx].m_RegionID)
  427. {
  428. SubWorld[0].m_Region[nRegionIdx].AddNpc(nIdx);
  429. Npc[nIdx].m_RegionIndex = nRegionIdx;
  430. Npc[nIdx].m_dwRegionID = SubWorld[0].m_Region[nRegionIdx].m_RegionID;
  431. Npc[nIdx].m_SyncSignal = SubWorld[0].m_dwCurrentTime;
  432. Npc[nIdx].SendCommand(do_stand);
  433. }
  434. }
  435. }
  436. #endif
  437. void KNpcSet::SetID(int m_nIndex)
  438. {
  439. if (m_nIndex <= 0 || m_nIndex >= MAX_NPC)
  440. return;
  441. Npc[m_nIndex].m_dwID = m_dwIDCreator;
  442. m_dwIDCreator++;
  443. }
  444. int KNpcSet::GetDistance(int nIdx1, int nIdx2)
  445. {
  446. int nRet = 0;
  447. if (Npc[nIdx1].m_SubWorldIndex != Npc[nIdx2].m_SubWorldIndex)
  448. return -1;
  449. if (Npc[nIdx1].m_RegionIndex == Npc[nIdx2].m_RegionIndex)
  450. {
  451. int XOff = (Npc[nIdx1].m_MapX - Npc[nIdx2].m_MapX) * SubWorld[Npc[nIdx1].m_SubWorldIndex].m_nCellWidth;
  452. XOff += (Npc[nIdx1].m_OffX - Npc[nIdx2].m_OffX) >> 10;
  453. int YOff = (Npc[nIdx1].m_MapY - Npc[nIdx2].m_MapY) * SubWorld[Npc[nIdx1].m_SubWorldIndex].m_nCellHeight;
  454. YOff += (Npc[nIdx1].m_OffY - Npc[nIdx2].m_OffY) >> 10;
  455. nRet = (int)sqrt(XOff * XOff + YOff * YOff);
  456. }
  457. else
  458. {
  459. int X1, Y1;
  460. SubWorld[Npc[nIdx1].m_SubWorldIndex].Map2Mps(Npc[nIdx1].m_RegionIndex, 
  461. Npc[nIdx1].m_MapX,
  462. Npc[nIdx1].m_MapY,
  463. Npc[nIdx1].m_OffX,
  464. Npc[nIdx1].m_OffY,
  465. &X1,
  466. &Y1);
  467. int X2, Y2;
  468. SubWorld[Npc[nIdx2].m_SubWorldIndex].Map2Mps(Npc[nIdx2].m_RegionIndex, 
  469. Npc[nIdx2].m_MapX,
  470. Npc[nIdx2].m_MapY,
  471. Npc[nIdx2].m_OffX,
  472. Npc[nIdx2].m_OffY,
  473. &X2,
  474. &Y2);
  475. nRet = (int)sqrt((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1));
  476. }
  477. return nRet;
  478. }
  479. int KNpcSet::GetDistanceSquare(int nIdx1, int nIdx2)
  480. {
  481. int nRet = 0;
  482. if (Npc[nIdx1].m_SubWorldIndex != Npc[nIdx2].m_SubWorldIndex)
  483. return -1;
  484. if (Npc[nIdx1].m_RegionIndex == Npc[nIdx2].m_RegionIndex)
  485. {
  486. int XOff = (Npc[nIdx1].m_MapX - Npc[nIdx2].m_MapX) * SubWorld[Npc[nIdx1].m_SubWorldIndex].m_nCellWidth;
  487. XOff += (Npc[nIdx1].m_OffX - Npc[nIdx2].m_OffX) >> 10;
  488. int YOff = (Npc[nIdx1].m_MapY - Npc[nIdx2].m_MapY) * SubWorld[Npc[nIdx1].m_SubWorldIndex].m_nCellHeight;
  489. YOff += (Npc[nIdx1].m_OffY - Npc[nIdx2].m_OffY) >> 10;
  490. nRet = (int)(XOff * XOff + YOff * YOff);
  491. }
  492. else
  493. {
  494. int X1, Y1;
  495. SubWorld[Npc[nIdx1].m_SubWorldIndex].Map2Mps(Npc[nIdx1].m_RegionIndex, 
  496. Npc[nIdx1].m_MapX,
  497. Npc[nIdx1].m_MapY,
  498. Npc[nIdx1].m_OffX,
  499. Npc[nIdx1].m_OffY,
  500. &X1,
  501. &Y1);
  502. int X2, Y2;
  503. SubWorld[Npc[nIdx2].m_SubWorldIndex].Map2Mps(Npc[nIdx2].m_RegionIndex, 
  504. Npc[nIdx2].m_MapX,
  505. Npc[nIdx2].m_MapY,
  506. Npc[nIdx2].m_OffX,
  507. Npc[nIdx2].m_OffY,
  508. &X2,
  509. &Y2);
  510. nRet = (int)((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1));
  511. }
  512. return nRet;
  513. }
  514. int KNpcSet::GetNextIdx(int nIdx)
  515. {
  516. if (nIdx < 0 || nIdx >= MAX_NPC)
  517. return 0;
  518. return m_UseIdx.GetNext(nIdx);
  519. }
  520. #ifdef _SERVER
  521. BOOL KNpcSet::SyncNpc(DWORD dwID, int nClientIdx)
  522. {
  523. int nFindIndex;
  524. nFindIndex = SearchID(dwID);
  525. if (nFindIndex <= 0)
  526. {
  527. NPC_REQUEST_FAIL RequestFail;
  528. RequestFail.ProtocolType = s2c_requestnpcfail;
  529. RequestFail.ID = dwID;
  530. if (g_pServer)
  531. g_pServer->PackDataToClient(nClientIdx, &RequestFail, sizeof(NPC_REQUEST_FAIL));
  532. return FALSE;
  533. }
  534. Npc[nFindIndex].SendSyncData(nClientIdx);
  535. return TRUE;
  536. }
  537. #endif
  538. #ifndef _SERVER
  539. void KNpcSet::CheckBalance()
  540. {
  541. int nIdx;
  542. nIdx = m_UseIdx.GetNext(0);
  543. while(nIdx)
  544. {
  545. int nTmpIdx = m_UseIdx.GetNext(nIdx);
  546. if (SubWorld[0].m_dwCurrentTime - Npc[nIdx].m_SyncSignal > 1000)
  547. {
  548. if (nIdx != Player[CLIENT_PLAYER_INDEX].m_nIndex)
  549. {
  550. if (Npc[nIdx].m_RegionIndex >= 0)
  551. {
  552. SubWorld[0].m_Region[Npc[nIdx].m_RegionIndex].RemoveNpc(nIdx);
  553. SubWorld[0].m_Region[Npc[nIdx].m_RegionIndex].DecRef(Npc[nIdx].m_MapX, Npc[nIdx].m_MapY, obj_npc);
  554. }
  555. Remove(nIdx);
  556. }
  557. }
  558. nIdx = nTmpIdx;
  559. }
  560. nIdx = m_RequestUseIdx.GetNext(0);
  561. while(nIdx)
  562. {
  563. int nTmpIdx = m_RequestUseIdx.GetNext(nIdx);
  564. if (SubWorld[0].m_dwCurrentTime - m_RequestNpc[nIdx].dwRequestTime > 100)
  565. {
  566. DWORD dwID = m_RequestNpc[nIdx].dwRequestId;
  567. m_RequestNpc[nIdx].dwRequestId = 0;
  568. m_RequestNpc[nIdx].dwRequestTime = 0;
  569. m_RequestUseIdx.Remove(nIdx);
  570. m_RequestFreeIdx.Insert(nIdx);
  571. g_DebugLog("[Request]Remove %d from %d on %d timeout", dwID, nIdx, SubWorld[0].m_dwCurrentTime);
  572. }
  573. nIdx = nTmpIdx;
  574. }
  575. }
  576. #endif
  577. #ifndef _SERVER
  578. //-------------------------------------------------------------------------
  579. // 功能:获得周围玩家列表,用于界面,队伍邀请列表
  580. //-------------------------------------------------------------------------
  581. int KNpcSet::GetAroundPlayerForTeamInvite(KUiPlayerItem *pList, int nCount)
  582. {
  583. int nCamp = Npc[Player[CLIENT_PLAYER_INDEX].m_nIndex].m_Camp;
  584. int nNum = 0, i;
  585. if (nCount == 0)
  586. {
  587. int nIdx = 0;
  588. while (1)
  589. {
  590. nIdx = m_UseIdx.GetNext(nIdx);
  591. if (nIdx == 0)
  592. break;
  593. if (Npc[nIdx].m_Kind != kind_player)
  594. continue;
  595. if (nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex)
  596. continue;
  597. if (Npc[nIdx].m_Camp != camp_begin && nCamp == camp_begin)
  598. continue;
  599. if (Npc[nIdx].m_RegionIndex < 0)
  600. continue;
  601. for (i = 0; i < MAX_TEAM_MEMBER; i++)
  602. {
  603. if ((DWORD)g_Team[0].m_nMember[i] == Npc[nIdx].m_dwID)
  604. break;
  605. }
  606. if (i < MAX_TEAM_MEMBER)
  607. continue;
  608. if ((DWORD)g_Team[0].m_nCaptain == Npc[nIdx].m_dwID)
  609. continue;
  610. nNum++;
  611. }
  612. return nNum;
  613. }
  614. if (!pList)
  615. return 0;
  616. int nIdx = 0;
  617. while (1)
  618. {
  619. nIdx = m_UseIdx.GetNext(nIdx);
  620. if (nIdx == 0)
  621. break;
  622. if (Npc[nIdx].m_Kind != kind_player)
  623. continue;
  624. if (nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex)
  625. continue;
  626. if (Npc[nIdx].m_Camp != camp_begin && nCamp == camp_begin)
  627. continue;
  628. if (Npc[nIdx].m_RegionIndex < 0)
  629. continue;
  630. for (i = 0; i < MAX_TEAM_MEMBER; i++)
  631. {
  632. if ((DWORD)g_Team[0].m_nMember[i] == Npc[nIdx].m_dwID)
  633. break;
  634. }
  635. if (i < MAX_TEAM_MEMBER)
  636. continue;
  637. if ((DWORD)g_Team[0].m_nCaptain == Npc[nIdx].m_dwID)
  638. continue;
  639. pList[nNum].nIndex = nIdx;
  640. pList[nNum].uId = Npc[nIdx].m_dwID;
  641. strcpy(pList[nNum].Name, Npc[nIdx].Name);
  642. nNum++;
  643. }
  644. return nNum;
  645. }
  646. #endif
  647. #ifndef _SERVER
  648. //-------------------------------------------------------------------------
  649. // 功能:获得周围玩家列表(用于列表)
  650. //-------------------------------------------------------------------------
  651. int KNpcSet::GetAroundPlayer(KUiPlayerItem *pList, int nCount)
  652. {
  653. int nNum = 0;
  654. if (nCount <= 0)
  655. {
  656. int nIdx = 0;
  657. while (1)
  658. {
  659. nIdx = m_UseIdx.GetNext(nIdx);
  660. if (nIdx == 0)
  661. break;
  662. if (Npc[nIdx].m_Kind != kind_player ||
  663. nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex ||
  664. Npc[nIdx].m_RegionIndex < 0)
  665. {
  666. continue;
  667. }
  668. // if (Player[CLIENT_PLAYER_INDEX].m_cChat.CheckExist(Npc[nIdx].Name))
  669. // continue;
  670. nNum++;
  671. }
  672. return nNum;
  673. }
  674. if (!pList)
  675. return 0;
  676. int nIdx = 0;
  677. while (nNum < nCount)
  678. {
  679. nIdx = m_UseIdx.GetNext(nIdx);
  680. if (nIdx == 0)
  681. break;
  682. if (Npc[nIdx].m_Kind != kind_player ||
  683. nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex ||
  684. Npc[nIdx].m_RegionIndex < 0)
  685. {
  686. continue;
  687. }
  688. // if (Player[CLIENT_PLAYER_INDEX].m_cChat.CheckExist(Npc[nIdx].Name))
  689. // continue;
  690. pList[nNum].nIndex = nIdx;
  691. pList[nNum].uId = Npc[nIdx].m_dwID;
  692. strcpy(pList[nNum].Name, Npc[nIdx].Name);
  693. pList[nNum].nData = Npc[nIdx].GetMenuState();
  694. nNum++;
  695. }
  696. return nNum;
  697. }
  698. #endif
  699. #ifndef _SERVER
  700. //-------------------------------------------------------------------------
  701. // 功能:设定是否全部显示玩家的名字
  702. // bFlag == TRUE 显示,bFlag == FALSE 不显示 zroc add
  703. //-------------------------------------------------------------------------
  704. void KNpcSet::SetShowNameFlag(BOOL bFlag)
  705. {
  706. if (bFlag)
  707. m_nShowPateFlag |= PATE_NAME;
  708. else
  709. m_nShowPateFlag &= ~PATE_NAME;
  710. }
  711. #endif
  712. #ifndef _SERVER
  713. //-------------------------------------------------------------------------
  714. // 功能:判断是否全部显示玩家的名字  返回值 TRUE 显示,FALSE 不显示
  715. //-------------------------------------------------------------------------
  716. BOOL KNpcSet::CheckShowName()
  717. {
  718. return m_nShowPateFlag & PATE_NAME;
  719. }
  720. #endif
  721. #ifndef _SERVER
  722. //-------------------------------------------------------------------------
  723. // 功能:设定是否全部显示玩家的血
  724. // bFlag == TRUE 显示,bFlag == FALSE 不显示 zroc add
  725. //-------------------------------------------------------------------------
  726. void KNpcSet::SetShowLifeFlag(BOOL bFlag)
  727. {
  728. if (bFlag)
  729. m_nShowPateFlag |= PATE_LIFE;
  730. else
  731. m_nShowPateFlag &= ~PATE_LIFE;
  732. }
  733. #endif
  734. #ifndef _SERVER
  735. //-------------------------------------------------------------------------
  736. // 功能:判断是否全部显示玩家的血  返回值 TRUE 显示,FALSE 不显示
  737. //-------------------------------------------------------------------------
  738. BOOL KNpcSet::CheckShowLife()
  739. {
  740. return m_nShowPateFlag & PATE_LIFE;
  741. }
  742. #endif
  743. #ifndef _SERVER
  744. //-------------------------------------------------------------------------
  745. // 功能:设定是否全部显示玩家的聊天
  746. // bFlag == TRUE 显示,bFlag == FALSE 不显示 zroc add
  747. //-------------------------------------------------------------------------
  748. void KNpcSet::SetShowChatFlag(BOOL bFlag)
  749. {
  750. if (bFlag)
  751. m_nShowPateFlag |= PATE_CHAT;
  752. else
  753. m_nShowPateFlag &= ~PATE_CHAT;
  754. }
  755. #endif
  756. #ifndef _SERVER
  757. //-------------------------------------------------------------------------
  758. // 功能:判断是否全部显示玩家的聊天  返回值 TRUE 显示,FALSE 不显示
  759. //-------------------------------------------------------------------------
  760. BOOL KNpcSet::CheckShowChat()
  761. {
  762. return m_nShowPateFlag & PATE_CHAT;
  763. }
  764. #endif
  765. #ifndef _SERVER
  766. //-------------------------------------------------------------------------
  767. // 功能:设定是否全部显示玩家的内力
  768. // bFlag == TRUE 显示,bFlag == FALSE 不显示 zroc add
  769. //-------------------------------------------------------------------------
  770. void KNpcSet::SetShowManaFlag(BOOL bFlag)
  771. {
  772. if (bFlag)
  773. m_nShowPateFlag |= PATE_MANA;
  774. else
  775. m_nShowPateFlag &= ~PATE_MANA;
  776. }
  777. #endif
  778. #ifndef _SERVER
  779. //-------------------------------------------------------------------------
  780. // 功能:判断是否全部显示玩家的内力  返回值 TRUE 显示,FALSE 不显示
  781. //-------------------------------------------------------------------------
  782. BOOL KNpcSet::CheckShowMana()
  783. {
  784. return m_nShowPateFlag & PATE_MANA;
  785. }
  786. #endif
  787. //-------------------------------------------------------------------------
  788. // 功能:把所有npc的 bActivateFlag 设为 FALSE
  789. // (每次游戏循环处理所有npc的activate之前做这个处理)
  790. //-------------------------------------------------------------------------
  791. void KNpcSet::ClearActivateFlagOfAllNpc()
  792. {
  793. int nIdx = 0;
  794. while (1)
  795. {
  796. nIdx = m_UseIdx.GetNext(nIdx);
  797. if (nIdx == 0)
  798. break;
  799. Npc[nIdx].m_bActivateFlag = FALSE;
  800. }
  801. }
  802. #ifndef _SERVER
  803. //-------------------------------------------------------------------------
  804. // 功能:获得周围同阵营的已开放队伍队长列表 不同阵营现在可以组队
  805. //-------------------------------------------------------------------------
  806. void KNpcSet::GetAroundOpenCaptain(int nCamp)
  807. {
  808. int nIdx, nNum, nNo;
  809. nIdx = 0;
  810. nNum = 0;
  811. while (1)
  812. {
  813. nIdx = m_UseIdx.GetNext(nIdx);
  814. if (nIdx == 0)
  815. break;
  816. if (Npc[nIdx].m_Kind != kind_player)
  817. continue;
  818. if (nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex)
  819. continue;
  820. // 不同阵营现在可以组队,老手不能加入新人队伍,新人可以加入老手队伍
  821. if (Npc[nIdx].m_Camp == camp_begin && nCamp != camp_begin)
  822. continue;
  823. // if (Npc[nIdx].m_Camp != nCamp)
  824. // continue;
  825. if (Npc[nIdx].m_RegionIndex < 0)
  826. continue;
  827. if (Npc[nIdx].GetMenuState() == PLAYER_MENU_STATE_TEAMOPEN)
  828. nNum++;
  829. }
  830. if (nNum > 0)
  831. {
  832. KUiTeamItem* const pTeamList = new KUiTeamItem[nNum];
  833. nIdx = 0;
  834. nNo = 0;
  835. while (1)
  836. {
  837. nIdx = m_UseIdx.GetNext(nIdx);
  838. if (nIdx == 0)
  839. break;
  840. if (Npc[nIdx].m_Kind != kind_player)
  841. continue;
  842. if (nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex)
  843. continue;
  844. // 不同阵营现在可以组队,老手不能加入新人队伍,新人可以加入老手队伍
  845. if (Npc[nIdx].m_Camp == camp_begin && nCamp != camp_begin)
  846. continue;
  847. // if (Npc[nIdx].m_Camp != nCamp)
  848. // continue;
  849. if (Npc[nIdx].m_RegionIndex < 0)
  850. continue;
  851. if (Npc[nIdx].GetMenuState() == PLAYER_MENU_STATE_TEAMOPEN)
  852. {
  853. pTeamList[nNo].Leader.nIndex = nIdx;
  854. pTeamList[nNo].Leader.uId = Npc[nIdx].m_dwID;
  855. strcpy(pTeamList[nNo].Leader.Name, Npc[nIdx].Name);
  856. nNo++;
  857. if (nNo >= nNum)
  858. break;
  859. }
  860. }
  861. CoreDataChanged(GDCNI_TEAM_NEARBY_LIST, (unsigned int)pTeamList, nNo);
  862. delete []pTeamList;
  863. }
  864. }
  865. #endif
  866. #ifndef _SERVER // 用于客户端
  867. int KNpcSet::SearchNpcAt(int nX, int nY, int nRelation, int nRange)
  868. {
  869. int nIdx;
  870. int nMin = nRange;
  871. int nMinIdx = 0;
  872. int nLength = 0;
  873. int nSrcX[2];
  874. int nSrcY[2];
  875. nSrcX[0] = nX;
  876. nSrcY[0] = nY;
  877. g_ScenePlace.ViewPortCoordToSpaceCoord(nSrcX[0], nSrcY[0], 0);
  878. nSrcX[1] = nX;
  879. nSrcY[1] = nY;
  880. g_ScenePlace.ViewPortCoordToSpaceCoord(nSrcX[1], nSrcY[1], 120);
  881. int nDx = nSrcX[0] - nSrcX[1];
  882. int nDy = nSrcY[0] - nSrcY[1];
  883. nIdx = 0;
  884. while (1)
  885. {
  886. nIdx = m_UseIdx.GetNext(nIdx);
  887. if (nIdx == 0)
  888. break;
  889. if (Npc[nIdx].m_RegionIndex < 0)
  890. continue;
  891. if (nIdx == Player[CLIENT_PLAYER_INDEX].m_nIndex)
  892. continue;
  893. if (Npc[nIdx].m_bClientOnly)
  894. continue;
  895. if (!(GetRelation(Player[CLIENT_PLAYER_INDEX].m_nIndex, nIdx) & nRelation))
  896. continue;
  897. int x, y;
  898. SubWorld[0].Map2Mps(Npc[nIdx].m_RegionIndex, Npc[nIdx].m_MapX, Npc[nIdx].m_MapY,
  899. Npc[nIdx].m_OffX, Npc[nIdx].m_OffY, &x, &y);
  900. if (nSrcY[0] > y)
  901. continue;
  902. if (nSrcY[0] < y - 120)
  903. continue;
  904. nLength = abs(nDx * (nSrcY[0] - y) / nDy + nSrcX[0] - x);
  905. if (nLength < nMin)
  906. {
  907. nMin = nLength;
  908. nMinIdx = nIdx;
  909. }
  910. }
  911. return nMinIdx;
  912. }
  913. #endif
  914. #ifndef _SERVER
  915. BOOL KNpcSet::IsNpcRequestExist(DWORD dwID)
  916. {
  917. return (GetRequestIndex(dwID) > 0);
  918. }
  919. void KNpcSet::InsertNpcRequest(DWORD dwID)
  920. {
  921. if (IsNpcRequestExist(dwID))
  922. {
  923. return;
  924. }
  925. int nIndex = m_RequestFreeIdx.GetNext(0);
  926. if (!nIndex)
  927. return;
  928. m_RequestNpc[nIndex].dwRequestId = dwID;
  929. m_RequestNpc[nIndex].dwRequestTime = SubWorld[0].m_dwCurrentTime;
  930. m_RequestFreeIdx.Remove(nIndex);
  931. m_RequestUseIdx.Insert(nIndex);
  932. g_DebugLog("[Request]Insert %d at %d on %d", dwID, nIndex, SubWorld[0].m_dwCurrentTime);
  933. }
  934. void KNpcSet::RemoveNpcRequest(DWORD dwID)
  935. {
  936. if(!IsNpcRequestExist(dwID))
  937. {
  938. return;
  939. }
  940. int nIndex = GetRequestIndex(dwID);
  941. // because _ASSERT(IsNpcRequestExist()); so nIndex > 0;
  942. m_RequestNpc[nIndex].dwRequestId = 0;
  943. m_RequestNpc[nIndex].dwRequestTime = 0;
  944. m_RequestUseIdx.Remove(nIndex);
  945. m_RequestFreeIdx.Insert(nIndex);
  946. g_DebugLog("[Request]Remove %d from %d on %d", dwID, nIndex, SubWorld[0].m_dwCurrentTime);
  947. }
  948. int KNpcSet::GetRequestIndex(DWORD dwID)
  949. {
  950. int nIndex = m_RequestUseIdx.GetNext(0);
  951. while(nIndex)
  952. {
  953. if (m_RequestNpc[nIndex].dwRequestId == dwID)
  954. {
  955. return nIndex;
  956. }
  957. nIndex = m_RequestUseIdx.GetNext(nIndex);
  958. }
  959. return 0;
  960. }
  961. #endif
  962. NPC_RELATION KNpcSet::GetRelation(int nId1, int nId2)
  963. {
  964. // 同一个人
  965. if (nId1 == nId2)
  966. return relation_self;
  967. #ifndef _SERVER
  968. if (Npc[nId1].m_bClientOnly || Npc[nId2].m_bClientOnly)
  969. return relation_none;
  970. #endif
  971.     _ASSERT(
  972.         ((Npc[nId1].m_Kind >= 0) && (Npc[nId1].m_Kind < kind_num)) &&
  973.         ((Npc[nId2].m_Kind >= 0) && (Npc[nId2].m_Kind < kind_num)) &&
  974.         ((Npc[nId1].m_CurrentCamp >= 0) && (Npc[nId1].m_CurrentCamp < camp_num)) &&
  975.         ((Npc[nId2].m_CurrentCamp >= 0) && (Npc[nId2].m_CurrentCamp < camp_num))
  976.     );
  977. #ifndef _SERVER
  978. if (Player[CLIENT_PLAYER_INDEX].m_nIndex != nId1 && Player[CLIENT_PLAYER_INDEX].m_nIndex != nId2)
  979. {
  980. if (Npc[nId1].m_Kind == kind_player && Npc[nId2].m_Kind == kind_player && Npc[nId1].m_nPKFlag == FALSE)
  981. return relation_none;
  982. return (NPC_RELATION)m_RelationTable
  983. [Npc[nId1].m_Kind]
  984. [Npc[nId2].m_Kind]
  985. [Npc[nId1].m_CurrentCamp]
  986. [Npc[nId2].m_CurrentCamp];
  987. }
  988. else if (Player[CLIENT_PLAYER_INDEX].m_nIndex == nId1)
  989. {
  990. if (Player[CLIENT_PLAYER_INDEX].m_cPK.GetExercisePKAim() == Npc[nId2].m_dwID)
  991. return relation_enemy;
  992. if (Player[CLIENT_PLAYER_INDEX].m_cPK.GetEnmityPKState() == enumPK_ENMITY_STATE_PKING &&
  993. Player[CLIENT_PLAYER_INDEX].m_cPK.GetEnmityPKAimNpcID() == Npc[nId2].m_dwID)
  994. return relation_enemy;
  995. if (Npc[nId2].m_Kind == kind_player && Player[CLIENT_PLAYER_INDEX].m_cPK.GetNormalPKState() == FALSE)
  996. return relation_none;
  997. return (NPC_RELATION)m_RelationTable
  998. [Npc[nId1].m_Kind]
  999. [Npc[nId2].m_Kind]
  1000. [Npc[nId1].m_CurrentCamp]
  1001. [Npc[nId2].m_CurrentCamp];
  1002. }
  1003. else // if (Player[CLIENT_PLAYER_INDEX].m_nIndex == nId2)
  1004. {
  1005. if (Player[CLIENT_PLAYER_INDEX].m_cPK.GetExercisePKAim() == Npc[nId1].m_dwID)
  1006. return relation_enemy;
  1007. if (Player[CLIENT_PLAYER_INDEX].m_cPK.GetEnmityPKState() == enumPK_ENMITY_STATE_PKING &&
  1008. Player[CLIENT_PLAYER_INDEX].m_cPK.GetEnmityPKAimNpcID() == Npc[nId1].m_dwID)
  1009. return relation_enemy;
  1010. if (Npc[nId1].m_Kind == kind_player && Npc[nId2].m_Kind == kind_player && !Npc[nId1].m_nPKFlag)
  1011. return relation_none;
  1012. return (NPC_RELATION)m_RelationTable
  1013. [Npc[nId1].m_Kind]
  1014. [Npc[nId2].m_Kind]
  1015. [Npc[nId1].m_CurrentCamp]
  1016. [Npc[nId2].m_CurrentCamp];
  1017. }
  1018. #endif
  1019. #ifdef _SERVER
  1020. if (Npc[nId1].m_Kind != kind_player || Npc[nId2].m_Kind != kind_player)
  1021. {
  1022. return (NPC_RELATION)m_RelationTable
  1023. [Npc[nId1].m_Kind]
  1024. [Npc[nId2].m_Kind]
  1025. [Npc[nId1].m_CurrentCamp]
  1026. [Npc[nId2].m_CurrentCamp];
  1027. }
  1028. else
  1029. {
  1030. if (Player[Npc[nId1].m_nPlayerIdx].m_cPK.GetExercisePKAim() == Npc[nId2].m_nPlayerIdx)
  1031. return relation_enemy;
  1032. if (Player[Npc[nId1].m_nPlayerIdx].m_cPK.GetEnmityPKState() == enumPK_ENMITY_STATE_PKING
  1033. && Player[Npc[nId1].m_nPlayerIdx].m_cPK.GetEnmityPKAim() == Npc[nId2].m_nPlayerIdx)
  1034. return relation_enemy;
  1035. // if (!Player[Npc[nId1].m_nPlayerIdx].m_cPK.GetNormalPKState())
  1036. // return relation_none;
  1037. NPC_RELATION nRelation =  (NPC_RELATION)m_RelationTable
  1038. [Npc[nId1].m_Kind]
  1039. [Npc[nId2].m_Kind]
  1040. [Npc[nId1].m_CurrentCamp]
  1041. [Npc[nId2].m_CurrentCamp];
  1042. if (nRelation == relation_enemy)
  1043. {
  1044. if (!Player[Npc[nId1].m_nPlayerIdx].m_cPK.GetNormalPKState())
  1045. return relation_none;
  1046. }
  1047. return nRelation;
  1048. }
  1049. #endif
  1050. }
  1051. //------------------------ class KInstantSpecial start -------------------------
  1052. #ifndef _SERVER
  1053. KInstantSpecial::KInstantSpecial()
  1054. {
  1055. int i;
  1056. this->m_nLoadFlag = FALSE;
  1057. for (i = 0; i < MAX_INSTANT_STATE; i++)
  1058. this->m_szSprName[i][0] = 0;
  1059. for (i = 0; i < MAX_INSTANT_SOUND; i++)
  1060. this->m_szSoundName[i][0] = 0;
  1061. m_pSoundNode = NULL;
  1062. m_pWave = NULL;
  1063. }
  1064. void KInstantSpecial::LoadSprName()
  1065. {
  1066. int i;
  1067. for (i = 0; i < MAX_INSTANT_STATE; i++)
  1068. m_szSprName[i][0] = 0;
  1069. KTabFile cSprName;
  1070. // g_SetFilePath("\");
  1071. if (!cSprName.Load(PLAYER_INSTANT_SPECIAL_FILE))
  1072. return;
  1073. for (i = 0; i < MAX_INSTANT_STATE; i++)
  1074. cSprName.GetString(i + 2, 3, "", m_szSprName[i], sizeof(m_szSprName[i]));
  1075. }
  1076. void KInstantSpecial::LoadSoundName()
  1077. {
  1078. int i;
  1079. for (i = 0; i < MAX_INSTANT_SOUND; i++)
  1080. m_szSoundName[i][0] = 0;
  1081. KIniFile cSoundName;
  1082. char szTemp[32];
  1083. // g_SetFilePath("\");
  1084. if (!cSoundName.Load(defINSTANT_SOUND_FILE))
  1085. return;
  1086. for (i = 0; i < MAX_INSTANT_SOUND; i++)
  1087. {
  1088. sprintf(szTemp, "%d", i);
  1089. cSoundName.GetString("Game", szTemp, "", this->m_szSoundName[i], sizeof(m_szSoundName[i]));
  1090. }
  1091. }
  1092. void KInstantSpecial::GetSprName(int nNo, char *lpszName, int nLength)
  1093. {
  1094. if (!lpszName || nLength <= 0)
  1095. return;
  1096. if (nNo < 0 || nNo >= MAX_INSTANT_STATE)
  1097. {
  1098. lpszName[0] = 0;
  1099. return;
  1100. }
  1101. if (this->m_nLoadFlag == FALSE)
  1102. {
  1103. this->LoadSprName();
  1104. this->LoadSoundName();
  1105. m_nLoadFlag = TRUE;
  1106. }
  1107. if (strlen(this->m_szSprName[nNo]) < (DWORD)nLength)
  1108. strcpy(lpszName, m_szSprName[nNo]);
  1109. else
  1110. lpszName[0] = 0;
  1111. }
  1112. void KInstantSpecial::PlaySound(int nNo)
  1113. {
  1114. if (this->m_nLoadFlag == FALSE)
  1115. {
  1116. this->LoadSprName();
  1117. this->LoadSoundName();
  1118. m_nLoadFlag = TRUE;
  1119. }
  1120. if (nNo < 0 || nNo >= MAX_INSTANT_SOUND)
  1121. return;
  1122. if ( !m_szSoundName[nNo][0] )
  1123. return;
  1124. m_pSoundNode = (KCacheNode*)g_SoundCache.GetNode(m_szSoundName[nNo], (KCacheNode*)m_pSoundNode);
  1125. m_pWave = (KWavSound*)m_pSoundNode->m_lpData;
  1126. if (m_pWave)
  1127. {
  1128. if (m_pWave->IsPlaying())
  1129. return;
  1130. m_pWave->Play(0, -10000 + Option.GetSndVolume() * 100, 0);
  1131. }
  1132. }
  1133. #endif
  1134. //------------------------- class KInstantSpecial end --------------------------