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

模拟服务器

开发平台:

C/C++

  1. //-----------------------------------------------------------------------
  2. // Sword3 KNpc.cpp
  3. //-----------------------------------------------------------------------
  4. #include "KCore.h"
  5. //#include <crtdbg.h>
  6. #include "KNpcAI.h"
  7. #include "KSkills.h"
  8. #include "KObj.h"
  9. #include "KObjSet.h"
  10. #include "KMath.h"
  11. #include "KPlayer.h"
  12. #include "KNpc.h"
  13. #include "GameDataDef.h"
  14. #include "KSubWorldSet.h"
  15. #include "KRegion.h"
  16. #include "KNpcTemplate.h"
  17. #include "KItemSet.h"
  18. #ifdef _SERVER
  19. //#include "KNetServer.h"
  20. //#include "../MultiServer/Heaven/Interface/iServer.h"
  21. #include "KPlayerSet.h"
  22. #include "KSkillManager.h"
  23. #else
  24. #include "../../Headers/IClient.h"
  25. #include "CoreShell.h"
  26. #include "Scene/KScenePlaceC.h"
  27. #include "KIme.h"
  28. #include "../../Represent/iRepresent/iRepresentshell.h"
  29. #include "ImgRef.h"
  30. #include "Text.h"
  31. #endif
  32. #include "KNpcAttribModify.h"
  33. #include "CoreUseNameDef.h"
  34. #include "KSubWorld.h"
  35. #include "Scene/ObstacleDef.h"
  36. #include "KThiefSkill.h"
  37. #ifdef _STANDALONE
  38. #include "KThiefSkill.cpp"
  39. #endif
  40. #ifndef max
  41. #define max(a,b)    (((a) > (b)) ? (a) : (b))
  42. #endif
  43. extern KLuaScript *g_pNpcLevelScript;
  44. #define ATTACKACTION_EFFECT_PERCENT 60 // 发技能动作完成百分之多少才真正发出来
  45. #define MIN_JUMP_RANGE 0
  46. #define ACCELERATION_OF_GRAVITY 10
  47. #define SHOW_CHAT_WIDTH 24
  48. #define SHOW_CHAT_COLOR 0xffffffff
  49. #define SHOW_BLOOD_COLOR 0x00ff0000
  50. #define defMAX_SHOW_BLOOD_TIME 27
  51. #define defSHOW_BLOOD_MOVE_SPEED 2
  52. #define SHOW_LIFE_WIDTH 38
  53. #define SHOW_LIFE_HEIGHT 3
  54. #define SHOW_SPACE_HEIGHT 5
  55. //-----------------------------------------------------------------------
  56. #define GAME_UPDATE_TIME 10
  57. #define GAME_SYNC_LOSS 100
  58. #define STAMINA_RECOVER_SCALE 4
  59. // 区域的宽高(格子单位)
  60. #define REGIONWIDTH SubWorld[m_SubWorldIndex].m_nRegionWidth
  61. #define REGIONHEIGHT SubWorld[m_SubWorldIndex].m_nRegionHeight
  62. // 格子的宽高(像素单位,放大了1024倍)
  63. #define CELLWIDTH (SubWorld[m_SubWorldIndex].m_nCellWidth << 10)
  64. #define CELLHEIGHT (SubWorld[m_SubWorldIndex].m_nCellHeight << 10)
  65. // 当前区域
  66. #define CURREGION SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex]
  67. // 相邻区域的索引
  68. #define LEFTREGIONIDX CURREGION.m_nConnectRegion[2]
  69. #define RIGHTREGIONIDX CURREGION.m_nConnectRegion[6]
  70. #define UPREGIONIDX CURREGION.m_nConnectRegion[4]
  71. #define DOWNREGIONIDX CURREGION.m_nConnectRegion[0]
  72. #define LEFTUPREGIONIDX CURREGION.m_nConnectRegion[3]
  73. #define LEFTDOWNREGIONIDX CURREGION.m_nConnectRegion[1]
  74. #define RIGHTUPREGIONIDX CURREGION.m_nConnectRegion[5]
  75. #define RIGHTDOWNREGIONIDX CURREGION.m_nConnectRegion[7]
  76. #define LEFTREGION SubWorld[m_SubWorldIndex].m_Region[LEFTREGIONIDX]
  77. #define RIGHTREGION SubWorld[m_SubWorldIndex].m_Region[RIGHTREGIONIDX]
  78. #define UPREGION SubWorld[m_SubWorldIndex].m_Region[UPREGIONIDX]
  79. #define DOWNREGION SubWorld[m_SubWorldIndex].m_Region[DOWNREGIONIDX]
  80. #define LEFTUPREGION SubWorld[m_SubWorldIndex].m_Region[LEFTUPREGIONIDX]
  81. #define LEFTDOWNREGION SubWorld[m_SubWorldIndex].m_Region[LEFTDOWNREGIONIDX]
  82. #define RIGHTUPREGION SubWorld[m_SubWorldIndex].m_Region[RIGHTUPREGIONIDX]
  83. #define RIGHTDOWNREGION SubWorld[m_SubWorldIndex].m_Region[RIGHTDOWNREGIONIDX]
  84. #define CONREGION(x) SubWorld[m_SubWorldIndex].m_Region[CURREGION.m_nConnectRegion[x]]
  85. #define CONREGIONIDX(x) CURREGION.m_nConnectRegion[x]
  86. // 当前技能
  87. //-----------------------------------------------------------------------
  88. // Npc[0]不在游戏世界中使用,做为一个NpcSet用于添加新的NPC。
  89. KNpc Npc[MAX_NPC];
  90. KNpcTemplate * g_pNpcTemplate[MAX_NPCSTYLE][MAX_NPC_LEVEL]; //0,0为起点
  91. //-----------------------------------------------------------------------
  92. KNpc::KNpc()
  93. {
  94. #ifdef _SERVER
  95. m_AiSkillRadiusLoadFlag = 0; // 只需要在构造的时候初始化一次
  96. #endif
  97. Init();
  98. }
  99. void KNpc::Init()
  100. {
  101. m_dwID = 0;
  102. m_Index = 0;
  103. m_nPlayerIdx = 0;
  104. m_ProcessAI = 1;
  105. m_Kind = kind_normal;
  106. m_Series = series_metal;
  107. m_Camp = camp_free;
  108. m_CurrentCamp = camp_free;
  109. m_Doing = do_stand;
  110. m_Height = 0;
  111. m_Frames.nCurrentFrame = 0;
  112. m_Frames.nTotalFrame = 0;
  113. m_SubWorldIndex = 0;
  114. m_RegionIndex = -1;
  115. m_Experience = 0;
  116. m_ActiveSkillID = 0;
  117. m_SkillParam1 = 0;
  118. m_SkillParam2 = 0;
  119. #ifndef _SERVER
  120. m_nChatContentLen = 0;
  121. m_nCurChatTime = 0;
  122. m_nChatNumLine = 0;
  123. m_nChatFontWidth = 0;
  124. m_nStature = 0;
  125. #endif
  126. m_CurrentLife = 100; // Npc的当前生命
  127. m_CurrentLifeMax = 100; // Npc的当前生命最大值
  128. m_CurrentLifeReplenish = 0; // Npc的当前生命回复速度
  129. m_CurrentMana = 100; // Npc的当前内力
  130. m_CurrentManaMax = 100; // Npc的当前最大内力
  131. m_CurrentManaReplenish = 0; // Npc的当前内力回复速度
  132. m_CurrentStamina = 100; // Npc的当前体力
  133. m_CurrentStaminaMax = 100; // Npc的当前最大体力
  134. m_CurrentStaminaGain = 0; // Npc的当前体力回复速度
  135. m_CurrentStaminaLoss = 0; // Npc的当前体力下降速度
  136. m_CurrentAttackRating = 100; // Npc的当前命中率
  137. m_CurrentDefend = 10; // Npc的当前防御
  138. m_CurrentWalkSpeed = 5; // Npc的当前走动速度
  139. m_CurrentRunSpeed = 10; // Npc的当前跑动速度
  140. m_CurrentJumpSpeed = 12; // Npc的当前跳跃速度
  141. m_CurrentJumpFrame = 40; // Npc的当前跳跃时间
  142. m_CurrentAttackSpeed = 0; // Npc的当前攻击速度
  143. m_CurrentCastSpeed = 0; // Npc的当前施法速度
  144. m_CurrentVisionRadius = 40; // Npc的当前视野范围
  145. m_CurrentAttackRadius = 30; // Npc的当前攻击范围
  146. m_CurrentHitRecover = 0; // Npc的当前受击回复速度
  147. m_CurrentAddPhysicsDamage = 0; // Npc的当前物理伤害直接加的点数
  148. m_Dir = 0; // Npc的方向
  149. m_JumpStep = 0;
  150. m_JumpDir = 0;
  151. m_MapZ = 0; // Npc的高度
  152. m_HelmType = 1; // Npc的头盔类型
  153. m_ArmorType = 1; // Npc的盔甲类型
  154. m_WeaponType = 1; // Npc的武器类型
  155. m_HorseType = -1; // Npc的骑马类型
  156. m_bRideHorse = FALSE; // Npc是否骑马
  157. ZeroMemory(Name, 32); // Npc的名称
  158. m_NpcSettingIdx = 0; // Npc的设定文件索引
  159. m_CorpseSettingIdx = 0; // Body的设定文件索引
  160. ZeroMemory(ActionScript,32);
  161. m_ActionScriptID = 0;
  162. m_TrapScriptID = 0;
  163. m_btRankId = 0;
  164. m_LifeMax = 100; // Npc的最大生命
  165. m_LifeReplenish = 0; // Npc的生命回复速度
  166. m_ManaMax = 100; // Npc的最大内力
  167. m_ManaReplenish = 0; // Npc的内力回复速度
  168. m_StaminaMax = 100; // Npc的最大体力
  169. m_StaminaGain = 0; // Npc的体力回复速度
  170. m_StaminaLoss = 0; // Npc的体力下降速度
  171. m_AttackRating = 100; // Npc的命中率
  172. m_Defend = 10; // Npc的防御
  173. m_WalkSpeed = 6; // Npc的行走速度
  174. m_RunSpeed = 10; // Npc的跑动速度
  175. m_JumpSpeed = 12; // Npc的跳跃速度
  176. m_AttackSpeed = 0; // Npc的攻击速度
  177. m_CastSpeed = 0; // Npc的施法速度
  178. m_VisionRadius = 40; // Npc的视野范围
  179. m_DialogRadius = 124; // Npc的对话范围
  180. m_HitRecover = 12; // Npc的受击回复速度
  181. m_nPeopleIdx = 0;
  182. m_LoopFrames = 0;
  183. m_WalkFrame = 12;
  184. m_RunFrame = 15;
  185. m_StandFrame = 15;
  186. m_DeathFrame = 15;
  187. m_HurtFrame = 10;
  188. m_AttackFrame = 20;
  189. m_CastFrame = 20;
  190. m_SitFrame = 15;
  191. m_JumpFrame = 40;
  192. m_AIMAXTime = 25;
  193. m_NextAITime = 0;
  194. m_ProcessState = 1;
  195. m_ReviveFrame = 100;
  196. m_bExchangeServer = FALSE;
  197. m_bActivateFlag = FALSE;
  198. m_FightMode = 0;
  199. m_OldFightMode = 0;
  200. #ifdef _SERVER
  201. m_nNextStatePos = 0;
  202. m_pDropRate = NULL;
  203. #endif
  204. #ifndef _SERVER
  205. m_SyncSignal = 0;
  206. m_sClientNpcID.m_dwRegionID = 0;
  207. m_sClientNpcID.m_nNo = -1;
  208. m_ResDir = 0;
  209. m_nPKFlag = 0;
  210. m_nSleepFlag = 0;
  211. memset(&m_sSyncPos, 0, sizeof(m_sSyncPos));
  212. m_nBloodNo = 0;
  213. m_nBloodAlpha = 0;
  214. m_nBloodTime = 0;
  215. m_szBloodNo[0] = 0;
  216. m_nTongFlag = 0;
  217. #endif
  218. m_nLastPoisonDamageIdx = 0;
  219. m_nLastDamageIdx = 0;
  220. m_bHaveLoadedFromTemplate = FALSE;
  221. m_bClientOnly = FALSE;
  222. }
  223. ISkill* KNpc::GetActiveSkill()
  224. {
  225. _ASSERT(m_ActiveSkillID < MAX_SKILL);
  226. int nCurLevel = m_SkillList.GetCurrentLevel(m_ActiveSkillID);
  227. if (nCurLevel > 0)
  228. return g_SkillManager.GetSkill(m_ActiveSkillID, nCurLevel);
  229. else 
  230. return NULL;
  231. };
  232. void KNpc::SetCurrentCamp(int nCamp)
  233. {
  234. m_CurrentCamp = nCamp;
  235. #ifdef _SERVER
  236. POINT POff[8] = 
  237. {
  238. {0, 32},
  239. {-16, 32},
  240. {-16, 0},
  241. {-16, -32},
  242. {0, -32},
  243. {16, -32},
  244. {16, 0},
  245. {16, 32},
  246. };
  247. if (m_RegionIndex < 0)
  248. return;
  249. NPC_CHGCURCAMP_SYNC NetCommand;
  250. NetCommand.ProtocolType = (BYTE)s2c_npcchgcurcamp;
  251. NetCommand.ID = m_dwID;
  252. NetCommand.Camp = (BYTE)m_CurrentCamp;
  253. int nMaxCount = MAX_BROADCAST_COUNT;
  254. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  255. int i;
  256. for (i = 0; i < 8; i++)
  257. {
  258. if (CONREGIONIDX(i) == -1)
  259. continue;
  260. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  261. }
  262. #endif
  263. }
  264. void KNpc::SetCamp(int nCamp)
  265. {
  266. m_Camp = nCamp;
  267. #ifdef _SERVER
  268. POINT POff[8] = 
  269. {
  270. {0, 32},
  271. {-16, 32},
  272. {-16, 0},
  273. {-16, -32},
  274. {0, -32},
  275. {16, -32},
  276. {16, 0},
  277. {16, 32},
  278. };
  279. if (m_RegionIndex < 0)
  280. return;
  281. NPC_CHGCAMP_SYNC NetCommand;
  282. NetCommand.ProtocolType = (BYTE)s2c_npcchgcamp;
  283. NetCommand.ID = m_dwID;
  284. NetCommand.Camp = (BYTE)m_Camp;
  285. int nMaxCount = MAX_BROADCAST_COUNT;
  286. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  287. int i;
  288. for (i = 0; i < 8; i++)
  289. {
  290. if (CONREGIONIDX(i) == -1)
  291. continue;
  292. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  293. }
  294. #endif
  295. }
  296. void KNpc::RestoreCurrentCamp()
  297. {
  298. m_CurrentCamp = m_Camp;
  299. #ifdef _SERVER
  300. POINT POff[8] = 
  301. {
  302. {0, 32},
  303. {-16, 32},
  304. {-16, 0},
  305. {-16, -32},
  306. {0, -32},
  307. {16, -32},
  308. {16, 0},
  309. {16, 32},
  310. };
  311. if (m_RegionIndex < 0)
  312. return;
  313. NPC_CHGCURCAMP_SYNC NetCommand;
  314. NetCommand.ProtocolType = (BYTE)s2c_npcchgcurcamp;
  315. NetCommand.ID = m_dwID;
  316. NetCommand.Camp = (BYTE)m_CurrentCamp;
  317. int nMaxCount = MAX_BROADCAST_COUNT;
  318. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  319. int i;
  320. for (i = 0; i < 8; i++)
  321. {
  322. if (CONREGIONIDX(i) == -1)
  323. continue;
  324. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  325. }
  326. #endif
  327. }
  328. #define NPC_SHOW_CHAT_TIME 15000
  329. int IR_IsTimePassed(unsigned int uInterval, unsigned int& uLastTimer);
  330. void KNpc::Activate()
  331. {
  332. // 不存在这个NPC
  333. if (!m_Index)
  334. {
  335. //g_DebugLog("[DEATH] No Index: %d", m_Index);
  336. return;
  337. }
  338. // 切换地图中,不处理
  339. if (m_bExchangeServer)
  340. {
  341. //g_DebugLog("[DEATH] Change Server: %d", m_bExchangeServer);
  342. return;
  343. }
  344. // Check here
  345. if (m_bActivateFlag)
  346. {
  347. m_bActivateFlag = FALSE; // restore flag
  348. return;
  349. }
  350. // m_bActivateFlag = TRUE;
  351. m_LoopFrames++;
  352. // Process npc special state, such as curse, etc.
  353. //g_DebugLog("[DEATH] m_ProcessState: %d", m_ProcessState);
  354. if (m_ProcessState)
  355. {
  356. if (ProcessState())
  357. return;
  358. }
  359. if (m_ProcessAI)
  360. {
  361. NpcAI.Activate(m_Index);
  362. }
  363. ProcCommand(m_ProcessAI);
  364. ProcStatus();
  365. #ifdef _SERVER
  366. this->m_cDeathCalcExp.Active();
  367. #endif
  368. #ifndef _SERVER
  369. if (m_RegionIndex == -1)
  370. return;
  371. // HurtAutoMove();
  372. int nMpsX, nMpsY;
  373. m_DataRes.SetAction(m_ClientDoing);
  374. m_DataRes.SetRideHorse(m_bRideHorse);
  375. m_DataRes.SetArmor(m_ArmorType);
  376. m_DataRes.SetHelm(m_HelmType);
  377. m_DataRes.SetHorse(m_HorseType);
  378. m_DataRes.SetWeapon(m_WeaponType);
  379. // 处理技能产生的状态的特效
  380. m_DataRes.SetState(&m_StateSkillList, &g_NpcResList);
  381. if (Player[CLIENT_PLAYER_INDEX].m_nIndex == m_Index)
  382. {
  383. SubWorld[0].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &nMpsX, &nMpsY);
  384. m_DataRes.SetPos(m_Index, nMpsX, nMpsY, m_Height, TRUE);
  385. }
  386. else
  387. {
  388. SubWorld[0].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &nMpsX, &nMpsY);
  389. m_DataRes.SetPos(m_Index, nMpsX, nMpsY, m_Height, FALSE);
  390. }
  391. // client npc 时间计数处理:不往后跳
  392. if (m_Kind == kind_bird || m_Kind == kind_mouse)
  393. m_SyncSignal = SubWorld[0].m_dwCurrentTime;
  394. if (m_nChatContentLen > 0)
  395. {
  396. if (IR_GetCurrentTime() - m_nCurChatTime > NPC_SHOW_CHAT_TIME)
  397. {
  398. m_nChatContentLen = 0;
  399. m_nChatNumLine = 0;
  400. m_nChatFontWidth = 0;
  401. m_nCurChatTime = 0;
  402. }
  403. }
  404. #endif
  405. }
  406. void KNpc::ProcStatus()
  407. {
  408. //g_DebugLog("[DEATH] m_bExchangeServer: %d", m_bExchangeServer);
  409. if (m_bExchangeServer)
  410. return;
  411. switch(m_Doing)
  412. {
  413. case do_stand:
  414. OnStand();
  415. break;
  416. case do_run:
  417. OnRun();
  418. break;
  419. case do_walk:
  420. OnWalk();
  421. break;
  422. case do_attack:
  423. case do_magic:
  424. OnSkill();
  425. break;
  426. case do_sit:
  427. OnSit();
  428. break;
  429. case do_jump:
  430. OnJump();
  431. break;
  432. case do_hurt:
  433. OnHurt();
  434. break;
  435. case do_revive:
  436. OnRevive();
  437. break;
  438. case do_death:
  439. OnDeath();
  440. break;
  441. case do_defense:
  442. OnDefense();
  443. break;
  444. case do_special1:
  445. OnSpecial1();
  446. break;
  447. case do_special2:
  448. OnSpecial2();
  449. break;
  450. case do_special3:
  451. OnSpecial3();
  452. break;
  453. case do_special4:
  454. OnSpecial4();
  455. break;
  456. case do_manyattack:
  457. OnManyAttack();
  458. break;
  459. case do_runattack:
  460. OnRunAttack();
  461. break;
  462. case do_jumpattack:
  463. OnJumpAttack();
  464. break;
  465. case do_idle:
  466. OnIdle();
  467. default:
  468. break;
  469. }
  470. }
  471. void KNpc::ProcCommand(int nAI)
  472. {
  473. // CmdKind < 0 表示没有指令 交换地图也不处理
  474. if (m_Command.CmdKind == do_none || m_bExchangeServer)
  475. return;
  476. if (nAI)
  477. {
  478. if (m_RegionIndex < 0)
  479. return;
  480. switch (m_Command.CmdKind)
  481. {
  482. case do_stand:
  483. DoStand();
  484. break;
  485. case do_walk:
  486. Goto(m_Command.Param_X, m_Command.Param_Y);
  487. break;
  488. case do_run:
  489. RunTo(m_Command.Param_X, m_Command.Param_Y);
  490. break;
  491. case do_jump:
  492. JumpTo(m_Command.Param_X, m_Command.Param_Y);
  493. break;
  494. case do_skill:
  495. if (int nSkillIdx = m_SkillList.FindSame(m_Command.Param_X))
  496. {
  497. SetActiveSkill(nSkillIdx);
  498. DoSkill(m_Command.Param_Y, m_Command.Param_Z);
  499. }
  500. else
  501. {
  502. DoStand();
  503. }
  504. break;
  505. case do_sit:
  506. DoSit();
  507. break;
  508. case do_defense:
  509. DoDefense();
  510. break;
  511. case do_idle:
  512. DoIdle();
  513. break;
  514. case do_hurt:
  515. DoHurt(m_Command.Param_X, m_Command.Param_Y, m_Command.Param_Z);
  516. break;
  517. // 因为跨地图能把ai设为1
  518. case do_revive:
  519. DoStand();
  520. m_ProcessAI = 1;
  521. m_ProcessState = 1;
  522. #ifndef _SERVER
  523. this->SetInstantSpr(enumINSTANT_STATE_REVIVE);
  524. #endif
  525. break;
  526. }
  527. }
  528. else
  529. {
  530. switch(m_Command.CmdKind)
  531. {
  532. case do_hurt:
  533. if (m_RegionIndex >= 0)
  534. DoHurt(m_Command.Param_X, m_Command.Param_Y, m_Command.Param_Z);
  535. break;
  536. case do_revive:
  537. DoStand();
  538. m_ProcessAI = 1;
  539. m_ProcessState = 1;
  540. #ifndef _SERVER
  541. this->SetInstantSpr(enumINSTANT_STATE_REVIVE);
  542. #endif
  543. break;
  544. default:
  545. break;
  546. }
  547. }
  548. m_Command.CmdKind = do_none;
  549. }
  550. BOOL KNpc::ProcessState()
  551. {
  552. int nRet = FALSE;
  553. if (m_RegionIndex < 0)
  554. return FALSE;
  555. if (!(m_LoopFrames % GAME_UPDATE_TIME))
  556. {
  557. // 生命、内力、体力变化只由服务器计算
  558. #ifdef _SERVER
  559. // 打坐中
  560. if (m_Doing == do_sit)
  561. {
  562. int nLifeAdd = m_CurrentLifeMax * 3 / 1000;
  563. if (nLifeAdd <= 0)
  564. nLifeAdd = 1;
  565. m_CurrentLife += nLifeAdd;
  566. if (m_CurrentLife > m_CurrentLifeMax)
  567. m_CurrentLife = m_CurrentLifeMax;
  568. int nManaAdd = m_CurrentManaMax * 3 / 1000;
  569. if (nManaAdd <= 0)
  570. nManaAdd = 1;
  571. m_CurrentMana += nManaAdd;
  572. if (m_CurrentMana > m_CurrentManaMax)
  573. m_CurrentMana = m_CurrentManaMax;
  574. // if (m_CurrentLife >= m_CurrentLifeMax && m_CurrentMana >= m_CurrentManaMax)
  575. // this->SendCommand(do_stand);
  576. }
  577. // 生命自然回复
  578. m_CurrentLife += m_CurrentLifeReplenish;
  579. if (m_CurrentLife > m_CurrentLifeMax)
  580. m_CurrentLife = m_CurrentLifeMax;
  581. // 内力自然回复
  582. m_CurrentMana += m_CurrentManaReplenish;
  583. if (m_CurrentMana > m_CurrentManaMax)
  584. m_CurrentMana = m_CurrentManaMax;
  585. // 体力自然回复
  586. if (m_Doing == do_run)
  587. m_CurrentStamina += m_CurrentStaminaGain / STAMINA_RECOVER_SCALE;
  588. else
  589. m_CurrentStamina += m_CurrentStaminaGain;
  590. if (m_CurrentStamina > m_CurrentStaminaMax)
  591. m_CurrentStamina = m_CurrentStaminaMax;
  592. #endif
  593. // 光环技能
  594. if (m_ActiveAuraID)
  595. {
  596. int nLevel = m_SkillList.GetCurrentLevel(m_ActiveAuraID);
  597. if (nLevel > 0)
  598. {
  599. int nMpsX, nMpsY;
  600. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &nMpsX, &nMpsY);
  601. _ASSERT(m_ActiveAuraID < MAX_SKILL && nLevel < MAX_SKILLLEVEL);
  602. #ifdef _SERVER
  603. NPC_SKILL_SYNC SkillCmd;
  604. SkillCmd.ID = this->m_dwID;
  605. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(m_ActiveAuraID, nLevel);
  606. if (pOrdinSkill)
  607.                 {
  608. // if (pOrdinSkill->GetSkillStyle() == SKILL_SS_Missles)
  609. SkillCmd.nSkillID = pOrdinSkill->GetChildSkillId();
  610.                 }
  611. else
  612.                 {
  613. SkillCmd.nSkillID = 0;
  614.                 }
  615. SkillCmd.nSkillLevel = nLevel;
  616. SkillCmd.nMpsX = -1;
  617. SkillCmd.nMpsY = m_dwID;
  618. SkillCmd.ProtocolType = s2c_castskilldirectly;
  619. POINT POff[8] = 
  620. {
  621. {0, 32},
  622. {-16, 32},
  623. {-16, 0},
  624. {-16, -32},
  625. {0, -32},
  626. {16, -32},
  627. {16, 0},
  628. {16, 32},
  629. };
  630. int nMaxCount = MAX_BROADCAST_COUNT;
  631. CURREGION.BroadCast(&SkillCmd, sizeof(SkillCmd), nMaxCount, m_MapX, m_MapY);
  632. int i;
  633. for (i = 0; i < 8; i++)
  634. {
  635. if (CONREGIONIDX(i) == -1)
  636. continue;
  637. CONREGION(i).BroadCast(&SkillCmd, sizeof(SkillCmd), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  638. }
  639. #endif
  640. KSkill * pOrdinSkill1 = (KSkill *) g_SkillManager.GetSkill(m_ActiveAuraID, nLevel);
  641. int nChildSkillId = 0;
  642. if (pOrdinSkill1)
  643. {
  644. nChildSkillId = pOrdinSkill1->GetChildSkillId();
  645.                     
  646. KSkill * pOrdinSkill2 = (KSkill *) g_SkillManager.GetSkill(nChildSkillId, nLevel);
  647. if (pOrdinSkill2)
  648.                     {
  649. pOrdinSkill2->Cast(m_Index, nMpsX, nMpsY);
  650.                     }
  651. }
  652. }
  653. }
  654. }
  655. #ifdef _SERVER
  656. // 物理护盾
  657. if (m_PhysicsArmor.nTime)
  658. {
  659. m_PhysicsArmor.nTime--;
  660. }
  661. else
  662. {
  663. m_PhysicsArmor.nValue[0] = 0;
  664. }
  665. // 冰护盾
  666. if (m_ColdArmor.nTime)
  667. {
  668. m_ColdArmor.nTime--;
  669. }
  670. else
  671. {
  672. m_ColdArmor.nValue[0] = 0;
  673. }
  674. // 火护盾
  675. if (m_FireArmor.nTime)
  676. {
  677. m_FireArmor.nTime--;
  678. }
  679. else
  680. {
  681. m_FireArmor.nValue[0] = 0;
  682. }
  683. // 毒护盾
  684. if (m_PoisonArmor.nTime)
  685. {
  686. m_PoisonArmor.nTime--;
  687. }
  688. else
  689. {
  690. m_PoisonArmor.nValue[0] = 0;
  691. }
  692. // 电护盾
  693. if (m_LightArmor.nTime)
  694. {
  695. m_LightArmor.nTime--;
  696. }
  697. else
  698. {
  699. m_LightArmor.nValue[0] = 0;
  700. }
  701. // 魔法盾
  702. if (m_ManaShield.nTime)
  703. {
  704. m_ManaShield.nTime--;
  705. }
  706. else
  707. {
  708. m_ManaShield.nValue[0] = 0;
  709. }
  710. // m_PowerState; // 怒火状态
  711.  //中毒状态
  712. if (m_PoisonState.nTime > 0)
  713. {
  714. m_PoisonState.nTime--;
  715. if (m_PoisonState.nValue[1] == 0)
  716. {
  717. m_PoisonState.nValue[1] = 1;
  718. }
  719. if (!(m_PoisonState.nTime % m_PoisonState.nValue[1]))
  720. {
  721. CalcDamage(m_nLastPoisonDamageIdx, m_PoisonState.nValue[0], m_PoisonState.nValue[0], damage_poison, FALSE, FALSE, TRUE);
  722. }
  723. }
  724. // 冰冻状态
  725. if (m_FreezeState.nTime > 0)
  726. {
  727. m_FreezeState.nTime--;
  728. if (m_FreezeState.nTime & 1)
  729. {
  730. nRet = TRUE;
  731. }
  732. }
  733. // 燃烧状态
  734. if (m_BurnState.nTime > 0)
  735. {
  736. m_BurnState.nTime--;
  737. if (m_BurnState.nValue[1] == 0)
  738. {
  739. m_BurnState.nValue[1] = 1;
  740. }
  741. if (!(m_BurnState.nTime % m_BurnState.nValue[1]))
  742. {
  743. CalcDamage(m_Index, m_BurnState.nValue[0], m_BurnState.nValue[0], damage_fire, TRUE, FALSE);
  744. }
  745. }
  746. // 混乱状态
  747. if (m_ConfuseState.nTime > 0)
  748. {
  749. m_ConfuseState.nTime--;
  750. if (m_ConfuseState.nTime <= 0)
  751. {
  752. m_CurrentCamp = m_Camp;
  753. }
  754. }
  755. // 眩晕状态
  756. if (m_StunState.nTime > 0)
  757. {
  758. m_StunState.nTime--;
  759. nRet = TRUE;
  760. }
  761. // 补血状态
  762. if (m_LifeState.nTime > 0)
  763. {
  764. m_LifeState.nTime--;
  765. if (!(m_LifeState.nTime % GAME_UPDATE_TIME))
  766. {
  767. m_CurrentLife += m_LifeState.nValue[0];
  768. if (m_CurrentLife > m_CurrentLifeMax)
  769. {
  770. m_CurrentLife = m_CurrentLifeMax;
  771. }
  772. }
  773. }
  774. // 补MANA状态
  775. if (m_ManaState.nTime > 0)
  776. {
  777. m_ManaState.nTime--;
  778. if (!(m_ManaState.nTime % GAME_UPDATE_TIME))
  779. {
  780. m_CurrentMana += m_ManaState.nValue[0];
  781. if (m_CurrentMana > m_CurrentManaMax)
  782. {
  783. m_CurrentMana = m_CurrentManaMax;
  784. }
  785. }
  786. }
  787. // 醉酒状态
  788. if (m_DrunkState.nTime > 0)
  789. {
  790. m_DrunkState.nTime--;
  791. }
  792. #endif
  793. #ifndef _SERVER
  794. bool bAdjustColorId = false;
  795. if (m_FreezeState.nTime > 0)
  796. {
  797. if (SubWorld[0].m_dwCurrentTime & 1)
  798. nRet = TRUE;
  799. m_DataRes.SetAdjustColorId(KNpcRes::adjustcolor_freeze);
  800. bAdjustColorId = true;
  801. }
  802. if (m_StunState.nTime > 0)
  803. {
  804. m_DataRes.SetAdjustColorId(KNpcRes::adjustcolor_stun);
  805. nRet = TRUE;
  806. bAdjustColorId = true;
  807. }
  808. if (m_PoisonState.nTime > 0)
  809. {
  810. // m_PoisonState.nTime--;
  811. m_DataRes.SetAdjustColorId(KNpcRes::adjustcolor_poison);
  812. bAdjustColorId = true;
  813. }
  814. // 燃烧状态
  815. if (m_BurnState.nTime > 0)
  816. {
  817. // m_BurnState.nTime--;
  818. m_DataRes.SetAdjustColorId(KNpcRes::adjustcolor_burn);
  819. bAdjustColorId = true;
  820. }
  821. // 混乱状态
  822. if (m_ConfuseState.nTime > 0)
  823. {
  824. // m_ConfuseState.nTime--;
  825. m_DataRes.SetAdjustColorId(KNpcRes::adjustcolor_confuse);
  826. bAdjustColorId = true;
  827. }
  828. if (!bAdjustColorId)
  829. m_DataRes.SetAdjustColorId(KNpcRes::adjustcolor_physics);
  830. #endif
  831. KStateNode* pNode;
  832. pNode = (KStateNode *)m_StateSkillList.GetHead();
  833. while(pNode)
  834. {
  835. KStateNode* pTempNode = pNode;
  836. pNode = (KStateNode *)pNode->GetNext();
  837. if (pTempNode->m_LeftTime == -1) // 被动技能
  838. continue;
  839. if (pTempNode->m_LeftTime == 0)
  840. {
  841. int i;
  842. for (i = 0; i < MAX_SKILL_STATE; i++)
  843. {
  844. if (pTempNode->m_State[i].nAttribType)
  845. ModifyAttrib(m_Index, &pTempNode->m_State[i]);
  846. }
  847. _ASSERT(pTempNode != NULL);
  848. pTempNode->Remove();
  849. delete pTempNode;
  850. #ifdef _SERVER
  851. UpdateNpcStateInfo();
  852. BroadCastState();
  853. #endif
  854. pTempNode = NULL;
  855. continue;
  856. }
  857. else
  858. pTempNode->m_LeftTime --;
  859. }
  860. return nRet;
  861. }
  862. void KNpc::DoDeath(int nMode/* = 0*/)
  863. {
  864. // _ASSERT(m_Doing != do_death);
  865. // do_death == 10
  866. //g_DebugLog("[DEATH] m_Doing: %d", m_Doing);
  867. _ASSERT(m_RegionIndex >= 0);
  868. if (m_RegionIndex < 0)
  869. return;
  870. if (m_Doing == do_death)
  871. return;
  872. if (IsPlayer() && !m_FightMode) // 城镇内不会死亡
  873. {
  874. m_CurrentLife = 1;
  875. return;
  876. }
  877. #ifndef _SERVER
  878. if (this->m_Kind == kind_normal)
  879. this->SetBlood(this->m_CurrentLife);
  880. #endif
  881. m_Doing = do_death;
  882. m_ProcessAI = 0;
  883. m_ProcessState = 0;
  884. m_Frames.nTotalFrame = m_DeathFrame;
  885. m_Frames.nCurrentFrame = 0;
  886. m_Height = 0;
  887. #ifdef _SERVER
  888. int nPlayer = 0;
  889. // 杀死玩家不得经验
  890. if (this->m_Kind != kind_player)
  891. {
  892. nPlayer = m_cDeathCalcExp.CalcExp();
  893. }
  894. //丢物品
  895. DeathPunish(nMode, nPlayer);
  896. NPC_DEATH_SYNC NetCommand;
  897. NetCommand.ProtocolType = (BYTE)s2c_npcdeath;
  898. NetCommand.ID = m_dwID;
  899. POINT POff[8] = 
  900. {
  901. {0, 32},
  902. {-16, 32},
  903. {-16, 0},
  904. {-16, -32},
  905. {0, -32},
  906. {16, -32},
  907. {16, 0},
  908. {16, 32},
  909. };
  910. int nMaxCount = MAX_BROADCAST_COUNT;
  911. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  912. int i;
  913. for (i = 0; i < 8; i++)
  914. {
  915. if (CONREGIONIDX(i) == -1)
  916. continue;
  917. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  918. }
  919. #endif
  920. #ifndef _SERVER
  921. m_ClientDoing = cdo_death;
  922. if (Npc[Player[CLIENT_PLAYER_INDEX].m_nIndex].m_nPeopleIdx == m_Index)
  923. {
  924. Npc[Player[CLIENT_PLAYER_INDEX].m_nIndex].m_nPeopleIdx = 0;
  925. }
  926. this->m_cGold.ClientClearState();
  927. #endif
  928. if (IsPlayer())
  929. {
  930. //离队 Not Finish
  931. }
  932. }
  933. void KNpc::OnDeath()
  934. {
  935. if (WaitForFrame())
  936. {
  937. g_DebugLog("[DEATH] WaitForFrame TRUE");
  938. m_Frames.nCurrentFrame = m_Frames.nTotalFrame - 1; // 保证不会有重回第一帧的情况
  939. #ifndef _SERVER
  940. int nTempX, nTempY;
  941. KObjItemInfo sInfo;
  942. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &nTempX, &nTempY);
  943. sInfo.m_nItemID = 0;
  944. sInfo.m_nItemWidth = 0;
  945. sInfo.m_nItemHeight = 0;
  946. sInfo.m_nMoneyNum = 0;
  947. sInfo.m_nColorID = 0;
  948. sInfo.m_nMovieFlag = 0;
  949. sInfo.m_nSoundFlag = 0;
  950. sInfo.m_szName[0] = 0;
  951. ObjSet.ClientAdd(0, m_CorpseSettingIdx, 0, m_Dir, 0, nTempX, nTempY, sInfo);
  952. m_ProcessAI = 1;
  953. #else
  954. //如果当间死者为主角,则看有没有死亡脚本,有则运行。
  955. if (IsPlayer())
  956. {
  957. if (Player[m_nPlayerIdx].m_dwDeathScriptId)
  958. {
  959. char szNpcIndex[30];
  960. sprintf(szNpcIndex, "%d", m_nLastDamageIdx);
  961. Player[m_nPlayerIdx].ExecuteScript(Player[m_nPlayerIdx].m_dwDeathScriptId, "OnDeath", szNpcIndex);
  962. }
  963. }
  964. //如果死者是Npc,而打死他的是主角,并有死亡脚本则运行脚本
  965. else  if (Npc[m_nLastDamageIdx].IsPlayer())
  966. {
  967. int nIdx = Npc[m_nLastDamageIdx].m_nPlayerIdx;
  968. if (nIdx)
  969. {
  970. // 执行战斗npc死亡脚本
  971. if (ActionScript[0])
  972. {
  973. char szNpcIndex[30];
  974. sprintf(szNpcIndex, "%d", m_nLastDamageIdx);
  975. Player[nIdx].ExecuteScript(ActionScript, "OnDeath", szNpcIndex);
  976. }
  977. }
  978. }
  979. if (!IsPlayer())
  980. this->m_cGold.RecoverBackData();
  981. #endif
  982. // 重生点
  983. if (m_Kind != kind_partner)//战斗Npc时
  984. {
  985. DoRevive();
  986. #ifndef _SERVER
  987. // 客户端把NPC删除
  988. if (m_Kind != kind_player)
  989. {
  990. SubWorld[0].m_WorldMessage.Send(GWM_NPC_DEL, m_Index);
  991. return;
  992. }
  993. #endif
  994. }
  995. else // 同伴类?以后再说吧
  996. {
  997. // 以后再说Not Finish
  998. }
  999. }
  1000. else
  1001. {
  1002. g_DebugLog("[DEATH] WaitForFrame FALSE");
  1003. }
  1004. }
  1005. void KNpc::DoDefense()
  1006. {
  1007. m_ProcessAI = 0;
  1008. }
  1009. void KNpc::OnDefense()
  1010. {
  1011. }
  1012. void KNpc::DoIdle()
  1013. {
  1014. if (m_Doing == do_idle)
  1015. return;
  1016. m_Doing = do_idle;
  1017. }
  1018. void KNpc::OnIdle()
  1019. {
  1020. }
  1021. void KNpc::DoHurt(int nHurtFrames, int nX, int nY)
  1022. {
  1023. _ASSERT(m_RegionIndex >= 0);
  1024. #ifndef _SERVER
  1025. m_DataRes.SetBlur(FALSE);
  1026. #endif
  1027. if (m_RegionIndex < 0)
  1028. return;
  1029. if (m_Doing == do_hurt || m_Doing == do_death)
  1030. return;
  1031. // 受击回复速度已经达到100%了,不做受伤动作
  1032. #ifdef _SERVER
  1033. if (m_CurrentHitRecover >= 100)
  1034. return;
  1035. #define MIN_HURT_PERCENT 50
  1036. if (!g_RandPercent(MIN_HURT_PERCENT + m_CurrentHitRecover * (100 - MIN_HURT_PERCENT) / 100))
  1037. {
  1038. return;
  1039. }
  1040. #endif
  1041. m_Doing = do_hurt;
  1042. m_ProcessAI = 0;
  1043. #ifdef _SERVER
  1044. m_Frames.nTotalFrame = m_HurtFrame * (100 - m_CurrentHitRecover) / 100;
  1045. #else
  1046. m_ClientDoing = cdo_hurt;
  1047. m_Frames.nTotalFrame = nHurtFrames;
  1048. m_nHurtDesX = nX;
  1049. m_nHurtDesY = nY;
  1050. if (m_Height > 0)
  1051. {
  1052. // 临时记录下来做为高度变化,在OnHurt中使用
  1053. m_nHurtHeight = m_Height;
  1054. }
  1055. else
  1056. {
  1057. m_nHurtHeight = 0;
  1058. }
  1059. #endif
  1060. if (m_Frames.nTotalFrame == 0)
  1061. m_Frames.nTotalFrame = 1;
  1062. m_Frames.nCurrentFrame = 0;
  1063. #ifdef _SERVER // 向周围9个Region广播发技能
  1064. NPC_HURT_SYNC NetCommand;
  1065. NetCommand.ProtocolType = (BYTE)s2c_npchurt;
  1066. NetCommand.ID = m_dwID;
  1067. NetCommand.nFrames = m_Frames.nTotalFrame;
  1068. GetMpsPos(&NetCommand.nX, &NetCommand.nY);
  1069. POINT POff[8] = 
  1070. {
  1071. {0, 32},
  1072. {-16, 32},
  1073. {-16, 0},
  1074. {-16, -32},
  1075. {0, -32},
  1076. {16, -32},
  1077. {16, 0},
  1078. {16, 32},
  1079. };
  1080. int nMaxCount = MAX_BROADCAST_COUNT;
  1081. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  1082. int i;
  1083. for (i = 0; i < 8; i++)
  1084. {
  1085. if (CONREGIONIDX(i) == -1)
  1086. continue;
  1087. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1088. }
  1089. #endif
  1090. }
  1091. void KNpc::OnHurt()
  1092. {
  1093. if (m_RegionIndex < 0)
  1094. {
  1095. g_DebugLog("[error]%s Region Index < 0 when hurt", Name);
  1096. return;
  1097. }
  1098. int nX, nY;
  1099. GetMpsPos(&nX, &nY);
  1100. #ifdef _SERVER
  1101. m_Height = 0;
  1102. #endif
  1103. #ifndef _SERVER
  1104. m_Height = m_nHurtHeight * (m_Frames.nTotalFrame - m_Frames.nCurrentFrame - 1) / m_Frames.nTotalFrame;
  1105. nX = nX + (m_nHurtDesX - nX) * m_Frames.nCurrentFrame / m_Frames.nTotalFrame;
  1106. nY = nY + (m_nHurtDesY - nY) * m_Frames.nCurrentFrame / m_Frames.nTotalFrame;
  1107. int nOldRegion = m_RegionIndex;
  1108. //SetPos(nX, nY);
  1109. CURREGION.DecRef(m_MapX, m_MapY, obj_npc);
  1110. int nRegion, nMapX, nMapY, nOffX, nOffY;
  1111. nRegion = -1;
  1112. nMapX = nMapY = nOffX = nOffY = 0;
  1113. SubWorld[m_SubWorldIndex].Mps2Map(nX, nY, &nRegion, &nMapX, &nMapY, &nOffX, &nOffY);
  1114. if (nRegion == -1)
  1115. {
  1116. SubWorld[0].m_Region[nOldRegion].RemoveNpc(m_Index);
  1117. m_dwRegionID = 0;
  1118. }
  1119. else if (nOldRegion != nRegion)
  1120. {
  1121. m_RegionIndex = nRegion;
  1122. m_MapX = nMapX;
  1123. m_MapY = nMapY;
  1124. m_OffX = nOffX;
  1125. m_OffY = nOffY;
  1126. SubWorld[0].NpcChangeRegion(SubWorld[0].m_Region[nOldRegion].m_RegionID, SubWorld[0].m_Region[m_RegionIndex].m_RegionID, m_Index);
  1127. m_dwRegionID = SubWorld[0].m_Region[m_RegionIndex].m_RegionID;
  1128. }
  1129. if (nRegion >= 0)
  1130. CURREGION.AddRef(m_MapX, m_MapY, obj_npc);
  1131. #endif
  1132. if (WaitForFrame())
  1133. {
  1134. g_DebugLog("[DEATH]On Hurt Finished");
  1135. DoStand();
  1136. m_ProcessAI = 1;
  1137. }
  1138. }
  1139. void KNpc::DoSpecial1()
  1140. {
  1141. DoBlurAttack();
  1142. }
  1143. void KNpc::OnSpecial1()
  1144. {
  1145. if (WaitForFrame() &&m_Frames.nTotalFrame != 0)
  1146. {
  1147. #ifndef _SERVER
  1148. m_DataRes.SetBlur(FALSE);
  1149. #endif
  1150. DoStand();
  1151. m_ProcessAI = 1;
  1152. }
  1153. else if (IsReachFrame(ATTACKACTION_EFFECT_PERCENT))
  1154. {
  1155. KSkill * pSkill = (KSkill*)GetActiveSkill();
  1156. if (pSkill)
  1157. {
  1158. int nChildSkill = pSkill->GetChildSkillId();
  1159. int nChildSkillLevel = pSkill->m_ulLevel;
  1160. if (nChildSkill > 0)
  1161. {
  1162. KSkill * pChildSkill = (KSkill*)g_SkillManager.GetSkill(nChildSkill, nChildSkillLevel);
  1163. if (pChildSkill)
  1164. {
  1165. pChildSkill->Cast(m_Index, m_SkillParam1, m_SkillParam2);
  1166. }
  1167. }
  1168. }
  1169. if (m_Frames.nTotalFrame == 0)
  1170. {
  1171. m_ProcessAI = 1;
  1172. }
  1173. }
  1174. }
  1175. void KNpc::DoSpecial2()
  1176. {
  1177. }
  1178. void KNpc::OnSpecial2()
  1179. {
  1180. if (WaitForFrame() &&m_Frames.nTotalFrame != 0)
  1181. {
  1182. #ifndef _SERVER
  1183. m_DataRes.SetBlur(FALSE);
  1184. #endif
  1185. DoStand();
  1186. m_ProcessAI = 1;
  1187. }
  1188. else if (IsReachFrame(ATTACKACTION_EFFECT_PERCENT))
  1189. {
  1190. ISkill * pSkill = GetActiveSkill();
  1191. eSkillStyle eStyle = (eSkillStyle)pSkill->GetSkillStyle();
  1192. switch(eStyle)
  1193. {
  1194. case SKILL_SS_Thief:
  1195. {
  1196. ( (KThiefSkill*)pSkill )->OnSkill(this);
  1197. }
  1198. break;
  1199. if (m_Frames.nTotalFrame == 0)
  1200. {
  1201. m_ProcessAI = 1;
  1202. }
  1203. }
  1204. }
  1205. void KNpc::DoSpecial3()
  1206. {
  1207. }
  1208. void KNpc::OnSpecial3()
  1209. {
  1210. }
  1211. void KNpc::DoSpecial4()
  1212. {
  1213. }
  1214. void KNpc::OnSpecial4()
  1215. {
  1216. }
  1217. void KNpc::DoStand()
  1218. {
  1219. m_Frames.nTotalFrame = m_StandFrame;
  1220. if (m_Doing == do_stand)
  1221. {
  1222. return;
  1223. }
  1224. else
  1225. {
  1226. m_Doing = do_stand;
  1227. m_Frames.nCurrentFrame = 0;
  1228. GetMpsPos(&m_DesX, &m_DesY);
  1229. #ifndef _SERVER
  1230. if (m_FightMode)
  1231. m_ClientDoing = cdo_fightstand;
  1232. else if (g_Random(6) != 1)
  1233. {
  1234. m_ClientDoing = cdo_stand;
  1235. }
  1236. else
  1237. {
  1238. m_ClientDoing = cdo_stand1;
  1239. }
  1240. m_DataRes.StopSound();
  1241. #endif
  1242. }
  1243. }
  1244. void KNpc::OnStand()
  1245. {
  1246. if (WaitForFrame())
  1247. {
  1248. #ifndef _SERVER
  1249. if (m_FightMode)
  1250. {
  1251. m_ClientDoing = cdo_fightstand;
  1252. }
  1253. else if (g_Random(6) != 1)
  1254. {
  1255. m_ClientDoing = cdo_stand;
  1256. }
  1257. else
  1258. {
  1259. m_ClientDoing = cdo_stand1;
  1260. }
  1261. #endif
  1262. }
  1263. }
  1264. void KNpc::DoRevive()
  1265. {
  1266. if (m_RegionIndex < 0)
  1267. {
  1268. g_DebugLog("[error]%s Region Index < 0 when dorevive", Name);
  1269. return;
  1270. }
  1271. if (m_Doing == do_revive)
  1272. {
  1273. return;
  1274. }
  1275. else
  1276. {
  1277. m_Doing = do_revive;
  1278. m_ProcessAI = 0;
  1279. m_ProcessState = 0;
  1280. ClearStateSkillEffect();
  1281. ClearNormalState();
  1282. #ifdef _SERVER
  1283. if (IsPlayer())
  1284. return;
  1285. m_Frames.nTotalFrame = m_ReviveFrame;
  1286. SubWorld[m_SubWorldIndex].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  1287. SubWorld[m_SubWorldIndex].NpcChangeRegion(m_RegionIndex, VOID_REGION, m_Index); // spe 03/06/28
  1288. m_Frames.nCurrentFrame = 0;
  1289. #else
  1290. // 客户端
  1291. if (IsPlayer())
  1292. {
  1293. KSystemMessage Msg;
  1294. Msg.byConfirmType = SMCT_UI_RENASCENCE;
  1295. Msg.byParamSize = 0;
  1296. Msg.byPriority = 255;
  1297. Msg.eType = SMT_PLAYER;
  1298. sprintf(Msg.szMessage, MSG_NPC_DEATH, Name);
  1299. CoreDataChanged(GDCNI_SYSTEM_MESSAGE, (unsigned int)&Msg, NULL);
  1300. }
  1301. m_Frames.nTotalFrame = m_DeathFrame;
  1302. m_ClientDoing = cdo_death;
  1303. #endif
  1304. }
  1305. }
  1306. void KNpc::OnRevive()
  1307. {
  1308. #ifdef _SERVER
  1309. if (!IsPlayer() && WaitForFrame())
  1310. {
  1311. Revive();
  1312. }
  1313. #else // 客户端
  1314. m_Frames.nCurrentFrame = m_Frames.nTotalFrame - 1;
  1315. #endif
  1316. }
  1317. void KNpc::DoRun()
  1318. {
  1319. _ASSERT(m_RegionIndex >= 0);
  1320. if (m_CurrentRunSpeed)
  1321. m_Frames.nTotalFrame = (m_RunFrame * m_RunSpeed) / m_CurrentRunSpeed;
  1322. else
  1323. m_Frames.nTotalFrame = m_RunFrame;
  1324. #ifndef _SERVER
  1325. if (m_FightMode)
  1326. {
  1327. m_ClientDoing = cdo_fightrun;
  1328. }
  1329. else
  1330. {
  1331. m_ClientDoing = cdo_run;
  1332. }
  1333. #endif
  1334. if (IsPlayer())
  1335. {
  1336. /* if (!Cost(attrib_stamina, m_CurrentStaminaLoss))
  1337. {
  1338. DoWalk();
  1339. return;
  1340. }*/
  1341. }
  1342. #ifdef _SERVER
  1343. NPC_RUN_SYNC NetCommand;
  1344. NetCommand.ProtocolType = (BYTE)s2c_npcrun;
  1345. NetCommand.ID = m_dwID;
  1346. NetCommand.nMpsX = m_DesX;
  1347. NetCommand.nMpsY = m_DesY;
  1348. POINT POff[8] = 
  1349. {
  1350. {0, 32},
  1351. {-16, 32},
  1352. {-16, 0},
  1353. {-16, -32},
  1354. {0, -32},
  1355. {16, -32},
  1356. {16, 0},
  1357. {16, 32},
  1358. };
  1359. int nMaxCount = MAX_BROADCAST_COUNT;
  1360. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  1361. int i;
  1362. for (i = 0; i < 8; i++)
  1363. {
  1364. if (CONREGIONIDX(i) == -1)
  1365. continue;
  1366. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1367. }
  1368. #endif
  1369. if (m_Doing == do_run)
  1370. {
  1371. return;
  1372. }
  1373. m_Doing = do_run;
  1374. m_Frames.nCurrentFrame = 0;
  1375. }
  1376. void KNpc::OnRun()
  1377. {
  1378. WaitForFrame();
  1379. ServeMove(m_CurrentRunSpeed);
  1380. }
  1381. void KNpc::DoSit()
  1382. {
  1383. _ASSERT(m_RegionIndex >= 0);
  1384. if (m_Doing == do_sit)
  1385. {
  1386. // DoStand();
  1387. return;
  1388. }
  1389. m_Doing = do_sit;
  1390. #ifdef _SERVER // 向周围9个Region广播发技能
  1391. NPC_SIT_SYNC NetCommand;
  1392. NetCommand.ProtocolType = (BYTE)s2c_npcsit;
  1393. NetCommand.ID = m_dwID;
  1394. POINT POff[8] = 
  1395. {
  1396. {0, 32},
  1397. {-16, 32},
  1398. {-16, 0},
  1399. {-16, -32},
  1400. {0, -32},
  1401. {16, -32},
  1402. {16, 0},
  1403. {16, 32},
  1404. };
  1405. int nMaxCount = MAX_BROADCAST_COUNT;
  1406. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  1407. int i;
  1408. for (i = 0; i < 8; i++)
  1409. {
  1410. if (CONREGIONIDX(i) == -1)
  1411. continue;
  1412. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1413. }
  1414. #endif
  1415. #ifndef _SERVER
  1416. m_ClientDoing = cdo_sit;
  1417. #endif
  1418. m_Frames.nTotalFrame = m_SitFrame;
  1419. m_Frames.nCurrentFrame = 0;
  1420. }
  1421. void KNpc::OnSit()
  1422. {
  1423. // 体力换内力(没有设定)
  1424. if (WaitForFrame())
  1425. {
  1426. m_Frames.nCurrentFrame = m_Frames.nTotalFrame - 1;
  1427. }
  1428. }
  1429. void KNpc::DoSkill(int nX, int nY)
  1430. {
  1431. _ASSERT(m_RegionIndex >= 0);
  1432. if (m_Doing == do_skill)
  1433. return;
  1434. // 非战斗状态不能发技能
  1435. if (IsPlayer())
  1436. {
  1437. if (!m_FightMode)
  1438. return;
  1439. #ifdef _SERVER
  1440. if (m_nPlayerIdx > 0)
  1441. Player[m_nPlayerIdx].m_ItemList.Abrade(enumAbradeAttack);
  1442. #endif
  1443. }
  1444. ISkill * pSkill = GetActiveSkill();
  1445. if(pSkill)
  1446. {
  1447. eSkillStyle eStyle = (eSkillStyle)pSkill->GetSkillStyle();
  1448. if (m_SkillList.CanCast(m_ActiveSkillID, SubWorld[m_SubWorldIndex].m_dwCurrentTime)
  1449. && pSkill->CanCastSkill(m_Index, nX, nY) 
  1450. && 
  1451. ( m_Kind != kind_player 
  1452. || Cost(pSkill->GetSkillCostType(), pSkill->GetSkillCost(this))
  1453. )
  1454. )
  1455. {
  1456. /*------------------------------------------------------------------------------------
  1457. 发技能时,当需指定目标对象时,传至Skill.Cast的两个参数第一个参数为-1,第二个为Npc index
  1458. 在S2C时,第二个参数必须由Server的NpcIndex转为NpcdwID参出去。
  1459. 在C收到该指令时,将NpcdwID转为本机的NpcIndex
  1460. -------------------------------------------------------------------------------------*/
  1461. #ifdef _SERVER // 向周围9个Region广播发技能
  1462. NPC_SKILL_SYNC NetCommand;
  1463. NetCommand.ProtocolType = (BYTE)s2c_skillcast;
  1464. NetCommand.ID = m_dwID;
  1465. NetCommand.nSkillID = m_ActiveSkillID;
  1466. NetCommand.nSkillLevel = m_SkillList.GetCurrentLevel(m_ActiveSkillID);
  1467. if (nY <= 0 ) 
  1468. {
  1469. DoStand();
  1470. return;
  1471. }
  1472. NetCommand.nMpsX = nX;
  1473. if (nX == -1) //m_nDesX == -1 means attack someone whose id is DesY , and if m_nDesX == -2 means attack at somedir
  1474. {
  1475. NetCommand.nMpsY = Npc[nY].m_dwID;
  1476. if (0 == NetCommand.nMpsY || Npc[nY].m_SubWorldIndex != m_SubWorldIndex)
  1477. return;
  1478. }
  1479. else
  1480. {
  1481. NetCommand.nMpsY = nY;
  1482. }
  1483. m_SkillParam1 = nX;
  1484. m_SkillParam2 = nY;
  1485. m_DesX = nX;
  1486. m_DesY = nY;
  1487. POINT POff[8] = 
  1488. {
  1489. {0, 32},
  1490. {-16, 32},
  1491. {-16, 0},
  1492. {-16, -32},
  1493. {0, -32},
  1494. {16, -32},
  1495. {16, 0},
  1496. {16, 32},
  1497. };
  1498. int nMaxCount = MAX_BROADCAST_COUNT;
  1499. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  1500. int i;
  1501. for (i = 0; i < 8; i++)
  1502. {
  1503. if (CONREGIONIDX(i) == -1)
  1504. continue;
  1505. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1506. }
  1507. #endif
  1508. if (eStyle == SKILL_SS_Missles 
  1509. || eStyle == SKILL_SS_Melee 
  1510. || eStyle == SKILL_SS_InitiativeNpcState 
  1511. || eStyle == SKILL_SS_PassivityNpcState)
  1512. {
  1513. DoOrdinSkill((KSkill *) pSkill, nX, nY);
  1514. }
  1515. else
  1516. {
  1517. switch(eStyle)
  1518. {
  1519. case SKILL_SS_Thief:
  1520. {
  1521. ((KThiefSkill*)pSkill)->DoSkill(this, nX, nY);
  1522. }break;
  1523. default:
  1524. return;
  1525. }
  1526. }
  1527. }
  1528. else
  1529. {
  1530. m_nPeopleIdx = 0;
  1531. m_nObjectIdx = 0;
  1532. DoStand();
  1533. }
  1534. }
  1535. else
  1536. {
  1537. _ASSERT(pSkill);
  1538. }
  1539. int KNpc::DoOrdinSkill(KSkill * pSkill, int nX, int nY)
  1540. {
  1541. _ASSERT(pSkill);
  1542. #ifndef _SERVER
  1543. m_DataRes.StopSound();
  1544. int x, y, tx, ty;
  1545. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, m_OffX, m_OffY, &x, &y);
  1546. if (nY < 0)
  1547. return 0;
  1548. if (nX < 0)
  1549. {
  1550. if (nX != -1) 
  1551. return 0;
  1552. if (nY >= MAX_NPC || Npc[nY].m_dwID == 0 || Npc[nY].m_SubWorldIndex != m_SubWorldIndex)
  1553. return 0;
  1554. Npc[nY].GetMpsPos(&tx, &ty);
  1555. }
  1556. else
  1557. {
  1558. tx = nX;
  1559. ty = nY;
  1560. }
  1561. m_SkillParam1 = nX;
  1562. m_SkillParam2 = nY;
  1563. m_DesX = nX;
  1564. m_DesY = nY;
  1565. m_Dir = g_GetDirIndex(x, y, tx, ty);
  1566. if (pSkill->GetPreCastEffectFile()[0])
  1567. m_DataRes.SetSpecialSpr((char *)pSkill->GetPreCastEffectFile());
  1568. if (IsPlayer())
  1569. pSkill->PlayPreCastSound(m_nSex,x, y);
  1570. if (pSkill->IsNeedShadow())
  1571. m_DataRes.SetBlur(TRUE);
  1572. else
  1573. m_DataRes.SetBlur(FALSE);
  1574. #endif
  1575. CLIENTACTION ClientDoing = pSkill->GetActionType();
  1576. #ifndef _SERVER
  1577. if (ClientDoing >= cdo_count) 
  1578. m_ClientDoing = cdo_magic;
  1579. else if (ClientDoing != cdo_none)
  1580. m_ClientDoing = ClientDoing;
  1581. #endif
  1582. if (pSkill->GetSkillStyle() == SKILL_SS_Melee)
  1583. {
  1584. if (CastMeleeSkill(pSkill) == FALSE)
  1585. {
  1586. m_nPeopleIdx = 0;
  1587. m_nObjectIdx = 0;
  1588. m_ProcessAI = 1;
  1589. DoStand();
  1590. return 1 ;
  1591. }
  1592. }
  1593. //物理技能的技能释放时间与普通技能不同,一个是AttackFrame,一个是CastFrame
  1594. else if (pSkill->IsPhysical())
  1595. {
  1596. if (ClientDoing == cdo_none) 
  1597. m_Frames.nTotalFrame = 0;
  1598. else
  1599. m_Frames.nTotalFrame = m_AttackFrame * 100 / (100 + m_CurrentAttackSpeed);
  1600. #ifndef _SERVER
  1601. if (g_Random(3))
  1602. m_ClientDoing = cdo_attack;
  1603. else 
  1604. m_ClientDoing = cdo_attack1;
  1605. #endif
  1606. m_Doing = do_attack;
  1607. }
  1608. else
  1609. {
  1610. if (ClientDoing == cdo_none) 
  1611. m_Frames.nTotalFrame = 0;
  1612. else
  1613. m_Frames.nTotalFrame = m_CastFrame * 100 / (m_CurrentCastSpeed + 100);
  1614. m_Doing  = do_magic;
  1615. }
  1616. m_ProcessAI = 0;
  1617. m_Frames.nCurrentFrame = 0;
  1618. return 1;
  1619. }
  1620. void KNpc::DoAttack()
  1621. {
  1622. if (m_Doing == do_attack)
  1623. return;
  1624. #ifndef _SERVER
  1625. if (g_Random(2) == 1)
  1626. {
  1627. m_ClientDoing = cdo_attack;
  1628. }
  1629. else
  1630. {
  1631. m_ClientDoing = cdo_attack1;
  1632. }
  1633. #endif
  1634. m_ProcessAI = 0;
  1635. m_Frames.nTotalFrame = m_AttackFrame * 100 / (100 + m_CurrentAttackSpeed);
  1636. m_Frames.nCurrentFrame = 0;
  1637. m_Doing = do_attack;
  1638. }
  1639. BOOL KNpc::CastMeleeSkill(KSkill * pSkill)
  1640. {
  1641. BOOL bSuceess = FALSE;
  1642. _ASSERT(pSkill);
  1643. switch(pSkill->GetMeleeType())
  1644. {
  1645. case Melee_AttackWithBlur:
  1646. {
  1647. bSuceess = DoBlurAttack();
  1648. }break;
  1649. case Melee_Jump:
  1650. {
  1651. if (NewJump(m_DesX, m_DesY))
  1652. {
  1653. DoJump();
  1654. bSuceess = TRUE;
  1655. }
  1656. }break;
  1657. case Melee_JumpAndAttack:
  1658. {
  1659. if (m_DesX < 0 && m_DesY > 0) 
  1660. {
  1661. int x, y;
  1662. SubWorld[m_SubWorldIndex].Map2Mps
  1663. (
  1664. Npc[m_DesY].m_RegionIndex,
  1665. Npc[m_DesY].m_MapX, 
  1666. Npc[m_DesY].m_MapY, 
  1667. Npc[m_DesY].m_OffX, 
  1668. Npc[m_DesY].m_OffY, 
  1669. &x,
  1670. &y
  1671. );
  1672. m_DesX = x + 1;
  1673. m_DesY = y;
  1674. }
  1675. if (NewJump(m_DesX, m_DesY))
  1676. {
  1677. DoJumpAttack();
  1678. bSuceess = TRUE;
  1679. }
  1680. }break;
  1681. case Melee_RunAndAttack:
  1682. {
  1683. bSuceess = DoRunAttack();
  1684. }break;
  1685. case Melee_ManyAttack:
  1686. {
  1687. bSuceess = DoManyAttack();
  1688. }break;
  1689. default:
  1690. m_ProcessAI = 1;
  1691. break;
  1692. }
  1693. return bSuceess;
  1694. }
  1695. BOOL KNpc::DoBlurAttack()// DoSpecail1
  1696. {
  1697. if (m_Doing == do_special1)
  1698. return FALSE;
  1699. KSkill * pSkill = (KSkill*) GetActiveSkill();
  1700. if (!pSkill) 
  1701.         return FALSE;
  1702. _ASSERT(pSkill->GetSkillStyle() == SKILL_SS_Melee);
  1703. #ifndef _SERVER
  1704. m_ClientDoing = pSkill->GetActionType();
  1705. m_DataRes.SetBlur(TRUE);
  1706. #endif
  1707. m_Frames.nTotalFrame = m_AttackFrame * 100 / (100 + m_CurrentAttackSpeed);
  1708. m_Frames.nCurrentFrame = 0;
  1709. m_Doing = do_special1;
  1710. return TRUE;
  1711. }
  1712. void KNpc::DoMagic()
  1713. {
  1714. if (m_Doing == do_magic)
  1715. return;
  1716. m_ProcessAI = 0;
  1717. #ifndef _SERVER
  1718. m_ClientDoing = cdo_magic;
  1719. #endif
  1720. m_Frames.nTotalFrame = m_CastFrame * 100 / (m_CurrentCastSpeed + 100);
  1721. m_Frames.nCurrentFrame = 0;
  1722. m_Doing = do_magic;
  1723. }
  1724. void KNpc::OnSkill()
  1725. {
  1726. KSkill * pSkill = NULL;
  1727. if (WaitForFrame() &&m_Frames.nTotalFrame != 0)
  1728. {
  1729. DoStand();
  1730. m_ProcessAI = 1;
  1731. }
  1732. else if (IsReachFrame(ATTACKACTION_EFFECT_PERCENT))
  1733. {
  1734. #ifndef _SERVER
  1735. m_DataRes.SetBlur(FALSE);
  1736. #endif
  1737. if (m_DesX == -1) 
  1738. {
  1739. if (m_DesY <= 0) 
  1740. goto Label_ProcessAI;
  1741. //此时该角色已经无效时
  1742. if (Npc[m_DesY].m_RegionIndex < 0) 
  1743. goto Label_ProcessAI;
  1744. }
  1745. pSkill =(KSkill*) GetActiveSkill();
  1746. if (pSkill)
  1747. {
  1748. pSkill->Cast(m_Index, m_DesX, m_DesY);
  1749. m_SkillList.SetNextCastTime(m_ActiveSkillID, SubWorld[m_SubWorldIndex].m_dwCurrentTime + pSkill->GetDelayPerCast());
  1750. }
  1751. Label_ProcessAI:
  1752. if (m_Frames.nTotalFrame == 0)
  1753. {
  1754. m_ProcessAI = 1;
  1755. }
  1756. }
  1757. }
  1758. void KNpc::JumpTo(int nMpsX, int nMpsY)
  1759. {
  1760. if (NewJump(nMpsX, nMpsY))
  1761. DoJump();
  1762. else
  1763. {
  1764. RunTo(nMpsX, nMpsY);
  1765. }
  1766. }
  1767. void KNpc::RunTo(int nMpsX, int nMpsY)
  1768. {
  1769. if (NewPath(nMpsX, nMpsY))
  1770. DoRun();
  1771. }
  1772. void KNpc::Goto(int nMpsX, int nMpsY)
  1773. {
  1774. if (NewPath(nMpsX, nMpsY))
  1775. DoWalk();
  1776. }
  1777. void KNpc::DoWalk()
  1778. {
  1779. _ASSERT(m_RegionIndex >= 0);
  1780. if (m_CurrentWalkSpeed)
  1781. m_Frames.nTotalFrame = (m_WalkFrame * m_WalkSpeed) / m_CurrentWalkSpeed + 1;
  1782. else
  1783. m_Frames.nTotalFrame = m_WalkFrame;
  1784. #ifdef _SERVER // Server端的代码
  1785. NPC_WALK_SYNC NetCommand;
  1786. NetCommand.ProtocolType = (BYTE)s2c_npcwalk;
  1787. NetCommand.ID = m_dwID;
  1788. NetCommand.nMpsX = m_DesX;
  1789. NetCommand.nMpsY = m_DesY;
  1790. POINT POff[8] = 
  1791. {
  1792. {0, 32},
  1793. {-16, 32},
  1794. {-16, 0},
  1795. {-16, -32},
  1796. {0, -32},
  1797. {16, -32},
  1798. {16, 0},
  1799. {16, 32},
  1800. };
  1801. int nMaxCount = MAX_BROADCAST_COUNT;
  1802. CURREGION.BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX, m_MapY);
  1803. int i;
  1804. for (i = 0; i < 8; i++)
  1805. {
  1806. if (CONREGIONIDX(i) == -1)
  1807. continue;
  1808. CONREGION(i).BroadCast(&NetCommand, sizeof(NetCommand), nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1809. }
  1810. #endif
  1811. if (m_Doing == do_walk)
  1812. {
  1813. return;
  1814. }
  1815. m_Doing = do_walk;
  1816. m_Frames.nCurrentFrame = 0;
  1817. #ifndef _SERVER
  1818. if (m_FightMode)
  1819. {
  1820. m_ClientDoing = cdo_fightwalk;
  1821. }
  1822. else
  1823. {
  1824. m_ClientDoing = cdo_walk;
  1825. }
  1826. #endif
  1827. }
  1828. void KNpc::DoPlayerTalk(char * szTalk)
  1829. {
  1830. #ifdef _SERVER
  1831. _ASSERT(m_RegionIndex >= 0);
  1832. int nTalkLen = strlen(szTalk);
  1833. if (!nTalkLen) return;
  1834. BYTE * pNetCommand = new  BYTE[nTalkLen + 6 + 1];
  1835. pNetCommand[0] = (BYTE)s2c_playertalk;
  1836. *(DWORD *)(pNetCommand + 1) = m_dwID;
  1837. pNetCommand[5] = nTalkLen;
  1838. strcpy((char*)(pNetCommand + 6), szTalk);
  1839. pNetCommand[nTalkLen + 6 ] = '';
  1840. POINT POff[8] = 
  1841. {
  1842. {0, 32},
  1843. {-16, 32},
  1844. {-16, 0},
  1845. {-16, -32},
  1846. {0, -32},
  1847. {16, -32},
  1848. {16, 0},
  1849. {16, 32},
  1850. };
  1851. int nMaxCount = MAX_BROADCAST_COUNT;
  1852. CURREGION.BroadCast(pNetCommand, nTalkLen + 6 + 1, nMaxCount, m_MapX, m_MapY);
  1853. int i;
  1854. for (i = 0; i < 8; i++)
  1855. {
  1856. if (CONREGIONIDX(i) == -1)
  1857. continue;
  1858. CONREGION(i).BroadCast(pNetCommand, nTalkLen + 6 + 1, nMaxCount, m_MapX - POff[i].x, m_MapY - POff[i].y);
  1859. }
  1860. if (pNetCommand)
  1861. {
  1862. delete [] pNetCommand;
  1863. }
  1864. #endif
  1865. }
  1866. void KNpc::OnPlayerTalk()
  1867. {
  1868. }
  1869. void KNpc::OnWalk()
  1870. {
  1871. #ifndef _SERVER
  1872. // 处理客户端的动画换帧等……
  1873. #endif
  1874. WaitForFrame();
  1875. ServeMove(m_CurrentWalkSpeed);
  1876. }
  1877. int KNpc::GetSkillLevel(int nSkillId)
  1878. {
  1879. int nIndex = m_SkillList.FindSame(nSkillId);
  1880. if (nIndex)
  1881. {
  1882. return m_SkillList.m_Skills[nIndex].SkillLevel;
  1883. }
  1884. else
  1885. {
  1886. return 0;
  1887. }
  1888. }
  1889. void KNpc::ModifyAttrib(int nAttacker, void* pData)
  1890. {
  1891. if (pData != NULL)
  1892. g_NpcAttribModify.ModifyAttrib(this, pData);
  1893. }
  1894. #ifdef _SERVER
  1895. void KNpc::CalcDamage(int nAttacker, int nMin, int nMax, DAMAGE_TYPE nType, BOOL bIsMelee, BOOL bDoHurt /* TRUE */, BOOL bReturn /* = FALSE */)
  1896. {
  1897. if (m_Doing == do_death || m_RegionIndex < 0)
  1898. return;
  1899. if (nMin + nMax <= 0)
  1900. return;
  1901. int nRes = 0;
  1902. int nDamageRange = nMax - nMin;
  1903. int nDamage = 0;
  1904. if (nDamageRange < 0) 
  1905. {
  1906. nDamage = nMax + g_Random(-nDamageRange);
  1907. }
  1908. else
  1909. nDamage = nMin + g_Random(nMax - nMin);
  1910. // 第一步,统计抗性,并计算吸收伤害
  1911. switch(nType)
  1912. {
  1913. case damage_physics:
  1914. nRes = m_CurrentPhysicsResist;
  1915. if (nRes > m_CurrentPhysicsResistMax)
  1916. {
  1917. nRes = m_CurrentPhysicsResistMax;
  1918. }
  1919. if (nRes > MAX_RESIST)
  1920. {
  1921. nRes = MAX_RESIST;
  1922. }
  1923. g_DebugLog("[数值]%s受到%d点原始物理伤害,物理抗性%d,物理盾%d", Name, nDamage, nRes, m_PhysicsArmor.nValue[0]);
  1924. m_PhysicsArmor.nValue[0] -= nDamage;
  1925. if (m_PhysicsArmor.nValue[0] < 0)
  1926. {
  1927. nDamage = -m_PhysicsArmor.nValue[0];
  1928. m_PhysicsArmor.nValue[0] = 0;
  1929. m_PhysicsArmor.nTime = 0;
  1930. }
  1931. else
  1932. {
  1933. nDamage = 0;
  1934. }
  1935. if (bIsMelee)
  1936. {
  1937. nMax = m_CurrentMeleeDmgRetPercent;
  1938. }
  1939. else
  1940. {
  1941. nMax = m_CurrentRangeDmgRetPercent;
  1942. }
  1943. break;
  1944. case damage_cold:
  1945. nRes = m_CurrentColdResist;
  1946. if (nRes > m_CurrentColdResistMax)
  1947. {
  1948. nRes = m_CurrentColdResistMax;
  1949. }
  1950. if (nRes > MAX_RESIST)
  1951. {
  1952. nRes = MAX_RESIST;
  1953. }
  1954. g_DebugLog("[数值]%s受到%d点原始冰伤害,冰抗性%d,冰盾%d", Name, nDamage, nRes, m_ColdArmor.nValue[0]);
  1955. m_ColdArmor.nValue[0] -= nDamage;
  1956. if (m_ColdArmor.nValue[0] < 0)
  1957. {
  1958. nDamage = -m_ColdArmor.nValue[0];
  1959. m_ColdArmor.nValue[0] = 0;
  1960. m_ColdArmor.nTime = 0;
  1961. }
  1962. else
  1963. {
  1964. nDamage = 0;
  1965. }
  1966. nMax = m_CurrentRangeDmgRetPercent;
  1967. break;
  1968. case damage_fire:
  1969. nRes = m_CurrentFireResist;
  1970. if (nRes > m_CurrentFireResistMax)
  1971. {
  1972. nRes = m_CurrentFireResistMax;
  1973. }
  1974. if (nRes > MAX_RESIST)
  1975. {
  1976. nRes = MAX_RESIST;
  1977. }
  1978. g_DebugLog("[数值]%s受到%d点原始火伤害,火抗性%d,火盾%d", Name, nDamage, nRes, m_FireArmor.nValue[0]);
  1979. m_FireArmor.nValue[0] -= nDamage;
  1980. if (m_FireArmor.nValue[0] < 0)
  1981. {
  1982. nDamage = -m_FireArmor.nValue[0];
  1983. m_FireArmor.nValue[0] = 0;
  1984. m_FireArmor.nTime = 0;
  1985. }
  1986. else
  1987. {
  1988. nDamage = 0;
  1989. }
  1990. nMax = m_CurrentRangeDmgRetPercent;
  1991. break;
  1992. case damage_light:
  1993. nRes = m_CurrentLightResist;
  1994. if (nRes > m_CurrentLightResistMax)
  1995. {
  1996. nRes = m_CurrentLightResistMax;
  1997. }
  1998. if (nRes > MAX_RESIST)
  1999. {
  2000. nRes = MAX_RESIST;
  2001. }
  2002. g_DebugLog("[数值]%s受到%d点原始电伤害,电抗性%d,电盾%d", Name, nDamage, nRes, m_LightArmor.nValue[0]);
  2003. m_LightArmor.nValue[0] -= nDamage;
  2004. if (m_LightArmor.nValue[0] < 0)
  2005. {
  2006. nDamage = -m_LightArmor.nValue[0];
  2007. m_LightArmor.nValue[0] = 0;
  2008. m_LightArmor.nTime = 0;
  2009. }
  2010. else
  2011. {
  2012. nDamage = 0;
  2013. }
  2014. nMax = m_CurrentRangeDmgRetPercent;
  2015. break;
  2016. case damage_poison:
  2017. g_DebugLog("[数值]%s受到%d点原始毒伤害", Name, nDamage);
  2018. nRes = m_CurrentPoisonResist;
  2019. if (nRes > m_CurrentPoisonResistMax)
  2020. {
  2021. nRes = m_CurrentPoisonResistMax;
  2022. }
  2023. if (nRes > MAX_RESIST)
  2024. {
  2025. nRes = MAX_RESIST;
  2026. }
  2027. g_DebugLog("[数值]%s受到%d点原始毒伤害,毒抗性%d,毒盾%d", Name, nDamage, nRes, m_PoisonArmor.nValue[0]);
  2028. m_PoisonArmor.nValue[0] -= nDamage;
  2029. if (m_PoisonArmor.nValue[0] < 0)
  2030. {
  2031. nDamage = -m_PoisonArmor.nValue[0];
  2032. m_PoisonArmor.nValue[0] = 0;
  2033. m_PoisonArmor.nTime = 0;
  2034. }
  2035. else
  2036. {
  2037. nDamage = 0;
  2038. }
  2039. nMax = m_CurrentRangeDmgRetPercent;
  2040. m_nLastPoisonDamageIdx = nAttacker;
  2041. break;
  2042. case damage_magic:
  2043. g_DebugLog("[数值]%s受到%d点原始魔法伤害", Name, nDamage);
  2044. nRes = 0;
  2045. break;
  2046. default:
  2047. nRes = 0;
  2048. break;
  2049. }
  2050. if (!nDamage)
  2051. return;
  2052. // 第二步判断是否有魔法盾存在
  2053. g_DebugLog("[数值]%s魔法盾吸收比例:%d", Name, m_ManaShield.nValue[0]);
  2054. if (m_ManaShield.nValue[0])
  2055. {
  2056. int nManaDamage = nDamage * m_ManaShield.nValue[0] / 100;
  2057. m_CurrentMana -= nManaDamage;
  2058. if (m_CurrentMana < 0)
  2059. {
  2060. nDamage -= m_CurrentMana;
  2061. m_CurrentMana = 0;
  2062. m_ManaShield.nValue[0] = 0;
  2063. m_ManaShield.nTime = 0;
  2064. }
  2065. else
  2066. {
  2067. nDamage -= nManaDamage;
  2068. }
  2069. }
  2070. nDamage = nDamage * (100 - nRes) / 100;
  2071. g_DebugLog("[数值]%s实际伤害:%d", Name, nDamage);
  2072. // 反弹伤害
  2073. if (nAttacker > 0 && bReturn == FALSE)
  2074. {
  2075. if (bIsMelee)
  2076. {
  2077. nMin = m_CurrentMeleeDmgRet;
  2078. nMin += nDamage * nMax / 100;
  2079. Npc[nAttacker].CalcDamage(m_Index, nMin, nMin, damage_magic, FALSE, FALSE, TRUE);
  2080. }
  2081. else
  2082. {
  2083. nMin = m_CurrentRangeDmgRet;
  2084. nMin += nDamage * nMax / 100;
  2085. Npc[nAttacker].CalcDamage(m_Index, nMin, nMin, damage_magic, FALSE, FALSE, TRUE);
  2086. }
  2087. g_DebugLog("[数值]%s返回伤害%d", Name, nMin);
  2088. }
  2089. // PK处理,伤害乘一个系数
  2090. if (this->m_Kind == kind_player && Npc[nAttacker].m_Kind == kind_player)
  2091. nDamage = nDamage * NpcSet.m_nPKDamageRate / 100;
  2092. m_nLastDamageIdx = nAttacker;
  2093. if (m_Kind != kind_player && Npc[nAttacker].m_Kind == kind_player && Npc[nAttacker].m_nPlayerIdx > 0)
  2094. m_cDeathCalcExp.AddDamage(Npc[nAttacker].m_nPlayerIdx, (m_CurrentLife - nDamage > 0 ? nDamage : m_CurrentLife));
  2095. m_CurrentLife -= nDamage;
  2096. if (nDamage > 0)
  2097. {
  2098. m_CurrentMana += m_CurrentDamage2Mana * nDamage / 100;
  2099. if (m_CurrentMana > m_CurrentManaMax)
  2100. {
  2101. m_CurrentMana = m_CurrentManaMax;
  2102. }
  2103. if (bDoHurt)
  2104. DoHurt();
  2105. }
  2106. if (m_CurrentLife < 0)
  2107. {
  2108. int nMode = DeathCalcPKValue(nAttacker);
  2109. DoDeath(nMode);
  2110. // if 死的是玩家,关闭他的仇杀和切磋状态
  2111. if (m_Kind == kind_player)
  2112. Player[m_nPlayerIdx].m_cPK.CloseAll();
  2113. }
  2114. }
  2115. #endif
  2116. #ifdef _SERVER
  2117. BOOL KNpc::ReceiveDamage(int nLauncher, BOOL bIsMelee, void *pData, BOOL bUseAR, BOOL bDoHurt)
  2118. {
  2119. if (m_Doing == do_death || m_Doing == do_revive)
  2120. return FALSE;
  2121. // 发技能的NPC不存在了,不用算了。
  2122. if (!Npc[nLauncher].m_Index)
  2123. return FALSE;
  2124. if (!pData)
  2125. return FALSE;
  2126. KMagicAttrib *pTemp = NULL;
  2127. pTemp = (KMagicAttrib *)pData;
  2128. int nAr = pTemp->nValue[0];
  2129. pTemp++;
  2130. int nIgnoreAr = pTemp->nValue[0];
  2131. pTemp++;
  2132. if (bUseAR)
  2133. {
  2134. if (!CheckHitTarget(nAr, m_CurrentDefend, nIgnoreAr))
  2135. {
  2136. g_DebugLog("[数值]%s闪过攻击", Name);
  2137. return FALSE;
  2138. }
  2139. }
  2140. /*
  2141. if (m_Doing != do_death)
  2142. DoHurt(m_HurtFrame);//Question ?*/
  2143. int nLife = m_CurrentLife;
  2144. // 磨损
  2145. CalcDamage(nLauncher, pTemp->nValue[0], pTemp->nValue[2], damage_physics, bIsMelee, bDoHurt);
  2146. pTemp++;
  2147. CalcDamage(nLauncher, pTemp->nValue[0], pTemp->nValue[2], damage_cold, bIsMelee, bDoHurt);
  2148. if (m_FreezeState.nTime <= 0)
  2149. {
  2150. m_FreezeState.nTime = pTemp->nValue[1] * (100 - m_CurrentFreezeTimeReducePercent) / 100;
  2151. }
  2152. pTemp++;
  2153. CalcDamage(nLauncher, pTemp->nValue[0], pTemp->nValue[2], damage_fire, bIsMelee, bDoHurt);
  2154. pTemp++;
  2155. CalcDamage(nLauncher, pTemp->nValue[0], pTemp->nValue[2], damage_light, bIsMelee, bDoHurt);
  2156. pTemp++;
  2157. CalcDamage(nLauncher, pTemp->nValue[0], pTemp->nValue[0], damage_poison, bIsMelee, bDoHurt);
  2158. if (m_PoisonState.nTime == 0)
  2159. {
  2160. m_PoisonState.nTime = pTemp->nValue[1];
  2161. m_PoisonState.nValue[0] = pTemp->nValue[0];
  2162. m_PoisonState.nValue[1] = pTemp->nValue[2];
  2163. }
  2164. else
  2165. {
  2166. int d1, d2, t1, t2, c1, c2;
  2167. d1 = m_PoisonState.nValue[0];
  2168. d2 = pTemp->nValue[0];
  2169. t1 = m_PoisonState.nTime;
  2170. t2 = pTemp->nValue[1];
  2171. c1 = m_PoisonState.nValue[1];
  2172. c2 = pTemp->nValue[2];
  2173. if (c1 > 0 && c2 > 0 && d1 > 0 && d2 > 0) 
  2174. {
  2175. m_PoisonState.nValue[0] = ((c1 + c2) * d1 / c1 + (c1 + c2) * d2 / c2) / 2;
  2176. m_PoisonState.nTime = (t1 * d1 * c2 + t2 *d2 * c1) /(d1 * c2 + d2 * c1);
  2177. m_PoisonState.nValue[1] = (c1 + c2) / 2;
  2178. }
  2179. }
  2180. m_PoisonState.nTime = m_PoisonState.nTime * (100 - m_CurrentPoisonTimeReducePercent) / 100;
  2181. pTemp++;
  2182. CalcDamage(nLauncher, pTemp->nValue[0], pTemp->nValue[2], damage_magic, bIsMelee, bDoHurt);
  2183. m_nPeopleIdx = nLauncher;
  2184. if (IsPlayer() && (m_CurrentLife - nLife < 0))
  2185. {
  2186. if (m_nPlayerIdx > 0)
  2187. {
  2188. Player[m_nPlayerIdx].m_ItemList.Abrade(enumAbradeDefend);
  2189. }
  2190. }
  2191. return TRUE;
  2192. }
  2193. #endif
  2194. void KNpc::SetImmediatelySkillEffect(int nLauncher, void *pData, int nDataNum)
  2195. {
  2196. if (!pData || !nDataNum)
  2197. return;
  2198. KMagicAttrib* pTemp = (KMagicAttrib *)pData;
  2199. _ASSERT(nDataNum <= MAX_SKILL_STATE);
  2200. for (int i = 0; i < nDataNum; i++)
  2201. {
  2202. ModifyAttrib(nLauncher, pTemp);
  2203. pTemp++;
  2204. }
  2205. }
  2206. void KNpc::AppendSkillEffect(BOOL bIsPhysical, BOOL bIsMelee, void *pSrcData, void *pDesData)
  2207. {
  2208. int nMinDamage = m_PhysicsDamage.nValue[0] + m_CurrentAddPhysicsDamage;
  2209. int nMaxDamage = m_PhysicsDamage.nValue[2] + m_CurrentAddPhysicsDamage;
  2210. KMagicAttrib* pTemp = (KMagicAttrib *)pSrcData;
  2211. KMagicAttrib* pDes = (KMagicAttrib *)pDesData;
  2212. // Get AR_p
  2213. if (pTemp->nAttribType == magic_attackrating_p)
  2214. {
  2215. pDes->nAttribType = magic_attackrating_v;
  2216. pDes->nValue[0] = m_CurrentAttackRating + m_AttackRating * pTemp->nValue[0] / 100;
  2217. }
  2218. else
  2219. {
  2220. pDes->nAttribType = magic_attackrating_v;
  2221. pDes->nValue[0] = m_CurrentAttackRating;
  2222. }
  2223. pTemp++;
  2224. pDes++;
  2225. if (pTemp->nAttribType == magic_ignoredefense_p)
  2226. {
  2227. pDes->nAttribType = magic_ignoredefense_p;
  2228. pDes->nValue[0] = pTemp->nValue[0];
  2229. }
  2230. pTemp++;
  2231. pDes++;
  2232. if (pTemp->nAttribType == magic_physicsenhance_p)
  2233. {
  2234. pDes->nAttribType = magic_physicsdamage_v;
  2235. pDes->nValue[0] = nMinDamage * (100 + pTemp->nValue[0]) / 100;
  2236. pDes->nValue[2] = nMaxDamage * (100 + pTemp->nValue[0]) / 100;
  2237. if (IsPlayer())
  2238. {
  2239. if (Player[m_nPlayerIdx].m_ItemList.GetWeaponType() == equip_meleeweapon)
  2240. {
  2241. pDes->nValue[0] += nMinDamage * m_CurrentMeleeEnhance[Player[m_nPlayerIdx].m_ItemList.GetWeaponParticular()] / 100;
  2242. pDes->nValue[2] += nMaxDamage * m_CurrentMeleeEnhance[Player[m_nPlayerIdx].m_ItemList.GetWeaponParticular()] / 100;
  2243. }
  2244. else if (Player[m_nPlayerIdx].m_ItemList.GetWeaponType() == equip_rangeweapon)
  2245. {
  2246. pDes->nValue[0] += nMinDamage * m_CurrentRangeEnhance / 100;
  2247. pDes->nValue[2] += nMaxDamage * m_CurrentRangeEnhance / 100;
  2248. }
  2249. else // 空手
  2250. {
  2251. pDes->nValue[0] += nMinDamage * m_CurrentHandEnhance / 100;
  2252. pDes->nValue[2] += nMaxDamage * m_CurrentHandEnhance / 100;
  2253. }
  2254. }
  2255. }
  2256. else if (pTemp->nAttribType == magic_physicsdamage_v)
  2257. {
  2258. pDes->nAttribType = magic_physicsdamage_v;
  2259. pDes->nValue[0] = pTemp->nValue[0];
  2260. pDes->nValue[2] = pTemp->nValue[2];
  2261. }
  2262. pTemp++;
  2263. pDes++;
  2264. if (pTemp->nAttribType == magic_colddamage_v)
  2265. {
  2266. pDes->nAttribType = magic_colddamage_v;
  2267. pDes->nValue[0] = pTemp->nValue[0];
  2268. pDes->nValue[1] = pTemp->nValue[1] + m_CurrentColdEnhance;
  2269. pDes->nValue[2] = pTemp->nValue[2];
  2270. }
  2271. if (bIsPhysical)
  2272. {
  2273. pDes->nValue[0] += m_CurrentColdDamage.nValue[0];
  2274. pDes->nValue[1] = max(pDes->nValue[1], m_CurrentColdDamage.nValue[1] + m_CurrentColdEnhance);
  2275. pDes->nValue[2] += m_CurrentColdDamage.nValue[2];
  2276. }
  2277. pTemp++;
  2278. pDes++;
  2279. if (pTemp->nAttribType == magic_firedamage_v)
  2280. {
  2281. // How to use FireEnhance???
  2282. pDes->nAttribType = magic_firedamage_v;
  2283. pDes->nValue[0] = pTemp->nValue[0];
  2284. pDes->nValue[2] = pTemp->nValue[2];
  2285. }
  2286. if (bIsPhysical)
  2287. {
  2288. pDes->nValue[0] += m_CurrentFireDamage.nValue[0];
  2289. pDes->nValue[2] += m_CurrentFireDamage.nValue[2];
  2290. }
  2291. pTemp++;
  2292. pDes++;
  2293. if (pTemp->nAttribType == magic_lightingdamage_v)
  2294. {
  2295. pDes->nAttribType = magic_lightingdamage_v;
  2296. pDes->nValue[0] = pTemp->nValue[0] + (pTemp->nValue[2] - pTemp->nValue[0]) * m_CurrentLightEnhance / 100;
  2297. pDes->nValue[2] = pTemp->nValue[2];
  2298. }
  2299. if (bIsPhysical)
  2300. {
  2301. pDes->nValue[0] += m_CurrentLightDamage.nValue[0];
  2302. pDes->nValue[2] += m_CurrentLightDamage.nValue[2];
  2303. }
  2304. pTemp++;
  2305. pDes++;
  2306. if (pTemp->nAttribType == magic_poisondamage_v)
  2307. {
  2308. pDes->nAttribType = magic_poisondamage_v;
  2309. pDes->nValue[0] = pTemp->nValue[0];
  2310. pDes->nValue[1] = pTemp->nValue[1];
  2311. pDes->nValue[2] = pTemp->nValue[2] * (100 - m_CurrentPoisonEnhance) / 100;
  2312. if (pDes->nValue[2] <= 0)
  2313. pDes->nValue[2] = 1;
  2314. }
  2315. if (bIsPhysical)
  2316. {
  2317. // 合成毒伤害
  2318. g_NpcAttribModify.MixPoisonDamage(pDes, &m_CurrentPoisonDamage);
  2319. }
  2320. pTemp++;
  2321. pDes++;
  2322. if (pTemp->nAttribType == magic_magicdamage_v)
  2323. {
  2324. pDes->nAttribType = magic_magicdamage_v;
  2325. pDes->nValue[0] = pTemp->nValue[0];
  2326. pDes->nValue[2] = pTemp->nValue[2];
  2327. }
  2328. }
  2329. void KNpc::ServeMove(int MoveSpeed)
  2330. {
  2331. if (m_Doing != do_walk && m_Doing != do_run && m_Doing != do_hurt && m_Doing != do_runattack)
  2332. return;
  2333. if (MoveSpeed <= 0)
  2334. return;
  2335. if (MoveSpeed >= SubWorld[m_SubWorldIndex].m_nCellWidth)
  2336. {
  2337. MoveSpeed = SubWorld[m_SubWorldIndex].m_nCellWidth - 1;
  2338. }
  2339. #ifndef _SERVER
  2340. if (m_RegionIndex < 0 || m_RegionIndex >= 9)
  2341. {
  2342. g_DebugLog("[zroc]Npc(%d)ServerMove RegionIdx = %d", m_Index, m_RegionIndex);
  2343. _ASSERT(0);
  2344. DoStand();
  2345. return;
  2346. }
  2347. #else
  2348. _ASSERT(m_RegionIndex >= 0);
  2349. if (m_RegionIndex < 0)
  2350. return;
  2351. #endif
  2352. int x, y;
  2353. SubWorld[m_SubWorldIndex].Map2Mps(m_RegionIndex, m_MapX, m_MapY, 0, 0, &x, &y);
  2354. x = (x << 10) + m_OffX;
  2355. y = (y << 10) + m_OffY;
  2356. int nRet = m_PathFinder.GetDir(x, y, m_Dir, m_DesX, m_DesY, MoveSpeed, &m_Dir);
  2357. #ifndef _SERVER
  2358. if(nRet == 1)
  2359. {
  2360. x = g_DirCos(m_Dir, 64) * MoveSpeed;
  2361. y = g_DirSin(m_Dir, 64) * MoveSpeed;
  2362. }
  2363. else if (nRet == 0)
  2364. {
  2365. DoStand();
  2366. return;
  2367. }
  2368. else if (nRet == -1)
  2369. {
  2370. SubWorld[0].m_Region[m_RegionIndex].RemoveNpc(m_Index);
  2371. SubWorld[0].m_Region[m_RegionIndex].DecRef(m_MapX, m_MapY, obj_npc);
  2372. m_RegionIndex = -1;
  2373. return;
  2374. }
  2375. else
  2376. {
  2377. return;
  2378. }
  2379. #endif
  2380. #ifdef _SERVER
  2381. if(nRet == 1)
  2382. {
  2383. x = g_DirCos(m_Dir, 64) * MoveSpeed;
  2384. y = g_DirSin(m_Dir, 64) * MoveSpeed;
  2385. }
  2386. else
  2387. {
  2388. DoStand();
  2389. return;
  2390. }
  2391. #endif
  2392. int nOldRegion = m_RegionIndex;
  2393. int nOldMapX = m_MapX;
  2394. int nOldMapY = m_MapY;
  2395. int nOldOffX = m_OffX;
  2396. int nOldOffY = m_OffY;
  2397. m_OffX += x;
  2398. m_OffY += y;
  2399. // 处理NPC的坐标变幻
  2400. // CELLWIDTH、CELLHEIGHT、OffX、OffY均是放大了1024倍
  2401. if (!m_bClientOnly)
  2402. CURREGION.DecRef(m_MapX, m_MapY, obj_npc);
  2403. if (m_OffX < 0)
  2404. {
  2405. m_MapX--;
  2406. m_OffX += CELLWIDTH;
  2407. }
  2408. else if (m_OffX > CELLWIDTH)
  2409. {
  2410. m_MapX++;
  2411. m_OffX -= CELLWIDTH;
  2412. }
  2413. if (m_OffY < 0)
  2414. {
  2415. m_MapY--;
  2416. m_OffY += CELLHEIGHT;
  2417. }
  2418. else if (m_OffY > CELLHEIGHT)
  2419. {
  2420. m_MapY++;
  2421. m_OffY -= CELLHEIGHT;
  2422. }
  2423. if (m_MapX < 0)
  2424. {
  2425. m_RegionIndex = LEFTREGIONIDX;
  2426. m_MapX += REGIONWIDTH;
  2427. }
  2428. else if (m_MapX >= REGIONWIDTH)
  2429. {
  2430. m_RegionIndex = RIGHTREGIONIDX;
  2431. m_MapX -= REGIONWIDTH;
  2432. }
  2433. if (m_RegionIndex >= 0)
  2434. {
  2435. if (m_MapY < 0)
  2436. {
  2437. m_RegionIndex = UPREGIONIDX;
  2438. m_MapY += REGIONHEIGHT;
  2439. }
  2440. else if (m_MapY >= REGIONHEIGHT)
  2441. {
  2442. m_RegionIndex = DOWNREGIONIDX;
  2443. m_MapY -= REGIONHEIGHT;
  2444. }
  2445. if (!m_bClientOnly && m_RegionIndex >= 0)
  2446. CURREGION.AddRef(m_MapX, m_MapY, obj_npc);
  2447. }
  2448. if (m_RegionIndex == -1) // 不可能移动到-1 Region,如果出现这种情况,恢复原坐标
  2449. {
  2450. m_RegionIndex = nOldRegion;
  2451. m_MapX = nOldMapX;
  2452. m_MapY = nOldMapY;
  2453. m_OffX = nOldOffX;
  2454. m_OffY = nOldOffY;
  2455. CURREGION.AddRef(m_MapX, m_MapY, obj_npc);
  2456. return;
  2457. }
  2458. if (nOldRegion != m_RegionIndex)
  2459. {
  2460. #ifdef _SERVER
  2461. SubWorld[m_SubWorldIndex].NpcChangeRegion(nOldRegion, m_RegionIndex, m_Index);
  2462. if (IsPlayer())
  2463. {
  2464. SubWorld[m_SubWorldIndex].PlayerChangeRegion(nOldRegion, m_RegionIndex, m_nPlayerIdx);
  2465. if (m_nPlayerIdx > 0)
  2466. {
  2467. Player[m_nPlayerIdx].m_ItemList.Abrade(enumAbradeMove);
  2468. }
  2469. }
  2470. #else
  2471. SubWorld[0].NpcChangeRegion(SubWorld[0].m_Region[nOldRegion].m_RegionID, SubWorld[0].m_Region[m_RegionIndex].m_RegionID, m_Index);
  2472. m_dwRegionID = SubWorld[0].m_Region[m_RegionIndex].m_RegionID;
  2473. #endif
  2474. }
  2475. }
  2476. void KNpc::ServeJump(int nSpeed)
  2477. {
  2478. _ASSERT(m_RegionIndex >= 0);
  2479. if (m_RegionIndex < 0)
  2480. return;
  2481. if (!(m_Doing == do_jump || m_Doing == do_jumpattack))
  2482. return;
  2483. if (nSpeed <= 0)
  2484. return;
  2485. if (nSpeed >= SubWorld[m_SubWorldIndex].m_nCellWidth)
  2486. {
  2487. nSpeed = SubWorld[m_SubWorldIndex].m_nCellWidth - 1;
  2488. }
  2489. m_OffX += g_DirCos(m_JumpDir, 64) * nSpeed;
  2490. m_OffY += g_DirSin(m_JumpDir, 64) * nSpeed;
  2491. // s = vt - a * t * t / 2
  2492. m_Height = (m_JumpFirstSpeed * m_Frames.nCurrentFrame - ACCELERATION_OF_GRAVITY * m_Frames.nCurrentFrame * m_Frames.nCurrentFrame / 2) / 8;
  2493. if (m_Height < 0)
  2494. m_Height = 0;
  2495. int nOldRegion = m_RegionIndex;
  2496. int nOldMapX = m_MapX;
  2497. int nOldMapY = m_MapY;
  2498. int nOldOffX = m_OffX;
  2499. int nOldOffY = m_OffY;
  2500. CURREGION.DecRef(m_MapX, m_MapY, obj_npc);
  2501. if (m_OffX < 0)
  2502. {
  2503. m_MapX--;
  2504. m_OffX += CELLWIDTH;
  2505. }
  2506. else if (m_OffX > CELLWIDTH)
  2507. {
  2508. m_MapX++;
  2509. m_OffX -= CELLWIDTH;
  2510. }
  2511. if (m_OffY < 0)
  2512. {
  2513. m_MapY--;
  2514. m_OffY += CELLHEIGHT;
  2515. }
  2516. else if (m_OffY > CELLHEIGHT)
  2517. {
  2518. m_MapY++;
  2519. m_OffY -= CELLHEIGHT;
  2520. }
  2521. if (m_MapX < 0)
  2522. {
  2523. m_RegionIndex = LEFTREGIONIDX;
  2524. m_MapX += REGIONWIDTH;
  2525. }
  2526. else if (m_MapX >= REGIONWIDTH)
  2527. {
  2528. m_RegionIndex = RIGHTREGIONIDX;
  2529. m_MapX -= REGIONWIDTH;
  2530. }
  2531. if (m_RegionIndex >= 0)
  2532. {
  2533. if (m_MapY < 0)
  2534. {
  2535. m_RegionIndex = UPREGIONIDX;
  2536. m_MapY += REGIONHEIGHT;
  2537. }
  2538. else if (m_MapY >= REGIONHEIGHT)
  2539. {
  2540. m_RegionIndex = DOWNREGIONIDX;
  2541. m_MapY -= REGIONHEIGHT;
  2542. }
  2543. if (m_RegionIndex >= 0)
  2544. CURREGION.AddRef(m_MapX, m_MapY, obj_npc);
  2545. }
  2546. if (m_RegionIndex == -1) // 不可能移动到-1 Region,如果出现这种情况,恢复原坐标
  2547. {
  2548. m_RegionIndex = nOldRegion;
  2549. m_MapX = nOldMapX;
  2550. m_MapY = nOldMapY;
  2551. m_OffX = nOldOffX;
  2552. m_OffY = nOldOffY;
  2553. CURREGION.AddRef(m_MapX, m_MapY, obj_npc);
  2554. return;
  2555. }
  2556. if (nOldRegion != m_RegionIndex)
  2557. {
  2558. #ifdef _SERVER
  2559. SubWorld[m_SubWorldIndex].NpcChangeRegion(nOldRegion, m_RegionIndex, m_Index);
  2560. if (IsPlayer())
  2561. {
  2562. SubWorld[m_SubWorldIndex].PlayerChangeRegion(nOldRegion, m_RegionIndex, m_nPlayerIdx);
  2563. if (m_nPlayerIdx > 0)
  2564. {
  2565. Player[m_nPlayerIdx].m_ItemList.Abrade(enumAbradeMove);
  2566. }
  2567. }
  2568. #else
  2569. if (m_RegionIndex >= 0)
  2570. {
  2571. SubWorld[0].NpcChangeRegion(SubWorld[0].m_Region[nOldRegion].m_RegionID, SubWorld[0].m_Region[m_RegionIndex].m_RegionID, m_Index);
  2572. m_dwRegionID = SubWorld[0].m_Region[m_RegionIndex].m_RegionID;
  2573. }
  2574. #endif
  2575. }
  2576. }
  2577. void KNpc::SendCommand(NPCCMD cmd,int x,int y, int z)
  2578. {
  2579. m_Command.CmdKind = cmd;
  2580. m_Command.Param_X = x;
  2581. m_Command.Param_Y = y;
  2582. m_Command.Param_Z = z;
  2583. }
  2584. BOOL KNpc::NewPath(int nMpsX, int nMpsY)
  2585. {
  2586. m_DesX = nMpsX;
  2587. m_DesY = nMpsY;
  2588. return TRUE;
  2589. }
  2590. BOOL KNpc::NewJump(int nMpsX, int nMpsY)
  2591. {
  2592. _ASSERT(m_CurrentJumpSpeed > 0);
  2593. if (m_CurrentJumpSpeed <= 0)
  2594. return FALSE;
  2595. int nX, nY;
  2596. GetMpsPos(&nX, &nY);
  2597. if (nX == nMpsX && nY == nMpsY)
  2598. return FALSE;
  2599. int nDir = g_GetDirIndex(nX, nY, nMpsX, nMpsY);
  2600. int nMaxLength = m_CurrentJumpSpeed * m_CurrentJumpFrame;
  2601. int nWantLength = g_GetDistance(nX, nY, nMpsX, nMpsY);
  2602. int nSin = g_DirSin(nDir, 64);
  2603. int nCos = g_DirCos(nDir, 64);
  2604. if (nWantLength > nMaxLength)
  2605. {
  2606. m_DesX = nX + ((nMaxLength * nCos) >> 10);
  2607. m_DesY = nY + ((nMaxLength * nSin) >> 10);
  2608. nWantLength = nMaxLength;
  2609. }
  2610. else if (nWantLength <= MIN_JUMP_RANGE)
  2611. {
  2612. m_DesX = nMpsX;
  2613. m_DesY = nMpsY;
  2614. return FALSE;
  2615. }
  2616. m_JumpStep = nWantLength / m_CurrentJumpSpeed;
  2617. int nTestX = 0;
  2618. int nTestY = 0;
  2619. int nSuccessStep = 0;
  2620. for (int i = 1; i < m_JumpStep + 1; i++)
  2621. {
  2622. nTestX = nX + ((m_CurrentJumpSpeed * nCos * i) >> 10);
  2623. nTestY = nY + ((m_CurrentJumpSpeed * nSin * i) >> 10);
  2624. int nBarrier = SubWorld[m_SubWorldIndex].GetBarrier(nTestX, nTestY);
  2625. if (Obstacle_NULL == nBarrier)
  2626. {
  2627. nSuccessStep = i;
  2628. }
  2629. if (Obstacle_Normal == nBarrier || Obstacle_Fly == nBarrier)
  2630. {
  2631. if (nSuccessStep <= MIN_JUMP_RANGE / m_CurrentJumpSpeed)
  2632. {
  2633. return FALSE;
  2634. }
  2635. m_DesX = nX + ((m_CurrentJumpSpeed * nCos * nSuccessStep) >> 10);
  2636. m_DesY = nY + ((m_CurrentJumpSpeed * nSin * nSuccessStep) >> 10);
  2637. m_JumpStep = nSuccessStep;
  2638. break;
  2639. }
  2640. int nTrap = SubWorld[m_SubWorldIndex].GetTrap(nTestX, nTestY);
  2641. if (nTrap)
  2642. {
  2643. if (i <= MIN_JUMP_RANGE / m_CurrentJumpSpeed)
  2644. {
  2645. return FALSE;
  2646. }
  2647. m_DesX = nX + ((m_CurrentJumpSpeed * nCos * i) >> 10);
  2648. m_DesY = nY + ((m_CurrentJumpSpeed * nSin * i) >> 10);
  2649. m_JumpStep = i;
  2650. break;
  2651. }
  2652. }
  2653. m_JumpDir = nDir;
  2654. return TRUE;
  2655. }
  2656. void KNpc::SelfDamage(int nDamage)
  2657. {
  2658. m_CurrentLife -= nDamage;
  2659. if (m_CurrentLife <= 0)
  2660. {
  2661. m_CurrentLife = 1;
  2662. }
  2663. }
  2664. BOOL KNpc::Cost(NPCATTRIB nType, int nCost, BOOL bOnlyCheckCanCast)
  2665. {
  2666. if (!IsPlayer())
  2667. return TRUE;
  2668. int *pSource = NULL;
  2669. switch(nType)
  2670. {
  2671. case attrib_mana:
  2672. pSource = &m_CurrentMana;
  2673. break;
  2674. case attrib_life:
  2675. pSource = &m_CurrentLife;
  2676. break;
  2677. case attrib_stamina:
  2678. pSource = &m_CurrentStamina;
  2679. break;
  2680. default:
  2681. break;
  2682. }
  2683. if (pSource)
  2684. {
  2685. if (*pSource < nCost)
  2686. {
  2687. #ifndef _SERVER
  2688. KSystemMessage Msg;
  2689. Msg.byConfirmType = SMCT_NONE;
  2690. Msg.byParamSize = 0;
  2691. Msg.byPriority = 1;
  2692. Msg.eType = SMT_NORMAL;
  2693. switch(nType)
  2694. {
  2695. case attrib_mana:
  2696. g_StrCpyLen(Msg.szMessage, MSG_NPC_NO_MANA, sizeof(Msg.szMessage));
  2697. break;
  2698. case attrib_life:
  2699. g_StrCpyLen(Msg.szMessage, MSG_NPC_NO_LIFE, sizeof(Msg.szMessage));
  2700. break;
  2701. case attrib_stamina:
  2702. g_StrCpyLen(Msg.szMessage, MSG_NPC_NO_STAMINA, sizeof(Msg.szMessage));
  2703. break;
  2704. default:
  2705. break;
  2706. }
  2707. CoreDataChanged(GDCNI_SYSTEM_MESSAGE, (unsigned int)&Msg, NULL);
  2708. #endif