bool IsDragonSoulRefineMaterial(LPITEM pItem) { if (pItem->GetType() != ITEM_MATERIAL) return false; return (pItem->GetSubType() == MATERIAL_DS_REFINE_NORMAL || pItem->GetSubType() == MATERIAL_DS_REFINE_BLESSED || pItem->GetSubType() == MATERIAL_DS_REFINE_HOLLY); }
DWORD ani_attack_speed(LPCHARACTER ch) { DWORD speed = 1000; if (NULL == ch) return speed; LPITEM item = ch->GetWear(WEAR_WEAPON); if (NULL == item) return speed; if (ITEM_WEAPON != item->GetType()) return speed; int race = ch->GetRaceNum(); int weapon = item->GetSubType(); /* dev_log(LOG_DEB0, "%s : (race,weapon) = (%s,%s) POINT_ATT_SPEED = %d", ch->GetName(), FN_race_name(race), FN_weapon_type(weapon), ch->GetPoint(POINT_ATT_SPEED)); */ /* ЕхЗЪµрµе јТµеАЗ °жїм »пї¬Вь°ш°Э°ъ ЅВё¶ЅГ */ /* їА·щ°Ў ё№ѕЖ ЗСјХ°Л јУµµ·О »э°ўЗПАЪ */ if (weapon == WEAPON_TWO_HANDED) weapon = WEAPON_SWORD; return s_ANI.attack_speed(race, weapon); }
DWORD GET_ATTACK_SPEED(LPCHARACTER ch) { if (NULL == ch) return 1000; LPITEM item = ch->GetWear(WEAR_WEAPON); DWORD default_bonus = SPEEDHACK_LIMIT_BONUS; // 유두리 공속(기본 80) DWORD riding_bonus = 0; if (ch->IsRiding()) { // 뭔가를 탔으면 추가공속 50 riding_bonus = 50; } DWORD ani_speed = ani_attack_speed(ch); DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus); // 단검의 경우 공속 2배 if (item && item->GetSubType() == WEAPON_DAGGER) real_speed /= 2; return real_speed; }
DWORD GET_ATTACK_SPEED(LPCHARACTER ch) { if (NULL == ch) return 1000; LPITEM item = ch->GetWear(WEAR_WEAPON); DWORD default_bonus = SPEEDHACK_LIMIT_BONUS; // АЇµОё® °шјУ(±вє» 80) DWORD riding_bonus = 0; if (ch->IsRiding()) { // №є°Ўё¦ ЕААёёй ГЯ°Ў°шјУ 50 riding_bonus = 50; } DWORD ani_speed = ani_attack_speed(ch); DWORD real_speed = (ani_speed * 100) / (default_bonus + ch->GetPoint(POINT_ATT_SPEED) + riding_bonus); // ґЬ°ЛАЗ °жїм °шјУ 2№и if (item && item->GetSubType() == WEAPON_DAGGER) real_speed /= 2; return real_speed; }
int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int & iRetDam) { //PROF_UNIT puHit("Hit"); if (test_server) sys_log(0, "battle_hit : [%s] attack to [%s] : dam :%d type :%d", pkAttacker->GetName(), pkVictim->GetName(), iRetDam); int iDam = CalcMeleeDamage(pkAttacker, pkVictim); if (iDam <= 0) return (BATTLE_DAMAGE); NormalAttackAffect(pkAttacker, pkVictim); // 데미지 계산 //iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST)) / 100; LPITEM pkWeapon = pkAttacker->GetWear(WEAR_WEAPON); if (pkWeapon) switch (pkWeapon->GetSubType()) { case WEAPON_SWORD: iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_SWORD)) / 100; break; case WEAPON_TWO_HANDED: iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_TWOHAND)) / 100; break; case WEAPON_DAGGER: iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_DAGGER)) / 100; break; case WEAPON_BELL: iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_BELL)) / 100; break; case WEAPON_FAN: iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_FAN)) / 100; break; case WEAPON_BOW: iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST_BOW)) / 100; break; } //최종적인 데미지 보정. (2011년 2월 현재 대왕거미에게만 적용.) float attMul = pkAttacker->GetAttMul(); float tempIDam = iDam; iDam = attMul * tempIDam + 0.5f; iRetDam = iDam; //PROF_UNIT puDam("Dam"); if (pkVictim->Damage(pkAttacker, iDam, DAMAGE_TYPE_NORMAL)) return (BATTLE_DEAD); return (BATTLE_DAMAGE); }
DWORD ani_combo_speed(LPCHARACTER ch, BYTE combo) { LPITEM item = ch->GetWear(WEAR_WEAPON); if (NULL == item || combo > 8) return 1000; return s_ANI.attack_speed(ch->GetRaceNum(), item->GetSubType(), combo, ch->IsRiding()); }
WORD DSManager::GetBasePosition(const LPITEM pItem) const { if (NULL == pItem) return WORD_MAX; BYTE type, grade_idx, step_idx, strength_idx; GetDragonSoulInfo(pItem->GetVnum(), type, grade_idx, step_idx, strength_idx); BYTE col_type = pItem->GetSubType(); BYTE row_type = grade_idx; if (row_type > DRAGON_SOUL_GRADE_MAX) return WORD_MAX; return col_type * DRAGON_SOUL_STEP_MAX * DRAGON_SOUL_BOX_SIZE + row_type * DRAGON_SOUL_BOX_SIZE; }
bool CItem::CanPutInto(LPITEM item) { if (item->GetType() == ITEM_BELT) return this->GetSubType() == USE_PUT_INTO_BELT_SOCKET; else if(item->GetType() == ITEM_RING) return CanPutIntoRing(item, this); else if (item->GetType() != ITEM_ARMOR) return false; DWORD vnum = item->GetVnum(); struct JewelAccessoryInfo { DWORD jewel; DWORD wrist; DWORD neck; DWORD ear; }; const static JewelAccessoryInfo infos[] = { { 50634, 14420, 16220, 17220 }, { 50635, 14500, 16500, 17500 }, { 50636, 14520, 16520, 17520 }, { 50637, 14540, 16540, 17540 }, { 50638, 14560, 16560, 17560 }, }; DWORD item_type = (item->GetVnum() / 10) * 10; for (unsigned int i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { const JewelAccessoryInfo& info = infos[i]; switch(item->GetSubType()) { case ARMOR_WRIST: if (info.wrist == item_type) { if (info.jewel == GetVnum()) { return true; } else { return false; } } break; case ARMOR_NECK: if (info.neck == item_type) { if (info.jewel == GetVnum()) { return true; } else { return false; } } break; case ARMOR_EAR: if (info.ear == item_type) { if (info.jewel == GetVnum()) { return true; } else { return false; } } break; } } if (item->GetSubType() == ARMOR_WRIST) vnum -= 14000; else if (item->GetSubType() == ARMOR_NECK) vnum -= 16000; else if (item->GetSubType() == ARMOR_EAR) vnum -= 17000; else return false; DWORD type = vnum / 20; if (type < 0 || type > 11) { type = (vnum - 170) / 20; if (50623 + type != GetVnum()) return false; else return true; } else if (item->GetVnum() >= 16210 && item->GetVnum() <= 16219) { if (50625 != GetVnum()) return false; else return true; } else if (item->GetVnum() >= 16230 && item->GetVnum() <= 16239) { if (50626 != GetVnum()) return false; else return true; } return 50623 + type == GetVnum(); }
int CalcArrowDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, LPITEM pkBow, LPITEM pkArrow, bool bIgnoreDefense) { if (!pkBow || pkBow->GetType() != ITEM_WEAPON || pkBow->GetSubType() != WEAPON_BOW) return 0; if (!pkArrow) return 0; // 타격치 계산부 int iDist = (int) (DISTANCE_SQRT(pkAttacker->GetX() - pkVictim->GetX(), pkAttacker->GetY() - pkVictim->GetY())); //int iGap = (iDist / 100) - 5 - pkBow->GetValue(5) - pkAttacker->GetPoint(POINT_BOW_DISTANCE); int iGap = (iDist / 100) - 5 - pkAttacker->GetPoint(POINT_BOW_DISTANCE); int iPercent = 100 - (iGap * 5); if (iPercent <= 0) return 0; else if (iPercent > 100) iPercent = 100; int iDam = 0; float fAR = CalcAttackRating(pkAttacker, pkVictim, false); iDam = number(pkBow->GetValue(3), pkBow->GetValue(4)) * 2 + pkArrow->GetValue(3); int iAtk; // level must be ignored when multiply by fAR, so subtract it before calculation. iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2); iAtk = (int) (iAtk * fAR); iAtk += pkAttacker->GetLevel() * 2; // and add again // Refine Grade iAtk += pkBow->GetValue(5) * 2; iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS); iAtk = (int) (iAtk * (100 + (pkAttacker->GetPoint(POINT_ATT_BONUS) + pkAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100); iAtk = CalcAttBonus(pkAttacker, pkVictim, iAtk); int iDef = 0; if (!bIgnoreDefense) iDef = (pkVictim->GetPoint(POINT_DEF_GRADE) * (100 + pkAttacker->GetPoint(POINT_DEF_BONUS)) / 100); if (pkAttacker->IsNPC()) iAtk = (int) (iAtk * pkAttacker->GetMobDamageMultiply()); iDam = MAX(0, iAtk - iDef); int iPureDam = iDam; iPureDam = (iPureDam * iPercent) / 100; if (test_server) { pkAttacker->ChatPacket(CHAT_TYPE_INFO, "ARROW %s -> %s, DAM %d DIST %d GAP %d %% %d", pkAttacker->GetName(), pkVictim->GetName(), iPureDam, iDist, iGap, iPercent); } return iPureDam; //return iDam; }
int CalcMeleeDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreDefense, bool bIgnoreTargetRating) { LPITEM pWeapon = pkAttacker->GetWear(WEAR_WEAPON); bool bPolymorphed = pkAttacker->IsPolymorphed(); if (pWeapon && !(bPolymorphed && !pkAttacker->IsPolyMaintainStat())) { if (pWeapon->GetType() != ITEM_WEAPON) return 0; switch (pWeapon->GetSubType()) { case WEAPON_SWORD: case WEAPON_DAGGER: case WEAPON_TWO_HANDED: case WEAPON_BELL: case WEAPON_FAN: case WEAPON_MOUNT_SPEAR: break; case WEAPON_BOW: sys_err("CalcMeleeDamage should not handle bows (name: %s)", pkAttacker->GetName()); return 0; default: return 0; } } int iDam = 0; float fAR = CalcAttackRating(pkAttacker, pkVictim, bIgnoreTargetRating); int iDamMin = 0, iDamMax = 0; // TESTSERVER_SHOW_ATTACKINFO int DEBUG_iDamCur = 0; int DEBUG_iDamBonus = 0; // END_OF_TESTSERVER_SHOW_ATTACKINFO if (bPolymorphed && !pkAttacker->IsPolyMaintainStat()) { // MONKEY_ROD_ATTACK_BUG_FIX Item_GetDamage(pWeapon, &iDamMin, &iDamMax); // END_OF_MONKEY_ROD_ATTACK_BUG_FIX DWORD dwMobVnum = pkAttacker->GetPolymorphVnum(); const CMob * pMob = CMobManager::instance().Get(dwMobVnum); if (pMob) { int iPower = pkAttacker->GetPolymorphPower(); iDamMin += pMob->m_table.dwDamageRange[0] * iPower / 100; iDamMax += pMob->m_table.dwDamageRange[1] * iPower / 100; } } else if (pWeapon) { // MONKEY_ROD_ATTACK_BUG_FIX Item_GetDamage(pWeapon, &iDamMin, &iDamMax); // END_OF_MONKEY_ROD_ATTACK_BUG_FIX } else if (pkAttacker->IsNPC()) { iDamMin = pkAttacker->GetMobDamageMin(); iDamMax = pkAttacker->GetMobDamageMax(); } iDam = number(iDamMin, iDamMax) * 2; // TESTSERVER_SHOW_ATTACKINFO DEBUG_iDamCur = iDam; // END_OF_TESTSERVER_SHOW_ATTACKINFO // int iAtk = 0; // level must be ignored when multiply by fAR, so subtract it before calculation. iAtk = pkAttacker->GetPoint(POINT_ATT_GRADE) + iDam - (pkAttacker->GetLevel() * 2); iAtk = (int) (iAtk * fAR); iAtk += pkAttacker->GetLevel() * 2; // and add again if (pWeapon) { iAtk += pWeapon->GetValue(5) * 2; // 2004.11.12.myevan.TESTSERVER_SHOW_ATTACKINFO DEBUG_iDamBonus = pWeapon->GetValue(5) * 2; /////////////////////////////////////////////// } iAtk += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS); // party attacker role bonus iAtk = (int) (iAtk * (100 + (pkAttacker->GetPoint(POINT_ATT_BONUS) + pkAttacker->GetPoint(POINT_MELEE_MAGIC_ATT_BONUS_PER))) / 100); iAtk = CalcAttBonus(pkAttacker, pkVictim, iAtk); int iDef = 0; if (!bIgnoreDefense) { iDef = (pkVictim->GetPoint(POINT_DEF_GRADE) * (100 + pkVictim->GetPoint(POINT_DEF_BONUS)) / 100); if (!pkAttacker->IsPC()) iDef += pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_DEFENSE_BONUS); } if (pkAttacker->IsNPC()) iAtk = (int) (iAtk * pkAttacker->GetMobDamageMultiply()); iDam = MAX(0, iAtk - iDef); if (test_server) { int DEBUG_iLV = pkAttacker->GetLevel()*2; int DEBUG_iST = int((pkAttacker->GetPoint(POINT_ATT_GRADE) - DEBUG_iLV) * fAR); int DEBUG_iPT = pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS); int DEBUG_iWP = 0; int DEBUG_iPureAtk = 0; int DEBUG_iPureDam = 0; char szRB[32] = ""; char szGradeAtkBonus[32] = ""; DEBUG_iWP = int(DEBUG_iDamCur * fAR); DEBUG_iPureAtk = DEBUG_iLV + DEBUG_iST + DEBUG_iWP+DEBUG_iDamBonus; DEBUG_iPureDam = iAtk - iDef; if (pkAttacker->IsNPC()) { snprintf(szGradeAtkBonus, sizeof(szGradeAtkBonus), "=%d*%.1f", DEBUG_iPureAtk, pkAttacker->GetMobDamageMultiply()); DEBUG_iPureAtk = int(DEBUG_iPureAtk * pkAttacker->GetMobDamageMultiply()); } if (DEBUG_iDamBonus != 0) snprintf(szRB, sizeof(szRB), "+RB(%d)", DEBUG_iDamBonus); char szPT[32] = ""; if (DEBUG_iPT != 0) snprintf(szPT, sizeof(szPT), ", PT=%d", DEBUG_iPT); char szUnknownAtk[32] = ""; if (iAtk != DEBUG_iPureAtk) snprintf(szUnknownAtk, sizeof(szUnknownAtk), "+?(%d)", iAtk-DEBUG_iPureAtk); char szUnknownDam[32] = ""; if (iDam != DEBUG_iPureDam) snprintf(szUnknownDam, sizeof(szUnknownDam), "+?(%d)", iDam-DEBUG_iPureDam); char szMeleeAttack[128]; snprintf(szMeleeAttack, sizeof(szMeleeAttack), "%s(%d)-%s(%d)=%d%s, ATK=LV(%d)+ST(%d)+WP(%d)%s%s%s, AR=%.3g%s", pkAttacker->GetName(), iAtk, pkVictim->GetName(), iDef, iDam, szUnknownDam, DEBUG_iLV, DEBUG_iST, DEBUG_iWP, szRB, szUnknownAtk, szGradeAtkBonus, fAR, szPT); pkAttacker->ChatPacket(CHAT_TYPE_TALKING, "%s", szMeleeAttack); pkVictim->ChatPacket(CHAT_TYPE_TALKING, "%s", szMeleeAttack); } return CalcBattleDamage(iDam, pkAttacker->GetLevel(), pkVictim->GetLevel()); }
bool DSManager::DoRefineStrength(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 (pItem) { set_items.insert(pItem); } } if (set_items.size() == 0) { return false; } int fee; LPITEM pRefineStone = NULL; LPITEM pDragonSoul = NULL; for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++) { LPITEM pItem = *it; // Е¬¶у uiїЎј АеВшЗС ѕЖАМЕЫАє °і·®ГўїЎ їГё± јц ѕшµµ·П ё·ѕТ±в ¶§№®їЎ, // є°µµАЗ ѕЛёІ Гіё®ґВ ѕИЗФ. if (pItem->IsEquipped()) { return false; } // їлИҐј®°ъ °Иј®ёёАМ °і·®ГўїЎ АЦА» јц АЦґЩ. // ±Чё®°н ЗПіЄѕїёё АЦѕоѕЯЗСґЩ. if (pItem->IsDragonSoul()) { if (pDragonSoul != NULL) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } pDragonSoul = pItem; } else if(IsDragonSoulRefineMaterial(pItem)) { if (pRefineStone != NULL) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } pRefineStone = pItem; } else { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°ИїЎ ЗКїдЗС Аз·б°Ў ѕЖґХґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } } BYTE bType, bGrade, bStep, bStrength; if (!pDragonSoul || !pRefineStone) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS); return false; } if (NULL != pDragonSoul) { GetDragonSoulInfo(pDragonSoul->GetVnum(), bType, bGrade, bStep, bStrength); float fWeight = 0.f; // °ЎБЯДЎ °ЄАМ ѕшґЩёй °ИЗТ јц ѕшґВ їлИҐј® if (!m_pTable->GetWeight(bType, bGrade, bStep, bStrength + 1, fWeight)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°ИЗТ јц ѕшґВ їлИҐј®АФґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell())); return false; } // °ИЗЯА» ¶§ °ЎБЯДЎ°Ў 0АМ¶уёй ґх АМ»у °ИµЗјґВ ѕИµИґЩ. if (fWeight < FLT_EPSILON) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°ИЗТ јц ѕшґВ їлИҐј®АФґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell())); return false; } } float fProb; if (!m_pTable->GetRefineStrengthValues(bType, pRefineStone->GetSubType(), bStrength, fee, fProb)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°ИЗТ јц ѕшґВ їлИҐј®АФґПґЩ.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell())); 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; } ch->PointChange(POINT_GOLD, -fee); LPITEM pResult = NULL; BYTE bSubHeader; if (fnumber(0.f, 100.f) <= fProb) { pResult = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(bType, bGrade, bStep, bStrength + 1)); if (NULL == pResult) { sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(bType, bGrade, bStep, bStrength + 1)); return false; } pDragonSoul->RemoveFromCharacter(); pDragonSoul->CopyAttributeTo(pResult); RefreshItemAttributes(pResult); pDragonSoul->SetCount(pDragonSoul->GetCount() - 1); pRefineStone->SetCount(pRefineStone->GetCount() - 1); char buf[128]; sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength + 1); LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_SUCCESS", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°ИїЎ јє°шЗЯЅАґПґЩ.")); ch->AutoGiveItem(pResult, true); bSubHeader = DS_SUB_HEADER_REFINE_SUCCEED; } else { if (bStrength != 0) { pResult = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(bType, bGrade, bStep, bStrength - 1)); if (NULL == pResult) { sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(bType, bGrade, bStep, bStrength - 1)); return false; } pDragonSoul->CopyAttributeTo(pResult); RefreshItemAttributes(pResult); } bSubHeader = DS_SUB_HEADER_REFINE_FAIL; char buf[128]; sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength - 1); // strength°ИґВ ЅЗЖРЅГ ±ъБъ јцµµ АЦѕо, їшє» ѕЖАМЕЫА» №ЩЕБАё·О ·О±Чё¦ іІ±и. LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_FAIL", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°ИїЎ ЅЗЖРЗЯЅАґПґЩ.")); pDragonSoul->SetCount(pDragonSoul->GetCount() - 1); pRefineStone->SetCount(pRefineStone->GetCount() - 1); if (NULL != pResult) ch->AutoGiveItem(pResult, true); } SendRefineResultPacket(ch, bSubHeader, NULL == pResult? NPOS : TItemPos (pResult->GetWindow(), pResult->GetCell())); return true; }
bool DSManager::DoRefineStrength(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 (pItem) { set_items.insert(pItem); } } if (set_items.size() == 0) { return false; } int fee; LPITEM pRefineStone = NULL; LPITEM pDragonSoul = NULL; for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++) { LPITEM pItem = *it; // 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에, // 별도의 알림 처리는 안함. if (pItem->IsEquipped()) { return false; } // 용혼석과 강화석만이 개량창에 있을 수 있다. // 그리고 하나씩만 있어야한다. if (pItem->IsDragonSoul()) { if (pDragonSoul != NULL) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } pDragonSoul = pItem; } else if(IsDragonSoulRefineMaterial(pItem)) { if (pRefineStone != NULL) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_TOO_MUCH_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } pRefineStone = pItem; } else { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 필요한 재료가 아닙니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pItem->GetWindow(), pItem->GetCell())); return false; } } BYTE bType, bGrade, bStep, bStrength; if (!pDragonSoul || !pRefineStone) { SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_NOT_ENOUGH_MATERIAL, NPOS); return false; } if (NULL != pDragonSoul) { GetDragonSoulInfo(pDragonSoul->GetVnum(), bType, bGrade, bStep, bStrength); float fWeight = 0.f; // 가중치 값이 없다면 강화할 수 없는 용혼석 if (!m_pTable->GetWeight(bType, bGrade, bStep, bStrength + 1, fWeight)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell())); return false; } // 강화했을 때 가중치가 0이라면 더 이상 강화되서는 안된다. if (fWeight < FLT_EPSILON) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell())); return false; } } float fProb; if (!m_pTable->GetRefineStrengthValues(bType, pRefineStone->GetSubType(), bStrength, fee, fProb)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화할 수 없는 용혼석입니다.")); SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_INVALID_MATERIAL, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell())); 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; } ch->PointChange(POINT_GOLD, -fee); LPITEM pResult = NULL; BYTE bSubHeader; if (fnumber(0.f, 100.f) <= fProb) { pResult = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(bType, bGrade, bStep, bStrength + 1)); if (NULL == pResult) { sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(bType, bGrade, bStep, bStrength + 1)); return false; } pDragonSoul->RemoveFromCharacter(); pDragonSoul->CopyAttributeTo(pResult); RefreshItemAttributes(pResult); pDragonSoul->SetCount(pDragonSoul->GetCount() - 1); pRefineStone->SetCount(pRefineStone->GetCount() - 1); char buf[128]; sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength + 1); LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_SUCCESS", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 성공했습니다.")); ch->AutoGiveItem(pResult, true); bSubHeader = DS_SUB_HEADER_REFINE_SUCCEED; } else { if (bStrength != 0) { pResult = ITEM_MANAGER::instance().CreateItem(MakeDragonSoulVnum(bType, bGrade, bStep, bStrength - 1)); if (NULL == pResult) { sys_err ("INVALID DRAGON SOUL(%d)", MakeDragonSoulVnum(bType, bGrade, bStep, bStrength - 1)); return false; } pDragonSoul->CopyAttributeTo(pResult); RefreshItemAttributes(pResult); } bSubHeader = DS_SUB_HEADER_REFINE_FAIL; char buf[128]; sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength - 1); // strength강화는 실패시 깨질 수도 있어, 원본 아이템을 바탕으로 로그를 남김. LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_FAIL", buf); ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("강화에 실패했습니다.")); pDragonSoul->SetCount(pDragonSoul->GetCount() - 1); pRefineStone->SetCount(pRefineStone->GetCount() - 1); if (NULL != pResult) ch->AutoGiveItem(pResult, true); } SendRefineResultPacket(ch, bSubHeader, NULL == pResult? NPOS : TItemPos (pResult->GetWindow(), pResult->GetCell())); return true; }