// їлИҐј®А» №ЮѕЖј їлЅЙА» ГЯГвЗПґВ ЗФјц bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor) { if (NULL == ch || NULL == pItem) return false; if (pItem->IsEquipped()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Вшїл БЯАО їлИҐј®Ає ГЯГвЗТ јц ѕшЅАґПґЩ.")); return false; } DWORD dwVnum = pItem->GetVnum(); BYTE ds_type, grade_idx, step_idx, strength_idx; GetDragonSoulInfo(dwVnum, ds_type, grade_idx, step_idx, strength_idx); int iBonus = 0; if (NULL != pExtractor) { iBonus = pExtractor->GetValue(0); } std::vector <float> vec_chargings; std::vector <float> vec_probs; if (!m_pTable->GetDragonHeartExtValues(ds_type, grade_idx, vec_chargings, vec_probs)) { return false; } int idx = Gamble(vec_probs); float sum = 0.f; if (-1 == idx) { sys_err ("Gamble is failed. ds_type(%d), grade_idx(%d)", ds_type, grade_idx); return false; } float fCharge = vec_chargings[idx] * (100 + iBonus) / 100.f; fCharge = std::MINMAX <float> (0.f, fCharge, 100.f); if (fCharge < FLT_EPSILON) { pItem->SetCount(pItem->GetCount() - 1); if (NULL != pExtractor) { pExtractor->SetCount(pExtractor->GetCount() - 1); } LogManager::instance().ItemLog(ch, pItem, "DS_HEART_EXTRACT_FAIL", ""); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("їлЅЙ ГЯГвїЎ ЅЗЖРЗПїґЅАґПґЩ.")); return false; } else { LPITEM pDH = ITEM_MANAGER::instance().CreateItem(DRAGON_HEART_VNUM); if (NULL == pDH) { sys_err ("Cannot create DRAGON_HEART(%d).", DRAGON_HEART_VNUM); return NULL; } pItem->SetCount(pItem->GetCount() - 1); if (NULL != pExtractor) { pExtractor->SetCount(pExtractor->GetCount() - 1); } int iCharge = (int)(fCharge + 0.5f); pDH->SetSocket(ITEM_SOCKET_CHARGING_AMOUNT_IDX, iCharge); ch->AutoGiveItem(pDH, true); std::string s = boost::lexical_cast <std::string> (iCharge); s += "%s"; LogManager::instance().ItemLog(ch, pItem, "DS_HEART_EXTRACT_SUCCESS", s.c_str()); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("їлЅЙ ГЯГвїЎ јє°шЗПїґЅАґПґЩ.")); return true; } }
bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]) { if (NULL == ch) return false; if (NULL == aItemPoses) { return false; } if (!ch->DragonSoul_RefineWindow_CanRefine()) { sys_err ("%s do not activate DragonSoulRefineWindow. But how can he come here?", ch->GetName()); ch->ChatPacket(CHAT_TYPE_INFO, "[SYSTEM ERROR]You cannot use dragon soul refine window."); return false; } // И¤ЅГіЄ ёрё¦ БЯє№µЗґВ item pointer ѕшѕЦ±в А§ЗШј set »зїл // АМ»уЗС ЖРЕ¶А» єёіѕ °жїм, БЯє№µИ TItemPos°Ў АЦА» јцµµ АЦ°н, АЯёшµИ TItemPos°Ў АЦА» јцµµ АЦґЩ. std::set <LPITEM> set_items; for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++) { LPITEM pItem = ch->GetItem(aItemPoses[i]); if (NULL != pItem) { // їлИҐј®АМ ѕЖґС ѕЖАМЕЫАМ °і·®ГўїЎ АЦА» јц ѕшґЩ. if (!pItem->IsDragonSoul()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ґЬ°и °і·®їЎ ЗКїдЗС Аз·б°Ў ѕЖґХґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } set_items.insert(pItem); } } if (set_items.size() == 0) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS); return false; } std::string stGroupName; int count = set_items.size(); int need_count = 0; int fee = 0; std::vector <float> vec_probs; BYTE ds_type, grade_idx, step_idx, strength_idx; int result_step; // °ЎАе ГіАЅ °НА» °ИАЗ ±вБШАё·О »пґВґЩ. std::set <LPITEM>::iterator it = set_items.begin(); { LPITEM pItem = *it; GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx); if (!m_pTable->GetRefineStepValues(ds_type, step_idx, need_count, fee, vec_probs)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ґЬ°и °і·®ЗТ јц ѕшґВ їлИҐј®АФґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } } while(++it != set_items.end()) { LPITEM pItem = *it; // Е¬¶у uiїЎј АеВшЗС ѕЖАМЕЫАє °і·®ГўїЎ їГё± јц ѕшµµ·П ё·ѕТ±в ¶§№®їЎ, // є°µµАЗ ѕЛёІ Гіё®ґВ ѕИЗФ. if (pItem->IsEquipped()) { return false; } if (ds_type != GetType(pItem->GetVnum()) || grade_idx != GetGradeIdx(pItem->GetVnum()) || step_idx != GetStepIdx(pItem->GetVnum())) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ґЬ°и °і·®їЎ ЗКїдЗС Аз·б°Ў ѕЖґХґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } } // Е¬¶уїЎј ЗС№ш °№јц ГјЕ©ё¦ ЗП±в ¶§№®їЎ count != need_count¶уёй invalid Е¬¶уАП °ЎґЙјєАМ Е©ґЩ. if (count != need_count) { sys_err ("Possiblity of invalid client. Name %s", ch->GetName()); BYTE bSubHeader = count < need_count? DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL : DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL; SendRefineResultPacket(ch, bSubHeader, NPOS); return false; } if (ch->GetGold() < fee) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°і·®А» ЗП±в А§ЗС µ·АМ єОБ·ЗХґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS); return false; } float sum = 0.f; if (-1 == (result_step = Gamble(vec_probs))) { sys_err ("Gamble failed. See RefineStepTables' probabilities"); return false; } LPITEM pResultItem = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(ds_type, grade_idx, (BYTE)result_step, 0)); if (NULL == pResultItem) { sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(ds_type, grade_idx, (BYTE)result_step, 0)); return false; } ch->PointChange(POINT_GOLD, -fee); int left_count = need_count; for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++) { LPITEM pItem = *it; int n = pItem->GetCount(); if (left_count > n) { pItem->RemoveFromCharacter(); M2_DESTROY_ITEM(pItem); left_count -= n; } else { pItem->SetCount(n - left_count); } } ch->AutoGiveItem(pResultItem, true); if (result_step > step_idx) { char buf[128]; sprintf(buf, "STEP : %d -> %d", step_idx, result_step); LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_SUCCESS", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ґЬ°и °і·®їЎ јє°шЗЯЅАґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_SUCCEED, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell())); return true; } else { char buf[128]; sprintf(buf, "STEP : %d -> %d", step_idx, result_step); LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_FAIL", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ґЬ°и °і·®їЎ ЅЗЖРЗЯЅАґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell())); return false; } }
bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]) { if (NULL == ch) return false; if (NULL == aItemPoses) { return false; } if (!ch->DragonSoul_RefineWindow_CanRefine()) { sys_err ("%s do not activate DragonSoulRefineWindow. But how can he come here?", ch->GetName()); ch->ChatPacket(CHAT_TYPE_INFO, "[SYSTEM ERROR]You cannot use dragon soul refine window."); return false; } // 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용 // 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다. std::set <LPITEM> set_items; for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++) { LPITEM pItem = ch->GetItem(aItemPoses[i]); if (NULL != pItem) { // 용혼석이 아닌 아이템이 개량창에 있을 수 없다. if (!pItem->IsDragonSoul()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } set_items.insert(pItem); } } if (set_items.size() == 0) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS); return false; } std::string stGroupName; int count = set_items.size(); int need_count = 0; int fee = 0; std::vector <float> vec_probs; BYTE ds_type, grade_idx, step_idx, strength_idx; int result_step; // 가장 처음 것을 강화의 기준으로 삼는다. std::set <LPITEM>::iterator it = set_items.begin(); { LPITEM pItem = *it; GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx); if (!m_pTable->GetRefineStepValues(ds_type, step_idx, need_count, fee, vec_probs)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량할 수 없는 용혼석입니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } } while(++it != set_items.end()) { LPITEM pItem = *it; // 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에, // 별도의 알림 처리는 안함. if (pItem->IsEquipped()) { return false; } if (ds_type != GetType(pItem->GetVnum()) || grade_idx != GetGradeIdx(pItem->GetVnum()) || step_idx != GetStepIdx(pItem->GetVnum())) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 필요한 재료가 아닙니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } } // 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다. if (count != need_count) { sys_err ("Possiblity of invalid client. Name %s", ch->GetName()); BYTE bSubHeader = count < need_count? DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL : DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL; SendRefineResultPacket(ch, bSubHeader, NPOS); return false; } if (ch->GetGold() < fee) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("개량을 하기 위한 돈이 부족합니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MONEY, NPOS); return false; } float sum = 0.f; if (-1 == (result_step = Gamble(vec_probs))) { sys_err ("Gamble failed. See RefineStepTables' probabilities"); return false; } LPITEM pResultItem = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(ds_type, grade_idx, (BYTE)result_step, 0)); if (NULL == pResultItem) { sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(ds_type, grade_idx, (BYTE)result_step, 0)); return false; } ch->PointChange(POINT_GOLD, -fee); int left_count = need_count; for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++) { LPITEM pItem = *it; int n = pItem->GetCount(); if (left_count > n) { pItem->RemoveFromCharacter(); M2_DESTROY_ITEM(pItem); left_count -= n; } else { pItem->SetCount(n - left_count); } } ch->AutoGiveItem(pResultItem, true); if (result_step > step_idx) { char buf[128]; sprintf(buf, "STEP : %d -> %d", step_idx, result_step); LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_SUCCESS", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 성공했습니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_SUCCEED, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell())); return true; } else { char buf[128]; sprintf(buf, "STEP : %d -> %d", step_idx, result_step); LogManager::instance().ItemLog(ch, pResultItem, "DS_STEP_REFINE_FAIL", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("단계 개량에 실패했습니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL, TItemPos (pResultItem->GetWindow(), pResultItem->GetCell())); return false; } }