/********************************************************************* * date : 2006.11.20 * file : cube.cpp * author : mhh * description : */ #define _cube_cpp_ #include "stdafx.h" #include "constants.h" #include "utils.h" #include "log.h" #include "char.h" #include "dev_log.h" #include "locale_service.h" #include "item.h" #include "item_manager.h" #include extern int test_server; #define RETURN_IF_CUBE_IS_NOT_OPENED(ch) if (!(ch)->IsCubeOpen()) return /*--------------------------------------------------------*/ /* GLOBAL VARIABLES */ /*--------------------------------------------------------*/ static std::vector s_cube_proto; static bool s_isInitializedCubeMaterialInformation = false; /*--------------------------------------------------------*/ /* Cube Material Information */ /*--------------------------------------------------------*/ enum ECubeResultCategory { CUBE_CATEGORY_POTION, // ¾àÃÊ, Áø¾× µîµî.. (Æ÷¼ÇÀ¸·Î ƯÁ¤ÇÒ ¼ö ¾øÀ¸´Ï »ç¿ë ¾È ÇÔ. ¾àÃÊ°°Àº°Ç ´Ù °Á ±âŸ) CUBE_CATEGORY_WEAPON, // ¹«±â CUBE_CATEGORY_ARMOR, // ¹æ¾î±¸ CUBE_CATEGORY_ACCESSORY, // Àå½Å±¸ CUBE_CATEGORY_ETC, // ±âŸ µîµî... }; typedef std::vector TCubeValueVector; struct SCubeMaterialInfo { SCubeMaterialInfo() { bHaveComplicateMaterial = false; }; CUBE_VALUE reward; // º¸»óÀÌ ¹¹³Ä TCubeValueVector material; // Àç·áµéÀº ¹¹³Ä DWORD gold; // µ·Àº ¾ó¸¶µå³Ä TCubeValueVector complicateMaterial; // º¹ÀâÇÑ-_- Àç·áµé // .. Ŭ¶óÀ̾ðÆ®¿¡¼­ Àç·á¸¦ º¸¿©ÁÖ±â À§ÇÏ¿© ¾à¼ÓÇÑ Æ÷¸Ë // 72723,1&72724,2&72730,1 // 52001,1|52002,1|52003,1&72723,1&72724,5 // => ( 52001,1 or 52002,1 or 52003,1 ) and 72723,1 and 72724,5 std::string infoText; bool bHaveComplicateMaterial; // }; struct SItemNameAndLevel { SItemNameAndLevel() { level = 0; } std::string name; int level; }; // ÀڷᱸÁ¶³ª ÀÌ·±°Å º´½ÅÀ롂 ÀÌÇØÁ»... ´©±¸¶«¿¡ ¿µÈ¥ÀÌ ¾ø´Â »óÅ¿¡¼­ ¸¸µé¾ú¾¸ typedef std::vector TCubeResultList; typedef std::unordered_map TCubeMapByNPC; // °¢°¢ÀÇ NPCº°·Î ¾î¶² °É ¸¸µé ¼ö ÀÖ°í Àç·á°¡ ¹ºÁö... typedef std::unordered_map TCubeResultInfoTextByNPC; // °¢°¢ÀÇ NPCº°·Î ¸¸µé ¼ö ÀÖ´Â ¸ñ·ÏÀ» Á¤ÇØÁø Æ÷¸ËÀ¸·Î Á¤¸®ÇÑ Á¤º¸ TCubeMapByNPC cube_info_map; TCubeResultInfoTextByNPC cube_result_info_map_by_npc; // ³×ÀÌ¹Ö Á¸³ª º´½Å°°´Ù ¤»¤»¤» class CCubeMaterialInfoHelper { public: public: }; /*--------------------------------------------------------*/ /* STATIC FUNCTIONS */ /*--------------------------------------------------------*/ // ÇÊ¿äÇÑ ¾ÆÀÌÅÛ °³¼ö¸¦ °¡Áö°íÀִ°¡? static bool FN_check_item_count (LPITEM *items, DWORD item_vnum, int need_count) { int count = 0; // for all cube for (int i=0; iGetVnum()) { count += items[i]->GetCount(); } } return (count>=need_count); } // Å¥ºê³»ÀÇ Àç·á¸¦ Áö¿î´Ù. static void FN_remove_material (LPITEM *items, DWORD item_vnum, int need_count) { int count = 0; LPITEM item = NULL; // for all cube for (int i=0; iGetVnum()) { count += item->GetCount(); if (count>need_count) { item->SetCount(count-need_count); return; } else { item->SetCount(0); items[i] = NULL; } } } } static CUBE_DATA* FN_find_cube (LPITEM *items, WORD npc_vnum) { DWORD i, end_index; if (0==npc_vnum) return NULL; // FOR ALL CUBE_PROTO end_index = s_cube_proto.size(); for (i=0; ican_make_item(items, npc_vnum) ) return s_cube_proto[i]; } return NULL; } static bool FN_check_valid_npc( WORD vnum ) { for ( std::vector::iterator iter = s_cube_proto.begin(); iter != s_cube_proto.end(); iter++ ) { if ( std::find((*iter)->npc_vnum.begin(), (*iter)->npc_vnum.end(), vnum) != (*iter)->npc_vnum.end() ) return true; } return false; } // Å¥ºêµ¥ÀÌŸ°¡ ¿Ã¹Ù¸£°Ô ÃʱâÈ­ µÇ¾ú´ÂÁö üũÇÑ´Ù. static bool FN_check_cube_data (CUBE_DATA *cube_data) { DWORD i = 0; DWORD end_index = 0; end_index = cube_data->npc_vnum.size(); for (i=0; inpc_vnum[i] == 0 ) return false; } end_index = cube_data->item.size(); for (i=0; iitem[i].vnum == 0 ) return false; if ( cube_data->item[i].count == 0 ) return false; } end_index = cube_data->reward.size(); for (i=0; ireward[i].vnum == 0 ) return false; if ( cube_data->reward[i].count == 0 ) return false; } return true; } CUBE_DATA::CUBE_DATA() { this->percent = 0; this->gold = 0; } // ÇÊ¿äÇÑ Àç·áÀÇ ¼ö·®À» ¸¸Á·ÇÏ´ÂÁö üũÇÑ´Ù. bool CUBE_DATA::can_make_item (LPITEM *items, WORD npc_vnum) { // ÇÊ¿äÇÑ Àç·á, ¼ö·®À» ¸¸Á·ÇÏ´ÂÁö üũÇÑ´Ù. DWORD i, end_index; DWORD need_vnum; int need_count; int found_npc = false; // check npc_vnum end_index = this->npc_vnum.size(); for (i=0; inpc_vnum[i]) found_npc = true; } if (false==found_npc) return false; end_index = this->item.size(); for (i=0; iitem[i].vnum; need_count = this->item[i].count; if ( false==FN_check_item_count(items, need_vnum, need_count) ) return false; } return true; } // Å¥ºê¸¦ µ¹·ÈÀ»¶§ ³ª¿À´Â ¾ÆÀÌÅÛÀÇ Á¾·ù¸¦ °áÁ¤ÇÔ CUBE_VALUE* CUBE_DATA::reward_value () { int end_index = 0; DWORD reward_index = 0; end_index = this->reward.size(); reward_index = number(0, end_index); reward_index = number(0, end_index-1); return &this->reward[reward_index]; } // Å¥ºê¿¡ µé¾îÀÖ´Â Àç·á¸¦ Áö¿î´Ù void CUBE_DATA::remove_material (LPCHARACTER ch) { DWORD i, end_index; DWORD need_vnum; int need_count; LPITEM *items = ch->GetCubeItem(); end_index = this->item.size(); for (i=0; iitem[i].vnum; need_count = this->item[i].count; FN_remove_material (items, need_vnum, need_count); } } void Cube_clean_item (LPCHARACTER ch) { LPITEM *cube_item; cube_item = ch->GetCubeItem(); for (int i=0; iGetQuestNPC(); if (NULL==npc) { if (test_server) dev_log(LOG_DEB0, "cube_npc is NULL"); return; } if ( FN_check_valid_npc(npc->GetRaceNum()) == false ) { if ( test_server == true ) { dev_log(LOG_DEB0, "cube not valid NPC"); } return; } if (ch->IsCubeOpen()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀÌ¹Ì Á¦Á¶Ã¢ÀÌ ¿­·ÁÀÖ½À´Ï´Ù.")); return; } if ( ch->GetExchange() || ch->GetMyShop() || ch->GetShopOwner() || ch->IsOpenSafebox() || ch->IsCubeOpen() ) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡Áß(â°í,±³È¯,»óÁ¡)¿¡´Â »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù.")); return; } long distance = DISTANCE_APPROX(ch->GetX() - npc->GetX(), ch->GetY() - npc->GetY()); if (distance >= CUBE_MAX_DISTANCE) { sys_log(1, "CUBE: TOO_FAR: %s distance %d", ch->GetName(), distance); return; } Cube_clean_item(ch); ch->SetCubeNpc(npc); ch->ChatPacket(CHAT_TYPE_COMMAND, "cube open %d", npc->GetRaceNum()); } // Å¥ºê ĵ½½ void Cube_close (LPCHARACTER ch) { RETURN_IF_CUBE_IS_NOT_OPENED(ch); Cube_clean_item(ch); ch->SetCubeNpc(NULL); ch->ChatPacket(CHAT_TYPE_COMMAND, "cube close"); dev_log(LOG_DEB0, " close (%s)", ch->GetName()); } void Cube_init() { CUBE_DATA * p_cube = NULL; std::vector::iterator iter; char file_name[256+1]; snprintf(file_name, sizeof(file_name), "%s/cube.txt", LocaleService_GetBasePath().c_str()); sys_log(0, "Cube_Init %s", file_name); for (iter = s_cube_proto.begin(); iter!=s_cube_proto.end(); iter++) { p_cube = *iter; M2_DELETE(p_cube); } s_cube_proto.clear(); if (false == Cube_load(file_name)) sys_err("Cube_Init failed"); } bool Cube_load (const char *file) { FILE *fp; char one_line[256]; int value1, value2; const char *delim = " \t\r\n"; char *v, *token_string; CUBE_DATA *cube_data = NULL; CUBE_VALUE cube_value = {0,0}; if (0 == file || 0 == file[0]) return false; if ((fp = fopen(file, "r")) == 0) return false; while (fgets(one_line, 256, fp)) { value1 = value2 = 0; if (one_line[0] == '#') continue; token_string = strtok(one_line, delim); if (NULL == token_string) continue; // set value1, value2 if ((v = strtok(NULL, delim))) str_to_number(value1, v); if ((v = strtok(NULL, delim))) str_to_number(value2, v); TOKEN("section") { cube_data = M2_NEW CUBE_DATA; } else TOKEN("npc") { cube_data->npc_vnum.push_back((WORD)value1); } else TOKEN("item") { cube_value.vnum = value1; cube_value.count = value2; cube_data->item.push_back(cube_value); } else TOKEN("reward") { cube_value.vnum = value1; cube_value.count = value2; cube_data->reward.push_back(cube_value); } else TOKEN("percent") { cube_data->percent = value1; } else TOKEN("gold") { // Á¦Á¶¿¡ ÇÊ¿äÇÑ ±Ý¾× cube_data->gold = value1; } else TOKEN("end") { // TODO : check cube data if (false == FN_check_cube_data(cube_data)) { dev_log(LOG_DEB0, "something wrong"); M2_DELETE(cube_data); continue; } s_cube_proto.push_back(cube_data); } } fclose(fp); return true; } static void FN_cube_print (CUBE_DATA *data, DWORD index) { DWORD i; dev_log(LOG_DEB0, "--------------------------------"); dev_log(LOG_DEB0, "CUBE_DATA[%d]", index); for (i=0; inpc_vnum.size(); ++i) { dev_log(LOG_DEB0, "\tNPC_VNUM[%d] = %d", i, data->npc_vnum[i]); } for (i=0; iitem.size(); ++i) { dev_log(LOG_DEB0, "\tITEM[%d] = (%d, %d)", i, data->item[i].vnum, data->item[i].count); } for (i=0; ireward.size(); ++i) { dev_log(LOG_DEB0, "\tREWARD[%d] = (%d, %d)", i, data->reward[i].vnum, data->reward[i].count); } dev_log(LOG_DEB0, "\tPERCENT = %d", data->percent); dev_log(LOG_DEB0, "--------------------------------"); } void Cube_print () { for (DWORD i=0; iIsCubeOpen()) return false; LPCHARACTER npc = ch->GetQuestNPC(); if (NULL == npc) return false; CUBE_DATA* cube = FN_find_cube(ch->GetCubeItem(), npc->GetRaceNum()); if (NULL == cube) { ch->ChatPacket(CHAT_TYPE_COMMAND, "cube info 0 0 0"); return false; } ch->ChatPacket(CHAT_TYPE_COMMAND, "cube info %d %d %d", cube->gold, 0, 0); return true; } // return new item bool Cube_make (LPCHARACTER ch) { // ÁÖ¾îÁø ¾ÆÀÌÅÛÀ» ÇÊ¿ä·ÎÇÏ´Â Á¶ÇÕÀ» ã´Â´Ù. (Å¥ºêµ¥ÀÌŸ·Î ĪÇÔ) // Å¥ºê µ¥ÀÌŸ°¡ ÀÖ´Ù¸é ¾ÆÀÌÅÛÀÇ Àç·á¸¦ üũÇÑ´Ù. // »õ·Î¿î ¾ÆÀÌÅÛÀ» ¸¸µç´Ù. // »õ·Î¿î ¾ÆÀÌÅÛ Áö±Þ LPCHARACTER npc; int percent_number = 0; CUBE_DATA *cube_proto; LPITEM *items; LPITEM new_item; if (!(ch)->IsCubeOpen()) { (ch)->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Á¦Á¶Ã¢ÀÌ ¿­·ÁÀÖÁö ¾Ê½À´Ï´Ù")); return false; } npc = ch->GetQuestNPC(); if (NULL == npc) { return false; } items = ch->GetCubeItem(); cube_proto = FN_find_cube(items, npc->GetRaceNum()); if (NULL == cube_proto) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Á¦Á¶ Àç·á°¡ ºÎÁ·ÇÕ´Ï´Ù")); return false; } if (ch->GetGold() < cube_proto->gold) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("µ·ÀÌ ºÎÁ·Çϰųª ¾ÆÀÌÅÛÀÌ Á¦ÀÚ¸®¿¡ ¾ø½À´Ï´Ù.")); // ÀÌ ÅؽºÆ®´Â ÀÌ¹Ì ³Î¸® ¾²À̴°Ŷó Ãß°¡¹ø¿ª ÇÊ¿ä ¾øÀ½ return false; } CUBE_VALUE *reward_value = cube_proto->reward_value(); // »ç¿ëµÇ¾ú´ø Àç·á¾ÆÀÌÅÛ »èÁ¦ cube_proto->remove_material (ch); // Á¦Á¶½Ã ÇÊ¿äÇÑ °ñµå Â÷°¨ if (0 < cube_proto->gold) ch->PointChange(POINT_GOLD, -(cube_proto->gold), false); percent_number = number(1,100); if ( percent_number<=cube_proto->percent) { // ¼º°ø ch->ChatPacket(CHAT_TYPE_COMMAND, "cube success %d %d", reward_value->vnum, reward_value->count); new_item = ch->AutoGiveItem(reward_value->vnum, reward_value->count); LogManager::instance().CubeLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(), reward_value->vnum, new_item->GetID(), reward_value->count, 1); return true; } else { // ½ÇÆÐ ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Á¦Á¶¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù.")); // 2012.11.12 »õ·Î Ãß°¡µÈ ¸Þ¼¼Áö (locale_string.txt ¿¡ Ãß°¡ÇØ¾ß ÇÔ) ch->ChatPacket(CHAT_TYPE_COMMAND, "cube fail"); LogManager::instance().CubeLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(), reward_value->vnum, 0, 0, 0); return false; } return false; } // Å¥ºê¿¡ ÀÖ´Â ¾ÆÀÌÅÛµéÀ» Ç¥½Ã void Cube_show_list (LPCHARACTER ch) { LPITEM *cube_item; LPITEM item; RETURN_IF_CUBE_IS_NOT_OPENED(ch); cube_item = ch->GetCubeItem(); for (int i=0; iChatPacket(CHAT_TYPE_INFO, "cube[%d]: inventory[%d]: %s", i, item->GetCell(), item->GetName()); } } // Àκ¥Å丮¿¡ ÀÖ´Â ¾ÆÀÌÅÛÀ» Å¥ºê¿¡ µî·Ï void Cube_add_item (LPCHARACTER ch, int cube_index, int inven_index) { // ¾ÆÀÌÅÛÀÌ Àִ°¡? // Å¥ºê³»ÀÇ ºóÀÚ¸® ã±â // Å¥ºê¼¼Æà // ¸Þ½ÃÁö Àü¼Û LPITEM item; LPITEM *cube_item; RETURN_IF_CUBE_IS_NOT_OPENED(ch); if (inven_index<0 || INVENTORY_MAX_NUM<=inven_index) return; if (cube_index<0 || CUBE_MAX_NUM<=cube_index) return; item = ch->GetInventoryItem(inven_index); if (NULL==item) return; cube_item = ch->GetCubeItem(); // ÀÌ¹Ì ´Ù¸¥À§Ä¡¿¡ µî·ÏµÇ¾ú´ø ¾ÆÀÌÅÛÀÌ¸é ±âÁ¸ indext»èÁ¦ for (int i=0; iChatPacket(CHAT_TYPE_INFO, "cube[%d]: inventory[%d]: %s added", cube_index, inven_index, item->GetName()); // ÇöÀç »óÀÚ¿¡ ¿Ã¶ó¿Â ¾ÆÀÌÅÛµé·Î ¹«¾ùÀ» ¸¸µé ¼ö ÀÖ´ÂÁö Ŭ¶óÀ̾ðÆ®¿¡ Á¤º¸ Àü´Þ // À» ÇÏ°í½Í¾úÀ¸³ª ±×³É ÇÊ¿äÇÑ °ñµå°¡ ¾ó¸¶ÀÎÁö Àü´Þ FN_update_cube_status(ch); return; } // Å¥ºê¿¡ÀÖ´Â ¾ÆÀÌÅÛÀ» Á¦°Å void Cube_delete_item (LPCHARACTER ch, int cube_index) { LPITEM item; LPITEM *cube_item; RETURN_IF_CUBE_IS_NOT_OPENED(ch); if (cube_index<0 || CUBE_MAX_NUM<=cube_index) return; cube_item = ch->GetCubeItem(); if ( NULL== cube_item[cube_index] ) return; item = cube_item[cube_index]; cube_item[cube_index] = NULL; if (test_server) ch->ChatPacket(CHAT_TYPE_INFO, "cube[%d]: cube[%d]: %s deleted", cube_index, item->GetCell(), item->GetName()); // ÇöÀç »óÀÚ¿¡ ¿Ã¶ó¿Â ¾ÆÀÌÅÛµé·Î ¹«¾ùÀ» ¸¸µé ¼ö ÀÖ´ÂÁö Ŭ¶óÀ̾ðÆ®¿¡ Á¤º¸ Àü´Þ // À» ÇÏ°í½Í¾úÀ¸³ª ±×³É ÇÊ¿äÇÑ °ñµå°¡ ¾ó¸¶ÀÎÁö Àü´Þ FN_update_cube_status(ch); return; } // ¾ÆÀÌÅÛ À̸§À» ÅëÇؼ­ ¼ø¼ö À̸§°ú °­È­·¹º§À» ºÐ¸®ÇÏ´Â ÇÔ¼ö (¹«½Ö°Ë+5 -> ¹«½Ö°Ë, 5) SItemNameAndLevel SplitItemNameAndLevelFromName(const std::string& name) { int level = 0; SItemNameAndLevel info; info.name = name; size_t pos = name.find("+"); if (std::string::npos != pos) { const std::string levelStr = name.substr(pos + 1, name.size() - pos - 1); str_to_number(level, levelStr.c_str()); info.name = name.substr(0, pos); } info.level = level; return info; }; bool FIsEqualCubeValue(const CUBE_VALUE& a, const CUBE_VALUE& b) { return (a.vnum == b.vnum) && (a.count == b.count); } bool FIsLessCubeValue(const CUBE_VALUE& a, const CUBE_VALUE& b) { return a.vnum < b.vnum; } void Cube_MakeCubeInformationText() { // ÀÌÁ¦ Á¤¸®µÈ Å¥ºê °á°ú ¹× Àç·áµéÀÇ Á¤º¸·Î Ŭ¶óÀ̾ðÆ®¿¡ º¸³» ÁÙ Á¤º¸·Î º¯È¯ÇÔ. for (TCubeMapByNPC::iterator iter = cube_info_map.begin(); cube_info_map.end() != iter; ++iter) { const DWORD& npcVNUM = iter->first; TCubeResultList& resultList = iter->second; for (TCubeResultList::iterator resultIter = resultList.begin(); resultList.end() != resultIter; ++resultIter) { SCubeMaterialInfo& materialInfo = *resultIter; std::string& infoText = materialInfo.infoText; // À̳ðÀÌ ³ª»Û³ðÀÌ¾ß if (0 < materialInfo.complicateMaterial.size()) { std::sort(materialInfo.complicateMaterial.begin(), materialInfo.complicateMaterial.end(), FIsLessCubeValue); std::sort(materialInfo.material.begin(), materialInfo.material.end(), FIsLessCubeValue); //// Áߺ¹µÇ´Â Àç·áµéÀ» Áö¿ò for (TCubeValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter) { for (TCubeValueVector::iterator targetIter = materialInfo.material.begin(); materialInfo.material.end() != targetIter; ++targetIter) { if (*targetIter == *iter) { targetIter = materialInfo.material.erase(targetIter); } } } // 72723,1 or 72725,1 or ... ÀÌ·± ½ÄÀÇ ¾à¼ÓµÈ Æ÷¸ËÀ» ÁöÅ°´Â ÅؽºÆ®¸¦ »ý¼º for (TCubeValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter) { char tempBuffer[128]; sprintf(tempBuffer, "%d,%d|", iter->vnum, iter->count); infoText += std::string(tempBuffer); } infoText.erase(infoText.size() - 1); if (0 < materialInfo.material.size()) infoText.push_back('&'); } // Áߺ¹µÇÁö ¾Ê´Â ÀÏ¹Ý Àç·áµéµµ Æ÷¸Ë »ý¼º for (TCubeValueVector::iterator iter = materialInfo.material.begin(); materialInfo.material.end() != iter; ++iter) { char tempBuffer[128]; sprintf(tempBuffer, "%d,%d&", iter->vnum, iter->count); infoText += std::string(tempBuffer); } infoText.erase(infoText.size() - 1); // ¸¸µé ¶§ °ñµå°¡ ÇÊ¿äÇÏ´Ù¸é °ñµåÁ¤º¸ Ãß°¡ if (0 < materialInfo.gold) { char temp[128]; sprintf(temp, "%d", materialInfo.gold); infoText += std::string("/") + temp; } //sys_err("\t\tNPC: %d, Reward: %d(%s)\n\t\t\tInfo: %s", npcVNUM, materialInfo.reward.vnum, ITEM_MANAGER::Instance().GetTable(materialInfo.reward.vnum)->szName, materialInfo.infoText.c_str()); } // for resultList } // for npc } bool Cube_InformationInitialize() { for (int i = 0; i < s_cube_proto.size(); ++i) { CUBE_DATA* cubeData = s_cube_proto[i]; const std::vector& rewards = cubeData->reward; // ÇϵåÄÚµù ¤¸¤µ if (1 != rewards.size()) { sys_err("[CubeInfo] WARNING! Does not support multiple rewards (count: %d)", rewards.size()); continue; } //if (1 != cubeData->npc_vnum.size()) //{ // sys_err("[CubeInfo] WARNING! Does not support multiple NPC (count: %d)", cubeData->npc_vnum.size()); // continue; //} const CUBE_VALUE& reward = rewards.at(0); const WORD& npcVNUM = cubeData->npc_vnum.at(0); bool bComplicate = false; TCubeMapByNPC& cubeMap = cube_info_map; TCubeResultList& resultList = cubeMap[npcVNUM]; SCubeMaterialInfo materialInfo; materialInfo.reward = reward; materialInfo.gold = cubeData->gold; materialInfo.material = cubeData->item; for (TCubeResultList::iterator iter = resultList.begin(); resultList.end() != iter; ++iter) { SCubeMaterialInfo& existInfo = *iter; // ÀÌ¹Ì Áߺ¹µÇ´Â º¸»óÀÌ µî·ÏµÇ¾î ÀÖ´Ù¸é ¾Æ¿¹ ´Ù¸¥ Á¶ÇÕÀ¸·Î ¸¸µå´Â °ÍÀÎÁö, // °ÅÀÇ °°Àº Á¶ÇÕÀε¥ ƯÁ¤ ºÎºÐ¸¸ Ʋ¸° °ÍÀÎÁö ±¸ºÐÇÔ. // ¿¹¸¦µé¸é ƯÁ¤ ºÎºÐ¸¸ Ʋ¸° ¾ÆÀÌÅÛµéÀº ¾Æ·¡Ã³·³ Çϳª·Î ¹­¾î¼­ ÇϳªÀÇ °á°ú·Î º¸¿©ÁÖ±â À§ÇÔÀÓ: // ¿ë½ÅÁö°Ë: // ¹«½Ö°Ë+5 ~ +9 x 1 // ºÓÀº Ä®ÀÚ·ç Á¶°¢ x1 // ³ì»ö °ËÀå½Ä Á¶°¢ x1 if (reward.vnum == existInfo.reward.vnum) { for (TCubeValueVector::iterator existMaterialIter = existInfo.material.begin(); existInfo.material.end() != existMaterialIter; ++existMaterialIter) { TItemTable* existMaterialProto = ITEM_MANAGER::Instance().GetTable(existMaterialIter->vnum); if (NULL == existMaterialProto) { sys_err("There is no item(%u)", existMaterialIter->vnum); return false; } SItemNameAndLevel existItemInfo = SplitItemNameAndLevelFromName(existMaterialProto->szName); if (0 < existItemInfo.level) { // Áö±Ý Ãß°¡Çϴ ťºê °á°ú¹°ÀÇ Àç·á¿Í, ±âÁ¸¿¡ µî·ÏµÇ¾îÀÖ´ø Å¥ºê °á°ú¹°ÀÇ Àç·á Áß // Áߺ¹µÇ´Â ºÎºÐÀÌ ÀÖ´ÂÁö °Ë»öÇÑ´Ù for (TCubeValueVector::iterator currentMaterialIter = materialInfo.material.begin(); materialInfo.material.end() != currentMaterialIter; ++currentMaterialIter) { TItemTable* currentMaterialProto = ITEM_MANAGER::Instance().GetTable(currentMaterialIter->vnum); SItemNameAndLevel currentItemInfo = SplitItemNameAndLevelFromName(currentMaterialProto->szName); if (currentItemInfo.name == existItemInfo.name) { bComplicate = true; existInfo.complicateMaterial.push_back(*currentMaterialIter); if (std::find(existInfo.complicateMaterial.begin(), existInfo.complicateMaterial.end(), *existMaterialIter) == existInfo.complicateMaterial.end()) existInfo.complicateMaterial.push_back(*existMaterialIter); //currentMaterialIter = materialInfo.material.erase(currentMaterialIter); // TODO: Áߺ¹µÇ´Â ¾ÆÀÌÅÛ µÎ °³ ÀÌ»ó °ËÃâÇØ¾ß µÉ ¼öµµ ÀÖÀ½ break; } } // for currentMaterialIter } // if level } // for existMaterialInfo } // if (reward.vnum == existInfo.reward.vnum) } // for resultList if (false == bComplicate) resultList.push_back(materialInfo); } Cube_MakeCubeInformationText(); s_isInitializedCubeMaterialInformation = true; return true; } // Ŭ¶óÀ̾ðÆ®¿¡¼­ ¼­¹ö·Î : ÇöÀç NPC°¡ ¸¸µé ¼ö ÀÖ´Â ¾ÆÀÌÅÛµéÀÇ Á¤º¸(¸ñ·Ï)¸¦ ¿äû void Cube_request_result_list(LPCHARACTER ch) { RETURN_IF_CUBE_IS_NOT_OPENED(ch); LPCHARACTER npc = ch->GetQuestNPC(); if (NULL == npc) return; DWORD npcVNUM = npc->GetRaceNum(); size_t resultCount = 0; std::string& resultText = cube_result_info_map_by_npc[npcVNUM]; // ÇØ´ç NPC°¡ ¸¸µé ¼ö ÀÖ´Â ¸ñ·ÏÀÌ Á¤¸®µÈ °Ô ¾ø´Ù¸é ij½Ã¸¦ »ý¼º if (resultText.length() == 0) { resultText.clear(); const TCubeResultList& resultList = cube_info_map[npcVNUM]; for (TCubeResultList::const_iterator iter = resultList.begin(); resultList.end() != iter; ++iter) { const SCubeMaterialInfo& materialInfo = *iter; char temp[128]; sprintf(temp, "%d,%d", materialInfo.reward.vnum, materialInfo.reward.count); resultText += std::string(temp) + "/"; } resultCount = resultList.size(); resultText.erase(resultText.size() - 1); // äÆà ÆÐŶÀÇ ÇѰ踦 ³Ñ¾î°¡¸é ¿¡·¯ ³²±è... ±âȹÀÚ ºÐµé ²² Á¶Á¤ÇØ´Þ¶ó°í ¿äûÇϰųª, ³ªÁß¿¡ ´Ù¸¥ ¹æ½ÄÀ¸·Î ¹Ù²Ù°Å³ª... if (resultText.size() - 20 >= CHAT_MAX_LEN) { sys_err("[CubeInfo] Too long cube result list text. (NPC: %d, length: %d)", npcVNUM, resultText.size()); resultText.clear(); resultCount = 0; } } // ÇöÀç NPC°¡ ¸¸µé ¼ö ÀÖ´Â ¾ÆÀÌÅÛµéÀÇ ¸ñ·ÏÀ» ¾Æ·¡ Æ÷¸ËÀ¸·Î Àü¼ÛÇÑ´Ù. // (Server -> Client) /cube r_list npcVNUM resultCount vnum1,count1/vnum2,count2,/vnum3,count3/... // (Server -> Client) /cube r_list 20383 4 123,1/125,1/128,1/130,5 ch->ChatPacket(CHAT_TYPE_COMMAND, "cube r_list %d %d %s", npcVNUM, resultCount, resultText.c_str()); } // void Cube_request_material_info(LPCHARACTER ch, int requestStartIndex, int requestCount) { RETURN_IF_CUBE_IS_NOT_OPENED(ch); LPCHARACTER npc = ch->GetQuestNPC(); if (NULL == npc) return; DWORD npcVNUM = npc->GetRaceNum(); std::string materialInfoText = ""; int index = 0; bool bCatchInfo = false; const TCubeResultList& resultList = cube_info_map[npcVNUM]; for (TCubeResultList::const_iterator iter = resultList.begin(); resultList.end() != iter; ++iter) { const SCubeMaterialInfo& materialInfo = *iter; if (index++ == requestStartIndex) { bCatchInfo = true; } if (bCatchInfo) { materialInfoText += materialInfo.infoText + "@"; } if (index >= requestStartIndex + requestCount) break; } if (false == bCatchInfo) { sys_err("[CubeInfo] Can't find matched material info (NPC: %d, index: %d, request count: %d)", npcVNUM, requestStartIndex, requestCount); return; } materialInfoText.erase(materialInfoText.size() - 1); // // (Server -> Client) /cube m_info start_index count 125,1|126,2|127,2|123,5&555,5&555,4/120000 if (materialInfoText.size() - 20 >= CHAT_MAX_LEN) { sys_err("[CubeInfo] Too long material info. (NPC: %d, requestStart: %d, requestCount: %d, length: %d)", npcVNUM, requestStartIndex, requestCount, materialInfoText.size()); } ch->ChatPacket(CHAT_TYPE_COMMAND, "cube m_info %d %d %s", requestStartIndex, requestCount, materialInfoText.c_str()); }