void DSManager::GetDragonSoulInfo(DWORD dwVnum, BYTE& bType, BYTE& bGrade, BYTE& bStep, BYTE& bStrength) const { bType = GetType(dwVnum); bGrade = GetGradeIdx(dwVnum); bStep = GetStepIdx(dwVnum); bStrength = GetStrengthIdx(dwVnum); }
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; } }