#include #include #include #include #include "ContentLoader.h" #include "MixManager.h" #include "StructItem.h" #include "GameDBUtil.h" #include "StructPlayer.h" #include "GlobalVariableManager.h" #include "DBPerformanceTracker.h" #include "ADOConnection.h" typedef KHash< _MARKET_INFO* , hashPr_string_nocase > MARKET_HASH; static MARKET_HASH & getMarketHash() { static MARKET_HASH _inst; return _inst; } struct lessByMarketIndex : public std::binary_function< _MARKET_INFO::_MARKET_TAG, _MARKET_INFO::_MARKET_TAG, bool > { result_type operator() ( first_argument_type a, second_argument_type b ) { return a.index < b.index; } }; void AddMarketInfo( const char *szMarketName, int index, ItemBase::ItemCode code, const StructGold & price, const int huntaholic_point, const int arena_point) { _MARKET_INFO *pInfo = GameContent::GetMarketInfo(szMarketName); if( !pInfo ) { pInfo = new _MARKET_INFO( szMarketName ); getMarketHash().add( szMarketName, pInfo ); } pInfo->vItemList.push_back(_MARKET_INFO::_MARKET_TAG(index, code, price, huntaholic_point, arena_point)); std::sort( pInfo->vItemList.begin(), pInfo->vItemList.end(), lessByMarketIndex() ); } _MARKET_INFO * GameContent::GetMarketInfo( const char *szMarketName ) { _MARKET_INFO *pInfo = NULL; if( !szMarketName ) return NULL; getMarketHash().lookup( szMarketName, pInfo ); return pInfo; } struct dbMarket : public CADORecordBinding { char szMarketName[61]; int nIndex; ItemBase::ItemCode nCode; _decimal_variant fPriceRatio; _decimal_variant fHuntaholicRatio; _decimal_variant fArenaRatio; BEGIN_ADO_BINDING(dbMarket) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, nIndex, sizeof(nIndex), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(2, adVarChar, szMarketName, _countof(szMarketName), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(3, adInteger, nCode, sizeof(nCode), FALSE) ADO_NUMERIC_ENTRY2(4, adDecimal, fPriceRatio, 10, 3, FALSE) ADO_NUMERIC_ENTRY2(5, adDecimal, fHuntaholicRatio, 10, 3, FALSE) ADO_NUMERIC_ENTRY2(6, adDecimal, fArenaRatio, 10, 3, FALSE) END_ADO_BINDING() }; void onMarketInfo( dbMarket * emprs ) { const ItemBaseServer &itemBase = StructItem::GetItemBase( emprs->nCode ); if( itemBase.nCode != emprs->nCode ) return; // Market information registration c_fixed10 fPriceRatio; fPriceRatio.set( emprs->fPriceRatio.getMultipleInteger( 10000 ) ); c_fixed10 fHuntaholicRatio; fHuntaholicRatio.set( emprs->fHuntaholicRatio.getMultipleInteger( 10000 ) ); c_fixed10 fArenaRatio; fArenaRatio.set( emprs->fArenaRatio.getMultipleInteger( 10000 ) ); StructGold nDefaultPrice( itemBase.nPrice ); AddMarketInfo( emprs->szMarketName, emprs->nIndex, emprs->nCode, StructGold( fPriceRatio * nDefaultPrice.GetRawData() ), fHuntaholicRatio * itemBase.nHuntaholicPoint, fArenaRatio * itemBase.nArenaPoint ); } void onMarketDeleteInfo(dbMarket* emprs) { const ItemBaseServer& itemBase = StructItem::GetItemBase(emprs->nCode); if (itemBase.nCode != emprs->nCode) return; // 마켓 정보 등록 c_fixed10 fPriceRatio; fPriceRatio.set(emprs->fPriceRatio.getMultipleInteger(10000)); c_fixed10 fHuntaholicRatio; fHuntaholicRatio.set(emprs->fHuntaholicRatio.getMultipleInteger(10000)); c_fixed10 fArenaRatio; fArenaRatio.set(emprs->fArenaRatio.getMultipleInteger(10000)); StructGold nDefaultPrice(itemBase.nPrice); _MARKET_INFO* pInfo = NULL; if (pInfo = GameContent::GetMarketInfo(emprs->szMarketName)) { pInfo->vItemList.clear(); } } void LoadMarketData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); //size_t cnt0 = LoadDbResource< dbMarket >("MarketResource", ConnPtr, onMarketDeleteInfo); size_t cnt = LoadDbResource< dbMarket >( "MarketResource", ConnPtr, onMarketInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d Market info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d Market info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d Market info loaded...\n", cnt ); FILELOG( "Total %d Market info loaded...", cnt ); #endif } struct dbLevelUpTable : public CADORecordBinding { int level; __int64 exp; __int64 jp[4]; BEGIN_ADO_BINDING(dbLevelUpTable) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, level, sizeof(level), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(2, adBigInt, exp, sizeof(exp), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(3, adBigInt, jp[0], sizeof(jp), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(4, adBigInt, jp[1], sizeof(jp), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(5, adBigInt, jp[2], sizeof(jp), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(6, adBigInt, jp[3], sizeof(jp), FALSE) END_ADO_BINDING() }; struct dbSummonLevelUpTable : public CADORecordBinding { int level; __int64 normal_exp; __int64 growth_exp; __int64 evolve_exp; BEGIN_ADO_BINDING(dbSummonLevelUpTable) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, level, sizeof(level), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(2, adBigInt, normal_exp, sizeof(normal_exp), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(3, adBigInt, growth_exp, sizeof(growth_exp), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(4, adBigInt, evolve_exp, sizeof(evolve_exp), FALSE) END_ADO_BINDING() }; void onLevelUpTableInfo( dbLevelUpTable * emprs ) { // 경험치 정보 등록 GameContent::RegisterExpTable( emprs->level, emprs->exp, emprs->jp[0], emprs->jp[1], emprs->jp[2], emprs->jp[3] ); } void onSummonLevelUpTableInfo( dbSummonLevelUpTable * emprs ) { GameContent::RegisterSummonExpTable( emprs->level, emprs->normal_exp, emprs->growth_exp, emprs->evolve_exp ); } void LoadLevelUpTableData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); size_t cnt = LoadDbResource< dbLevelUpTable >( "LevelResource", ConnPtr, onLevelUpTableInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d LevelUpTable info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d LevelUpTable info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d LevelUpTable info loaded...\n", cnt ); FILELOG( "Total %d LevelUpTable info loaded...", cnt ); #endif } void LoadSummonLevelUpTableData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); size_t cnt = LoadDbResource< dbSummonLevelUpTable >( "SummonLevelResource", ConnPtr, onSummonLevelUpTableInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d SummonLevelUpTable info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d SummonLevelUpTable info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d SummonLevelUpTable info loaded...\n", cnt ); FILELOG( "Total %d SummonLevelUpTable info loaded...", cnt ); #endif } struct dbStateInfo : public CADORecordBinding, public StateInfo { BEGIN_ADO_BINDING(dbStateInfo) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, id, sizeof(id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(2, adInteger, name_id, sizeof(name_id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(3, adInteger, tooltip_id, sizeof(tooltip_id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(4, adBoolean, is_harmful, sizeof(is_harmful), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(5, adInteger, state_time_type, sizeof(state_time_type), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(6, adInteger, state_group, sizeof(state_group), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(7, adInteger, duplicate_group[0], sizeof(duplicate_group[0]), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(8, adInteger, duplicate_group[1], sizeof(duplicate_group[1]), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(9, adInteger, duplicate_group[2], sizeof(duplicate_group[2]), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(10, adTinyInt, uf_avatar, sizeof(uf_avatar), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(11, adTinyInt, uf_summon, sizeof(uf_summon), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(12, adTinyInt, uf_monster, sizeof(uf_monster), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(13, adSmallInt, reiteration_count, sizeof(reiteration_count), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(14, adInteger, base_effect_id, sizeof(base_effect_id), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(15, adInteger, fire_interval, sizeof(fire_interval), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(16, adInteger, elemental_type, sizeof(elemental_type), FALSE) ADO_NUMERIC_ENTRY2( 17, adDecimal, cst_amplify_base, 13, 3, FALSE) ADO_NUMERIC_ENTRY2( 18, adDecimal, cst_amplify_per_skl, 13, 3, FALSE) ADO_VARIABLE_LENGTH_ENTRY4(19, adInteger, add_damage_base, sizeof(add_damage_base), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(20, adInteger, add_damage_per_skl, sizeof(add_damage_per_skl), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(21, adInteger, effect_type, sizeof(effect_type), FALSE) ADO_NUMERIC_ENTRY2( 22, adDecimal, cst_var[0], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 23, adDecimal, cst_var[1], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 24, adDecimal, cst_var[2], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 25, adDecimal, cst_var[3], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 26, adDecimal, cst_var[4], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 27, adDecimal, cst_var[5], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 28, adDecimal, cst_var[6], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 29, adDecimal, cst_var[7], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 30, adDecimal, cst_var[8], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 31, adDecimal, cst_var[9], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 32, adDecimal, cst_var[10], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 33, adDecimal, cst_var[11], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 34, adDecimal, cst_var[12], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 35, adDecimal, cst_var[13], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 36, adDecimal, cst_var[14], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 37, adDecimal, cst_var[15], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 38, adDecimal, cst_var[16], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 39, adDecimal, cst_var[17], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 40, adDecimal, cst_var[18], 13,3,FALSE) ADO_NUMERIC_ENTRY2( 41, adDecimal, cst_var[19], 13,3,FALSE) END_ADO_BINDING() _decimal_variant cst_var[ StateInfo::MAX_STATE_VALUE ]; _decimal_variant cst_amplify_base; _decimal_variant cst_amplify_per_skl; }; void onStateInfo( dbStateInfo * emprs ) { for( int i = 0 ; i < StateInfo::MAX_STATE_VALUE ; ++i ) { emprs->fValue[i].set( emprs->cst_var[i].getMultipleInteger( 10000 ) ); } emprs->amplify_base.set( emprs->cst_amplify_base.getMultipleInteger( 10000 ) ); emprs->amplify_per_skl.set( emprs->cst_amplify_per_skl.getMultipleInteger( 10000 ) ); // 지속효과 소멸 시 로그 남겨야 하는지에 대한 설정 별도 로딩 처리 // * 런타임 성능을 위해 지속효과 소멸 시 마다 설정 리스트를 체크하지 않고 StateInfo에 미리 세팅해 둠 { // 로딩 중에 GameRule::strLogRequiredStateList가 바뀔 일은 없다고 가정하고 static std::set 컨테이너에 토큰화시켜서 담아놓고 처리 함 static bool bInitComplete = false; static std::set< int /* StructState::StateCode */ > setLogRequiredStateList; // 최초 1회만 토큰화 처리 적용 if( !bInitComplete ) { bInitComplete = true; std::vector< std::string > vTokenList; XStringUtil::Split( GameRule::strLogRequiredStateList.c_str(), vTokenList, "|", false ); for( std::vector< std::string >::const_iterator it = vTokenList.begin() ; it != vTokenList.end() ; ++it ) { int nStateID = atoi( (*it).c_str() ); if( nStateID ) setLogRequiredStateList.insert( nStateID ); } } if( setLogRequiredStateList.size() && setLogRequiredStateList.find( emprs->id ) != setLogRequiredStateList.end() ) emprs->is_log_required_on_expiration = true; else emprs->is_log_required_on_expiration = false; } // 일어설 때 삭제되는 지속효과라면 반드시 로그아웃 시에도 사라지는 지속효과여야 한다. // 현재는 앉기 여부를 저장하기 않기 때문에 로그인 시에는 무조건 일어선 상태일 것이고 만약 로그아웃 시에 삭제가 되지 않았다면 일어선 채로 일어선 상대에서 부여될 수 없는 지속효과가 걸릴 것이기 때문이다. // 물론 일어설 때 삭제되는 플래그가 설정되어있다면 로그아웃 시에 알아서 제거해줘도 되겠지만, // 제어할 수 있는 별도의 플래그가 존재하며 앉기와 로그아웃은 개념상으로 완벽히 분리된 내용이기 때문에 굳이 파악하기 힘든 연관 관계를 만들지 않고 기획 데이터에 의존한다. assert( !( emprs->state_time_type & StateInfo::ERASE_ON_STAND_UP ) || ( emprs->state_time_type & StateInfo::ERASE_ON_LOGOUT ) ); GameContent::RegisterStateInfo( *emprs ); } void LoadStateData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); size_t cnt = LoadDbResource< dbStateInfo >( "StateResource", ConnPtr, onStateInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d State info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d State info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d State info loaded...\n", cnt ); FILELOG( "Total %d State info loaded...", cnt ); #endif } struct dbStatInfo : public CADORecordBinding, public CreatureStat { BEGIN_ADO_BINDING(dbStatInfo) ADO_VARIABLE_LENGTH_ENTRY4(1, adSmallInt, stat_id, sizeof(stat_id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(2, adSmallInt, strength, sizeof(strength), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(3, adSmallInt, vital, sizeof(vital), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(4, adSmallInt, dexterity, sizeof(dexterity), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(5, adSmallInt, agility, sizeof(agility), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(6, adSmallInt, intelligence, sizeof(intelligence), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(7, adSmallInt, mentality, sizeof(mentality), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(8, adSmallInt, luck, sizeof(luck), FALSE ) END_ADO_BINDING() }; void onStatInfo( dbStatInfo * emprs ) { // 스텟 정보 등록 GameContent::RegisterStatInfo( *emprs ); } void LoadStatData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); size_t cnt = LoadDbResource< dbStatInfo >( "StatResource", ConnPtr, onStatInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d Stat info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d Stat info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d Stat info loaded...\n", cnt ); FILELOG( "Total %d Stat info loaded...", cnt ); #endif } struct dbJobInfo : public CADORecordBinding, public JobInfo { BEGIN_ADO_BINDING(dbJobInfo) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, id, sizeof(id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(2, adInteger, text_id, sizeof(text_id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(3, adInteger, stat_id, sizeof(stat_id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(4, adInteger, skill_tree_id, sizeof(skill_tree_id), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(5, adTinyInt, job_class, sizeof(job_class), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(6, adTinyInt, job_depth, sizeof(job_depth), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(7, adSmallInt, up_lv, sizeof(up_lv), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(8, adSmallInt, up_jlv, sizeof(up_jlv), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(9, adSmallInt, availble_job[0], sizeof(availble_job[0]), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(10, adSmallInt, availble_job[1], sizeof(availble_job[1]), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(11, adSmallInt, availble_job[2], sizeof(availble_job[2]), FALSE ) ADO_VARIABLE_LENGTH_ENTRY4(12, adSmallInt, availble_job[3], sizeof(availble_job[3]), FALSE ) END_ADO_BINDING() }; struct dbJobLevelBonus : public CADORecordBinding, public JobLevelBonus { BEGIN_ADO_BINDING(dbJobLevelBonus) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, job_id, sizeof(job_id), FALSE ) ADO_NUMERIC_ENTRY2(2, adDecimal, dec_str[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(3, adDecimal, dec_vit[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(4, adDecimal, dec_dex[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(5, adDecimal, dec_agi[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(6, adDecimal, dec_int[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(7, adDecimal, dec_men[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(8, adDecimal, dec_luk[0], 10,3,FALSE) ADO_NUMERIC_ENTRY2(9, adDecimal, dec_str[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(10, adDecimal, dec_vit[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(11, adDecimal, dec_dex[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(12, adDecimal, dec_agi[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(13, adDecimal, dec_int[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(14, adDecimal, dec_men[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(15, adDecimal, dec_luk[1], 10,3,FALSE) ADO_NUMERIC_ENTRY2(16, adDecimal, dec_str[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(17, adDecimal, dec_vit[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(18, adDecimal, dec_dex[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(19, adDecimal, dec_agi[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(20, adDecimal, dec_int[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(21, adDecimal, dec_men[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(22, adDecimal, dec_luk[2], 10,3,FALSE) ADO_NUMERIC_ENTRY2(23, adDecimal, dec_str[3], 10,3,FALSE) ADO_NUMERIC_ENTRY2(24, adDecimal, dec_vit[3], 10,3,FALSE) ADO_NUMERIC_ENTRY2(25, adDecimal, dec_dex[3], 10,3,FALSE) ADO_NUMERIC_ENTRY2(26, adDecimal, dec_agi[3], 10,3,FALSE) ADO_NUMERIC_ENTRY2(27, adDecimal, dec_int[3], 10,3,FALSE) ADO_NUMERIC_ENTRY2(28, adDecimal, dec_men[3], 10,3,FALSE) ADO_NUMERIC_ENTRY2(29, adDecimal, dec_luk[3], 10,3,FALSE) END_ADO_BINDING() _decimal_variant dec_str[4]; _decimal_variant dec_vit[4]; _decimal_variant dec_dex[4]; _decimal_variant dec_agi[4]; _decimal_variant dec_int[4]; _decimal_variant dec_men[4]; _decimal_variant dec_luk[4]; }; void onJobInfo( dbJobInfo * emprs ) { // 직업 정보 등록 emprs->skill_tree = NULL; GameContent::RegisterJobInfo( *emprs ); } void onJobLevelBonus( dbJobLevelBonus * emprs ) { for( int i = 0; i < 4; ++i ) { emprs->strength[i] = emprs->dec_str[i].getMultipleInteger( 100 ); emprs->vital[i] = emprs->dec_vit[i].getMultipleInteger( 100 ); emprs->dexterity[i] = emprs->dec_dex[i].getMultipleInteger( 100 ); emprs->agility[i] = emprs->dec_agi[i].getMultipleInteger( 100 ); emprs->intelligence[i] = emprs->dec_int[i].getMultipleInteger( 100 ); emprs->mentality[i] = emprs->dec_men[i].getMultipleInteger( 100 ); emprs->luck[i] = emprs->dec_luk[i].getMultipleInteger( 100 ); } GameContent::RegisterJobLevelBonusInfo( *emprs ); } void LoadJobData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); size_t cnt = LoadDbResource< dbJobInfo >( "JobResource", ConnPtr, onJobInfo ); size_t job_bonus_cnt = LoadDbResource< dbJobLevelBonus >( "JobLevelBonus", ConnPtr, onJobLevelBonus ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d Job info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d Job info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d Job info loaded...\n", cnt ); FILELOG( "Total %d Job info loaded...", cnt ); #endif } struct dbBannedWord : public CADORecordBinding { BEGIN_ADO_BINDING(dbBannedWord) ADO_VARIABLE_LENGTH_ENTRY4(1, adVarWChar, szBannedWord, _countof(szBannedWord) - 1, FALSE) END_ADO_BINDING() wchar_t szBannedWord[512]; }; void onBannedWordInfo( dbBannedWord * emprs ) { // 금지단어 정보 등록(대문자화) wchar_t szUprWord[512]; char szResultWord[512]; s_strcpy( szUprWord, _countof( szUprWord ), emprs->szBannedWord ); s_toupper( szUprWord, _countof( szUprWord ) ); WideCharToMultiByte( ENV().GetInt( "CodePage", CP_ACP ), 0, szUprWord, _countof( szUprWord ), szResultWord, _countof( szResultWord ), NULL, NULL ); GameContent::RegisterBannedWord( szResultWord ); } void LoadBannedWordData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); GameContent::ClearBannedWord(); size_t cnt = LoadDbResource< dbBannedWord >( "BanWordResource", ConnPtr, onBannedWordInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d BannedWord info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d BannedWord info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d BannedWord info loaded...\n", cnt ); FILELOG( "Total %d BannedWord info loaded...", cnt ); #endif } struct dbEnhance : public CADORecordBinding , EnhanceInfo { BEGIN_ADO_BINDING(dbEnhance) ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, nSID, sizeof(nSID), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(3, adInteger, nFailResult, sizeof(nFailResult), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(4, adInteger, nMaxEnhance, sizeof(nMaxEnhance), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(5, adInteger, nLocalFlag, sizeof(nLocalFlag), FALSE) ADO_VARIABLE_LENGTH_ENTRY4(6, adInteger, nNeedItemCode, sizeof(nNeedItemCode), FALSE) ADO_NUMERIC_ENTRY2( 7, adDecimal, cst_var[0], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 8, adDecimal, cst_var[1], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 9, adDecimal, cst_var[2], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 10, adDecimal, cst_var[3], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 11, adDecimal, cst_var[4], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 12, adDecimal, cst_var[5], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 13, adDecimal, cst_var[6], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 14, adDecimal, cst_var[7], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 15, adDecimal, cst_var[8], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 16, adDecimal, cst_var[9], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 17, adDecimal, cst_var[10], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 18, adDecimal, cst_var[11], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 19, adDecimal, cst_var[12], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 20, adDecimal, cst_var[13], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 21, adDecimal, cst_var[14], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 22, adDecimal, cst_var[15], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 23, adDecimal, cst_var[16], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 24, adDecimal, cst_var[17], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 25, adDecimal, cst_var[18], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 26, adDecimal, cst_var[19], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 27, adDecimal, cst_var[20], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 28, adDecimal, cst_var[21], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 29, adDecimal, cst_var[22], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 30, adDecimal, cst_var[23], 10,5,FALSE) ADO_NUMERIC_ENTRY2( 31, adDecimal, cst_var[24], 10,5,FALSE) END_ADO_BINDING() _decimal_variant cst_var[25]; }; void onEnhanceInfo( dbEnhance * emprs ) { extern volatile int g_nCurrentLocalFlag; if( !(emprs->nLocalFlag & g_nCurrentLocalFlag ) ) return; for( int i = 0; i < 25; ++i ) { emprs->fPercentage[i].set( emprs->cst_var[i].getMultipleInteger( 10000 ) ); } MixManager::RegisterEnhanceInfo( *emprs ); } void LoadEnhanceData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif _ConnectionPtr ConnPtr = NULL; InitContentDbConnection( ConnPtr ); size_t cnt = LoadDbResource< dbEnhance >( "EnhanceResource", ConnPtr, onEnhanceInfo ); #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d Enhance info loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d Enhance info loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d Enhance info loaded...\n", cnt ); FILELOG( "Total %d Enhance info loaded...", cnt ); #endif } void LoadAutoAccountData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif DBConnection db; InitUserDbConnection( db.connection ); if( db.CreateCommand( db.command ) == false ) throw XException( "LoadAutoAccountData : CreateInstance(command) error" ); // 느린 쿼리 타임아웃 조정 db.command->CommandTimeout = 60; db.command->CommandType = adCmdStoredProc; db.command->CommandText = _bstr_t( "dbo.smp_read_auto_account_list" ); _RecordsetPtr pRS = db.command->Execute(NULL,NULL,adCmdStoredProc); unsigned cnt = 0; while( pRS->State != adStateClosed && !pRS->EndOfFile ) { StructPlayer::AddToAutoAccountList( pRS->Fields->Item["account_id"]->Value ); pRS->MoveNext(); ++cnt; } #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d Auto account loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d Auto account loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d Auto account loaded...\n", cnt ); FILELOG( "Total %d Auto account loaded...", cnt ); #endif } void LoadGlobalVariableData() { #ifdef FRAUN_PERFORMANCE_LOG DWORD dwTime = GetSafeTickCount(); #endif DBConnection db; InitUserDbConnection( db.connection ); if( db.CreateCommand( db.command ) == false ) throw XException( "LoadGlobalVariableData : CreateInstance(command) error" ); db.command->CommandType = adCmdTable; db.command->CommandText = _bstr_t( "dbo.GlobalVariable" ); _RecordsetPtr pRS = db.command->Execute( NULL, NULL, adCmdTable ); size_t cnt = 0; while( pRS->State != adStateClosed && !pRS->EndOfFile ) { GVM().Set( _bstr_t( pRS->Fields->Item["name"]->Value.bstrVal ), _bstr_t( pRS->Fields->Item["value"]->Value.bstrVal ), true ); pRS->MoveNext(); ++cnt; } #ifdef FRAUN_PERFORMANCE_LOG DWORD loadingTime = GetSafeTickCount() - dwTime; _cprint("Total %d GlobalVariables loaded; time taken: %d\n", cnt, loadingTime); FILELOG("Total %d GlobalVariables loaded; time taken: %d", cnt, loadingTime); #else _cprint( "Total %d GlobalVariables loaded...\n", cnt ); FILELOG( "Total %d GlobalVariables loaded...", cnt ); #endif } bool ETCLoader::onProcess( int nThreadNum ) { HRESULT hr = S_OK; DBPerformanceTrackHelper helper; try { while( ENV().GetString( "game.item_loading" ) != "complete" ) { Sleep( 1000 ); } helper.start(); LoadMarketData(); LoadLevelUpTableData(); LoadSummonLevelUpTableData(); LoadStatData(); LoadJobData(); LoadStateData(); LoadBannedWordData(); LoadEnhanceData(); LoadAutoAccountData(); LoadGlobalVariableData(); helper.end( "ETCLoader" ); } catch( _com_error &e ) { helper.end( e.Error(), "ETCLoader" ); LogDBError( e, "ETCLoader", "ETCLoader::onProcess()" ); std::string strError = "ETC RESOUCE DB ERROR : "; strError += e.Description(); throw XException( strError ); } return true; } bool ShopLoader::onProcess(int nThreadNum) { HRESULT hr = S_OK; DBPerformanceTrackHelper helper; try { while (ENV().GetString("game.item_loading") != "complete") { Sleep(1000); } helper.start(); LoadMarketData(); helper.end("ShopLoader"); } catch (_com_error & e) { helper.end(e.Error(), "ShopLoader"); LogDBError(e, "ShopLoader", "ShopLoader::onProcess()"); std::string strError = "ShopLoader RESOUCE DB ERROR : "; strError += e.Description(); throw XException(strError); } return true; }