Advertisement
Guest User

Untitled

a guest
Jan 12th, 2020
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.08 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "utils.h"
  3. #include "config.h"
  4. #include "desc.h"
  5. #include "char.h"
  6. #include "char_manager.h"
  7. #include "battle.h"
  8. #include "item.h"
  9. #include "item_manager.h"
  10. #include "mob_manager.h"
  11. #include "vector.h"
  12. #include "packet.h"
  13. #include "pvp.h"
  14. #include "profiler.h"
  15. #include "guild.h"
  16. #include "affect.h"
  17. #include "unique_item.h"
  18. #include "lua_incl.h"
  19. #include "arena.h"
  20. #include "castle.h"
  21. #include "sectree.h"
  22. #include "ani.h"
  23. #include "locale_service.h"
  24. #include "../../common/CommonDefines.h"
  25.  
  26. int battle_hit(LPCHARACTER ch, LPCHARACTER victim, int & iRetDam);
  27.  
  28. bool battle_distance_valid_by_xy(long x, long y, long tx, long ty)
  29. {
  30. long distance = DISTANCE_APPROX(x - tx, y - ty);
  31.  
  32. if (distance > 170)
  33. return false;
  34.  
  35. return true;
  36. }
  37.  
  38. bool battle_distance_valid(LPCHARACTER ch, LPCHARACTER victim)
  39. {
  40. return battle_distance_valid_by_xy(ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY());
  41. }
  42.  
  43. bool timed_event_cancel(LPCHARACTER ch)
  44. {
  45. if (ch->m_pkTimedEvent)
  46. {
  47. event_cancel(&ch->m_pkTimedEvent);
  48. return true;
  49. }
  50.  
  51. /* RECALL_DELAY
  52. Â÷ÈÄ ÀüÅõ·Î ÀÎÇØ ±ÍȯºÎ µô·¹ÀÌ°¡ Ãë¼Ò µÇ¾î¾ß ÇÒ °æ¿ì ÁÖ¼® ÇØÁ¦
  53. if (ch->m_pk_RecallEvent)
  54. {
  55. event_cancel(&ch->m_pkRecallEvent);
  56. return true;
  57. }
  58. END_OF_RECALL_DELAY */
  59.  
  60. return false;
  61. }
  62.  
  63. #ifdef NEW_ICEDAMAGE_SYSTEM
  64. bool battle_is_icedamage(LPCHARACTER pAttacker, LPCHARACTER pVictim)
  65. {
  66. if (pAttacker && pAttacker->IsPC())
  67. {
  68. DWORD race = pAttacker->GetRaceNum();
  69. const DWORD tmp_dwNDRFlag = pVictim->GetNoDamageRaceFlag();
  70. if (tmp_dwNDRFlag &&
  71. (race < MAIN_RACE_MAX_NUM) &&
  72. (IS_SET(tmp_dwNDRFlag, 1<<race))
  73. )
  74. {
  75. return false;
  76. }
  77. const std::set<DWORD> & tmp_setNDAFlag = pVictim->GetNoDamageAffectFlag();
  78. if (tmp_setNDAFlag.size())
  79. {
  80. for (std::set<DWORD>::iterator it = tmp_setNDAFlag.begin(); it != tmp_setNDAFlag.end(); ++it)
  81. {
  82. if (!pAttacker->IsAffectFlag(*it))
  83. {
  84. return false;
  85. }
  86. }
  87. }
  88. }
  89. return true;
  90. }
  91. #endif
  92.  
  93. bool battle_is_attackable(LPCHARACTER ch, LPCHARACTER victim)
  94. {
  95. // »ó´ë¹æÀÌ Á×¾úÀ¸¸é Áß´ÜÇÑ´Ù.
  96. if (victim->IsDead())
  97. return false;
  98.  
  99. if (victim->GetMyShop())
  100. return false;
  101.  
  102. // ¾ÈÀüÁö´ë¸é Áß´Ü
  103. {
  104. SECTREE *sectree = NULL;
  105.  
  106. sectree = ch->GetSectree();
  107. if (sectree && sectree->IsAttr(ch->GetX(), ch->GetY(), ATTR_BANPK))
  108. return false;
  109.  
  110. sectree = victim->GetSectree();
  111. if (sectree && sectree->IsAttr(victim->GetX(), victim->GetY(), ATTR_BANPK))
  112. return false;
  113. }
  114. #ifdef NEW_ICEDAMAGE_SYSTEM
  115. if (!battle_is_icedamage(ch, victim))
  116. return false;
  117. #endif
  118. // ³»°¡ Á×¾úÀ¸¸é Áß´ÜÇÑ´Ù.
  119. if (ch->IsStun() || ch->IsDead())
  120. return false;
  121.  
  122. if (ch->IsPC() && victim->IsPC())
  123. {
  124. CGuild* g1 = ch->GetGuild();
  125. CGuild* g2 = victim->GetGuild();
  126.  
  127. if (g1 && g2)
  128. {
  129. if (g1->UnderWar(g2->GetID()))
  130. return true;
  131. }
  132. }
  133.  
  134. if (IS_CASTLE_MAP(ch->GetMapIndex()) && false==castle_can_attack(ch, victim))
  135. return false;
  136.  
  137. if (CArenaManager::instance().CanAttack(ch, victim) == true)
  138. return true;
  139.  
  140. return CPVPManager::instance().CanAttack(ch, victim);
  141. }
  142.  
  143. int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
  144. {
  145. if (test_server&&ch->IsPC())
  146. sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
  147.  
  148. if (!victim || ch == victim)
  149. return BATTLE_NONE;
  150.  
  151. if (test_server&&ch->IsPC())
  152. sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
  153.  
  154. if (!battle_is_attackable(ch, victim))
  155. return BATTLE_NONE;
  156.  
  157. if (test_server&&ch->IsPC())
  158. sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
  159.  
  160. // °Å¸® üũ
  161. int distance = DISTANCE_APPROX(ch->GetX() - victim->GetX(), ch->GetY() - victim->GetY());
  162.  
  163. if (!victim->IsBuilding())
  164. {
  165. int max = 300;
  166.  
  167. if (false == ch->IsPC())
  168. {
  169. // ¸ó½ºÅÍÀÇ °æ¿ì ¸ó½ºÅÍ °ø°Ý °Å¸®¸¦ »ç¿ë
  170. max = (int) (ch->GetMobAttackRange() * 1.15f);
  171. }
  172. else
  173. {
  174. // PCÀÏ °æ¿ì »ó´ë°¡ melee ¸÷ÀÏ °æ¿ì ¸÷ÀÇ °ø°Ý °Å¸®°¡ ÃÖ´ë °ø°Ý °Å¸®
  175. if (false == victim->IsPC() && BATTLE_TYPE_MELEE == victim->GetMobBattleType())
  176. max = MAX(300, (int) (victim->GetMobAttackRange() * 1.15f));
  177. }
  178.  
  179. if (distance > max)
  180. {
  181. if (test_server)
  182. sys_log(0, "VICTIM_FAR: %s distance: %d max: %d", ch->GetName(), distance, max);
  183.  
  184. return BATTLE_NONE;
  185. }
  186. }
  187.  
  188. if (timed_event_cancel(ch))
  189. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀüÅõ°¡ ½ÃÀÛ µÇ¾î Ãë¼Ò µÇ¾ú½À´Ï´Ù."));
  190.  
  191. if (timed_event_cancel(victim))
  192. victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀüÅõ°¡ ½ÃÀÛ µÇ¾î Ãë¼Ò µÇ¾ú½À´Ï´Ù."));
  193.  
  194. ch->SetPosition(POS_FIGHTING);
  195. ch->SetVictim(victim);
  196.  
  197. const PIXEL_POSITION & vpos = victim->GetXYZ();
  198. ch->SetRotationToXY(vpos.x, vpos.y);
  199.  
  200. int dam;
  201. int ret = battle_hit(ch, victim, dam);
  202. return (ret);
  203. }
  204.  
  205. // ½ÇÁ¦ GET_BATTLE_VICTIMÀ» NULL·Î ¸¸µé°í À̺¥Æ®¸¦ ĵ½½ ½ÃŲ´Ù.
  206. void battle_end_ex(LPCHARACTER ch)
  207. {
  208. if (ch->IsPosition(POS_FIGHTING))
  209. ch->SetPosition(POS_STANDING);
  210. }
  211.  
  212. void battle_end(LPCHARACTER ch)
  213. {
  214. battle_end_ex(ch);
  215. }
  216.  
  217. // AG = Attack Grade
  218. // AL = Attack Limit
  219. int CalcBattleDamage(int iDam, int iAttackerLev, int iVictimLev)
  220. {
  221. if (iDam < 3)
  222. iDam = number(1, 5);
  223.  
  224. //return CALCULATE_DAMAGE_LVDELTA(iAttackerLev, iVictimLev, iDam);
  225. return iDam;
  226. }
  227.  
  228. int CalcMagicDamageWithValue(int iDam, LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
  229. {
  230. return CalcBattleDamage(iDam, pkAttacker->GetLevel(), pkVictim->GetLevel());
  231. }
  232.  
  233. int CalcMagicDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
  234. {
  235. int iDam = 0;
  236.  
  237. if (pkAttacker->IsNPC())
  238. {
  239. iDam = CalcMeleeDamage(pkAttacker, pkVictim, false, false);
  240. }
  241.  
  242. iDam += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
  243.  
  244. return CalcMagicDamageWithValue(iDam, pkAttacker, pkVictim);
  245. }
  246.  
  247. float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreTargetRating)
  248. {
  249. int iARSrc;
  250. int iERSrc;
  251.  
  252. {
  253. int attacker_dx = pkAttacker->GetPolymorphPoint(POINT_DX);
  254. int attacker_lv = pkAttacker->GetLevel();
  255.  
  256. int victim_dx = pkVictim->GetPolymorphPoint(POINT_DX);
  257. int victim_lv = pkAttacker->GetLevel();
  258.  
  259. iARSrc = MIN(90, (attacker_dx * 4 + attacker_lv * 2) / 6);
  260. iERSrc = MIN(90, (victim_dx * 4 + victim_lv * 2) / 6);
  261. }
  262.  
  263. float fAR = ((float) iARSrc + 210.0f) / 300.0f; // fAR = 0.7 ~ 1.0
  264.  
  265. if (bIgnoreTargetRating)
  266. return fAR;
  267.  
  268. // ((Edx * 2 + 20) / (Edx + 110)) * 0.3
  269. float fER = ((float) (iERSrc * 2 + 5) / (iERSrc + 95)) * 3.0f / 10.0f;
  270.  
  271. return fAR - fER;
  272. }
  273.  
  274. int CalcAttBonus(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int iAtk)
  275. {
  276. // PvP¿¡´Â Àû¿ëÇÏÁö¾ÊÀ½
  277. if (!pkVictim->IsPC())
  278. iAtk += pkAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_ATTACK_BONUS);
  279.  
  280. // PvP¿¡´Â Àû¿ëÇÏÁö¾ÊÀ½
  281. if (!pkAttacker->IsPC())
  282. {
  283. int iReduceDamagePct = pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_TRANSFER_DAMAGE);
  284. iAtk = iAtk * (100 + iReduceDamagePct) / 100;
  285. }
  286.  
  287. if (pkAttacker->IsNPC() && pkVictim->IsPC())
  288. {
  289. iAtk = (iAtk * CHARACTER_MANAGER::instance().GetMobDamageRate(pkAttacker)) / 100;
  290. }
  291.  
  292. if (pkVictim->IsNPC())
  293. {
  294. if (pkVictim->IsRaceFlag(RACE_FLAG_ANIMAL))
  295. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ANIMAL)) / 100;
  296. else if (pkVictim->IsRaceFlag(RACE_FLAG_UNDEAD))
  297. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_UNDEAD)) / 100;
  298. else if (pkVictim->IsRaceFlag(RACE_FLAG_DEVIL))
  299. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DEVIL)) / 100;
  300. else if (pkVictim->IsRaceFlag(RACE_FLAG_HUMAN))
  301. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100;
  302. else if (pkVictim->IsRaceFlag(RACE_FLAG_ORC))
  303. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ORC)) / 100;
  304. else if (pkVictim->IsRaceFlag(RACE_FLAG_MILGYO))
  305. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MILGYO)) / 100;
  306. else if (pkVictim->IsRaceFlag(RACE_FLAG_INSECT))
  307. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_INSECT)) / 100;
  308. else if (pkVictim->IsRaceFlag(RACE_FLAG_FIRE))
  309. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_FIRE)) / 100;
  310. else if (pkVictim->IsRaceFlag(RACE_FLAG_ICE))
  311. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ICE)) / 100;
  312. else if (pkVictim->IsRaceFlag(RACE_FLAG_DESERT))
  313. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DESERT)) / 100;
  314. else if (pkVictim->IsRaceFlag(RACE_FLAG_TREE))
  315. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_TREE)) / 100;
  316.  
  317. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MONSTER)) / 100;
  318. }
  319. else if (pkVictim->IsPC())
  320. {
  321. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100;
  322.  
  323. switch (pkVictim->GetJob())
  324. {
  325. case JOB_WARRIOR:
  326. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_WARRIOR)) / 100;
  327. break;
  328.  
  329. case JOB_ASSASSIN:
  330. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ASSASSIN)) / 100;
  331. break;
  332.  
  333. case JOB_SURA:
  334. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_SURA)) / 100;
  335. break;
  336.  
  337. case JOB_SHAMAN:
  338. iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_SHAMAN)) / 100;
  339. break;
  340. }
  341. }
  342.  
  343. if (pkAttacker->IsPC() == true)
  344. {
  345. switch (pkAttacker->GetJob())
  346. {
  347. case JOB_WARRIOR:
  348. iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_WARRIOR)) / 100;
  349. break;
  350.  
  351. case JOB_ASSASSIN:
  352. iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_ASSASSIN)) / 100;
  353. break;
  354.  
  355. case JOB_SURA:
  356. iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_SURA)) / 100;
  357. break;
  358.  
  359. case JOB_SHAMAN:
  360. iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_SHAMAN)) / 100;
  361. break;
  362. }
  363. }
  364.  
  365. //[ mob -> PC ] ¿ø¼Ò ¼Ó¼º ¹æ¾î Àû¿ë
  366. //2013/01/17
  367. //¸ó½ºÅÍ ¼Ó¼º°ø°Ý µ¥¹ÌÁöÀÇ 30%¿¡ ÇØ´çÇÏ´Â ¼öÄ¡¿¡¸¸ ÀúÇ×ÀÌ Àû¿ëµÊ.
  368. if (pkAttacker->IsNPC() && pkVictim->IsPC())
  369. {
  370. if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ELEC))
  371. iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_ELEC)) / 10000;
  372. else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_FIRE))
  373. iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_FIRE)) / 10000;
  374. else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ICE))
  375. iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_ICE)) / 10000;
  376. else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_WIND))
  377. iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_WIND)) / 10000;
  378. else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_EARTH))
  379. iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_EARTH)) / 10000;
  380. else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_DARK))
  381. iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_DARK)) / 10000;
  382. }
  383.  
  384.  
  385. return iAtk;
  386. }
  387.  
  388. void Item_GetDamage(LPITEM pkItem, int* pdamMin, int* pdamMax)
  389. {
  390. *pdamMin = 0;
  391. *pdamMax = 1;
  392.  
  393. if (!pkItem)
  394. return;
  395.  
  396. switch (pkItem->GetType())
  397. {
  398. case ITEM_ROD:
  399. case ITEM_PICK:
  400. return;
  401. }
  402.  
  403. if (pkItem->GetType() != ITEM_WEAPON)
  404. sys_err("Item_GetDamage - !ITEM_WEAPON vnum=%d, type=%d", pkItem->GetOriginalVnum(), pkItem->GetType());
  405.  
  406. *pdamMin = pkItem->GetValue(3);
  407. *pdamMax = pkItem->GetValue(4);
  408. }
  409.  
  410. int CalcMeleeDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreDefense, bool bIgnoreTargetRating)
  411. {
  412. LPITEM pWeapon = pkAttacker->GetWear(WEAR_WEAPON);
  413. bool bPolymorphed = pkAttacker->IsPolymorphed();
  414.  
  415. if (pWeapon && !(bPolymorphed && !pkAttacker->IsPolyMaintainStat()))
  416. {
  417. if (pWeapon->GetType() != ITEM_WEAPON)
  418. return 0;
  419.  
  420. switch (pWeapon->GetSubType())
  421. {
  422. case WEAPON_SWORD:
  423. case WEAPON_DAGGER:
  424. case WEAPON_TWO_HANDED:
  425. case WEAPON_BELL:
  426. case WEAPON_FAN:
  427. case WEAPON_MOUNT_SPEAR:
  428. break;
  429.  
  430. case WEAPON_BOW:
  431. sys_err("CalcMeleeDamage should not handle bows (name: %s)", pkAttacker->GetName());
  432. return 0;
  433.  
  434. default:
  435. return 0;
  436. }
  437. }
  438.  
  439. int iDam = 0;
  440. float fAR = CalcAttackRating(pkAttacker, pkVictim, bIgnoreTargetRating);
  441. int iDamMin = 0, iDamMax = 0;
  442.  
  443. // TESTSERVER_SHOW_ATTACKINFO
  444. int DEBUG_iDamCur = 0;
  445. int DEBUG_iDamBonus = 0;
  446. // END_OF_TESTSERVER_SHOW_ATTACKINFO
  447.  
  448. if (bPolymorphed && !pkAttacker->IsPolyMaintainStat())
  449. {
  450. // MONKEY_ROD_ATTACK_BUG_FIX
  451. Item_GetDamage(pWeapon, &iDamMin, &iDamMax);
  452. // END_OF_MONKEY_ROD_ATTACK_BUG_FIX
  453.  
  454. DWORD dwMobVnum = pkAttacker->GetPolymorphVnum();
  455. const CMob * pMob = CMobManager::instance().Get(dwMobVnum);
  456.  
  457. if (pMob)
  458. {
  459. int iPower = pkAttacker->GetPolymorphPower();
  460. iDamMin += pMob->m_table.dwDamageRange[0] * iPower / 100;
  461. iDamMax += pMob->m_table.dwDamageRange[1] * iPower / 100;
  462. }
  463. }
  464. else if (pWeapon)
  465. {
  466. // MONKEY_ROD_ATTACK_BUG_FIX
  467. Item_GetDamage(pWeapon, &iDamMin, &iDamMax);
  468. // END_OF_MONKEY_ROD_ATTACK_BUG_FIX
  469. }
  470. else if (pkAttacker->IsNPC())
  471. {
  472. iDamMin = pkAttacker->GetMobDamageMin();
  473. iDamMax = pkAttacker->GetMobDamageMax();
  474. }
  475.  
  476. iDam = number(iDamMin, iDamMax) * 2;
  477.  
  478. // TESTSERVER_SHOW_ATTACKINFO
  479. DEBUG_iDamCur = iDam;
  480. // END_OF_TESTSERVER_SHOW_ATTACKINFO
  481. //
  482. int iAtk = 0;
  483.  
  484. // level must be ignored when multiply by fAR, so subtract it before calculation.
  485. iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2);
  486. iAtk = (int) (iAtk * fAR);
  487. iAtk += pkAttacker->GetLevel() * 2; // and add again
  488.  
  489. if (pWeapon)
  490. {
  491. iAtk += pWeapon->GetValue(5) * 2;
  492.  
  493. // 2004.11.12.myevan.TESTSERVER_SHOW_ATTACKINFO
  494. DEBUG_iDamBonus = pWeapon->GetValue(5) * 2;
  495. ///////////////////////////////////////////////
  496. }
  497.  
  498. iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS); // party attacker role bonus
  499. iAtk = (int) (iAtk * (100 + (pkAttacker->GetPoint(POINT_ATT_BONUS) + pkAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100);
  500.  
  501. iAtk = CalcAttBonus(pkAttacker, pkVictim, iAtk);
  502.  
  503. int iDef = 0;
  504.  
  505. if (!bIgnoreDefense)
  506. {
  507. iDef = (pkVictim->GetPoint(POINT_DEF_GRADE) * (100 + pkVictim->GetPoint(POINT_DEF_BONUS)) / 100);
  508.  
  509. if (!pkAttacker->IsPC())
  510. iDef += pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_DEFENSE_BONUS);
  511. }
  512.  
  513. if (pkAttacker->IsNPC())
  514. iAtk = (int) (iAtk * pkAttacker->GetMobDamageMultiply());
  515.  
  516. iDam = MAX(0, iAtk - iDef);
  517.  
  518. if (test_server)
  519. {
  520. int DEBUG_iLV = pkAttacker->GetLevel()*2;
  521. int DEBUG_iST = int((pkAttacker->GetPoint(POINT_ATT_GRADE) - DEBUG_iLV) * fAR);
  522. int DEBUG_iPT = pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
  523. int DEBUG_iWP = 0;
  524. int DEBUG_iPureAtk = 0;
  525. int DEBUG_iPureDam = 0;
  526. char szRB[32] = "";
  527. char szGradeAtkBonus[32] = "";
  528.  
  529. DEBUG_iWP = int(DEBUG_iDamCur * fAR);
  530. DEBUG_iPureAtk = DEBUG_iLV + DEBUG_iST + DEBUG_iWP+DEBUG_iDamBonus;
  531. DEBUG_iPureDam = iAtk - iDef;
  532.  
  533. if (pkAttacker->IsNPC())
  534. {
  535. snprintf(szGradeAtkBonus, sizeof(szGradeAtkBonus), "=%d*%.1f", DEBUG_iPureAtk, pkAttacker->GetMobDamageMultiply());
  536. DEBUG_iPureAtk = int(DEBUG_iPureAtk * pkAttacker->GetMobDamageMultiply());
  537. }
  538.  
  539. if (DEBUG_iDamBonus != 0)
  540. snprintf(szRB, sizeof(szRB), "+RB(%d)", DEBUG_iDamBonus);
  541.  
  542. char szPT[32] = "";
  543.  
  544. if (DEBUG_iPT != 0)
  545. snprintf(szPT, sizeof(szPT), ", PT=%d", DEBUG_iPT);
  546.  
  547. char szUnknownAtk[32] = "";
  548.  
  549. if (iAtk != DEBUG_iPureAtk)
  550. snprintf(szUnknownAtk, sizeof(szUnknownAtk), "+?(%d)", iAtk-DEBUG_iPureAtk);
  551.  
  552. char szUnknownDam[32] = "";
  553.  
  554. if (iDam != DEBUG_iPureDam)
  555. snprintf(szUnknownDam, sizeof(szUnknownDam), "+?(%d)", iDam-DEBUG_iPureDam);
  556.  
  557. char szMeleeAttack[128];
  558.  
  559. snprintf(szMeleeAttack, sizeof(szMeleeAttack),
  560. "%s(%d)-%s(%d)=%d%s, ATK=LV(%d)+ST(%d)+WP(%d)%s%s%s, AR=%.3g%s",
  561. pkAttacker->GetName(),
  562. iAtk,
  563. pkVictim->GetName(),
  564. iDef,
  565. iDam,
  566. szUnknownDam,
  567. DEBUG_iLV,
  568. DEBUG_iST,
  569. DEBUG_iWP,
  570. szRB,
  571. szUnknownAtk,
  572. szGradeAtkBonus,
  573. fAR,
  574. szPT);
  575.  
  576. pkAttacker->ChatPacket(CHAT_TYPE_TALKING, "%s", szMeleeAttack);
  577. pkVictim->ChatPacket(CHAT_TYPE_TALKING, "%s", szMeleeAttack);
  578. }
  579.  
  580. return CalcBattleDamage(iDam, pkAttacker->GetLevel(), pkVictim->GetLevel());
  581. }
  582.  
  583. int CalcArrowDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, LPITEM pkBow, LPITEM pkArrow, bool bIgnoreDefense)
  584. {
  585. if (!pkBow || pkBow->GetType() != ITEM_WEAPON || pkBow->GetSubType() != WEAPON_BOW)
  586. return 0;
  587.  
  588. if (!pkArrow)
  589. return 0;
  590.  
  591. // Ÿ°ÝÄ¡ °è»êºÎ
  592. int iDist = (int) (DISTANCE_SQRT(pkAttacker->GetX() - pkVictim->GetX(), pkAttacker->GetY() - pkVictim->GetY()));
  593. //int iGap = (iDist / 100) - 5 - pkBow->GetValue(5) - pkAttacker->GetPoint(POINT_BOW_DISTANCE);
  594. int iGap = (iDist / 100) - 5 - pkAttacker->GetPoint(POINT_BOW_DISTANCE);
  595. int iPercent = 100 - (iGap * 5);
  596.  
  597. if (iPercent <= 0)
  598. return 0;
  599. else if (iPercent > 100)
  600. iPercent = 100;
  601.  
  602. int iDam = 0;
  603.  
  604. float fAR = CalcAttackRating(pkAttacker, pkVictim, false);
  605. iDam = number(pkBow->GetValue(3), pkBow->GetValue(4)) * 2 + pkArrow->GetValue(3);
  606. int iAtk;
  607.  
  608. // level must be ignored when multiply by fAR, so subtract it before calculation.
  609. iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2);
  610. iAtk = (int) (iAtk * fAR);
  611. iAtk += pkAttacker->GetLevel() * 2; // and add again
  612.  
  613. // Refine Grade
  614. iAtk += pkBow->GetValue(5) * 2;
  615.  
  616. iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
  617. iAtk = (int) (iAtk * (100 + (pkAttacker->GetPoint(POINT_ATT_BONUS) + pkAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100);
  618.  
  619. iAtk = CalcAttBonus(pkAttacker, pkVictim, iAtk);
  620.  
  621. int iDef = 0;
  622.  
  623. if (!bIgnoreDefense)
  624. iDef = (pkVictim->GetPoint(POINT_DEF_GRADE) * (100 + pkAttacker->GetPoint(POINT_DEF_BONUS)) / 100);
  625.  
  626. if (pkAttacker->IsNPC())
  627. iAtk = (int) (iAtk * pkAttacker->GetMobDamageMultiply());
  628.  
  629. iDam = MAX(0, iAtk - iDef);
  630.  
  631. int iPureDam = iDam;
  632.  
  633. iPureDam = (iPureDam * iPercent) / 100;
  634.  
  635. if (test_server)
  636. {
  637. pkAttacker->ChatPacket(CHAT_TYPE_INFO, "ARROW %s -> %s, DAM %d DIST %d GAP %d %% %d",
  638. pkAttacker->GetName(),
  639. pkVictim->GetName(),
  640. iPureDam,
  641. iDist, iGap, iPercent);
  642. }
  643.  
  644. return iPureDam;
  645. //return iDam;
  646. }
  647.  
  648.  
  649. void NormalAttackAffect(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
  650. {
  651. // µ¶ °ø°ÝÀº ƯÀÌÇϹǷΠƯ¼ö ó¸®
  652. if (pkAttacker->GetPoint(POINT_POISON_PCT) && !pkVictim->IsAffectFlag(AFF_POISON))
  653. {
  654. if (number(1, 100) <= pkAttacker->GetPoint(POINT_POISON_PCT))
  655. pkVictim->AttackedByPoison(pkAttacker);
  656. }
  657.  
  658. int iStunDuration = 2;
  659.  
  660. if (pkAttacker->IsPC() && !pkVictim->IsPC())
  661. iStunDuration = 4;
  662.  
  663. AttackAffect(pkAttacker, pkVictim, POINT_STUN_PCT, IMMUNE_STUN, AFFECT_STUN, POINT_NONE, 0, AFF_STUN, iStunDuration, "STUN");
  664. AttackAffect(pkAttacker, pkVictim, POINT_SLOW_PCT, IMMUNE_SLOW, AFFECT_SLOW, POINT_MOV_SPEED, -30, AFF_SLOW, 20, "SLOW");
  665. }
  666.  
  667. int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int & iRetDam)
  668. {
  669. //PROF_UNIT puHit("Hit");
  670. if (test_server)
  671. sys_log(0, "battle_hit : [%s] attack to [%s] : dam :%d type :%d", pkAttacker->GetName(), pkVictim->GetName(), iRetDam);
  672.  
  673. int iDam = CalcMeleeDamage(pkAttacker, pkVictim);
  674.  
  675. if (iDam <= 0)
  676. return (BATTLE_DAMAGE);
  677.  
  678. NormalAttackAffect(pkAttacker, pkVictim);
  679.  
  680. // µ¥¹ÌÁö °è»ê
  681. //iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST)) / 100;
  682. LPITEM pkWeapon = pkAttacker->GetWear(WEAR_WEAPON);
  683.  
  684. if (pkWeapon)
  685. switch (pkWeapon->GetSubType())
  686. {
  687. case WEAPON_SWORD:
  688. iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_SWORD)) / 100;
  689. break;
  690.  
  691. case WEAPON_TWO_HANDED:
  692. iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_TWOHAND)) / 100;
  693. break;
  694.  
  695. case WEAPON_DAGGER:
  696. iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_DAGGER)) / 100;
  697. break;
  698.  
  699. case WEAPON_BELL:
  700. iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_BELL)) / 100;
  701. break;
  702.  
  703. case WEAPON_FAN:
  704. iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_FAN)) / 100;
  705. break;
  706.  
  707. case WEAPON_BOW:
  708. iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_BOW)) / 100;
  709. break;
  710. }
  711.  
  712.  
  713. //ÃÖÁ¾ÀûÀÎ µ¥¹ÌÁö º¸Á¤. (2011³â 2¿ù ÇöÀç ´ë¿Õ°Å¹Ì¿¡°Ô¸¸ Àû¿ë.)
  714. float attMul = pkAttacker->GetAttMul();
  715. float tempIDam = iDam;
  716. iDam = attMul * tempIDam + 0.5f;
  717.  
  718. iRetDam = iDam;
  719.  
  720. //PROF_UNIT puDam("Dam");
  721. if (pkVictim->Damage(pkAttacker, iDam, DAMAGE_TYPE_NORMAL))
  722. return (BATTLE_DEAD);
  723.  
  724. return (BATTLE_DAMAGE);
  725. }
  726.  
  727. DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
  728. {
  729. if (NULL == ch)
  730. return 1000;
  731.  
  732. LPITEM item = ch->GetWear(WEAR_WEAPON);
  733. DWORD default_bonus = SPEEDHACK_LIMIT_BONUS; // À¯µÎ¸® °ø¼Ó(±âº» 80)
  734. DWORD riding_bonus = 0;
  735.  
  736. if (ch->IsRiding())
  737. {
  738. // ¹º°¡¸¦ ÅÀÀ¸¸é Ãß°¡°ø¼Ó 50
  739. riding_bonus = 50;
  740. }
  741.  
  742. DWORD ani_speed = ani_attack_speed(ch);
  743. DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus);
  744.  
  745. // ´Ü°ËÀÇ °æ¿ì °ø¼Ó 2¹è
  746. if (item && item->GetSubType() == WEAPON_DAGGER)
  747. real_speed /= 2;
  748.  
  749. return real_speed;
  750.  
  751. }
  752.  
  753. void SET_ATTACK_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
  754. {
  755. if (NULL == ch || NULL == victim)
  756. return;
  757.  
  758. if (!ch->IsPC())
  759. return;
  760.  
  761. ch->m_kAttackLog.dwVID = victim->GetVID();
  762. ch->m_kAttackLog.dwTime = current_time;
  763. }
  764.  
  765. void SET_ATTACKED_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
  766. {
  767. if (NULL == ch || NULL == victim)
  768. return;
  769.  
  770. if (!ch->IsPC())
  771. return;
  772.  
  773. victim->m_AttackedLog.dwPID = ch->GetPlayerID();
  774. victim->m_AttackedLog.dwAttackedTime= current_time;
  775. }
  776.  
  777. bool IS_SPEED_HACK(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
  778. {
  779. if(!gHackCheckEnable) return false;
  780.  
  781. if (ch->m_kAttackLog.dwVID == victim->GetVID())
  782. {
  783. if (current_time - ch->m_kAttackLog.dwTime < GET_ATTACK_SPEED(ch))
  784. {
  785. INCREASE_SPEED_HACK_COUNT(ch);
  786.  
  787. if (test_server)
  788. {
  789. sys_log(0, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d",
  790. ch->GetName(),
  791. current_time - ch->m_kAttackLog.dwTime,
  792. GET_ATTACK_SPEED(ch),
  793. ch->m_speed_hack_count);
  794.  
  795. ch->ChatPacket(CHAT_TYPE_INFO, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d",
  796. ch->GetName(),
  797. current_time - ch->m_kAttackLog.dwTime,
  798. GET_ATTACK_SPEED(ch),
  799. ch->m_speed_hack_count);
  800. }
  801.  
  802. SET_ATTACK_TIME(ch, victim, current_time);
  803. SET_ATTACKED_TIME(ch, victim, current_time);
  804. return true;
  805. }
  806. }
  807.  
  808. SET_ATTACK_TIME(ch, victim, current_time);
  809.  
  810. if (victim->m_AttackedLog.dwPID == ch->GetPlayerID())
  811. {
  812. if (current_time - victim->m_AttackedLog.dwAttackedTime < GET_ATTACK_SPEED(ch))
  813. {
  814. INCREASE_SPEED_HACK_COUNT(ch);
  815.  
  816. if (test_server)
  817. {
  818. sys_log(0, "%s Attack Speed HACK! time (delta, limit)=(%u, %u), hack_count = %d",
  819. ch->GetName(),
  820. current_time - victim->m_AttackedLog.dwAttackedTime,
  821. GET_ATTACK_SPEED(ch),
  822. ch->m_speed_hack_count);
  823.  
  824. ch->ChatPacket(CHAT_TYPE_INFO, "Attack Speed Hack(%s), (delta, limit)=(%u, %u)",
  825. ch->GetName(),
  826. current_time - victim->m_AttackedLog.dwAttackedTime,
  827. GET_ATTACK_SPEED(ch));
  828. }
  829.  
  830. SET_ATTACKED_TIME(ch, victim, current_time);
  831. return true;
  832. }
  833. }
  834.  
  835. SET_ATTACKED_TIME(ch, victim, current_time);
  836. return false;
  837. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement