Guest User

dragonsoul.cp

a guest
Dec 18th, 2024
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.80 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "constants.h"
  3. #include "item.h"
  4. #include "item_manager.h"
  5. #include "unique_item.h"
  6. #include "packet.h"
  7. #include "desc.h"
  8. #include "char.h"
  9. #include "dragon_soul_table.h"
  10. #include "log.h"
  11. #include "DragonSoul.h"
  12. #include <boost/lexical_cast.hpp>
  13.  
  14. typedef std::vector <std::string> TTokenVector;
  15.  
  16. template <typename T> T MINMAX(T min, T value, T max)
  17. {
  18. T tv;
  19.  
  20. tv = (min > value ? min : value);
  21. return (max < tv) ? max : tv;
  22. }
  23.  
  24. int Gamble(std::vector<float>& vec_probs)
  25. {
  26. float range = 0.f;
  27. for (size_t i = 0; i < vec_probs.size(); i++)
  28. {
  29. range += vec_probs[i];
  30. }
  31. float fProb = fnumber(0.f, range);
  32. float sum = 0.f;
  33. for (size_t idx = 0; idx < vec_probs.size(); idx++)
  34. {
  35. sum += vec_probs[idx];
  36. if (sum >= fProb)
  37. return idx;
  38. }
  39. return -1;
  40. }
  41.  
  42. // 가중치 테이블(prob_lst)을 받아 random_set.size()개의 index를 선택하여 random_set을 return
  43. bool MakeDistinctRandomNumberSet(std::list <float> prob_lst, OUT std::vector<int>& random_set)
  44. {
  45. int size = prob_lst.size();
  46. int n = random_set.size();
  47. if (size < n)
  48. return false;
  49.  
  50. std::vector <int> select_bit(size, 0);
  51. for (int i = 0; i < n; i++)
  52. {
  53. float range = 0.f;
  54. for (std::list <float>::iterator it = prob_lst.begin(); it != prob_lst.end(); it++)
  55. {
  56. range += *it;
  57. }
  58. float r = fnumber (0.f, range);
  59. float sum = 0.f;
  60. int idx = 0;
  61. for (std::list <float>::iterator it = prob_lst.begin(); it != prob_lst.end(); it++)
  62. {
  63. while (select_bit[idx++]);
  64.  
  65. sum += *it;
  66. if (sum >= r)
  67. {
  68. select_bit[idx - 1] = 1;
  69. random_set[i] = idx - 1;
  70. prob_lst.erase(it);
  71. break;
  72. }
  73. }
  74. }
  75. return true;
  76. }
  77.  
  78. /* 용혼석 Vnum에 대한 comment
  79. * ITEM VNUM을 10만 자리부터, FEDCBA라고 한다면
  80. * FE : 용혼석 종류. D : 등급
  81. * C : 단계 B : 강화
  82. * A : 여벌의 번호들...
  83. */
  84.  
  85. BYTE GetType(DWORD dwVnum)
  86. {
  87. return (dwVnum / 10000);
  88. }
  89.  
  90. BYTE GetGradeIdx(DWORD dwVnum)
  91. {
  92. return (dwVnum / 1000) % 10;
  93. }
  94.  
  95. BYTE GetStepIdx(DWORD dwVnum)
  96. {
  97. return (dwVnum / 100) % 10;
  98. }
  99.  
  100. BYTE GetStrengthIdx(DWORD dwVnum)
  101. {
  102. return (dwVnum / 10) % 10;
  103. }
  104.  
  105. bool DSManager::ReadDragonSoulTableFile(const char * c_pszFileName)
  106. {
  107. m_pTable = new DragonSoulTable();
  108. return m_pTable->ReadDragonSoulTableFile(c_pszFileName);
  109. }
  110.  
  111. void DSManager::GetDragonSoulInfo(DWORD dwVnum, BYTE& bType, BYTE& bGrade, BYTE& bStep, BYTE& bStrength) const
  112. {
  113. bType = GetType(dwVnum);
  114. bGrade = GetGradeIdx(dwVnum);
  115. bStep = GetStepIdx(dwVnum);
  116. bStrength = GetStrengthIdx(dwVnum);
  117. }
  118.  
  119. bool DSManager::IsValidCellForThisItem(const LPITEM pItem, const TItemPos& Cell) const
  120. {
  121. if (NULL == pItem)
  122. return false;
  123.  
  124. WORD wBaseCell = GetBasePosition(pItem);
  125. if (WORD_MAX == wBaseCell)
  126. return false;
  127.  
  128. if (Cell.window_type != DRAGON_SOUL_INVENTORY
  129. || (Cell.cell < wBaseCell || Cell.cell >= wBaseCell + DRAGON_SOUL_BOX_SIZE))
  130. {
  131. return false;
  132. }
  133. else
  134. return true;
  135.  
  136. }
  137.  
  138. WORD DSManager::GetBasePosition(const LPITEM pItem) const
  139. {
  140. if (NULL == pItem)
  141. return WORD_MAX;
  142.  
  143. BYTE type, grade_idx, step_idx, strength_idx;
  144. GetDragonSoulInfo(pItem->GetVnum(), type, grade_idx, step_idx, strength_idx);
  145.  
  146. BYTE col_type = pItem->GetSubType();
  147. BYTE row_type = grade_idx;
  148. if (row_type > DRAGON_SOUL_GRADE_MAX)
  149. return WORD_MAX;
  150.  
  151. return col_type * DRAGON_SOUL_STEP_MAX * DRAGON_SOUL_BOX_SIZE + row_type * DRAGON_SOUL_BOX_SIZE;
  152. }
  153.  
  154. bool DSManager::RefreshItemAttributes(LPITEM pDS)
  155. {
  156. if (!pDS->IsDragonSoul())
  157. {
  158. sys_err ("This item(ID : %d) is not DragonSoul.", pDS->GetID());
  159. return false;
  160. }
  161.  
  162. BYTE ds_type, grade_idx, step_idx, strength_idx;
  163. GetDragonSoulInfo(pDS->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
  164.  
  165. DragonSoulTable::TVecApplys vec_basic_applys;
  166. DragonSoulTable::TVecApplys vec_addtional_applys;
  167.  
  168. if (!m_pTable->GetBasicApplys(ds_type, vec_basic_applys))
  169. {
  170. sys_err ("There is no BasicApply about %d type dragon soul.", ds_type);
  171. return false;
  172. }
  173.  
  174. if (!m_pTable->GetAdditionalApplys(ds_type, vec_addtional_applys))
  175. {
  176. sys_err ("There is no AdditionalApply about %d type dragon soul.", ds_type);
  177. return false;
  178. }
  179.  
  180. // add_min과 add_max는 더미로 읽음.
  181. int basic_apply_num, add_min, add_max;
  182. if (!m_pTable->GetApplyNumSettings(ds_type, grade_idx, basic_apply_num, add_min, add_max))
  183. {
  184. sys_err ("In ApplyNumSettings, INVALID VALUES Group type(%d), GRADE idx(%d)", ds_type, grade_idx);
  185. return false;
  186. }
  187.  
  188. float fWeight = 0.f;
  189. if (!m_pTable->GetWeight(ds_type, grade_idx, step_idx, strength_idx, fWeight))
  190. {
  191. return false;
  192. }
  193. fWeight /= 100.f;
  194.  
  195. int n = MIN(basic_apply_num, vec_basic_applys.size());
  196. for (int i = 0; i < n; i++)
  197. {
  198. const SApply& basic_apply = vec_basic_applys[i];
  199. BYTE bType = basic_apply.apply_type;
  200. short sValue = (short)(ceil((float)basic_apply.apply_value * fWeight - 0.01f));
  201.  
  202. pDS->SetForceAttribute(i, bType, sValue);
  203. }
  204.  
  205. for (int i = DRAGON_SOUL_ADDITIONAL_ATTR_START_IDX; i < ITEM_ATTRIBUTE_MAX_NUM; i++)
  206. {
  207. BYTE bType = pDS->GetAttributeType(i);
  208. short sValue = 0;
  209. if (APPLY_NONE == bType)
  210. continue;
  211. for (size_t j = 0; j < vec_addtional_applys.size(); j++)
  212. {
  213. if (vec_addtional_applys[j].apply_type == bType)
  214. {
  215. sValue = vec_addtional_applys[j].apply_value;
  216. break;
  217. }
  218. }
  219. pDS->SetForceAttribute(i, bType, (short)(ceil((float)sValue * fWeight - 0.01f)));
  220. }
  221. return true;
  222. }
  223.  
  224. bool DSManager::PutAttributes(LPITEM pDS)
  225. {
  226. if (!pDS->IsDragonSoul())
  227. {
  228. sys_err ("This item(ID : %d) is not DragonSoul.", pDS->GetID());
  229. return false;
  230. }
  231.  
  232. BYTE ds_type, grade_idx, step_idx, strength_idx;
  233. GetDragonSoulInfo(pDS->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
  234.  
  235. DragonSoulTable::TVecApplys vec_basic_applys;
  236. DragonSoulTable::TVecApplys vec_addtional_applys;
  237.  
  238. if (!m_pTable->GetBasicApplys(ds_type, vec_basic_applys))
  239. {
  240. sys_err ("There is no BasicApply about %d type dragon soul.", ds_type);
  241. return false;
  242. }
  243. if (!m_pTable->GetAdditionalApplys(ds_type, vec_addtional_applys))
  244. {
  245. sys_err ("There is no AdditionalApply about %d type dragon soul.", ds_type);
  246. return false;
  247. }
  248.  
  249.  
  250. int basic_apply_num, add_min, add_max;
  251. if (!m_pTable->GetApplyNumSettings(ds_type, grade_idx, basic_apply_num, add_min, add_max))
  252. {
  253. sys_err ("In ApplyNumSettings, INVALID VALUES Group type(%d), GRADE idx(%d)", ds_type, grade_idx);
  254. return false;
  255. }
  256.  
  257. float fWeight = 0.f;
  258. if (!m_pTable->GetWeight(ds_type, grade_idx, step_idx, strength_idx, fWeight))
  259. {
  260. return false;
  261. }
  262. fWeight /= 100.f;
  263.  
  264. int n = MIN(basic_apply_num, vec_basic_applys.size());
  265. for (int i = 0; i < n; i++)
  266. {
  267. const SApply& basic_apply = vec_basic_applys[i];
  268. BYTE bType = basic_apply.apply_type;
  269. short sValue = (short)(ceil((float)basic_apply.apply_value * fWeight - 0.01f));
  270.  
  271. pDS->SetForceAttribute(i, bType, sValue);
  272. }
  273.  
  274. BYTE additional_attr_num = MIN(number (add_min, add_max), 3);
  275.  
  276. std::vector <int> random_set;
  277. if (additional_attr_num > 0)
  278. {
  279. random_set.resize(additional_attr_num);
  280. std::list <float> list_probs;
  281. for (size_t i = 0; i < vec_addtional_applys.size(); i++)
  282. {
  283. list_probs.push_back(vec_addtional_applys[i].prob);
  284. }
  285. if (!MakeDistinctRandomNumberSet(list_probs, random_set))
  286. {
  287. sys_err ("MakeDistinctRandomNumberSet error.");
  288. return false;
  289. }
  290.  
  291. for (int i = 0; i < additional_attr_num; i++)
  292. {
  293. int r = random_set[i];
  294. const SApply& additional_attr = vec_addtional_applys[r];
  295. BYTE bType = additional_attr.apply_type;
  296. short sValue = (short)(ceil((float)additional_attr.apply_value * fWeight - 0.01f));
  297.  
  298. pDS->SetForceAttribute(DRAGON_SOUL_ADDITIONAL_ATTR_START_IDX + i, bType, sValue);
  299. }
  300. }
  301.  
  302. return true;
  303. }
  304.  
  305. bool DSManager::DragonSoulItemInitialize(LPITEM pItem)
  306. {
  307. if (NULL == pItem || !pItem->IsDragonSoul())
  308. return false;
  309. PutAttributes(pItem);
  310. int time = DSManager::instance().GetDuration(pItem);
  311. if (time > 0)
  312. pItem->SetSocket(ITEM_SOCKET_REMAIN_SEC, time);
  313. return true;
  314. }
  315.  
  316. DWORD DSManager::MakeDragonSoulVnum(BYTE bType, BYTE grade, BYTE step, BYTE refine)
  317. {
  318. return bType * 10000 + grade * 1000 + step * 100 + refine * 10;
  319. }
  320.  
  321. int DSManager::GetDuration(const LPITEM pItem) const
  322. {
  323. return pItem->GetDuration();
  324. }
  325.  
  326. // 용혼석을 받아서 용심을 추출하는 함수
  327. bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor)
  328. {
  329. if (NULL == ch || NULL == pItem)
  330. return false;
  331. if (pItem->IsEquipped())
  332. {
  333. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("착용 중인 용혼석은 추출할 수 없습니다."));
  334. return false;
  335. }
  336.  
  337. DWORD dwVnum = pItem->GetVnum();
  338. BYTE ds_type, grade_idx, step_idx, strength_idx;
  339. GetDragonSoulInfo(dwVnum, ds_type, grade_idx, step_idx, strength_idx);
  340.  
  341. int iBonus = 0;
  342.  
  343. if (NULL != pExtractor)
  344. {
  345. iBonus = pExtractor->GetValue(0);
  346. }
  347.  
  348. std::vector <float> vec_chargings;
  349. std::vector <float> vec_probs;
  350.  
  351. if (!m_pTable->GetDragonHeartExtValues(ds_type, grade_idx, vec_chargings, vec_probs))
  352. {
  353. return false;
  354. }
  355.  
  356. int idx = Gamble(vec_probs);
  357.  
  358. //float sum = 0.f;
  359. if (-1 == idx)
  360. {
  361. sys_err ("Gamble is failed. ds_type(%d), grade_idx(%d)", ds_type, grade_idx);
  362. return false;
  363. }
  364.  
  365. float fCharge = vec_chargings[idx] * (100 + iBonus) / 100.f;
  366. fCharge = MINMAX <float> (0.f, fCharge, 100.f);
  367.  
  368. if (fCharge < FLT_EPSILON)
  369. {
  370. pItem->SetCount(pItem->GetCount() - 1);
  371. if (NULL != pExtractor)
  372. {
  373. pExtractor->SetCount(pExtractor->GetCount() - 1);
  374. }
  375. LogManager::instance().ItemLog(ch, pItem, "DS_HEART_EXTRACT_FAIL", "");
  376.  
  377. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용심 추출에 실패하였습니다."));
  378. return false;
  379. }
  380. else
  381. {
  382. LPITEM pDH = ITEM_MANAGER::instance().CreateItem(DRAGON_HEART_VNUM);
  383.  
  384. if (NULL == pDH)
  385. {
  386. sys_err ("Cannot create DRAGON_HEART(%d).", DRAGON_HEART_VNUM);
  387. return NULL;
  388. }
  389.  
  390. pItem->SetCount(pItem->GetCount() - 1);
  391. if (NULL != pExtractor)
  392. {
  393. pExtractor->SetCount(pExtractor->GetCount() - 1);
  394. }
  395.  
  396. int iCharge = (int)(fCharge + 0.5f);
  397. pDH->SetSocket(ITEM_SOCKET_CHARGING_AMOUNT_IDX, iCharge);
  398. ch->AutoGiveItem(pDH, true);
  399.  
  400. std::string s = boost::lexical_cast <std::string> (iCharge);
  401. s += "%s";
  402. LogManager::instance().ItemLog(ch, pItem, "DS_HEART_EXTRACT_SUCCESS", s.c_str());
  403. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용심 추출에 성공하였습니다."));
  404. return true;
  405. }
  406. }
  407.  
  408. // 특정 용혼석을 장비창에서 제거할 때에 성공 여부를 결정하고, 실패시 부산물을 주는 함수.
  409. bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM pExtractor)
  410. {
  411. if (NULL == ch || NULL == pItem)
  412. {
  413. sys_err ("NULL POINTER. ch(%p) or pItem(%p)", ch, pItem);
  414. return false;
  415. }
  416.  
  417. // 목표 위치가 valid한지 검사 후, valid하지 않다면 임의의 빈 공간을 찾는다.
  418. if (!IsValidCellForThisItem(pItem, DestCell))
  419. {
  420. int iEmptyCell = ch->GetEmptyDragonSoulInventory(pItem);
  421. if (iEmptyCell < 0)
  422. {
  423. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("소지품에 빈 공간이 없습니다."));
  424. return false;
  425. }
  426. else
  427. {
  428. DestCell.window_type = DRAGON_SOUL_INVENTORY;
  429. DestCell.cell = iEmptyCell;
  430. }
  431. }
  432.  
  433. if (!pItem->IsEquipped() || !pItem->RemoveFromCharacter())
  434. return false;
  435.  
  436. bool bSuccess;
  437. DWORD dwByProduct = 0;
  438. int iBonus = 0;
  439. float fProb;
  440. float fDice;
  441. // 용혼석 추출 성공 여부 결정.
  442. {
  443. //DWORD dwVnum = pItem->GetVnum();
  444.  
  445. BYTE ds_type, grade_idx, step_idx, strength_idx;
  446. GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
  447.  
  448. // 추출 정보가 없다면 일단 무조건 성공하는 것이라 생각하자.
  449. if (!m_pTable->GetDragonSoulExtValues(ds_type, grade_idx, fProb, dwByProduct))
  450. {
  451. pItem->AddToCharacter(ch, DestCell);
  452. return true;
  453. }
  454.  
  455.  
  456. if (NULL != pExtractor)
  457. {
  458. iBonus = pExtractor->GetValue(ITEM_VALUE_DRAGON_SOUL_POLL_OUT_BONUS_IDX);
  459. pExtractor->SetCount(pExtractor->GetCount() - 1);
  460. }
  461. fDice = fnumber(0.f, 100.f);
  462. bSuccess = fDice <= (fProb * (100 + iBonus) / 100.f);
  463. }
  464.  
  465. // 캐릭터의 용혼석 추출 및 추가 혹은 제거. 부산물 제공.
  466. {
  467. char buf[128];
  468.  
  469. if (bSuccess)
  470. {
  471. if (pExtractor)
  472. {
  473. sprintf(buf, "dice(%d) prob(%d + %d) EXTR(VN:%d)", (int)fDice, (int)fProb, iBonus, pExtractor->GetVnum());
  474. }
  475. else
  476. {
  477. sprintf(buf, "dice(%d) prob(%d)", (int)fDice, (int)fProb);
  478. }
  479. LogManager::instance().ItemLog(ch, pItem, "DS_PULL_OUT_SUCCESS", buf);
  480. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 성공하였습니다."));
  481. pItem->AddToCharacter(ch, DestCell);
  482. return true;
  483. }
  484. else
  485. {
  486. if (pExtractor)
  487. {
  488. sprintf(buf, "dice(%d) prob(%d + %d) EXTR(VN:%d) ByProd(VN:%d)", (int)fDice, (int)fProb, iBonus, pExtractor->GetVnum(), dwByProduct);
  489. }
  490. else
  491. {
  492. sprintf(buf, "dice(%d) prob(%d) ByProd(VNUM:%d)", (int)fDice, (int)fProb, dwByProduct);
  493. }
  494. LogManager::instance().ItemLog(ch, pItem, "DS_PULL_OUT_FAILED", buf);
  495. M2_DESTROY_ITEM(pItem);
  496. pItem = NULL;
  497. if (dwByProduct)
  498. {
  499. LPITEM pByProduct = ch->AutoGiveItem(dwByProduct, true);
  500. if (pByProduct)
  501. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하여 %s를 얻었습니다."), pByProduct->GetName());
  502. else
  503. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하였습니다."));
  504. }
  505. else
  506. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("용혼석 추출에 실패하였습니다."));
  507. }
  508. }
  509.  
  510. return bSuccess;
  511. }
  512.  
  513. bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE])
  514. {
  515. if (NULL == ch)
  516. return false;
  517.  
  518. if (NULL == aItemPoses)
  519. {
  520. return false;
  521. }
  522.  
  523. if (!ch->DragonSoul_RefineWindow_CanRefine())
  524. {
  525. sys_err ("%s do not activate DragonSoulRefineWindow. But how can he come here?", ch->GetName());
  526. ch->ChatPacket(CHAT_TYPE_INFO, "[SYSTEM ERROR]You cannot upgrade dragon soul without refine window.");
  527. return false;
  528. }
  529.  
  530. // 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
  531. // 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
  532. std::set <LPITEM> set_items;
  533. for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
  534. {
  535. if (aItemPoses[i].IsEquipPosition())
  536. return false;
  537. LPITEM pItem = ch->GetItem(aItemPoses[i]);
  538. if (NULL != pItem)
  539. {
  540. // 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
  541. if (!pItem->IsDragonSoul())
  542. {
  543. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 필요한 재료가 아닙니다."));
  544. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  545.  
  546. return false;
  547. }
  548.  
  549. set_items.insert(pItem);
  550. }
  551. }
  552.  
  553. if (set_items.size() == 0)
  554. {
  555. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS);
  556. return false;
  557. }
  558.  
  559. int count = set_items.size();
  560. int need_count = 0;
  561. int fee = 0;
  562. std::vector <float> vec_probs;
  563. //float prob_sum;
  564.  
  565. BYTE ds_type, grade_idx, step_idx, strength_idx;
  566. int result_grade;
  567.  
  568. // 가장 처음 것을 강화의 기준으로 삼는다.
  569. std::set <LPITEM>::iterator it = set_items.begin();
  570. {
  571. LPITEM pItem = *it;
  572.  
  573. GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
  574.  
  575. if (!m_pTable->GetRefineGradeValues(ds_type, grade_idx, need_count, fee, vec_probs))
  576. {
  577. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량할 수 없는 용혼석입니다."));
  578. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  579.  
  580. return false;
  581. }
  582. }
  583. while (++it != set_items.end())
  584. {
  585. LPITEM pItem = *it;
  586.  
  587. // 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
  588. // 별도의 알림 처리는 안함.
  589. if (pItem->IsEquipped())
  590. {
  591. return false;
  592. }
  593.  
  594. if (ds_type != GetType(pItem->GetVnum()) || grade_idx != GetGradeIdx(pItem->GetVnum()))
  595. {
  596. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 필요한 재료가 아닙니다."));
  597. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  598.  
  599. return false;
  600. }
  601. }
  602.  
  603. // 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
  604. if (count != need_count)
  605. {
  606. sys_err ("Possiblity of invalid client. Name %s", ch->GetName());
  607. BYTE bSubHeader = count < need_count? DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL : DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL;
  608. SendRefineResultPacket(ch, bSubHeader, NPOS);
  609. return false;
  610. }
  611.  
  612. if (ch->GetGold() < fee)
  613. {
  614. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
  615. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS);
  616. return false;
  617. }
  618.  
  619. if (-1 == (result_grade = Gamble(vec_probs)))
  620. {
  621. sys_err ("Gamble failed. See RefineGardeTables' probabilities");
  622. return false;
  623. }
  624.  
  625. LPITEM pResultItem = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(ds_type, (BYTE)result_grade, 0, 0));
  626.  
  627. if (NULL == pResultItem)
  628. {
  629. sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(ds_type, (BYTE)result_grade, 0, 0));
  630. return false;
  631. }
  632.  
  633. ch->PointChange(POINT_GOLD, -fee);
  634. int left_count = need_count;
  635.  
  636. for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++)
  637. {
  638. LPITEM pItem = *it;
  639. int n = pItem->GetCount();
  640. if (left_count > n)
  641. {
  642. pItem->RemoveFromCharacter();
  643. M2_DESTROY_ITEM(pItem);
  644. left_count -= n;
  645. }
  646. else
  647. {
  648. pItem->SetCount(n - left_count);
  649. }
  650. }
  651.  
  652. ch->AutoGiveItem(pResultItem, true);
  653.  
  654. if (result_grade > grade_idx)
  655. {
  656. char buf[128];
  657. sprintf(buf, "GRADE : %d -> %d", grade_idx, result_grade);
  658. LogManager::instance().ItemLog(ch, pResultItem, "DS_GRADE_REFINE_SUCCESS", buf);
  659. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 성공했습니다."));
  660. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_SUCCEED, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
  661. return true;
  662. }
  663. else
  664. {
  665. char buf[128];
  666. sprintf(buf, "GRADE : %d -> %d", grade_idx, result_grade);
  667. LogManager::instance().ItemLog(ch, pResultItem, "DS_GRADE_REFINE_FAIL", buf);
  668. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("등급 개량에 실패했습니다."));
  669. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
  670. return false;
  671. }
  672. }
  673.  
  674. bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE])
  675. {
  676. if (NULL == ch)
  677. return false;
  678. if (NULL == aItemPoses)
  679. {
  680. return false;
  681. }
  682.  
  683. if (!ch->DragonSoul_RefineWindow_CanRefine())
  684. {
  685. sys_err ("%s do not activate DragonSoulRefineWindow. But how can he come here?", ch->GetName());
  686. ch->ChatPacket(CHAT_TYPE_INFO, "[SYSTEM ERROR]You cannot use dragon soul refine window.");
  687. return false;
  688. }
  689.  
  690. // 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
  691. // 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
  692. std::set <LPITEM> set_items;
  693. for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
  694. {
  695. LPITEM pItem = ch->GetItem(aItemPoses[i]);
  696. if (NULL != pItem)
  697. {
  698. // 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
  699. if (!pItem->IsDragonSoul())
  700. {
  701. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다."));
  702. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  703. return false;
  704. }
  705. set_items.insert(pItem);
  706. }
  707. }
  708.  
  709. if (set_items.size() == 0)
  710. {
  711. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS);
  712. return false;
  713. }
  714.  
  715. std::string stGroupName;
  716. int count = set_items.size();
  717. int need_count = 0;
  718. int fee = 0;
  719. std::vector <float> vec_probs;
  720.  
  721. BYTE ds_type, grade_idx, step_idx, strength_idx;
  722. int result_step;
  723.  
  724. // 가장 처음 것을 강화의 기준으로 삼는다.
  725. std::set <LPITEM>::iterator it = set_items.begin();
  726. {
  727. LPITEM pItem = *it;
  728. GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
  729.  
  730. if (!m_pTable->GetRefineStepValues(ds_type, step_idx, need_count, fee, vec_probs))
  731. {
  732. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량할 수 없는 용혼석입니다."));
  733. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  734. return false;
  735. }
  736. }
  737.  
  738. while(++it != set_items.end())
  739. {
  740. LPITEM pItem = *it;
  741. // 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
  742. // 별도의 알림 처리는 안함.
  743. if (pItem->IsEquipped())
  744. {
  745. return false;
  746. }
  747. if (ds_type != GetType(pItem->GetVnum()) || grade_idx != GetGradeIdx(pItem->GetVnum()) || step_idx != GetStepIdx(pItem->GetVnum()))
  748. {
  749. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다."));
  750. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  751. return false;
  752. }
  753. }
  754.  
  755. // 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
  756. if (count != need_count)
  757. {
  758. sys_err ("Possiblity of invalid client. Name %s", ch->GetName());
  759. BYTE bSubHeader = count < need_count? DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL : DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL;
  760. SendRefineResultPacket(ch, bSubHeader, NPOS);
  761. return false;
  762. }
  763.  
  764. if (ch->GetGold() < fee)
  765. {
  766. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
  767. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS);
  768. return false;
  769. }
  770.  
  771. //float sum = 0.f;
  772.  
  773. if (-1 == (result_step = Gamble(vec_probs)))
  774. {
  775. sys_err ("Gamble failed. See RefineStepTables' probabilities");
  776. return false;
  777. }
  778.  
  779. LPITEM pResultItem = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(ds_type, grade_idx, (BYTE)result_step, 0));
  780.  
  781. if (NULL == pResultItem)
  782. {
  783. sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(ds_type, grade_idx, (BYTE)result_step, 0));
  784. return false;
  785. }
  786.  
  787. ch->PointChange(POINT_GOLD, -fee);
  788. int left_count = need_count;
  789. for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++)
  790. {
  791. LPITEM pItem = *it;
  792. int n = pItem->GetCount();
  793. if (left_count > n)
  794. {
  795. pItem->RemoveFromCharacter();
  796. M2_DESTROY_ITEM(pItem);
  797. left_count -= n;
  798. }
  799. else
  800. {
  801. pItem->SetCount(n - left_count);
  802. }
  803. }
  804.  
  805. ch->AutoGiveItem(pResultItem, true);
  806. if (result_step > step_idx)
  807. {
  808. char buf[128];
  809. sprintf(buf, "STEP : %d -> %d", step_idx, result_step);
  810. LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_SUCCESS", buf);
  811. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 성공했습니다."));
  812. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_SUCCEED, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
  813. return true;
  814. }
  815. else
  816. {
  817. char buf[128];
  818. sprintf(buf, "STEP : %d -> %d", step_idx, result_step);
  819. LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_FAIL", buf);
  820. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 실패했습니다."));
  821. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell()));
  822. return false;
  823. }
  824. }
  825.  
  826. bool IsDragonSoulRefineMaterial(LPITEM pItem)
  827. {
  828. if (pItem->GetType() != ITEM_MATERIAL)
  829. return false;
  830. return (pItem->GetSubType() == MATERIAL_DS_REFINE_NORMAL ||
  831. pItem->GetSubType() == MATERIAL_DS_REFINE_BLESSED ||
  832. pItem->GetSubType() == MATERIAL_DS_REFINE_HOLLY);
  833. }
  834.  
  835. bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE])
  836. {
  837. if (NULL == ch)
  838. return false;
  839. if (NULL == aItemPoses)
  840. {
  841. return false;
  842. }
  843.  
  844. if (!ch->DragonSoul_RefineWindow_CanRefine())
  845. {
  846. sys_err ("%s do not activate DragonSoulRefineWindow. But how can he come here?", ch->GetName());
  847. ch->ChatPacket(CHAT_TYPE_INFO, "[SYSTEM ERROR]You cannot use dragon soul refine window.");
  848. return false;
  849. }
  850.  
  851. // 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
  852. // 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
  853. std::set <LPITEM> set_items;
  854. for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
  855. {
  856. LPITEM pItem = ch->GetItem(aItemPoses[i]);
  857. if (pItem)
  858. {
  859. set_items.insert(pItem);
  860. }
  861. }
  862. if (set_items.size() == 0)
  863. {
  864. return false;
  865. }
  866.  
  867. int fee;
  868.  
  869. LPITEM pRefineStone = NULL;
  870. LPITEM pDragonSoul = NULL;
  871. for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++)
  872. {
  873. LPITEM pItem = *it;
  874. // 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
  875. // 별도의 알림 처리는 안함.
  876. if (pItem->IsEquipped())
  877. {
  878. return false;
  879. }
  880.  
  881. // 용혼석과 강화석만이 개량창에 있을 수 있다.
  882. // 그리고 하나씩만 있어야한다.
  883. if (pItem->IsDragonSoul())
  884. {
  885. if (pDragonSoul != NULL)
  886. {
  887. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  888. return false;
  889. }
  890. pDragonSoul = pItem;
  891. }
  892. else if(IsDragonSoulRefineMaterial(pItem))
  893. {
  894. if (pRefineStone != NULL)
  895. {
  896. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  897. return false;
  898. }
  899. pRefineStone = pItem;
  900. }
  901. else
  902. {
  903. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 필요한 재료가 아닙니다."));
  904. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell()));
  905. return false;
  906. }
  907. }
  908.  
  909. BYTE bType, bGrade, bStep, bStrength;
  910.  
  911. if (!pDragonSoul || !pRefineStone)
  912. {
  913. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS);
  914.  
  915. return false;
  916. }
  917.  
  918. if (NULL != pDragonSoul)
  919. {
  920. GetDragonSoulInfo(pDragonSoul->GetVnum(), bType, bGrade, bStep, bStrength);
  921.  
  922. float fWeight = 0.f;
  923. if (!m_pTable->GetWeight(bType, bGrade, bStep, bStrength + 1, fWeight))
  924. {
  925. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
  926. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
  927. return false;
  928. }
  929. if (fWeight < FLT_EPSILON)
  930. {
  931. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
  932. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
  933. return false;
  934. }
  935. }
  936.  
  937. float fProb;
  938. if (!m_pTable->GetRefineStrengthValues(bType, pRefineStone->GetSubType(), bStrength, fee, fProb))
  939. {
  940. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다."));
  941. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
  942.  
  943. return false;
  944. }
  945.  
  946. if (ch->GetGold() < fee)
  947. {
  948. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다."));
  949. SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS);
  950. return false;
  951. }
  952.  
  953. ch->PointChange(POINT_GOLD, -fee);
  954. LPITEM pResult = NULL;
  955. BYTE bSubHeader;
  956.  
  957. if (fnumber(0.f, 100.f) <= fProb)
  958. {
  959. pResult = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(bType, bGrade, bStep, bStrength + 1));
  960. if (NULL == pResult)
  961. {
  962. sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(bType, bGrade, bStep, bStrength + 1));
  963. return false;
  964. }
  965. pDragonSoul->RemoveFromCharacter();
  966.  
  967. pDragonSoul->CopyAttributeTo(pResult);
  968. RefreshItemAttributes(pResult);
  969.  
  970. pDragonSoul->SetCount(pDragonSoul->GetCount() - 1);
  971. pRefineStone->SetCount(pRefineStone->GetCount() - 1);
  972.  
  973. char buf[128];
  974. sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength + 1);
  975. LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_SUCCESS", buf);
  976. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 성공했습니다."));
  977. ch->AutoGiveItem(pResult, true);
  978. bSubHeader = DS_SUB_HEADER_REFINE_SUCCEED;
  979. }
  980. else
  981. {
  982. if (bStrength != 0)
  983. {
  984. pResult = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(bType, bGrade, bStep, bStrength - 1));
  985. if (NULL == pResult)
  986. {
  987. sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(bType, bGrade, bStep, bStrength - 1));
  988. return false;
  989. }
  990. pDragonSoul->CopyAttributeTo(pResult);
  991. RefreshItemAttributes(pResult);
  992. }
  993. bSubHeader = DS_SUB_HEADER_REFINE_FAIL;
  994.  
  995. char buf[128];
  996. sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength - 1);
  997. // strength강화는 실패시 깨질 수도 있어, 원본 아이템을 바탕으로 로그를 남김.
  998. LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_FAIL", buf);
  999.  
  1000. ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 실패했습니다."));
  1001. pDragonSoul->SetCount(pDragonSoul->GetCount() - 1);
  1002. pRefineStone->SetCount(pRefineStone->GetCount() - 1);
  1003. if (NULL != pResult)
  1004. ch->AutoGiveItem(pResult, true);
  1005.  
  1006. }
  1007.  
  1008. SendRefineResultPacket(ch, bSubHeader, NULL == pResult? NPOS : TItemPos (pResult->GetWindow(), pResult->GetCell()));
  1009.  
  1010. return true;
  1011. }
  1012.  
  1013. void DSManager::SendRefineResultPacket(LPCHARACTER ch, BYTE bSubHeader, const TItemPos& pos)
  1014. {
  1015. TPacketGCDragonSoulRefine pack;
  1016. pack.bSubType = bSubHeader;
  1017.  
  1018. if (pos.IsValidItemPosition())
  1019. {
  1020. pack.Pos = pos;
  1021. }
  1022. LPDESC d = ch->GetDesc();
  1023. if (NULL == d)
  1024. {
  1025. return ;
  1026. }
  1027. else
  1028. {
  1029. d->Packet(&pack, sizeof(pack));
  1030. }
  1031. }
  1032.  
  1033. int DSManager::LeftTime(LPITEM pItem) const
  1034. {
  1035. if (pItem == NULL)
  1036. return false;
  1037.  
  1038. // 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
  1039. if (pItem->GetProto()->cLimitTimerBasedOnWearIndex >= 0)
  1040. {
  1041. return pItem->GetSocket(ITEM_SOCKET_REMAIN_SEC);
  1042. }
  1043. // 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
  1044. else
  1045. {
  1046. return INT_MAX;
  1047. }
  1048. }
  1049.  
  1050. bool DSManager::IsTimeLeftDragonSoul(LPITEM pItem) const
  1051. {
  1052. if (pItem == NULL)
  1053. return false;
  1054.  
  1055. // 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
  1056. if (pItem->GetProto()->cLimitTimerBasedOnWearIndex >= 0)
  1057. {
  1058. return pItem->GetSocket(ITEM_SOCKET_REMAIN_SEC) > 0;
  1059. }
  1060. // 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
  1061. else
  1062. {
  1063. return true;
  1064. }
  1065. }
  1066.  
  1067. bool DSManager::IsActiveDragonSoul(LPITEM pItem) const
  1068. {
  1069. return pItem->GetSocket(ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX);
  1070. }
  1071.  
  1072. bool DSManager::ActivateDragonSoul(LPITEM pItem)
  1073. {
  1074. if (NULL == pItem)
  1075. return false;
  1076. LPCHARACTER pOwner = pItem->GetOwner();
  1077. if (NULL == pOwner)
  1078. return false;
  1079.  
  1080. int deck_idx = pOwner->DragonSoul_GetActiveDeck();
  1081.  
  1082. if (deck_idx < 0)
  1083. return false;
  1084.  
  1085. if (INVENTORY_MAX_NUM + WEAR_MAX_NUM + DS_SLOT_MAX * deck_idx <= pItem->GetCell() &&
  1086. pItem->GetCell() < INVENTORY_MAX_NUM + WEAR_MAX_NUM + DS_SLOT_MAX * (deck_idx + 1))
  1087. {
  1088. if (IsTimeLeftDragonSoul(pItem) && !IsActiveDragonSoul(pItem))
  1089. {
  1090. char buf[128];
  1091. sprintf (buf, "LEFT TIME(%d)", LeftTime(pItem));
  1092. LogManager::instance().ItemLog(pOwner, pItem, "DS_ACTIVATE", buf);
  1093. pItem->ModifyPoints(true);
  1094. pItem->SetSocket(ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX, 1);
  1095.  
  1096. pItem->StartTimerBasedOnWearExpireEvent();
  1097. }
  1098. return true;
  1099. }
  1100. else
  1101. return false;
  1102. }
  1103.  
  1104. bool DSManager::DeactivateDragonSoul(LPITEM pItem, bool bSkipRefreshOwnerActiveState)
  1105. {
  1106. if (NULL == pItem)
  1107. return false;
  1108.  
  1109. LPCHARACTER pOwner = pItem->GetOwner();
  1110. if (NULL == pOwner)
  1111. return false;
  1112.  
  1113. if (!IsActiveDragonSoul(pItem))
  1114. return false;
  1115.  
  1116. char buf[128];
  1117. pItem->StopTimerBasedOnWearExpireEvent();
  1118. pItem->SetSocket(ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX, 0);
  1119. pItem->ModifyPoints(false);
  1120.  
  1121. sprintf (buf, "LEFT TIME(%d)", LeftTime(pItem));
  1122. LogManager::instance().ItemLog(pOwner, pItem, "DS_DEACTIVATE", buf);
  1123.  
  1124. if (false == bSkipRefreshOwnerActiveState)
  1125. RefreshDragonSoulState(pOwner);
  1126.  
  1127. return true;
  1128. }
  1129.  
  1130. void DSManager::RefreshDragonSoulState(LPCHARACTER ch)
  1131. {
  1132. if (NULL == ch)
  1133. return ;
  1134. for (int i = WEAR_MAX_NUM; i < WEAR_MAX_NUM + DS_SLOT_MAX * DRAGON_SOUL_DECK_MAX_NUM; i++)
  1135. {
  1136. LPITEM pItem = ch->GetWear(i);
  1137. if (pItem != NULL)
  1138. {
  1139. if(IsActiveDragonSoul(pItem))
  1140. {
  1141. return;
  1142. }
  1143. }
  1144. }
  1145. ch->DragonSoul_DeactivateAll();
  1146. }
  1147.  
  1148. DSManager::DSManager()
  1149. {
  1150. m_pTable = NULL;
  1151. }
  1152.  
  1153. DSManager::~DSManager()
  1154. {
  1155. if (m_pTable)
  1156. delete m_pTable;
  1157. }
  1158.  
Advertisement
Add Comment
Please, Sign In to add comment