273 lines
9.1 KiB
C++
273 lines
9.1 KiB
C++
|
|
#include <toolkit/XConsole.h>
|
|
#include <toolkit/Khash.h>
|
|
#include <logging/FileLog.h>
|
|
|
|
#include "ContentLoader.h"
|
|
#include "StructNPC.h"
|
|
#include "GameDBUtil.h"
|
|
#include "GameProc.h"
|
|
#include "NPCBase.h"
|
|
#include "DBPerformanceTracker.h"
|
|
#include "ADOConnection.h"
|
|
|
|
volatile int g_nCurrentLocalFlag = GameContent::LOCAL_INFO_KOREA;
|
|
static std::vector< NPCEventPeriodBase > s_vNPCEventPeriodList;
|
|
|
|
struct dbNPC : public CADORecordBinding, public NPCBase
|
|
{
|
|
DBTIMESTAMP dtBeginOfPeriod;
|
|
DBTIMESTAMP dtEndOfPeriod;
|
|
|
|
BEGIN_ADO_BINDING(dbNPC)
|
|
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, name_text_id, sizeof(name_text_id), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(6, adInteger, x, sizeof(x), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(7, adInteger, y, sizeof(y), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(8, adInteger, z, sizeof(z), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(9, adInteger, face, sizeof(face), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(10, adInteger, local_flag, sizeof(local_flag), FALSE)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(32, adInteger, roaming_id, sizeof(roaming_id), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(33, adInteger, standard_walk_speed, sizeof(standard_walk_speed), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(34, adInteger, standard_run_speed, sizeof(standard_run_speed), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(35, adInteger, walk_speed, sizeof(walk_speed), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(36, adInteger, run_speed, sizeof(run_speed), FALSE)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(37, adTinyInt, attackable, sizeof(attackable), FALSE)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(38, adTinyInt, offensive_type, sizeof(offensive_type), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(39, adInteger, spawn_type, sizeof(spawn_type), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(40, adInteger, chase_range, sizeof(chase_range), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(41, adInteger, regen_time, sizeof(regen_time), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(42, adInteger, level, sizeof(level), FALSE)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(43, adInteger, stat_id, sizeof(stat_id), FALSE)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(44, adInteger, attack_range, sizeof(attack_range), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(45, adInteger, attack_speed_type, sizeof(attack_speed_type), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(46, adInteger, hp, sizeof(hp), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(47, adInteger, mp, sizeof(mp), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(48, adInteger, attack_point, sizeof(attack_point), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(49, adInteger, magic_point, sizeof(magic_point), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(50, adInteger, defence, sizeof(defence), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(51, adInteger, magic_defence, sizeof(magic_defence), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(52, adInteger, attack_speed, sizeof(attack_speed), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(53, adInteger, magic_speed, sizeof(magic_speed), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(54, adInteger, accuracy, sizeof(accuracy), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(55, adInteger, avoid, sizeof(avoid), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(56, adInteger, magic_accuracy, sizeof(magic_accuracy), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(57, adInteger, magic_avoid, sizeof(magic_avoid), FALSE)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(58, adVarChar, ai_script, _countof(ai_script), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(59, adVarChar, contact_script, _countof(contact_script), FALSE)
|
|
END_ADO_BINDING()
|
|
};
|
|
|
|
struct dbNPCEventPeriod : public CADORecordBinding, public NPCEventPeriodBase
|
|
{
|
|
DBTIMESTAMP dtBeginOfPeriod;
|
|
DBTIMESTAMP dtEndOfPeriod;
|
|
int local_flag;
|
|
|
|
BEGIN_ADO_BINDING(dbNPCEventPeriod)
|
|
|
|
ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, id, sizeof(id), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(2, adInteger, local_flag, sizeof(local_flag), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(3, adDBTimeStamp, dtBeginOfPeriod, sizeof(dtBeginOfPeriod), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(4, adDBTimeStamp, dtEndOfPeriod, sizeof(dtEndOfPeriod), FALSE)
|
|
|
|
END_ADO_BINDING()
|
|
|
|
};
|
|
|
|
void onNPCEventPeriodData( dbNPCEventPeriod * emprs )
|
|
{
|
|
if( !( emprs->local_flag & g_nCurrentLocalFlag ) )
|
|
return;
|
|
|
|
struct tm tmPeriod;
|
|
|
|
tmPeriod.tm_year = emprs->dtBeginOfPeriod.year - 1900;
|
|
tmPeriod.tm_mon = emprs->dtBeginOfPeriod.month - 1;
|
|
tmPeriod.tm_mday = emprs->dtBeginOfPeriod.day;
|
|
tmPeriod.tm_hour = emprs->dtBeginOfPeriod.hour;
|
|
tmPeriod.tm_min = emprs->dtBeginOfPeriod.minute;
|
|
tmPeriod.tm_sec = emprs->dtBeginOfPeriod.second;
|
|
tmPeriod.tm_isdst = -1;
|
|
emprs->begin_of_period = mktime( &tmPeriod );
|
|
|
|
if( emprs->begin_of_period == -1 )
|
|
{
|
|
assert( 0 );
|
|
return;
|
|
}
|
|
|
|
tmPeriod.tm_year = emprs->dtEndOfPeriod.year - 1900;
|
|
tmPeriod.tm_mon = emprs->dtEndOfPeriod.month - 1;
|
|
tmPeriod.tm_mday = emprs->dtEndOfPeriod.day;
|
|
tmPeriod.tm_hour = emprs->dtEndOfPeriod.hour;
|
|
tmPeriod.tm_min = emprs->dtEndOfPeriod.minute;
|
|
tmPeriod.tm_sec = emprs->dtEndOfPeriod.second;
|
|
tmPeriod.tm_isdst = -1;
|
|
emprs->end_of_period = mktime( &tmPeriod );
|
|
|
|
if( emprs->end_of_period == -1 )
|
|
{
|
|
assert( 0 );
|
|
return;
|
|
}
|
|
|
|
static const int nPeriodicalNPCAdjustment = ENV().GetInt( "game.periodical_npc_adjustment" );
|
|
if( nPeriodicalNPCAdjustment )
|
|
{
|
|
if( emprs->begin_of_period > nPeriodicalNPCAdjustment )
|
|
emprs->begin_of_period -= nPeriodicalNPCAdjustment;
|
|
else
|
|
emprs->begin_of_period = 0;
|
|
|
|
if( emprs->end_of_period > nPeriodicalNPCAdjustment )
|
|
emprs->end_of_period -= nPeriodicalNPCAdjustment;
|
|
else
|
|
emprs->end_of_period = 0;
|
|
}
|
|
|
|
// Skip loading if the NPC should already have been removed
|
|
if( time( NULL ) >= emprs->end_of_period )
|
|
return;
|
|
|
|
s_vNPCEventPeriodList.push_back( *emprs );
|
|
}
|
|
|
|
void onNPCData( dbNPC * emprs )
|
|
{
|
|
bool bFind = false;
|
|
|
|
// s_vNPCEventPeriodList 에 등록된 NPC들은 이미 국가플래그 검증이 끝났으므로 그대로 날짜세팅만 해서 넣어준다.
|
|
// 즉, s_vNPCEventPeriodList에 NPC가 등록 된 경우 그 ID를 가진 NPC는 기존 NPC 리소스 국가 플래그에 영향을 받지 않는다.
|
|
std::vector< NPCEventPeriodBase >::iterator it;
|
|
for( it = s_vNPCEventPeriodList.begin() ; it != s_vNPCEventPeriodList.end() ; ++it )
|
|
{
|
|
if( emprs->id == (*it).id )
|
|
{
|
|
emprs->begin_of_period = (*it).begin_of_period;
|
|
emprs->end_of_period = (*it).end_of_period;
|
|
emprs->is_periodic = true;
|
|
s_vNPCEventPeriodList.erase( it );
|
|
bFind = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !bFind )
|
|
{
|
|
if( emprs->local_flag & g_nCurrentLocalFlag )
|
|
return;
|
|
|
|
emprs->is_periodic = false;
|
|
emprs->begin_of_period = 0;
|
|
emprs->end_of_period = 0;
|
|
}
|
|
|
|
// 본 테섭 사용 불가 플래그의 경우 항상 체크해준다. (기존 NPCResource의 플래그에 따라 NPCEventPeriodResource에서 온 NPC들도 영향을 받음.
|
|
if( ( emprs->local_flag & GameContent::LOCAL_EXCLUDE_TEST_SERV ) && !ENV().GetInt( "game.ServiceServer" ) )
|
|
return;
|
|
if( ( emprs->local_flag & GameContent::LOCAL_EXCLUDE_SERVICE_SERV ) && ENV().GetInt( "game.ServiceServer" ) )
|
|
return;
|
|
|
|
GameContent::RegisterNPCInfo( *emprs );
|
|
}
|
|
|
|
static bool LoadNPCEventPeriodResource()
|
|
{
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD dwTime = GetSafeTickCount();
|
|
#endif
|
|
_ConnectionPtr ConnPtr = NULL;
|
|
|
|
InitContentDbConnection( ConnPtr );
|
|
|
|
size_t cnt = LoadDbResource< dbNPCEventPeriod >( "NPCEventPeriodResource", ConnPtr, onNPCEventPeriodData );
|
|
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD loadingTime = GetSafeTickCount() - dwTime;
|
|
_cprint("Total %d NPCEventPeriod loaded; time taken: %d\n", cnt, loadingTime);
|
|
FILELOG("Total %d NPCEventPeriod loaded; time taken: %d", cnt, loadingTime);
|
|
#else
|
|
_cprint( "Total %d NPCEventPeriod data loaded...\n", cnt );
|
|
FILELOG( "Total %d NPCEventPeriod data loaded...", cnt );
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool LoadNPCResource()
|
|
{
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD dwTime = GetSafeTickCount();
|
|
#endif
|
|
_ConnectionPtr ConnPtr = NULL;
|
|
|
|
InitContentDbConnection( ConnPtr );
|
|
|
|
size_t cnt = LoadDbResource< dbNPC >( "NPCResource", ConnPtr, onNPCData );
|
|
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD loadingTime = GetSafeTickCount() - dwTime;
|
|
_cprint("Total %d NPC loaded; time taken: %d\n", cnt, loadingTime);
|
|
FILELOG("Total %d NPC loaded; time taken: %d", cnt, loadingTime);
|
|
#else
|
|
_cprint( "Total %d NPC loaded...\n", cnt );
|
|
FILELOG( "Total %d NPC loaded...", cnt );
|
|
#endif
|
|
|
|
if( s_vNPCEventPeriodList.size() > 0 )
|
|
{
|
|
_cprint( "!! %d of NPC Event Period data are unused...\n", static_cast< int >( s_vNPCEventPeriodList.size() ) );
|
|
FILELOG( "!! %d of NPC Event Period data are unused...", static_cast< int >( s_vNPCEventPeriodList.size() ) );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool NPCLoader::onProcess( int nThreadNum )
|
|
{
|
|
DBPerformanceTrackHelper helper;
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
LoadNPCEventPeriodResource();
|
|
helper.end( "NPCLoader" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( e.Error(), "NPCLoader" );
|
|
LogDBError( e, "NPCLoader", "LoadNPCEventPeriodResource()" );
|
|
|
|
std::string strError = "NPC RESOUCE DB ERROR : ";
|
|
strError += e.Description();
|
|
throw XException( strError );
|
|
}
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
LoadNPCResource();
|
|
helper.end( "NPCLoader" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( e.Error(), "NPCLoader" );
|
|
LogDBError( e, "NPCLoader", "LoadNPCResource()" );
|
|
|
|
std::string strError = "NPC RESOUCE DB ERROR : ";
|
|
strError += e.Description();
|
|
throw XException( strError );
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|