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

模拟服务器

开发平台:

C/C++

  1. /*******************************************************************************
  2. // FileName : KMissle.cpp
  3. // FileAuthor : RomanDou
  4. // FileCreateDate : 2002-6-10 15:32:22
  5. // FileDescription :
  6. // Revision Count :
  7. *******************************************************************************/
  8. #include "KCore.h"
  9. #include "KMissle.h"
  10. #include "KSubWorld.h"
  11. #include "KSubWorldSet.h"
  12. #include "KRegion.h"
  13. #include "KNpc.h"
  14. #include "KNpcSet.h"
  15. #include "KMath.h"
  16. #include <math.h>
  17. #include "KSkillSpecial.h"
  18. //#include "myassert.h"
  19. #ifndef _SERVER
  20. #include "../../Represent/iRepresent/iRepresentshell.h"
  21. #include "SceneKScenePlaceC.h"
  22. #include "ImgRef.h"
  23. #endif
  24. #include "Scene/ObstacleDef.h"
  25. #include "KPlayer.h"
  26. #include "KMissleSet.h"
  27. #ifdef _STANDALONE
  28. #include "KSG_StringProcess.h"
  29. #else
  30. #include "../../Engine/Src/KSG_StringProcess.h"
  31. #endif
  32. TCollisionMatrix g_CollisionMatrix[64] =
  33. {
  34. {0, 0, -1, 1, 0, 1, 1, 1}, // 0--------
  35. {0, 0, -1, 1, 0, 1, 1, 1}, // 1
  36. {0, 0, -1, 1, 0, 1, 1, 1}, // 2
  37. {0, 0, -1, 1, 0, 1, 1, 1}, // 3
  38. {0, 0, -1, 0, -1, 1, 0, 1}, // 4
  39. {0, 0, -1, 0, -1, 1, 0, 1}, // 5
  40. {0, 0, -1, 0, -1, 1, 0, 1}, // 6
  41. {0, 0, -1, 0, -1, 1, 0, 1}, // 7
  42. {0, 0, -1, 0, -1, 1, 0, 1}, // 8--------
  43. {0, 0, -1, 0, -1, 1, 0, 1}, // 9
  44. {0, 0, -1, 0, -1, 1, 0, 1}, // 10
  45. {0, 0, -1, 0, -1, 1, 0, 1}, // 11
  46. {0, 0, -1, -1, -1, 0, -1, 1}, // 12
  47. {0, 0, -1, -1, -1, 0, -1, 1}, // 13
  48. {0, 0, -1, -1, -1, 0, -1, 1}, // 14
  49. {0, 0, -1, -1, -1, 0, -1, 1}, // 15
  50. {0, 0, -1, -1, -1, 0, -1, 1}, // 16--------
  51. {0, 0, -1, -1, -1, 0, -1, 1}, // 17
  52. {0, 0, -1, -1, -1, 0, -1, 1}, // 18
  53. {0, 0, -1, -1, -1, 0, -1, 1}, // 19
  54. {0, 0, 0, -1, -1, -1, -1, 0}, // 20
  55. {0, 0, 0, -1, -1, -1, -1, 0}, // 21
  56. {0, 0, 0, -1, -1, -1, -1, 0}, // 22
  57. {0, 0, 0, -1, -1, -1, -1, 0}, // 23
  58. {0, 0, 0, -1, -1, -1, -1, 0}, // 24--------
  59. {0, 0, 0, -1, -1, -1, -1, 0}, // 25
  60. {0, 0, 0, -1, -1, -1, -1, 0}, // 26
  61. {0, 0, 0, -1, -1, -1, -1, 0}, // 27
  62. {0, 0, -1, -1, 0, -1, 1, -1}, // 28
  63. {0, 0, -1, -1, 0, -1, 1, -1}, // 29
  64. {0, 0, -1, -1, 0, -1, 1, -1}, // 30
  65. {0, 0, -1, -1, 0, -1, 1, -1}, // 31
  66. {0, 0, -1, -1, 0, -1, 1, -1}, // 32--------
  67. {0, 0, -1, -1, 0, -1, 1, -1}, // 33
  68. {0, 0, -1, -1, 0, -1, 1, -1}, // 34
  69. {0, 0, -1, -1, 0, -1, 1, -1}, // 35
  70. {0, 0, 0, -1, 1, -1, 1, 0}, // 36
  71. {0, 0, 0, -1, 1, -1, 1, 0}, // 37
  72. {0, 0, 0, -1, 1, -1, 1, 0}, // 38
  73. {0, 0, 0, -1, 1, -1, 1, 0}, // 39
  74. {0, 0, 0, -1, 1, -1, 1, 0}, // 40--------
  75. {0, 0, 0, -1, 1, -1, 1, 0}, // 41
  76. {0, 0, 0, -1, 1, -1, 1, 0}, // 42
  77. {0, 0, 0, -1, 1, -1, 1, 0}, // 43
  78. {0, 0, 1, -1, 1, 0, 1, 1}, // 44
  79. {0, 0, 1, -1, 1, 0, 1, 1}, // 45
  80. {0, 0, 1, -1, 1, 0, 1, 1}, // 46
  81. {0, 0, 1, -1, 1, 0, 1, 1}, // 47
  82. {0, 0, 1, -1, 1, 0, 1, 1}, // 48--------
  83. {0, 0, 1, -1, 1, 0, 1, 1}, // 49
  84. {0, 0, 1, -1, 1, 0, 1, 1}, // 50
  85. {0, 0, 1, -1, 1, 0, 1, 1}, // 51
  86. {0, 0, 1, 0, 1, 1, 0, 1}, // 52
  87. {0, 0, 1, 0, 1, 1, 0, 1}, // 53
  88. {0, 0, 1, 0, 1, 1, 0, 1}, // 54
  89. {0, 0, 1, 0, 1, 1, 0, 1}, // 55
  90. {0, 0, 1, 0, 1, 1, 0, 1}, // 56---------
  91. {0, 0, 1, 0, 1, 1, 0, 1}, // 57
  92. {0, 0, 1, 0, 1, 1, 0, 1}, // 58
  93. {0, 0, 1, 0, 1, 1, 0, 1}, // 59
  94. {0, 0, -1, 1, 0, 1, 1, 1}, // 60
  95. {0, 0, -1, 1, 0, 1, 1, 1}, // 61
  96. {0, 0, -1, 1, 0, 1, 1, 1}, // 62
  97. {0, 0, -1, 1, 0, 1, 1, 1}, // 63
  98. };
  99. KMissle g_MisslesLib[MAX_MISSLESTYLE];
  100. //每个格子的像素长宽
  101. #define CellWidth (SubWorld[m_nSubWorldId].m_nCellWidth << 10)
  102. #define CellHeight (SubWorld[m_nSubWorldId].m_nCellHeight << 10)
  103. //每个region格点长宽
  104. #define RegionWidth (SubWorld[m_nSubWorldId].m_nRegionWidth)
  105. #define RegionHeight (SubWorld[m_nSubWorldId].m_nRegionHeight)
  106. #define CurRegion SubWorld[m_nSubWorldId].m_Region[m_nRegionId]
  107. #define CurSubWorld SubWorld[m_nSubWorldId]
  108. #define LeftRegion(nRegionId) SubWorld[m_nSubWorldId].m_Region[nRegionId].m_nConnectRegion[2]
  109. #define RightRegion(nRegionId) SubWorld[m_nSubWorldId].m_Region[nRegionId].m_nConnectRegion[6]
  110. #define UpRegion(nRegionId) SubWorld[m_nSubWorldId].m_Region[nRegionId].m_nConnectRegion[4]
  111. #define DownRegion(nRegionId) SubWorld[m_nSubWorldId].m_Region[nRegionId].m_nConnectRegion[0]
  112. //随机移动魔法的左右偏移表
  113. int g_nRandMissleTab[100] = {0 };
  114. CORE_API KMissle Missle[MAX_MISSLE];
  115. //////////////////////////////////////////////////////////////////////
  116. // Construction/Destruction
  117. //////////////////////////////////////////////////////////////////////
  118. KMissle::KMissle()
  119. {
  120. m_nMissleId = -1;
  121. m_nCollideOrVanishTime = 0;
  122. m_ulDamageInterval = 0;
  123. m_nTempParam1 = 0;
  124. m_nTempParam2 = 0;
  125. m_nFirstReclaimTime = 0;
  126. m_nEndReclaimTime = 0;
  127. #ifdef _SERVER
  128. m_pMagicAttribsData = NULL;
  129. m_ulNextCalDamageTime = 0;
  130. #else
  131. m_bFollowNpcWhenCollid = 1;
  132. m_bRemoving = FALSE;
  133. m_btRedLum = m_btGreenLum = m_btBlueLum = 0xff;
  134. m_usLightRadius = 50;
  135. #endif
  136. }
  137. void KMissle::Release()
  138. {
  139. ///#pragma message(ATTENTION("子弹消亡时,需更新发送者使用该技能时的当前使用次数,使之减一"))
  140. #ifndef _SERVER
  141. g_ScenePlace.RemoveObject(CGOG_MISSLE, m_nMissleId, m_SceneID);
  142. m_MissleRes.Clear();
  143. m_nMissleId = -1;
  144. m_nFollowNpcIdx = 0;
  145. #endif
  146. #ifdef _SERVER
  147. if (m_pMagicAttribsData)
  148. if (m_pMagicAttribsData->DelRef() == 0)
  149. delete m_pMagicAttribsData;
  150. m_pMagicAttribsData = NULL;
  151. #endif
  152. }
  153. KMissle::~KMissle()
  154. {
  155. }
  156. /*!*****************************************************************************
  157. // Function : KMissle::GetInfoFromTabFile
  158. // Purpose : 获得TabFile有关子弹的基本信息
  159. // Return : BOOL 
  160. // Argumant : int nMissleId
  161. // Comments :
  162. // Author : RomanDou
  163. *****************************************************************************/
  164. BOOL KMissle::GetInfoFromTabFile(int nMissleId)
  165. {
  166. if (nMissleId <= 0 ) return FALSE;
  167. KITabFile * pITabFile = &g_MisslesSetting;
  168. return GetInfoFromTabFile(pITabFile, nMissleId);
  169. }
  170. BOOL KMissle::GetInfoFromTabFile(KITabFile * pMisslesSetting, int nMissleId)
  171. {
  172. if (nMissleId <= 0 ) return FALSE;
  173. m_nMissleId = nMissleId;
  174. int nRow = nMissleId;
  175. pMisslesSetting->GetString(nRow, "MissleName",    "", m_szMissleName,30, TRUE);
  176. int nHeightOld ;
  177. pMisslesSetting->GetInteger(nRow, "MissleHeight", 0, &nHeightOld, TRUE);
  178. m_nHeight = nHeightOld << 10;
  179. pMisslesSetting->GetInteger(nRow, "LifeTime", 0, &m_nLifeTime, TRUE);
  180. pMisslesSetting->GetInteger(nRow, "Speed", 0, &m_nSpeed, TRUE);
  181. pMisslesSetting->GetInteger(nRow, "ResponseSkill", 0, &m_nSkillId, TRUE);
  182. pMisslesSetting->GetInteger(nRow, "CollidRange", 0, &m_nCollideRange, TRUE);
  183. pMisslesSetting->GetInteger(nRow, "ColVanish", 0, &m_bCollideVanish, TRUE);
  184. pMisslesSetting->GetInteger(nRow, "CanColFriend", 0, &m_bCollideFriend, TRUE);
  185. pMisslesSetting->GetInteger(nRow, "CanSlow", 0, &m_bCanSlow, TRUE);
  186. pMisslesSetting->GetInteger(nRow, "IsRangeDmg", 0, &m_bRangeDamage, TRUE);
  187. pMisslesSetting->GetInteger(nRow, "DmgRange", 0, &m_nDamageRange, TRUE);
  188. pMisslesSetting->GetInteger(nRow, "MoveKind", 0, (int*)&m_eMoveKind, TRUE);
  189. pMisslesSetting->GetInteger(nRow, "FollowKind", 0, (int*)&m_eFollowKind, TRUE);
  190. pMisslesSetting->GetInteger(nRow, "Zacc", 0,(int*)&m_nZAcceleration, TRUE);
  191. pMisslesSetting->GetInteger(nRow, "Zspeed", 0,(int*)&m_nHeightSpeed, TRUE);
  192. pMisslesSetting->GetInteger(nRow, "Param1", 0, &m_nParam1, TRUE);
  193. pMisslesSetting->GetInteger(nRow, "Param2", 0, &m_nParam2, TRUE);
  194. pMisslesSetting->GetInteger(nRow, "Param3", 0, &m_nParam3, TRUE);
  195. BOOL bAutoExplode = 0;
  196. pMisslesSetting->GetInteger(nRow, "AutoExplode", 0, (int*)&bAutoExplode, TRUE);
  197. m_bAutoExplode = bAutoExplode;
  198. pMisslesSetting->GetInteger(nRow, "DmgInterval", 0, (int*)&m_ulDamageInterval, TRUE);
  199. #ifndef _SERVER
  200. char AnimFileCol[64];
  201. char SndFileCol[64];
  202. char AnimFileInfoCol[100];
  203. char szAnimFileInfo[100];
  204.     const char *pcszTemp = NULL;
  205. pMisslesSetting->GetInteger(nRow, "RedLum",     255, (int*)&m_btRedLum, TRUE);
  206. pMisslesSetting->GetInteger(nRow, "GreenLum", 255, (int*)&m_btGreenLum, TRUE);
  207. pMisslesSetting->GetInteger(nRow, "BlueLum", 255, (int*)&m_btBlueLum, TRUE);
  208. int nLightRadius = 0;
  209. pMisslesSetting->GetInteger(nRow, "LightRadius", 50, (int*)&nLightRadius, TRUE);
  210. m_usLightRadius = nLightRadius;
  211. pMisslesSetting->GetInteger(nRow, "MultiShow", 0, &m_bMultiShow, TRUE);
  212. for (int i  = 0; i < MAX_MISSLE_STATUS; i++)
  213. {
  214. sprintf(AnimFileCol, "AnimFile%d", i + 1);
  215. sprintf(SndFileCol,  "SndFile%d", i + 1);
  216. sprintf(AnimFileInfoCol, "AnimFileInfo%d", i + 1);
  217. pMisslesSetting->GetString(nRow, AnimFileCol, "", m_MissleRes.m_MissleRes[i].AnimFileName, 64, TRUE);
  218. pMisslesSetting->GetString(nRow, SndFileCol, "", m_MissleRes.m_MissleRes[i].SndFileName, 64, TRUE);
  219. pMisslesSetting->GetString(nRow, AnimFileInfoCol, "", szAnimFileInfo, 100, TRUE);
  220. //m_MissleRes.m_MissleRes[i].nInterval = 1;
  221. //m_MissleRes.m_MissleRes[i].nDir = 16;
  222. //m_MissleRes.m_MissleRes[i].nTotalFrame = 100;
  223.         pcszTemp = szAnimFileInfo;
  224.         m_MissleRes.m_MissleRes[i].nTotalFrame = KSG_StringGetInt(&pcszTemp, 100);
  225.         KSG_StringSkipSymbol(&pcszTemp, ',');
  226.         m_MissleRes.m_MissleRes[i].nDir = KSG_StringGetInt(&pcszTemp, 16);
  227.         KSG_StringSkipSymbol(&pcszTemp, ',');
  228.         m_MissleRes.m_MissleRes[i].nInterval = KSG_StringGetInt(&pcszTemp, 1);
  229. //sscanf(szAnimFileInfo, "%d,%d,%d", 
  230. // &m_MissleRes.m_MissleRes[i].nTotalFrame,
  231. // &m_MissleRes.m_MissleRes[i].nDir,
  232. // &m_MissleRes.m_MissleRes[i].nInterval
  233.         //);
  234. sprintf(AnimFileCol, "AnimFileB%d", i + 1);
  235. sprintf(SndFileCol,  "SndFileB%d", i + 1);
  236. sprintf(AnimFileInfoCol, "AnimFileInfoB%d", i + 1);
  237. pMisslesSetting->GetString(nRow, AnimFileCol, "", m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].AnimFileName, 64, TRUE);
  238. pMisslesSetting->GetString(nRow, SndFileCol, "", m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].SndFileName, 64, TRUE);
  239. pMisslesSetting->GetString(nRow, AnimFileInfoCol, "", szAnimFileInfo, 100, TRUE);
  240. //m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nInterval = 1;
  241. //m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nDir = 16;
  242. //m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nTotalFrame = 100;
  243.         pcszTemp = szAnimFileInfo;
  244.         m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nTotalFrame = KSG_StringGetInt(&pcszTemp, 100);
  245.         KSG_StringSkipSymbol(&pcszTemp, ',');
  246.         m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nDir = KSG_StringGetInt(&pcszTemp, 16);
  247.         KSG_StringSkipSymbol(&pcszTemp, ',');
  248.         m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nInterval = KSG_StringGetInt(&pcszTemp, 1);
  249. //sscanf(szAnimFileInfo, "%d,%d,%d", 
  250. // &m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nTotalFrame,
  251. // &m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nDir,
  252. // &m_MissleRes.m_MissleRes[i + MAX_MISSLE_STATUS].nInterval
  253.         //);
  254. }
  255. pMisslesSetting->GetInteger(nRow, "LoopPlay", 0, &m_MissleRes.m_bLoopAnim, TRUE);
  256. pMisslesSetting->GetInteger(nRow, "SubLoop", 0, &m_MissleRes.m_bSubLoop, TRUE);
  257. pMisslesSetting->GetInteger(nRow, "SubStart", 0, &m_MissleRes.m_nSubStart, TRUE);
  258. pMisslesSetting->GetInteger(nRow, "SubStop", 0, &m_MissleRes.m_nSubStop, TRUE);
  259. pMisslesSetting->GetInteger(nRow, "ColFollowTarget",0, (int *)&m_bFollowNpcWhenCollid, TRUE);
  260. #endif
  261. return TRUE;
  262. }
  263. BOOL KMissle::Init( int nLauncher, int nMissleId, int nXFactor, int nYFactor, int nLevel)
  264. {
  265. #ifndef _SERVER
  266. m_MissleRes.Init();
  267. #endif
  268. return TRUE;
  269. }
  270. /*!*****************************************************************************
  271. // Function : KMissle::Activate
  272. // Purpose : 
  273. // Return : void 
  274. // Comments :
  275. // Author : RomanDou
  276. *****************************************************************************/
  277. int KMissle::Activate()
  278. {
  279. if (m_nMissleId <= 0 || m_nRegionId < 0)
  280. {
  281. return  0 ;
  282. }
  283. _ASSERT(m_nLauncher > 0);
  284. if (m_nLauncher <= 0)
  285. return 0;
  286. //子弹的主人已经离开,So 子弹消亡
  287. if (!Npc[m_nLauncher].IsMatch(m_dwLauncherId) || Npc[m_nLauncher].m_SubWorldIndex != m_nSubWorldId || Npc[m_nLauncher].m_RegionIndex < 0)
  288. {
  289. DoVanish();
  290. return 0;
  291. }
  292. //跟踪的目标人物已经不在该地图上时,自动清空
  293. if (m_nFollowNpcIdx > 0)
  294. {
  295. if (!Npc[m_nFollowNpcIdx].IsMatch(m_dwFollowNpcID) || Npc[m_nFollowNpcIdx].m_SubWorldIndex != m_nSubWorldId)
  296. {
  297. m_nFollowNpcIdx = 0;
  298. }
  299. }
  300. eMissleStatus eLastStatus = m_eMissleStatus;
  301. //如果当前状态是子弹生命正常结束正准备消亡状态时,而不是消亡中或者已碰撞中
  302. if (
  303. m_nCurrentLife >= m_nLifeTime 
  304. && m_eMissleStatus != MS_DoVanish 
  305. && m_eMissleStatus != MS_DoCollision
  306. )
  307. {
  308. if (m_bAutoExplode)
  309. {
  310. ProcessCollision();//处理碰撞
  311. }
  312. DoVanish();
  313. #ifdef _SERVER
  314. m_nCurrentLife ++;
  315. return 1;
  316. #endif
  317. }
  318. if (m_nCurrentLife == m_nStartLifeTime && m_eMissleStatus != MS_DoVanish)
  319. {
  320. if (PrePareFly())
  321. {
  322. #ifndef _SERVER
  323. int nSrcX2 = 0 ;
  324. int nSrcY2 = 0 ;
  325. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX2, &nSrcY2);
  326. m_MissleRes.PlaySound(MS_DoFly, nSrcX2, nSrcY2, 0);
  327. //CreateSpecialEffect(MS_DoFly, nSrcX2, nSrcY2, m_nCurrentMapZ);
  328. #endif
  329. DoFly();
  330. }
  331. else
  332. DoVanish();
  333. }
  334. switch(m_eMissleStatus)
  335. {
  336. case MS_DoWait:
  337. {
  338. OnWait();
  339. }
  340. break;
  341. case MS_DoFly:
  342. {
  343. OnFly();
  344. if (m_bFlyEvent)
  345. {
  346. if ( (m_nCurrentLife - m_nStartLifeTime) % m_nFlyEventTime == 0 )
  347. {
  348. _ASSERT(m_nSkillId < MAX_SKILL && m_nLevel < MAX_SKILLLEVEL);
  349. if (m_nLevel  <= 0 ) return 0;
  350. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(m_nSkillId , m_nLevel);
  351. if (pOrdinSkill)
  352. {
  353. pOrdinSkill->FlyEvent(this);
  354. }
  355. }
  356. }
  357. }
  358. break;
  359. case MS_DoCollision:
  360. {
  361. OnCollision();
  362. }
  363. break;
  364. case MS_DoVanish:
  365. {
  366. OnVanish();
  367. }
  368. break;
  369. }
  370. #ifndef _SERVER
  371. //子弹未消亡掉
  372. if (m_nMissleId > 0)
  373. {
  374. int nSrcX;
  375. int nSrcY;
  376. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX, &nSrcY);
  377. if (m_usLightRadius && m_eMissleStatus != MS_DoWait)
  378. g_ScenePlace.MoveObject(CGOG_MISSLE, m_nMissleId, nSrcX, nSrcY, m_nCurrentMapZ, m_SceneID, IPOT_RL_OBJECT | IPOT_RL_LIGHT_PROP );
  379. else
  380. g_ScenePlace.MoveObject(CGOG_MISSLE, m_nMissleId, nSrcX, nSrcY, m_nCurrentMapZ, m_SceneID, IPOT_RL_OBJECT);
  381. }
  382. #endif
  383. m_nCurrentLife ++;
  384. return 1;
  385. }
  386. /*!*****************************************************************************
  387. // Function : KMissle::OnWait
  388. // Purpose : 
  389. // Return : void 
  390. // Comments :
  391. // Author : RomanDou
  392. *****************************************************************************/
  393. void KMissle::OnWait()
  394. {
  395. return;
  396. }
  397. /*!*****************************************************************************
  398. // Function : KMissle::OnCollision
  399. // Purpose : 
  400. // Return : void 
  401. // Comments :
  402. // Author : RomanDou
  403. *****************************************************************************/
  404. void KMissle::OnCollision()
  405. {
  406. return;
  407. }
  408. // 1表示正常碰撞到物体,0表示未碰撞到任何物体, -1表示落地
  409. int KMissle::CheckCollision()
  410. {
  411. #ifdef TOOLVERSION
  412. return FALSE;
  413. #endif
  414. if (m_nCurrentMapZ <= MISSLE_MIN_COLLISION_ZHEIGHT) 
  415. {
  416. return -1;
  417. }
  418. //子弹在高于一定高度时,不处理越界碰撞问题
  419. if (m_nCurrentMapZ > MISSLE_MAX_COLLISION_ZHEIGHT) return 0;
  420. if (m_nRegionId < 0) 
  421. {
  422. return -1;
  423. }
  424. int nAbsX = 0;
  425. int nAbsY = 0;
  426. int nCellWidth = CellWidth;
  427. int nCellHeight = CellHeight;
  428. _ASSERT(nCellWidth > 0 && nCellHeight > 0);
  429. int nRMx = 0;
  430. int nRMy = 0;
  431. int nSearchRegion = 0;
  432. int nNpcIdx = 0;
  433. int nDX = 0;
  434. int nDY = 0;
  435. int nNpcOffsetX = 0;
  436. int nNpcOffsetY = 0;
  437. BOOL bCollision = FALSE;
  438. int nColRegion = m_nRegionId;
  439. int nColMapX = m_nCurrentMapX;
  440. int nColMapY = m_nCurrentMapY;
  441. if (m_nCollideRange == 1)
  442. {
  443. if (m_bNeedReclaim && m_nCurrentLife >= m_nFirstReclaimTime && m_nCurrentLife <= m_nEndReclaimTime)
  444. {
  445. if (m_nCurrentLife == m_nEndReclaimTime) 
  446. m_bNeedReclaim = FALSE;
  447. nNpcIdx =  CheckNearestCollision();
  448. }
  449. else
  450. {
  451. nNpcIdx = SubWorld[m_nSubWorldId].m_Region[nColRegion].FindNpc(nColMapX, nColMapY, m_nLauncher, m_eRelation);
  452. }
  453. if (nNpcIdx > 0)
  454. if (m_nDamageRange == 1)//在目标Npc处碰撞
  455. ProcessCollision(m_nLauncher, Npc[nNpcIdx].m_RegionIndex , Npc[nNpcIdx].m_MapX, Npc[nNpcIdx].m_MapY, m_nDamageRange , m_eRelation);
  456. else
  457. ProcessCollision();//在子弹位置处理碰撞
  458. DoCollision();//子弹作碰撞后的效果
  459. return 1;
  460. }
  461. }
  462. else
  463. {
  464. for (int i = -m_nCollideRange; i <= m_nCollideRange; i ++)
  465. for (int j = -m_nCollideRange; j <= m_nCollideRange; j ++)
  466. {
  467. if (!GetOffsetAxis(m_nSubWorldId, m_nRegionId, m_nCurrentMapX, m_nCurrentMapY, i , j , nSearchRegion, nRMx, nRMy))
  468. continue;
  469. _ASSERT(nSearchRegion >= 0);
  470. nNpcIdx = SubWorld[m_nSubWorldId].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nLauncher, m_eRelation);
  471. if (nNpcIdx > 0)
  472. {
  473. ProcessCollision();//处理碰撞
  474. DoCollision();//子弹作碰撞后的效果
  475. return 1;
  476. }
  477. }
  478. }
  479. return 0;
  480. }
  481. inline DWORD KMissle::GetCurrentSubWorldTime()
  482. {
  483. return SubWorld[m_nSubWorldId].m_dwCurrentTime;
  484. }
  485. void KMissle::OnFly()
  486. {
  487. if (m_nInteruptTypeWhenMove)
  488. {
  489. //当发送者位置移动了,不仅正从do_wait状态到do_fly状态的新子弹被消失掉
  490. //而且已进入dofly状态的旧的所属子弹也要强制消失掉
  491. if (m_nInteruptTypeWhenMove == Interupt_EndOldMissleLifeWhenMove)
  492. {
  493. int nPX, nPY;
  494. Npc[m_nLauncher].GetMpsPos(&nPX, &nPY);
  495. if (nPX != m_nLauncherSrcPX || nPY != m_nLauncherSrcPY)
  496. {
  497. #ifndef _SERVER 
  498. int nSrcX2 = 0 ;
  499. int nSrcY2 = 0 ;
  500. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX2, &nSrcY2);
  501. CreateSpecialEffect(MS_DoVanish, nSrcX2, nSrcY2, m_nCurrentMapZ);
  502. #endif
  503. DoVanish();
  504. return ;
  505. }
  506. }
  507. }
  508. //检测当前位置是否有障碍
  509. if (TestBarrier()) 
  510. {
  511. #ifndef _SERVER 
  512. int nSrcX3 = 0 ;
  513. int nSrcY3 = 0 ;
  514. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX3, &nSrcY3);
  515. CreateSpecialEffect(MS_DoVanish, nSrcX3, nSrcY3, m_nCurrentMapZ);
  516. #endif
  517. DoVanish();
  518. return;
  519. }
  520. int nDOffsetX = 0;
  521. int nDOffsetY = 0;
  522. ZAxisMove();
  523. switch(this->m_eMoveKind)
  524. {
  525. case MISSLE_MMK_Stand: // 原地
  526. {
  527. }
  528. break;
  529. case MISSLE_MMK_Parabola: // 抛物线
  530. case MISSLE_MMK_Line: // 直线飞行
  531. {
  532. nDOffsetX    = (m_nSpeed * m_nXFactor);
  533. nDOffsetY  = (m_nSpeed * m_nYFactor);
  534. }
  535. break;
  536. case MISSLE_MMK_RollBack:
  537. {
  538. if (!m_nTempParam1)
  539. {
  540. if (m_nTempParam2 <= m_nCurrentLife)
  541. {
  542. m_nXFactor = -m_nXFactor;
  543. m_nYFactor = -m_nYFactor;
  544. m_nTempParam1 = 1;
  545. m_nDir = m_nDir - MaxMissleDir / 2;
  546. if (m_nDir < 0) m_nDir += MaxMissleDir;
  547. }
  548. }
  549. nDOffsetX = (m_nSpeed * m_nXFactor);
  550. nDOffsetY = (m_nSpeed * m_nYFactor);
  551. }break;
  552. //按照设计方案,随机飞行无法达到客服两端的同步
  553. case MISSLE_MMK_Random: // 随机飞行(暗黑二女巫的Charged Bolt)
  554. {
  555. }break;
  556. //参数一表示顺时针还是逆时针转动
  557. //参数二表示固定原心还是围饶发动者
  558. //dx = SinA * R
  559. //dy = Ctg(90-A/2).R = SinA*SinA / (1 + CosA) * R
  560. case MISSLE_MMK_Circle: // 环行飞行(围绕在身边,暗黑二刺客的集气)
  561. {
  562. int nPreAngle = m_nAngle - 1;
  563. if (nPreAngle < 0) nPreAngle = MaxMissleDir - 1;
  564. m_nDir = m_nAngle + (MaxMissleDir / 4);
  565. if (m_nDir >= MaxMissleDir) m_nDir = m_nDir - MaxMissleDir;
  566. int dx = (m_nSpeed + 50)  * (g_DirCos(m_nAngle,MaxMissleDir) - g_DirCos(nPreAngle,MaxMissleDir)) ;
  567. int dy = (m_nSpeed + 50)  * (g_DirSin(m_nAngle,MaxMissleDir) - g_DirSin(nPreAngle, MaxMissleDir)) ; 
  568. if (m_nParam2) //原地转
  569. {
  570. nDOffsetX = dx;
  571. nDOffsetY = dy;
  572. }
  573. else // 围绕着发送者转
  574. {
  575. int nOldRegion = m_nRegionId;
  576. CurRegion.DecRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  577. m_nRegionId = Npc[m_nLauncher].m_RegionIndex;
  578. m_nCurrentMapX = Npc[m_nLauncher].m_MapX;
  579. m_nCurrentMapY = Npc[m_nLauncher].m_MapY;
  580. m_nXOffset = Npc[m_nLauncher].m_OffX;
  581. m_nYOffset = Npc[m_nLauncher].m_OffY;
  582. CurRegion.AddRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  583. if (nOldRegion != m_nRegionId)
  584. {
  585. SubWorld[m_nSubWorldId].m_WorldMessage.Send(GWM_MISSLE_CHANGE_REGION, nOldRegion, m_nRegionId, m_nMissleId);
  586. }  
  587. nDOffsetX = dx;
  588. nDOffsetY = dy;
  589. }
  590. //顺时针还是逆时针
  591. if (m_nParam1)
  592. {
  593. m_nAngle ++;
  594. if (m_nAngle >= MaxMissleDir)
  595. m_nAngle = 0;
  596. }
  597. else
  598. {
  599. m_nAngle --;
  600. if (m_nAngle < 0 )
  601. m_nAngle = MaxMissleDir - 1;
  602. }
  603. }
  604. break;
  605. //参数一表示顺时针还是逆时针转动
  606. //参数二表示固定原心还是围饶发动者
  607. case MISSLE_MMK_Helix: // 阿基米德螺旋线(暗黑二游侠的Bless Hammer)
  608. {
  609. int nPreAngle = m_nAngle - 1;
  610. if (nPreAngle < 0) 
  611. {
  612. nPreAngle = MaxMissleDir -1;
  613. }
  614. m_nDir = m_nAngle + (MaxMissleDir / 4);
  615. if (m_nDir >= MaxMissleDir) m_nDir = m_nDir - MaxMissleDir;
  616. int dx = (m_nSpeed + m_nCurrentLife + 50)  * (g_DirCos(m_nAngle,MaxMissleDir) - g_DirCos(nPreAngle, MaxMissleDir)) ;
  617. int dy = (m_nSpeed + m_nCurrentLife + 50)  * (g_DirSin(m_nAngle,MaxMissleDir) - g_DirSin(nPreAngle,MaxMissleDir)) ; 
  618. if (m_nParam2) //原地转
  619. {
  620. nDOffsetX = dx;
  621. nDOffsetY = dy;
  622. }
  623. else // 围绕着发送者转
  624. {
  625. int nOldRegion = m_nRegionId;
  626. CurRegion.DecRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  627. m_nRegionId = Npc[m_nLauncher].m_RegionIndex;
  628. m_nCurrentMapX = Npc[m_nLauncher].m_MapX;
  629. m_nCurrentMapY = Npc[m_nLauncher].m_MapY;
  630. m_nXOffset = Npc[m_nLauncher].m_OffX;
  631. m_nYOffset = Npc[m_nLauncher].m_OffY;
  632. CurRegion.AddRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  633. if (nOldRegion != m_nRegionId)
  634. {
  635. SubWorld[m_nSubWorldId].m_WorldMessage.Send(GWM_MISSLE_CHANGE_REGION, nOldRegion, m_nRegionId, m_nMissleId);
  636. }  
  637. nDOffsetX = dx;
  638. nDOffsetY = dy;
  639. }
  640. if (m_nParam1)
  641. {
  642. m_nAngle ++;
  643. if (m_nAngle >= MaxMissleDir)
  644. m_nAngle = 0;
  645. }
  646. else
  647. {
  648. m_nAngle --;
  649. if (m_nAngle < 0 )
  650. m_nAngle = MaxMissleDir - 1;
  651. }
  652. }
  653. break; 
  654. case MISSLE_MMK_Follow: // 跟踪目标飞行
  655. {
  656. int nDistance = 0;
  657. int nSrcMpsX = 0;
  658. int nSrcMpsY = 0;
  659. int nDesMpsX = 0;
  660. int nDesMpsY = 0;
  661. SubWorld[m_nSubWorldId].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY, m_nXOffset, m_nYOffset, &nSrcMpsX, &nSrcMpsY);
  662. SubWorld[m_nSubWorldId].Map2Mps(Npc[m_nFollowNpcIdx].m_RegionIndex, Npc[m_nFollowNpcIdx].m_MapX, Npc[m_nFollowNpcIdx].m_MapY, Npc[m_nFollowNpcIdx].m_OffX, Npc[m_nFollowNpcIdx].m_OffY, &nDesMpsX, &nDesMpsY);
  663. nDistance = SubWorld[m_nSubWorldId].GetDistance(nSrcMpsX, nSrcMpsY, nDesMpsX, nDesMpsY);
  664. if (nDistance != 0)
  665. {
  666. int nXFactor = ((nDesMpsX - nSrcMpsY ) << 10) / nDistance;
  667. int nYFactor = ((nDesMpsY - nSrcMpsY ) << 10) / nDistance;
  668. int dx  = nXFactor * m_nSpeed;
  669. int dy  = nYFactor * m_nSpeed;
  670. nDOffsetX  = dx;
  671. nDOffsetY  = dy;
  672. }
  673. }break;
  674. case MISSLE_MMK_Motion: // 玩家动作类
  675. {
  676. }break;
  677. case MISSLE_MMK_SingleLine: // 必中的单一直线飞行魔法
  678. {
  679. //单一必中类子弹,类式于传奇以及其它的同类网络游戏中的基本直线魔法
  680. #ifdef _SERVER
  681. #else
  682. int x = m_nXOffset;
  683. int y = m_nYOffset;
  684. int dx = (m_nSpeed * m_nXFactor);
  685. int dy = (m_nSpeed * m_nYFactor);
  686. nDOffsetX =  dx;//* m_nCurrentLife;
  687. nDOffsetY =  dy;//* m_nCurrentLife;
  688. #endif
  689. }
  690. break;
  691. default:
  692. _ASSERT(0);
  693. }
  694. //
  695. if (CheckBeyondRegion(nDOffsetX, nDOffsetY))
  696. {
  697. if (CheckCollision() == -1) 
  698. {
  699. if (m_bAutoExplode)
  700. {
  701. ProcessCollision();//处理碰撞
  702. }
  703. #ifndef _SERVER 
  704. int nSrcX4 = 0 ;
  705. int nSrcY4 = 0 ;
  706. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX4, &nSrcY4);
  707. CreateSpecialEffect(MS_DoVanish, nSrcX4, nSrcY4, m_nCurrentMapZ);
  708. #endif
  709. DoVanish();
  710. return;
  711. }
  712. }
  713. else//如果子弹飞行过程中进入了一个无效的Region则子弹自动消亡
  714. {
  715. DoVanish();
  716. }
  717. }
  718. /*!*****************************************************************************
  719. // Function : KMissle::OnVanish
  720. // Purpose : 
  721. // Return : void 
  722. // Comments :
  723. // Author : RomanDou
  724. *****************************************************************************/
  725. void KMissle::OnVanish()
  726. {
  727. }
  728. #ifndef _SERVER
  729. void KMissle::Paint()
  730. {
  731. if (m_nMissleId <= 0 ) return;
  732. int nSrcX;
  733. int nSrcY;
  734. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX, &nSrcY);
  735. if (!m_nZAcceleration)
  736. {
  737. m_MissleRes.Draw(m_eMissleStatus, nSrcX, nSrcY, m_nCurrentMapZ, m_nDir,m_nLifeTime - m_nStartLifeTime,  m_nCurrentLife - m_nStartLifeTime );
  738. }
  739. else
  740. {
  741. int nDirIndex = g_GetDirIndex(0,0,m_nXFactor, m_nYFactor);
  742. int nDir = g_DirIndex2Dir(nDirIndex, 64);
  743. m_MissleRes.Draw(m_eMissleStatus, nSrcX, nSrcY, m_nCurrentMapZ, nDir,m_nLifeTime - m_nStartLifeTime,  m_nCurrentLife - m_nStartLifeTime );
  744. }
  745. //对于客户端,直到子弹及其产生的效果全部播放完才终止并删除掉!
  746. if (m_MissleRes.m_bHaveEnd && (m_MissleRes.SpecialMovieIsAllEnd()))
  747. SubWorld[m_nSubWorldId].m_WorldMessage.Send(GWM_MISSLE_DEL, m_nMissleId);
  748. }
  749. #endif
  750. BOOL KMissle::CheckBeyondRegion(int nDOffsetX, int nDOffsetY)
  751. {
  752. if (m_nRegionId < 0) 
  753. return FALSE;
  754. //未动
  755. if (nDOffsetX == 0 && nDOffsetY == 0) return TRUE;
  756. if (abs(nDOffsetX) > CellWidth) 
  757. {
  758. return FALSE;
  759. }
  760. if (abs(nDOffsetY) > CellHeight) 
  761. {
  762. return FALSE;
  763. }
  764. int nOldRegion = m_nRegionId;
  765. int nNewXOffset = m_nXOffset + nDOffsetX;
  766. int nNewYOffset = m_nYOffset + nDOffsetY;
  767. int nNewMapX = m_nCurrentMapX;
  768. int nNewMapY = m_nCurrentMapY;
  769. int nNewRegion = m_nRegionId;
  770. DWORD nRegionWidth = RegionWidth;
  771. DWORD nRegionHeight = RegionHeight;
  772. _ASSERT(abs(nNewXOffset) <= CellWidth * 2);
  773. _ASSERT(abs(nNewYOffset) <= CellHeight * 2);
  774. // 处理NPC的坐标变幻
  775. // CELLWIDTH、CELLHEIGHT、OffX、OffY均是放大了1024倍
  776. if (nNewXOffset < 0)
  777. {
  778. nNewMapX--;
  779. nNewXOffset += CellWidth;
  780. }
  781. else if (nNewXOffset > CellWidth)
  782. {
  783. nNewMapX++;
  784. nNewXOffset -= CellWidth;
  785. }
  786. if (nNewYOffset < 0)
  787. {
  788. nNewMapY--;
  789. nNewYOffset += CellHeight;
  790. }
  791. else if (nNewYOffset > CellHeight)
  792. {
  793. nNewMapY++;
  794. nNewYOffset -= CellHeight;
  795. }
  796. if (nNewMapX < 0)
  797. {
  798. nNewRegion = LeftRegion(m_nRegionId);
  799. nNewMapX += nRegionWidth;
  800. }
  801. else if ((DWORD)nNewMapX >= nRegionWidth)
  802. {
  803. nNewRegion = RightRegion(m_nRegionId);
  804. nNewMapX -= nRegionWidth;
  805. }
  806. if (nNewRegion < 0) 
  807. {
  808. return FALSE; 
  809. }
  810. if (nNewMapY < 0)
  811. {
  812. nNewRegion = UpRegion(nNewRegion);
  813. nNewMapY += nRegionHeight;
  814. }
  815. else if (nNewMapY >= RegionHeight)
  816. {
  817. nNewRegion = DownRegion(nNewRegion);
  818. nNewMapY -= nRegionHeight;
  819. }
  820. //下一个位置为不合法位置,则消亡
  821. if (nNewRegion < 0) 
  822. {
  823. return FALSE; 
  824. }
  825. else
  826. {
  827. CurRegion.DecRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  828. _ASSERT(m_nCurrentMapX >= 0  &&  m_nCurrentMapY >= 0);
  829. m_nRegionId    = nNewRegion;
  830. m_nCurrentMapX = nNewMapX;
  831. m_nCurrentMapY = nNewMapY;
  832. m_nXOffset    = nNewXOffset;
  833. m_nYOffset    = nNewYOffset;
  834. CurRegion.AddRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  835. if (nOldRegion != m_nRegionId)
  836. {
  837. SubWorld[m_nSubWorldId].m_WorldMessage.Send(GWM_MISSLE_CHANGE_REGION, nOldRegion, m_nRegionId, m_nMissleId);
  838. }
  839. }
  840. return TRUE;
  841. }
  842. KMissle& KMissle::operator=(KMissle& Missle)
  843. {
  844. Missle.m_nTempParam1 = 0;
  845. Missle.m_nTempParam2 = 0;
  846. Missle.m_nDesMapX = 0;
  847. Missle.m_nDesMapY = 0;
  848. Missle.m_nDesRegion = 0;
  849. Missle.m_bNeedReclaim = FALSE;
  850. Missle.m_nFirstReclaimTime = 0;
  851. Missle.m_nEndReclaimTime = 0;
  852. memset(Missle.m_NeedReclaimPos, 0, sizeof(m_NeedReclaimPos));
  853. Missle.m_bCanSlow = m_bCanSlow;
  854. Missle.m_bCollideEvent = m_bCollideEvent;
  855. Missle.m_bCollideFriend = m_bCollideFriend;
  856. Missle.m_bCollideVanish = m_bCollideVanish;
  857. Missle.m_bRangeDamage = m_bRangeDamage;
  858. Missle.m_eFollowKind = m_eFollowKind;
  859. Missle.m_eMoveKind = m_eMoveKind;
  860. Missle.m_nAction = m_nAction;
  861. Missle.m_nAngle = m_nAngle;
  862. Missle.m_nCollideRange = m_nCollideRange;
  863. Missle.m_nCurrentLife = 0;
  864. Missle.m_nDamageRange = m_nDamageRange;
  865. Missle.m_nHeight = m_nHeight;
  866. Missle.m_nLifeTime = m_nLifeTime;
  867. Missle.m_nSpeed =   m_nSpeed;
  868. Missle.m_nParam1 = m_nParam1;
  869. Missle.m_nParam2 = m_nParam2;
  870. Missle.m_nParam3 = m_nParam3;
  871. Missle.m_nCurrentMapZ =   m_nHeight >> 10;
  872. Missle.m_bFlyEvent = m_bFlyEvent;
  873. Missle.m_nFlyEventTime  = m_nFlyEventTime;
  874. Missle.m_nZAcceleration = m_nZAcceleration;
  875. Missle.m_nHeightSpeed = m_nHeightSpeed;
  876. Missle.m_bAutoExplode = m_bAutoExplode;
  877. Missle.m_ulDamageInterval = m_ulDamageInterval;
  878. strcpy(Missle.m_szMissleName , m_szMissleName);
  879. #ifndef  _SERVER
  880. Missle.m_bMultiShow =  m_bMultiShow;
  881. Missle.m_MissleRes.m_bLoopAnim = m_MissleRes.m_bLoopAnim;
  882. Missle.m_MissleRes.m_bHaveEnd = FALSE;
  883. Missle.m_btRedLum = m_btRedLum;
  884. Missle.m_btGreenLum = m_btGreenLum;
  885. Missle.m_btBlueLum = m_btBlueLum;
  886. Missle.m_usLightRadius = m_usLightRadius;
  887. int nOffset = 0;
  888. //如果是相同的子弹可以以不同方式显示时,则随机产生
  889. if (m_bMultiShow)
  890. {
  891. if (g_Random(2) == 0)
  892. {
  893. nOffset = 0;
  894. }
  895. else
  896. nOffset = MAX_MISSLE_STATUS;
  897. }
  898. for (int t = 0; t < MAX_MISSLE_STATUS ; t++)
  899. {
  900. strcpy(Missle.m_MissleRes.m_MissleRes[t].AnimFileName,m_MissleRes.m_MissleRes[t + nOffset].AnimFileName);
  901. Missle.m_MissleRes.m_MissleRes[t].nTotalFrame = m_MissleRes.m_MissleRes[t + nOffset].nTotalFrame;
  902. Missle.m_MissleRes.m_MissleRes[t].nDir = m_MissleRes.m_MissleRes[t + nOffset].nDir;
  903. Missle.m_MissleRes.m_MissleRes[t].nInterval = m_MissleRes.m_MissleRes[t + nOffset].nInterval;
  904. strcpy(Missle.m_MissleRes.m_MissleRes[t].SndFileName,m_MissleRes.m_MissleRes[t + nOffset].SndFileName);
  905. }
  906. Missle.m_MissleRes.m_bSubLoop = m_MissleRes.m_bSubLoop;
  907. Missle.m_MissleRes.m_nSubStart = m_MissleRes.m_nSubStart;
  908. Missle.m_MissleRes.m_nSubStop = m_MissleRes.m_nSubStop;
  909. #endif
  910. return (Missle);
  911. }
  912. /*!*****************************************************************************
  913. // Function : KMissle::ProcessDamage
  914. // Purpose : 
  915. // Return : BOOL 
  916. // Argumant : int nNpcId
  917. // Comments :
  918. // Author : RomanDou
  919. *****************************************************************************/
  920. BOOL KMissle::ProcessDamage(int nNpcId)
  921. {
  922. #ifdef _SERVER
  923. bool bCalDamage = false;
  924. _ASSERT (Npc[m_nLauncher].IsMatch(m_dwLauncherId));
  925. if (m_pMagicAttribsData) 
  926. {
  927. if (Npc[nNpcId].ReceiveDamage(m_nLauncher, m_bIsMelee, m_pMagicAttribsData->m_pDamageMagicAttribs, m_bUseAttackRating, m_bDoHurt))
  928. {
  929. if (m_pMagicAttribsData->m_nStateMagicAttribsNum > 0)
  930. Npc[nNpcId].SetStateSkillEffect(m_nLauncher, m_nSkillId, m_nLevel, m_pMagicAttribsData->m_pStateMagicAttribs, m_pMagicAttribsData->m_nStateMagicAttribsNum, m_pMagicAttribsData->m_pStateMagicAttribs[0].nValue[1]);
  931. if (m_pMagicAttribsData->m_nImmediateMagicAttribsNum > 0)
  932. Npc[nNpcId].SetImmediatelySkillEffect(m_nLauncher, m_pMagicAttribsData->m_pImmediateAttribs, m_pMagicAttribsData->m_nImmediateMagicAttribsNum);
  933. }
  934. return TRUE;
  935. }
  936. #endif //_SERVER
  937. return FALSE;
  938. }
  939. void KMissle::DoVanish()
  940. {
  941. if (m_eMissleStatus == MS_DoVanish) return ;
  942. #ifndef _SERVER
  943. m_MissleRes.m_bHaveEnd = TRUE;
  944. m_nCollideOrVanishTime = m_nCurrentLife;
  945. #endif
  946. if (m_bVanishedEvent)
  947. {
  948. _ASSERT(m_nSkillId < MAX_SKILL && m_nLevel < MAX_SKILLLEVEL);
  949. KSkill * pOrdinSkill = (KSkill *) g_SkillManager.GetSkill(m_nSkillId,m_nLevel);
  950. if (pOrdinSkill)
  951.         {
  952. pOrdinSkill->Vanish(this);
  953.         }
  954. }
  955. #ifdef _SERVER //服务器端时子弹一旦进入消亡期则直接删除掉
  956. SubWorld[m_nSubWorldId].m_WorldMessage.Send(GWM_MISSLE_DEL, m_nMissleId);
  957. m_eMissleStatus = MS_DoVanish;
  958. return ;
  959. #endif
  960. m_eMissleStatus = MS_DoVanish;
  961. #ifndef _SERVER 
  962. if (m_nRegionId < 0)
  963. {
  964. _ASSERT(0);
  965. m_bRemoving = TRUE;
  966. return ;
  967. }
  968. #endif
  969. }
  970. void KMissle::DoCollision()
  971. {
  972. if (m_eMissleStatus == MS_DoCollision) return;
  973. #ifndef _SERVER
  974. int nSrcX = 0 ;
  975. int nSrcY = 0 ;
  976. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX, &nSrcY);
  977. #endif
  978. if (m_bCollideEvent)
  979. {
  980. _ASSERT(m_nSkillId < MAX_SKILL && m_nLevel < MAX_SKILLLEVEL);
  981. KSkill * pOrdinSkill = (KSkill *)g_SkillManager.GetSkill(m_nSkillId, m_nLevel);
  982. if (pOrdinSkill)
  983.         {
  984. pOrdinSkill->Collidsion(this);
  985.         }
  986. }
  987. if (m_bCollideVanish)
  988. {
  989. #ifndef _SERVER
  990. m_MissleRes.m_bHaveEnd = TRUE;
  991. #endif
  992. #ifndef _SERVER 
  993. int nSrcX5 = 0 ;
  994. int nSrcY5 = 0 ;
  995. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX5, &nSrcY5);
  996. CreateSpecialEffect(MS_DoVanish, nSrcX5, nSrcY5, m_nCurrentMapZ);
  997. #endif
  998. DoVanish();
  999. }
  1000. else 
  1001. {
  1002. #ifndef _SERVER
  1003. //增加撞后的效果
  1004. if (m_MissleRes.SpecialMovieIsAllEnd())
  1005. CreateSpecialEffect(MS_DoCollision, nSrcX, nSrcY, m_nCurrentMapZ);
  1006. #endif
  1007. m_eMissleStatus = MS_DoFly;
  1008. }
  1009. }
  1010. void KMissle::DoFly()
  1011. {
  1012. if (m_eMissleStatus == MS_DoFly) return ;
  1013. //初始化贴图
  1014. m_eMissleStatus = MS_DoFly;
  1015. }
  1016. BOOL KMissle::GetOffsetAxis(int nSubWorld, int nSrcRegionId, int nSrcMapX, int nSrcMapY,
  1017. int nOffsetMapX, int nOffsetMapY, 
  1018. int &nDesRegionId, int &nDesMapX, int &nDesMapY)
  1019. {
  1020. nDesRegionId = -1;
  1021. // 确定目标格子实际的REGION和坐标确定
  1022. nDesMapX = nSrcMapX + nOffsetMapX;
  1023. nDesMapY = nSrcMapY + nOffsetMapY;
  1024. if (nSrcRegionId < 0) 
  1025. return FALSE;
  1026. int nSearchRegion = nSrcRegionId;
  1027. if (nDesMapX < 0)
  1028. {
  1029. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[2];
  1030. nDesMapX += SubWorld[nSubWorld].m_nRegionWidth;
  1031. }
  1032. else if (nDesMapX >= SubWorld[nSubWorld].m_nRegionWidth)
  1033. {
  1034. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[6];
  1035. nDesMapX -= SubWorld[nSubWorld].m_nRegionWidth;
  1036. }
  1037. if (nSearchRegion < 0) 
  1038. return FALSE;
  1039. if (nDesMapY < 0)
  1040. {
  1041. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[4];
  1042. nDesMapY += SubWorld[nSubWorld].m_nRegionHeight;
  1043. }
  1044. else if (nDesMapY >= SubWorld[nSubWorld].m_nRegionHeight)
  1045. {
  1046. nSearchRegion = SubWorld[nSubWorld].m_Region[nSearchRegion].m_nConnectRegion[0];
  1047. nDesMapY -= SubWorld[nSubWorld].m_nRegionHeight;
  1048. }
  1049. if (nSearchRegion < 0) 
  1050. return FALSE;
  1051. nDesRegionId = nSearchRegion;
  1052. return TRUE;
  1053. // 从REGION的NPC列表中查找满足条件的NPC
  1054. //int nNpcIdx = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nDesMapX, nDesMapY, nLauncherIdx, relation_all);
  1055. }
  1056. /*!*****************************************************************************
  1057. // Function : KMissle::ProcessCollision
  1058. // Purpose : 
  1059. // Return : int 
  1060. // Argumant : int nLauncherIdx
  1061. // Argumant : int nRegionId
  1062. // Argumant : int nMapX
  1063. // Argumant : int nMapY
  1064. // Argumant : int nRange
  1065. // Argumant : MISSLE_RELATION eRelation
  1066. // Comments :
  1067. // Author : RomanDou
  1068. *****************************************************************************/
  1069. int KMissle::ProcessCollision(int nLauncherIdx, int nRegionId, int nMapX, int nMapY, int nRange , int eRelation)
  1070. {
  1071. #ifdef TOOLVERSION 
  1072. return 0;
  1073. #endif
  1074. #ifdef _SERVER
  1075. if (m_ulDamageInterval)
  1076. {
  1077. if (m_ulNextCalDamageTime > g_SubWorldSet.GetGameTime())
  1078. {
  1079. return FALSE;
  1080. }
  1081. else
  1082. {
  1083. // 6.29 romandou missledamage interval 
  1084. m_ulNextCalDamageTime = g_SubWorldSet.GetGameTime() + m_ulDamageInterval;
  1085. }
  1086. }
  1087. #endif
  1088. if (nLauncherIdx <= 0 ) return 0;
  1089. if (nRange <= 0) return 0;
  1090. int nRangeX = nRange / 2;
  1091. int nRangeY = nRangeX;
  1092. int nSubWorld = Npc[nLauncherIdx].m_SubWorldIndex;
  1093. _ASSERT(Npc[nLauncherIdx].m_SubWorldIndex >= 0);
  1094. _ASSERT(nRegionId >= 0);
  1095. int nRegion = nRegionId;
  1096. int nRet = 0;
  1097. int nRMx, nRMy, nSearchRegion;
  1098. // 检查范围内的格子里的NPC
  1099. for (int i = -nRangeX; i <= nRangeX; i++)
  1100. {
  1101. for (int j = -nRangeY; j <= nRangeY; j++)
  1102. {
  1103. // 去掉边角几个格子,保证视野是椭圆形
  1104. //if ((i * i + j * j ) > nRangeX * nRangeX)
  1105. //continue;
  1106. if (!GetOffsetAxis(nSubWorld, nRegionId, nMapX, nMapY, i , j , nSearchRegion, nRMx, nRMy))
  1107. continue;
  1108. _ASSERT(nSearchRegion >= 0);
  1109. // 从REGION的NPC列表中查找满足条件的NPC
  1110. int nNpcIdx = SubWorld[nSubWorld].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, nLauncherIdx, eRelation);
  1111. if (nNpcIdx > 0)
  1112. {
  1113. nRet++;
  1114. #ifndef _SERVER
  1115. int nSrcX = 0;
  1116. int nSrcY = 0;
  1117. SubWorld[0].Map2Mps(nSearchRegion, Npc[nNpcIdx].m_MapX,Npc[nNpcIdx].m_MapY, Npc[nNpcIdx].m_OffX, Npc[nNpcIdx].m_OffY,  &nSrcX, &nSrcY);
  1118. if (m_bFollowNpcWhenCollid)
  1119. CreateSpecialEffect(MS_DoCollision, nSrcX, nSrcY, m_nCurrentMapZ, nNpcIdx);
  1120. else 
  1121. CreateSpecialEffect(MS_DoCollision, nSrcX, nSrcY, m_nCurrentMapZ);
  1122. #else
  1123. ProcessDamage(nNpcIdx);
  1124. #endif
  1125. }
  1126. }
  1127. }
  1128. return nRet;
  1129. }
  1130. int KMissle::ProcessCollision()
  1131. {
  1132. #ifdef TOOLVERSION
  1133. return 0;
  1134. #endif
  1135. if (m_bClientSend) return 0;
  1136. return ProcessCollision(m_nLauncher, m_nRegionId, m_nCurrentMapX, m_nCurrentMapY, m_nDamageRange , m_eRelation);
  1137. }
  1138. #ifndef _SERVER 
  1139. //生成某个特效结点
  1140. #define MISSLE_Y_OFFSET 1
  1141. BOOL KMissle::CreateSpecialEffect(eMissleStatus eStatus, int nPX, int nPY, int nPZ, int nNpcIndex)
  1142. {
  1143. KSkillSpecialNode * pNode = NULL;
  1144. //同一颗子碟不能有几个爆炸效果在一个Npc身上
  1145. if (nNpcIndex > 0)
  1146. {
  1147. pNode = (KSkillSpecialNode*)m_MissleRes.m_SkillSpecialList.GetHead();
  1148. while(pNode)
  1149. {
  1150. if (pNode->m_pSkillSpecial->m_dwMatchID == Npc[nNpcIndex].m_dwID) return FALSE;
  1151. pNode = (KSkillSpecialNode*)pNode->GetNext();
  1152. }
  1153. }
  1154. m_MissleRes.PlaySound(eStatus, nPX, nPY, 0);
  1155. if (!m_MissleRes.m_MissleRes[eStatus].AnimFileName[0]) return FALSE; 
  1156. pNode = new KSkillSpecialNode;
  1157. KSkillSpecial * pSkillSpecial = new KSkillSpecial;
  1158. pNode->m_pSkillSpecial = pSkillSpecial;
  1159. int nSrcX = nPX;
  1160. int nSrcY = nPY;
  1161. pSkillSpecial->m_nPX = nSrcX;
  1162. pSkillSpecial->m_nPY = nSrcY - 5;// MISSLE_Y_OFFSET;
  1163. pSkillSpecial->m_nPZ = nPZ;
  1164. pSkillSpecial->m_nNpcIndex = nNpcIndex;
  1165. pSkillSpecial->m_dwMatchID = Npc[nNpcIndex].m_dwID;
  1166. pSkillSpecial->m_pMissleRes = &m_MissleRes.m_MissleRes[eStatus];
  1167. pSkillSpecial->m_nBeginTime = g_SubWorldSet.GetGameTime();
  1168. pSkillSpecial->m_nEndTime = g_SubWorldSet.GetGameTime() + (pSkillSpecial->m_pMissleRes->nInterval * pSkillSpecial->m_pMissleRes->nTotalFrame / pSkillSpecial->m_pMissleRes->nDir);
  1169. pSkillSpecial->m_nCurDir = g_DirIndex2Dir(m_nDirIndex, m_MissleRes.m_MissleRes[eStatus].nDir);
  1170. pSkillSpecial->Init();
  1171. m_MissleRes.m_SkillSpecialList.AddTail(pNode);
  1172. return TRUE;
  1173. }
  1174. BOOL KMissle::CreateMissleForShow(char * szMovie, char * szFormat, char * szSound, TMissleForShow * pShowParam)
  1175. {
  1176. if (!pShowParam || !szMovie || !szMovie[0])
  1177. return FALSE;
  1178. int nPX = 0;
  1179. int nPY = 0;
  1180. int nPZ = 0;
  1181. if (pShowParam->nNpcIndex > 0)
  1182. {
  1183. Npc[pShowParam->nNpcIndex].GetMpsPos(&nPX, &nPY);
  1184. }
  1185. else
  1186. {
  1187. nPX = pShowParam->nPX;
  1188. nPY = pShowParam->nPY;
  1189. }
  1190. int nSubWorldId = Npc[Player[CLIENT_PLAYER_INDEX].m_nIndex].m_SubWorldIndex;
  1191. int nMissleIndex = MissleSet.Add(nSubWorldId , nPX , nPY);
  1192. if (nMissleIndex < 0)
  1193. return FALSE;
  1194. Missle[nMissleIndex].m_nDir = Npc[Player[CLIENT_PLAYER_INDEX].m_nIndex].m_Dir;
  1195. Missle[nMissleIndex].m_nDirIndex = g_Dir2DirIndex(Missle[nMissleIndex].m_nDir, MaxMissleDir);
  1196. Missle[nMissleIndex].m_nFollowNpcIdx = 0;
  1197. Missle[nMissleIndex].m_dwBornTime = SubWorld[nSubWorldId].m_dwCurrentTime;
  1198. Missle[nMissleIndex].m_nSubWorldId = nSubWorldId;
  1199. Missle[nMissleIndex].m_nLauncher = pShowParam->nLauncherIndex;
  1200. Missle[nMissleIndex].m_dwLauncherId = Npc[pShowParam->nLauncherIndex].m_dwID;
  1201. Missle[nMissleIndex].m_nParentMissleIndex = 0;
  1202. Missle[nMissleIndex].m_nSkillId = 0;
  1203. Missle[nMissleIndex].m_nStartLifeTime = 0;
  1204. Missle[nMissleIndex].m_nLifeTime = 1;
  1205. Missle[nMissleIndex].m_nRefPX = 0;
  1206. Missle[nMissleIndex].m_nRefPY = 0;
  1207. Missle[nMissleIndex].m_MissleRes.Clear();
  1208. Missle[nMissleIndex].m_MissleRes.LoadResource(MS_DoWait, szMovie, szSound);
  1209. char * pcszTemp = szFormat;
  1210. Missle[nMissleIndex].m_MissleRes.m_MissleRes[MS_DoWait].nTotalFrame = KSG_StringGetInt(&pcszTemp, 100);
  1211. KSG_StringSkipSymbol(&pcszTemp, ',');
  1212. Missle[nMissleIndex].m_MissleRes.m_MissleRes[MS_DoWait].nDir = KSG_StringGetInt(&pcszTemp, 16);
  1213. KSG_StringSkipSymbol(&pcszTemp, ',');
  1214.     Missle[nMissleIndex].m_MissleRes.m_MissleRes[MS_DoWait].nInterval = KSG_StringGetInt(&pcszTemp, 1);
  1215. Missle[nMissleIndex].CreateSpecialEffect(MS_DoWait, nPX, nPY, nPZ, pShowParam->nNpcIndex);
  1216. return TRUE;
  1217. }
  1218. void KMissle::GetLightInfo(KLightInfo * pLightInfo)
  1219. {
  1220. if (!pLightInfo) 
  1221. {
  1222. return ;
  1223. }
  1224. int nPX, nPY, nPZ;
  1225. GetMpsPos(&nPX, &nPY);
  1226. nPZ = m_nCurrentMapZ;
  1227. pLightInfo->oPosition.nX = nPX;
  1228. pLightInfo->oPosition.nY = nPY;
  1229. pLightInfo->oPosition.nZ = nPZ;
  1230. pLightInfo->dwColor = 0xff000000 | m_btRedLum << 16 | m_btGreenLum << 8 | m_btBlueLum;
  1231. pLightInfo->nRadius = m_usLightRadius;
  1232. }
  1233. #endif
  1234. void KMissle::DoWait()
  1235. {
  1236. // if (m_eMissleStatus == MS_DoWait) return;
  1237. m_eMissleStatus = MS_DoWait;
  1238. #ifndef _SERVER 
  1239. int nSrcX = 0 ;
  1240. int nSrcY = 0 ;
  1241. SubWorld[0].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY,m_nXOffset, m_nYOffset, &nSrcX, &nSrcY);
  1242. CreateSpecialEffect(MS_DoWait, nSrcX, nSrcY, m_nCurrentMapZ);
  1243. #endif
  1244. }
  1245. //当子碟进入fly状态时,需要根据情况变动
  1246. BOOL KMissle::PrePareFly()
  1247. {
  1248. if (m_eMoveKind == MISSLE_MMK_RollBack)
  1249. m_nTempParam2 =  m_nStartLifeTime + (m_nLifeTime - m_nStartLifeTime ) / 2;
  1250. //是否会随发送者的移动而中断,类式魔兽3中大型法术
  1251. if (m_nInteruptTypeWhenMove)
  1252. {
  1253. int nPX, nPY;
  1254. Npc[m_nLauncher].GetMpsPos(&nPX, &nPY);
  1255. if (nPX != m_nLauncherSrcPX || nPY != m_nLauncherSrcPY)
  1256. {
  1257. return false;
  1258. }
  1259. }
  1260. //子碟位置需要更正为到适当的位置(子弹的出现总是以某个可能位置在不断变化的物体为参照物)
  1261. if (m_bHeelAtParent)
  1262. {
  1263. int nNewPX = 0;
  1264. int nNewPY = 0;
  1265. if (m_nParentMissleIndex) // 参考点为母子弹
  1266. {
  1267. if (Missle[m_nParentMissleIndex].m_dwLauncherId != m_dwLauncherId)
  1268. {
  1269. return false;
  1270. }
  1271. else
  1272. {
  1273. int nParentPX, nParentPY;
  1274. int nSrcPX, nSrcPY;
  1275. Missle[m_nParentMissleIndex].GetMpsPos(&nParentPX, &nParentPY);
  1276. GetMpsPos(&nSrcPX, &nSrcPY);
  1277. nNewPX = nSrcPX + (nParentPX - m_nRefPX);
  1278. nNewPY = nSrcPY + (nParentPY - m_nRefPY);
  1279. }
  1280. }
  1281. else
  1282. //参考点为发送者
  1283. {
  1284. _ASSERT(m_nLauncher > 0);
  1285. int nParentPX, nParentPY;
  1286. int nSrcPX, nSrcPY;
  1287. Npc[m_nLauncher].GetMpsPos(&nParentPX, &nParentPY);
  1288. GetMpsPos(&nSrcPX, &nSrcPY);
  1289. nNewPX = nSrcPX + (nParentPX - m_nRefPX);
  1290. nNewPY = nSrcPY + (nParentPY - m_nRefPY);
  1291. }
  1292. int nOldRegion = m_nRegionId;
  1293. CurRegion.DecRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  1294. SubWorld[m_nSubWorldId].Mps2Map(nNewPX, nNewPY, &m_nRegionId, &m_nCurrentMapX, &m_nCurrentMapY, &m_nXOffset, &m_nYOffset);
  1295. CurRegion.AddRef(m_nCurrentMapX, m_nCurrentMapY, obj_missle);
  1296. if (nOldRegion != m_nRegionId)
  1297. {
  1298. SubWorld[m_nSubWorldId].m_WorldMessage.Send(GWM_MISSLE_CHANGE_REGION, nOldRegion, m_nRegionId, m_nMissleId);
  1299. }
  1300. return true;
  1301. }
  1302. int KMissle::CheckNearestCollision()
  1303. {
  1304. int nSearchRegion = 0;
  1305. int nRMx = 0;
  1306. int nRMy = 0;
  1307. BOOL bCollision = TRUE;
  1308. int nNpcIdx = 0;
  1309. int nDX = 0;
  1310. int nDY = 0;
  1311. int nNpcOffsetX = 0;
  1312. int nNpcOffsetY = 0;
  1313. int nAbsX = 0;
  1314. int nAbsY = 0;
  1315. int nCellWidth = CellWidth;
  1316. int nCellHeight = CellHeight;
  1317. _ASSERT(nCellWidth > 0 && nCellHeight > 0);
  1318. for (int i = -1; i <= 1; i ++)
  1319. for (int j = -1; j <= 1; j ++)
  1320. {
  1321. if (!KMissle::GetOffsetAxis(
  1322. m_nSubWorldId,
  1323. m_nRegionId, 
  1324. m_nCurrentMapX, 
  1325. m_nCurrentMapY, 
  1326. i , 
  1327. j , 
  1328. nSearchRegion, 
  1329. nRMx, 
  1330. nRMy
  1331. ))
  1332. continue;
  1333. _ASSERT(nSearchRegion >= 0);
  1334. nNpcIdx = SubWorld[m_nSubWorldId].m_Region[nSearchRegion].FindNpc(nRMx, nRMy, m_nLauncher, m_eRelation);
  1335. if (nNpcIdx > 0)
  1336. {
  1337. bCollision = TRUE;
  1338. nDX = m_nCurrentMapX - Npc[nNpcIdx].m_MapX;
  1339. nDY = m_nCurrentMapY - Npc[nNpcIdx].m_MapY;
  1340. nNpcOffsetX = Npc[nNpcIdx].m_OffX;
  1341. nNpcOffsetY = Npc[nNpcIdx].m_OffY;
  1342. nAbsX = abs(nDX);
  1343. nAbsY = abs(nDY);
  1344. if (nAbsX)
  1345. {
  1346. if (nDX < 0)
  1347. {
  1348. if (nCellWidth - m_nXOffset + nNpcOffsetX > nCellWidth)
  1349. {
  1350. bCollision = FALSE;
  1351. goto CheckCollision;
  1352. }
  1353. }
  1354. else if (nDX > 0)
  1355. {
  1356. if (nCellWidth - nNpcOffsetX + m_nXOffset > nCellWidth)
  1357. {
  1358. bCollision = FALSE;
  1359. goto CheckCollision;
  1360. }
  1361. }
  1362. }
  1363. if (nAbsY)
  1364. {
  1365. if (nDY <0)
  1366. {
  1367. if (nCellHeight - m_nYOffset + nNpcOffsetY > nCellHeight)
  1368. {
  1369. bCollision = FALSE;
  1370. goto CheckCollision;
  1371. }
  1372. }
  1373. else if (nDY >0)
  1374. {
  1375. if (nCellHeight - nNpcOffsetY + m_nYOffset > nCellHeight)
  1376. {
  1377. bCollision = FALSE;
  1378. goto CheckCollision;
  1379. }
  1380. }
  1381. }
  1382. CheckCollision:
  1383. if (bCollision)
  1384. return nNpcIdx;
  1385. }
  1386. }
  1387. return 0;
  1388. }
  1389. void KMissle::GetMpsPos(int *pPosX, int *pPosY)
  1390. {
  1391. SubWorld[m_nSubWorldId].Map2Mps(m_nRegionId, m_nCurrentMapX, m_nCurrentMapY, m_nXOffset, m_nYOffset, pPosX, pPosY);
  1392. };