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

模拟服务器

开发平台:

C/C++

  1. return FALSE;
  2. }
  3. else
  4. {
  5. if (!bOnlyCheckCanCast)
  6. *pSource -= nCost;
  7. return TRUE;
  8. }
  9. }
  10. return FALSE;
  11. }
  12. void KNpc::DoJump()
  13. {
  14. _ASSERT(m_RegionIndex >= 0);
  15. if (m_RegionIndex < 0)
  16. return;
  17. if (m_Doing == do_jump)
  18. return;
  19. m_Doing = do_jump;
  20. m_Dir = m_JumpDir;
  21. m_ProcessAI = 0;
  22. m_JumpFirstSpeed = ACCELERATION_OF_GRAVITY * (m_JumpStep - 1) / 2 ;
  23. #ifdef _SERVER // 向周围9个Region广播发技能
  24. NPC_JUMP_SYNC NetCommand;
  25. NetCommand.ProtocolType = (BYTE)s2c_npcjump;
  26. NetCommand.ID = m_dwID;
  27. NetCommand.nMpsX = m_DesX;
  28. NetCommand.nMpsY = m_DesY;
  29. POINT POff[8] = 
  30. {
  31. {0, 32},
  32. {-16, 32},
  33. {-16, 0},
  34. {-16, -32},
  35. {0, -32},
  36. {16, -32},
  37. {16, 0},
  38. {16, 32},
  39. };
  40. int nMaxCount = MAX_BROADCAST_COUNT;
  41. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  42. for (int i= 0; i < 8; i++)
  43. {
  44. if (CONREGIONIDX(i) == -1)
  45. continue;
  46. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  47. }
  48. #endif
  49. #ifndef _SERVER
  50. m_ClientDoing = cdo_jump;
  51. #endif
  52. m_Frames.nTotalFrame = m_JumpStep;
  53. m_Frames.nCurrentFrame = 0;
  54. }
  55. BOOL KNpc::OnJump()
  56. {
  57. ServeJump(m_CurrentJumpSpeed);
  58. if (WaitForFrame())
  59. {
  60. DoStand();
  61. m_ProcessAI = 1;
  62. return FALSE;
  63. }
  64. return TRUE;
  65. }
  66. BOOL KNpc::WaitForFrame()
  67. {
  68. m_Frames.nCurrentFrame++;
  69. if (m_Frames.nCurrentFrame < m_Frames.nTotalFrame)
  70. {
  71. return FALSE;
  72. }
  73. m_Frames.nCurrentFrame = 0;
  74. return TRUE;
  75. }
  76. BOOL KNpc::IsReachFrame(int nPercent)
  77. {
  78. if (m_Frames.nCurrentFrame == m_Frames.nTotalFrame * nPercent / 100)
  79. {
  80. return TRUE;
  81. }
  82. return FALSE;
  83. }
  84. //客户端从网络得到的NpcSettingIdx是包含高16位Npc的模板号与低16位为等级
  85. void KNpc::Load(int nNpcSettingIdx, int nLevel)
  86. {
  87. m_PathFinder.Init(m_Index);
  88. if (nLevel <= 0) 
  89. {
  90. nLevel = 1;
  91. }
  92. #ifndef _SERVER
  93. char szNpcTypeName[32];
  94. #endif
  95. if (nNpcSettingIdx == PLAYER_MALE_NPCTEMPLATEID || nNpcSettingIdx == PLAYER_FEMALE_NPCTEMPLATEID)
  96. {
  97. m_NpcSettingIdx = nNpcSettingIdx;
  98. m_Level = nLevel;
  99. #ifndef _SERVER
  100. if (nNpcSettingIdx == PLAYER_MALE_NPCTEMPLATEID)
  101. {
  102. strcpy(szNpcTypeName, "男主角");
  103. m_StandFrame = NpcSet.GetPlayerStandFrame(TRUE);
  104. m_WalkFrame = NpcSet.GetPlayerWalkFrame(TRUE);
  105. m_RunFrame = NpcSet.GetPlayerRunFrame(TRUE);
  106. }
  107. else
  108. {
  109. strcpy(szNpcTypeName, "女主角");
  110. m_StandFrame = NpcSet.GetPlayerStandFrame(FALSE);
  111. m_WalkFrame = NpcSet.GetPlayerWalkFrame(FALSE);
  112. m_RunFrame = NpcSet.GetPlayerRunFrame(FALSE);
  113. }
  114. #endif
  115. // TODO: Load Player Data;
  116. m_WalkSpeed = NpcSet.GetPlayerWalkSpeed();
  117. m_RunSpeed = NpcSet.GetPlayerRunSpeed();
  118. m_AttackFrame = NpcSet.GetPlayerAttackFrame();
  119. m_HurtFrame = NpcSet.GetPlayerHurtFrame();
  120. }
  121. else
  122. {
  123. GetNpcCopyFromTemplate(nNpcSettingIdx, nLevel);
  124. #ifndef _SERVER
  125. g_NpcSetting.GetString(nNpcSettingIdx + 2, "NpcResType", "", szNpcTypeName, sizeof(szNpcTypeName));
  126. if (!szNpcTypeName[0])
  127. {
  128. g_NpcKindFile.GetString(2, "人物名称", "", szNpcTypeName, sizeof(szNpcTypeName));//如果没找到,用第一个npc代替
  129. }
  130. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIMode", 12, &m_AiMode);
  131. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam1", 12, &m_AiParam[0]);
  132. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam2", 12, &m_AiParam[1]);
  133. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam3", 12, &m_AiParam[2]);
  134. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam4", 12, &m_AiParam[3]);
  135. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam5", 12, &m_AiParam[4]);
  136. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam6", 12, &m_AiParam[5]);
  137. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "AIParam7", 12, &m_AiParam[6]);
  138. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "ActiveRadius", 12, &m_ActiveRadius);
  139. g_NpcSetting.GetInteger(nNpcSettingIdx + 2, "ClientOnly", 0, &m_bClientOnly);
  140. // 飞行类,11,12,17,用AiParam[6]保存策划设定高度
  141. // add by flying
  142. if (m_AiMode == 11 || m_AiMode == 12 || m_AiMode == 17)
  143. m_AiParam[6] = m_AiMode;
  144. #endif
  145. }
  146. #ifndef _SERVER
  147. m_DataRes.Init(szNpcTypeName, &g_NpcResList);
  148. m_DataRes.SetAction(m_ClientDoing);
  149. m_DataRes.SetRideHorse(m_bRideHorse);
  150. m_DataRes.SetArmor(m_ArmorType);
  151. m_DataRes.SetHelm(m_HelmType);
  152. m_DataRes.SetHorse(m_HorseType);
  153. m_DataRes.SetWeapon(m_WeaponType);
  154. #endif
  155. m_CurrentCamp = m_Camp;
  156. }
  157. void KNpc::GetMpsPos(int *pPosX, int *pPosY)
  158. {
  159. #ifdef _SERVER
  160. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, pPosX, pPosY);
  161. #else
  162. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, pPosX, pPosY);
  163. // KSubWorld::Map2Mps(C_REGION_X(m_RegionIndex), C_REGION_Y(m_RegionIndex), m_MapX, m_MapY, m_OffX, m_OffY, pPosX, pPosY);
  164. #endif
  165. }
  166. BOOL KNpc::SetActiveSkill(int nSkillIdx)
  167. {
  168. if (nSkillIdx <= 0 || nSkillIdx >= MAX_NPCSKILL)
  169. return FALSE;
  170. if (!(m_SkillList.m_Skills[nSkillIdx].SkillId && m_SkillList.m_Skills[nSkillIdx].CurrentSkillLevel))
  171. return FALSE;
  172. m_ActiveSkillID = m_SkillList.m_Skills[nSkillIdx].SkillId;
  173. int nLevel = m_SkillList.m_Skills[nSkillIdx].SkillLevel;
  174. _ASSERT(m_ActiveSkillID < MAX_SKILL && nLevel < MAX_SKILLLEVEL && nLevel > 0);
  175. ISkill * pISkill =  g_SkillManager.GetSkill(m_ActiveSkillID, nLevel);
  176. if (pISkill)
  177.     {
  178. m_CurrentAttackRadius = pISkill->GetAttackRadius();
  179.     }
  180. return TRUE;
  181. }
  182. void KNpc::SetAuraSkill(int nSkillID)
  183. {
  184. int nCurLevel = 0;
  185. if (nSkillID <= 0 || nSkillID >= MAX_SKILL) 
  186.     {
  187.         nSkillID = 0;
  188.     }
  189. else
  190. {
  191. nCurLevel = m_SkillList.GetCurrentLevel(nSkillID);
  192. if (nCurLevel <= 0) 
  193.         {
  194.             nSkillID = 0;
  195.         }
  196. else
  197. {
  198. _ASSERT(nSkillID < MAX_SKILL && nCurLevel < MAX_SKILLLEVEL);
  199. KSkill * pOrdinSkill = (KSkill *)g_SkillManager.GetSkill(nSkillID, nCurLevel);
  200.             if (!pOrdinSkill || !pOrdinSkill->IsAura())
  201. {
  202. nSkillID  = 0;
  203. }
  204. }
  205. }
  206. m_ActiveAuraID = nSkillID;
  207. #ifdef _SERVER
  208. if (m_ActiveAuraID)
  209. {
  210. int nStateSpecialId = 0;
  211. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(nSkillID, nCurLevel);
  212. if (pOrdinSkill)
  213.         {
  214. nStateSpecialId = pOrdinSkill->GetStateSpecailId();
  215.         }
  216. if (nStateSpecialId) m_btStateInfo[m_nNextStatePos] = nStateSpecialId;
  217. if ((++m_nNextStatePos) >= MAX_NPC_RECORDER_STATE) m_nNextStatePos = 0;
  218. BroadCastState();
  219. }
  220. else
  221. {
  222. UpdateNpcStateInfo();
  223. BroadCastState();
  224. }
  225. #endif
  226. #ifndef _SERVER
  227. SKILL_CHANGEAURASKILL_COMMAND ChangeAuraMsg;
  228. ChangeAuraMsg.ProtocolType = c2s_changeauraskill;
  229. ChangeAuraMsg.m_nAuraSkill = m_ActiveAuraID;
  230. if (g_pClient)
  231. g_pClient->SendPackToServer(&ChangeAuraMsg, sizeof(SKILL_CHANGEAURASKILL_COMMAND));
  232. #endif
  233. }
  234. BOOL KNpc::SetPlayerIdx(int nIdx)
  235. {
  236. if (nIdx <= 0 || nIdx >= MAX_PLAYER)
  237. return FALSE;
  238. if (m_Kind != kind_player)
  239. return FALSE;
  240. m_nPlayerIdx = nIdx;
  241. return TRUE;
  242. }
  243. #ifdef _SERVER
  244. BOOL KNpc::SendSyncData(int nClient)
  245. {
  246. BOOL bRet = FALSE;
  247. NPC_SYNC NpcSync;
  248. NpcSync.ProtocolType = (BYTE)s2c_syncnpc;
  249. NpcSync.m_btKind = (BYTE)m_Kind;
  250. NpcSync.Camp = (BYTE)m_Camp;
  251. NpcSync.CurrentCamp = (BYTE)m_CurrentCamp;
  252. NpcSync.m_bySeries = (BYTE)m_Series;
  253. NpcSync.m_Doing = (BYTE)m_Doing;
  254. if (m_CurrentLifeMax > 0)
  255. NpcSync.LifePerCent = (BYTE)((m_CurrentLife << 7) / m_CurrentLifeMax);//Question只改了这部分,其它的也需要spe修改
  256. else
  257. NpcSync.LifePerCent = 0;
  258. if (this->IsPlayer())
  259. NpcSync.m_btMenuState = (BYTE)Player[this->m_nPlayerIdx].m_cMenuState.m_nState;
  260. else
  261. NpcSync.m_btMenuState = 0;
  262. GetMpsPos((int *)&NpcSync.MapX, (int *)&NpcSync.MapY);
  263. NpcSync.ID = m_dwID;
  264. NpcSync.NpcSettingIdx = MAKELONG(m_Level, m_NpcSettingIdx);
  265. // NpcSync.NpcEnchant = (WORD)m_NpcEnchant;
  266. NpcSync.NpcEnchant = (WORD)this->m_cGold.GetGoldType();
  267. strcpy(NpcSync.m_szName, Name);
  268. NpcSync.m_wLength = sizeof(NPC_SYNC) - 1 - sizeof(NpcSync.m_szName) + strlen(NpcSync.m_szName);
  269. if (SUCCEEDED(g_pServer->PackDataToClient(nClient, (BYTE*)&NpcSync, NpcSync.m_wLength + 1)))
  270. {
  271. //printf("Packing sync data ok...n");
  272. bRet = TRUE;
  273. }
  274. else
  275. {
  276. printf("Packing sync data failed...n");
  277. return FALSE;
  278. }
  279. g_DebugLog("[Sync]%d:%s<%d> request to %d. size:%d", SubWorld[m_SubWorldIndex].m_dwCurrentTime, Name, m_Kind, nClient, NpcSync.m_wLength + 1);
  280. if (IsPlayer())
  281. {
  282. PLAYER_SYNC PlayerSync;
  283. PlayerSync.ProtocolType = (BYTE)s2c_syncplayer;
  284. PlayerSync.ID = m_dwID;
  285. PlayerSync.ArmorType = (BYTE)m_ArmorType;
  286. PlayerSync.AttackSpeed = (BYTE)m_CurrentAttackSpeed;
  287. PlayerSync.CastSpeed = (BYTE)m_CurrentCastSpeed;
  288. PlayerSync.HelmType = (BYTE)m_HelmType;
  289. PlayerSync.HorseType = (BYTE)m_HorseType;
  290. PlayerSync.RunSpeed = (BYTE)m_CurrentRunSpeed;
  291. PlayerSync.WalkSpeed = (BYTE)m_CurrentWalkSpeed;
  292. PlayerSync.WeaponType = (BYTE)m_WeaponType;
  293. PlayerSync.RankID = (BYTE)m_btRankId;
  294. PlayerSync.m_btSomeFlag = 0;
  295. if (Player[m_nPlayerIdx].m_cPK.GetNormalPKState())
  296. PlayerSync.m_btSomeFlag |= 0x01;
  297. if (Npc[Player[m_nPlayerIdx].m_nIndex].m_FightMode)
  298. PlayerSync.m_btSomeFlag |= 0x02;
  299. if (Player[m_nPlayerIdx].m_bSleepMode)
  300. PlayerSync.m_btSomeFlag |= 0x04;
  301. if (SUCCEEDED(g_pServer->PackDataToClient(nClient, (BYTE*)&PlayerSync, sizeof(PLAYER_SYNC))))
  302. {
  303. //printf("Packing player sync data ok...n");
  304. bRet = TRUE;
  305. }
  306. else
  307. {
  308. printf("Packing player sync data failed...n");
  309. return FALSE;
  310. }
  311. }
  312. return bRet;
  313. }
  314. // 平时数据的同步
  315. void KNpc::NormalSync()
  316. {
  317. if (m_Doing == do_revive || m_Doing == do_death || !m_Index || m_RegionIndex < 0)
  318. return;
  319. NPC_NORMAL_SYNC NpcSync;
  320. int nMpsX, nMpsY;
  321. GetMpsPos(&nMpsX, &nMpsY);
  322. NpcSync.ProtocolType = (BYTE)s2c_syncnpcmin;
  323. NpcSync.ID = m_dwID;
  324. if (m_CurrentLife > 0)
  325. NpcSync.LifePerCent = (BYTE)((m_CurrentLife << 7) / m_CurrentLifeMax);
  326. else
  327. NpcSync.LifePerCent = 0;
  328. NpcSync.MapX = nMpsX;
  329. NpcSync.MapY = nMpsY;
  330. NpcSync.Camp = (BYTE)m_CurrentCamp;
  331. NpcSync.State = 0;
  332. if (m_FreezeState.nTime > 0)
  333. NpcSync.State |= STATE_FREEZE;
  334. if (m_PoisonState.nTime > 0)
  335. NpcSync.State |= STATE_POISON;
  336. if (m_ConfuseState.nTime > 0)
  337. NpcSync.State |= STATE_CONFUSE;
  338. if (m_StunState.nTime > 0)
  339. NpcSync.State |= STATE_STUN;
  340. NpcSync.Doing = (BYTE)m_Doing;
  341. // 由于同步数据每次同步的很少,所以上限就是MAX_PLAYER
  342. POINT POff[8] = 
  343. {
  344. {0, 32},
  345. {-16, 32},
  346. {-16, 0},
  347. {-16, -32},
  348. {0, -32},
  349. {16, -32},
  350. {16, 0},
  351. {16, 32},
  352. };
  353. int nMaxCount = MAX_PLAYER;//MAX_BROADCAST_COUNT;
  354. CURREGION.BroadCast(&NpcSync, sizeof(NPC_NORMAL_SYNC), nMaxCount, m_MapX, m_MapY);
  355. int j;
  356. for (j = 0; j < 8; j++)
  357. {
  358. int nConRegion = CURREGION.m_nConnectRegion[j];
  359. if (nConRegion == -1)
  360. continue;
  361. _ASSERT(m_SubWorldIndex >= 0 && nConRegion >= 0);
  362. SubWorld[m_SubWorldIndex].m_Region[nConRegion].BroadCast((BYTE*)&NpcSync, sizeof(NPC_NORMAL_SYNC), nMaxCount, m_MapX - POff[j].x, m_MapY - POff[j].y);
  363. }
  364. if (IsPlayer())
  365. {
  366. PLAYER_NORMAL_SYNC PlayerSync;
  367. PlayerSync.ProtocolType = (BYTE)s2c_syncplayermin;
  368. PlayerSync.ID = m_dwID;
  369. PlayerSync.AttackSpeed = (BYTE)m_CurrentAttackSpeed;
  370. PlayerSync.CastSpeed = (BYTE)m_CurrentCastSpeed;
  371. PlayerSync.RunSpeed = (BYTE)m_CurrentRunSpeed;
  372. PlayerSync.WalkSpeed = (BYTE)m_CurrentWalkSpeed;
  373. PlayerSync.HelmType = (BYTE)m_HelmType;
  374. PlayerSync.ArmorType = (BYTE)m_ArmorType;
  375. PlayerSync.WeaponType = (BYTE)m_WeaponType;
  376. PlayerSync.HorseType = (BYTE)m_HorseType;
  377. PlayerSync.RankID = (BYTE)m_btRankId;
  378. PlayerSync.m_btSomeFlag = 0;
  379. if (Player[m_nPlayerIdx].m_cPK.GetNormalPKState())
  380. PlayerSync.m_btSomeFlag |= 0x01;
  381. if (m_FightMode)
  382. PlayerSync.m_btSomeFlag |= 0x02;
  383. if (Player[m_nPlayerIdx].m_bSleepMode)
  384. PlayerSync.m_btSomeFlag |= 0x04;
  385. if (Player[m_nPlayerIdx].m_cTong.GetOpenFlag())
  386. PlayerSync.m_btSomeFlag |= 0x08;
  387. int nMaxCount = MAX_PLAYER;//MAX_BROADCAST_COUNT;
  388. CURREGION.BroadCast(&PlayerSync, sizeof(PLAYER_NORMAL_SYNC), nMaxCount, m_MapX, m_MapY);
  389. for (j = 0; j < 8; j++)
  390. {
  391. int nConRegion = CURREGION.m_nConnectRegion[j];
  392. if (nConRegion == -1)
  393. continue;
  394. SubWorld[m_SubWorldIndex].m_Region[nConRegion].BroadCast((BYTE*)&PlayerSync, sizeof(PLAYER_NORMAL_SYNC), nMaxCount, m_MapX - POff[j].x, m_MapY - POff[j].y);
  395. }
  396. NPC_PLAYER_TYPE_NORMAL_SYNC sSync;
  397. sSync.ProtocolType = s2c_syncnpcminplayer;
  398. sSync.m_dwNpcID = m_dwID;
  399. if (m_CurrentLife > 0 && m_CurrentLifeMax > 0)
  400. sSync.m_btLifePerCent = (BYTE)((m_CurrentLife << 7) / m_CurrentLifeMax);
  401. else
  402. sSync.m_btLifePerCent = 0;
  403. // sSync.m_nRegionID = SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].m_RegionID;
  404. sSync.m_btCamp = (BYTE)m_CurrentCamp;
  405. sSync.m_dwMapX = nMpsX;
  406. sSync.m_dwMapY = nMpsY;
  407. sSync.m_wOffX = m_OffX;
  408. sSync.m_wOffY = m_OffY;
  409. sSync.m_byDoing = this->m_Doing;
  410. g_pServer->PackDataToClient(Player[m_nPlayerIdx].m_nNetConnectIdx, (BYTE*)&sSync, sizeof(sSync));
  411. }
  412. }
  413. void KNpc::BroadCastRevive(int nType)
  414. {
  415. if (!IsPlayer())
  416. return;
  417. if (m_RegionIndex < 0)
  418. return;
  419. NPC_REVIVE_SYNC NpcReviveSync;
  420. NpcReviveSync.ProtocolType = s2c_playerrevive;
  421. NpcReviveSync.ID = m_dwID;
  422. NpcReviveSync.Type = (BYTE)nType;
  423. POINT POff[8] = 
  424. {
  425. {0, 32},
  426. {-16, 32},
  427. {-16, 0},
  428. {-16, -32},
  429. {0, -32},
  430. {16, -32},
  431. {16, 0},
  432. {16, 32},
  433. };
  434. int nMaxCount = MAX_BROADCAST_COUNT;
  435. CURREGION.BroadCast((BYTE*)&NpcReviveSync, sizeof(NPC_REVIVE_SYNC), nMaxCount, m_MapX, m_MapY);
  436. int j;
  437. for (j = 0; j < 8; j++)
  438. {
  439. int nConRegion = CURREGION.m_nConnectRegion[j];
  440. if (nConRegion == -1)
  441. continue;
  442. SubWorld[m_SubWorldIndex].m_Region[nConRegion].BroadCast((BYTE*)&NpcReviveSync, sizeof(NPC_REVIVE_SYNC), nMaxCount, m_MapX - POff[j].x, m_MapY - POff[j].y);
  443. }
  444. }
  445. int KNpc::GetPlayerIdx()
  446. {
  447. if (m_Kind != kind_player)
  448. return 0;
  449. return m_nPlayerIdx;
  450. }
  451. #endif
  452. #ifndef _SERVER
  453. #include "scene/KScenePlaceC.h"
  454. int KNpc::PaintInfo(int nHeightOffset, bool bSelect, int nFontSize, DWORD dwBorderColor)
  455. {
  456. int nMpsX, nMpsY;
  457. GetMpsPos(&nMpsX, &nMpsY);
  458. DWORD dwColor;
  459. int nHeightOff = nHeightOffset + nFontSize + 1;
  460. if (m_Kind == kind_player)
  461. {
  462. switch(m_CurrentCamp)
  463. {
  464. case camp_begin:
  465. dwColor = 0xffffffff;
  466. break;
  467. case camp_justice:
  468. dwColor = 0xff000000 | (255 << 16) | (168 << 8) | 94;
  469. break;
  470. case camp_evil:
  471. dwColor = 0xff000000 | (255 << 16) | (146 << 8) | 255;
  472. break;
  473. case camp_balance:
  474. dwColor = 0xff000000 | (85 << 16) | (255 << 8) | 145;
  475. break;
  476. case camp_free:
  477. dwColor = 0xff000000 | (255 << 16);
  478. break;
  479. default:
  480. dwColor = 0xffff00ff;
  481. break;
  482. /* case camp_animal:
  483. dwColor = 
  484. break;
  485. case camp_event:
  486. break;*/
  487. }
  488. char szString[128];
  489. strcpy(szString, Name);
  490. if (m_FreezeState.nTime || m_PoisonState.nTime || m_ConfuseState.nTime || m_StunState.nTime)
  491. {
  492. strcat(szString, "(");
  493. if (m_FreezeState.nTime)
  494. strcat(szString, "冰");
  495. if (m_PoisonState.nTime)
  496. strcat(szString, "毒");
  497. if (m_ConfuseState.nTime)
  498. strcat(szString, "乱");
  499. if (m_StunState.nTime)
  500. strcat(szString, "晕");
  501. strcat(szString, ")");
  502. }
  503. g_pRepresent->OutputText(nFontSize, szString, KRF_ZERO_END, nMpsX - nFontSize * g_StrLen(Name) / 4, nMpsY, dwColor, 0, nHeightOff, dwBorderColor);
  504. nHeightOffset += nFontSize + 1;
  505. }
  506. else if (m_Kind == kind_dialoger)
  507. {
  508. dwColor = 0xffffffff;
  509. g_pRepresent->OutputText(nFontSize, Name, KRF_ZERO_END, nMpsX - nFontSize * g_StrLen(Name) / 4, nMpsY, dwColor, 0, nHeightOff, dwBorderColor);
  510. nHeightOffset += nFontSize + 1;
  511. }
  512. else if (bSelect)
  513. {
  514. if (this->m_cGold.GetGoldType() == 0)
  515. dwColor = 0xffffffff;
  516. else
  517. dwColor = 0xffebb200; // 金色
  518. g_pRepresent->OutputText(nFontSize, Name, KRF_ZERO_END, nMpsX - nFontSize * g_StrLen(Name) / 4, nMpsY, dwColor, 0, nHeightOff, dwBorderColor);
  519. nHeightOffset += nFontSize + 1;
  520. }
  521. #ifdef SWORDONLINE_SHOW_DBUG_INFO
  522. if (Player[CLIENT_PLAYER_INDEX].m_DebugMode)
  523. {
  524. char szNameID[50];
  525. sprintf(szNameID,"[%d]", m_dwID);
  526. g_pRepresent->OutputText(12, szNameID, KRF_ZERO_END, nMpsX, nMpsY + 20, 0xfff0fff0, 0, m_Height);
  527. }
  528. if (Player[CLIENT_PLAYER_INDEX].m_nIndex == m_Index && Player[CLIENT_PLAYER_INDEX].m_DebugMode)
  529. {
  530. char szMsg[256];
  531. int nCount[9];
  532. for (int i = 0; i < 9; i++)
  533. nCount[i] = 0;
  534. if (LEFTUPREGIONIDX >= 0)
  535. nCount[0] = LEFTUPREGION.m_NpcList.GetNodeCount();
  536. if (UPREGIONIDX >= 0)
  537. nCount[1] = UPREGION.m_NpcList.GetNodeCount();
  538. if (RIGHTUPREGIONIDX >= 0)
  539. nCount[2] = RIGHTUPREGION.m_NpcList.GetNodeCount();
  540. if (LEFTREGIONIDX >= 0)
  541. nCount[3] = LEFTREGION.m_NpcList.GetNodeCount();
  542. if (m_RegionIndex >= 0)
  543. nCount[4] = CURREGION.m_NpcList.GetNodeCount();
  544. if (RIGHTREGIONIDX >= 0)
  545. nCount[5] = RIGHTREGION.m_NpcList.GetNodeCount();
  546. if (LEFTDOWNREGIONIDX >= 0)
  547. nCount[6] = LEFTDOWNREGION.m_NpcList.GetNodeCount();
  548. if (DOWNREGIONIDX >= 0)
  549. nCount[7] = DOWNREGION.m_NpcList.GetNodeCount();
  550. if (RIGHTDOWNREGIONIDX >= 0)
  551. nCount[8] = RIGHTDOWNREGION.m_NpcList.GetNodeCount();
  552. int nPosX, nPosY;
  553. GetMpsPos(&nPosX, &nPosY);
  554. sprintf(szMsg,
  555. "NpcID:%d  Life:%dnRegionIndex:%d Pos:%d,%dnPlayerNumber:%dn"
  556. "NpcNumber:n%02d,%02d,%02dn%02d,%02d,%02dn%02d,%02d,%02d",
  557. m_dwID,
  558. m_CurrentLife,
  559. m_RegionIndex,
  560. m_MapX,
  561. m_MapY,
  562. CURREGION.m_PlayerList.GetNodeCount(),
  563. nCount[0], nCount[1], nCount[2],
  564. nCount[3], nCount[4], nCount[5],
  565. nCount[6], nCount[7], nCount[8]
  566. );
  567. g_pRepresent->OutputText(12, szMsg, -1, 320, 40, 0xffffffff);
  568. }
  569. #endif
  570. return nHeightOffset;
  571. }
  572. int KNpc::PaintChat(int nHeightOffset)
  573. {
  574. if (m_Kind != kind_player)
  575. return nHeightOffset;
  576. if (m_nChatContentLen <= 0)
  577. return nHeightOffset;
  578. if (m_nChatNumLine <= 0)
  579. return nHeightOffset;
  580. int nFontSize = 12;
  581. int nWidth, nHeight;
  582. int nMpsX, nMpsY;
  583. KRUShadow sShadow;
  584. KOutputTextParam sParam;
  585. sParam.BorderColor = 0;
  586. sParam.nNumLine = m_nChatNumLine;
  587. nWidth = m_nChatFontWidth * nFontSize / 2;
  588. nHeight = sParam.nNumLine * (nFontSize + 1);
  589. nWidth += 6; //为了好看
  590. nHeight += 5; //为了好看
  591. GetMpsPos(&nMpsX, &nMpsY);
  592. sParam.nX = nMpsX - nWidth / 2;
  593. sParam.nY = nMpsY;
  594. sParam.nZ = nHeightOffset + nHeight;
  595. sParam.Color = SHOW_CHAT_COLOR;
  596. sParam.nSkipLine = 0;
  597. sParam.nVertAlign = 0;
  598. sShadow.oPosition.nX = sParam.nX;
  599. sShadow.oPosition.nX -= 3; //为了好看
  600. sShadow.oPosition.nY = sParam.nY;
  601. sShadow.oPosition.nZ = sParam.nZ;
  602. sShadow.oEndPos.nX = sParam.nX + nWidth;
  603. sShadow.oEndPos.nX += 2; //为了好看
  604. sShadow.oEndPos.nY = sParam.nY;
  605. sShadow.oEndPos.nZ = sParam.nZ - nHeight;
  606. //sShadow.Color.Color_dw = 0x00FFFF00;
  607. //g_pRepresent->DrawPrimitives(1, &sShadow, RU_T_RECT, false);
  608. sShadow.Color.Color_dw = 0x14000000;
  609. //g_pRepresent->DrawPrimitives(1, &sShadow, RU_T_SHADOW, false);
  610. sParam.bPicPackInSingleLine = true;
  611. g_pRepresent->OutputRichText(nFontSize, &sParam, m_szChatBuffer, m_nChatContentLen, nWidth);
  612. return sParam.nZ;
  613. }
  614. #include "../../Engine/Src/Text.h"
  615. int KNpc::SetChatInfo(const char* Name, const char* pMsgBuff, unsigned short nMsgLength)
  616. {
  617. int nFontSize = 12;
  618. char szChatBuffer[MAX_SENTENCE_LENGTH];
  619. memset(szChatBuffer, 0, sizeof(szChatBuffer));
  620. if (nMsgLength)
  621. {
  622. int nOffset = 0;
  623. if (pMsgBuff[0] != KTC_TAB)
  624. {
  625. szChatBuffer[nOffset] = (char)KTC_COLOR;
  626. nOffset++;
  627. szChatBuffer[nOffset] = (char)0xFF;
  628. nOffset++;
  629. szChatBuffer[nOffset] = (char)0xFF;
  630. nOffset++;
  631. szChatBuffer[nOffset] = (char)0x00;
  632. nOffset++;
  633. strncpy(szChatBuffer + nOffset, Name, 32);
  634. nOffset += strlen(Name);
  635. szChatBuffer[nOffset] = ':';
  636. nOffset++;
  637. szChatBuffer[nOffset] = (char)KTC_COLOR_RESTORE;
  638. nOffset++;
  639. }
  640. else
  641. {
  642. pMsgBuff ++;
  643. nMsgLength --;
  644. }
  645. if (nMsgLength)
  646. {
  647. memcpy(szChatBuffer + nOffset, pMsgBuff, nMsgLength);
  648. nOffset += nMsgLength;
  649. memset(m_szChatBuffer, 0, sizeof(m_szChatBuffer));
  650. m_nChatContentLen = MAX_SENTENCE_LENGTH;
  651. TGetLimitLenEncodedString(szChatBuffer, nOffset, nFontSize, SHOW_CHAT_WIDTH,
  652. m_szChatBuffer, m_nChatContentLen, 2, true);
  653. m_nChatNumLine = TGetEncodedTextLineCount(m_szChatBuffer, m_nChatContentLen, SHOW_CHAT_WIDTH, m_nChatFontWidth, nFontSize, 0, 0, true);
  654. if (m_nChatNumLine >= 2)
  655. m_nChatNumLine = 2;
  656. m_nCurChatTime = IR_GetCurrentTime();
  657. return true;
  658. }
  659. }
  660. return false;
  661. }
  662. int KNpc::PaintLife(int nHeightOffset, bool bSelect)
  663. {
  664. if (!bSelect &&
  665. (m_Kind != kind_player &&
  666. m_Kind != kind_partner)
  667. )
  668. return nHeightOffset;
  669. if (m_CurrentLifeMax <= 0)
  670. return nHeightOffset;
  671. if (relation_enemy == NpcSet.GetRelation(m_Index, Player[CLIENT_PLAYER_INDEX].m_nIndex) &&
  672. (m_Kind == kind_player ||
  673.  m_Kind == kind_partner)
  674. )
  675. return nHeightOffset; //有敌对关系的玩家不显示生命
  676. int nMpsX, nMpsY;
  677. GetMpsPos(&nMpsX, &nMpsY);
  678. int nWid = SHOW_LIFE_WIDTH;
  679. int nHei = SHOW_LIFE_HEIGHT;
  680. KRUShadow Blood;
  681. int nX = m_CurrentLife * 100 / m_CurrentLifeMax;
  682. if (nX >= 50)
  683. {
  684. Blood.Color.Color_b.r = 0;
  685. Blood.Color.Color_b.g = 255;
  686. Blood.Color.Color_b.b = 0;
  687. }
  688. else if (nX >= 25)
  689. {
  690. Blood.Color.Color_b.r = 255;
  691. Blood.Color.Color_b.g = 255;
  692. Blood.Color.Color_b.b = 0;
  693. }
  694. else
  695. {
  696. Blood.Color.Color_b.r = 255;
  697. Blood.Color.Color_b.g = 0;
  698. Blood.Color.Color_b.b = 0;
  699. }
  700. Blood.Color.Color_b.a = 0;
  701. Blood.oPosition.nX = nMpsX - nWid / 2;
  702. Blood.oPosition.nY = nMpsY;
  703. Blood.oPosition.nZ = nHeightOffset + nHei;
  704. Blood.oEndPos.nX = Blood.oPosition.nX + nWid * nX / 100;
  705. Blood.oEndPos.nY = nMpsY;
  706. Blood.oEndPos.nZ = nHeightOffset;
  707. g_pRepresent->DrawPrimitives(1, &Blood, RU_T_SHADOW, FALSE);
  708. Blood.Color.Color_b.r = 128;
  709. Blood.Color.Color_b.g = 128;
  710. Blood.Color.Color_b.b = 128;
  711. Blood.oPosition.nX = Blood.oEndPos.nX;
  712. Blood.oEndPos.nX = nMpsX + nWid / 2;
  713. g_pRepresent->DrawPrimitives(1, &Blood, RU_T_SHADOW, FALSE);
  714. return nHeightOffset + nHei;
  715. }
  716. int KNpc::PaintMana(int nHeightOffset)
  717. {
  718. if (m_Kind != kind_player &&
  719. m_Kind != kind_partner)
  720. return nHeightOffset;
  721. if (m_CurrentManaMax <= 0)
  722. return nHeightOffset;
  723. return nHeightOffset;
  724. int nMpsX, nMpsY;
  725. GetMpsPos(&nMpsX, &nMpsY);
  726. int nWid = 38;
  727. int nHei = 5;
  728. KRUShadow Blood;
  729. int nX = m_CurrentMana * 100 / m_CurrentManaMax;
  730. if (nX >= 50)
  731. {
  732. Blood.Color.Color_b.r = 0;
  733. Blood.Color.Color_b.g = 0;
  734. Blood.Color.Color_b.b = 255;
  735. }
  736. else if (nX >= 25)
  737. {
  738. Blood.Color.Color_b.r = 255;
  739. Blood.Color.Color_b.g = 255;
  740. Blood.Color.Color_b.b = 0;
  741. }
  742. else
  743. {
  744. Blood.Color.Color_b.r = 255;
  745. Blood.Color.Color_b.g = 0;
  746. Blood.Color.Color_b.b = 0;
  747. }
  748. Blood.Color.Color_b.a = 0;
  749. Blood.oPosition.nX = nMpsX - nWid / 2;
  750. Blood.oPosition.nY = nMpsY;
  751. Blood.oPosition.nZ = nHeightOffset + nHei;
  752. Blood.oEndPos.nX = Blood.oPosition.nX + nWid * nX / 100;
  753. Blood.oEndPos.nY = nMpsY;
  754. Blood.oEndPos.nZ = nHeightOffset;
  755. g_pRepresent->DrawPrimitives(1, &Blood, RU_T_SHADOW, FALSE);
  756. Blood.Color.Color_b.r = 255;
  757. Blood.Color.Color_b.g = 255;
  758. Blood.Color.Color_b.b = 255;
  759. Blood.oPosition.nX = Blood.oEndPos.nX;
  760. Blood.oEndPos.nX = nMpsX + nWid / 2;
  761. g_pRepresent->DrawPrimitives(1, &Blood, RU_T_SHADOW, FALSE);
  762. return nHeightOffset + nHei;
  763. }
  764. void KNpc::Paint()
  765. {
  766. if (m_ResDir != m_Dir)
  767. {
  768. int nDirOff = m_Dir - m_ResDir;
  769. if (nDirOff > 32)
  770. nDirOff -= 64;
  771. else if (nDirOff < - 32)
  772. nDirOff += 64;
  773. m_ResDir += nDirOff / 2;
  774. if (m_ResDir >= 64)
  775. m_ResDir -= 64;
  776. if (m_ResDir < 0)
  777. m_ResDir += 64;
  778. }
  779. m_DataRes.Draw(m_Index, m_ResDir, m_Frames.nTotalFrame, m_Frames.nCurrentFrame);
  780. int nHeight = GetNpcPate() + GetNpcPatePeopleInfo();
  781. DrawMenuState(nHeight);
  782. }
  783. #endif
  784. //--------------------------------------------------------------------------
  785. // 功能:增加基本最大生命点
  786. //--------------------------------------------------------------------------
  787. void KNpc::AddBaseLifeMax(int nLife)
  788. {
  789. m_LifeMax += nLife;
  790. m_CurrentLifeMax = m_LifeMax;
  791. }
  792. //--------------------------------------------------------------------------
  793. // 功能:增加当前最大生命点
  794. //--------------------------------------------------------------------------
  795. void KNpc::AddCurLifeMax(int nLife)
  796. {
  797. m_CurrentLifeMax += nLife;
  798. }
  799. //--------------------------------------------------------------------------
  800. // 功能:增加基本最大体力点
  801. //--------------------------------------------------------------------------
  802. void KNpc::AddBaseStaminaMax(int nStamina)
  803. {
  804. m_StaminaMax += nStamina;
  805. m_CurrentStaminaMax = m_StaminaMax;
  806. }
  807. //--------------------------------------------------------------------------
  808. // 功能:增加当前最大体力点
  809. //--------------------------------------------------------------------------
  810. void KNpc::AddCurStaminaMax(int nStamina)
  811. {
  812. m_CurrentStaminaMax += nStamina;
  813. }
  814. //--------------------------------------------------------------------------
  815. // 功能:增加基本最大内力点
  816. //--------------------------------------------------------------------------
  817. void KNpc::AddBaseManaMax(int nMana)
  818. {
  819. m_ManaMax += nMana;
  820. m_CurrentManaMax = m_ManaMax;
  821. }
  822. //--------------------------------------------------------------------------
  823. // 功能:增加当前最大内力点
  824. //--------------------------------------------------------------------------
  825. void KNpc::AddCurManaMax(int nMana)
  826. {
  827. m_CurrentManaMax += nMana;
  828. }
  829. /*
  830. //--------------------------------------------------------------------------
  831. // 功能:重新计算生命回复速度
  832. //--------------------------------------------------------------------------
  833. void KNpc::ResetLifeReplenish()
  834. {
  835. m_LifeReplenish = (m_Level + 5) / 6;
  836. m_CurrentLifeReplenish = m_LifeReplenish;
  837. }
  838. */
  839. /*
  840. //--------------------------------------------------------------------------
  841. // 功能:计算当前最大生命点
  842. //--------------------------------------------------------------------------
  843. void KNpc::CalcCurLifeMax()
  844. {
  845. }
  846. */
  847. /*
  848. //--------------------------------------------------------------------------
  849. // 功能:计算当前最大体力点
  850. //--------------------------------------------------------------------------
  851. void KNpc::CalcCurStaminaMax()
  852. {
  853. m_CurrentStaminaMax = m_StaminaMax; // 还需要加上 装备、技能、药物(临时)等的影响
  854. }
  855. */
  856. /*
  857. //--------------------------------------------------------------------------
  858. // 功能:计算当前最大内力点
  859. //--------------------------------------------------------------------------
  860. void KNpc::CalcCurManaMax()
  861. {
  862. m_CurrentManaMax = m_ManaMax; // 还需要加上 装备、技能、药物(临时)等的影响
  863. }
  864. */
  865. //--------------------------------------------------------------------------
  866. // 功能:计算当前生命回复速度
  867. //--------------------------------------------------------------------------
  868. void KNpc::CalcCurLifeReplenish()
  869. {
  870. m_CurrentLifeReplenish = m_LifeReplenish; // 与角色系别、角色等级和是否使用药剂、技能和魔法装备有关
  871. }
  872. void KNpc::Remove()
  873. {
  874. /* m_LoopFrames = 0;
  875. m_Index = 0;
  876. m_PlayerIdx = -1;
  877. m_Kind = 0;
  878. m_dwID = 0;
  879. Name[0] = 0;*/
  880. Init();
  881. #ifndef _SERVER
  882. m_DataRes.Remove(m_Index);
  883. #endif
  884. }
  885. #ifndef _SERVER
  886. void KNpc::RemoveRes()
  887. {
  888. m_DataRes.Remove(m_Index);
  889. }
  890. #endif
  891. //--------------------------------------------------------------------------
  892. // 功能:设定此 npc 的五行属性(内容还没完成)not end
  893. //--------------------------------------------------------------------------
  894. void KNpc::SetSeries(int nSeries)
  895. {
  896. if (nSeries >= series_metal && nSeries < series_num)
  897. m_Series = nSeries;
  898. else
  899. m_Series = series_metal;
  900. }
  901. /*!*****************************************************************************
  902. // Function : KNpc::SetStateSkill
  903. // Purpose : 
  904. // Return : void 
  905. // Argumant : int nSkillID
  906. // Argumant : int nLevel
  907. // Argumant : void *pData
  908. // Argumant : int nDataNum
  909. // Argumant : int nTime -1表示被动技能,时间无限
  910. // Comments :
  911. // Author : Spe
  912. *****************************************************************************/
  913. void KNpc::SetStateSkillEffect(int nLauncher, int nSkillID, int nLevel, void *pData, int nDataNum, int nTime/* = -1*/)
  914. {
  915. if (nLevel <= 0|| nSkillID <= 0) return ;
  916. _ASSERT(nDataNum < MAX_SKILL_STATE);
  917. if (nDataNum >= MAX_SKILL_STATE)
  918. nDataNum = MAX_SKILL_STATE;
  919. #ifdef _SERVER
  920. if (IsPlayer() && pData && nDataNum >= 0)
  921. {
  922. STATE_EFFECT_SYNC Sync;
  923. Sync.ProtocolType = s2c_syncstateeffect;
  924. Sync.m_dwSkillID = nSkillID;
  925. Sync.m_nLevel = nLevel;
  926. Sync.m_nTime = nTime;
  927. memcpy(Sync.m_MagicAttrib, pData, sizeof(KMagicAttrib) * nDataNum);
  928. Sync.m_wLength = sizeof(Sync) - sizeof(KMagicAttrib) * (MAX_SKILL_STATE - nDataNum) - 1;
  929. g_pServer->PackDataToClient(Player[m_nPlayerIdx].m_nNetConnectIdx, &Sync, Sync.m_wLength + 1);
  930. }
  931. #endif
  932. KStateNode* pNode;
  933. KMagicAttrib* pTemp = NULL;
  934. pNode = (KStateNode *)m_StateSkillList.GetHead();
  935. while(pNode)
  936. {
  937. if (pNode->m_SkillID == nSkillID)
  938. {
  939. if (pNode->m_Level == nLevel)
  940. {
  941. pNode->m_LeftTime = nTime;
  942. }
  943. else if (pNode->m_Level < nLevel)
  944. {
  945. pTemp = (KMagicAttrib *)pData;
  946. for (int i = 0; i < nDataNum; i++)
  947. {
  948. // 清除原技能的影响
  949. ModifyAttrib(nLauncher, &pNode->m_State[i]);
  950. // 把新等级下技能的影响计算到NPC身上
  951. ModifyAttrib(nLauncher, pTemp);
  952. pNode->m_State[i].nValue[0] = -pTemp->nValue[0];
  953. pNode->m_State[i].nValue[1] = -pTemp->nValue[1];
  954. pNode->m_State[i].nValue[2] = -pTemp->nValue[2];
  955. pTemp++;
  956. }
  957. }
  958. return;
  959. }
  960. pNode = (KStateNode *)pNode->GetNext();
  961. }
  962. // 没有在循环中返回,说明是新技能
  963. pNode = new KStateNode;
  964. pNode->m_SkillID = nSkillID;
  965. pNode->m_Level = nLevel;
  966. pNode->m_LeftTime = nTime;
  967. _ASSERT(nSkillID < MAX_SKILL && nLevel < MAX_SKILLLEVEL);
  968. KSkill * pOrdinSkill = (KSkill *)g_SkillManager.GetSkill(nSkillID, nLevel);
  969. if (pOrdinSkill)
  970.         pNode->m_StateGraphics = pOrdinSkill->GetStateSpecailId();
  971. else
  972. pNode->m_StateGraphics = 0;
  973. #ifdef _SERVER
  974. //如果为新的状态则需要更新角色的状态信息,并且广播给各个玩家
  975. if (pNode->m_StateGraphics) 
  976. {
  977. m_btStateInfo[m_nNextStatePos] = pNode->m_StateGraphics;
  978. if ((++m_nNextStatePos) >= MAX_NPC_RECORDER_STATE) m_nNextStatePos = 0;
  979. BroadCastState();
  980. }
  981. #else
  982. if (IsPlayer() && pNode->m_StateGraphics) 
  983. {
  984. m_btStateInfo[m_nNextStatePos] = pNode->m_StateGraphics;
  985. if ((++m_nNextStatePos) >= MAX_NPC_RECORDER_STATE)
  986. m_nNextStatePos = 0;
  987. }
  988. #endif
  989. pTemp = (KMagicAttrib *)pData;
  990. for (int i = 0; i < nDataNum; i++)
  991. {
  992. // 调整NPC属性
  993. ModifyAttrib(nLauncher, pTemp);
  994. // 把相反值加入链表中以供移除时使用
  995. pNode->m_State[i].nAttribType = pTemp->nAttribType;
  996. pNode->m_State[i].nValue[0] = -pTemp->nValue[0];
  997. pNode->m_State[i].nValue[1] = -pTemp->nValue[1];
  998. pNode->m_State[i].nValue[2] = -pTemp->nValue[2];
  999. pTemp++;
  1000. }
  1001. m_StateSkillList.AddTail(pNode);
  1002. }
  1003. /*!*****************************************************************************
  1004. // Function : KNpc::ModifyMissleCollsion
  1005. // Purpose : 
  1006. // Return : BOOL 
  1007. // Argumant : BOOL bCollsion
  1008. // Comments :
  1009. // Author : Spe
  1010. *****************************************************************************/
  1011. BOOL KNpc::ModifyMissleCollsion(BOOL bCollsion)
  1012. {
  1013. if (bCollsion)
  1014. return TRUE;
  1015. if (g_RandPercent(m_CurrentPiercePercent))
  1016. return TRUE;
  1017. else
  1018. return FALSE;
  1019. }
  1020. int KNpc::ModifyMissleLifeTime(int nLifeTime)
  1021. {
  1022. if (IsPlayer())
  1023. {
  1024. //return Player[m_PlayerIdx].GetWeapon().GetRange();
  1025. return nLifeTime;
  1026. }
  1027. else
  1028. {
  1029. return nLifeTime;
  1030. }
  1031. }
  1032. int KNpc::ModifyMissleSpeed(int nSpeed)
  1033. {
  1034. if (m_CurrentSlowMissle)
  1035. {
  1036. return nSpeed / 2;
  1037. }
  1038. return nSpeed;
  1039. }
  1040. BOOL KNpc::DoManyAttack()
  1041. {
  1042. m_ProcessAI = 0;
  1043. KSkill * pSkill =(KSkill*) GetActiveSkill();
  1044. if (!pSkill) 
  1045.         return FALSE;
  1046. if (pSkill->GetChildSkillNum() <= m_SpecialSkillStep) 
  1047.         goto ExitManyAttack;
  1048. #ifndef _SERVER
  1049.         m_DataRes.SetBlur(TRUE);
  1050. #endif
  1051. m_Frames.nTotalFrame = pSkill->GetMissleGenerateTime(m_SpecialSkillStep);
  1052. int x, y;
  1053. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &x, &y);
  1054. // m_DesX = x;
  1055. // m_DesY = y;
  1056. #ifndef _SERVER
  1057. if (m_nPlayerIdx > 0)
  1058. pSkill->PlayPreCastSound(m_nSex, x ,y);
  1059. if (g_Random(2))
  1060. m_ClientDoing = cdo_attack;
  1061. else 
  1062. m_ClientDoing = cdo_attack1;
  1063. #endif
  1064. m_Doing = do_manyattack;
  1065. m_Frames.nCurrentFrame = 0;
  1066. return TRUE;
  1067. ExitManyAttack:
  1068. #ifndef _SERVER
  1069. m_DataRes.SetBlur(FALSE);
  1070. #endif
  1071. DoStand();
  1072. m_ProcessAI = 1;
  1073. m_SpecialSkillStep = 0;
  1074. return TRUE;
  1075. }
  1076. void KNpc::OnManyAttack()
  1077. {
  1078. if (WaitForFrame())
  1079. {
  1080. #ifndef _SERVER
  1081. m_DataRes.SetBlur(FALSE);
  1082. #endif
  1083. KSkill * pSkill = (KSkill*)GetActiveSkill();
  1084. if (!pSkill) 
  1085.             return ;
  1086. int nPhySkillId =  pSkill->GetChildSkillId();//GetCurActiveWeaponSkill(); Changed 
  1087. if (nPhySkillId > 0)
  1088. {
  1089. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(nPhySkillId, pSkill->m_ulLevel, SKILL_SS_Missles);
  1090. if (pOrdinSkill)
  1091.             {
  1092. pOrdinSkill->Cast(m_Index, m_SkillParam1, m_SkillParam2);
  1093.             }
  1094. }
  1095. m_SpecialSkillStep ++;
  1096. DoManyAttack();
  1097. }
  1098. }
  1099. BOOL KNpc::DoRunAttack()
  1100. {
  1101. m_ProcessAI = 0;
  1102. switch(m_SpecialSkillStep)
  1103. {
  1104. case 0:
  1105. m_Frames.nTotalFrame = m_RunSpeed;
  1106. m_ProcessAI = 0;
  1107. #ifndef _SERVER
  1108. m_DataRes.SetBlur(TRUE);
  1109. if (m_FightMode)
  1110. {
  1111. m_ClientDoing = cdo_fightrun;
  1112. }
  1113. else
  1114. {
  1115. m_ClientDoing = cdo_run;
  1116. }
  1117. #endif
  1118. if (m_DesX < 0 && m_DesY > 0) 
  1119. {
  1120. int x, y;
  1121. SubWorld[m_SubWorldIndex].Map2Mps
  1122. (
  1123. Npc[m_DesY].m_RegionIndex,
  1124. Npc[m_DesY].m_MapX, 
  1125. Npc[m_DesY].m_MapY, 
  1126. Npc[m_DesY].m_OffX, 
  1127. Npc[m_DesY].m_OffY, 
  1128. &x,
  1129. &y
  1130. );
  1131. m_DesX = x;
  1132. m_DesY = y;
  1133. }
  1134. m_Frames.nCurrentFrame = 0;
  1135. m_Doing = do_runattack;
  1136. break;
  1137. case 1:
  1138. #ifndef _SERVER
  1139. if (g_Random(2))
  1140. m_ClientDoing = cdo_attack;
  1141. else
  1142. m_ClientDoing = cdo_attack1;
  1143. int x, y, tx, ty;
  1144. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &x, &y);
  1145. if (m_SkillParam1 == -1)
  1146. {
  1147. Npc[m_SkillParam2].GetMpsPos(&tx, &ty);
  1148. }
  1149. else
  1150. {
  1151. tx = m_SkillParam1;
  1152. ty = m_SkillParam2;
  1153. }
  1154. m_Dir = g_GetDirIndex(x, y, tx, ty);
  1155. #endif
  1156. m_Frames.nTotalFrame = m_AttackFrame * 100 / (100 + m_CurrentAttackSpeed);
  1157. m_Frames.nCurrentFrame = 0;
  1158. m_Doing = do_runattack;
  1159. break;
  1160. case 2:
  1161. case 3:
  1162. #ifndef _SERVER
  1163. m_DataRes.SetBlur(FALSE);
  1164. #endif
  1165. DoStand();
  1166. m_ProcessAI = 1;
  1167. m_SpecialSkillStep = 0;
  1168. return FALSE;
  1169. break;
  1170. }
  1171. m_Frames.nCurrentFrame = 0;
  1172. return TRUE;
  1173. }
  1174. void KNpc::OnRunAttack()
  1175. {
  1176. if (m_SpecialSkillStep == 0)
  1177. {
  1178. OnRun();
  1179. KSkill * pSkill = (KSkill*)GetActiveSkill();
  1180. if (!pSkill) 
  1181.             return ;
  1182.         if (m_Doing == do_stand || (DWORD)m_nCurrentMeleeTime > pSkill->GetMissleGenerateTime(0)) 
  1183. {
  1184. m_SpecialSkillStep ++;
  1185. m_nCurrentMeleeTime = 0;
  1186. DoRunAttack();
  1187. }
  1188. else
  1189. m_nCurrentMeleeTime ++;
  1190. m_ProcessAI = 0;
  1191. }
  1192. else if (m_SpecialSkillStep == 1)
  1193. {
  1194. if (WaitForFrame() &&m_Frames.nTotalFrame != 0)
  1195. {
  1196. DoStand();
  1197. m_ProcessAI = 1;
  1198. }
  1199. else if (IsReachFrame(ATTACKACTION_EFFECT_PERCENT))
  1200. {
  1201. KSkill * pSkill = (KSkill*)GetActiveSkill();
  1202. if (!pSkill) 
  1203.                 return ;
  1204.             int nCurPhySkillId = pSkill->GetChildSkillId();//GetCurActiveWeaponSkill();
  1205. if (nCurPhySkillId > 0)
  1206. {
  1207. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(nCurPhySkillId, pSkill->m_ulLevel, SKILL_SS_Missles);
  1208. if (pOrdinSkill)
  1209.                 {
  1210.     pOrdinSkill->Cast(m_Index, m_SkillParam1, m_SkillParam2);
  1211.                 }
  1212. }
  1213. DoStand();
  1214. m_ProcessAI = 1;
  1215. m_SpecialSkillStep = 0;
  1216. }
  1217. #ifndef _SERVER
  1218. m_DataRes.SetBlur(FALSE);
  1219. #endif
  1220. }
  1221. else
  1222. {
  1223. #ifndef _SERVER
  1224. m_DataRes.SetBlur(FALSE);
  1225. #endif
  1226. DoStand();
  1227. m_ProcessAI = 1;
  1228. m_SpecialSkillStep = 0;
  1229. }
  1230. }
  1231. BOOL KNpc::DoJumpAttack()
  1232. {
  1233. m_ProcessAI = 0;
  1234. switch(m_SpecialSkillStep)
  1235. {
  1236. case 0:
  1237. DoJump();
  1238. #ifndef _SERVER
  1239. m_DataRes.SetBlur(TRUE);
  1240. m_ClientDoing = cdo_jump;
  1241. #endif
  1242. m_Doing = do_jumpattack;
  1243. break;
  1244. case 1:
  1245. #ifndef _SERVER
  1246. if (g_Random(2))
  1247. m_ClientDoing = cdo_attack;
  1248. else
  1249. m_ClientDoing = cdo_attack1;
  1250. int x, y, tx, ty;
  1251. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &x, &y);
  1252. if (m_SkillParam1 == -1)
  1253. {
  1254. Npc[m_SkillParam2].GetMpsPos(&tx, &ty);
  1255. }
  1256. else
  1257. {
  1258. tx = m_SkillParam1;
  1259. ty = m_SkillParam2;
  1260. }
  1261. m_Dir = g_GetDirIndex(x, y, tx, ty);
  1262. #endif
  1263. m_Frames.nTotalFrame = m_AttackFrame * 100 / (100 + m_CurrentAttackSpeed);
  1264. m_Frames.nCurrentFrame = 0;
  1265. m_Doing = do_jumpattack;
  1266. break;
  1267. case 2:
  1268. case 3:
  1269. #ifndef _SERVER
  1270. m_DataRes.SetBlur(FALSE);
  1271. #endif
  1272. DoStand();
  1273. m_ProcessAI = 1;
  1274. m_SpecialSkillStep = 0;
  1275. return FALSE;
  1276. break;
  1277. }
  1278. m_Frames.nCurrentFrame = 0;
  1279. return TRUE;
  1280. }
  1281. BOOL KNpc::OnJumpAttack()
  1282. {
  1283. if (m_SpecialSkillStep == 0)
  1284. {
  1285. if (!OnJump())
  1286. {
  1287. m_SpecialSkillStep ++;
  1288. m_nCurrentMeleeTime = 0;
  1289. DoJumpAttack();
  1290. }
  1291. m_ProcessAI = 0;
  1292. }
  1293. else if (m_SpecialSkillStep == 1)
  1294. {
  1295. #ifndef _SERVER
  1296. m_DataRes.SetBlur(FALSE);
  1297. #endif
  1298. if (WaitForFrame() &&m_Frames.nTotalFrame != 0)
  1299. {
  1300. DoStand();
  1301. m_ProcessAI = 1;
  1302. }
  1303. else if (IsReachFrame(ATTACKACTION_EFFECT_PERCENT))
  1304. {
  1305. KSkill * pSkill =(KSkill*) GetActiveSkill();
  1306. if (!pSkill) 
  1307.                 return FALSE;
  1308.             int nCurPhySkillId = pSkill->GetChildSkillId();//GetCurActiveWeaponSkill();
  1309. if (nCurPhySkillId > 0)
  1310. {
  1311. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(nCurPhySkillId, pSkill->m_ulLevel, SKILL_SS_Missles);
  1312. if (pOrdinSkill)
  1313.                 {
  1314. pOrdinSkill->Cast(m_Index, m_SkillParam1, m_SkillParam2);
  1315.                 }
  1316. }
  1317. DoStand();
  1318. m_ProcessAI = 1;
  1319. m_SpecialSkillStep = 0;
  1320. }
  1321. }
  1322. else
  1323. {
  1324. #ifndef _SERVER
  1325. m_DataRes.SetBlur(FALSE);
  1326. #endif
  1327. DoStand();
  1328. m_ProcessAI = 1;
  1329. m_SpecialSkillStep = 0;
  1330. return FALSE;
  1331. }
  1332. return TRUE;
  1333. }
  1334. BOOL KNpc::CheckHitTarget(int nAR, int nDf, int nIngore/* = 0*/)
  1335. {
  1336. int nDefense = nDf * (100 - nIngore) / 100;
  1337. int nPercent = 0;
  1338. //Question nAr+ nDefense  == 0 ,error!so.....,must modify
  1339. if ((nAR + nDefense) == 0) 
  1340. nPercent = 50;
  1341. else
  1342. nPercent = nAR * 100 / (nAR + nDefense);
  1343. if (nPercent > MAX_HIT_PERCENT)
  1344. nPercent = MAX_HIT_PERCENT;
  1345. if (nPercent < MIN_HIT_PERCENT)
  1346. nPercent = MIN_HIT_PERCENT;
  1347. BOOL bRet = g_RandPercent(nPercent);
  1348. g_DebugLog("[数值]AttackRating %d : Defense %d: RandomPercent (%d, %d)", nAR, nDf, nPercent, bRet);
  1349. return bRet;
  1350. }
  1351. void KNpc::GetNpcCopyFromTemplate(int nNpcTemplateId, int nLevel)
  1352. {
  1353. if (nNpcTemplateId < 0 || nLevel < 1 ) 
  1354. return ;
  1355. if (g_pNpcTemplate[nNpcTemplateId][nLevel]) //数据有效则拷贝,否则重新生成
  1356. LoadDataFromTemplate(nNpcTemplateId, nLevel);
  1357. else
  1358. {
  1359. if (!g_pNpcTemplate[nNpcTemplateId][0])
  1360. {
  1361. g_pNpcTemplate[nNpcTemplateId][0] = new KNpcTemplate;
  1362. g_pNpcTemplate[nNpcTemplateId][0]->InitNpcBaseData(nNpcTemplateId);
  1363. g_pNpcTemplate[nNpcTemplateId][0]->m_NpcSettingIdx = nNpcTemplateId;
  1364. g_pNpcTemplate[nNpcTemplateId][0]->m_bHaveLoadedFromTemplate = TRUE;
  1365. }
  1366. KLuaScript * pLevelScript = NULL;
  1367. #ifdef _SERVER
  1368. pLevelScript = (KLuaScript*)g_GetScript(
  1369. g_pNpcTemplate[nNpcTemplateId][0]->m_dwLevelSettingScript
  1370. );
  1371. if (pLevelScript == NULL)
  1372. pLevelScript = g_pNpcLevelScript;
  1373. #else
  1374. KLuaScript LevelScript;
  1375. if (!g_pNpcTemplate[nNpcTemplateId][0]->m_szLevelSettingScript[0])
  1376. pLevelScript = g_pNpcLevelScript;
  1377. else
  1378. {
  1379. LevelScript.Init();
  1380. if (!LevelScript.Load(g_pNpcTemplate[nNpcTemplateId][0]->m_szLevelSettingScript))
  1381. {
  1382. g_DebugLog ("[error]致命错误,无法正确读取%s", g_pNpcTemplate[nNpcTemplateId][0]->m_szLevelSettingScript);
  1383. _ASSERT(0);
  1384. pLevelScript = g_pNpcLevelScript;
  1385. }
  1386. else
  1387. pLevelScript = &LevelScript;
  1388. }
  1389. #endif
  1390. g_pNpcTemplate[nNpcTemplateId][nLevel] = new KNpcTemplate;
  1391. *g_pNpcTemplate[nNpcTemplateId][nLevel] = *g_pNpcTemplate[nNpcTemplateId][0];
  1392. g_pNpcTemplate[nNpcTemplateId][nLevel]->m_nLevel = nLevel;
  1393. g_pNpcTemplate[nNpcTemplateId][nLevel]->InitNpcLevelData(&g_NpcKindFile, nNpcTemplateId, pLevelScript, nLevel);
  1394. g_pNpcTemplate[nNpcTemplateId][nLevel]->m_bHaveLoadedFromTemplate = TRUE;
  1395. LoadDataFromTemplate(nNpcTemplateId,nLevel);
  1396. }
  1397. }
  1398. void KNpc::LoadDataFromTemplate(int nNpcTemplateId, int nLevel)
  1399. {
  1400. if (nNpcTemplateId < 0 )
  1401. {
  1402. g_DebugLog("载入Npc%d模板请求非法!", nNpcTemplateId);
  1403. return ;
  1404. }
  1405. KNpcTemplate * pNpcTemp = g_pNpcTemplate[nNpcTemplateId][nLevel];
  1406. strcpy(Name,pNpcTemp->Name);
  1407. m_Kind = pNpcTemp->m_Kind;
  1408. m_Camp = pNpcTemp->m_Camp;
  1409. m_Series = pNpcTemp->m_Series;
  1410. m_HeadImage = pNpcTemp->m_HeadImage;
  1411. m_bClientOnly = pNpcTemp->m_bClientOnly;
  1412. m_CorpseSettingIdx = pNpcTemp->m_CorpseSettingIdx;
  1413. m_DeathFrame = pNpcTemp->m_DeathFrame;
  1414. m_WalkFrame = pNpcTemp->m_WalkFrame;
  1415. m_RunFrame = pNpcTemp->m_RunFrame;
  1416. m_HurtFrame = pNpcTemp->m_HurtFrame;
  1417. m_WalkSpeed = pNpcTemp->m_WalkSpeed;
  1418. m_AttackFrame = pNpcTemp->m_AttackFrame;
  1419. m_CastFrame = pNpcTemp->m_CastFrame;
  1420. m_RunSpeed = pNpcTemp->m_RunSpeed;
  1421. m_StandFrame =  pNpcTemp->m_StandFrame;
  1422. m_StandFrame1 = pNpcTemp->m_StandFrame1;
  1423. m_NpcSettingIdx = pNpcTemp->m_NpcSettingIdx;
  1424. m_nStature = pNpcTemp->m_nStature;
  1425. #ifdef _SERVER
  1426. m_Treasure = pNpcTemp->m_Treasure;
  1427. m_SkillList = pNpcTemp->m_SkillList;
  1428. m_AiMode = pNpcTemp->m_AiMode;
  1429. m_AiAddLifeTime = 0;
  1430. m_pDropRate = pNpcTemp->m_pItemDropRate;
  1431. if (!m_AiSkillRadiusLoadFlag)
  1432. {
  1433. m_AiSkillRadiusLoadFlag = 1;
  1434. int i;
  1435. for (i = 0; i < MAX_AI_PARAM - 1; i ++)
  1436. m_AiParam[i] = pNpcTemp->m_AiParam[i];
  1437. int nMaxRadius = 0, nTempRadius;
  1438. KSkill *pSkill;
  1439. for (i = 1; i < MAX_NPC_USE_SKILL + 1; i++)
  1440. {
  1441. pSkill = (KSkill*)g_SkillManager.GetSkill(m_SkillList.m_Skills[i].SkillId, m_SkillList.m_Skills[i].SkillLevel);
  1442. if (!pSkill)
  1443. continue;
  1444. nTempRadius = pSkill->GetAttackRadius();
  1445. if (nTempRadius > nMaxRadius)
  1446. nMaxRadius = nTempRadius;
  1447. }
  1448. m_AiParam[MAX_AI_PARAM - 1] = nMaxRadius * nMaxRadius;
  1449. }
  1450. m_FireResistMax = pNpcTemp->m_FireResistMax;
  1451. m_ColdResistMax = pNpcTemp->m_ColdResistMax;
  1452. m_LightResistMax = pNpcTemp->m_LightResistMax;
  1453. m_PoisonResistMax = pNpcTemp->m_PoisonResistMax;
  1454. m_PhysicsResistMax = pNpcTemp->m_PhysicsResistMax;
  1455. m_ActiveRadius = pNpcTemp->m_ActiveRadius;
  1456. m_VisionRadius = pNpcTemp->m_VisionRadius;
  1457. m_AIMAXTime = pNpcTemp->m_AIMAXTime;
  1458. m_HitRecover = pNpcTemp->m_HitRecover;
  1459. m_ReviveFrame = pNpcTemp->m_ReviveFrame;
  1460. m_Experience = pNpcTemp->m_Experience;
  1461. m_CurrentExperience = m_Experience;
  1462. m_LifeMax = pNpcTemp->m_LifeMax;
  1463. m_LifeReplenish = pNpcTemp->m_LifeReplenish;
  1464. m_AttackRating = pNpcTemp->m_AttackRating;
  1465. m_Defend = pNpcTemp->m_Defend;
  1466. m_PhysicsDamage = pNpcTemp->m_PhysicsDamage;
  1467. m_RedLum = pNpcTemp->m_RedLum;
  1468. m_GreenLum = pNpcTemp->m_GreenLum;
  1469. m_BlueLum = pNpcTemp->m_BlueLum;
  1470. m_FireResist = pNpcTemp->m_FireResist;
  1471. m_ColdResist = pNpcTemp->m_ColdResist;
  1472. m_LightResist = pNpcTemp->m_LightResist;
  1473. m_PoisonResist = pNpcTemp->m_PoisonResist;
  1474. m_PhysicsResist = pNpcTemp->m_PhysicsResist;
  1475. #else
  1476. m_LifeMax = pNpcTemp->m_LifeMax;
  1477. m_ArmorType = pNpcTemp->m_ArmorType;
  1478. m_HelmType = pNpcTemp->m_HelmType;
  1479. m_WeaponType = pNpcTemp->m_WeaponType;
  1480. m_HorseType = pNpcTemp->m_HorseType;
  1481. m_bRideHorse = pNpcTemp->m_bRideHorse;
  1482. strcpy(ActionScript, pNpcTemp->ActionScript);
  1483. #endif
  1484. /*for (int j  = 0; j < 4; j ++)
  1485. m_SkillList.Add()
  1486. int m_nSkillID[4];
  1487. int m_nSkillLevel[4];*/
  1488. //BOOL m_bHaveLoadedFromTemplate;
  1489. //int m_nNpcTemplateId;
  1490. m_Level = pNpcTemp->m_nLevel;
  1491. RestoreNpcBaseInfo();
  1492. }
  1493. //-----------------------------------------------------------------------
  1494. // 功能:设定物理攻击的最大最小值 not end 需要考虑调用的地方
  1495. //-----------------------------------------------------------------------
  1496. void KNpc::SetPhysicsDamage(int nMinDamage, int nMaxDamage)
  1497. {
  1498. m_PhysicsDamage.nValue[0] = nMinDamage;
  1499. m_PhysicsDamage.nValue[2] = nMaxDamage;
  1500. }
  1501. //-----------------------------------------------------------------------
  1502. // 功能:设定攻击命中率
  1503. //-----------------------------------------------------------------------
  1504. void KNpc::SetBaseAttackRating(int nAttackRating)
  1505. {
  1506. m_AttackRating = nAttackRating;
  1507. // 此处还需要加上装备、技能的影响,计算出当前值
  1508. m_CurrentAttackRating = m_AttackRating;
  1509. }
  1510. //-----------------------------------------------------------------------
  1511. // 功能:设定防御力
  1512. //-----------------------------------------------------------------------
  1513. void KNpc::SetBaseDefence(int nDefence)
  1514. {
  1515. m_Defend = nDefence;
  1516. // 此处还需要加上装备、技能的影响,计算出当前值
  1517. m_CurrentDefend = m_Defend;
  1518. }
  1519. /*
  1520. //-----------------------------------------------------------------------
  1521. // 功能:设定行走速度
  1522. //-----------------------------------------------------------------------
  1523. void KNpc::SetBaseWalkSpeed(int nSpeed)
  1524. {
  1525. m_WalkSpeed = nSpeed;
  1526. // 此处还需要加上装备、技能的影响,计算出当前值 (not end)
  1527. m_CurrentWalkSpeed = m_WalkSpeed;
  1528. }
  1529. */
  1530. /*
  1531. //-----------------------------------------------------------------------
  1532. // 功能:设定跑步速度
  1533. //-----------------------------------------------------------------------
  1534. void KNpc::SetBaseRunSpeed(int nSpeed)
  1535. {
  1536. m_RunSpeed = nSpeed;
  1537. // 此处还需要加上装备、技能的影响,计算出当前值 (not end)
  1538. m_CurrentRunSpeed = m_RunSpeed;
  1539. }
  1540. */
  1541. #ifdef _SERVER
  1542. void KNpc::DeathPunish(int nMode, int nBelongPlayer)
  1543. {
  1544. #define LOSE_EXP_SCALE 10
  1545. if (IsPlayer())
  1546. {
  1547. // 被npc kill
  1548. if (nMode == enumDEATH_MODE_NPC_KILL)
  1549. {
  1550. // 经验减少
  1551. if (Player[m_nPlayerIdx].m_nExp > 0)
  1552. {
  1553. int nSubExp;
  1554. if (m_Level <= 10)
  1555. nSubExp = (PlayerSet.m_cLevelAdd.GetLevelExp(m_Level) * 2) / 100;
  1556. else
  1557. nSubExp = (PlayerSet.m_cLevelAdd.GetLevelExp(m_Level) * 4) / 100;
  1558. if (Player[m_nPlayerIdx].m_nExp >= nSubExp)
  1559. Player[m_nPlayerIdx].DirectAddExp( -nSubExp );
  1560. else
  1561. Player[m_nPlayerIdx].DirectAddExp( -Player[m_nPlayerIdx].m_nExp );
  1562. }
  1563. // 钱减少
  1564. int nMoney = Player[m_nPlayerIdx].m_ItemList.GetEquipmentMoney() / 2;
  1565. if (nMoney > 0)
  1566. {
  1567. Player[m_nPlayerIdx].m_ItemList.CostMoney(nMoney);
  1568. // 损失金钱消息
  1569. SHOW_MSG_SYNC sMsg;
  1570. sMsg.ProtocolType = s2c_msgshow;
  1571. sMsg.m_wMsgID = enumMSG_ID_DEC_MONEY;
  1572. sMsg.m_lpBuf = (void *)(nMoney);
  1573. sMsg.m_wLength = sizeof(SHOW_MSG_SYNC) - 1;
  1574. g_pServer->PackDataToClient(Player[m_nPlayerIdx].m_nNetConnectIdx, &sMsg, sMsg.m_wLength + 1);
  1575. sMsg.m_lpBuf = 0;
  1576. if (nMoney / 2 > 0)
  1577. PlayerDeadCreateMoneyObj(nMoney / 2);
  1578. }
  1579. }
  1580. // 切磋,没有惩罚
  1581. else if (nMode == enumDEATH_MODE_PLAYER_NO_PUNISH)
  1582. {
  1583. return;
  1584. }
  1585. else if (nMode == enumDEATH_MODE_PKBATTLE_PUNISH)
  1586. {
  1587. return;
  1588. }
  1589. // PK致死,按PK值计算惩罚
  1590. else //if (nMode == enumDEATH_MODE_PLAYER_PUNISH)
  1591. {
  1592. int nPKValue;
  1593. nPKValue = Player[this->m_nPlayerIdx].m_cPK.GetPKValue();
  1594. if (nPKValue < 0)
  1595. nPKValue = 0;
  1596. if (nPKValue > MAX_DEATH_PUNISH_PK_VALUE)
  1597. nPKValue = MAX_DEATH_PUNISH_PK_VALUE;
  1598. // 经验减少
  1599. int nLevelExp = PlayerSet.m_cLevelAdd.GetLevelExp(m_Level);
  1600. Player[m_nPlayerIdx].DirectAddExp( -(nLevelExp * PlayerSet.m_sPKPunishParam[nPKValue].m_nExp / 100) );
  1601. // 钱减少
  1602. int nMoney = Player[m_nPlayerIdx].m_ItemList.GetEquipmentMoney() * PlayerSet.m_sPKPunishParam[nPKValue].m_nMoney / 100;
  1603. if (nMoney > 0)
  1604. {
  1605. Player[m_nPlayerIdx].m_ItemList.CostMoney(nMoney);
  1606. // 损失金钱消息
  1607. SHOW_MSG_SYNC sMsg;
  1608. sMsg.ProtocolType = s2c_msgshow;
  1609. sMsg.m_wMsgID = enumMSG_ID_DEC_MONEY;
  1610. sMsg.m_lpBuf = (void *)(nMoney);
  1611. sMsg.m_wLength = sizeof(SHOW_MSG_SYNC) - 1;
  1612. g_pServer->PackDataToClient(Player[m_nPlayerIdx].m_nNetConnectIdx, &sMsg, sMsg.m_wLength + 1);
  1613. sMsg.m_lpBuf = 0;
  1614. if (nMoney / 2 > 0)
  1615. PlayerDeadCreateMoneyObj(nMoney / 2);
  1616. }
  1617. // 丢失物品
  1618. Player[m_nPlayerIdx].m_ItemList.AutoLoseItemFromEquipmentRoom(PlayerSet.m_sPKPunishParam[nPKValue].m_nItem);
  1619. // 丢失穿在身上的装备
  1620. if (g_Random(100) < PlayerSet.m_sPKPunishParam[nPKValue].m_nEquip)
  1621. {
  1622. Player[m_nPlayerIdx].m_ItemList.AutoLoseEquip();
  1623. }
  1624. Player[m_nPlayerIdx].m_cPK.AddPKValue(NpcSet.m_nBeKilledAddPKValue);
  1625. if (m_nLastDamageIdx)
  1626. {
  1627. if (Npc[m_nLastDamageIdx].IsPlayer())
  1628. {
  1629. KPlayerChat::MakeEnemy(Name, Npc[m_nLastDamageIdx].Name);
  1630. }
  1631. }
  1632. }
  1633. }
  1634. // else if (m_nLastDamageIdx && Npc[m_nLastDamageIdx].IsPlayer())
  1635. else if (nBelongPlayer > 0 && m_pDropRate)
  1636. {
  1637. for (int i = 0; i < m_CurrentTreasure; i++)
  1638. {
  1639. if (g_RandPercent(m_pDropRate->nMoneyRate))
  1640. {
  1641. LoseMoney(nBelongPlayer);
  1642. }
  1643. else
  1644. {
  1645. LoseSingleItem(nBelongPlayer);
  1646. }
  1647. }
  1648. }
  1649. }
  1650. // 玩家死的时候掉出来的钱生成一个object
  1651. void KNpc::PlayerDeadCreateMoneyObj(int nMoneyNum)
  1652. {
  1653. int nX, nY;
  1654. POINT ptLocal;
  1655. KMapPos Pos;
  1656. GetMpsPos(&nX, &nY);
  1657. ptLocal.x = nX;
  1658. ptLocal.y = nY;
  1659. SubWorld[m_SubWorldIndex].GetFreeObjPos(ptLocal);
  1660. Pos.nSubWorld = m_SubWorldIndex;
  1661. SubWorld[m_SubWorldIndex].Mps2Map(ptLocal.x, ptLocal.y, 
  1662. &Pos.nRegion, &Pos.nMapX, &Pos.nMapY, 
  1663. &Pos.nOffX, &Pos.nOffY);
  1664. int nObjIdx = ObjSet.AddMoneyObj(Pos, nMoneyNum);
  1665. if (nObjIdx > 0 && nObjIdx < MAX_OBJECT)
  1666. {
  1667. Object[nObjIdx].SetItemBelong(-1);
  1668. }
  1669. }
  1670. void KNpc::LoseMoney(int nBelongPlayer)
  1671. {
  1672. int nX, nY;
  1673. POINT ptLocal;
  1674. KMapPos Pos;
  1675. int nMoney = m_CurrentExperience * m_pDropRate->nMoneyScale / 100;
  1676. if (nMoney <= 0)
  1677. return;
  1678. GetMpsPos(&nX, &nY);
  1679. ptLocal.x = nX;
  1680. ptLocal.y = nY;
  1681. SubWorld[m_SubWorldIndex].GetFreeObjPos(ptLocal);
  1682. Pos.nSubWorld = m_SubWorldIndex;
  1683. SubWorld[m_SubWorldIndex].Mps2Map(ptLocal.x, ptLocal.y, 
  1684. &Pos.nRegion, &Pos.nMapX, &Pos.nMapY, 
  1685. &Pos.nOffX, &Pos.nOffY);
  1686. int nObjIdx = ObjSet.AddMoneyObj(Pos, nMoney);
  1687. if (nObjIdx > 0 && nObjIdx < MAX_OBJECT)
  1688. {
  1689. if (nBelongPlayer > 0)
  1690. Object[nObjIdx].SetItemBelong(nBelongPlayer);
  1691. else
  1692. Object[nObjIdx].SetItemBelong(-1);
  1693. }
  1694. }
  1695. void KNpc::LoseSingleItem(int nBelongPlayer)
  1696. {
  1697. if (!m_pDropRate)
  1698. return;
  1699. if (m_pDropRate->nMaxItemLevelScale <= 0 || m_pDropRate->nMinItemLevelScale <= 0)
  1700. return;
  1701. int nRand = g_Random(m_pDropRate->nMaxRandRate);
  1702. int nCheckRand = 0; // 累加概率,确认是否落在区间内
  1703. int i;
  1704. for (i = 0; i < m_pDropRate->nCount; i++)
  1705. {
  1706. if (nRand >= nCheckRand && nRand < nCheckRand + m_pDropRate->pItemParam[i].nRate)
  1707. {
  1708. break;
  1709. }
  1710. nCheckRand += m_pDropRate->pItemParam[i].nRate;
  1711. }
  1712. if (i == m_pDropRate->nCount)
  1713. return;
  1714. int nGenre, nSeries, nLuck, nDetail, nParticular, nLevel, pnMagicLevel[6];
  1715. nGenre = m_pDropRate->pItemParam[i].nGenre;
  1716. nDetail = m_pDropRate->pItemParam[i].nDetailType;
  1717. nParticular = m_pDropRate->pItemParam[i].nParticulType;
  1718. nSeries = m_Series;
  1719. nLuck = Player[nBelongPlayer].m_nCurLucky;
  1720. int nMaxLevel = m_Level / m_pDropRate->nMaxItemLevelScale;
  1721. int nMinLevel = m_Level / m_pDropRate->nMinItemLevelScale;
  1722. if (nMaxLevel > m_pDropRate->nMaxItemLevel)
  1723. nMaxLevel = m_pDropRate->nMaxItemLevel;
  1724. if (nMinLevel < m_pDropRate->nMinItemLevel)
  1725. nMinLevel = m_pDropRate->nMinItemLevel;
  1726. if (nMaxLevel < nMinLevel)
  1727. {
  1728. int nTemp = nMinLevel;
  1729. nMinLevel = nMaxLevel;
  1730. nMaxLevel = nTemp;
  1731. }
  1732. nLevel = g_Random(nMaxLevel - nMinLevel) + nMinLevel;
  1733. BOOL bSkip = FALSE;
  1734. for (int j = 0; j < 6; j++)
  1735. {
  1736. if (!bSkip)
  1737. {
  1738.  if (g_Random(m_pDropRate->nMagicRate))
  1739.  {
  1740.  pnMagicLevel[j] = nLevel;
  1741.  }
  1742.  else
  1743.  {
  1744.  pnMagicLevel[j] = 0;
  1745.  bSkip = TRUE;
  1746.  }
  1747. }
  1748. else
  1749. {
  1750. pnMagicLevel[j] = 0;
  1751. }
  1752. }
  1753. int nIdx = ItemSet.Add(nGenre, nSeries, nLevel, nLuck, nDetail, nParticular, pnMagicLevel, g_SubWorldSet.GetGameVersion());
  1754. if (nIdx <= 0)
  1755. return;
  1756. int nX, nY;
  1757. POINT ptLocal;
  1758. KMapPos Pos;
  1759. GetMpsPos(&nX, &nY);
  1760. ptLocal.x = nX;
  1761. ptLocal.y = nY;
  1762. SubWorld[m_SubWorldIndex].GetFreeObjPos(ptLocal);
  1763. Pos.nSubWorld = m_SubWorldIndex;
  1764. SubWorld[m_SubWorldIndex].Mps2Map(ptLocal.x, ptLocal.y, 
  1765. &Pos.nRegion, &Pos.nMapX, &Pos.nMapY, 
  1766. &Pos.nOffX, &Pos.nOffY);
  1767. int nObj;
  1768. KObjItemInfo sInfo;
  1769. sInfo.m_nItemID = nIdx;
  1770. sInfo.m_nItemWidth = Item[nIdx].GetWidth();
  1771. sInfo.m_nItemHeight = Item[nIdx].GetHeight();
  1772. sInfo.m_nMoneyNum = 0;
  1773. strcpy(sInfo.m_szName, Item[nIdx].GetName());
  1774. sInfo.m_nColorID = 0;
  1775. sInfo.m_nMovieFlag = 1;
  1776. sInfo.m_nSoundFlag = 1;
  1777. nObj = ObjSet.Add(Item[nIdx].GetObjIdx(), Pos, sInfo);
  1778. if (nObj == -1)
  1779. {
  1780. ItemSet.Remove(nIdx);
  1781. }
  1782. else
  1783. {
  1784. if (nBelongPlayer > 0)
  1785. Object[nObj].SetItemBelong(nBelongPlayer);
  1786. else
  1787. Object[nObj].SetItemBelong(-1);
  1788. }
  1789. }
  1790. void KNpc::Revive()
  1791. {
  1792. //RestoreLiveData();
  1793. RestoreNpcBaseInfo();
  1794. int nRegion, nMapX, nMapY, nOffX, nOffY;
  1795. SubWorld[m_SubWorldIndex].Mps2Map(m_OriginX, m_OriginY, &nRegion, &nMapX, &nMapY, &nOffX, &nOffY);
  1796. m_RegionIndex = nRegion;
  1797. m_MapX = nMapX;
  1798. m_MapY = nMapY;
  1799. m_MapZ = 0;
  1800. m_OffX = nOffX;
  1801. m_OffY = nOffY;
  1802. if (m_RegionIndex < 0)
  1803. return;
  1804. SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].AddRef(m_MapX, m_MapY, obj_npc);
  1805. #ifdef _SERVER
  1806. //SubWorld[m_SubWorldIndex].m_WorldMessage.Send(GWM_NPC_CHANGE_REGION, VOID_REGION, nRegion, m_Index);
  1807. SubWorld[m_SubWorldIndex].NpcChangeRegion(VOID_REGION, nRegion, m_Index); // spe 03/06/28
  1808. #else
  1809. SubWorld[0].NpcChangeRegion(VOID_REGION, SubWorld[0].m_Region[nRegion].m_RegionID, m_Index);
  1810. #endif
  1811. DoStand();
  1812. m_ProcessAI = 1;
  1813. m_ProcessState = 1;
  1814. m_AiAddLifeTime = 0;
  1815. #ifdef _SERVER
  1816. this->m_cGold.RandChangeGold();
  1817. #endif
  1818. }
  1819. void KNpc::RestoreLiveData()
  1820. {
  1821. }
  1822. #endif
  1823. #ifdef _SERVER
  1824. // 向周围九屏广播
  1825. void KNpc::SendDataToNearRegion(void* pBuffer, DWORD dwSize)
  1826. {
  1827. _ASSERT(m_RegionIndex >= 0);
  1828. if (m_RegionIndex < 0)
  1829. return;
  1830. POINT POff[8] = 
  1831. {
  1832. {0, 32},
  1833. {-16, 32},
  1834. {-16, 0},
  1835. {-16, -32},
  1836. {0, -32},
  1837. {16, -32},
  1838. {16, 0},
  1839. {16, 32},
  1840. };
  1841. int nMaxCount = MAX_BROADCAST_COUNT;
  1842. SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].BroadCast(pBuffer, dwSize, nMaxCount, m_MapX, m_MapY);
  1843. for (int i= 0; i < 8; i++)
  1844. {
  1845. if (SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].m_nConnectRegion[i] < 0)
  1846. continue;
  1847. SubWorld[m_SubWorldIndex].m_Region[SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].m_nConnectRegion[i]].BroadCast(pBuffer, dwSize, nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1848. }
  1849. }
  1850. #endif
  1851. #ifdef _SERVER
  1852. //-----------------------------------------------------------------------------
  1853. // 功能:死亡时候计算PK值
  1854. //-----------------------------------------------------------------------------
  1855. int KNpc::DeathCalcPKValue(int nKiller)
  1856. {
  1857. // 出错
  1858. if (nKiller <= 0 || nKiller >= MAX_NPC)
  1859. return enumDEATH_MODE_NPC_KILL;
  1860. if (m_nCurPKPunishState == enumDEATH_MODE_PKBATTLE_PUNISH)
  1861. return enumDEATH_MODE_PKBATTLE_PUNISH;
  1862. // 玩家之间,城镇内
  1863. if (this->m_Kind != kind_player || Npc[nKiller].m_Kind != kind_player || !m_FightMode)
  1864. return enumDEATH_MODE_NPC_KILL;
  1865. // 如果是切磋,不计算
  1866. if (Player[m_nPlayerIdx].m_cPK.GetExercisePKAim() == Npc[nKiller].m_nPlayerIdx)
  1867. return enumDEATH_MODE_PLAYER_NO_PUNISH;
  1868. // 如果是仇杀
  1869. if (Player[m_nPlayerIdx].m_cPK.GetEnmityPKState() == enumPK_ENMITY_STATE_PKING &&
  1870. Player[m_nPlayerIdx].m_cPK.GetEnmityPKAim() == Npc[nKiller].m_nPlayerIdx)
  1871. {
  1872. if (Player[Npc[nKiller].m_nPlayerIdx].m_cPK.IsEnmityPKLauncher())
  1873. Player[Npc[nKiller].m_nPlayerIdx].m_cPK.AddPKValue(NpcSet.m_nEnmityAddPKValue);
  1874. return enumDEATH_MODE_PLAYER_PUNISH;
  1875. }
  1876. // 如果等级差过大,算PK新手(HLv:LLv >= 3:2)
  1877. if (m_Level <= 50 && Npc[nKiller].m_Level * 2 >= m_Level * 3)
  1878. {
  1879. if (!Player[m_nPlayerIdx].m_cPK.GetNormalPKState())
  1880. {
  1881. if (Npc[nKiller].m_CurrentCamp == camp_free)
  1882. Player[Npc[nKiller].m_nPlayerIdx].m_cPK.AddPKValue(NpcSet.m_nKillerPKFactionAddPKValue);
  1883. else
  1884. Player[Npc[nKiller].m_nPlayerIdx].m_cPK.AddPKValue(NpcSet.m_nFactionPKFactionAddPKValue);
  1885. }
  1886. return enumDEATH_MODE_PLAYER_PUNISH;
  1887. }
  1888. return enumDEATH_MODE_PLAYER_PUNISH;
  1889. }
  1890. #endif
  1891. #ifdef _SERVER
  1892. //-----------------------------------------------------------------------------
  1893. // 功能:查找周围9个Region中是否有指定的 player
  1894. //-----------------------------------------------------------------------------
  1895. BOOL KNpc::CheckPlayerAround(int nPlayerIdx)
  1896. {
  1897. if (nPlayerIdx <= 0 || m_RegionIndex < 0)
  1898. return FALSE;
  1899. if (SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].CheckPlayerIn(nPlayerIdx))
  1900. return TRUE;
  1901. int nRegionNo;
  1902. for (int i = 0; i < 8; i++)
  1903. {
  1904. nRegionNo = SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].m_nConnectRegion[i];
  1905. if ( nRegionNo < 0)
  1906. continue;
  1907. if (SubWorld[m_SubWorldIndex].m_Region[nRegionNo].CheckPlayerIn(nPlayerIdx))
  1908. return TRUE;
  1909. }
  1910. return FALSE;
  1911. }
  1912. #endif
  1913. #ifndef _SERVER
  1914. //-------------------------------------------------------------------------
  1915. // 功能:设定头顶状态
  1916. //-------------------------------------------------------------------------
  1917. void KNpc::SetMenuState(int nState, char *lpszSentence, int nLength)
  1918. {
  1919. this->m_DataRes.SetMenuState(nState, lpszSentence, nLength);
  1920. }
  1921. #endif
  1922. #ifndef _SERVER
  1923. //-------------------------------------------------------------------------
  1924. // 功能:获得头顶状态
  1925. //-------------------------------------------------------------------------
  1926. int KNpc::GetMenuState()
  1927. {
  1928. return this->m_DataRes.GetMenuState();
  1929. }
  1930. #endif
  1931. #ifndef _SERVER
  1932. //-------------------------------------------------------------------------
  1933. // 功能:查找周围9个Region中是否有指定 ID 的 npc
  1934. //-------------------------------------------------------------------------
  1935. DWORD KNpc::SearchAroundID(DWORD dwID)
  1936. {
  1937. int nIdx, nRegionNo;
  1938. nIdx = SubWorld[0].m_Region[m_RegionIndex].SearchNpc(dwID);
  1939. if (nIdx)
  1940. return nIdx;
  1941. for (int i = 0; i < 8; i++)
  1942. {
  1943. nRegionNo = SubWorld[0].m_Region[m_RegionIndex].m_nConnectRegion[i];
  1944. if ( nRegionNo < 0)
  1945. continue;
  1946. nIdx = SubWorld[0].m_Region[nRegionNo].SearchNpc(dwID);
  1947. if (nIdx)
  1948. return nIdx;
  1949. }
  1950. return 0;
  1951. }
  1952. #endif
  1953. #ifndef _SERVER
  1954. //-------------------------------------------------------------------------
  1955. // 功能:设定特殊的只播放一遍的随身spr文件
  1956. //-------------------------------------------------------------------------
  1957. void KNpc::SetSpecialSpr(char *lpszSprName)
  1958. {
  1959. m_DataRes.SetSpecialSpr(lpszSprName);
  1960. }
  1961. #endif
  1962. #ifndef _SERVER
  1963. //-------------------------------------------------------------------------
  1964. // 功能:设定瞬间特效
  1965. //-------------------------------------------------------------------------
  1966. void KNpc::SetInstantSpr(int nNo)
  1967. {
  1968. char szName[FILE_NAME_LENGTH];
  1969. szName[0] = 0;
  1970. NpcSet.m_cInstantSpecial.GetSprName(nNo, szName, sizeof(szName));
  1971. if (szName[0])
  1972. this->SetSpecialSpr(szName);
  1973. }
  1974. #endif
  1975. #ifndef _SERVER
  1976. int KNpc::GetNormalNpcStandDir(int nFrame)
  1977. {
  1978. return m_DataRes.GetNormalNpcStandDir(nFrame);
  1979. }
  1980. #endif
  1981. #ifdef _SERVER
  1982. //重新更新角色状态信息数据
  1983. void KNpc::UpdateNpcStateInfo()
  1984. {
  1985. int i = 0;
  1986. memset(m_btStateInfo, 0 ,sizeof(BYTE) * MAX_NPC_RECORDER_STATE);
  1987. KStateNode *pNode = (KStateNode*)m_StateSkillList.GetTail();
  1988. if (m_ActiveAuraID)
  1989. {
  1990. int nLevel = m_SkillList.GetCurrentLevel(m_ActiveAuraID);
  1991. if (nLevel > 0)
  1992. {
  1993. int nSpecialID = 0;
  1994. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(m_ActiveAuraID, nLevel);
  1995. if (pOrdinSkill)
  1996.             {
  1997. if (nSpecialID = pOrdinSkill->GetStateSpecailId())
  1998. m_btStateInfo[i++] = nSpecialID;
  1999.             }
  2000. }
  2001. }
  2002. while ( pNode && i < MAX_NPC_RECORDER_STATE)
  2003. {
  2004. if (pNode->m_StateGraphics > 0)
  2005. m_btStateInfo[i++] = pNode->m_StateGraphics;
  2006. pNode = (KStateNode*)pNode->GetPrev();
  2007. }
  2008. }
  2009. //广播状态数据
  2010. void KNpc::BroadCastState()
  2011. {
  2012. if (m_RegionIndex < 0)
  2013. return;
  2014. NPC_SYNC_STATEINFO StateInfo;
  2015. StateInfo.ProtocolType = (BYTE)s2c_syncnpcstate;
  2016. StateInfo.m_ID = m_dwID;
  2017. int i;
  2018. for (i = 0; i < MAX_NPC_RECORDER_STATE; i++)
  2019. StateInfo.m_btStateInfo[i] = m_btStateInfo[i];
  2020. POINT POff[8] = 
  2021. {
  2022. {0, 32},
  2023. {-16, 32},
  2024. {-16, 0},
  2025. {-16, -32},
  2026. {0, -32},
  2027. {16, -32},
  2028. {16, 0},
  2029. {16, 32},
  2030. };
  2031. int nMaxCount = MAX_BROADCAST_COUNT;
  2032. CURREGION.BroadCast(&StateInfo, sizeof(NPC_SYNC_STATEINFO), nMaxCount, m_MapX, m_MapY);
  2033. for (i= 0; i < 8; i++)
  2034. {
  2035. if (CONREGIONIDX(i) == -1)
  2036. continue;
  2037. CONREGION(i).BroadCast(&StateInfo, sizeof(NPC_SYNC_STATEINFO), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  2038. }
  2039. }
  2040. #endif
  2041. #ifndef _SERVER
  2042. void KNpc::SetNpcState(BYTE* pNpcState)
  2043. {
  2044. ClearNpcState();
  2045. if (!pNpcState)
  2046. return ;
  2047. for (int i = 0; i < MAX_NPC_RECORDER_STATE; i++)
  2048. {
  2049. if (*(pNpcState + i) != 0)
  2050. {
  2051. KStateNode * pNewNode = new KStateNode;
  2052. pNewNode->m_StateGraphics = *(pNpcState + i);
  2053. m_StateSkillList.AddTail(pNewNode);
  2054. }
  2055. }
  2056. }
  2057. #endif
  2058. void KNpc::ClearNpcState()
  2059. {
  2060. KStateNode * pNode = (KStateNode*)m_StateSkillList.GetHead();
  2061. KStateNode * pTempNode = NULL;
  2062. while(pNode)
  2063. {
  2064. pTempNode = pNode;
  2065. pNode = (KStateNode*) pNode->GetNext();
  2066. pTempNode->Remove();
  2067. delete pTempNode;
  2068. }
  2069. return;
  2070. }
  2071. void KNpc::RestoreNpcBaseInfo()
  2072. {
  2073. m_CurrentCamp = m_Camp;
  2074. m_ActiveSkillID = 0;
  2075. m_ActiveAuraID = 0;
  2076. m_nPeopleIdx = 0;
  2077. m_nLastDamageIdx = 0;
  2078. m_nLastPoisonDamageIdx = 0;
  2079. m_nObjectIdx = 0;
  2080. m_CurrentLife = m_LifeMax;
  2081. m_CurrentLifeMax = m_LifeMax;
  2082. m_CurrentLifeReplenish = m_LifeReplenish;
  2083. m_CurrentMana = m_ManaMax;
  2084. m_CurrentManaMax = m_ManaMax;
  2085. m_CurrentManaReplenish = m_ManaReplenish;
  2086. m_CurrentStamina = m_StaminaMax;
  2087. m_CurrentStaminaMax = m_StaminaMax;
  2088. m_CurrentStaminaGain = m_StaminaGain;
  2089. m_CurrentStaminaLoss = m_StaminaLoss;
  2090. memset(&m_CurrentFireDamage, 0, sizeof(m_CurrentFireDamage));
  2091. memset(&m_CurrentColdDamage, 0, sizeof(m_CurrentColdDamage));
  2092. memset(&m_CurrentLightDamage, 0, sizeof(m_CurrentLightDamage));
  2093. memset(&m_CurrentPoisonDamage, 0, sizeof(m_CurrentPoisonDamage));
  2094. m_CurrentAttackRating = m_AttackRating;
  2095. m_CurrentDefend = m_Defend;
  2096. m_CurrentFireResist = m_FireResist;
  2097. m_CurrentColdResist = m_ColdResist;
  2098. m_CurrentPoisonResist = m_PoisonResist;
  2099. m_CurrentLightResist = m_LightResist;
  2100. m_CurrentPhysicsResist = m_PhysicsResist;
  2101. m_CurrentFireResistMax = m_FireResistMax;
  2102. m_CurrentColdResistMax = m_ColdResistMax;
  2103. m_CurrentPoisonResistMax = m_PoisonResistMax;
  2104. m_CurrentLightResistMax = m_LightResistMax;
  2105. m_CurrentPhysicsResistMax  = m_PhysicsResistMax;
  2106. m_CurrentWalkSpeed = m_WalkSpeed;
  2107. m_CurrentRunSpeed = m_RunSpeed;
  2108. m_CurrentAttackSpeed = m_AttackSpeed;
  2109. m_CurrentCastSpeed = m_CastSpeed;
  2110. m_CurrentVisionRadius = m_VisionRadius;
  2111. m_CurrentActiveRadius = m_ActiveRadius;
  2112. m_CurrentHitRecover = m_HitRecover;
  2113. m_CurrentTreasure = m_Treasure;
  2114. m_CurrentDamage2Mana = 0;
  2115. m_CurrentManaPerEnemy = 0;
  2116. m_CurrentLifeStolen = 0;
  2117. m_CurrentManaStolen = 0;
  2118. m_CurrentStaminaStolen = 0;
  2119. m_CurrentKnockBack = 0;
  2120. m_CurrentDeadlyStrike = 0;
  2121. m_CurrentBlindEnemy = 0;
  2122. m_CurrentPiercePercent = 0;
  2123. m_CurrentFreezeTimeReducePercent = 0;
  2124. m_CurrentPoisonTimeReducePercent = 0;
  2125. m_CurrentStunTimeReducePercent = 0;
  2126. m_CurrentFireEnhance = 0;
  2127. m_CurrentColdEnhance = 0;
  2128. m_CurrentPoisonEnhance = 0;
  2129. m_CurrentLightEnhance = 0;
  2130. m_CurrentRangeEnhance = 0;
  2131. m_CurrentHandEnhance = 0;
  2132. ZeroMemory(m_CurrentMeleeEnhance, sizeof(m_CurrentMeleeEnhance));
  2133. ClearStateSkillEffect();
  2134. ClearNormalState();
  2135. }
  2136. #ifndef _SERVER
  2137. void KNpc::DrawBorder()
  2138. {
  2139. if (m_Index <= 0)
  2140. return;
  2141. m_DataRes.DrawBorder();
  2142. }
  2143. int KNpc::DrawMenuState(int n)
  2144. {
  2145. if (m_Index <= 0)
  2146. return n;
  2147. return m_DataRes.DrawMenuState(n);
  2148. }
  2149. void KNpc::DrawBlood()
  2150. {
  2151. if (m_Kind != kind_normal)
  2152. return;
  2153. int nFontSize = 12;
  2154. // KRUShadow Blood;
  2155. //
  2156. // char szString[128];
  2157. // strcpy(szString, Name);
  2158. // if (m_FreezeState.nTime || m_PoisonState.nTime || m_ConfuseState.nTime || m_StunState.nTime)
  2159. // {
  2160. // strcat(szString, "(");
  2161. // if (m_FreezeState.nTime)
  2162. // strcat(szString, "冰");
  2163. // if (m_PoisonState.nTime)
  2164. // strcat(szString, "毒");
  2165. // if (m_ConfuseState.nTime)
  2166. // strcat(szString, "乱");
  2167. // if (m_StunState.nTime)
  2168. // strcat(szString, "晕");
  2169. // strcat(szString, ")");
  2170. // }
  2171. //
  2172. // int nLength = g_StrLen(szString) * nFontSize / 2;
  2173. // int nX = 400 - nLength / 2;
  2174. // int nY = 28;
  2175. // nLength += 40;
  2176. //
  2177. // Blood.Color.Color_b.r = 130;
  2178. // Blood.Color.Color_b.g = 30;
  2179. // Blood.Color.Color_b.b = 30;
  2180. // Blood.Color.Color_b.a = 10;
  2181. // Blood.oPosition.nX = nX - 20;
  2182. // Blood.oPosition.nY = nY;
  2183. // Blood.oPosition.nZ = 0;
  2184. // Blood.oEndPos.nX = Blood.oPosition.nX + nLength * m_CurrentLife / m_CurrentLifeMax;
  2185. // Blood.oEndPos.nY = nY + 16;
  2186. //
  2187. // g_pRepresent->DrawPrimitives(1, &Blood, RU_T_SHADOW, TRUE);
  2188. //
  2189. // Blood.Color.Color_b.r = 30;
  2190. // Blood.oPosition.nX = Blood.oEndPos.nX;
  2191. // Blood.oEndPos.nX = nX - 20 + nLength;
  2192. //
  2193. // g_pRepresent->DrawPrimitives(1, &Blood, RU_T_SHADOW, TRUE);
  2194. //
  2195. // g_pRepresent->OutputText(nFontSize, szString, KRF_ZERO_END, nX, nY + 2, 0xffffffff);
  2196. int nHeightOff = GetNpcPate();
  2197. //if (NpcSet.CheckShowLife())
  2198. {
  2199. nHeightOff = PaintLife(nHeightOff, true);
  2200. nHeightOff += SHOW_SPACE_HEIGHT;
  2201. }
  2202. //if (NpcSet.CheckShowName())
  2203. {
  2204. nHeightOff = PaintInfo(nHeightOff, true);
  2205. }
  2206. }
  2207. #endif
  2208. #ifdef _SERVER
  2209. int KNpc::SetPos(int nX, int nY)
  2210. {
  2211. if (m_SubWorldIndex < 0)
  2212. {
  2213. _ASSERT(0);
  2214. return 0;
  2215. }
  2216. int nRegion, nMapX, nMapY, nOffX, nOffY;
  2217. SubWorld[m_SubWorldIndex].Mps2Map(nX, nY, &nRegion, &nMapX, &nMapY, &nOffX, &nOffY);
  2218. if (nRegion < 0)
  2219. {
  2220. g_DebugLog("[Script]SetPos error:SubWorld:%d, Pos(%d, %d)", SubWorld[m_SubWorldIndex].m_SubWorldID, nX, nY);
  2221. return 0;
  2222. }
  2223. int nOldRegion = m_RegionIndex;
  2224. if (m_RegionIndex >= 0)
  2225. {
  2226. SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2227. }
  2228. m_RegionIndex = nRegion;
  2229. m_MapX = nMapX;
  2230. m_MapY = nMapY;
  2231. m_MapZ = 0;
  2232. m_OffX = nOffX;
  2233. m_OffY = nOffY;
  2234. if (nOldRegion != nRegion)
  2235. {
  2236. SubWorld[m_SubWorldIndex].NpcChangeRegion(nOldRegion, nRegion, m_Index);
  2237. if (IsPlayer())
  2238. SubWorld[m_SubWorldIndex].PlayerChangeRegion(nOldRegion, nRegion, m_nPlayerIdx);
  2239. }
  2240. SubWorld[m_SubWorldIndex].m_Region[nRegion].AddRef(m_MapX, m_MapY, obj_npc);
  2241. DoStand();
  2242. m_ProcessAI = 1;
  2243. m_ProcessState = 1;
  2244. return 1;
  2245. }
  2246. #endif
  2247. #ifdef _SERVER
  2248. int KNpc::ChangeWorld(DWORD dwSubWorldID, int nX, int nY)
  2249. {
  2250. int nTargetSubWorld = g_SubWorldSet.SearchWorld(dwSubWorldID);
  2251. if (!IsPlayer())
  2252. return 0;
  2253. // 不在这台服务器上
  2254. if (-1 == nTargetSubWorld)
  2255. {
  2256. if (m_SubWorldIndex >= 0)
  2257. SubWorld[m_SubWorldIndex].m_MissionArray.RemovePlayer(m_nPlayerIdx);
  2258. TobeExchangeServer(dwSubWorldID, nX, nY);
  2259. g_DebugLog("[Map]World%d haven't been loaded!", dwSubWorldID);
  2260. return 2; // 需要加切换服务器的处理 -- spe
  2261. }
  2262. Player[m_nPlayerIdx].m_nPrePayMoney = 0;// 不是跨服务器,不用还钱
  2263. // 切换的世界就是本身
  2264. if (nTargetSubWorld == m_SubWorldIndex)
  2265. {
  2266. // 只需切换座标
  2267. return SetPos(nX, nY);
  2268. }
  2269. int nRegion, nMapX, nMapY, nOffX, nOffY;
  2270. SubWorld[nTargetSubWorld].Mps2Map(nX, nY, &nRegion, &nMapX, &nMapY, &nOffX, &nOffY);
  2271. // 切换到的坐标非法
  2272. if (nRegion < 0)
  2273. {
  2274. g_DebugLog("[Map]Change Pos(%d,%d) Invalid!", nX, nY);
  2275. return 0;
  2276. }
  2277. if (m_SubWorldIndex >= 0)
  2278. SubWorld[m_SubWorldIndex].m_MissionArray.RemovePlayer(m_nPlayerIdx);
  2279. // 真正开始切换工作
  2280. if (m_SubWorldIndex >= 0 && m_RegionIndex >= 0)
  2281. {
  2282. SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].RemoveNpc(m_Index);// m_WorldMessage.Send(GWM_NPC_REMOVE, m_RegionIndex, m_Index);
  2283. SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2284. }
  2285. int nSourceSubWorld = m_SubWorldIndex;
  2286. int nSourceRegion = m_RegionIndex;
  2287. m_SubWorldIndex = nTargetSubWorld;
  2288. m_RegionIndex = nRegion;
  2289. m_MapX = nMapX;
  2290. m_MapY = nMapY;
  2291. m_MapZ = 0;
  2292. m_OffX = nOffX;
  2293. m_OffY = nOffY;
  2294. SubWorld[nTargetSubWorld].m_Region[nRegion].AddNpc(m_Index);// m_WorldMessage.Send(GWM_NPC_ADD, nRegion, m_Index);
  2295. SubWorld[nTargetSubWorld].m_Region[nRegion].AddRef(m_MapX, m_MapY, obj_npc);
  2296. DoStand();
  2297. m_ProcessAI = 1;
  2298. if (IsPlayer())
  2299. {
  2300. SubWorld[nTargetSubWorld].SendSyncData(m_Index, Player[m_nPlayerIdx].m_nNetConnectIdx);
  2301. SubWorld[nSourceSubWorld].RemovePlayer(nSourceRegion, m_nPlayerIdx);
  2302. SubWorld[nTargetSubWorld].AddPlayer(nRegion, m_nPlayerIdx);
  2303. }
  2304. return 1;
  2305. }
  2306. #endif
  2307. #ifdef _SERVER
  2308. void KNpc::TobeExchangeServer(DWORD dwMapID, int nX, int nY)
  2309. {
  2310. if (!IsPlayer())
  2311. {
  2312. return;
  2313. }
  2314. m_OldFightMode = m_FightMode;
  2315. m_bExchangeServer = TRUE;
  2316. if (m_nPlayerIdx > 0 && m_nPlayerIdx <= MAX_PLAYER)
  2317. {
  2318. Player[m_nPlayerIdx].TobeExchangeServer(dwMapID, nX, nY);
  2319. }
  2320. }
  2321. #endif
  2322. BOOL KNpc::IsPlayer()
  2323. {
  2324. #ifdef _SERVER
  2325. return m_Kind == kind_player;
  2326. #else
  2327. return m_Index == Player[CLIENT_PLAYER_INDEX].m_nIndex;
  2328. #endif
  2329. }
  2330. // 清除NPC身上的非被动类的技能状态
  2331. void KNpc::ClearStateSkillEffect()
  2332. {
  2333. KStateNode* pNode;
  2334. pNode = (KStateNode *)m_StateSkillList.GetHead();
  2335. while(pNode)
  2336. {
  2337. KStateNode* pTempNode = pNode;
  2338. pNode = (KStateNode *)pNode->GetNext();
  2339. if (pTempNode->m_LeftTime == -1) // 被动技能
  2340. continue;
  2341. if (pTempNode->m_LeftTime > 0)
  2342. {
  2343. for (int i = 0; i < MAX_SKILL_STATE; i++)
  2344. {
  2345. if (pTempNode->m_State[i].nAttribType)
  2346. ModifyAttrib(m_Index, &pTempNode->m_State[i]);
  2347. }
  2348. _ASSERT(pTempNode != NULL);
  2349. pTempNode->Remove();
  2350. delete pTempNode;
  2351. #ifdef _SERVER
  2352. UpdateNpcStateInfo();
  2353. BroadCastState();
  2354. #endif
  2355. pTempNode = NULL;
  2356. continue;
  2357. }
  2358. }
  2359. }
  2360. void KNpc::ClearNormalState()
  2361. {
  2362. ZeroMemory(&m_PhysicsArmor, sizeof(m_PhysicsArmor));
  2363. ZeroMemory(&m_ColdArmor, sizeof(m_ColdArmor));
  2364. ZeroMemory(&m_FireArmor, sizeof(m_FireArmor));
  2365. ZeroMemory(&m_PoisonArmor, sizeof(m_PoisonArmor));
  2366. ZeroMemory(&m_LightArmor, sizeof(m_LightArmor));
  2367. ZeroMemory(&m_ManaShield, sizeof(m_ManaShield));
  2368. ZeroMemory(&m_PoisonState, sizeof(m_PoisonState));
  2369. ZeroMemory(&m_FreezeState, sizeof(m_FreezeState));
  2370. ZeroMemory(&m_BurnState, sizeof(m_BurnState));
  2371. ZeroMemory(&m_ConfuseState, sizeof(m_ConfuseState));
  2372. ZeroMemory(&m_StunState, sizeof(m_StunState));
  2373. ZeroMemory(&m_LifeState, sizeof(m_LifeState));
  2374. ZeroMemory(&m_ManaState, sizeof(m_ManaState));
  2375. ZeroMemory(&m_DrunkState, sizeof(m_DrunkState));
  2376. }
  2377. void KNpc::CheckTrap()
  2378. {
  2379. if (m_Kind != kind_player)
  2380. return;
  2381. if (m_Index <= 0)
  2382. return;
  2383. if (m_SubWorldIndex < 0 || m_RegionIndex < 0)
  2384. return;
  2385. DWORD dwTrap = SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].GetTrap(m_MapX, m_MapY);
  2386. if (m_TrapScriptID == dwTrap)
  2387. {
  2388. return;
  2389. }
  2390. else
  2391. {
  2392. m_TrapScriptID = dwTrap;
  2393. }
  2394. if (!m_TrapScriptID)
  2395. {
  2396. return;
  2397. }
  2398. Player[m_nPlayerIdx].ExecuteScript(m_TrapScriptID, "main", 0);
  2399. }
  2400. void KNpc::SetFightMode(BOOL bFightMode)
  2401. {
  2402. //g_DebugLog("[DEATH]SetMode:%d", bFightMode);
  2403. m_FightMode = bFightMode;
  2404. #ifdef _SERVER
  2405. if (this->m_Kind == kind_player)
  2406. Player[this->m_nPlayerIdx].m_cPK.CloseAll();
  2407. #endif
  2408. }
  2409. void KNpc::TurnTo(int nIdx)
  2410. {
  2411. if (!Npc[nIdx].m_Index || !m_Index)
  2412. return;
  2413. int nX1, nY1, nX2, nY2;
  2414. GetMpsPos(&nX1, &nY1);
  2415. Npc[nIdx].GetMpsPos(&nX2, &nY2);
  2416. m_Dir = g_GetDirIndex(nX1, nY1, nX2, nY2);
  2417. }
  2418. void KNpc::ReCalcStateEffect()
  2419. {
  2420. KStateNode* pNode;
  2421. pNode = (KStateNode *)m_StateSkillList.GetHead();
  2422. while(pNode)
  2423. {
  2424. if (pNode->m_LeftTime != 0) // 包括被动(-1)和主动(>0)
  2425. {
  2426. int i;
  2427. for (i = 0; i < MAX_SKILL_STATE; i++)
  2428. {
  2429. if (pNode->m_State[i].nAttribType)
  2430. {
  2431. KMagicAttrib MagicAttrib;
  2432. MagicAttrib.nAttribType = pNode->m_State[i].nAttribType;
  2433. MagicAttrib.nValue[0] = -pNode->m_State[i].nValue[0];
  2434. MagicAttrib.nValue[1] = -pNode->m_State[i].nValue[1];
  2435. MagicAttrib.nValue[2] = -pNode->m_State[i].nValue[2];
  2436. ModifyAttrib(m_Index, &MagicAttrib);
  2437. }
  2438. }
  2439. }
  2440. pNode = (KStateNode *)pNode->GetNext();
  2441. }
  2442. }
  2443. #ifndef _SERVER
  2444. extern KTabFile g_ClientWeaponSkillTabFile;
  2445. #endif
  2446. int KNpc::GetCurActiveWeaponSkill()
  2447. {
  2448. int nSkillId = 0;
  2449. if (IsPlayer())
  2450. {
  2451. int nDetailType = Player[m_nPlayerIdx].m_ItemList.GetWeaponType();
  2452. int nParticularType = Player[m_nPlayerIdx].m_ItemList.GetWeaponParticular();
  2453. //近身武器
  2454. if (nDetailType == 0)
  2455. {
  2456. nSkillId = g_nMeleeWeaponSkill[nParticularType];
  2457. }//远程武器
  2458. else if (nDetailType == 1)
  2459. {
  2460. nSkillId = g_nRangeWeaponSkill[nParticularType];
  2461. }//空手
  2462. else if (nDetailType == -1)
  2463. {
  2464. nSkillId = g_nHandSkill;
  2465. }
  2466. }
  2467. else
  2468. {
  2469. #ifdef _SERVER
  2470. //Real Npc
  2471. return 0;
  2472. #else
  2473. if (m_Kind == kind_player) // No Local Player
  2474. {
  2475. g_ClientWeaponSkillTabFile.GetInteger(m_WeaponType + 1, "SkillId", 0, &nSkillId);
  2476. }
  2477. else //Real Npc
  2478. {
  2479. return 0;//
  2480. }
  2481. #endif
  2482. }
  2483. return nSkillId;
  2484. }
  2485. #ifndef _SERVER
  2486. void KNpc::HurtAutoMove()
  2487. {
  2488. if (this->m_Index != Player[CLIENT_PLAYER_INDEX].m_nIndex)
  2489. return;
  2490. if (this->m_Doing != do_hurt)
  2491. return;
  2492. if (m_sSyncPos.m_nDoing != do_hurt && m_sSyncPos.m_nDoing != do_stand)
  2493. return;
  2494. int nFrames, nRegionIdx;
  2495. nFrames = m_Frames.nTotalFrame - m_Frames.nCurrentFrame;
  2496. if (nFrames <= 1)
  2497. {
  2498. if ((DWORD)SubWorld[0].m_Region[m_RegionIndex].m_RegionID == m_sSyncPos.m_dwRegionID)
  2499. {
  2500. SubWorld[0].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2501. m_MapX = m_sSyncPos.m_nMapX;
  2502. m_MapY = m_sSyncPos.m_nMapY;
  2503. m_OffX = m_sSyncPos.m_nOffX;
  2504. m_OffY = m_sSyncPos.m_nOffY;
  2505. memset(&m_sSyncPos, 0, sizeof(m_sSyncPos));
  2506. SubWorld[0].m_Region[m_RegionIndex].AddRef(m_MapX, m_MapY, obj_npc);
  2507. }
  2508. else
  2509. {
  2510. nRegionIdx = SubWorld[0].FindRegion(m_sSyncPos.m_dwRegionID);
  2511. if (nRegionIdx < 0)
  2512. return;
  2513. SubWorld[0].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2514. SubWorld[0].NpcChangeRegion(SubWorld[0].m_Region[m_RegionIndex].m_RegionID, SubWorld[0].m_Region[nRegionIdx].m_RegionID, m_Index);
  2515. m_RegionIndex = nRegionIdx;
  2516. m_dwRegionID = m_sSyncPos.m_dwRegionID;
  2517. m_MapX = m_sSyncPos.m_nMapX;
  2518. m_MapY = m_sSyncPos.m_nMapY;
  2519. m_OffX = m_sSyncPos.m_nOffX;
  2520. m_OffY = m_sSyncPos.m_nOffY;
  2521. memset(&m_sSyncPos, 0, sizeof(m_sSyncPos));
  2522. }
  2523. }
  2524. else
  2525. {
  2526. nRegionIdx = SubWorld[0].FindRegion(m_sSyncPos.m_dwRegionID);
  2527. if (nRegionIdx < 0)
  2528. return;
  2529. int nNpcX, nNpcY, nSyncX, nSyncY;
  2530. int nNewX, nNewY, nMapX, nMapY, nOffX, nOffY;
  2531. SubWorld[0].Map2Mps(m_RegionIndex, 
  2532. m_MapX, m_MapY,
  2533. m_OffX, m_OffY,
  2534. &nNpcX, &nNpcY);
  2535. SubWorld[0].Map2Mps(nRegionIdx, 
  2536. m_sSyncPos.m_nMapX, m_sSyncPos.m_nMapY,
  2537. m_sSyncPos.m_nOffX, m_sSyncPos.m_nOffY,
  2538. &nSyncX, &nSyncY);
  2539. nNewX = nNpcX + (nSyncX - nNpcX) / nFrames;
  2540. nNewY = nNpcY + (nSyncY - nNpcY) / nFrames;
  2541. SubWorld[0].Mps2Map(nNewX, nNewY, &nRegionIdx, &nMapX, &nMapY, &nOffX, &nOffY);
  2542. _ASSERT(nRegionIdx >= 0);
  2543. if (nRegionIdx < 0)
  2544. return;
  2545. if (nRegionIdx != m_RegionIndex)
  2546. {
  2547. SubWorld[0].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2548. SubWorld[0].NpcChangeRegion(SubWorld[0].m_Region[m_RegionIndex].m_RegionID, SubWorld[0].m_Region[nRegionIdx].m_RegionID, m_Index);
  2549. m_RegionIndex = nRegionIdx;
  2550. m_dwRegionID = m_sSyncPos.m_dwRegionID;
  2551. m_MapX = nMapX;
  2552. m_MapY = nMapY;
  2553. m_OffX = nOffX;
  2554. m_OffY = nOffY;
  2555. }
  2556. else
  2557. {
  2558. SubWorld[0].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2559. m_MapX = nMapX;
  2560. m_MapY = nMapY;
  2561. m_OffX = nOffX;
  2562. m_OffY = nOffY;
  2563. SubWorld[0].m_Region[m_RegionIndex].AddRef(m_MapX, m_MapY, obj_npc);
  2564. }
  2565. }
  2566. }
  2567. #endif
  2568. #ifndef _SERVER
  2569. void KNpc::ProcNetCommand(NPCCMD cmd, int x /* = 0 */, int y /* = 0 */, int z /* = 0 */)
  2570. {
  2571. switch (cmd)
  2572. {
  2573. case do_death:
  2574. DoDeath();
  2575. break;
  2576. case do_hurt:
  2577. DoHurt(x, y, z);
  2578. break;
  2579. case do_revive:
  2580. DoStand();
  2581. m_ProcessAI = 1;
  2582. m_ProcessState = 1;
  2583. SetInstantSpr(enumINSTANT_STATE_REVIVE);
  2584. break;
  2585. case do_stand:
  2586. DoStand();
  2587. m_ProcessAI = 1;
  2588. m_ProcessState = 1;
  2589. default:
  2590. break;
  2591. }
  2592. }
  2593. #endif
  2594. #ifndef _SERVER
  2595. void KNpc::ClearBlood()
  2596. {
  2597. m_nBloodNo = 0;
  2598. m_nBloodAlpha = 0;
  2599. m_nBloodTime = 0;
  2600. m_szBloodNo[0] = 0;
  2601. }
  2602. #endif
  2603. #ifndef _SERVER
  2604. void KNpc::SetBlood(int nNo)
  2605. {
  2606. if (nNo <= 0)
  2607. return;
  2608. m_nBloodNo = nNo;
  2609. m_nBloodAlpha = 0;
  2610. m_nBloodTime = defMAX_SHOW_BLOOD_TIME;
  2611. sprintf(m_szBloodNo, "%d", nNo);
  2612. }
  2613. #endif
  2614. #ifndef _SERVER
  2615. int KNpc::PaintBlood(int nHeightOffset)
  2616. {
  2617. if (!m_szBloodNo[0])
  2618. return nHeightOffset;
  2619. int nHeightOff = nHeightOffset + (defMAX_SHOW_BLOOD_TIME - m_nBloodTime) * defSHOW_BLOOD_MOVE_SPEED;
  2620. int nFontSize = 16;
  2621. DWORD dwColor = SHOW_BLOOD_COLOR | (m_nBloodAlpha << 24);
  2622. int nMpsX, nMpsY;
  2623. GetMpsPos(&nMpsX, &nMpsY);
  2624. g_pRepresent->OutputText(nFontSize, m_szBloodNo, KRF_ZERO_END, nMpsX - nFontSize * g_StrLen(m_szBloodNo) / 4, nMpsY, dwColor, 0, nHeightOff);
  2625. m_nBloodTime--;
  2626. if (m_nBloodTime <= 0)
  2627. {
  2628. ClearBlood();
  2629. return nHeightOff;
  2630. }
  2631. m_nBloodAlpha++;
  2632. if (m_nBloodAlpha > 31)
  2633. m_nBloodAlpha = 31;
  2634. return nHeightOff;
  2635. }
  2636. #endif
  2637. #ifndef _SERVER
  2638. int KNpc::GetNpcPate()
  2639. {
  2640. int nHeight = m_Height + m_nStature;
  2641. if (m_Kind == kind_player)
  2642. {
  2643. if (m_nSex)
  2644. nHeight += 84; //女
  2645. else
  2646. nHeight += 84; //男
  2647. if (m_Doing == do_sit && MulDiv(10, m_Frames.nCurrentFrame, m_Frames.nTotalFrame) >= 8)
  2648. nHeight -= MulDiv(30, m_Frames.nCurrentFrame, m_Frames.nTotalFrame);
  2649. if (m_bRideHorse)
  2650. nHeight += 38; //骑马
  2651. }
  2652. return nHeight;
  2653. }
  2654. #endif
  2655. #ifndef _SERVER
  2656. int KNpc::GetNpcPatePeopleInfo()
  2657. {
  2658. int nFontSize = 12;
  2659. if (m_nChatContentLen > 0 && m_nChatNumLine > 0)
  2660. return m_nChatNumLine * (nFontSize + 1);
  2661. int nHeight = 0;
  2662. if (NpcSet.CheckShowLife())
  2663. {
  2664. if (m_Kind == kind_player ||
  2665. m_Kind == kind_partner)
  2666. {
  2667. if (m_CurrentLifeMax > 0 &&
  2668. (relation_enemy == NpcSet.GetRelation(m_Index, Player[CLIENT_PLAYER_INDEX].m_nIndex))
  2669. )
  2670. nHeight += SHOW_LIFE_HEIGHT;
  2671. }
  2672. }
  2673. if (NpcSet.CheckShowName())
  2674. {
  2675. if (nHeight != 0)
  2676. nHeight += SHOW_SPACE_HEIGHT;//好看
  2677. if (m_Kind == kind_player || m_Kind == kind_dialoger)
  2678. nHeight += nFontSize + 1;
  2679. }
  2680. return nHeight;
  2681. }
  2682. #endif