Guest User

Untitled

a guest
May 24th, 2020
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 101.40 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include <sstream>
  3.  
  4. #include "utils.h"
  5. #include "config.h"
  6. #include "vector.h"
  7. #include "char.h"
  8. #include "char_manager.h"
  9. #include "battle.h"
  10. #include "desc.h"
  11. #include "desc_manager.h"
  12. #include "packet.h"
  13. #include "affect.h"
  14. #include "item.h"
  15. #include "sectree_manager.h"
  16. #include "mob_manager.h"
  17. #include "start_position.h"
  18. #include "party.h"
  19. #include "buffer_manager.h"
  20. #include "guild.h"
  21. #include "log.h"
  22. #include "unique_item.h"
  23. #include "questmanager.h"
  24. #include "../../common/CommonDefines.h"
  25.  
  26. #define ENABLE_FORCE2MASTERSKILL
  27. // #define ENABLE_MOUNTSKILL_CHECK
  28. // #define ENABLE_NULLIFYAFFECT_LIMIT
  29.  
  30. static const DWORD s_adwSubSkillVnums[] =
  31. {
  32. SKILL_LEADERSHIP,
  33. SKILL_COMBO,
  34. SKILL_MINING,
  35. SKILL_LANGUAGE1,
  36. SKILL_LANGUAGE2,
  37. SKILL_LANGUAGE3,
  38. SKILL_POLYMORPH,
  39. SKILL_HORSE,
  40. SKILL_HORSE_SUMMON,
  41. SKILL_HORSE_WILDATTACK,
  42. SKILL_HORSE_CHARGE,
  43. SKILL_HORSE_ESCAPE,
  44. SKILL_HORSE_WILDATTACK_RANGE,
  45. SKILL_ADD_HP,
  46. SKILL_RESIST_PENETRATE
  47. };
  48.  
  49. time_t CHARACTER::GetSkillNextReadTime(DWORD dwVnum) const
  50. {
  51. if (dwVnum >= SKILL_MAX_NUM)
  52. {
  53. sys_err("vnum overflow (vnum: %u)", dwVnum);
  54. return 0;
  55. }
  56.  
  57. return m_pSkillLevels ? m_pSkillLevels[dwVnum].tNextRead : 0;
  58. }
  59.  
  60. void CHARACTER::SetSkillNextReadTime(DWORD dwVnum, time_t time)
  61. {
  62. if (m_pSkillLevels && dwVnum < SKILL_MAX_NUM)
  63. m_pSkillLevels[dwVnum].tNextRead = time;
  64. }
  65.  
  66. bool TSkillUseInfo::HitOnce(DWORD dwVnum)
  67. {
  68. // ¾²Áöµµ¾Ê¾ÒÀ¸¸é ¶§¸®Áöµµ ¸øÇÑ´Ù.
  69. if (!bUsed)
  70. return false;
  71.  
  72. sys_log(1, "__HitOnce NextUse %u current %u count %d scount %d", dwNextSkillUsableTime, get_dword_time(), iHitCount, iSplashCount);
  73.  
  74. if (dwNextSkillUsableTime && dwNextSkillUsableTime<get_dword_time() && dwVnum != SKILL_MUYEONG && dwVnum != SKILL_HORSE_WILDATTACK)
  75. {
  76. sys_log(1, "__HitOnce can't hit");
  77.  
  78. return false;
  79. }
  80.  
  81. if (iHitCount == -1)
  82. {
  83. sys_log(1, "__HitOnce OK %d %d %d", dwNextSkillUsableTime, get_dword_time(), iHitCount);
  84. return true;
  85. }
  86.  
  87. if (iHitCount)
  88. {
  89. sys_log(1, "__HitOnce OK %d %d %d", dwNextSkillUsableTime, get_dword_time(), iHitCount);
  90. iHitCount--;
  91. return true;
  92. }
  93. return false;
  94. }
  95.  
  96.  
  97.  
  98. bool TSkillUseInfo::UseSkill(bool isGrandMaster, DWORD vid, DWORD dwCooltime, int splashcount, int hitcount, int range)
  99. {
  100. this->isGrandMaster = isGrandMaster;
  101. DWORD dwCur = get_dword_time();
  102.  
  103. // ¾ÆÁ÷ ÄðŸÀÓÀÌ ³¡³ªÁö ¾Ê¾Ò´Ù.
  104. if (bUsed && dwNextSkillUsableTime > dwCur)
  105. {
  106. sys_log(0, "cooltime is not over delta %u", dwNextSkillUsableTime - dwCur);
  107. iHitCount = 0;
  108. return false;
  109. }
  110.  
  111. bUsed = true;
  112.  
  113. if (dwCooltime)
  114. dwNextSkillUsableTime = dwCur + dwCooltime;
  115. else
  116. dwNextSkillUsableTime = 0;
  117.  
  118. iRange = range;
  119. iMaxHitCount = iHitCount = hitcount;
  120.  
  121. if (test_server)
  122. sys_log(0, "UseSkill NextUse %u current %u cooltime %d hitcount %d/%d", dwNextSkillUsableTime, dwCur, dwCooltime, iHitCount, iMaxHitCount);
  123.  
  124. dwVID = vid;
  125. iSplashCount = splashcount;
  126. return true;
  127. }
  128.  
  129. int CHARACTER::GetChainLightningMaxCount() const
  130. {
  131. return aiChainLightningCountBySkillLevel[MIN(SKILL_MAX_LEVEL, GetSkillLevel(SKILL_CHAIN))];
  132. }
  133.  
  134. void CHARACTER::SetAffectedEunhyung()
  135. {
  136. m_dwAffectedEunhyungLevel = GetSkillPower(SKILL_EUNHYUNG);
  137. }
  138.  
  139. void CHARACTER::SetSkillGroup(BYTE bSkillGroup)
  140. {
  141. if (bSkillGroup > 2)
  142. return;
  143.  
  144. if (GetLevel() < 5)
  145. return;
  146.  
  147. m_points.skill_group = bSkillGroup;
  148.  
  149. TPacketGCChangeSkillGroup p;
  150. p.header = HEADER_GC_SKILL_GROUP;
  151. p.skill_group = m_points.skill_group;
  152.  
  153. GetDesc()->Packet(&p, sizeof(TPacketGCChangeSkillGroup));
  154. }
  155.  
  156. int CHARACTER::ComputeCooltime(int time)
  157. {
  158. return CalculateDuration(GetPoint(POINT_CASTING_SPEED), time);
  159. }
  160.  
  161. void CHARACTER::SkillLevelPacket()
  162. {
  163. if (!GetDesc())
  164. return;
  165.  
  166. TPacketGCSkillLevel pack;
  167.  
  168. pack.bHeader = HEADER_GC_SKILL_LEVEL;
  169. thecore_memcpy(&pack.skills, m_pSkillLevels, sizeof(TPlayerSkill) * SKILL_MAX_NUM);
  170. GetDesc()->Packet(&pack, sizeof(TPacketGCSkillLevel));
  171. }
  172.  
  173. void CHARACTER::SetSkillLevel(DWORD dwVnum, BYTE bLev)
  174. {
  175. if (NULL == m_pSkillLevels)
  176. return;
  177.  
  178. if (dwVnum >= SKILL_MAX_NUM)
  179. {
  180. sys_err("vnum overflow (vnum %u)", dwVnum);
  181. return;
  182. }
  183.  
  184. m_pSkillLevels[dwVnum].bLevel = MIN(40, bLev);
  185.  
  186. if (bLev >= 40)
  187. m_pSkillLevels[dwVnum].bMasterType = SKILL_PERFECT_MASTER;
  188. else if (bLev >= 30)
  189. m_pSkillLevels[dwVnum].bMasterType = SKILL_GRAND_MASTER;
  190. else if (bLev >= 20)
  191. m_pSkillLevels[dwVnum].bMasterType = SKILL_MASTER;
  192. else
  193. m_pSkillLevels[dwVnum].bMasterType = SKILL_NORMAL;
  194. }
  195.  
  196. bool CHARACTER::IsLearnableSkill(DWORD dwSkillVnum) const
  197. {
  198. const CSkillProto * pkSkill = CSkillManager::instance().Get(dwSkillVnum);
  199.  
  200. if (!pkSkill)
  201. return false;
  202.  
  203. if (GetSkillLevel(dwSkillVnum) >= SKILL_MAX_LEVEL)
  204. return false;
  205.  
  206. if (pkSkill->dwType == 0)
  207. {
  208. if (GetSkillLevel(dwSkillVnum) >= pkSkill->bMaxLevel)
  209. return false;
  210.  
  211. return true;
  212. }
  213.  
  214. if (pkSkill->dwType == 5)
  215. {
  216. if (dwSkillVnum == SKILL_HORSE_WILDATTACK_RANGE && GetJob() != JOB_ASSASSIN)
  217. return false;
  218.  
  219. return true;
  220. }
  221.  
  222. if (GetSkillGroup() == 0)
  223. return false;
  224.  
  225. if (pkSkill->dwType - 1 == GetJob())
  226. return true;
  227. #ifdef ENABLE_WOLFMAN_CHARACTER
  228. // ¼öÀÎÁ· ½ºÅ³
  229. if (7 == pkSkill->dwType && JOB_WOLFMAN == GetJob())
  230. return true;
  231. #endif
  232. if (6 == pkSkill->dwType)
  233. {
  234. if (SKILL_7_A_ANTI_TANHWAN <= dwSkillVnum && dwSkillVnum <= SKILL_7_D_ANTI_YONGBI)
  235. {
  236. for (int i=0 ; i < 4 ; i++)
  237. {
  238. if (unsigned(SKILL_7_A_ANTI_TANHWAN + i) != dwSkillVnum)
  239. {
  240. if (0 != GetSkillLevel(SKILL_7_A_ANTI_TANHWAN + i))
  241. {
  242. return false;
  243. }
  244. }
  245. }
  246.  
  247. return true;
  248. }
  249.  
  250. if (SKILL_8_A_ANTI_GIGONGCHAM <= dwSkillVnum && dwSkillVnum <= SKILL_8_D_ANTI_BYEURAK)
  251. {
  252. for (int i=0 ; i < 4 ; i++)
  253. {
  254. if (unsigned(SKILL_8_A_ANTI_GIGONGCHAM + i) != dwSkillVnum)
  255. {
  256. if (0 != GetSkillLevel(SKILL_8_A_ANTI_GIGONGCHAM + i))
  257. return false;
  258. }
  259. }
  260.  
  261. return true;
  262. }
  263. }
  264.  
  265. return false;
  266. }
  267.  
  268. // ADD_GRANDMASTER_SKILL
  269. bool CHARACTER::LearnGrandMasterSkill(DWORD dwSkillVnum)
  270. {
  271. CSkillProto * pkSk = CSkillManager::instance().Get(dwSkillVnum);
  272.  
  273. if (!pkSk)
  274. return false;
  275.  
  276. if (!IsLearnableSkill(dwSkillVnum))
  277. {
  278. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ö·ÃÇÒ ¼ö ¾ø´Â ½ºÅ³ÀÔ´Ï´Ù."));
  279. return false;
  280. }
  281.  
  282. sys_log(0, "learn grand master skill[%d] cur %d, next %d", dwSkillVnum, get_global_time(), GetSkillNextReadTime(dwSkillVnum));
  283.  
  284. /*
  285. if (get_global_time() < GetSkillNextReadTime(dwSkillVnum))
  286. {
  287. if (!(test_server && quest::CQuestManager::instance().GetEventFlag("no_read_delay")))
  288. {
  289. if (FindAffect(AFFECT_SKILL_NO_BOOK_DELAY))
  290. {
  291. // Á־ȼú¼­ »ç¿ëÁß¿¡´Â ½Ã°£ Á¦ÇÑ ¹«½Ã
  292. RemoveAffect(AFFECT_SKILL_NO_BOOK_DELAY);
  293. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Á־ȼú¼­¸¦ ÅëÇØ ÁÖÈ­ÀÔ¸¶¿¡¼­ ºüÁ®³ª¿Ô½À´Ï´Ù."));
  294. }
  295. else
  296. {
  297. SkillLearnWaitMoreTimeMessage(GetSkillNextReadTime(dwSkillVnum) - get_global_time());
  298. return false;
  299. }
  300. }
  301. }
  302. */
  303.  
  304. // bTypeÀÌ 0À̸é óÀ½ºÎÅÍ Ã¥À¸·Î ¼ö·Ã °¡´É
  305. if (pkSk->dwType == 0)
  306. {
  307. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("±×·£µå ¸¶½ºÅÍ ¼ö·ÃÀ» ÇÒ ¼ö ¾ø´Â ½ºÅ³ÀÔ´Ï´Ù."));
  308. return false;
  309. }
  310.  
  311. if (GetSkillMasterType(dwSkillVnum) != SKILL_GRAND_MASTER)
  312. {
  313. if (GetSkillMasterType(dwSkillVnum) > SKILL_GRAND_MASTER)
  314. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÆÛÆåÆ® ¸¶½ºÅÍµÈ ½ºÅ³ÀÔ´Ï´Ù. ´õ ÀÌ»ó ¼ö·Ã ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  315. else
  316. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀÌ ½ºÅ³Àº ¾ÆÁ÷ ±×·£µå ¸¶½ºÅÍ ¼ö·ÃÀ» ÇÒ °æÁö¿¡ À̸£Áö ¾Ê¾Ò½À´Ï´Ù."));
  317. return false;
  318. }
  319.  
  320. std::string strTrainSkill;
  321. {
  322. std::ostringstream os;
  323. os << "training_grandmaster_skill.skill" << dwSkillVnum;
  324. strTrainSkill = os.str();
  325. }
  326.  
  327. // ¿©±â¼­ È®·üÀ» °è»êÇÕ´Ï´Ù.
  328. BYTE bLastLevel = GetSkillLevel(dwSkillVnum);
  329.  
  330. int idx = MIN(9, GetSkillLevel(dwSkillVnum) - 30);
  331.  
  332. sys_log(0, "LearnGrandMasterSkill %s table idx %d value %d", GetName(), idx, aiGrandMasterSkillBookCountForLevelUp[idx]);
  333.  
  334. int iTotalReadCount = GetQuestFlag(strTrainSkill) + 1;
  335. SetQuestFlag(strTrainSkill, iTotalReadCount);
  336.  
  337. int iMinReadCount = aiGrandMasterSkillBookMinCount[idx];
  338. int iMaxReadCount = aiGrandMasterSkillBookMaxCount[idx];
  339.  
  340. int iBookCount = aiGrandMasterSkillBookCountForLevelUp[idx];
  341.  
  342. if (FindAffect(AFFECT_SKILL_BOOK_BONUS))
  343. {
  344. if (iBookCount&1)
  345. iBookCount = iBookCount / 2 + 1;
  346. else
  347. iBookCount = iBookCount / 2;
  348.  
  349. RemoveAffect(AFFECT_SKILL_BOOK_BONUS);
  350. }
  351.  
  352. int n = number(1, iBookCount);
  353. sys_log(0, "Number(%d)", n);
  354.  
  355. DWORD nextTime = get_global_time() + number(28800, 43200);
  356.  
  357. sys_log(0, "GrandMaster SkillBookCount min %d cur %d max %d (next_time=%d)", iMinReadCount, iTotalReadCount, iMaxReadCount, nextTime);
  358.  
  359. bool bSuccess = n == 2;
  360.  
  361. if (iTotalReadCount < iMinReadCount)
  362. bSuccess = false;
  363. if (iTotalReadCount > iMaxReadCount)
  364. bSuccess = true;
  365.  
  366. if (bSuccess)
  367. {
  368. SkillLevelUp(dwSkillVnum, SKILL_UP_BY_QUEST);
  369. }
  370.  
  371. SetSkillNextReadTime(dwSkillVnum, nextTime);
  372.  
  373. if (bLastLevel == GetSkillLevel(dwSkillVnum))
  374. {
  375. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("Å©À¹, ±â°¡ ¿ª·ùÇϰí ÀÖ¾î! À̰м³¸¶ ÁÖÈ­ÀÔ¸¶Àΰ¡!? Á¨Àå!"));
  376. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ö·ÃÀÌ ½ÇÆÐ·Î ³¡³µ½À´Ï´Ù. ´Ù½Ã µµÀüÇØÁֽñ⠹ٶø´Ï´Ù."));
  377. LogManager::instance().CharLog(this, dwSkillVnum, "GM_READ_FAIL", "");
  378. return false;
  379. }
  380.  
  381. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("¸ö¿¡¼­ ¹º°¡ ÈûÀÌ ÅÍÁ® ³ª¿À´Â ±âºÐÀ̾ß!"));
  382. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("¶ß°Å¿î ¹«¾ùÀÌ °è¼Ó ¿ë¼ÚÀ½Ä¡°í ÀÖ¾î! À̰Ç, À̰ÍÀº!"));
  383. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´õ ³ôÀº °æÁöÀÇ ¼ö·ÃÀ» ¼º°øÀûÀ¸·Î ³¡³»¼Ì½À´Ï´Ù."));
  384. LogManager::instance().CharLog(this, dwSkillVnum, "GM_READ_SUCCESS", "");
  385. return true;
  386. }
  387. // END_OF_ADD_GRANDMASTER_SKILL
  388.  
  389. static bool FN_should_check_exp(LPCHARACTER ch)
  390. {
  391. // @warme005
  392. return ch->GetLevel() < gPlayerMaxLevel;
  393. }
  394.  
  395.  
  396. bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
  397. {
  398. const CSkillProto* pkSk = CSkillManager::instance().Get(dwSkillVnum);
  399.  
  400. if (!pkSk)
  401. return false;
  402.  
  403. if (!IsLearnableSkill(dwSkillVnum))
  404. {
  405. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ö·ÃÇÒ ¼ö ¾ø´Â ½ºÅ³ÀÔ´Ï´Ù."));
  406. return false;
  407. }
  408.  
  409. DWORD need_exp = 0;
  410.  
  411. if (FN_should_check_exp(this))
  412. {
  413. need_exp = 20000;
  414.  
  415. if ( GetExp() < need_exp )
  416. {
  417. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°æÇèÄ¡°¡ ºÎÁ·ÇÏ¿© Ã¥À» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù."));
  418. return false;
  419. }
  420. }
  421.  
  422. // bTypeÀÌ 0À̸é óÀ½ºÎÅÍ Ã¥À¸·Î ¼ö·Ã °¡´É
  423. if (pkSk->dwType != 0)
  424. {
  425. if (GetSkillMasterType(dwSkillVnum) != SKILL_MASTER)
  426. {
  427. if (GetSkillMasterType(dwSkillVnum) > SKILL_MASTER)
  428. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀÌ ½ºÅ³Àº Ã¥À¸·Î ´õÀÌ»ó ¼ö·ÃÇÒ ¼ö ¾ø½À´Ï´Ù."));
  429. else
  430. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀÌ ½ºÅ³Àº ¾ÆÁ÷ Ã¥À¸·Î ¼ö·ÃÇÒ °æÁö¿¡ À̸£Áö ¾Ê¾Ò½À´Ï´Ù."));
  431. return false;
  432. }
  433. }
  434.  
  435. if (get_global_time() < GetSkillNextReadTime(dwSkillVnum))
  436. {
  437. if (!(test_server && quest::CQuestManager::instance().GetEventFlag("no_read_delay")))
  438. {
  439. if (FindAffect(AFFECT_SKILL_NO_BOOK_DELAY))
  440. {
  441. // Á־ȼú¼­ »ç¿ëÁß¿¡´Â ½Ã°£ Á¦ÇÑ ¹«½Ã
  442. RemoveAffect(AFFECT_SKILL_NO_BOOK_DELAY);
  443. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Á־ȼú¼­¸¦ ÅëÇØ ÁÖÈ­ÀÔ¸¶¿¡¼­ ºüÁ®³ª¿Ô½À´Ï´Ù."));
  444. }
  445. else
  446. {
  447. SkillLearnWaitMoreTimeMessage(GetSkillNextReadTime(dwSkillVnum) - get_global_time());
  448. return false;
  449. }
  450. }
  451. }
  452.  
  453. // ¿©±â¼­ È®·üÀ» °è»êÇÕ´Ï´Ù.
  454. BYTE bLastLevel = GetSkillLevel(dwSkillVnum);
  455.  
  456. if (bProb != 0)
  457. {
  458. // SKILL_BOOK_BONUS
  459. if (FindAffect(AFFECT_SKILL_BOOK_BONUS))
  460. {
  461. bProb += bProb / 2;
  462. RemoveAffect(AFFECT_SKILL_BOOK_BONUS);
  463. }
  464. // END_OF_SKILL_BOOK_BONUS
  465.  
  466. sys_log(0, "LearnSkillByBook Pct %u prob %d", dwSkillVnum, bProb);
  467.  
  468. if (number(1, 100) <= bProb)
  469. {
  470. if (test_server)
  471. sys_log(0, "LearnSkillByBook %u SUCC", dwSkillVnum);
  472.  
  473. SkillLevelUp(dwSkillVnum, SKILL_UP_BY_BOOK);
  474. }
  475. else
  476. {
  477. if (test_server)
  478. sys_log(0, "LearnSkillByBook %u FAIL", dwSkillVnum);
  479. }
  480. }
  481. else
  482. {
  483. int idx = MIN(9, GetSkillLevel(dwSkillVnum) - 20);
  484.  
  485. sys_log(0, "LearnSkillByBook %s table idx %d value %d", GetName(), idx, aiSkillBookCountForLevelUp[idx]);
  486.  
  487. {
  488. int need_bookcount = GetSkillLevel(dwSkillVnum) - 20;
  489.  
  490. PointChange(POINT_EXP, -need_exp);
  491.  
  492. quest::CQuestManager& q = quest::CQuestManager::instance();
  493. quest::PC* pPC = q.GetPC(GetPlayerID());
  494.  
  495. if (pPC)
  496. {
  497. char flag[128+1];
  498. memset(flag, 0, sizeof(flag));
  499. snprintf(flag, sizeof(flag), "traning_master_skill.%u.read_count", dwSkillVnum);
  500.  
  501. int read_count = pPC->GetFlag(flag);
  502. int percent = 65;
  503.  
  504. if (FindAffect(AFFECT_SKILL_BOOK_BONUS))
  505. {
  506. percent = 0;
  507. RemoveAffect(AFFECT_SKILL_BOOK_BONUS);
  508. }
  509.  
  510. if (number(1, 100) > percent)
  511. {
  512. // Ã¥Àб⿡ ¼º°ø
  513. if (read_count >= need_bookcount)
  514. {
  515. SkillLevelUp(dwSkillVnum, SKILL_UP_BY_BOOK);
  516. pPC->SetFlag(flag, 0);
  517.  
  518. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Ã¥À¸·Î ´õ ³ôÀº °æÁöÀÇ ¼ö·ÃÀ» ¼º°øÀûÀ¸·Î ³¡³»¼Ì½À´Ï´Ù."));
  519. LogManager::instance().CharLog(this, dwSkillVnum, "READ_SUCCESS", "");
  520. return true;
  521. }
  522. else
  523. {
  524. pPC->SetFlag(flag, read_count + 1);
  525.  
  526. switch (number(1, 3))
  527. {
  528. case 1:
  529. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("¾î´ÀÁ¤µµ ÀÌ ±â¼ú¿¡ ´ëÇØ ÀÌÇØ°¡ µÇ¾úÁö¸¸ Á¶±Ý ºÎÁ·Çѵí Çѵ¥.."));
  530. break;
  531.  
  532. case 2:
  533. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("µåµð¾î ³¡ÀÌ º¸ÀÌ´Â °Ç°¡... ÀÌ ±â¼úÀº ÀÌÇØÇϱⰡ ³Ê¹« Èûµé¾î.."));
  534. break;
  535.  
  536. case 3:
  537. default:
  538. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("¿­½ÉÈ÷ ÇÏ´Â ¹è¿òÀ» °¡Áö´Â °Í¸¸ÀÌ ±â¼úÀ» ¹è¿ï¼ö ÀÖ´Â À¯ÀÏÇÑ ±æÀÌ´Ù.."));
  539. break;
  540. }
  541.  
  542. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d ±ÇÀ» ´õ Àоî¾ß ¼ö·ÃÀ» ¿Ï·á ÇÒ ¼ö ÀÖ½À´Ï´Ù."), need_bookcount - read_count);
  543. return true;
  544. }
  545. }
  546. }
  547. else
  548. {
  549. // »ç¿ëÀÚÀÇ Äù½ºÆ® Á¤º¸ ·Îµå ½ÇÆÐ
  550. }
  551. }
  552. }
  553.  
  554. if (bLastLevel != GetSkillLevel(dwSkillVnum))
  555. {
  556. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("¸ö¿¡¼­ ¹º°¡ ÈûÀÌ ÅÍÁ® ³ª¿À´Â ±âºÐÀ̾ß!"));
  557. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("¶ß°Å¿î ¹«¾ùÀÌ °è¼Ó ¿ë¼ÚÀ½Ä¡°í ÀÖ¾î! À̰Ç, À̰ÍÀº!"));
  558. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Ã¥À¸·Î ´õ ³ôÀº °æÁöÀÇ ¼ö·ÃÀ» ¼º°øÀûÀ¸·Î ³¡³»¼Ì½À´Ï´Ù."));
  559. LogManager::instance().CharLog(this, dwSkillVnum, "READ_SUCCESS", "");
  560. }
  561. else
  562. {
  563. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("Å©À¹, ±â°¡ ¿ª·ùÇϰí ÀÖ¾î! À̰м³¸¶ ÁÖÈ­ÀÔ¸¶Àΰ¡!? Á¨Àå!"));
  564. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ö·ÃÀÌ ½ÇÆÐ·Î ³¡³µ½À´Ï´Ù. ´Ù½Ã µµÀüÇØÁֽñ⠹ٶø´Ï´Ù."));
  565. LogManager::instance().CharLog(this, dwSkillVnum, "READ_FAIL", "");
  566. }
  567.  
  568. return true;
  569. }
  570.  
  571. bool CHARACTER::SkillLevelDown(DWORD dwVnum)
  572. {
  573. if (NULL == m_pSkillLevels)
  574. return false;
  575.  
  576. if (g_bSkillDisable)
  577. return false;
  578.  
  579. if (IsPolymorphed())
  580. return false;
  581.  
  582. CSkillProto * pkSk = CSkillManager::instance().Get(dwVnum);
  583.  
  584. if (!pkSk)
  585. {
  586. sys_err("There is no such skill by number %u", dwVnum);
  587. return false;
  588. }
  589.  
  590. if (!IsLearnableSkill(dwVnum))
  591. return false;
  592.  
  593. if (GetSkillMasterType(pkSk->dwVnum) != SKILL_NORMAL)
  594. return false;
  595.  
  596. if (!GetSkillGroup())
  597. return false;
  598.  
  599. if (pkSk->dwVnum >= SKILL_MAX_NUM)
  600. return false;
  601.  
  602. if (m_pSkillLevels[pkSk->dwVnum].bLevel == 0)
  603. return false;
  604.  
  605. int idx = POINT_SKILL;
  606. switch (pkSk->dwType)
  607. {
  608. case 0:
  609. idx = POINT_SUB_SKILL;
  610. break;
  611. case 1:
  612. case 2:
  613. case 3:
  614. case 4:
  615. case 6:
  616. #ifdef ENABLE_WOLFMAN_CHARACTER
  617. case 7:
  618. #endif
  619. idx = POINT_SKILL;
  620. break;
  621. case 5:
  622. idx = POINT_HORSE_SKILL;
  623. break;
  624. default:
  625. sys_err("Wrong skill type %d skill vnum %d", pkSk->dwType, pkSk->dwVnum);
  626. return false;
  627.  
  628. }
  629.  
  630. PointChange(idx, +1);
  631. SetSkillLevel(pkSk->dwVnum, m_pSkillLevels[pkSk->dwVnum].bLevel - 1);
  632.  
  633. sys_log(0, "SkillDown: %s %u %u %u type %u", GetName(), pkSk->dwVnum, m_pSkillLevels[pkSk->dwVnum].bMasterType, m_pSkillLevels[pkSk->dwVnum].bLevel, pkSk->dwType);
  634. Save();
  635.  
  636. ComputePoints();
  637. SkillLevelPacket();
  638. return true;
  639. }
  640.  
  641. void CHARACTER::SkillLevelUp(DWORD dwVnum, BYTE bMethod)
  642. {
  643. if (NULL == m_pSkillLevels)
  644. return;
  645.  
  646. if (g_bSkillDisable)
  647. return;
  648.  
  649. if (IsPolymorphed())
  650. {
  651. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("µÐ°© Áß¿¡´Â ´É·ÂÀ» ¿Ã¸± ¼ö ¾ø½À´Ï´Ù."));
  652. return;
  653. }
  654.  
  655. if (SKILL_7_A_ANTI_TANHWAN <= dwVnum && dwVnum <= SKILL_8_D_ANTI_BYEURAK)
  656. {
  657. if (0 == GetSkillLevel(dwVnum))
  658. return;
  659. }
  660.  
  661. const CSkillProto* pkSk = CSkillManager::instance().Get(dwVnum);
  662.  
  663. if (!pkSk)
  664. {
  665. sys_err("There is no such skill by number (vnum %u)", dwVnum);
  666. return;
  667. }
  668.  
  669. if (pkSk->dwVnum >= SKILL_MAX_NUM)
  670. {
  671. sys_err("Skill Vnum overflow (vnum %u)", dwVnum);
  672. return;
  673. }
  674.  
  675. if (!IsLearnableSkill(dwVnum))
  676. return;
  677.  
  678. // ±×·£µå ¸¶½ºÅÍ´Â Äù½ºÆ®·Î¸¸ ¼öÇà°¡´É
  679. if (pkSk->dwType != 0)
  680. {
  681. switch (GetSkillMasterType(pkSk->dwVnum))
  682. {
  683. case SKILL_GRAND_MASTER:
  684. if (bMethod != SKILL_UP_BY_QUEST)
  685. return;
  686. break;
  687.  
  688. case SKILL_PERFECT_MASTER:
  689. return;
  690. }
  691. }
  692.  
  693. if (bMethod == SKILL_UP_BY_POINT)
  694. {
  695. // ¸¶½ºÅͰ¡ ¾Æ´Ñ »óÅ¿¡¼­¸¸ ¼ö·Ã°¡´É
  696. if (GetSkillMasterType(pkSk->dwVnum) != SKILL_NORMAL)
  697. return;
  698.  
  699. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_DISABLE_BY_POINT_UP))
  700. return;
  701. }
  702. else if (bMethod == SKILL_UP_BY_BOOK)
  703. {
  704. if (pkSk->dwType != 0) // Á÷¾÷¿¡ ¼ÓÇÏÁö ¾Ê¾Ò°Å³ª Æ÷ÀÎÆ®·Î ¿Ã¸±¼ö ¾ø´Â ½ºÅ³Àº óÀ½ºÎÅÍ Ã¥À¸·Î ¹è¿ï ¼ö ÀÖ´Ù.
  705. if (GetSkillMasterType(pkSk->dwVnum) != SKILL_MASTER)
  706. return;
  707. }
  708.  
  709. if (GetLevel() < pkSk->bLevelLimit)
  710. return;
  711.  
  712. if (pkSk->preSkillVnum)
  713. if (GetSkillMasterType(pkSk->preSkillVnum) == SKILL_NORMAL &&
  714. GetSkillLevel(pkSk->preSkillVnum) < pkSk->preSkillLevel)
  715. return;
  716.  
  717. if (!GetSkillGroup())
  718. return;
  719.  
  720. if (bMethod == SKILL_UP_BY_POINT)
  721. {
  722. int idx;
  723.  
  724. switch (pkSk->dwType)
  725. {
  726. case 0:
  727. idx = POINT_SUB_SKILL;
  728. break;
  729.  
  730. case 1:
  731. case 2:
  732. case 3:
  733. case 4:
  734. case 6:
  735. #ifdef ENABLE_WOLFMAN_CHARACTER
  736. case 7:
  737. #endif
  738. idx = POINT_SKILL;
  739. break;
  740.  
  741. case 5:
  742. idx = POINT_HORSE_SKILL;
  743. break;
  744.  
  745. default:
  746. sys_err("Wrong skill type %d skill vnum %d", pkSk->dwType, pkSk->dwVnum);
  747. return;
  748. }
  749.  
  750. if (GetPoint(idx) < 1)
  751. return;
  752.  
  753. PointChange(idx, -1);
  754. }
  755.  
  756. int SkillPointBefore = GetSkillLevel(pkSk->dwVnum);
  757. SetSkillLevel(pkSk->dwVnum, m_pSkillLevels[pkSk->dwVnum].bLevel + 1);
  758.  
  759. if (pkSk->dwType != 0)
  760. {
  761. // °©Àڱ⠱׷¹ÀÌµå ¾÷ÇÏ´Â ÄÚµù
  762. switch (GetSkillMasterType(pkSk->dwVnum))
  763. {
  764. case SKILL_NORMAL:
  765. // ¹ø¼·Àº ½ºÅ³ ¾÷±×·¹À̵å 17~20 »çÀÌ ·£´ý ¸¶½ºÅÍ ¼ö·Ã
  766. if (GetSkillLevel(pkSk->dwVnum) >= 16)
  767. {
  768. #ifdef ENABLE_FORCE2MASTERSKILL
  769. SetSkillLevel(pkSk->dwVnum, 20);
  770. #else
  771. if (GetQuestFlag("reset_scroll.force_to_master_skill") > 0)
  772. {
  773. SetSkillLevel(pkSk->dwVnum, 20);
  774. SetQuestFlag("reset_scroll.force_to_master_skill", 0);
  775. }
  776. else
  777. {
  778. if (number(1, 21 - MIN(20, GetSkillLevel(pkSk->dwVnum))) == 1)
  779. SetSkillLevel(pkSk->dwVnum, 20);
  780. }
  781. #endif
  782. }
  783. break;
  784.  
  785. case SKILL_MASTER:
  786. if (GetSkillLevel(pkSk->dwVnum) >= 30)
  787. {
  788. if (number(1, 31 - MIN(30, GetSkillLevel(pkSk->dwVnum))) == 1)
  789. SetSkillLevel(pkSk->dwVnum, 30);
  790. }
  791. break;
  792.  
  793. case SKILL_GRAND_MASTER:
  794. if (GetSkillLevel(pkSk->dwVnum) >= 40)
  795. {
  796. SetSkillLevel(pkSk->dwVnum, 40);
  797. }
  798. break;
  799. }
  800. }
  801.  
  802. char szSkillUp[1024];
  803.  
  804. snprintf(szSkillUp, sizeof(szSkillUp), "SkillUp: %s %u %d %d[Before:%d] type %u",
  805. GetName(), pkSk->dwVnum, m_pSkillLevels[pkSk->dwVnum].bMasterType, m_pSkillLevels[pkSk->dwVnum].bLevel, SkillPointBefore, pkSk->dwType);
  806.  
  807. sys_log(0, "%s", szSkillUp);
  808.  
  809. LogManager::instance().CharLog(this, pkSk->dwVnum, "SKILLUP", szSkillUp);
  810. Save();
  811.  
  812. ComputePoints();
  813. SkillLevelPacket();
  814. }
  815.  
  816. void CHARACTER::ComputeSkillPoints()
  817. {
  818. if (g_bSkillDisable)
  819. return;
  820. }
  821.  
  822. void CHARACTER::ResetSkill()
  823. {
  824. if (NULL == m_pSkillLevels)
  825. return;
  826.  
  827. // º¸Á¶ ½ºÅ³Àº ¸®¼Â½ÃŰÁö ¾Ê´Â´Ù
  828. std::vector<std::pair<DWORD, TPlayerSkill> > vec;
  829. size_t count = sizeof(s_adwSubSkillVnums) / sizeof(s_adwSubSkillVnums[0]);
  830.  
  831. for (size_t i = 0; i < count; ++i)
  832. {
  833. if (s_adwSubSkillVnums[i] >= SKILL_MAX_NUM)
  834. continue;
  835.  
  836. vec.push_back(std::make_pair(s_adwSubSkillVnums[i], m_pSkillLevels[s_adwSubSkillVnums[i]]));
  837. }
  838.  
  839. memset(m_pSkillLevels, 0, sizeof(TPlayerSkill) * SKILL_MAX_NUM);
  840.  
  841. std::vector<std::pair<DWORD, TPlayerSkill> >::const_iterator iter = vec.begin();
  842.  
  843. while (iter != vec.end())
  844. {
  845. const std::pair<DWORD, TPlayerSkill>& pair = *(iter++);
  846. m_pSkillLevels[pair.first] = pair.second;
  847. }
  848.  
  849. ComputePoints();
  850. SkillLevelPacket();
  851. }
  852.  
  853. void CHARACTER::ComputePassiveSkill(DWORD dwVnum)
  854. {
  855. if (g_bSkillDisable)
  856. return;
  857.  
  858. if (GetSkillLevel(dwVnum) == 0)
  859. return;
  860.  
  861. CSkillProto * pkSk = CSkillManager::instance().Get(dwVnum);
  862. pkSk->SetPointVar("k", GetSkillLevel(dwVnum));
  863. int iAmount = (int) pkSk->kPointPoly.Eval();
  864.  
  865. sys_log(2, "%s passive #%d on %d amount %d", GetName(), dwVnum, pkSk->bPointOn, iAmount);
  866. PointChange(pkSk->bPointOn, iAmount);
  867. }
  868.  
  869. struct FFindNearVictim
  870. {
  871. FFindNearVictim(LPCHARACTER center, LPCHARACTER attacker, const CHARACTER_SET& excepts_set = empty_set_)
  872. : m_pkChrCenter(center),
  873. m_pkChrNextTarget(NULL),
  874. m_pkChrAttacker(attacker),
  875. m_count(0),
  876. m_excepts_set(excepts_set)
  877. {
  878. }
  879.  
  880. void operator ()(LPENTITY ent)
  881. {
  882. if (!ent->IsType(ENTITY_CHARACTER))
  883. return;
  884.  
  885. LPCHARACTER pkChr = (LPCHARACTER) ent;
  886.  
  887. if (!m_excepts_set.empty()) {
  888. if (m_excepts_set.find(pkChr) != m_excepts_set.end())
  889. return;
  890. }
  891.  
  892. if (m_pkChrCenter == pkChr)
  893. return;
  894.  
  895. if (!battle_is_attackable(m_pkChrAttacker, pkChr))
  896. {
  897. return;
  898. }
  899.  
  900. if (abs(m_pkChrCenter->GetX() - pkChr->GetX()) > 1000 || abs(m_pkChrCenter->GetY() - pkChr->GetY()) > 1000)
  901. return;
  902.  
  903. float fDist = DISTANCE_APPROX(m_pkChrCenter->GetX() - pkChr->GetX(), m_pkChrCenter->GetY() - pkChr->GetY());
  904.  
  905. if (fDist < 1000)
  906. {
  907. ++m_count;
  908.  
  909. if ((m_count == 1) || number(1, m_count) == 1)
  910. m_pkChrNextTarget = pkChr;
  911. }
  912. }
  913.  
  914. LPCHARACTER GetVictim()
  915. {
  916. return m_pkChrNextTarget;
  917. }
  918.  
  919. LPCHARACTER m_pkChrCenter;
  920. LPCHARACTER m_pkChrNextTarget;
  921. LPCHARACTER m_pkChrAttacker;
  922. int m_count;
  923. const CHARACTER_SET & m_excepts_set;
  924. private:
  925. static CHARACTER_SET empty_set_;
  926. };
  927.  
  928. CHARACTER_SET FFindNearVictim::empty_set_;
  929.  
  930. EVENTINFO(chain_lightning_event_info)
  931. {
  932. DWORD dwVictim;
  933. DWORD dwChr;
  934.  
  935. chain_lightning_event_info()
  936. : dwVictim(0)
  937. , dwChr(0)
  938. {
  939. }
  940. };
  941.  
  942. EVENTFUNC(ChainLightningEvent)
  943. {
  944. chain_lightning_event_info * info = dynamic_cast<chain_lightning_event_info *>( event->info );
  945.  
  946. LPCHARACTER pkChrVictim = CHARACTER_MANAGER::instance().Find(info->dwVictim);
  947. LPCHARACTER pkChr = CHARACTER_MANAGER::instance().Find(info->dwChr);
  948. LPCHARACTER pkTarget = NULL;
  949.  
  950. if (!pkChr || !pkChrVictim)
  951. {
  952. sys_log(1, "use chainlighting, but no character");
  953. return 0;
  954. }
  955.  
  956. sys_log(1, "chainlighting event %s", pkChr->GetName());
  957.  
  958. if (pkChrVictim->GetParty()) // ÆÄƼ ¸ÕÀú
  959. {
  960. pkTarget = pkChrVictim->GetParty()->GetNextOwnership(NULL, pkChrVictim->GetX(), pkChrVictim->GetY());
  961. if (pkTarget == pkChrVictim || !number(0, 2) || pkChr->GetChainLightingExcept().find(pkTarget) != pkChr->GetChainLightingExcept().end())
  962. pkTarget = NULL;
  963. }
  964.  
  965. if (!pkTarget)
  966. {
  967. // 1. Find Next victim
  968. FFindNearVictim f(pkChrVictim, pkChr, pkChr->GetChainLightingExcept());
  969.  
  970. if (pkChrVictim->GetSectree())
  971. {
  972. pkChrVictim->GetSectree()->ForEachAround(f);
  973. // 2. If exist, compute it again
  974. pkTarget = f.GetVictim();
  975. }
  976. }
  977.  
  978. if (pkTarget)
  979. {
  980. pkChrVictim->CreateFly(FLY_CHAIN_LIGHTNING, pkTarget);
  981. pkChr->ComputeSkill(SKILL_CHAIN, pkTarget);
  982. pkChr->AddChainLightningExcept(pkTarget);
  983. }
  984. else
  985. {
  986. sys_log(1, "%s use chainlighting, but find victim failed near %s", pkChr->GetName(), pkChrVictim->GetName());
  987. }
  988.  
  989. return 0;
  990. }
  991.  
  992. void SetPolyVarForAttack(LPCHARACTER ch, CSkillProto * pkSk, LPITEM pkWeapon)
  993. {
  994. if (ch->IsPC())
  995. {
  996. if (pkWeapon && pkWeapon->GetType() == ITEM_WEAPON)
  997. {
  998. int iWep = number(pkWeapon->GetValue(3), pkWeapon->GetValue(4));
  999. iWep += pkWeapon->GetValue(5);
  1000.  
  1001. int iMtk = number(pkWeapon->GetValue(1), pkWeapon->GetValue(2));
  1002. iMtk += pkWeapon->GetValue(5);
  1003.  
  1004. pkSk->SetPointVar("wep", iWep);
  1005. pkSk->SetPointVar("mtk", iMtk);
  1006. pkSk->SetPointVar("mwep", iMtk);
  1007. }
  1008. else
  1009. {
  1010. pkSk->SetPointVar("wep", 0);
  1011. pkSk->SetPointVar("mtk", 0);
  1012. pkSk->SetPointVar("mwep", 0);
  1013. }
  1014. }
  1015. else
  1016. {
  1017. int iWep = number(ch->GetMobDamageMin(), ch->GetMobDamageMax());
  1018. pkSk->SetPointVar("wep", iWep);
  1019. pkSk->SetPointVar("mwep", iWep);
  1020. pkSk->SetPointVar("mtk", iWep);
  1021. }
  1022. }
  1023.  
  1024. struct FuncSplashDamage
  1025. {
  1026. FuncSplashDamage(int x, int y, CSkillProto * pkSk, LPCHARACTER pkChr, int iAmount, int iAG, int iMaxHit, LPITEM pkWeapon, bool bDisableCooltime, TSkillUseInfo* pInfo, BYTE bUseSkillPower)
  1027. :
  1028. m_x(x), m_y(y), m_pkSk(pkSk), m_pkChr(pkChr), m_iAmount(iAmount), m_iAG(iAG), m_iCount(0), m_iMaxHit(iMaxHit), m_pkWeapon(pkWeapon), m_bDisableCooltime(bDisableCooltime), m_pInfo(pInfo), m_bUseSkillPower(bUseSkillPower)
  1029. {
  1030. }
  1031.  
  1032. void operator () (LPENTITY ent)
  1033. {
  1034. if (!ent->IsType(ENTITY_CHARACTER))
  1035. {
  1036. //if (m_pkSk->dwVnum == SKILL_CHAIN) sys_log(0, "CHAIN target not character %s", m_pkChr->GetName());
  1037. return;
  1038. }
  1039.  
  1040. LPCHARACTER pkChrVictim = (LPCHARACTER) ent;
  1041.  
  1042. if (DISTANCE_APPROX(m_x - pkChrVictim->GetX(), m_y - pkChrVictim->GetY()) > m_pkSk->iSplashRange)
  1043. {
  1044. if(test_server)
  1045. sys_log(0, "XXX target too far %s", m_pkChr->GetName());
  1046. return;
  1047. }
  1048.  
  1049. if (!battle_is_attackable(m_pkChr, pkChrVictim))
  1050. {
  1051. if(test_server)
  1052. sys_log(0, "XXX target not attackable %s", m_pkChr->GetName());
  1053. return;
  1054. }
  1055.  
  1056. if (m_pkChr->IsPC())
  1057. // ±æµå ½ºÅ³Àº ÄðŸÀÓ Ã³¸®¸¦ ÇÏÁö ¾Ê´Â´Ù.
  1058. if (!(m_pkSk->dwVnum >= GUILD_SKILL_START && m_pkSk->dwVnum <= GUILD_SKILL_END))
  1059. if (!m_bDisableCooltime && m_pInfo && !m_pInfo->HitOnce(m_pkSk->dwVnum) && m_pkSk->dwVnum != SKILL_MUYEONG)
  1060. {
  1061. if(test_server)
  1062. sys_log(0, "check guild skill %s", m_pkChr->GetName());
  1063. return;
  1064. }
  1065.  
  1066. ++m_iCount;
  1067.  
  1068. int iDam;
  1069.  
  1070. ////////////////////////////////////////////////////////////////////////////////
  1071. //float k = 1.0f * m_pkChr->GetSkillPower(m_pkSk->dwVnum) * m_pkSk->bMaxLevel / 100;
  1072. //m_pkSk->kPointPoly2.SetVar("k", 1.0 * m_bUseSkillPower * m_pkSk->bMaxLevel / 100);
  1073. m_pkSk->SetPointVar("k", 1.0 * m_bUseSkillPower * m_pkSk->bMaxLevel / 100);
  1074. m_pkSk->SetPointVar("lv", m_pkChr->GetLevel());
  1075. m_pkSk->SetPointVar("iq", m_pkChr->GetPoint(POINT_IQ));
  1076. m_pkSk->SetPointVar("str", m_pkChr->GetPoint(POINT_ST));
  1077. m_pkSk->SetPointVar("dex", m_pkChr->GetPoint(POINT_DX));
  1078. m_pkSk->SetPointVar("con", m_pkChr->GetPoint(POINT_HT));
  1079. m_pkSk->SetPointVar("def", m_pkChr->GetPoint(POINT_DEF_GRADE));
  1080. m_pkSk->SetPointVar("odef", m_pkChr->GetPoint(POINT_DEF_GRADE) - m_pkChr->GetPoint(POINT_DEF_GRADE_BONUS));
  1081. m_pkSk->SetPointVar("horse_level", m_pkChr->GetHorseLevel());
  1082.  
  1083. //int iPenetratePct = (int)(1 + k*4);
  1084. bool bIgnoreDefense = false;
  1085.  
  1086. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_PENETRATE))
  1087. {
  1088. int iPenetratePct = (int) m_pkSk->kPointPoly2.Eval();
  1089.  
  1090. if (number(1, 100) <= iPenetratePct)
  1091. bIgnoreDefense = true;
  1092. }
  1093.  
  1094. bool bIgnoreTargetRating = false;
  1095.  
  1096. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_IGNORE_TARGET_RATING))
  1097. {
  1098. int iPct = (int) m_pkSk->kPointPoly2.Eval();
  1099.  
  1100. if (number(1, 100) <= iPct)
  1101. bIgnoreTargetRating = true;
  1102. }
  1103.  
  1104. m_pkSk->SetPointVar("ar", CalcAttackRating(m_pkChr, pkChrVictim, bIgnoreTargetRating));
  1105.  
  1106. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_USE_MELEE_DAMAGE))
  1107. m_pkSk->SetPointVar("atk", CalcMeleeDamage(m_pkChr, pkChrVictim, true, bIgnoreTargetRating));
  1108. else if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_USE_ARROW_DAMAGE))
  1109. {
  1110. LPITEM pkBow, pkArrow;
  1111.  
  1112. if (1 == m_pkChr->GetArrowAndBow(&pkBow, &pkArrow, 1))
  1113. m_pkSk->SetPointVar("atk", CalcArrowDamage(m_pkChr, pkChrVictim, pkBow, pkArrow, true));
  1114. else
  1115. m_pkSk->SetPointVar("atk", 0);
  1116. }
  1117.  
  1118. if (m_pkSk->bPointOn == POINT_MOV_SPEED)
  1119. m_pkSk->kPointPoly.SetVar("maxv", pkChrVictim->GetLimitPoint(POINT_MOV_SPEED));
  1120.  
  1121. m_pkSk->SetPointVar("maxhp", pkChrVictim->GetMaxHP());
  1122. m_pkSk->SetPointVar("maxsp", pkChrVictim->GetMaxSP());
  1123.  
  1124. m_pkSk->SetPointVar("chain", m_pkChr->GetChainLightningIndex());
  1125. m_pkChr->IncChainLightningIndex();
  1126.  
  1127. bool bUnderEunhyung = m_pkChr->GetAffectedEunhyung() > 0; // ÀÌ°Ç ¿Ö ¿©±â¼­ ÇÏÁö??
  1128.  
  1129. m_pkSk->SetPointVar("ek", m_pkChr->GetAffectedEunhyung()*1./100);
  1130. //m_pkChr->ClearAffectedEunhyung();
  1131. SetPolyVarForAttack(m_pkChr, m_pkSk, m_pkWeapon);
  1132.  
  1133. int iAmount = 0;
  1134.  
  1135. if (m_pkChr->GetUsedSkillMasterType(m_pkSk->dwVnum) >= SKILL_GRAND_MASTER)
  1136. {
  1137. iAmount = (int) m_pkSk->kMasterBonusPoly.Eval();
  1138. }
  1139. else
  1140. {
  1141. iAmount = (int) m_pkSk->kPointPoly.Eval();
  1142. }
  1143.  
  1144. if (test_server && iAmount == 0 && m_pkSk->bPointOn != POINT_NONE)
  1145. {
  1146. m_pkChr->ChatPacket(CHAT_TYPE_INFO, "È¿°ú°¡ ¾ø½À´Ï´Ù. ½ºÅ³ °ø½ÄÀ» È®ÀÎÇϼ¼¿ä");
  1147. }
  1148. ////////////////////////////////////////////////////////////////////////////////
  1149. iAmount = -iAmount;
  1150.  
  1151. if (m_pkSk->dwVnum == SKILL_AMSEOP)
  1152. {
  1153. float fDelta = GetDegreeDelta(m_pkChr->GetRotation(), pkChrVictim->GetRotation());
  1154. float adjust;
  1155.  
  1156. if (fDelta < 35.0f)
  1157. {
  1158. adjust = 1.5f;
  1159.  
  1160. if (bUnderEunhyung)
  1161. adjust += 0.5f;
  1162.  
  1163. if (m_pkChr->GetWear(WEAR_WEAPON) && m_pkChr->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_DAGGER)
  1164. {
  1165. adjust += 0.5f;
  1166. }
  1167. }
  1168. else
  1169. {
  1170. adjust = 1.0f;
  1171.  
  1172. if (bUnderEunhyung)
  1173. adjust += 0.5f;
  1174.  
  1175. if (m_pkChr->GetWear(WEAR_WEAPON) && m_pkChr->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_DAGGER)
  1176. adjust += 0.5f;
  1177. }
  1178.  
  1179. iAmount = (int) (iAmount * adjust);
  1180. }
  1181. else if (m_pkSk->dwVnum == SKILL_GUNGSIN)
  1182. {
  1183. float adjust = 1.0;
  1184.  
  1185. if (m_pkChr->GetWear(WEAR_WEAPON) && m_pkChr->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_DAGGER)
  1186. {
  1187. adjust = 1.35f;
  1188. }
  1189.  
  1190. iAmount = (int) (iAmount * adjust);
  1191. }
  1192. #ifdef ENABLE_WOLFMAN_CHARACTER
  1193. else if (m_pkSk->dwVnum == SKILL_GONGDAB)
  1194. {
  1195. float adjust = 1.0;
  1196.  
  1197. if (m_pkChr->GetWear(WEAR_WEAPON) && m_pkChr->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_CLAW)
  1198. {
  1199. adjust = 1.35f;
  1200. }
  1201.  
  1202. iAmount = (int)(iAmount * adjust);
  1203. }
  1204. #endif
  1205. ////////////////////////////////////////////////////////////////////////////////
  1206. //sys_log(0, "name: %s skill: %s amount %d to %s", m_pkChr->GetName(), m_pkSk->szName, iAmount, pkChrVictim->GetName());
  1207.  
  1208. iDam = CalcBattleDamage(iAmount, m_pkChr->GetLevel(), pkChrVictim->GetLevel());
  1209.  
  1210. if (m_pkChr->IsPC() && m_pkChr->m_SkillUseInfo[m_pkSk->dwVnum].GetMainTargetVID() != (DWORD) pkChrVictim->GetVID())
  1211. {
  1212. // µ¥¹ÌÁö °¨¼Ò
  1213. iDam = (int) (iDam * m_pkSk->kSplashAroundDamageAdjustPoly.Eval());
  1214. }
  1215.  
  1216. // TODO ½ºÅ³¿¡ µû¸¥ µ¥¹ÌÁö ŸÀÔ ±â·ÏÇØ¾ßÇÑ´Ù.
  1217. EDamageType dt = DAMAGE_TYPE_NONE;
  1218.  
  1219. switch (m_pkSk->bSkillAttrType)
  1220. {
  1221. case SKILL_ATTR_TYPE_NORMAL:
  1222. break;
  1223.  
  1224. case SKILL_ATTR_TYPE_MELEE:
  1225. {
  1226. dt = DAMAGE_TYPE_MELEE;
  1227.  
  1228. LPITEM pkWeapon = m_pkChr->GetWear(WEAR_WEAPON);
  1229.  
  1230. if (pkWeapon)
  1231. switch (pkWeapon->GetSubType())
  1232. {
  1233. case WEAPON_SWORD:
  1234. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_SWORD)) / 100;
  1235. break;
  1236.  
  1237. case WEAPON_TWO_HANDED:
  1238. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_TWOHAND)) / 100;
  1239. // ¾ç¼Õ°Ë Æä³ÎƼ 10%
  1240. //iDam = iDam * 95 / 100;
  1241.  
  1242. break;
  1243.  
  1244. case WEAPON_DAGGER:
  1245. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_DAGGER)) / 100;
  1246. break;
  1247.  
  1248. case WEAPON_BELL:
  1249. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_BELL)) / 100;
  1250. break;
  1251.  
  1252. case WEAPON_FAN:
  1253. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_FAN)) / 100;
  1254. break;
  1255. #ifdef ENABLE_WOLFMAN_CHARACTER
  1256. case WEAPON_CLAW:
  1257. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_CLAW)) / 100;
  1258. break;
  1259. #endif
  1260. }
  1261.  
  1262. if (!bIgnoreDefense)
  1263. iDam -= pkChrVictim->GetPoint(POINT_DEF_GRADE);
  1264. }
  1265. break;
  1266.  
  1267. case SKILL_ATTR_TYPE_RANGE:
  1268. dt = DAMAGE_TYPE_RANGE;
  1269. // À¸¾Æ¾Æ¾Æ¾Ç
  1270. // ¿¹Àü¿¡ Àû¿ë¾ÈÇß´ø ¹ö±×°¡ À־ ¹æ¾î·Â °è»êÀ» ´Ù½ÃÇϸé À¯Àú°¡ ³­¸®³²
  1271. //iDam -= pkChrVictim->GetPoint(POINT_DEF_GRADE);
  1272. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_BOW)) / 100;
  1273. break;
  1274.  
  1275. case SKILL_ATTR_TYPE_MAGIC:
  1276. dt = DAMAGE_TYPE_MAGIC;
  1277. iDam = CalcAttBonus(m_pkChr, pkChrVictim, iDam);
  1278. // À¸¾Æ¾Æ¾Æ¾Ç
  1279. // ¿¹Àü¿¡ Àû¿ë¾ÈÇß´ø ¹ö±×°¡ À־ ¹æ¾î·Â °è»êÀ» ´Ù½ÃÇϸé À¯Àú°¡ ³­¸®³²
  1280. //iDam -= pkChrVictim->GetPoint(POINT_MAGIC_DEF_GRADE);
  1281. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_MAGIC)) / 100;
  1282. break;
  1283.  
  1284. default:
  1285. sys_err("Unknown skill attr type %u vnum %u", m_pkSk->bSkillAttrType, m_pkSk->dwVnum);
  1286. break;
  1287. }
  1288.  
  1289. //
  1290. // 20091109 µ¶ÀÏ ½ºÅ³ ¼Ó¼º ¿äû ÀÛ¾÷
  1291. // ±âÁ¸ ½ºÅ³ Å×ÀÌºí¿¡ SKILL_FLAG_WIND, SKILL_FLAG_ELEC, SKILL_FLAG_FIRE¸¦ °¡Áø ½ºÅ³ÀÌ
  1292. // ÀüÇô ¾ø¾úÀ¸¹Ç·Î ¸ó½ºÅÍÀÇ RESIST_WIND, RESIST_ELEC, RESIST_FIREµµ »ç¿ëµÇÁö ¾Ê°í ÀÖ¾ú´Ù.
  1293. //
  1294. // PvP¿Í PvE¹ë·±½º ºÐ¸®¸¦ À§ÇØ ÀǵµÀûÀ¸·Î NPC¸¸ Àû¿ëÇϵµ·Ï ÇßÀ¸¸ç ±âÁ¸ ¹ë·±½º¿Í Â÷ÀÌÁ¡À»
  1295. // ´À³¢Áö ¸øÇϱâ À§ÇØ mob_protoÀÇ RESIST_MAGICÀ» RESIST_WIND, RESIST_ELEC, RESIST_FIRE·Î
  1296. // º¹»çÇÏ¿´´Ù.
  1297. //
  1298. if (pkChrVictim->IsNPC())
  1299. {
  1300. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_WIND))
  1301. {
  1302. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_WIND)) / 100;
  1303. }
  1304.  
  1305. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_ELEC))
  1306. {
  1307. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_ELEC)) / 100;
  1308. }
  1309.  
  1310. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_FIRE))
  1311. {
  1312. iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_FIRE)) / 100;
  1313. }
  1314. }
  1315.  
  1316. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_COMPUTE_MAGIC_DAMAGE))
  1317. dt = DAMAGE_TYPE_MAGIC;
  1318.  
  1319. if (pkChrVictim->CanBeginFight())
  1320. pkChrVictim->BeginFight(m_pkChr);
  1321.  
  1322. if (m_pkSk->dwVnum == SKILL_CHAIN)
  1323. sys_log(0, "%s CHAIN INDEX %d DAM %d DT %d", m_pkChr->GetName(), m_pkChr->GetChainLightningIndex() - 1, iDam, dt);
  1324.  
  1325. {
  1326. BYTE AntiSkillID = 0;
  1327.  
  1328. switch (m_pkSk->dwVnum)
  1329. {
  1330. case SKILL_TANHWAN: AntiSkillID = SKILL_7_A_ANTI_TANHWAN; break;
  1331. case SKILL_AMSEOP: AntiSkillID = SKILL_7_B_ANTI_AMSEOP; break;
  1332. case SKILL_SWAERYUNG: AntiSkillID = SKILL_7_C_ANTI_SWAERYUNG; break;
  1333. case SKILL_YONGBI: AntiSkillID = SKILL_7_D_ANTI_YONGBI; break;
  1334. case SKILL_GIGONGCHAM: AntiSkillID = SKILL_8_A_ANTI_GIGONGCHAM; break;
  1335. case SKILL_YEONSA: AntiSkillID = SKILL_8_B_ANTI_YEONSA; break;
  1336. case SKILL_MAHWAN: AntiSkillID = SKILL_8_C_ANTI_MAHWAN; break;
  1337. case SKILL_BYEURAK: AntiSkillID = SKILL_8_D_ANTI_BYEURAK; break;
  1338. }
  1339.  
  1340. if (0 != AntiSkillID)
  1341. {
  1342. BYTE AntiSkillLevel = pkChrVictim->GetSkillLevel(AntiSkillID);
  1343.  
  1344. if (0 != AntiSkillLevel)
  1345. {
  1346. CSkillProto* pkSk = CSkillManager::instance().Get(AntiSkillID);
  1347. if (!pkSk)
  1348. {
  1349. sys_err ("There is no anti skill(%d) in skill proto", AntiSkillID);
  1350. }
  1351. else
  1352. {
  1353. pkSk->SetPointVar("k", 1.0f * pkChrVictim->GetSkillPower(AntiSkillID) * pkSk->bMaxLevel / 100);
  1354.  
  1355. double ResistAmount = pkSk->kPointPoly.Eval();
  1356.  
  1357. sys_log(0, "ANTI_SKILL: Resist(%lf) Orig(%d) Reduce(%d)", ResistAmount, iDam, int(iDam * (ResistAmount/100.0)));
  1358.  
  1359. iDam -= iDam * (ResistAmount/100.0);
  1360. }
  1361. }
  1362. }
  1363. }
  1364.  
  1365. if (!pkChrVictim->Damage(m_pkChr, iDam, dt) && !pkChrVictim->IsStun())
  1366. {
  1367. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_REMOVE_GOOD_AFFECT))
  1368. {
  1369. #ifdef ENABLE_NULLIFYAFFECT_LIMIT
  1370. int iLevel = m_pkChr->GetLevel();
  1371. int yLevel = pkChrVictim->GetLevel();
  1372. // const float k = 1.0 * m_pkChr->GetSkillPower(m_pkSk->dwVnum, bSkillLevel) * m_pkSk->bMaxLevel / 100;
  1373. int iDifLev = 9;
  1374. if ((iLevel-iDifLev <= yLevel) && (iLevel+iDifLev >= yLevel))
  1375. #endif
  1376. {
  1377. int iAmount2 = (int) m_pkSk->kPointPoly2.Eval();
  1378. int iDur2 = (int) m_pkSk->kDurationPoly2.Eval();
  1379. iDur2 += m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);
  1380.  
  1381. if (number(1, 100) <= iAmount2)
  1382. {
  1383. pkChrVictim->RemoveGoodAffect();
  1384. pkChrVictim->AddAffect(m_pkSk->dwVnum, POINT_NONE, 0, AFF_PABEOP, iDur2, 0, true);
  1385. }
  1386. }
  1387. }
  1388. #ifdef ENABLE_WOLFMAN_CHARACTER
  1389. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_SLOW | SKILL_FLAG_STUN | SKILL_FLAG_FIRE_CONT | SKILL_FLAG_POISON | SKILL_FLAG_BLEEDING))
  1390. #else
  1391. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_SLOW | SKILL_FLAG_STUN | SKILL_FLAG_FIRE_CONT | SKILL_FLAG_POISON))
  1392. #endif
  1393. {
  1394. int iPct = (int) m_pkSk->kPointPoly2.Eval();
  1395. int iDur = (int) m_pkSk->kDurationPoly2.Eval();
  1396.  
  1397. iDur += m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);
  1398.  
  1399. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_STUN))
  1400. {
  1401. SkillAttackAffect(pkChrVictim, iPct, IMMUNE_STUN, AFFECT_STUN, POINT_NONE, 0, AFF_STUN, iDur, m_pkSk->szName);
  1402. }
  1403. else if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_SLOW))
  1404. {
  1405. SkillAttackAffect(pkChrVictim, iPct, IMMUNE_SLOW, AFFECT_SLOW, POINT_MOV_SPEED, -30, AFF_SLOW, iDur, m_pkSk->szName);
  1406. }
  1407. else if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_FIRE_CONT))
  1408. {
  1409. m_pkSk->SetDurationVar("k", 1.0 * m_bUseSkillPower * m_pkSk->bMaxLevel / 100);
  1410. m_pkSk->SetDurationVar("iq", m_pkChr->GetPoint(POINT_IQ));
  1411.  
  1412. iDur = (int)m_pkSk->kDurationPoly2.Eval();
  1413. int bonus = m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);
  1414.  
  1415. if (bonus != 0)
  1416. {
  1417. iDur += bonus / 2;
  1418. }
  1419.  
  1420. if (number(1, 100) <= iDur)
  1421. {
  1422. pkChrVictim->AttackedByFire(m_pkChr, iPct, 5);
  1423. }
  1424. }
  1425. else if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_POISON))
  1426. {
  1427. if (number(1, 100) <= iPct)
  1428. pkChrVictim->AttackedByPoison(m_pkChr);
  1429. }
  1430. #ifdef ENABLE_WOLFMAN_CHARACTER
  1431. else if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_BLEEDING))
  1432. {
  1433. if (number(1, 100) <= iPct)
  1434. pkChrVictim->AttackedByBleeding(m_pkChr);
  1435. }
  1436. #endif
  1437. }
  1438.  
  1439. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_CRUSH | SKILL_FLAG_CRUSH_LONG) &&
  1440. !IS_SET(pkChrVictim->GetAIFlag(), AIFLAG_NOMOVE))
  1441. {
  1442. float fCrushSlidingLength = 200;
  1443.  
  1444. if (m_pkChr->IsNPC())
  1445. fCrushSlidingLength = 400;
  1446.  
  1447. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_CRUSH_LONG))
  1448. fCrushSlidingLength *= 2;
  1449.  
  1450. float fx, fy;
  1451. float degree = GetDegreeFromPositionXY(m_pkChr->GetX(), m_pkChr->GetY(), pkChrVictim->GetX(), pkChrVictim->GetY());
  1452.  
  1453. if (m_pkSk->dwVnum == SKILL_HORSE_WILDATTACK)
  1454. {
  1455. degree -= m_pkChr->GetRotation();
  1456. degree = fmod(degree, 360.0f) - 180.0f;
  1457.  
  1458. if (degree > 0)
  1459. degree = m_pkChr->GetRotation() + 90.0f;
  1460. else
  1461. degree = m_pkChr->GetRotation() - 90.0f;
  1462. }
  1463.  
  1464. GetDeltaByDegree(degree, fCrushSlidingLength, &fx, &fy);
  1465. sys_log(0, "CRUSH! %s -> %s (%d %d) -> (%d %d)", m_pkChr->GetName(), pkChrVictim->GetName(), pkChrVictim->GetX(), pkChrVictim->GetY(), (long)(pkChrVictim->GetX()+fx), (long)(pkChrVictim->GetY()+fy));
  1466. long tx = (long)(pkChrVictim->GetX()+fx);
  1467. long ty = (long)(pkChrVictim->GetY()+fy);
  1468.  
  1469. pkChrVictim->Sync(tx, ty);
  1470. pkChrVictim->Goto(tx, ty);
  1471. pkChrVictim->CalculateMoveDuration();
  1472.  
  1473. if (m_pkChr->IsPC() && m_pkChr->m_SkillUseInfo[m_pkSk->dwVnum].GetMainTargetVID() == (DWORD) pkChrVictim->GetVID())
  1474. {
  1475. SkillAttackAffect(pkChrVictim, 1000, IMMUNE_STUN, m_pkSk->dwVnum, POINT_NONE, 0, AFF_STUN, 4, m_pkSk->szName);
  1476. }
  1477. else
  1478. {
  1479. pkChrVictim->SyncPacket();
  1480. }
  1481. }
  1482. }
  1483.  
  1484. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_HP_ABSORB))
  1485. {
  1486. int iPct = (int) m_pkSk->kPointPoly2.Eval();
  1487. m_pkChr->PointChange(POINT_HP, iDam * iPct / 100);
  1488. }
  1489.  
  1490. if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_SP_ABSORB))
  1491. {
  1492. int iPct = (int) m_pkSk->kPointPoly2.Eval();
  1493. m_pkChr->PointChange(POINT_SP, iDam * iPct / 100);
  1494. }
  1495.  
  1496. if (m_pkSk->dwVnum == SKILL_CHAIN && m_pkChr->GetChainLightningIndex() < m_pkChr->GetChainLightningMaxCount())
  1497. {
  1498. chain_lightning_event_info* info = AllocEventInfo<chain_lightning_event_info>();
  1499.  
  1500. info->dwVictim = pkChrVictim->GetVID();
  1501. info->dwChr = m_pkChr->GetVID();
  1502.  
  1503. event_create(ChainLightningEvent, info, passes_per_sec / 5);
  1504. }
  1505. if(test_server)
  1506. sys_log(0, "FuncSplashDamage End :%s ", m_pkChr->GetName());
  1507. }
  1508.  
  1509. int m_x;
  1510. int m_y;
  1511. CSkillProto * m_pkSk;
  1512. LPCHARACTER m_pkChr;
  1513. int m_iAmount;
  1514. int m_iAG;
  1515. int m_iCount;
  1516. int m_iMaxHit;
  1517. LPITEM m_pkWeapon;
  1518. bool m_bDisableCooltime;
  1519. TSkillUseInfo* m_pInfo;
  1520. BYTE m_bUseSkillPower;
  1521. };
  1522.  
  1523. struct FuncSplashAffect
  1524. {
  1525. FuncSplashAffect(LPCHARACTER ch, int x, int y, int iDist, DWORD dwVnum, BYTE bPointOn, int iAmount, DWORD dwAffectFlag, int iDuration, int iSPCost, bool bOverride, int iMaxHit)
  1526. {
  1527. m_x = x;
  1528. m_y = y;
  1529. m_iDist = iDist;
  1530. m_dwVnum = dwVnum;
  1531. m_bPointOn = bPointOn;
  1532. m_iAmount = iAmount;
  1533. m_dwAffectFlag = dwAffectFlag;
  1534. m_iDuration = iDuration;
  1535. m_iSPCost = iSPCost;
  1536. m_bOverride = bOverride;
  1537. m_pkChrAttacker = ch;
  1538. m_iMaxHit = iMaxHit;
  1539. m_iCount = 0;
  1540. }
  1541.  
  1542. void operator () (LPENTITY ent)
  1543. {
  1544. if (m_iMaxHit && m_iMaxHit <= m_iCount)
  1545. return;
  1546.  
  1547. if (ent->IsType(ENTITY_CHARACTER))
  1548. {
  1549. LPCHARACTER pkChr = (LPCHARACTER) ent;
  1550.  
  1551. if (test_server)
  1552. sys_log(0, "FuncSplashAffect step 1 : name:%s vnum:%d iDur:%d", pkChr->GetName(), m_dwVnum, m_iDuration);
  1553. if (DISTANCE_APPROX(m_x - pkChr->GetX(), m_y - pkChr->GetY()) < m_iDist)
  1554. {
  1555. if (test_server)
  1556. sys_log(0, "FuncSplashAffect step 2 : name:%s vnum:%d iDur:%d", pkChr->GetName(), m_dwVnum, m_iDuration);
  1557. if (m_dwVnum == SKILL_TUSOK)
  1558. if (pkChr->CanBeginFight())
  1559. pkChr->BeginFight(m_pkChrAttacker);
  1560.  
  1561. if (pkChr->IsPC() && m_dwVnum == SKILL_TUSOK)
  1562. pkChr->AddAffect(m_dwVnum, m_bPointOn, m_iAmount, m_dwAffectFlag, m_iDuration/3, m_iSPCost, m_bOverride);
  1563. else
  1564. pkChr->AddAffect(m_dwVnum, m_bPointOn, m_iAmount, m_dwAffectFlag, m_iDuration, m_iSPCost, m_bOverride);
  1565.  
  1566. m_iCount ++;
  1567. }
  1568. }
  1569. }
  1570.  
  1571. LPCHARACTER m_pkChrAttacker;
  1572. int m_x;
  1573. int m_y;
  1574. int m_iDist;
  1575. DWORD m_dwVnum;
  1576. BYTE m_bPointOn;
  1577. int m_iAmount;
  1578. DWORD m_dwAffectFlag;
  1579. int m_iDuration;
  1580. int m_iSPCost;
  1581. bool m_bOverride;
  1582. int m_iMaxHit;
  1583. int m_iCount;
  1584. };
  1585.  
  1586. EVENTINFO(skill_gwihwan_info)
  1587. {
  1588. DWORD pid;
  1589. BYTE bsklv;
  1590.  
  1591. skill_gwihwan_info()
  1592. : pid( 0 )
  1593. , bsklv( 0 )
  1594. {
  1595. }
  1596. };
  1597.  
  1598. EVENTFUNC(skill_gwihwan_event)
  1599. {
  1600. skill_gwihwan_info* info = dynamic_cast<skill_gwihwan_info*>( event->info );
  1601.  
  1602. if ( info == NULL )
  1603. {
  1604. sys_err( "skill_gwihwan_event> <Factor> Null pointer" );
  1605. return 0;
  1606. }
  1607.  
  1608. DWORD pid = info->pid;
  1609. BYTE sklv= info->bsklv;
  1610. LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pid);
  1611.  
  1612. if (!ch)
  1613. return 0;
  1614.  
  1615. int percent = 20 * sklv - 1;
  1616.  
  1617. if (number(1, 100) <= percent)
  1618. {
  1619. PIXEL_POSITION pos;
  1620.  
  1621. // ¼º°ø
  1622. if (SECTREE_MANAGER::instance().GetRecallPositionByEmpire(ch->GetMapIndex(), ch->GetEmpire(), pos))
  1623. {
  1624. sys_log(1, "Recall: %s %d %d -> %d %d", ch->GetName(), ch->GetX(), ch->GetY(), pos.x, pos.y);
  1625. ch->WarpSet(pos.x, pos.y);
  1626. }
  1627. else
  1628. {
  1629. sys_err("CHARACTER::UseItem : cannot find spawn position (name %s, %d x %d)", ch->GetName(), ch->GetX(), ch->GetY());
  1630. ch->WarpSet(EMPIRE_START_X(ch->GetEmpire()), EMPIRE_START_Y(ch->GetEmpire()));
  1631. }
  1632. }
  1633. else
  1634. {
  1635. //½ÇÆÐ
  1636. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("±Íȯ¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."));
  1637. }
  1638. return 0;
  1639. }
  1640.  
  1641. int CHARACTER::ComputeSkillAtPosition(DWORD dwVnum, const PIXEL_POSITION& posTarget, BYTE bSkillLevel)
  1642. {
  1643. if (GetMountVnum())
  1644. return BATTLE_NONE;
  1645.  
  1646. if (IsPolymorphed())
  1647. return BATTLE_NONE;
  1648.  
  1649. if (g_bSkillDisable)
  1650. return BATTLE_NONE;
  1651.  
  1652. CSkillProto * pkSk = CSkillManager::instance().Get(dwVnum);
  1653.  
  1654. if (!pkSk)
  1655. return BATTLE_NONE;
  1656.  
  1657. if (test_server)
  1658. {
  1659. sys_log(0, "ComputeSkillAtPosition %s vnum %d x %d y %d level %d",
  1660. GetName(), dwVnum, posTarget.x, posTarget.y, bSkillLevel);
  1661. }
  1662.  
  1663. // ³ª¿¡°Ô ¾²´Â ½ºÅ³Àº ³» À§Ä¡¸¦ ¾´´Ù.
  1664. //if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
  1665. // posTarget = GetXYZ();
  1666.  
  1667. // ½ºÇ÷¡½¬°¡ ¾Æ´Ñ ½ºÅ³Àº ÁÖÀ§À̸é ÀÌ»óÇÏ´Ù
  1668. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  1669. return BATTLE_NONE;
  1670.  
  1671. if (0 == bSkillLevel)
  1672. {
  1673. if ((bSkillLevel = GetSkillLevel(pkSk->dwVnum)) == 0)
  1674. {
  1675. return BATTLE_NONE;
  1676. }
  1677. }
  1678.  
  1679. const float k = 1.0 * GetSkillPower(pkSk->dwVnum, bSkillLevel) * pkSk->bMaxLevel / 100;
  1680.  
  1681. pkSk->SetPointVar("k", k);
  1682. pkSk->kSplashAroundDamageAdjustPoly.SetVar("k", k);
  1683.  
  1684. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_MELEE_DAMAGE))
  1685. {
  1686. pkSk->SetPointVar("atk", CalcMeleeDamage(this, this, true, false));
  1687. }
  1688. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_MAGIC_DAMAGE))
  1689. {
  1690. pkSk->SetPointVar("atk", CalcMagicDamage(this, this));
  1691. }
  1692. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_ARROW_DAMAGE))
  1693. {
  1694. LPITEM pkBow, pkArrow;
  1695. if (1 == GetArrowAndBow(&pkBow, &pkArrow, 1))
  1696. {
  1697. pkSk->SetPointVar("atk", CalcArrowDamage(this, this, pkBow, pkArrow, true));
  1698. }
  1699. else
  1700. {
  1701. pkSk->SetPointVar("atk", 0);
  1702. }
  1703. }
  1704.  
  1705. if (pkSk->bPointOn == POINT_MOV_SPEED)
  1706. {
  1707. pkSk->SetPointVar("maxv", this->GetLimitPoint(POINT_MOV_SPEED));
  1708. }
  1709.  
  1710. pkSk->SetPointVar("lv", GetLevel());
  1711. pkSk->SetPointVar("iq", GetPoint(POINT_IQ));
  1712. pkSk->SetPointVar("str", GetPoint(POINT_ST));
  1713. pkSk->SetPointVar("dex", GetPoint(POINT_DX));
  1714. pkSk->SetPointVar("con", GetPoint(POINT_HT));
  1715. pkSk->SetPointVar("maxhp", this->GetMaxHP());
  1716. pkSk->SetPointVar("maxsp", this->GetMaxSP());
  1717. pkSk->SetPointVar("chain", 0);
  1718. pkSk->SetPointVar("ar", CalcAttackRating(this, this));
  1719. pkSk->SetPointVar("def", GetPoint(POINT_DEF_GRADE));
  1720. pkSk->SetPointVar("odef", GetPoint(POINT_DEF_GRADE) - GetPoint(POINT_DEF_GRADE_BONUS));
  1721. pkSk->SetPointVar("horse_level", GetHorseLevel());
  1722.  
  1723. if (pkSk->bSkillAttrType != SKILL_ATTR_TYPE_NORMAL)
  1724. OnMove(true);
  1725.  
  1726. LPITEM pkWeapon = GetWear(WEAR_WEAPON);
  1727.  
  1728. SetPolyVarForAttack(this, pkSk, pkWeapon);
  1729.  
  1730. pkSk->SetDurationVar("k", k/*bSkillLevel*/);
  1731.  
  1732. int iAmount = (int) pkSk->kPointPoly.Eval();
  1733. int iAmount2 = (int) pkSk->kPointPoly2.Eval();
  1734.  
  1735. // ADD_GRANDMASTER_SKILL
  1736. int iAmount3 = (int) pkSk->kPointPoly3.Eval();
  1737.  
  1738. if (GetUsedSkillMasterType(pkSk->dwVnum) >= SKILL_GRAND_MASTER)
  1739. {
  1740. /*
  1741. if (iAmount >= 0)
  1742. iAmount += (int) m_pkSk->kMasterBonusPoly.Eval();
  1743. else
  1744. iAmount -= (int) m_pkSk->kMasterBonusPoly.Eval();
  1745. */
  1746. iAmount = (int) pkSk->kMasterBonusPoly.Eval();
  1747. }
  1748.  
  1749. if (test_server && iAmount == 0 && pkSk->bPointOn != POINT_NONE)
  1750. {
  1751. ChatPacket(CHAT_TYPE_INFO, "È¿°ú°¡ ¾ø½À´Ï´Ù. ½ºÅ³ °ø½ÄÀ» È®ÀÎÇϼ¼¿ä");
  1752. }
  1753.  
  1754. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_REMOVE_BAD_AFFECT))
  1755. {
  1756. if (number(1, 100) <= iAmount2)
  1757. {
  1758. RemoveBadAffect();
  1759. }
  1760. }
  1761. // END_OF_ADD_GRANDMASTER_SKILL
  1762.  
  1763. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK | SKILL_FLAG_USE_MELEE_DAMAGE | SKILL_FLAG_USE_MAGIC_DAMAGE))
  1764. {
  1765. //
  1766. // °ø°Ý ½ºÅ³ÀÏ °æ¿ì
  1767. //
  1768. bool bAdded = false;
  1769.  
  1770. if (pkSk->bPointOn == POINT_HP && iAmount < 0)
  1771. {
  1772. int iAG = 0;
  1773.  
  1774. FuncSplashDamage f(posTarget.x, posTarget.y, pkSk, this, iAmount, iAG, pkSk->lMaxHit, pkWeapon, m_bDisableCooltime, IsPC()?&m_SkillUseInfo[dwVnum]:NULL, GetSkillPower(dwVnum, bSkillLevel));
  1775.  
  1776. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  1777. {
  1778. if (GetSectree())
  1779. GetSectree()->ForEachAround(f);
  1780. }
  1781. else
  1782. {
  1783. //if (dwVnum == SKILL_CHAIN) sys_log(0, "CHAIN skill call FuncSplashDamage %s", GetName());
  1784. f(this);
  1785. }
  1786. }
  1787. else
  1788. {
  1789. //if (dwVnum == SKILL_CHAIN) sys_log(0, "CHAIN skill no damage %d %s", iAmount, GetName());
  1790. int iDur = (int) pkSk->kDurationPoly.Eval();
  1791.  
  1792. if (IsPC())
  1793. if (!(dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)) // ±æµå ½ºÅ³Àº ÄðŸÀÓ Ã³¸®¸¦ ÇÏÁö ¾Ê´Â´Ù.
  1794. if (!m_bDisableCooltime && !m_SkillUseInfo[dwVnum].HitOnce(dwVnum) && dwVnum != SKILL_MUYEONG)
  1795. {
  1796. //if (dwVnum == SKILL_CHAIN) sys_log(0, "CHAIN skill cannot hit %s", GetName());
  1797. return BATTLE_NONE;
  1798. }
  1799.  
  1800.  
  1801. if (iDur > 0)
  1802. {
  1803. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  1804.  
  1805. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  1806. AddAffect(pkSk->dwVnum, pkSk->bPointOn, iAmount, pkSk->dwAffectFlag, iDur, 0, true);
  1807. else
  1808. {
  1809. if (GetSectree())
  1810. {
  1811. FuncSplashAffect f(this, posTarget.x, posTarget.y, pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn, iAmount, pkSk->dwAffectFlag, iDur, 0, true, pkSk->lMaxHit);
  1812. GetSectree()->ForEachAround(f);
  1813. }
  1814. }
  1815. bAdded = true;
  1816. }
  1817. }
  1818.  
  1819. if (pkSk->bPointOn2 != POINT_NONE)
  1820. {
  1821. int iDur = (int) pkSk->kDurationPoly2.Eval();
  1822.  
  1823. sys_log(1, "try second %u %d %d", pkSk->dwVnum, pkSk->bPointOn2, iDur);
  1824.  
  1825. if (iDur > 0)
  1826. {
  1827. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  1828.  
  1829. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  1830. AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur, 0, !bAdded);
  1831. else
  1832. {
  1833. if (GetSectree())
  1834. {
  1835. FuncSplashAffect f(this, posTarget.x, posTarget.y, pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur, 0, !bAdded, pkSk->lMaxHit);
  1836. GetSectree()->ForEachAround(f);
  1837. }
  1838. }
  1839. bAdded = true;
  1840. }
  1841. else
  1842. {
  1843. PointChange(pkSk->bPointOn2, iAmount2);
  1844. }
  1845. }
  1846.  
  1847. // ADD_GRANDMASTER_SKILL
  1848. if (GetUsedSkillMasterType(pkSk->dwVnum) >= SKILL_GRAND_MASTER && pkSk->bPointOn3 != POINT_NONE)
  1849. {
  1850. int iDur = (int) pkSk->kDurationPoly3.Eval();
  1851.  
  1852. if (iDur > 0)
  1853. {
  1854. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  1855.  
  1856. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  1857. AddAffect(pkSk->dwVnum, pkSk->bPointOn3, iAmount3, 0 /*pkSk->dwAffectFlag3*/, iDur, 0, !bAdded);
  1858. else
  1859. {
  1860. if (GetSectree())
  1861. {
  1862. FuncSplashAffect f(this, posTarget.x, posTarget.y, pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn3, iAmount3, 0 /*pkSk->dwAffectFlag3*/, iDur, 0, !bAdded, pkSk->lMaxHit);
  1863. GetSectree()->ForEachAround(f);
  1864. }
  1865. }
  1866. }
  1867. else
  1868. {
  1869. PointChange(pkSk->bPointOn3, iAmount3);
  1870. }
  1871. }
  1872. // END_OF_ADD_GRANDMASTER_SKILL
  1873.  
  1874. return BATTLE_DAMAGE;
  1875. }
  1876. else
  1877. {
  1878. bool bAdded = false;
  1879. int iDur = (int) pkSk->kDurationPoly.Eval();
  1880.  
  1881. if (iDur > 0)
  1882. {
  1883. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  1884. // AffectFlag°¡ ¾ø°Å³ª, toggle ÇÏ´Â °ÍÀÌ ¾Æ´Ï¶ó¸é..
  1885. pkSk->kDurationSPCostPoly.SetVar("k", k/*bSkillLevel*/);
  1886.  
  1887. AddAffect(pkSk->dwVnum,
  1888. pkSk->bPointOn,
  1889. iAmount,
  1890. pkSk->dwAffectFlag,
  1891. iDur,
  1892. (long) pkSk->kDurationSPCostPoly.Eval(),
  1893. !bAdded);
  1894.  
  1895. bAdded = true;
  1896. }
  1897. else
  1898. {
  1899. PointChange(pkSk->bPointOn, iAmount);
  1900. }
  1901.  
  1902. if (pkSk->bPointOn2 != POINT_NONE)
  1903. {
  1904. int iDur = (int) pkSk->kDurationPoly2.Eval();
  1905.  
  1906. if (iDur > 0)
  1907. {
  1908. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  1909. AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur, 0, !bAdded);
  1910. bAdded = true;
  1911. }
  1912. else
  1913. {
  1914. PointChange(pkSk->bPointOn2, iAmount2);
  1915. }
  1916. }
  1917.  
  1918. // ADD_GRANDMASTER_SKILL
  1919. if (GetUsedSkillMasterType(pkSk->dwVnum) >= SKILL_GRAND_MASTER && pkSk->bPointOn3 != POINT_NONE)
  1920. {
  1921. int iDur = (int) pkSk->kDurationPoly3.Eval();
  1922.  
  1923. if (iDur > 0)
  1924. {
  1925. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  1926. AddAffect(pkSk->dwVnum, pkSk->bPointOn3, iAmount3, 0 /*pkSk->dwAffectFlag3*/, iDur, 0, !bAdded);
  1927. }
  1928. else
  1929. {
  1930. PointChange(pkSk->bPointOn3, iAmount3);
  1931. }
  1932. }
  1933. // END_OF_ADD_GRANDMASTER_SKILL
  1934.  
  1935. return BATTLE_NONE;
  1936. }
  1937. }
  1938.  
  1939. #ifdef ENABLE_WOLFMAN_CHARACTER
  1940. struct FComputeSkillParty
  1941. {
  1942. FComputeSkillParty(DWORD dwVnum, LPCHARACTER pkAttacker, BYTE bSkillLevel = 0)
  1943. : m_dwVnum(dwVnum), m_pkAttacker(pkAttacker), m_bSkillLevel(bSkillLevel)
  1944. {
  1945. }
  1946.  
  1947. void operator () (LPCHARACTER ch)
  1948. {
  1949. m_pkAttacker->ComputeSkill(m_dwVnum, ch, m_bSkillLevel);
  1950. }
  1951.  
  1952. DWORD m_dwVnum;
  1953. LPCHARACTER m_pkAttacker;
  1954. BYTE m_bSkillLevel;
  1955. };
  1956.  
  1957. int CHARACTER::ComputeSkillParty(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel)
  1958. {
  1959. FComputeSkillParty f(dwVnum, pkVictim, bSkillLevel);
  1960. if (GetParty() && GetParty()->GetNearMemberCount())
  1961. GetParty()->ForEachNearMember(f);
  1962. else
  1963. f(this);
  1964.  
  1965. return BATTLE_NONE;
  1966. }
  1967. #endif
  1968.  
  1969. // bSkillLevel ÀÎÀÚ°¡ 0ÀÌ ¾Æ´Ò °æ¿ì¿¡´Â m_abSkillLevels¸¦ »ç¿ëÇÏÁö ¾Ê°í °­Á¦·Î
  1970. // bSkillLevel·Î °è»êÇÑ´Ù.
  1971. int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel)
  1972. {
  1973. const bool bCanUseHorseSkill = CanUseHorseSkill();
  1974.  
  1975. // ¸»À» Ÿ°íÀÖÁö¸¸ ½ºÅ³Àº »ç¿ëÇÒ ¼ö ¾ø´Â »óŶó¸é return
  1976. if (false == bCanUseHorseSkill && true == IsRiding())
  1977. return BATTLE_NONE;
  1978.  
  1979. if (IsPolymorphed())
  1980. return BATTLE_NONE;
  1981.  
  1982. if (g_bSkillDisable)
  1983. return BATTLE_NONE;
  1984.  
  1985. CSkillProto* pkSk = CSkillManager::instance().Get(dwVnum);
  1986.  
  1987. if (!pkSk)
  1988. return BATTLE_NONE;
  1989.  
  1990. if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE)
  1991. return BATTLE_NONE;
  1992.  
  1993. if (!bCanUseHorseSkill && pkSk->dwType == SKILL_TYPE_HORSE)
  1994. return BATTLE_NONE;
  1995.  
  1996.  
  1997. // »ó´ë¹æ¿¡°Ô ¾²´Â °ÍÀÌ ¾Æ´Ï¸é ³ª¿¡°Ô ½á¾ß ÇÑ´Ù.
  1998. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
  1999. pkVictim = this;
  2000. // #ifdef ENABLE_WOLFMAN_CHARACTER
  2001. // else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY))
  2002. // pkVictim = this;
  2003. // #endif
  2004.  
  2005. if (!pkVictim)
  2006. {
  2007. if (test_server)
  2008. sys_log(0, "ComputeSkill: %s Victim == null, skill %d", GetName(), dwVnum);
  2009.  
  2010. return BATTLE_NONE;
  2011. }
  2012.  
  2013. if (pkSk->dwTargetRange && DISTANCE_SQRT(GetX() - pkVictim->GetX(), GetY() - pkVictim->GetY()) >= pkSk->dwTargetRange + 50)
  2014. {
  2015. if (test_server)
  2016. sys_log(0, "ComputeSkill: Victim too far, skill %d : %s to %s (distance %u limit %u)",
  2017. dwVnum,
  2018. GetName(),
  2019. pkVictim->GetName(),
  2020. (long)DISTANCE_SQRT(GetX() - pkVictim->GetX(), GetY() - pkVictim->GetY()),
  2021. pkSk->dwTargetRange);
  2022.  
  2023. return BATTLE_NONE;
  2024. }
  2025.  
  2026. if (0 == bSkillLevel)
  2027. {
  2028. if ((bSkillLevel = GetSkillLevel(pkSk->dwVnum)) == 0)
  2029. {
  2030. if (test_server)
  2031. sys_log(0, "ComputeSkill : name:%s vnum:%d skillLevelBySkill : %d ", GetName(), pkSk->dwVnum, bSkillLevel);
  2032. return BATTLE_NONE;
  2033. }
  2034. }
  2035.  
  2036. if (pkVictim->IsAffectFlag(AFF_PABEOP) && pkVictim->IsGoodAffect(dwVnum))
  2037. {
  2038. return BATTLE_NONE;
  2039. }
  2040.  
  2041. const float k = 1.0 * GetSkillPower(pkSk->dwVnum, bSkillLevel) * pkSk->bMaxLevel / 100;
  2042.  
  2043. pkSk->SetPointVar("k", k);
  2044. pkSk->kSplashAroundDamageAdjustPoly.SetVar("k", k);
  2045.  
  2046. if (pkSk->dwType == SKILL_TYPE_HORSE)
  2047. {
  2048. LPITEM pkBow, pkArrow;
  2049. if (1 == GetArrowAndBow(&pkBow, &pkArrow, 1))
  2050. {
  2051. pkSk->SetPointVar("atk", CalcArrowDamage(this, pkVictim, pkBow, pkArrow, true));
  2052. }
  2053. else
  2054. {
  2055. pkSk->SetPointVar("atk", CalcMeleeDamage(this, pkVictim, true, false));
  2056. }
  2057. }
  2058. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_MELEE_DAMAGE))
  2059. {
  2060. pkSk->SetPointVar("atk", CalcMeleeDamage(this, pkVictim, true, false));
  2061. }
  2062. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_MAGIC_DAMAGE))
  2063. {
  2064. pkSk->SetPointVar("atk", CalcMagicDamage(this, pkVictim));
  2065. }
  2066. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_ARROW_DAMAGE))
  2067. {
  2068. LPITEM pkBow, pkArrow;
  2069. if (1 == GetArrowAndBow(&pkBow, &pkArrow, 1))
  2070. {
  2071. pkSk->SetPointVar("atk", CalcArrowDamage(this, pkVictim, pkBow, pkArrow, true));
  2072. }
  2073. else
  2074. {
  2075. pkSk->SetPointVar("atk", 0);
  2076. }
  2077. }
  2078.  
  2079. if (pkSk->bPointOn == POINT_MOV_SPEED)
  2080. {
  2081. pkSk->SetPointVar("maxv", pkVictim->GetLimitPoint(POINT_MOV_SPEED));
  2082. }
  2083.  
  2084. pkSk->SetPointVar("lv", GetLevel());
  2085. pkSk->SetPointVar("iq", GetPoint(POINT_IQ));
  2086. pkSk->SetPointVar("str", GetPoint(POINT_ST));
  2087. pkSk->SetPointVar("dex", GetPoint(POINT_DX));
  2088. pkSk->SetPointVar("con", GetPoint(POINT_HT));
  2089. pkSk->SetPointVar("maxhp", pkVictim->GetMaxHP());
  2090. pkSk->SetPointVar("maxsp", pkVictim->GetMaxSP());
  2091. pkSk->SetPointVar("chain", 0);
  2092. pkSk->SetPointVar("ar", CalcAttackRating(this, pkVictim));
  2093. pkSk->SetPointVar("def", GetPoint(POINT_DEF_GRADE));
  2094. pkSk->SetPointVar("odef", GetPoint(POINT_DEF_GRADE) - GetPoint(POINT_DEF_GRADE_BONUS));
  2095. pkSk->SetPointVar("horse_level", GetHorseLevel());
  2096.  
  2097. if (pkSk->bSkillAttrType != SKILL_ATTR_TYPE_NORMAL)
  2098. OnMove(true);
  2099.  
  2100. LPITEM pkWeapon = GetWear(WEAR_WEAPON);
  2101.  
  2102. SetPolyVarForAttack(this, pkSk, pkWeapon);
  2103.  
  2104. pkSk->kDurationPoly.SetVar("k", k/*bSkillLevel*/);
  2105. pkSk->kDurationPoly2.SetVar("k", k/*bSkillLevel*/);
  2106.  
  2107. int iAmount = (int) pkSk->kPointPoly.Eval();
  2108. int iAmount2 = (int) pkSk->kPointPoly2.Eval();
  2109. int iAmount3 = (int) pkSk->kPointPoly3.Eval();
  2110.  
  2111. if (test_server && IsPC())
  2112. sys_log(0, "iAmount: %d %d %d , atk:%f skLevel:%f k:%f GetSkillPower(%d) MaxLevel:%d Per:%f",
  2113. iAmount, iAmount2, iAmount3,
  2114. pkSk->kPointPoly.GetVar("atk"),
  2115. pkSk->kPointPoly.GetVar("k"),
  2116. k,
  2117. GetSkillPower(pkSk->dwVnum, bSkillLevel),
  2118. pkSk->bMaxLevel,
  2119. pkSk->bMaxLevel/100
  2120. );
  2121.  
  2122. // ADD_GRANDMASTER_SKILL
  2123. if (GetUsedSkillMasterType(pkSk->dwVnum) >= SKILL_GRAND_MASTER)
  2124. {
  2125. iAmount = (int) pkSk->kMasterBonusPoly.Eval();
  2126. }
  2127.  
  2128. if (test_server && iAmount == 0 && pkSk->bPointOn != POINT_NONE)
  2129. {
  2130. ChatPacket(CHAT_TYPE_INFO, "È¿°ú°¡ ¾ø½À´Ï´Ù. ½ºÅ³ °ø½ÄÀ» È®ÀÎÇϼ¼¿ä");
  2131. }
  2132. // END_OF_ADD_GRANDMASTER_SKILL
  2133.  
  2134. //sys_log(0, "XXX SKILL Calc %d Amount %d", dwVnum, iAmount);
  2135.  
  2136. // REMOVE_BAD_AFFECT_BUG_FIX
  2137. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_REMOVE_BAD_AFFECT))
  2138. {
  2139. if (number(1, 100) <= iAmount2)
  2140. {
  2141. pkVictim->RemoveBadAffect();
  2142. }
  2143. }
  2144. // END_OF_REMOVE_BAD_AFFECT_BUG_FIX
  2145.  
  2146. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK | SKILL_FLAG_USE_MELEE_DAMAGE | SKILL_FLAG_USE_MAGIC_DAMAGE) &&
  2147. !(pkSk->dwVnum == SKILL_MUYEONG && pkVictim == this) && !(pkSk->IsChargeSkill() && pkVictim == this))
  2148. {
  2149. bool bAdded = false;
  2150.  
  2151. if (pkSk->bPointOn == POINT_HP && iAmount < 0)
  2152. {
  2153. int iAG = 0;
  2154.  
  2155.  
  2156. FuncSplashDamage f(pkVictim->GetX(), pkVictim->GetY(), pkSk, this, iAmount, iAG, pkSk->lMaxHit, pkWeapon, m_bDisableCooltime, IsPC()?&m_SkillUseInfo[dwVnum]:NULL, GetSkillPower(dwVnum, bSkillLevel));
  2157. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  2158. {
  2159. if (pkVictim->GetSectree())
  2160. pkVictim->GetSectree()->ForEachAround(f);
  2161. }
  2162. else
  2163. {
  2164. f(pkVictim);
  2165. }
  2166. }
  2167. else
  2168. {
  2169. pkSk->kDurationPoly.SetVar("k", k/*bSkillLevel*/);
  2170. int iDur = (int) pkSk->kDurationPoly.Eval();
  2171.  
  2172.  
  2173. if (IsPC())
  2174. if (!(dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)) // ±æµå ½ºÅ³Àº ÄðŸÀÓ Ã³¸®¸¦ ÇÏÁö ¾Ê´Â´Ù.
  2175. if (!m_bDisableCooltime && !m_SkillUseInfo[dwVnum].HitOnce(dwVnum) && dwVnum != SKILL_MUYEONG)
  2176. {
  2177. return BATTLE_NONE;
  2178. }
  2179.  
  2180. if (iDur > 0)
  2181. {
  2182. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2183.  
  2184. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  2185. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn, iAmount, pkSk->dwAffectFlag, iDur, 0, true);
  2186. else
  2187. {
  2188. if (pkVictim->GetSectree())
  2189. {
  2190. FuncSplashAffect f(this, pkVictim->GetX(), pkVictim->GetY(), pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn, iAmount, pkSk->dwAffectFlag, iDur, 0, true, pkSk->lMaxHit);
  2191. pkVictim->GetSectree()->ForEachAround(f);
  2192. }
  2193. }
  2194. bAdded = true;
  2195. }
  2196. }
  2197.  
  2198. if (pkSk->bPointOn2 != POINT_NONE && !pkSk->IsChargeSkill())
  2199. {
  2200. pkSk->kDurationPoly2.SetVar("k", k/*bSkillLevel*/);
  2201. int iDur = (int) pkSk->kDurationPoly2.Eval();
  2202.  
  2203. if (iDur > 0)
  2204. {
  2205. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2206.  
  2207. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  2208. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur, 0, !bAdded);
  2209. else
  2210. {
  2211. if (pkVictim->GetSectree())
  2212. {
  2213. FuncSplashAffect f(this, pkVictim->GetX(), pkVictim->GetY(), pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur, 0, !bAdded, pkSk->lMaxHit);
  2214. pkVictim->GetSectree()->ForEachAround(f);
  2215. }
  2216. }
  2217.  
  2218. bAdded = true;
  2219. }
  2220. else
  2221. {
  2222. pkVictim->PointChange(pkSk->bPointOn2, iAmount2);
  2223. }
  2224. }
  2225.  
  2226. // ADD_GRANDMASTER_SKILL
  2227. if (pkSk->bPointOn3 != POINT_NONE && !pkSk->IsChargeSkill() && GetUsedSkillMasterType(pkSk->dwVnum) >= SKILL_GRAND_MASTER)
  2228. {
  2229. pkSk->kDurationPoly3.SetVar("k", k/*bSkillLevel*/);
  2230. int iDur = (int) pkSk->kDurationPoly3.Eval();
  2231.  
  2232.  
  2233. if (iDur > 0)
  2234. {
  2235. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2236.  
  2237. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  2238. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn3, iAmount3, /*pkSk->dwAffectFlag3*/ 0, iDur, 0, !bAdded);
  2239. else
  2240. {
  2241. if (pkVictim->GetSectree())
  2242. {
  2243. FuncSplashAffect f(this, pkVictim->GetX(), pkVictim->GetY(), pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn3, iAmount3, /*pkSk->dwAffectFlag3*/ 0, iDur, 0, !bAdded, pkSk->lMaxHit);
  2244. pkVictim->GetSectree()->ForEachAround(f);
  2245. }
  2246. }
  2247.  
  2248. bAdded = true;
  2249. }
  2250. else
  2251. {
  2252. pkVictim->PointChange(pkSk->bPointOn3, iAmount3);
  2253. }
  2254. }
  2255. // END_OF_ADD_GRANDMASTER_SKILL
  2256.  
  2257. return BATTLE_DAMAGE;
  2258. }
  2259. else
  2260. {
  2261. if (dwVnum == SKILL_MUYEONG)
  2262. {
  2263. pkSk->kDurationPoly.SetVar("k", k/*bSkillLevel*/);
  2264. pkSk->kDurationSPCostPoly.SetVar("k", k/*bSkillLevel*/);
  2265.  
  2266. int iDur = (long) pkSk->kDurationPoly.Eval();
  2267. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2268.  
  2269. if (pkVictim == this)
  2270. AddAffect(dwVnum,
  2271. POINT_NONE, 0,
  2272. AFF_MUYEONG,
  2273. iDur,
  2274. (long) pkSk->kDurationSPCostPoly.Eval(),
  2275. true);
  2276.  
  2277. return BATTLE_NONE;
  2278. }
  2279.  
  2280. bool bAdded = false;
  2281. pkSk->kDurationPoly.SetVar("k", k/*bSkillLevel*/);
  2282. int iDur = (int) pkSk->kDurationPoly.Eval();
  2283.  
  2284. if (iDur > 0)
  2285. {
  2286. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2287. // AffectFlag°¡ ¾ø°Å³ª, toggle ÇÏ´Â °ÍÀÌ ¾Æ´Ï¶ó¸é..
  2288. pkSk->kDurationSPCostPoly.SetVar("k", k/*bSkillLevel*/);
  2289.  
  2290. if (pkSk->bPointOn2 != POINT_NONE)
  2291. {
  2292. pkVictim->RemoveAffect(pkSk->dwVnum);
  2293.  
  2294. int iDur2 = (int) pkSk->kDurationPoly2.Eval();
  2295.  
  2296. if (iDur2 > 0)
  2297. {
  2298. if (test_server)
  2299. sys_log(0, "SKILL_AFFECT: %s %s Dur:%d To:%d Amount:%d",
  2300. GetName(),
  2301. pkSk->szName,
  2302. iDur2,
  2303. pkSk->bPointOn2,
  2304. iAmount2);
  2305.  
  2306. iDur2 += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2307. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur2, 0, false);
  2308. }
  2309. else
  2310. {
  2311. pkVictim->PointChange(pkSk->bPointOn2, iAmount2);
  2312. }
  2313.  
  2314. DWORD affact_flag = pkSk->dwAffectFlag;
  2315.  
  2316. // ADD_GRANDMASTER_SKILL
  2317. if ((pkSk->dwVnum == SKILL_CHUNKEON && GetUsedSkillMasterType(pkSk->dwVnum) < SKILL_GRAND_MASTER))
  2318. affact_flag = AFF_CHEONGEUN_WITH_FALL;
  2319. // END_OF_ADD_GRANDMASTER_SKILL
  2320.  
  2321. pkVictim->AddAffect(pkSk->dwVnum,
  2322. pkSk->bPointOn,
  2323. iAmount,
  2324. affact_flag,
  2325. iDur,
  2326. (long) pkSk->kDurationSPCostPoly.Eval(),
  2327. false);
  2328. }
  2329. else
  2330. {
  2331. if (test_server)
  2332. sys_log(0, "SKILL_AFFECT: %s %s Dur:%d To:%d Amount:%d",
  2333. GetName(),
  2334. pkSk->szName,
  2335. iDur,
  2336. pkSk->bPointOn,
  2337. iAmount);
  2338.  
  2339. pkVictim->AddAffect(pkSk->dwVnum,
  2340. pkSk->bPointOn,
  2341. iAmount,
  2342. pkSk->dwAffectFlag,
  2343. iDur,
  2344. (long) pkSk->kDurationSPCostPoly.Eval(),
  2345. // ADD_GRANDMASTER_SKILL
  2346. !bAdded);
  2347. // END_OF_ADD_GRANDMASTER_SKILL
  2348. }
  2349.  
  2350. bAdded = true;
  2351. }
  2352. else
  2353. {
  2354. if (!pkSk->IsChargeSkill())
  2355. pkVictim->PointChange(pkSk->bPointOn, iAmount);
  2356.  
  2357. if (pkSk->bPointOn2 != POINT_NONE)
  2358. {
  2359. pkVictim->RemoveAffect(pkSk->dwVnum);
  2360.  
  2361. int iDur2 = (int) pkSk->kDurationPoly2.Eval();
  2362.  
  2363. if (iDur2 > 0)
  2364. {
  2365. iDur2 += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2366.  
  2367. if (pkSk->IsChargeSkill())
  2368. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, AFF_TANHWAN_DASH, iDur2, 0, false);
  2369. else
  2370. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn2, iAmount2, pkSk->dwAffectFlag2, iDur2, 0, false);
  2371. }
  2372. else
  2373. {
  2374. pkVictim->PointChange(pkSk->bPointOn2, iAmount2);
  2375. }
  2376.  
  2377. }
  2378. }
  2379.  
  2380. // ADD_GRANDMASTER_SKILL
  2381. if (pkSk->bPointOn3 != POINT_NONE && !pkSk->IsChargeSkill() && GetUsedSkillMasterType(pkSk->dwVnum) >= SKILL_GRAND_MASTER)
  2382. {
  2383.  
  2384. pkSk->kDurationPoly3.SetVar("k", k/*bSkillLevel*/);
  2385. int iDur = (int) pkSk->kDurationPoly3.Eval();
  2386.  
  2387. sys_log(0, "try third %u %d %d %d 1894", pkSk->dwVnum, pkSk->bPointOn3, iDur, iAmount3);
  2388.  
  2389. if (iDur > 0)
  2390. {
  2391. iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
  2392.  
  2393. if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
  2394. pkVictim->AddAffect(pkSk->dwVnum, pkSk->bPointOn3, iAmount3, /*pkSk->dwAffectFlag3*/ 0, iDur, 0, !bAdded);
  2395. else
  2396. {
  2397. if (pkVictim->GetSectree())
  2398. {
  2399. FuncSplashAffect f(this, pkVictim->GetX(), pkVictim->GetY(), pkSk->iSplashRange, pkSk->dwVnum, pkSk->bPointOn3, iAmount3, /*pkSk->dwAffectFlag3*/ 0, iDur, 0, !bAdded, pkSk->lMaxHit);
  2400. pkVictim->GetSectree()->ForEachAround(f);
  2401. }
  2402. }
  2403.  
  2404. bAdded = true;
  2405. }
  2406. else
  2407. {
  2408. pkVictim->PointChange(pkSk->bPointOn3, iAmount3);
  2409. }
  2410. }
  2411. // END_OF_ADD_GRANDMASTER_SKILL
  2412.  
  2413. return BATTLE_NONE;
  2414. }
  2415. }
  2416.  
  2417. bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaster)
  2418. {
  2419. if (false == CanUseSkill(dwVnum))
  2420. return false;
  2421.  
  2422. // NO_GRANDMASTER
  2423. if (test_server)
  2424. {
  2425. if (quest::CQuestManager::instance().GetEventFlag("no_grand_master"))
  2426. {
  2427. bUseGrandMaster = false;
  2428. }
  2429. }
  2430. // END_OF_NO_GRANDMASTER
  2431.  
  2432. if (g_bSkillDisable)
  2433. return false;
  2434.  
  2435. if (IsObserverMode())
  2436. return false;
  2437.  
  2438. if (!CanMove())
  2439. return false;
  2440.  
  2441. if (IsPolymorphed())
  2442. return false;
  2443.  
  2444. const bool bCanUseHorseSkill = CanUseHorseSkill();
  2445.  
  2446.  
  2447. if (dwVnum == SKILL_HORSE_SUMMON)
  2448. {
  2449. if (GetSkillLevel(dwVnum) == 0)
  2450. return false;
  2451.  
  2452. if (GetHorseLevel() <= 0)
  2453. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¸»ÀÌ ¾ø½À´Ï´Ù. ¸¶±Â°£ °æºñº´À» ã¾Æ°¡¼¼¿ä."));
  2454. else
  2455. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¸» ¼Òȯ ¾ÆÀÌÅÛÀ» »ç¿ëÇϼ¼¿ä."));
  2456.  
  2457. return true;
  2458. }
  2459.  
  2460. // ¸»À» Ÿ°íÀÖÁö¸¸ ½ºÅ³Àº »ç¿ëÇÒ ¼ö ¾ø´Â »óŶó¸é return false
  2461. if (false == bCanUseHorseSkill && true == IsRiding())
  2462. return false;
  2463.  
  2464. CSkillProto * pkSk = CSkillManager::instance().Get(dwVnum);
  2465. sys_log(0, "%s: USE_SKILL: %d pkVictim %p", GetName(), dwVnum, get_pointer(pkVictim));
  2466.  
  2467. if (!pkSk)
  2468. return false;
  2469.  
  2470. if (bCanUseHorseSkill && pkSk->dwType != SKILL_TYPE_HORSE)
  2471. return BATTLE_NONE;
  2472.  
  2473. if (!bCanUseHorseSkill && pkSk->dwType == SKILL_TYPE_HORSE)
  2474. return BATTLE_NONE;
  2475.  
  2476. if (GetSkillLevel(dwVnum) == 0)
  2477. return false;
  2478.  
  2479.  
  2480. // NO_GRANDMASTER
  2481. if (GetSkillMasterType(dwVnum) < SKILL_GRAND_MASTER)
  2482. bUseGrandMaster = false;
  2483. // END_OF_NO_GRANDMASTER
  2484.  
  2485. // MINING
  2486. if (GetWear(WEAR_WEAPON) && (GetWear(WEAR_WEAPON)->GetType() == ITEM_ROD || GetWear(WEAR_WEAPON)->GetType() == ITEM_PICK))
  2487. return false;
  2488. // END_OF_MINING
  2489.  
  2490. m_SkillUseInfo[dwVnum].TargetVIDMap.clear();
  2491.  
  2492. if (pkSk->IsChargeSkill())
  2493. {
  2494. if ((IsAffectFlag(AFF_TANHWAN_DASH)) || (pkVictim && (pkVictim != this)))
  2495. {
  2496. if (!pkVictim)
  2497. return false;
  2498.  
  2499. if (!IsAffectFlag(AFF_TANHWAN_DASH))
  2500. {
  2501. if (!UseSkill(dwVnum, this))
  2502. return false;
  2503. }
  2504.  
  2505. m_SkillUseInfo[dwVnum].SetMainTargetVID(pkVictim->GetVID());
  2506. // DASH »óÅÂÀÇ ÅºÈ¯°ÝÀº °ø°Ý±â¼ú
  2507. ComputeSkill(dwVnum, pkVictim);
  2508. RemoveAffect(dwVnum);
  2509. return true;
  2510. }
  2511. }
  2512.  
  2513. if (dwVnum == SKILL_COMBO)
  2514. {
  2515. if (m_bComboIndex)
  2516. m_bComboIndex = 0;
  2517. else
  2518. m_bComboIndex = GetSkillLevel(SKILL_COMBO);
  2519.  
  2520. ChatPacket(CHAT_TYPE_COMMAND, "combo %d", m_bComboIndex);
  2521. return true;
  2522. }
  2523.  
  2524. // Toggle ÇÒ ¶§´Â SP¸¦ ¾²Áö ¾ÊÀ½ (SelfOnly·Î ±¸ºÐ)
  2525. if ((0 != pkSk->dwAffectFlag || pkSk->dwVnum == SKILL_MUYEONG) && (pkSk->dwFlag & SKILL_FLAG_TOGGLE) && RemoveAffect(pkSk->dwVnum))
  2526. {
  2527. return true;
  2528. }
  2529.  
  2530. if (IsAffectFlag(AFF_REVIVE_INVISIBLE))
  2531. RemoveAffect(AFFECT_REVIVE_INVISIBLE);
  2532.  
  2533. const float k = 1.0 * GetSkillPower(pkSk->dwVnum) * pkSk->bMaxLevel / 100;
  2534.  
  2535. pkSk->SetPointVar("k", k);
  2536. pkSk->kSplashAroundDamageAdjustPoly.SetVar("k", k);
  2537.  
  2538. // ÄðŸÀÓ Ã¼Å©
  2539. pkSk->kCooldownPoly.SetVar("k", k);
  2540. int iCooltime = (int) pkSk->kCooldownPoly.Eval();
  2541. int lMaxHit = pkSk->lMaxHit ? pkSk->lMaxHit : -1;
  2542.  
  2543. pkSk->SetSPCostVar("k", k);
  2544.  
  2545. DWORD dwCur = get_dword_time();
  2546.  
  2547. if (dwVnum == SKILL_TERROR && m_SkillUseInfo[dwVnum].bUsed && m_SkillUseInfo[dwVnum].dwNextSkillUsableTime > dwCur )
  2548. {
  2549. sys_log(0, " SKILL_TERROR's Cooltime is not delta over %u", m_SkillUseInfo[dwVnum].dwNextSkillUsableTime - dwCur );
  2550. return false;
  2551. }
  2552.  
  2553. int iNeededSP = 0;
  2554.  
  2555. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_USE_HP_AS_COST))
  2556. {
  2557. pkSk->SetSPCostVar("maxhp", GetMaxHP());
  2558. pkSk->SetSPCostVar("v", GetHP());
  2559. iNeededSP = (int) pkSk->kSPCostPoly.Eval();
  2560.  
  2561. // ADD_GRANDMASTER_SKILL
  2562. if (GetSkillMasterType(dwVnum) >= SKILL_GRAND_MASTER && bUseGrandMaster)
  2563. {
  2564. iNeededSP = (int) pkSk->kGrandMasterAddSPCostPoly.Eval();
  2565. }
  2566. // END_OF_ADD_GRANDMASTER_SKILL
  2567.  
  2568. if (GetHP() < iNeededSP)
  2569. return false;
  2570.  
  2571. PointChange(POINT_HP, -iNeededSP);
  2572. }
  2573. else
  2574. {
  2575. // SKILL_FOMULA_REFACTORING
  2576. pkSk->SetSPCostVar("maxhp", GetMaxHP());
  2577. pkSk->SetSPCostVar("maxv", GetMaxSP());
  2578. pkSk->SetSPCostVar("v", GetSP());
  2579.  
  2580. iNeededSP = (int) pkSk->kSPCostPoly.Eval();
  2581.  
  2582. if (GetSkillMasterType(dwVnum) >= SKILL_GRAND_MASTER && bUseGrandMaster)
  2583. {
  2584. iNeededSP = (int) pkSk->kGrandMasterAddSPCostPoly.Eval();
  2585. }
  2586. // END_OF_SKILL_FOMULA_REFACTORING
  2587.  
  2588. if (GetSP() < iNeededSP)
  2589. return false;
  2590.  
  2591. if (test_server)
  2592. ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s SP¼Ò¸ð: %d"), pkSk->szName, iNeededSP);
  2593.  
  2594. PointChange(POINT_SP, -iNeededSP);
  2595. }
  2596.  
  2597. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
  2598. pkVictim = this;
  2599. #ifdef ENABLE_WOLFMAN_CHARACTER
  2600. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY))
  2601. pkVictim = this;
  2602. #endif
  2603.  
  2604. if ((pkSk->dwVnum == SKILL_MUYEONG) || (pkSk->IsChargeSkill() && !IsAffectFlag(AFF_TANHWAN_DASH) && !pkVictim))
  2605. {
  2606. // óÀ½ »ç¿ëÇÏ´Â ¹«¿µÁøÀº Àڽſ¡°Ô Affect¸¦ ºÙÀδÙ.
  2607. pkVictim = this;
  2608. }
  2609.  
  2610. int iSplashCount = 1;
  2611.  
  2612. if (false == m_bDisableCooltime)
  2613. {
  2614. if (false ==
  2615. m_SkillUseInfo[dwVnum].UseSkill(
  2616. bUseGrandMaster,
  2617. (NULL != pkVictim && SKILL_HORSE_WILDATTACK != dwVnum) ? pkVictim->GetVID() : NULL,
  2618. ComputeCooltime(iCooltime * 1000),
  2619. iSplashCount,
  2620. lMaxHit))
  2621. {
  2622. if (test_server)
  2623. ChatPacket(CHAT_TYPE_NOTICE, "cooltime not finished %s %d", pkSk->szName, iCooltime);
  2624.  
  2625. return false;
  2626. }
  2627. }
  2628.  
  2629. if (dwVnum == SKILL_CHAIN)
  2630. {
  2631. ResetChainLightningIndex();
  2632. AddChainLightningExcept(pkVictim);
  2633. }
  2634.  
  2635.  
  2636. if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
  2637. ComputeSkill(dwVnum, this);
  2638. #ifdef ENABLE_WOLFMAN_CHARACTER
  2639. else if (IS_SET(pkSk->dwFlag, SKILL_FLAG_PARTY))
  2640. ComputeSkillParty(dwVnum, this);
  2641. #endif
  2642. else if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK))
  2643. ComputeSkill(dwVnum, pkVictim);
  2644. else if (dwVnum == SKILL_BYEURAK)
  2645. ComputeSkill(dwVnum, pkVictim);
  2646. else if (dwVnum == SKILL_MUYEONG || pkSk->IsChargeSkill())
  2647. ComputeSkill(dwVnum, pkVictim);
  2648.  
  2649. m_dwLastSkillTime = get_dword_time();
  2650.  
  2651. return true;
  2652. }
  2653.  
  2654. int CHARACTER::GetUsedSkillMasterType(DWORD dwVnum)
  2655. {
  2656. const TSkillUseInfo& rInfo = m_SkillUseInfo[dwVnum];
  2657.  
  2658. if (GetSkillMasterType(dwVnum) < SKILL_GRAND_MASTER)
  2659. return GetSkillMasterType(dwVnum);
  2660.  
  2661. if (rInfo.isGrandMaster)
  2662. return GetSkillMasterType(dwVnum);
  2663.  
  2664. return MIN(GetSkillMasterType(dwVnum), SKILL_MASTER);
  2665. }
  2666.  
  2667. int CHARACTER::GetSkillMasterType(DWORD dwVnum) const
  2668. {
  2669. if (!IsPC())
  2670. return 0;
  2671.  
  2672. if (dwVnum >= SKILL_MAX_NUM)
  2673. {
  2674. sys_err("%s skill vnum overflow %u", GetName(), dwVnum);
  2675. return 0;
  2676. }
  2677.  
  2678. return m_pSkillLevels ? m_pSkillLevels[dwVnum].bMasterType:SKILL_NORMAL;
  2679. }
  2680.  
  2681. int CHARACTER::GetSkillPower(DWORD dwVnum, BYTE bLevel) const
  2682. {
  2683. // Àξî¹ÝÁö ¾ÆÀÌÅÛ
  2684. if (dwVnum >= SKILL_LANGUAGE1 && dwVnum <= SKILL_LANGUAGE3 && IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
  2685. {
  2686. return 100;
  2687. }
  2688.  
  2689. if (dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)
  2690. {
  2691. if (GetGuild())
  2692. return 100 * GetGuild()->GetSkillLevel(dwVnum) / 7 / 7;
  2693. else
  2694. return 0;
  2695. }
  2696.  
  2697. if (bLevel)
  2698. {
  2699. //SKILL_POWER_BY_LEVEL
  2700. return GetSkillPowerByLevel(bLevel, true);
  2701. //END_SKILL_POWER_BY_LEVEL;
  2702. }
  2703.  
  2704. if (dwVnum >= SKILL_MAX_NUM)
  2705. {
  2706. sys_err("%s skill vnum overflow %u", GetName(), dwVnum);
  2707. return 0;
  2708. }
  2709.  
  2710. //SKILL_POWER_BY_LEVEL
  2711. return GetSkillPowerByLevel(GetSkillLevel(dwVnum));
  2712. //SKILL_POWER_BY_LEVEL
  2713. }
  2714.  
  2715. int CHARACTER::GetSkillLevel(DWORD dwVnum) const
  2716. {
  2717. if (dwVnum >= SKILL_MAX_NUM)
  2718. {
  2719. sys_err("%s skill vnum overflow %u", GetName(), dwVnum);
  2720. sys_log(0, "%s skill vnum overflow %u", GetName(), dwVnum);
  2721. return 0;
  2722. }
  2723.  
  2724. return MIN(SKILL_MAX_LEVEL, m_pSkillLevels ? m_pSkillLevels[dwVnum].bLevel : 0);
  2725. }
  2726.  
  2727. EVENTFUNC(skill_muyoung_event)
  2728. {
  2729. char_event_info* info = dynamic_cast<char_event_info*>( event->info );
  2730.  
  2731. if ( info == NULL )
  2732. {
  2733. sys_err( "skill_muyoung_event> <Factor> Null pointer" );
  2734. return 0;
  2735. }
  2736.  
  2737. LPCHARACTER ch = info->ch;
  2738.  
  2739. if (ch == NULL) { // <Factor>
  2740. return 0;
  2741. }
  2742.  
  2743. if (!ch->IsAffectFlag(AFF_MUYEONG))
  2744. {
  2745. ch->StopMuyeongEvent();
  2746. return 0;
  2747. }
  2748.  
  2749. // 1. Find Victim
  2750. FFindNearVictim f(ch, ch);
  2751. if (ch->GetSectree())
  2752. {
  2753. ch->GetSectree()->ForEachAround(f);
  2754. // 2. Shoot!
  2755. if (f.GetVictim())
  2756. {
  2757. ch->CreateFly(FLY_SKILL_MUYEONG, f.GetVictim());
  2758. ch->ComputeSkill(SKILL_MUYEONG, f.GetVictim());
  2759. }
  2760. }
  2761.  
  2762. return PASSES_PER_SEC(3);
  2763. }
  2764.  
  2765. void CHARACTER::StartMuyeongEvent()
  2766. {
  2767. if (m_pkMuyeongEvent)
  2768. return;
  2769.  
  2770. char_event_info* info = AllocEventInfo<char_event_info>();
  2771.  
  2772. info->ch = this;
  2773. m_pkMuyeongEvent = event_create(skill_muyoung_event, info, PASSES_PER_SEC(1));
  2774. }
  2775.  
  2776. void CHARACTER::StopMuyeongEvent()
  2777. {
  2778. event_cancel(&m_pkMuyeongEvent);
  2779. }
  2780.  
  2781. void CHARACTER::SkillLearnWaitMoreTimeMessage(DWORD ms)
  2782. {
  2783. int horas;
  2784. int minutos;
  2785. int segundos;
  2786. horas = (int)(ms / 3600);
  2787. minutos = (int)((ms - horas * 3600) / 60);
  2788. segundos = ms - (horas * 3600 + minutos * 60);
  2789. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("__book__"));
  2790. ChatPacket(CHAT_TYPE_TALKING, LC_TEXT("book_ %d:%d:%d"), horas, minutos, segundos);
  2791. }
  2792.  
  2793. void CHARACTER::DisableCooltime()
  2794. {
  2795. m_bDisableCooltime = true;
  2796. }
  2797.  
  2798. bool CHARACTER::HasMobSkill() const
  2799. {
  2800. return CountMobSkill() > 0;
  2801. }
  2802.  
  2803. size_t CHARACTER::CountMobSkill() const
  2804. {
  2805. if (!m_pkMobData)
  2806. return 0;
  2807.  
  2808. size_t c = 0;
  2809.  
  2810. for (size_t i = 0; i < MOB_SKILL_MAX_NUM; ++i)
  2811. if (m_pkMobData->m_table.Skills[i].dwVnum)
  2812. ++c;
  2813.  
  2814. return c;
  2815. }
  2816.  
  2817. const TMobSkillInfo* CHARACTER::GetMobSkill(unsigned int idx) const
  2818. {
  2819. if (idx >= MOB_SKILL_MAX_NUM)
  2820. return NULL;
  2821.  
  2822. if (!m_pkMobData)
  2823. return NULL;
  2824.  
  2825. if (0 == m_pkMobData->m_table.Skills[idx].dwVnum)
  2826. return NULL;
  2827.  
  2828. return &m_pkMobData->m_mobSkillInfo[idx];
  2829. }
  2830.  
  2831. bool CHARACTER::CanUseMobSkill(unsigned int idx) const
  2832. {
  2833. const TMobSkillInfo* pInfo = GetMobSkill(idx);
  2834.  
  2835. if (!pInfo)
  2836. return false;
  2837.  
  2838. if (m_adwMobSkillCooltime[idx] > get_dword_time())
  2839. return false;
  2840.  
  2841. if (number(0, 1))
  2842. return false;
  2843.  
  2844. return true;
  2845. }
  2846.  
  2847. EVENTINFO(mob_skill_event_info)
  2848. {
  2849. DynamicCharacterPtr ch;
  2850. PIXEL_POSITION pos;
  2851. DWORD vnum;
  2852. int index;
  2853. BYTE level;
  2854.  
  2855. mob_skill_event_info()
  2856. : ch()
  2857. , pos()
  2858. , vnum(0)
  2859. , index(0)
  2860. , level(0)
  2861. {
  2862. }
  2863. };
  2864.  
  2865. EVENTFUNC(mob_skill_hit_event)
  2866. {
  2867. mob_skill_event_info * info = dynamic_cast<mob_skill_event_info *>( event->info );
  2868.  
  2869. if ( info == NULL )
  2870. {
  2871. sys_err( "mob_skill_event_info> <Factor> Null pointer" );
  2872. return 0;
  2873. }
  2874.  
  2875. // <Factor>
  2876. LPCHARACTER ch = info->ch;
  2877. if (ch == NULL) {
  2878. return 0;
  2879. }
  2880.  
  2881. ch->ComputeSkillAtPosition(info->vnum, info->pos, info->level);
  2882. ch->m_mapMobSkillEvent.erase(info->index);
  2883.  
  2884. return 0;
  2885. }
  2886.  
  2887. bool CHARACTER::UseMobSkill(unsigned int idx)
  2888. {
  2889. if (IsPC())
  2890. return false;
  2891.  
  2892. const TMobSkillInfo* pInfo = GetMobSkill(idx);
  2893.  
  2894. if (!pInfo)
  2895. return false;
  2896.  
  2897. DWORD dwVnum = pInfo->dwSkillVnum;
  2898. CSkillProto * pkSk = CSkillManager::instance().Get(dwVnum);
  2899.  
  2900. if (!pkSk)
  2901. return false;
  2902.  
  2903. const float k = 1.0 * GetSkillPower(pkSk->dwVnum, pInfo->bSkillLevel) * pkSk->bMaxLevel / 100;
  2904.  
  2905. pkSk->kCooldownPoly.SetVar("k", k);
  2906. int iCooltime = (int) (pkSk->kCooldownPoly.Eval() * 1000);
  2907.  
  2908. m_adwMobSkillCooltime[idx] = get_dword_time() + iCooltime;
  2909.  
  2910. sys_log(0, "USE_MOB_SKILL: %s idx %d vnum %u cooltime %d", GetName(), idx, dwVnum, iCooltime);
  2911.  
  2912. if (m_pkMobData->m_mobSkillInfo[idx].vecSplashAttack.empty())
  2913. {
  2914. sys_err("No skill hit data for mob %s index %d", GetName(), idx);
  2915. return false;
  2916. }
  2917.  
  2918. for (size_t i = 0; i < m_pkMobData->m_mobSkillInfo[idx].vecSplashAttack.size(); i++)
  2919. {
  2920. PIXEL_POSITION pos = GetXYZ();
  2921. const TMobSplashAttackInfo& rInfo = m_pkMobData->m_mobSkillInfo[idx].vecSplashAttack[i];
  2922.  
  2923. if (rInfo.dwHitDistance)
  2924. {
  2925. float fx, fy;
  2926. GetDeltaByDegree(GetRotation(), rInfo.dwHitDistance, &fx, &fy);
  2927. pos.x += (long) fx;
  2928. pos.y += (long) fy;
  2929. }
  2930.  
  2931. if (rInfo.dwTiming)
  2932. {
  2933. if (test_server)
  2934. sys_log(0, " timing %ums", rInfo.dwTiming);
  2935.  
  2936. mob_skill_event_info* info = AllocEventInfo<mob_skill_event_info>();
  2937.  
  2938. info->ch = this;
  2939. info->pos = pos;
  2940. info->level = pInfo->bSkillLevel;
  2941. info->vnum = dwVnum;
  2942. info->index = i;
  2943.  
  2944. // <Factor> Cancel existing event first
  2945. itertype(m_mapMobSkillEvent) it = m_mapMobSkillEvent.find(i);
  2946. if (it != m_mapMobSkillEvent.end()) {
  2947. LPEVENT existing = it->second;
  2948. event_cancel(&existing);
  2949. m_mapMobSkillEvent.erase(it);
  2950. }
  2951.  
  2952. m_mapMobSkillEvent.insert(std::make_pair(i, event_create(mob_skill_hit_event, info, PASSES_PER_SEC(rInfo.dwTiming) / 1000)));
  2953. }
  2954. else
  2955. {
  2956. ComputeSkillAtPosition(dwVnum, pos, pInfo->bSkillLevel);
  2957. }
  2958. }
  2959.  
  2960. return true;
  2961. }
  2962.  
  2963. void CHARACTER::ResetMobSkillCooltime()
  2964. {
  2965. memset(m_adwMobSkillCooltime, 0, sizeof(m_adwMobSkillCooltime));
  2966. }
  2967.  
  2968. bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
  2969. {
  2970. DWORD selfJobGroup = (GetJob()+1) * 10 + GetSkillGroup();
  2971. #ifdef ENABLE_WOLFMAN_CHARACTER
  2972. const DWORD SKILL_NUM = 176;
  2973. #else
  2974. const DWORD SKILL_NUM = 158;
  2975. #endif
  2976. static DWORD s_anSkill2JobGroup[SKILL_NUM] = {
  2977. 0, // common_skill 0
  2978. 11, // job_skill 1
  2979. 11, // job_skill 2
  2980. 11, // job_skill 3
  2981. 11, // job_skill 4
  2982. 11, // job_skill 5
  2983. 11, // job_skill 6
  2984. 0, // common_skill 7
  2985. 0, // common_skill 8
  2986. 0, // common_skill 9
  2987. 0, // common_skill 10
  2988. 0, // common_skill 11
  2989. 0, // common_skill 12
  2990. 0, // common_skill 13
  2991. 0, // common_skill 14
  2992. 0, // common_skill 15
  2993. 12, // job_skill 16
  2994. 12, // job_skill 17
  2995. 12, // job_skill 18
  2996. 12, // job_skill 19
  2997. 12, // job_skill 20
  2998. 12, // job_skill 21
  2999. 0, // common_skill 22
  3000. 0, // common_skill 23
  3001. 0, // common_skill 24
  3002. 0, // common_skill 25
  3003. 0, // common_skill 26
  3004. 0, // common_skill 27
  3005. 0, // common_skill 28
  3006. 0, // common_skill 29
  3007. 0, // common_skill 30
  3008. 21, // job_skill 31
  3009. 21, // job_skill 32
  3010. 21, // job_skill 33
  3011. 21, // job_skill 34
  3012. 21, // job_skill 35
  3013. 21, // job_skill 36
  3014. 0, // common_skill 37
  3015. 0, // common_skill 38
  3016. 0, // common_skill 39
  3017. 0, // common_skill 40
  3018. 0, // common_skill 41
  3019. 0, // common_skill 42
  3020. 0, // common_skill 43
  3021. 0, // common_skill 44
  3022. 0, // common_skill 45
  3023. 22, // job_skill 46
  3024. 22, // job_skill 47
  3025. 22, // job_skill 48
  3026. 22, // job_skill 49
  3027. 22, // job_skill 50
  3028. 22, // job_skill 51
  3029. 0, // common_skill 52
  3030. 0, // common_skill 53
  3031. 0, // common_skill 54
  3032. 0, // common_skill 55
  3033. 0, // common_skill 56
  3034. 0, // common_skill 57
  3035. 0, // common_skill 58
  3036. 0, // common_skill 59
  3037. 0, // common_skill 60
  3038. 31, // job_skill 61
  3039. 31, // job_skill 62
  3040. 31, // job_skill 63
  3041. 31, // job_skill 64
  3042. 31, // job_skill 65
  3043. 31, // job_skill 66
  3044. 0, // common_skill 67
  3045. 0, // common_skill 68
  3046. 0, // common_skill 69
  3047. 0, // common_skill 70
  3048. 0, // common_skill 71
  3049. 0, // common_skill 72
  3050. 0, // common_skill 73
  3051. 0, // common_skill 74
  3052. 0, // common_skill 75
  3053. 32, // job_skill 76
  3054. 32, // job_skill 77
  3055. 32, // job_skill 78
  3056. 32, // job_skill 79
  3057. 32, // job_skill 80
  3058. 32, // job_skill 81
  3059. 0, // common_skill 82
  3060. 0, // common_skill 83
  3061. 0, // common_skill 84
  3062. 0, // common_skill 85
  3063. 0, // common_skill 86
  3064. 0, // common_skill 87
  3065. 0, // common_skill 88
  3066. 0, // common_skill 89
  3067. 0, // common_skill 90
  3068. 41, // job_skill 91
  3069. 41, // job_skill 92
  3070. 41, // job_skill 93
  3071. 41, // job_skill 94
  3072. 41, // job_skill 95
  3073. 41, // job_skill 96
  3074. 0, // common_skill 97
  3075. 0, // common_skill 98
  3076. 0, // common_skill 99
  3077. 0, // common_skill 100
  3078. 0, // common_skill 101
  3079. 0, // common_skill 102
  3080. 0, // common_skill 103
  3081. 0, // common_skill 104
  3082. 0, // common_skill 105
  3083. 42, // job_skill 106
  3084. 42, // job_skill 107
  3085. 42, // job_skill 108
  3086. 42, // job_skill 109
  3087. 42, // job_skill 110
  3088. 42, // job_skill 111
  3089. 0, // common_skill 112
  3090. 0, // common_skill 113
  3091. 0, // common_skill 114
  3092. 0, // common_skill 115
  3093. 0, // common_skill 116
  3094. 0, // common_skill 117
  3095. 0, // common_skill 118
  3096. 0, // common_skill 119
  3097. 0, // common_skill 120
  3098. 0, // common_skill 121
  3099. 0, // common_skill 122
  3100. 0, // common_skill 123
  3101. 0, // common_skill 124
  3102. 0, // common_skill 125
  3103. 0, // common_skill 126
  3104. 0, // common_skill 127
  3105. 0, // common_skill 128
  3106. 0, // common_skill 129
  3107. 0, // common_skill 130
  3108. 0, // common_skill 131
  3109. 0, // common_skill 132
  3110. 0, // common_skill 133
  3111. 0, // common_skill 134
  3112. 0, // common_skill 135
  3113. 0, // common_skill 136
  3114. 0, // job_skill 137
  3115. 0, // job_skill 138
  3116. 0, // job_skill 139
  3117. 0, // job_skill 140
  3118. 0, // common_skill 141
  3119. 0, // common_skill 142
  3120. 0, // common_skill 143
  3121. 0, // common_skill 144
  3122. 0, // common_skill 145
  3123. 0, // common_skill 146
  3124. 0, // common_skill 147
  3125. 0, // common_skill 148
  3126. 0, // common_skill 149
  3127. 0, // common_skill 150
  3128. 0, // common_skill 151
  3129. 0, // job_skill 152
  3130. 0, // job_skill 153
  3131. 0, // job_skill 154
  3132. 0, // job_skill 155
  3133. 0, // job_skill 156
  3134. 0, // job_skill 157
  3135. #ifdef ENABLE_WOLFMAN_CHARACTER
  3136. 0, // empty(reserved) 158
  3137. 0, // empty(reserved) 159
  3138. 0, // empty(reserved) 160
  3139. 0, // empty(reserved) 161
  3140. 0, // empty(reserved) 162
  3141. 0, // empty(reserved) 163
  3142. 0, // empty(reserved) 164
  3143. 0, // empty(reserved) 165
  3144. 0, // empty(reserved) 166
  3145. 0, // empty(reserved) 167
  3146. 0, // empty(reserved) 168
  3147. 0, // empty(reserved) 169
  3148. 51, // job_skill(WOLFMAN SKILL) 170
  3149. 51, // job_skill(WOLFMAN SKILL) 171
  3150. 51, // job_skill(WOLFMAN SKILL) 172
  3151. 51, // job_skill(WOLFMAN SKILL) 173
  3152. 51, // job_skill(WOLFMAN SKILL) 174
  3153. 51, // job_skill(WOLFMAN SKILL) 175
  3154. #endif
  3155. }; // s_anSkill2JobGroup
  3156.  
  3157. const DWORD MOTION_MAX_NUM = 124;
  3158. #ifdef ENABLE_WOLFMAN_CHARACTER
  3159. const DWORD SKILL_LIST_MAX_COUNT = 6;
  3160. #else
  3161. const DWORD SKILL_LIST_MAX_COUNT = 5;
  3162. #endif
  3163. static DWORD s_anMotion2SkillVnumList[MOTION_MAX_NUM][SKILL_LIST_MAX_COUNT] =
  3164. {
  3165. // ½ºÅ³¼ö ¹«»ç½ºÅ³ID ÀÚ°´½ºÅ³ID ¼ö¶ó½ºÅ³ID ¹«´ç½ºÅ³ID ¼öÀÎÁ·(WOLFMAN) ½ºÅ³ID
  3166. { 0, 0, 0, 0, 0 }, // 0
  3167.  
  3168. // 1¹ø Á÷±º ±âº» ½ºÅ³
  3169. #ifdef ENABLE_WOLFMAN_CHARACTER
  3170. { 5, 1, 31, 61, 91, 170 }, // 1
  3171. { 5, 2, 32, 62, 92, 171 }, // 2
  3172. { 5, 3, 33, 63, 93, 172 }, // 3
  3173. { 5, 4, 34, 64, 94, 173 }, // 4
  3174. { 5, 5, 35, 65, 95, 174 }, // 5
  3175. { 5, 6, 36, 66, 96, 175 }, // 6
  3176. #else
  3177. { 4, 1, 31, 61, 91 }, // 1
  3178. { 4, 2, 32, 62, 92 }, // 2
  3179. { 4, 3, 33, 63, 93 }, // 3
  3180. { 4, 4, 34, 64, 94 }, // 4
  3181. { 4, 5, 35, 65, 95 }, // 5
  3182. { 4, 6, 36, 66, 96 }, // 6
  3183. #endif
  3184. { 0, 0, 0, 0, 0 }, // 7
  3185. { 0, 0, 0, 0, 0 }, // 8
  3186. // 1¹ø Á÷±º ±âº» ½ºÅ³ ³¡
  3187.  
  3188. // ¿©À¯ºÐ
  3189. { 0, 0, 0, 0, 0 }, // 9
  3190. { 0, 0, 0, 0, 0 }, // 10
  3191. { 0, 0, 0, 0, 0 }, // 11
  3192. { 0, 0, 0, 0, 0 }, // 12
  3193. { 0, 0, 0, 0, 0 }, // 13
  3194. { 0, 0, 0, 0, 0 }, // 14
  3195. { 0, 0, 0, 0, 0 }, // 15
  3196. // ¿©À¯ºÐ ³¡
  3197.  
  3198. // 2¹ø Á÷±º ±âº» ½ºÅ³
  3199. { 4, 16, 46, 76, 106 }, // 16
  3200. { 4, 17, 47, 77, 107 }, // 17
  3201. { 4, 18, 48, 78, 108 }, // 18
  3202. { 4, 19, 49, 79, 109 }, // 19
  3203. { 4, 20, 50, 80, 110 }, // 20
  3204. { 4, 21, 51, 81, 111 }, // 21
  3205. { 0, 0, 0, 0, 0 }, // 22
  3206. { 0, 0, 0, 0, 0 }, // 23
  3207. // 2¹ø Á÷±º ±âº» ½ºÅ³ ³¡
  3208.  
  3209. // ¿©À¯ºÐ
  3210. { 0, 0, 0, 0, 0 }, // 24
  3211. { 0, 0, 0, 0, 0 }, // 25
  3212. // ¿©À¯ºÐ ³¡
  3213.  
  3214. // 1¹ø Á÷±º ¸¶½ºÅÍ ½ºÅ³
  3215. #ifdef ENABLE_WOLFMAN_CHARACTER
  3216. { 5, 1, 31, 61, 91, 170 }, // 26
  3217. { 5, 2, 32, 62, 92, 171 }, // 27
  3218. { 5, 3, 33, 63, 93, 172 }, // 28
  3219. { 5, 4, 34, 64, 94, 173 }, // 29
  3220. { 5, 5, 35, 65, 95, 174 }, // 30
  3221. { 5, 6, 36, 66, 96, 175 }, // 31
  3222. #else
  3223. { 4, 1, 31, 61, 91 }, // 26
  3224. { 4, 2, 32, 62, 92 }, // 27
  3225. { 4, 3, 33, 63, 93 }, // 28
  3226. { 4, 4, 34, 64, 94 }, // 29
  3227. { 4, 5, 35, 65, 95 }, // 30
  3228. { 4, 6, 36, 66, 96 }, // 31
  3229. #endif
  3230. { 0, 0, 0, 0, 0 }, // 32
  3231. { 0, 0, 0, 0, 0 }, // 33
  3232. // 1¹ø Á÷±º ¸¶½ºÅÍ ½ºÅ³ ³¡
  3233.  
  3234. // ¿©À¯ºÐ
  3235. { 0, 0, 0, 0, 0 }, // 34
  3236. { 0, 0, 0, 0, 0 }, // 35
  3237. { 0, 0, 0, 0, 0 }, // 36
  3238. { 0, 0, 0, 0, 0 }, // 37
  3239. { 0, 0, 0, 0, 0 }, // 38
  3240. { 0, 0, 0, 0, 0 }, // 39
  3241. { 0, 0, 0, 0, 0 }, // 40
  3242. // ¿©À¯ºÐ ³¡
  3243.  
  3244. // 2¹ø Á÷±º ¸¶½ºÅÍ ½ºÅ³
  3245. { 4, 16, 46, 76, 106 }, // 41
  3246. { 4, 17, 47, 77, 107 }, // 42
  3247. { 4, 18, 48, 78, 108 }, // 43
  3248. { 4, 19, 49, 79, 109 }, // 44
  3249. { 4, 20, 50, 80, 110 }, // 45
  3250. { 4, 21, 51, 81, 111 }, // 46
  3251. { 0, 0, 0, 0, 0 }, // 47
  3252. { 0, 0, 0, 0, 0 }, // 48
  3253. // 2¹ø Á÷±º ¸¶½ºÅÍ ½ºÅ³ ³¡
  3254.  
  3255. // ¿©À¯ºÐ
  3256. { 0, 0, 0, 0, 0 }, // 49
  3257. { 0, 0, 0, 0, 0 }, // 50
  3258. // ¿©À¯ºÐ ³¡
  3259.  
  3260. // 1¹ø Á÷±º ±×·£µå ¸¶½ºÅÍ ½ºÅ³
  3261. #ifdef ENABLE_WOLFMAN_CHARACTER
  3262. { 5, 1, 31, 61, 91, 170 }, // 51
  3263. { 5, 2, 32, 62, 92, 171 }, // 52
  3264. { 5, 3, 33, 63, 93, 172 }, // 53
  3265. { 5, 4, 34, 64, 94, 173 }, // 54
  3266. { 5, 5, 35, 65, 95, 174 }, // 55
  3267. { 5, 6, 36, 66, 96, 175 }, // 56
  3268. #else
  3269. { 4, 1, 31, 61, 91 }, // 51
  3270. { 4, 2, 32, 62, 92 }, // 52
  3271. { 4, 3, 33, 63, 93 }, // 53
  3272. { 4, 4, 34, 64, 94 }, // 54
  3273. { 4, 5, 35, 65, 95 }, // 55
  3274. { 4, 6, 36, 66, 96 }, // 56
  3275. #endif
  3276. { 0, 0, 0, 0, 0 }, // 57
  3277. { 0, 0, 0, 0, 0 }, // 58
  3278. // 1¹ø Á÷±º ±×·£µå ¸¶½ºÅÍ ½ºÅ³ ³¡
  3279.  
  3280. // ¿©À¯ºÐ
  3281. { 0, 0, 0, 0, 0 }, // 59
  3282. { 0, 0, 0, 0, 0 }, // 60
  3283. { 0, 0, 0, 0, 0 }, // 61
  3284. { 0, 0, 0, 0, 0 }, // 62
  3285. { 0, 0, 0, 0, 0 }, // 63
  3286. { 0, 0, 0, 0, 0 }, // 64
  3287. { 0, 0, 0, 0, 0 }, // 65
  3288. // ¿©À¯ºÐ ³¡
  3289.  
  3290. // 2¹ø Á÷±º ±×·£µå ¸¶½ºÅÍ ½ºÅ³
  3291. { 4, 16, 46, 76, 106 }, // 66
  3292. { 4, 17, 47, 77, 107 }, // 67
  3293. { 4, 18, 48, 78, 108 }, // 68
  3294. { 4, 19, 49, 79, 109 }, // 69
  3295. { 4, 20, 50, 80, 110 }, // 70
  3296. { 4, 21, 51, 81, 111 }, // 71
  3297. { 0, 0, 0, 0, 0 }, // 72
  3298. { 0, 0, 0, 0, 0 }, // 73
  3299. // 2¹ø Á÷±º ±×·£µå ¸¶½ºÅÍ ½ºÅ³ ³¡
  3300.  
  3301. //¿©À¯ºÐ
  3302. { 0, 0, 0, 0, 0 }, // 74
  3303. { 0, 0, 0, 0, 0 }, // 75
  3304. // ¿©À¯ºÐ ³¡
  3305.  
  3306. // 1¹ø Á÷±º ÆÛÆåÆ® ¸¶½ºÅÍ ½ºÅ³
  3307. #ifdef ENABLE_WOLFMAN_CHARACTER
  3308. { 5, 1, 31, 61, 91, 170 }, // 76
  3309. { 5, 2, 32, 62, 92, 171 }, // 77
  3310. { 5, 3, 33, 63, 93, 172 }, // 78
  3311. { 5, 4, 34, 64, 94, 173 }, // 79
  3312. { 5, 5, 35, 65, 95, 174 }, // 80
  3313. { 5, 6, 36, 66, 96, 175 }, // 81
  3314. #else
  3315. { 4, 1, 31, 61, 91 }, // 76
  3316. { 4, 2, 32, 62, 92 }, // 77
  3317. { 4, 3, 33, 63, 93 }, // 78
  3318. { 4, 4, 34, 64, 94 }, // 79
  3319. { 4, 5, 35, 65, 95 }, // 80
  3320. { 4, 6, 36, 66, 96 }, // 81
  3321. #endif
  3322. { 0, 0, 0, 0, 0 }, // 82
  3323. { 0, 0, 0, 0, 0 }, // 83
  3324. // 1¹ø Á÷±º ÆÛÆåÆ® ¸¶½ºÅÍ ½ºÅ³ ³¡
  3325.  
  3326. // ¿©À¯ºÐ
  3327. { 0, 0, 0, 0, 0 }, // 84
  3328. { 0, 0, 0, 0, 0 }, // 85
  3329. { 0, 0, 0, 0, 0 }, // 86
  3330. { 0, 0, 0, 0, 0 }, // 87
  3331. { 0, 0, 0, 0, 0 }, // 88
  3332. { 0, 0, 0, 0, 0 }, // 89
  3333. { 0, 0, 0, 0, 0 }, // 90
  3334. // ¿©À¯ºÐ ³¡
  3335.  
  3336. // 2¹ø Á÷±º ÆÛÆåÆ® ¸¶½ºÅÍ ½ºÅ³
  3337. { 4, 16, 46, 76, 106 }, // 91
  3338. { 4, 17, 47, 77, 107 }, // 92
  3339. { 4, 18, 48, 78, 108 }, // 93
  3340. { 4, 19, 49, 79, 109 }, // 94
  3341. { 4, 20, 50, 80, 110 }, // 95
  3342. { 4, 21, 51, 81, 111 }, // 96
  3343. { 0, 0, 0, 0, 0 }, // 97
  3344. { 0, 0, 0, 0, 0 }, // 98
  3345. // 2¹ø Á÷±º ÆÛÆåÆ® ¸¶½ºÅÍ ½ºÅ³ ³¡
  3346.  
  3347. // ¿©À¯ºÐ
  3348. { 0, 0, 0, 0, 0 }, // 99
  3349. { 0, 0, 0, 0, 0 }, // 100
  3350. // ¿©À¯ºÐ ³¡
  3351.  
  3352. // ±æµå ½ºÅ³
  3353. { 1, 152, 0, 0, 0}, // 101
  3354. { 1, 153, 0, 0, 0}, // 102
  3355. { 1, 154, 0, 0, 0}, // 103
  3356. { 1, 155, 0, 0, 0}, // 104
  3357. { 1, 156, 0, 0, 0}, // 105
  3358. { 1, 157, 0, 0, 0}, // 106
  3359. // ±æµå ½ºÅ³ ³¡
  3360.  
  3361. // ¿©À¯ºÐ
  3362. { 0, 0, 0, 0, 0}, // 107
  3363. { 0, 0, 0, 0, 0}, // 108
  3364. { 0, 0, 0, 0, 0}, // 109
  3365. { 0, 0, 0, 0, 0}, // 110
  3366. { 0, 0, 0, 0, 0}, // 111
  3367. { 0, 0, 0, 0, 0}, // 112
  3368. { 0, 0, 0, 0, 0}, // 113
  3369. { 0, 0, 0, 0, 0}, // 114
  3370. { 0, 0, 0, 0, 0}, // 115
  3371. { 0, 0, 0, 0, 0}, // 116
  3372. { 0, 0, 0, 0, 0}, // 117
  3373. { 0, 0, 0, 0, 0}, // 118
  3374. { 0, 0, 0, 0, 0}, // 119
  3375. { 0, 0, 0, 0, 0}, // 120
  3376. // ¿©À¯ºÐ ³¡
  3377.  
  3378. // ½Â¸¶ ½ºÅ³
  3379. { 2, 137, 140, 0, 0}, // 121
  3380. { 1, 138, 0, 0, 0}, // 122
  3381. { 1, 139, 0, 0, 0}, // 123
  3382. // ½Â¸¶ ½ºÅ³ ³¡
  3383. };
  3384.  
  3385. if (dwMotionIndex >= MOTION_MAX_NUM)
  3386. {
  3387. sys_err("OUT_OF_MOTION_VNUM: name=%s, motion=%d/%d", GetName(), dwMotionIndex, MOTION_MAX_NUM);
  3388. return false;
  3389. }
  3390.  
  3391. DWORD* skillVNums = s_anMotion2SkillVnumList[dwMotionIndex];
  3392.  
  3393. DWORD skillCount = *skillVNums++;
  3394. if (skillCount >= SKILL_LIST_MAX_COUNT)
  3395. {
  3396. sys_err("OUT_OF_SKILL_LIST: name=%s, count=%d/%d", GetName(), skillCount, SKILL_LIST_MAX_COUNT);
  3397. return false;
  3398. }
  3399.  
  3400. for (DWORD skillIndex = 0; skillIndex != skillCount; ++skillIndex)
  3401. {
  3402. if (skillIndex >= SKILL_MAX_NUM)
  3403. {
  3404. sys_err("OUT_OF_SKILL_VNUM: name=%s, skill=%d/%d", GetName(), skillIndex, SKILL_MAX_NUM);
  3405. return false;
  3406. }
  3407.  
  3408. DWORD eachSkillVNum = skillVNums[skillIndex];
  3409. if ( eachSkillVNum != 0 )
  3410. {
  3411. DWORD eachJobGroup = s_anSkill2JobGroup[eachSkillVNum];
  3412.  
  3413. if (0 == eachJobGroup || eachJobGroup == selfJobGroup)
  3414. {
  3415. // GUILDSKILL_BUG_FIX
  3416. DWORD eachSkillLevel = 0;
  3417.  
  3418. if (eachSkillVNum >= GUILD_SKILL_START && eachSkillVNum <= GUILD_SKILL_END)
  3419. {
  3420. if (GetGuild())
  3421. eachSkillLevel = GetGuild()->GetSkillLevel(eachSkillVNum);
  3422. else
  3423. eachSkillLevel = 0;
  3424. }
  3425. else
  3426. {
  3427. eachSkillLevel = GetSkillLevel(eachSkillVNum);
  3428. }
  3429.  
  3430. if (eachSkillLevel > 0)
  3431. {
  3432. return true;
  3433. }
  3434. // END_OF_GUILDSKILL_BUG_FIX
  3435. }
  3436. }
  3437. }
  3438.  
  3439. return false;
  3440. }
  3441.  
  3442. void CHARACTER::ClearSkill()
  3443. {
  3444. PointChange(POINT_SKILL, 4 + (GetLevel() - 5) - GetPoint(POINT_SKILL));
  3445.  
  3446. ResetSkill();
  3447. }
  3448.  
  3449. void CHARACTER::ClearSubSkill()
  3450. {
  3451. PointChange(POINT_SUB_SKILL, GetLevel() < 10 ? 0 : (GetLevel() - 9) - GetPoint(POINT_SUB_SKILL));
  3452.  
  3453. if (m_pSkillLevels == NULL)
  3454. {
  3455. sys_err("m_pSkillLevels nil (name: %s)", GetName());
  3456. return;
  3457. }
  3458.  
  3459. TPlayerSkill CleanSkill;
  3460. memset(&CleanSkill, 0, sizeof(TPlayerSkill));
  3461.  
  3462. size_t count = sizeof(s_adwSubSkillVnums) / sizeof(s_adwSubSkillVnums[0]);
  3463.  
  3464. for (size_t i = 0; i < count; ++i)
  3465. {
  3466. if (s_adwSubSkillVnums[i] >= SKILL_MAX_NUM)
  3467. continue;
  3468.  
  3469. m_pSkillLevels[s_adwSubSkillVnums[i]] = CleanSkill;
  3470. }
  3471.  
  3472. ComputePoints();
  3473. SkillLevelPacket();
  3474. }
  3475.  
  3476. bool CHARACTER::ResetOneSkill(DWORD dwVnum)
  3477. {
  3478. if (NULL == m_pSkillLevels)
  3479. {
  3480. sys_err("m_pSkillLevels nil (name %s, vnum %u)", GetName(), dwVnum);
  3481. return false;
  3482. }
  3483.  
  3484. if (dwVnum >= SKILL_MAX_NUM)
  3485. {
  3486. sys_err("vnum overflow (name %s, vnum %u)", GetName(), dwVnum);
  3487. return false;
  3488. }
  3489.  
  3490. BYTE level = m_pSkillLevels[dwVnum].bLevel;
  3491.  
  3492. m_pSkillLevels[dwVnum].bLevel = 0;
  3493. m_pSkillLevels[dwVnum].bMasterType = 0;
  3494. m_pSkillLevels[dwVnum].tNextRead = 0;
  3495.  
  3496. if (level > 17)
  3497. level = 17;
  3498.  
  3499. PointChange(POINT_SKILL, level);
  3500.  
  3501. LogManager::instance().CharLog(this, dwVnum, "ONE_SKILL_RESET_BY_SCROLL", "");
  3502.  
  3503. ComputePoints();
  3504. SkillLevelPacket();
  3505.  
  3506. return true;
  3507. }
  3508.  
  3509. int __MountAtkSkill(DWORD dwMountVnum, bool IsNew) // updated to 2014/12/10
  3510. {
  3511. if (!dwMountVnum)
  3512. return MOUNT_TYPE_NONE;
  3513.  
  3514. switch (dwMountVnum)
  3515. {
  3516. // ### YES SKILL
  3517. // @fixme116 begin
  3518. case 20107: // normal military horse (no guild)
  3519. case 20108: // normal military horse (guild member)
  3520. case 20109: // normal military horse (guild master)
  3521. if (IsNew)
  3522. return MOUNT_TYPE_NONE;
  3523. // @fixme116 end
  3524. // Classic
  3525. case 20110: // Classic Boar
  3526. case 20111: // Classic Wolf
  3527. case 20112: // Classic Tiger
  3528. case 20113: // Classic Lion
  3529. case 20114: // White Lion
  3530. // Special Lv2
  3531. case 20115: // Wild Battle Boar
  3532. case 20116: // Fight Wolf
  3533. case 20117: // Storm Tiger
  3534. case 20118: // Battle Lion (bugged)
  3535. case 20205: // Wild Battle Boar (alternative)
  3536. case 20206: // Fight Wolf (alternative)
  3537. case 20207: // Storm Tiger (alternative)
  3538. case 20208: // Battle Lion (bugged) (alternative)
  3539. // Royal Tigers
  3540. case 20120: // blue
  3541. case 20121: // dark red
  3542. case 20122: // gold
  3543. case 20123: // green
  3544. case 20124: // pied
  3545. case 20125: // white
  3546. // Royal mounts (Special Lv3)
  3547. case 20209: // Royal Boar
  3548. case 20210: // Royal Wolf
  3549. case 20211: // Royal Tiger
  3550. case 20212: // Royal Lion
  3551. //
  3552. case 20215: // Rudolph m Lv3 (yes skill, yes atk)
  3553. case 20218: // Rudolph f Lv3 (yes skill, yes atk)
  3554. case 20225: // Dyno Lv3 (yes skill, yes atk)
  3555. case 20230: // Turkey Lv3 (yes skill, yes atk)
  3556. return MOUNT_TYPE_MILITARY;
  3557. break;
  3558. // ### NO SKILL YES ATK
  3559. // @fixme116 begin
  3560. case 20104: // normal combat horse (no guild)
  3561. case 20105: // normal combat horse (guild member)
  3562. case 20106: // normal combat horse (guild master)
  3563. if (IsNew)
  3564. return MOUNT_TYPE_NONE;
  3565. // @fixme116 end
  3566. case 20119: // Black Horse (no skill, yes atk)
  3567. case 20214: // Rudolph m Lv2 (no skill, yes atk)
  3568. case 20217: // Rudolph f Lv2 (no skill, yes atk)
  3569. case 20219: // Equus Porphyreus (no skill, yes atk)
  3570. case 20220: // Comet (no skill, yes atk)
  3571. case 20221: // Polar Predator (no skill, yes atk)
  3572. case 20222: // Armoured Panda (no skill, yes atk)
  3573. case 20224: // Dyno Lv2 (no skill, yes atk)
  3574. case 20226: // Nightmare (no skill, yes atk)
  3575. case 20227: // Unicorn (no skill, yes atk)
  3576. case 20229: // Turkey Lv2 (no skill, yes atk)
  3577. case 20231: // Leopard (no skill, yes atk)
  3578. case 20232: // Black Panther (no skill, yes atk)
  3579. return MOUNT_TYPE_COMBAT;
  3580. break;
  3581. // ### NO SKILL NO ATK
  3582. // @fixme116 begin
  3583. case 20101: // normal beginner horse (no guild)
  3584. case 20102: // normal beginner horse (guild member)
  3585. case 20103: // normal beginner horse (guild master)
  3586. if (IsNew)
  3587. return MOUNT_TYPE_NONE;
  3588. // @fixme116 end
  3589. case 20213: // Rudolph m Lv1 (no skill, no atk)
  3590. case 20216: // Rudolph f Lv1 (no skill, no atk)
  3591. // Special Lv1
  3592. case 20201: // Boar Lv1 (no skill, no atk)
  3593. case 20202: // Wolf Lv1 (no skill, no atk)
  3594. case 20203: // Tiger Lv1 (no skill, no atk)
  3595. case 20204: // Lion Lv1 (no skill, no atk)
  3596. //
  3597. case 20223: // Dyno Lv1 (no skill, no atk)
  3598. case 20228: // Turkey Lv1 (no skill, no atk)
  3599. return MOUNT_TYPE_NORMAL;
  3600. break;
  3601. default:
  3602. return MOUNT_TYPE_NONE;
  3603. break;
  3604. }
  3605. }
  3606.  
  3607. const int SKILL_COUNT = 6;
  3608. static const DWORD SkillList[JOB_MAX_NUM][SKILL_GROUP_MAX_NUM][SKILL_COUNT] =
  3609. {
  3610. { { 1, 2, 3, 4, 5, 6 }, { 16, 17, 18, 19, 20, 21 } },
  3611. { { 31, 32, 33, 34, 35, 36 }, { 46, 47, 48, 49, 50, 51 } },
  3612. { { 61, 62, 63, 64, 65, 66 }, { 76, 77, 78, 79, 80, 81 } },
  3613. { { 91, 92, 93, 94, 95, 96 }, { 106,107,108,109,110,111 } },
  3614. #ifdef ENABLE_WOLFMAN_CHARACTER
  3615. { { 170,171,172,173,174,175 }, { 0, 0, 0, 0, 0, 0 } },
  3616. #endif
  3617. };
  3618.  
  3619. const DWORD GetRandomSkillVnum(BYTE bJob = JOB_MAX_NUM);
  3620. const DWORD GetRandomSkillVnum(BYTE bJob)
  3621. {
  3622. // the chosen skill
  3623. DWORD dwSkillVnum = 0;
  3624. do
  3625. {
  3626. // tmp stuff
  3627. DWORD tmpJob = (bJob != JOB_MAX_NUM)?MINMAX(0, bJob, JOB_MAX_NUM-1):number(0, JOB_MAX_NUM-1);
  3628. DWORD tmpSkillGroup = number(0, SKILL_GROUP_MAX_NUM-1);
  3629. DWORD tmpSkillCount = number(0, SKILL_COUNT-1);
  3630. // set skill
  3631. dwSkillVnum = SkillList[tmpJob][tmpSkillGroup][tmpSkillCount];
  3632.  
  3633. if (dwSkillVnum != 0 && NULL != CSkillManager::instance().Get(dwSkillVnum))
  3634. break;
  3635. } while (true);
  3636. return dwSkillVnum;
  3637. }
  3638.  
  3639. bool CHARACTER::CanUseSkill(DWORD dwSkillVnum) const
  3640. {
  3641. if (0 == dwSkillVnum) return false;
  3642.  
  3643. if (0 < GetSkillGroup())
  3644. {
  3645. const DWORD* pSkill = SkillList[ GetJob() ][ GetSkillGroup()-1 ];
  3646.  
  3647. for (int i=0 ; i < SKILL_COUNT ; ++i)
  3648. {
  3649. if (pSkill[i] == dwSkillVnum) return true;
  3650. }
  3651. }
  3652.  
  3653. //if (true == IsHorseRiding())
  3654.  
  3655. if (true == IsRiding())
  3656. {
  3657. //¸¶¿îÆ® Å»°ÍÁß °í±Þ¸»¸¸ ½ºÅ³ »ç¿ë°¡´É
  3658. #ifdef ENABLE_MOUNTSKILL_CHECK
  3659. int iIsMount = __MountAtkSkill(GetMountVnum(), false);
  3660. if (iIsMount!=MOUNT_TYPE_MILITARY)
  3661. {
  3662. if (test_server)
  3663. sys_log(0, "CanUseSkill: Mount can't skill. vnum(%u) type(%d)", GetMountVnum(), iIsMount);
  3664. return false;
  3665. }
  3666. #endif
  3667. switch(dwSkillVnum)
  3668. {
  3669. case SKILL_HORSE_WILDATTACK:
  3670. case SKILL_HORSE_CHARGE:
  3671. case SKILL_HORSE_ESCAPE:
  3672. case SKILL_HORSE_WILDATTACK_RANGE:
  3673. return true;
  3674. }
  3675. }
  3676.  
  3677. switch( dwSkillVnum )
  3678. {
  3679. case 121: case 122: case 124: case 126: case 127: case 128: case 129: case 130:
  3680. case 131:
  3681. case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159:
  3682. return true;
  3683. }
  3684.  
  3685. return false;
  3686. }
  3687.  
  3688. bool CHARACTER::CheckSkillHitCount(const BYTE SkillID, const VID TargetVID)
  3689. {
  3690. std::map<int, TSkillUseInfo>::iterator iter = m_SkillUseInfo.find(SkillID);
  3691.  
  3692. if (iter == m_SkillUseInfo.end())
  3693. {
  3694. sys_log(0, "SkillHack: Skill(%u) is not in container", SkillID);
  3695. return false;
  3696. }
  3697.  
  3698. TSkillUseInfo& rSkillUseInfo = iter->second;
  3699.  
  3700. if (false == rSkillUseInfo.bUsed)
  3701. {
  3702. sys_log(0, "SkillHack: not used skill(%u)", SkillID);
  3703. return false;
  3704. }
  3705.  
  3706. switch (SkillID)
  3707. {
  3708. case SKILL_YONGKWON:
  3709. case SKILL_HWAYEOMPOK:
  3710. case SKILL_DAEJINGAK:
  3711. case SKILL_PAERYONG:
  3712. sys_log(0, "SkillHack: cannot use attack packet for skill(%u)", SkillID);
  3713. return false;
  3714. }
  3715.  
  3716. boost::unordered_map<VID, size_t>::iterator iterTargetMap = rSkillUseInfo.TargetVIDMap.find(TargetVID);
  3717.  
  3718. if (rSkillUseInfo.TargetVIDMap.end() != iterTargetMap)
  3719. {
  3720. size_t MaxAttackCountPerTarget = 1;
  3721.  
  3722. switch (SkillID)
  3723. {
  3724. case SKILL_SAMYEON:
  3725. case SKILL_CHARYUN:
  3726. #ifdef ENABLE_WOLFMAN_CHARACTER
  3727. case SKILL_PASWAE:
  3728. #endif
  3729. MaxAttackCountPerTarget = 3;
  3730. break;
  3731.  
  3732. case SKILL_HORSE_WILDATTACK_RANGE:
  3733. MaxAttackCountPerTarget = 5;
  3734. break;
  3735.  
  3736. case SKILL_YEONSA:
  3737. MaxAttackCountPerTarget = 7;
  3738. break;
  3739.  
  3740. case SKILL_HORSE_ESCAPE:
  3741. MaxAttackCountPerTarget = 10;
  3742. break;
  3743. }
  3744.  
  3745. if (iterTargetMap->second >= MaxAttackCountPerTarget)
  3746. {
  3747. sys_log(0, "SkillHack: Too Many Hit count from SkillID(%u) count(%u)", SkillID, iterTargetMap->second);
  3748. return false;
  3749. }
  3750.  
  3751. iterTargetMap->second++;
  3752. }
  3753. else
  3754. {
  3755. rSkillUseInfo.TargetVIDMap.insert( std::make_pair(TargetVID, 1) );
  3756. }
  3757.  
  3758. return true;
  3759. }
Add Comment
Please, Sign In to add comment